[jboss-user] [JBoss Cache: Core Edition] - Re: is it possible for MVCCInvocationContext to have null mv
"dukehoops" wrote : | 1. the pattern I described in the post linked below is not an edge case: | http://www.jboss.org/index.html?module=bb&op=viewtopic&p=4217616#4217616 | I agree that the pattern is not an edge case for Hib/JBC3 integration, but it is an edge case for JBC3 in general. Rest assured, just because I refer to it as an edge case doesn't mean it isn't important and won't be fixed. :-) In fact, if you want to build JBC3 trunk and give it a whirl, I'd appreciate the feedback. View the original post : http://www.jboss.org/index.html?module=bb&op=viewtopic&p=4219033#4219033 Reply to the post : http://www.jboss.org/index.html?module=bb&op=posting&mode=reply&p=4219033 ___ jboss-user mailing list [email protected] https://lists.jboss.org/mailman/listinfo/jboss-user
[jboss-user] [JBoss Cache: Core Edition] - Re: is it possible for MVCCInvocationContext to have null mv
I am using mysql 5.1 with INNODB. the db reports iso as RR View the original post : http://www.jboss.org/index.html?module=bb&op=viewtopic&p=4218818#4218818 Reply to the post : http://www.jboss.org/index.html?module=bb&op=posting&mode=reply&p=4218818 ___ jboss-user mailing list [email protected] https://lists.jboss.org/mailman/listinfo/jboss-user
[jboss-user] [JBoss Cache: Core Edition] - Re: is it possible for MVCCInvocationContext to have null mv
"dukehoops" wrote : I see. Makes sense. | | anonymous wrote : Can you comment more on why making the datasource READ_COMMITTED as well was necessary? | | I don't know - puzzled as well. But it absolutely was the case that my multithreaded load tests kept failing until I made that change, and haven't failed since. | | Most DBs substitute SERIALIZABLE with REPEATABLE_READ. So if you make your DS RR you have likely just moved to single threaded access. View the original post : http://www.jboss.org/index.html?module=bb&op=viewtopic&p=4218817#4218817 Reply to the post : http://www.jboss.org/index.html?module=bb&op=posting&mode=reply&p=4218817 ___ jboss-user mailing list [email protected] https://lists.jboss.org/mailman/listinfo/jboss-user
[jboss-user] [JBoss Cache: Core Edition] - Re: is it possible for MVCCInvocationContext to have null mv
I see. Makes sense. anonymous wrote : Can you comment more on why making the datasource READ_COMMITTED as well was necessary? I don't know - puzzled as well. But it absolutely was the case that my multithreaded load tests kept failing until I made that change, and haven't failed since. View the original post : http://www.jboss.org/index.html?module=bb&op=viewtopic&p=4218783#4218783 Reply to the post : http://www.jboss.org/index.html?module=bb&op=posting&mode=reply&p=4218783 ___ jboss-user mailing list [email protected] https://lists.jboss.org/mailman/listinfo/jboss-user
[jboss-user] [JBoss Cache: Core Edition] - Re: is it possible for MVCCInvocationContext to have null mv
The idea of JBCACHE-1493 is not to enabled writeSkewCheck, it is to ensure that the removeNode call actually removes the node, whether or not the node existed when the tx earlier called get(). As a result the empty collection will be removed. Note I'm not disagreeing with you that this needs to be handled better in the Hib/JBC integration. Hence [ur;]http://opensource.atlassian.com/projects/hibernate/browse/HHH-3817[/url] and perhaps others. Just using an ordinary JBC put() to handle TransactionalAccess.putFromLoad() will not work because you'll get lock conflicts across the cluster when the call replicates. "dukehoops" wrote : Note that the workaround involved not only using READ_COMMITTED in jbc config but also ensuring that Datasource being enlisted as XA Resource was configured to READ_COMMITTED as well. Can you comment more on why making the datasource READ_COMMITTED as well was necessary? View the original post : http://www.jboss.org/index.html?module=bb&op=viewtopic&p=4218779#4218779 Reply to the post : http://www.jboss.org/index.html?module=bb&op=posting&mode=reply&p=4218779 ___ jboss-user mailing list [email protected] https://lists.jboss.org/mailman/listinfo/jboss-user
[jboss-user] [JBoss Cache: Core Edition] - Re: is it possible for MVCCInvocationContext to have null mv
Manik, Thanks for posting the JIRA. However, at the risk of appear to be a nit-picker, I don't think JBCACHE-1493 captures the extent of the problem as it pertains to R_R, and Hibernate - JBC3 interaction. Specifically, given an application that uses Hibernate and JBC3 (MVCC) as 2nd level cache in Transactional (as opposed to read-only) mode: 1. the pattern I described in the post linked below is not an edge case: http://www.jboss.org/index.html?module=bb&op=viewtopic&p=4217616#4217616 Basically, this will take place whenever app logic is such that the 1st time a collection is accessed the intent is to alter it. 2. as far as I can tell, enabling writeSkewCheck will merely result in data version exceptions being thrown in this use case - making collection un-cacheable if app does a write on 1st access. Given the above pattern, and sequence of calls that HIbernate Core issues in case of Collections I think the solution is not to use pfer() in org.hibernate.cache.jbc2.collection.TransactionalAccess.putFromLoad() if R_R is in use. -nikita View the original post : http://www.jboss.org/index.html?module=bb&op=viewtopic&p=4218771#4218771 Reply to the post : http://www.jboss.org/index.html?module=bb&op=posting&mode=reply&p=4218771 ___ jboss-user mailing list [email protected] https://lists.jboss.org/mailman/listinfo/jboss-user
[jboss-user] [JBoss Cache: Core Edition] - Re: is it possible for MVCCInvocationContext to have null mv
https://jira.jboss.org/jira/browse/JBCACHE-1493 View the original post : http://www.jboss.org/index.html?module=bb&op=viewtopic&p=4218759#4218759 Reply to the post : http://www.jboss.org/index.html?module=bb&op=posting&mode=reply&p=4218759 ___ jboss-user mailing list [email protected] https://lists.jboss.org/mailman/listinfo/jboss-user
[jboss-user] [JBoss Cache: Core Edition] - Re: is it possible for MVCCInvocationContext to have null mv
I am unsure what "inconsistency" means as relating to whether the software works as designed, but IMO this is a bug in the hib-jbc2 integration layer. Please note that if cache.evict() were used instead of removeNode() same problem would arise. Note that the workaround involved not only using READ_COMMITTED in jbc config but also ensuring that Datasource being enlisted as XA Resource was configured to READ_COMMITTED as well. View the original post : http://www.jboss.org/index.html?module=bb&op=viewtopic&p=4218746#4218746 Reply to the post : http://www.jboss.org/index.html?module=bb&op=posting&mode=reply&p=4218746 ___ jboss-user mailing list [email protected] https://lists.jboss.org/mailman/listinfo/jboss-user
[jboss-user] [JBoss Cache: Core Edition] - Re: is it possible for MVCCInvocationContext to have null mv
Good; thanks for thinking hard about this. :-) Something about not executing the remove seemed wrong; it was that inconsistency versus the modification. View the original post : http://www.jboss.org/index.html?module=bb&op=viewtopic&p=4218737#4218737 Reply to the post : http://www.jboss.org/index.html?module=bb&op=posting&mode=reply&p=4218737 ___ jboss-user mailing list [email protected] https://lists.jboss.org/mailman/listinfo/jboss-user
[jboss-user] [JBoss Cache: Core Edition] - Re: is it possible for MVCCInvocationContext to have null mv
"[email protected]" wrote : You only modify data that you read? What if I just call removeNode() with no preceding get()? | Then the read happens at the time of the removeNode(). I.e., the node to be removed is read from the data structure, then marked as removed and finally removed when the tx completes. "[email protected]" wrote : Well, anyway, that makes it clear that MVCC + R_R is not usable for Hibernate Second Level Caching, at least not without a major rewrite of the integration layer. Actually, this should actually be viewed as a bug/inconsistency in the way write skews are currently handled, since: 1. A write skew involving modifying data will overwrite any intermediate data and the last commit wins. 2. In the case of a removeNode(), a write preceeding the remove will win. To be consistent, with the same "last tx wins" approach to dealing with write skews, if write skew checking is disabled a removeNode() should remove *any* node present under the given Fqn, not necessarily the node read earlier in the same tx. View the original post : http://www.jboss.org/index.html?module=bb&op=viewtopic&p=4218732#4218732 Reply to the post : http://www.jboss.org/index.html?module=bb&op=posting&mode=reply&p=4218732 ___ jboss-user mailing list [email protected] https://lists.jboss.org/mailman/listinfo/jboss-user
[jboss-user] [JBoss Cache: Core Edition] - Re: is it possible for MVCCInvocationContext to have null mv
You only modify data that you read? What if I just call removeNode() with no preceding get()? Well, anyway, that makes it clear that MVCC + R_R is not usable for Hibernate Second Level Caching, at least not without a major rewrite of the integration layer. View the original post : http://www.jboss.org/index.html?module=bb&op=viewtopic&p=4218726#4218726 Reply to the post : http://www.jboss.org/index.html?module=bb&op=posting&mode=reply&p=4218726 ___ jboss-user mailing list [email protected] https://lists.jboss.org/mailman/listinfo/jboss-user
[jboss-user] [JBoss Cache: Core Edition] - Re: is it possible for MVCCInvocationContext to have null mv
"[email protected]" wrote : | Manik, why is the removeNode call not removing the node? Is the MVCC code detecting that the node didn't exist when the get() call happened and therefore turning the removeNode into a no-op? | Yes. This is consistent with R_R semantics in that you only modify data that you read. Now if write skew detection was enabled (by setting writeSkewCheck to true) this case would throw a DataVersioningException. See [1] for details on write skews. And contrary to what the docs say, writeSkewCheck is false by default. [1] http://www.jboss.org/file-access/default/members/jbosscache/freezone/docs/3.0.3.GA/userguide_en/html/transactions.html#transactions.locks.mvcc (See section on write skews) View the original post : http://www.jboss.org/index.html?module=bb&op=viewtopic&p=4218705#4218705 Reply to the post : http://www.jboss.org/index.html?module=bb&op=posting&mode=reply&p=4218705 ___ jboss-user mailing list [email protected] https://lists.jboss.org/mailman/listinfo/jboss-user
[jboss-user] [JBoss Cache: Core Edition] - Re: is it possible for MVCCInvocationContext to have null mv
READ_COMMITTED is the recommended isolation level for the Hibernate Second Level Cache use case[1], since the Session itself acts as a R_R cache. The reason you'd use R_R in JBC is if your app was calling Session.evict() or Session.clear() and then you wanted to re-read an entity with R_R semantics. Manik, why is the removeNode call not removing the node? Is the MVCC code detecting that the node didn't exist when the get() call happened and therefore turning the removeNode into a no-op? dukehoops, there's also a race at work here if there are multiple threads involved. See http://opensource.atlassian.com/projects/hibernate/browse/HHH-3817. To deal with that I think I need something more sophisticated in the Hibernate/JBC layer such that a call to org.hibernate.cache.Cache.evict(key) results in pending putForExternalRead calls being ignored. Basically turn get() + pfer() into a logical single operation that gets aborted if an evict happens in the middle. That's not so nice though, adds overhead. [1] See page 13 of http://www.jboss.org/file-access/default/members/jbossclustering/freezone/docs/hibernate-jbosscache-guide-3.pdf View the original post : http://www.jboss.org/index.html?module=bb&op=viewtopic&p=4218687#4218687 Reply to the post : http://www.jboss.org/index.html?module=bb&op=posting&mode=reply&p=4218687 ___ jboss-user mailing list [email protected] https://lists.jboss.org/mailman/listinfo/jboss-user
[jboss-user] [JBoss Cache: Core Edition] - Re: is it possible for MVCCInvocationContext to have null mv
You have a good point. Perhaps as a recommendation, READ_COMMITTED should be used *if* using JBC3, Hibernate + MVCC. View the original post : http://www.jboss.org/index.html?module=bb&op=viewtopic&p=4218569#4218569 Reply to the post : http://www.jboss.org/index.html?module=bb&op=posting&mode=reply&p=4218569 ___ jboss-user mailing list [email protected] https://lists.jboss.org/mailman/listinfo/jboss-user
[jboss-user] [JBoss Cache: Core Edition] - Re: is it possible for MVCCInvocationContext to have null mv
Manik,
Your explanation makes sense, however I wonder whether that means Hibernate /
Hib-JBC2 integration project / JBC3 stack is unusable with REPEATABLE_READ
then. Let me explain.
Person, Child are cached entities, parent.children is a cached collection
(using Hibernate's Transactional concurrency strategy).
Consider this method:
| public void addChild(parentId){
|
| tx.begin();
|
| Parent p = parentDAO.get(parentId);
| Set children = p.getChildren();
| Child newChild = new Child();
| children.add(newChild);
| tx.commit();
| }
|
Let's look at what calls hib-jbc integration layer
(org.hibernate.cache.jbc2.[collection|entity].TransactionalAccess) will issue
for each of the above lines:
1. Parent p = parentDAO.get(parentId);
cache.get(parentIdFqn); //cache miss on very 1st call
//hibernate goes to db to retrieve data and then puts it into cache:
cache.pfer(parentIdFqn, p)
2. Set children = p.getChildren();
//look in collection cache for parent.children with given parentId
cache.get(parentIdCollectionFqn) //miss
//hibernate will look in db, and if db returns nothing, will put an empty
collection into cache
cache.pfer(parentIdCollectionFqn, emptyCollection);
3. children.add(newChild);
Hibernate tells 2nd level cache to evict collection cache entry on any
collection modification. Specifically above add call will result in removeNode
call on tx.commit():
cache.removeNode(parentIdCollectionFqn); //should remove empty Collection from
cache to ensure next time step #2 above is executed cache misses and we go to
DB.
However, as you point out pfer() will operate in different tx than get() and
removeNode(). Therefore, removeNode will not remove the empty collection. Now
Node with parentIdCollectionFqn still has emptyCollection as value and so in a
subsequent transaction:
tx.begin();
cache.get(parentIdCollectionFqn); //hibernate expects a miss so that new
children can be re-read from db
tx.commit();
.. we will actually get a cache hit with stale emptyCollection, one that does
not contain newChildId. So as far as Hibernate will be concerned, given parent
will have no children. (even though newChild is in db).
So, I understand your explanation and agree that JBC code behaves correctly.
But it seems like the problem is that when child is added to a collection in
Hibernate, collection cache will see exactly this series of calls:
tx1:
-get()
-pfer()
-removeNode() //expected to ensure cache miss on the subsequent get()
tx2:
-get() //expect a miss
So that means that
org.hibernate.cache.jbc2.collection.TransactionalAccess.putFromLoad() should
use a Cache method that ensures that a subsequent Cache.removeNode will
actually remove, i.e putFromLoad()
- either should use put() instead of pfer()
- or use a new method that is like pfer() but does not suspend TX.
Here's the updated test that I believe issues the same calls that
org.hibernate.cache.jbc2.collection.TransactionalAccess would issue with the
above service method:
package org.jboss.cache.api;
|
| import org.jboss.cache.config.Configuration;
| import org.jboss.cache.config.Configuration.NodeLockingScheme;
| import org.jboss.cache.factories.UnitTestConfigurationFactory;
| import org.testng.annotations.Test;
|
| import javax.transaction.TransactionManager;
|
| import org.jboss.cache.*;
| import org.jboss.cache.lock.IsolationLevel;
|
| /**
| * Tests that a node that was putFromExternalRead and then removed in TX1
does NOT
| * get returned in subsequent TX2.
| *
| * @author [email protected]
| * @since 3.0.3.GA
| */
| @Test(groups = {"functional", "pessimistic"}, sequential = true, testName =
"api.RemovedNodeResurrectionInSubsequentTxTest")
| public class RemovedNodeResurrectionInSubsequentTxTest extends
AbstractSingleCacheTest {
|
| private static final Fqn A_B = Fqn.fromString("/a/b");
| private static final Fqn A = Fqn.fromString("/a");
| private static final Fqn A_C = Fqn.fromString("/a/c");
| private static final String KEY = "key";
| private static final String VALUE = "value";
| private static final String K2 = "k2";
| private static final String V2 = "v2";
| protected NodeSPI root;
| protected TransactionManager txManager;
|
| public CacheSPI createCache() {
| CacheSPI myCache = (CacheSPI) new
UnitTestCacheFactory().createCache(UnitTestConfigurationFactory.createConfiguration(Configuration.CacheMode.LOCAL,
false), false, getClass());
|
myCache.getConfiguration().setCacheMode(Configuration.CacheMode.LOCAL);
| myCache.getConfiguration().setCacheLoaderConfig(null);
|
myCache.getConfiguration().setNodeLockingScheme(NodeLockingScheme.MVCC);
| configure(myCache.getConfiguration());
| myCache.start();
| root = myCache.getRoot();
| txManager = myCache.getTransactionManager();
|
|
[jboss-user] [JBoss Cache: Core Edition] - Re: is it possible for MVCCInvocationContext to have null mv
Had a look at your test, and your test is invalid. Here's why: Case 1: You have commented out the line marked N1. This works fine, since you first do a pFER() and then a get(). Expected behaviour. Case 2: Line marked N1 is not commented out. Here is what happens: 1. tx starts 2. read the value, which is null 3. do a pFER(). Remember that pFER(), to be fail-safe, runs in a separate transaction. So this will suspend the tx started in 1, do the pFER(), and then resume the tx in 1. 4. read the value again, you get a null. This is correct, since you have REPEATABLE_READ specified. Since line 3 happens outside the scope of the transaction, the transaction correctly treats this as a different, concurrent transaction modifying the value. And since you have already read the value as null, you will always see it as null for the scope of the transaction. As proof, try running your test either without the tx.begin() and tx.commit(), or specify a weaker isolation level like READ_COMMITTED. View the original post : http://www.jboss.org/index.html?module=bb&op=viewtopic&p=4217541#4217541 Reply to the post : http://www.jboss.org/index.html?module=bb&op=posting&mode=reply&p=4217541 ___ jboss-user mailing list [email protected] https://lists.jboss.org/mailman/listinfo/jboss-user
[jboss-user] [JBoss Cache: Core Edition] - Re: is it possible for MVCCInvocationContext to have null mv
"dukehoops" wrote : Side note: Configuration.writeSkewCheck defaults to false (and not true as specified in JBC3 User Guide reference section Ch 12, p 104). | Well spotted. Thanks, corrected in trunk (3.1.0) View the original post : http://www.jboss.org/index.html?module=bb&op=viewtopic&p=4217340#4217340 Reply to the post : http://www.jboss.org/index.html?module=bb&op=posting&mode=reply&p=4217340 ___ jboss-user mailing list [email protected] https://lists.jboss.org/mailman/listinfo/jboss-user
[jboss-user] [JBoss Cache: Core Edition] - Re: is it possible for MVCCInvocationContext to have null mv
Got it. The following sequence will fail: 1. get() 2. pfer() 3. get() //fail here However, if the 1st step is eliminated, second get succeeds: pfer(); get();//success. Here's the test: package org.jboss.cache.api; | | import org.jboss.cache.config.Configuration; | import org.jboss.cache.config.Configuration.NodeLockingScheme; | import org.jboss.cache.factories.UnitTestConfigurationFactory; | import org.testng.annotations.Test; | | import javax.transaction.TransactionManager; | | import org.jboss.cache.*; | import org.jboss.cache.lock.IsolationLevel; | | /** | * Tests that a node that was putFromExternalRead and then removed in TX1 does NOT | * get returned in subsequent TX2. | * | * @author [email protected] | * @since 3.0.3.GA | */ | @Test(groups = {"functional", "pessimistic"}, sequential = true, testName = "api.RemovedNodeResurrectionInSubsequentTxTest") | public class RemovedNodeResurrectionInSubsequentTxTest extends AbstractSingleCacheTest { | | private static final Fqn A_B = Fqn.fromString("/a/b"); | private static final Fqn A = Fqn.fromString("/a"); | private static final Fqn A_C = Fqn.fromString("/a/c"); | private static final String KEY = "key"; | private static final String VALUE = "value"; | private static final String K2 = "k2"; | private static final String V2 = "v2"; | protected NodeSPI root; | protected TransactionManager txManager; | | public CacheSPI createCache() { | CacheSPI myCache = (CacheSPI) new UnitTestCacheFactory().createCache(UnitTestConfigurationFactory.createConfiguration(Configuration.CacheMode.LOCAL, false), false, getClass()); | myCache.getConfiguration().setCacheMode(Configuration.CacheMode.LOCAL); | myCache.getConfiguration().setCacheLoaderConfig(null); | myCache.getConfiguration().setNodeLockingScheme(NodeLockingScheme.MVCC); | configure(myCache.getConfiguration()); | myCache.start(); | root = myCache.getRoot(); | txManager = myCache.getTransactionManager(); | | return myCache; | } | | protected void configure(Configuration c) { | c.setIsolationLevel(IsolationLevel.REPEATABLE_READ); | } | | public void testPferAndEvictInSameTx() throws Exception { | | Object val = null; | | cache.getRoot().addChild(A); | | txManager.begin(); | | val = cache.get(A_B, KEY); //N1 IF THIS LINE IS EXECUTED, TEST FAILS BELOW AT N2 | | //put in cache | cache.putForExternalRead(A_B, KEY, VALUE); | | val = cache.get(A_B, KEY); | assert val != null : "get() after pfer() returned " + val; //N2 THIS WILL FAIL IF LINE N1 (ABOVE) IS EXECUTED (NOT COMMENTED OUT) | | //evict from cache | cache.evict(A_B); //sometimes MVCCInvocationContext has ref to mvccTCtx, sometimes NOT | | //verify eviction | val = cache.get(A_B, KEY); | assert val == null : "get() after evict() returned " + val; | | txManager.commit(); | | } | } | Here's the output: anonymous wrote : | | | java.lang.AssertionError: get() after pfer() returned null | at org.jboss.cache.api.RemovedNodeResurrectionInSubsequentTxTest.testPferAndEvictInSameTx(RemovedNodeResurrectionInSubsequentTxTest.java:65) | at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) | at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) | at java.lang.Thread.run(Thread.java:619) | However, if line marked as "N1" is commented out, test passes. Any ideas? View the original post : http://www.jboss.org/index.html?module=bb&op=viewtopic&p=4217201#4217201 Reply to the post : http://www.jboss.org/index.html?module=bb&op=posting&mode=reply&p=4217201 ___ jboss-user mailing list [email protected] https://lists.jboss.org/mailman/listinfo/jboss-user
[jboss-user] [JBoss Cache: Core Edition] - Re: is it possible for MVCCInvocationContext to have null mv
Well, it appears there isn't a problem in this test after all. To answer my own question above, mvccTCtx gets populated with Node in question in MVCCNodeHelper.wrapNodeForWriting (called by MVCCLockingInterceptor before EvictCommand.perform is executed). Side note: Configuration.writeSkewCheck defaults to false (and not true as specified in JBC3 User Guide reference section Ch 12, p 104). So the concurrency problem described in this post is probably rooted elsewhere :-( http://www.jboss.org/index.html?module=bb&op=viewtopic&t=151524&postdays=0&postorder=asc&start=20 View the original post : http://www.jboss.org/index.html?module=bb&op=viewtopic&p=4217106#4217106 Reply to the post : http://www.jboss.org/index.html?module=bb&op=posting&mode=reply&p=4217106 ___ jboss-user mailing list [email protected] https://lists.jboss.org/mailman/listinfo/jboss-user
[jboss-user] [JBoss Cache: Core Edition] - Re: is it possible for MVCCInvocationContext to have null mv
aha! So there *is* another thread at work - at least in this test environment. Look in createCache(): createCache(UnitTestConfigurationFactory.createConfiguration(Configuration.CacheMode.LOCAL, true); //true==some eviction policy That's why when I break in ctx.lookUpNode, I see the following stack running on a thread called "EvictionTimer-0". this certainly explains why stepping through with a debugger alters results: anonymous wrote : org.jboss.cache.invocation.MVCCInvocationContext.lookUpNode(MVCCInvocationContext.java:76) | org.jboss.cache.commands.write.EvictCommand.lookupForEviction(EvictCommand.java:168) | org.jboss.cache.commands.write.EvictCommand.perform(EvictCommand.java:93) | org.jboss.cache.interceptors.CallInterceptor.invokeCommand(CallInterceptor.java:108) | org.jboss.cache.interceptors.CallInterceptor.handleDefault(CallInterceptor.java:99) | org.jboss.cache.commands.AbstractVisitor.visitEvictFqnCommand(AbstractVisitor.java:85) | org.jboss.cache.commands.write.EvictCommand.acceptVisitor(EvictCommand.java:173) | org.jboss.cache.interceptors.base.CommandInterceptor.invokeNextInterceptor(CommandInterceptor.java:116) | org.jboss.cache.interceptors.EvictionInterceptor.visitEvictFqnCommand(EvictionInterceptor.java:80) | org.jboss.cache.commands.write.EvictCommand.acceptVisitor(EvictCommand.java:173) | org.jboss.cache.interceptors.base.CommandInterceptor.invokeNextInterceptor(CommandInterceptor.java:116) | org.jboss.cache.interceptors.MVCCLockingInterceptor.handleEvictFqnCommand(MVCCLockingInterceptor.java:141) | org.jboss.cache.interceptors.base.PrePostProcessingCommandInterceptor.visitEvictFqnCommand(PrePostProcessingCommandInterceptor.java:185) | org.jboss.cache.commands.write.EvictCommand.acceptVisitor(EvictCommand.java:173) | org.jboss.cache.interceptors.base.CommandInterceptor.invokeNextInterceptor(CommandInterceptor.java:116) | org.jboss.cache.interceptors.base.CommandInterceptor.handleDefault(CommandInterceptor.java:131) | org.jboss.cache.commands.AbstractVisitor.visitEvictFqnCommand(AbstractVisitor.java:85) | org.jboss.cache.commands.write.EvictCommand.acceptVisitor(EvictCommand.java:173) | org.jboss.cache.interceptors.base.CommandInterceptor.invokeNextInterceptor(CommandInterceptor.java:116) | org.jboss.cache.interceptors.TxInterceptor.attachGtxAndPassUpChain(TxInterceptor.java:261) | org.jboss.cache.interceptors.TxInterceptor.handleDefault(TxInterceptor.java:250) | org.jboss.cache.commands.AbstractVisitor.visitEvictFqnCommand(AbstractVisitor.java:85) | org.jboss.cache.commands.write.EvictCommand.acceptVisitor(EvictCommand.java:173) | org.jboss.cache.interceptors.base.CommandInterceptor.invokeNextInterceptor(CommandInterceptor.java:116) | org.jboss.cache.interceptors.CacheMgmtInterceptor.visitEvictFqnCommand(CacheMgmtInterceptor.java:65) | org.jboss.cache.commands.write.EvictCommand.acceptVisitor(EvictCommand.java:173) | org.jboss.cache.interceptors.base.CommandInterceptor.invokeNextInterceptor(CommandInterceptor.java:116) | org.jboss.cache.interceptors.InvocationContextInterceptor.handleAll(InvocationContextInterceptor.java:178) | org.jboss.cache.interceptors.InvocationContextInterceptor.handleDefault(InvocationContextInterceptor.java:130) | org.jboss.cache.commands.AbstractVisitor.visitEvictFqnCommand(AbstractVisitor.java:85) | org.jboss.cache.commands.write.EvictCommand.acceptVisitor(EvictCommand.java:173) | org.jboss.cache.interceptors.InterceptorChain.invoke(InterceptorChain.java:287) | org.jboss.cache.invocation.CacheInvocationDelegate.evict(CacheInvocationDelegate.java:370) | org.jboss.cache.invocation.CacheInvocationDelegate.evict(CacheInvocationDelegate.java:374) | org.jboss.cache.eviction.DefaultEvictionActionPolicy.evict(DefaultEvictionActionPolicy.java:50) | org.jboss.cache.eviction.BaseEvictionAlgorithm.evictCacheNode(BaseEvictionAlgorithm.java:265) | org.jboss.cache.eviction.LRUAlgorithm.evict(LRUAlgorithm.java:121) | org.jboss.cache.eviction.LRUAlgorithm.prune(LRUAlgorithm.java:153) | org.jboss.cache.eviction.BaseEvictionAlgorithm.process(BaseEvictionAlgorithm.java:146) | org.jboss.cache.RegionImpl.processEvictionQueues(RegionImpl.java:128) | org.jboss.cache.eviction.EvictionTimerTask.handleRegion(EvictionTimerTask.java:115) | org.jboss.cache.eviction.EvictionTimerTask.processRegions(EvictionTimerTask.java:107) | org.jboss.cache.eviction.EvictionTimerTask.access$100(EvictionTimerTask.java:42) | org.jboss.cache.eviction.EvictionTimerTask$Task.run(EvictionTimerTask.java:133) | java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441) | java.util.concurrent.FutureTask$Sync.innerRunAndReset(FutureTask.java:317) | java.util.concurrent.FutureTask.runAndReset(FutureTask.java:150) | java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$101(ScheduledThreadPoolExecutor.java:98) |
[jboss-user] [JBoss Cache: Core Edition] - Re: is it possible for MVCCInvocationContext to have null mv
and yes, I started the above-linked topic because the problem described there is consistently repro-able on our system under mild concurrency. View the original post : http://www.jboss.org/index.html?module=bb&op=viewtopic&p=4217083#4217083 Reply to the post : http://www.jboss.org/index.html?module=bb&op=posting&mode=reply&p=4217083 ___ jboss-user mailing list [email protected] https://lists.jboss.org/mailman/listinfo/jboss-user
[jboss-user] [JBoss Cache: Core Edition] - Re: is it possible for MVCCInvocationContext to have null mv
Manik, This test is an attempt to distill an issue that only shows up under concurrent load. Please see the last page of this topic background info (pull up a chair - this may take awhile ;-): http://www.jboss.org/index.html?module=bb&op=viewtopic&t=151524&postdays=0&postorder=asc&start=20 View the original post : http://www.jboss.org/index.html?module=bb&op=viewtopic&p=4217081#4217081 Reply to the post : http://www.jboss.org/index.html?module=bb&op=posting&mode=reply&p=4217081 ___ jboss-user mailing list [email protected] https://lists.jboss.org/mailman/listinfo/jboss-user
[jboss-user] [JBoss Cache: Core Edition] - Re: is it possible for MVCCInvocationContext to have null mv
Hmm, I don't see this failure on your test, even when running it on multiple threads, etc. Are you seeing this issue in a live use case, or just when using your debugger? View the original post : http://www.jboss.org/index.html?module=bb&op=viewtopic&p=4217077#4217077 Reply to the post : http://www.jboss.org/index.html?module=bb&op=posting&mode=reply&p=4217077 ___ jboss-user mailing list [email protected] https://lists.jboss.org/mailman/listinfo/jboss-user
[jboss-user] [JBoss Cache: Core Edition] - Re: is it possible for MVCCInvocationContext to have null mv
Thanks for the test. "dukehoops" wrote : To follow up further. Below is a test i wrote trying to capture above failure. When I run it I observe the following: | - if no debugger is used, test passes | - if I step through with a debugger when EvictCommand.perform calls ctx.lookUpNode(fqn) the underlying MVCCInvocationContext sometimes has a non-null mvccTCtx and sometimes mvccTCtx is null?! It seems to depend on where I break and for how long - though pattern is unclear. | Wow, that's not nice. "dukehoops" wrote : | 1. From my understanding ctx.mvccTCtx should NOT be null when used accessed from EvictCommand.perform in the above test. Do you agree? If not, why (how is it that mvccTCtx can be null in this case)? | Agreed. Between the InvocationContextInterceptor and the TxInterceptor, this should be made available. "dukehoops" wrote : | 2. Since it seems I can affect the outcome of the test merely by attaching a debugger and breaking throughput, I am guessing either multiple threads or timestamping is involved. Given that the entire duration of the test didn't exceed 40-50 seconds (including my think time) when varying results were obtained, this does not seem to be related to underlying JTA tx timing out. Any idea where to look for debugger breaks can affect? | It could be that the reference to the tCtx needs to be volatile, let me think about how and when this is accessed and let you know. View the original post : http://www.jboss.org/index.html?module=bb&op=viewtopic&p=4217065#4217065 Reply to the post : http://www.jboss.org/index.html?module=bb&op=posting&mode=reply&p=4217065 ___ jboss-user mailing list [email protected] https://lists.jboss.org/mailman/listinfo/jboss-user
[jboss-user] [JBoss Cache: Core Edition] - Re: is it possible for MVCCInvocationContext to have null mv
To follow up further. Below is a test i wrote trying to capture above failure. When I run it I observe the following: - if no debugger is used, test passes - if I step through with a debugger when EvictCommand.perform calls ctx.lookUpNode(fqn) the underlying MVCCInvocationContext sometimes has a non-null mvccTCtx and sometimes mvccTCtx is null?! It seems to depend on where I break and for how long - though pattern is unclear. When mvccTCtx is null, then Node in question *is* found in lookedUpNodes and eviction proceeds. When mvccTCtx is NOT null, it does not contain the node in question -> ctx.lookUpNode returns null (lookedUpNodes isn't consulted if mvccTCtx is null) and eviction does not proceed (command.perform returns true immediately) Questions: 1. From my understanding ctx.mvccTCtx should NOT be null when used accessed from EvictCommand.perform in the above test. Do you agree? If not, why (how is it that mvccTCtx can be null in this case)? 2. Since it seems I can affect the outcome of the test merely by attaching a debugger and breaking throughput, I am guessing either multiple threads or timestamping is involved. Given that the entire duration of the test didn't exceed 40-50 seconds (including my think time) when varying results were obtained, this does not seem to be related to underlying JTA tx timing out. Any idea where to look for debugger breaks can affect? thanks -nikita package org.jboss.cache.api; | | import org.jboss.cache.config.Configuration; | import org.jboss.cache.config.Configuration.NodeLockingScheme; | import org.jboss.cache.factories.UnitTestConfigurationFactory; | import org.testng.annotations.Test; | | import javax.transaction.TransactionManager; | | import org.jboss.cache.*; | import org.jboss.cache.lock.IsolationLevel; | | /** | * Tests that a node that was putFromExternalRead and then removed in TX1 does NOT | * get returned in subsequent TX2. | * | * @author [email protected] | * @since 3.0.3.GA | */ | @Test(groups = {"functional", "pessimistic"}, sequential = true, testName = "api.RemovedNodeResurrectionInSubsequentTxTest") | public class RemovedNodeResurrectionInSubsequentTxTest extends AbstractSingleCacheTest { | | private static final Fqn A_B = Fqn.fromString("/a/b"); | private static final Fqn A = Fqn.fromString("/a"); | private static final Fqn A_C = Fqn.fromString("/a/c"); | private static final String KEY = "key"; | private static final String VALUE = "value"; | private static final String K2 = "k2"; | private static final String V2 = "v2"; | protected NodeSPI root; | protected TransactionManager txManager; | | public CacheSPI createCache() { | CacheSPI myCache = (CacheSPI) new UnitTestCacheFactory().createCache(UnitTestConfigurationFactory.createConfiguration(Configuration.CacheMode.LOCAL, true), false, getClass()); | myCache.getConfiguration().setCacheMode(Configuration.CacheMode.LOCAL); | myCache.getConfiguration().setCacheLoaderConfig(null); | myCache.getConfiguration().setNodeLockingScheme(NodeLockingScheme.MVCC); | configure(myCache.getConfiguration()); | myCache.start(); | root = myCache.getRoot(); | txManager = myCache.getTransactionManager(); | | return myCache; | } | | protected void configure(Configuration c) { | c.setIsolationLevel(IsolationLevel.REPEATABLE_READ); | } | | public void testPferAndEvictInSameTx() throws Exception { | | Object val = null; | | cache.getRoot().addChild(A); | | txManager.begin(); | | //put in cache | cache.putForExternalRead(A, KEY, VALUE); | | //evict from cache | cache.evict(A); //sometimes MVCCInvocationContext has ref to mvccTCtx, sometimes NOT | | //verify eviction | val = cache.get(A, KEY); | assert val == null : "get() after evict() returned " + val; | | txManager.commit(); | | } | } | View the original post : http://www.jboss.org/index.html?module=bb&op=viewtopic&p=4216794#4216794 Reply to the post : http://www.jboss.org/index.html?module=bb&op=posting&mode=reply&p=4216794 ___ jboss-user mailing list [email protected] https://lists.jboss.org/mailman/listinfo/jboss-user
[jboss-user] [JBoss Cache: Core Edition] - Re: is it possible for MVCCInvocationContext to have null mv
Exactly, in my environment I am seeing precisely that: cache.evict() fails to evict. I wrote up what I thought was the root cause for of this failure: pfer writes to one (non-tx) context, while evict looks in another (please see my post right above yours) Could you please point out where in above reasoning I may be making a mistake (obviously being new to JBC I don't quite understand the internals yet)? fwiw, when I rebuilt jbc with pfer NOT using failSilently, evict-after-pfer started to work. However, it is true that thus far I am unable to replicate this failure in a jbc test suite test - so it is quite possible that the problem is not with JBC Core but, for example, with my setup or hibernate-jbosscache2 integration. thanks -nikita View the original post : http://www.jboss.org/index.html?module=bb&op=viewtopic&p=4216663#4216663 Reply to the post : http://www.jboss.org/index.html?module=bb&op=posting&mode=reply&p=4216663 ___ jboss-user mailing list [email protected] https://lists.jboss.org/mailman/listinfo/jboss-user
[jboss-user] [JBoss Cache: Core Edition] - Re: is it possible for MVCCInvocationContext to have null mv
Hi and sorry for not responding sooner. putForExternalRead was designed to specifically work outside the scope of any ongoing transaction, so that it does not cause any ongoing transaction to fail and roll back if the pFER() call fails. So this is why calls to ctx.lookUpNode() within the scope of a pFER() call uses the looked up nodes map on the InvocationContext rather than the TransactionContext, this is by design. The evict call, that then attempts to evict the node, should be referring to the transaction context and not the invocation context. This again is by design, and since the node does not exist in the transaction context, it would be loaded into the transaction context in MVCCLockingInterceptor.handleEvictFqnCommand(). If for some reason your call to cache.evict() fails, then this is probably a bug. View the original post : http://www.jboss.org/index.html?module=bb&op=viewtopic&p=4216642#4216642 Reply to the post : http://www.jboss.org/index.html?module=bb&op=posting&mode=reply&p=4216642 ___ jboss-user mailing list [email protected] https://lists.jboss.org/mailman/listinfo/jboss-user
[jboss-user] [JBoss Cache: Core Edition] - Re: is it possible for MVCCInvocationContext to have null mv
Well, it appears that the above *is* possible - but I wonder whether that is a
bug. Basically, because of failSilently==true putForExternalRead ends up adding
Node to MVCCInvocationContext.lookedUpNodes but subsequent evictNode() uses
MVCCInvocationContext.mvccTCtx to look up the same node (and fails to find it)
Setup: Hibernate, JBC 3.0.3.GA; MVCC; JTA tm injected; REPEATABLE_READ iso
Consider the following scenario:
pre: cache is empty
tx.begin()
cache.putForExternalRead(fqnA, val);
cache.evictNode(fqnA) //expect eviction to succeed
tx.commit()
1. By the time invocationContextInteceptor invokes next interceptor,
mvccInvocationContext.mvccTCtx is null!
Given failSilently=true in putForExternalRead:
getInvocationContext().getOptionOverrides().setFailSilently(true);
|
getInvocationContext().getOptionOverrides().setForceAsynchronous(true);
| PutForExternalReadCommand command =
commandsFactory.buildPutForExternalReadCommand(null, fqn, key, value);
| invoker.invoke(ctx, command);
... InvocationContextInterceptor sets transactionalContext twice in handleAll
(at lines 150 and 164):
if (txManager != null)
| {
| Transaction tx = getTransaction();
| GlobalTransaction realGtx = getGlobalTransaction(tx, gtx);
| if (tx == null && realGtx != null && realGtx.isRemote()) tx =
txTable.getLocalTransaction(gtx);
| setTransactionalContext(tx, realGtx, null, ctx);
| }
..and
if (optionOverride != null && optionOverride.isFailSilently())
| {
| log.debug("FAIL_SILENTLY Option is present - suspending any
ongoing transaction.");
| suppressExceptions = true;
| if (ctx.getTransaction() != null)
| {
|suspendedTransaction = txManager.suspend();
|setTransactionalContext(null, null, null, ctx);
|if (trace) log.trace("Suspending transaction " +
suspendedTransaction);
|resumeSuspended = true;
| }
The first invocation of setTransactionalContext injects valid
TransactionContext, Transaction into MVCCInvocationContext. but the second
invocation clears them, such that invocationContext.getTransaction() will
return null henceforth.
Subsequently other interceptors are invoked, including TxInterceptor, whose
attachGtxAndPassUpChain does not attach anything because
ctx.getTransaction()==null. For the remainder of this invocation
MVCCInvocationContext.mvccTCtx remains null and ctx.lookedUpNodes is used.
2. Cache.evictNode fails to evict because ctx.lookUpNode looks in mvccTCtx and
does not find Node.
Subsequent Cache.evictNode(fqn) does not use failSilently option, so
setTransactionalContext in InvocationContextInterceptor is NOT called twice and
valid transactionContext remains injected into invocationContext. So, when
ctx.lookUpNode() is called from EvictCommand.perform, existing ctx.mvccTCtx is
consulted (and NOT 'lookUpNodes'). And thus, the node is not found, and
eviction is not performed. NOTE: seems like any command that uses
ctx.lookUpNode and is NOT invoked with failSilently==true will fail to lookup
this node for the same reason.
Also note that in NotifierImpl.resetInvocationContext lookedUpNodes are copied,
so the above not-evicted-node would be copied as well.
Thoughts?
If the does seem like a bug, the obvious solution seems to be not to use
failSilently option in Cache.putForExternalRead (and in other places?). What
would be the implication?
View the original post :
http://www.jboss.org/index.html?module=bb&op=viewtopic&p=4216349#4216349
Reply to the post :
http://www.jboss.org/index.html?module=bb&op=posting&mode=reply&p=4216349
___
jboss-user mailing list
[email protected]
https://lists.jboss.org/mailman/listinfo/jboss-user
[jboss-user] [JBoss Cache: Core Edition] - Re: is it possible for MVCCInvocationContext to have null mv
Sorry, I meant 'mvccTCtx' from:
|public NodeSPI lookUpNode(Fqn fqn)
|{
| if (mvccTCtx != null) return mvccTCtx.lookUpNode(fqn);
| return lookedUpNodes == null ? null : lookedUpNodes.get(fqn);
|}
|
View the original post :
http://www.jboss.org/index.html?module=bb&op=viewtopic&p=4215971#4215971
Reply to the post :
http://www.jboss.org/index.html?module=bb&op=posting&mode=reply&p=4215971
___
jboss-user mailing list
[email protected]
https://lists.jboss.org/mailman/listinfo/jboss-user
