[jbosscache-dev] Issue with JBCACHE-1309 WAS: Branch for 2.1.X

Brian Stansberry brian.stansberry at redhat.com
Tue Apr 1 16:53:44 EDT 2008


Test for this is 
org.jboss.cache.integration.hibernate.UpdateTimestampsCachingTest.testTimestampUpdateInAfterCompletionOptimistic()

Brian Stansberry wrote:
> Thanks. :) Good news, bad news.
> 
> Good news is the JBCACHE-1170 problem seems to be gone!
> 
> Bad news is a problem that seems to come from the JBCACHE-1309 fix. 
> Hibernate 2nd Level Cache, OPTIMISTIC locking.
> 
> Here's what happens:
> 
> Hibernate registers a tx Synchronization. So does JBC. But Hibernate's 
> executes before JBC's. So any beforeCompletion()/afterCompletion() will 
> be invoked by Hibernate before the same is done for JBC. So,
> 
> 1) Say a tx updates an entity, resulting in a put: to Fqn
> 
> cache.put("/test/Accounts/ENTITY/id at 1", ITEM, value);
> 
> 2) Tx goes into commit. beforeCompletion() gets called on on Hibernate 
> and JBC synchronizations. JBC.beforeCompletion() acquires locks on the 
> main tree.
> 
> 3) Hibernate.afterCompletion() gets called. JBC.afterCompletion() not 
> yet called, so locks are held on main cache. Hibernate uses the callback 
> to update the timestamps caches, which will invalidate any queries using 
> entity types affected by the tx. Logic boils down to this pseudo-code:
> 
> // Suspend any ongoing tx
> Transaction tx = tm.suspend();
> // Timestamp updates must go async
> cache.getInvocationContext().getOptionOverrides().setForceAsynchronous(true); 
> 
> cache.put("/TS/test/org/hibernate/cache/UpdateTimestampsCache/Accounts",
>           ITEM, value);
> tm.resume(tx);
> 
> Note there is no overlap in Fqn between the two puts. The call with the 
> transaction suspended is not trying to write to the same subtree as the 
> uncommitted tx.
> 
> The put is failing with a lock acquisition timeout:
> 
> org.jboss.cache.lock.TimeoutException: write lock for / could not be 
> acquired after 15000 ms. Locks: Read lock owners: 
> [GlobalTransaction:<127.0.0.1:43985>:72]
> Write lock owner: null
>  (caller=GlobalTransaction:<127.0.0.1:43985>:74, lock info: read 
> owners=[GlobalTransaction:<127.0.0.1:43985>:72] (activeReaders=1, 
> activeWriter=null, waitingReaders=0, waitingWriters=0, waitingUpgrader=0))
>     at 
> org.jboss.cache.lock.IdentityLock.acquireWriteLock0(IdentityLock.java:249)
>     at 
> org.jboss.cache.lock.IdentityLock.acquireWriteLock(IdentityLock.java:172)
>     at 
> org.jboss.cache.interceptors.OptimisticInterceptor.lockAndCreateWorkspaceNode(OptimisticInterceptor.java:112) 
> 
>     at 
> org.jboss.cache.interceptors.OptimisticNodeInterceptor.fetchWorkspaceNode(OptimisticNodeInterceptor.java:542) 
> 
>     at 
> org.jboss.cache.interceptors.OptimisticNodeInterceptor.fetchWorkspaceNode(OptimisticNodeInterceptor.java:571) 
> 
>     at 
> org.jboss.cache.interceptors.OptimisticNodeInterceptor.fetchWorkspaceNode(OptimisticNodeInterceptor.java:571) 
> 
>     at 
> org.jboss.cache.interceptors.OptimisticNodeInterceptor.fetchWorkspaceNode(OptimisticNodeInterceptor.java:571) 
> 
>     at 
> org.jboss.cache.interceptors.OptimisticNodeInterceptor.fetchWorkspaceNode(OptimisticNodeInterceptor.java:571) 
> 
>     at 
> org.jboss.cache.interceptors.OptimisticNodeInterceptor.fetchWorkspaceNode(OptimisticNodeInterceptor.java:571) 
> 
>     at 
> org.jboss.cache.interceptors.OptimisticNodeInterceptor.fetchWorkspaceNode(OptimisticNodeInterceptor.java:571) 
> 
>     at 
> org.jboss.cache.interceptors.OptimisticNodeInterceptor.fetchWorkspaceNode(OptimisticNodeInterceptor.java:571) 
> 
>     at 
> org.jboss.cache.interceptors.OptimisticNodeInterceptor.invoke(OptimisticNodeInterceptor.java:81) 
> 
>     at
>   ......
> org.jboss.cache.invocation.CacheInvocationDelegate.put(CacheInvocationDelegate.java:488) 
> 
> 
> What's going on here is fetchWorkspaceNode() is walking up the tree from 
> /TS/test/org/hibernate/cache/UpdateTimestampsCache/Accounts to Fqn.ROOT, 
> calling lockAndCreateWorkspaceNode() on each Fqn.  When it gets to 
> Fqn.ROOT it fails.  This is because lockAndCreateWorkspaceNode() wants a 
> write lock on the target node before making the workspace copy. In this 
> case the WL can't be obtained, because a RL is held by the suspended tx.
> 
> Does lockAndCreateWorkspaceNode() need a write lock here?
> 
> I'll add a unit test for this; seems like a good candidate for the start 
> of the integration tests I'd talked about.  This one is for sure a weird 
> usage; hard to imagine a regular JBC test exercising this call pattern.
> 
> - Brian
> 
> Manik Surtani wrote:
>> Guys, this is now done.
>>
>> It is pretty much a snapshot of trunk as of today, with Elias' Amazon 
>> S3 cache loader stuff removed (don't want to introduce this in a micro 
>> version - it will be there in 2.2.0).
>>
>> Brian, I have even built a snapshot on the JBoss snapshot Maven repo, 
>> so please give it a whirl and see if issues like JBCACHE-1170 have 
>> successfully been taken care of.
>>
>> Cheers,
>> -- 
>> Manik Surtani
>> Lead, JBoss Cache
>> manik at jboss.org
>>
>>
>>
>>
>>
>>
>> _______________________________________________
>> jbosscache-dev mailing list
>> jbosscache-dev at lists.jboss.org
>> https://lists.jboss.org/mailman/listinfo/jbosscache-dev
> 

-- 
Brian Stansberry
Lead, AS Clustering
JBoss, a division of Red Hat
brian.stansberry at redhat.com



More information about the jbosscache-dev mailing list