-
1. Re: How to acquire a lock without possible transaction termination ?
matlach Apr 20, 2012 7:27 AM (in response to dudalov)hi dmitry,
in pessimistic mode, when acquiring lock, even if there's no value associated in the cache with the specified key, it will still lock the key you passed on.
if someone else has already aquired the lock, the lock operation will wait until it has been released either by commit or rollback.
hope this help.
-
2. Re: How to acquire a lock without possible transaction termination ?
dudalov Apr 20, 2012 1:25 PM (in response to matlach)Hi Mathieu,
Thank you for the prompt response. Let me see if I get it correctly. Are you saying that instead of locking directly the object in the main cache I could:
1. start transaction on cache A
2 ....
3. lock an auxiliary key on another cache B
4. only if it succeed lock the object in question in cache A
5. some updates in cache A
6. commit the main transaction on cache A
7. unlock auxiliary lock on cache B
In this scenario inability to lock an auxiliary key (step 3) won't damage the main transaction, so the process could decide what to do. Do I get it right? But what about performance? Any significant impact on it since it takes additional lock/unlock operations?
Thanks,
Dmitry
-
3. Re: How to acquire a lock without possible transaction termination ?
dudalov Apr 20, 2012 1:59 PM (in response to dudalov)BTW, it was pessimistic mode where I saw that TimeoutException, so the outcome is not only "... the lock operation will wait until it has been released either by commit or rollback ...".
The operation might also fail with an exception which would mark the transaction as "rollback only" as a side effect.
-
4. Re: How to acquire a lock without possible transaction termination ?
dudalov Apr 20, 2012 3:18 PM (in response to dudalov)Obviously I got it wrong. Embedded transactions are not supported.
So I'm back to my original question: how can I safely try if an object could be locked in the cache without breaking the existing transaction.
-
5. Re: How to acquire a lock without possible transaction termination ?
matlach Apr 20, 2012 6:30 PM (in response to dudalov)I don't think there's such feature like ReentrantLock::tryLock()
see actual LockManager documentation :
http://docs.jboss.org/infinispan/5.1/apidocs/org/infinispan/util/concurrent/locks/LockManager.html
tough, when lock acquisition fail, it do not break transaction at all, just catch the TimeoutException.
finally, maybe you should also have a look at how to manage user transaction :
https://community.jboss.org/wiki/WhatIsTheCorrectPatternForUserTransactions
-
6. Re: How to acquire a lock without possible transaction termination ?
dudalov Apr 20, 2012 7:11 PM (in response to matlach)Thanks for the links. As for re-trying, unfortunately it's not possible because transaction's state is set to rollback only. That's the point. I tried to catch the TimeoutException and re-submit lock acquisition request one more time but it failed immediately with IllegalStateException. Debugging showed that the state of the transaction was changed to to STATUS_MARKED_ROLLBACK by
InvocationContextInterceptor.markTxForRollbackAndRethrow called from line 144 (infinispan-5.1.2.FINAL)
Here's the complete stack traces
org.infinispan.util.concurrent.TimeoutException: Unable to acquire lock after [120 seconds] on key [737IMzDYBABCAAWmEkTPAZg==] for requestor [GlobalTransaction:<Sound-57047>:1:local]! Lock held by [null]
at org.infinispan.util.concurrent.locks.LockManagerImpl.lock(LockManagerImpl.java:206)
at org.infinispan.util.concurrent.locks.LockManagerImpl.acquireLock(LockManagerImpl.java:180)
at org.infinispan.util.concurrent.locks.LockManagerImpl.acquireLock(LockManagerImpl.java:170)
at org.infinispan.interceptors.locking.AbstractTxLockingInterceptor.lockKeyAndCheckOwnership(AbstractTxLockingInterceptor.java:209)
at org.infinispan.interceptors.locking.AbstractTxLockingInterceptor.lockAndRegisterBackupLock(AbstractTxLockingInterceptor.java:136)
at org.infinispan.interceptors.locking.PessimisticLockingInterceptor.visitLockControlCommand(PessimisticLockingInterceptor.java:228)
at org.infinispan.commands.control.LockControlCommand.acceptVisitor(LockControlCommand.java:129)
at org.infinispan.interceptors.base.CommandInterceptor.invokeNextInterceptor(CommandInterceptor.java:116)
at org.infinispan.interceptors.base.CommandInterceptor.handleDefault(CommandInterceptor.java:130)
at org.infinispan.commands.AbstractVisitor.visitLockControlCommand(AbstractVisitor.java:159)
at org.infinispan.commands.control.LockControlCommand.acceptVisitor(LockControlCommand.java:129)
at org.infinispan.interceptors.base.CommandInterceptor.invokeNextInterceptor(CommandInterceptor.java:116)
at org.infinispan.interceptors.TxInterceptor.visitLockControlCommand(TxInterceptor.java:144)
at org.infinispan.commands.control.LockControlCommand.acceptVisitor(LockControlCommand.java:129)
at org.infinispan.interceptors.base.CommandInterceptor.invokeNextInterceptor(CommandInterceptor.java:116)
at org.infinispan.interceptors.StateTransferLockInterceptor.handleWithRetries(StateTransferLockInterceptor.java:207)
at org.infinispan.interceptors.StateTransferLockInterceptor.visitLockControlCommand(StateTransferLockInterceptor.java:138)
at org.infinispan.commands.control.LockControlCommand.acceptVisitor(LockControlCommand.java:129)
at org.infinispan.interceptors.base.CommandInterceptor.invokeNextInterceptor(CommandInterceptor.java:116)
at org.infinispan.interceptors.base.CommandInterceptor.handleDefault(CommandInterceptor.java:130)
at org.infinispan.commands.AbstractVisitor.visitLockControlCommand(AbstractVisitor.java:159)
at org.infinispan.commands.control.LockControlCommand.acceptVisitor(LockControlCommand.java:129)
at org.infinispan.interceptors.base.CommandInterceptor.invokeNextInterceptor(CommandInterceptor.java:116)
at org.infinispan.interceptors.InvocationContextInterceptor.handleAll(InvocationContextInterceptor.java:130) <<<<<<<<<<<<<<<<< falls back here and changes transaction status
at org.infinispan.interceptors.InvocationContextInterceptor.visitLockControlCommand(InvocationContextInterceptor.java:94)
at org.infinispan.commands.control.LockControlCommand.acceptVisitor(LockControlCommand.java:129)
at org.infinispan.interceptors.InterceptorChain.invoke(InterceptorChain.java:345)
at org.infinispan.CacheImpl.lock(CacheImpl.java:484)
at org.infinispan.CacheImpl.lock(CacheImpl.java:468)
.....
And it's easy reproducible with pessimistic transactional replicated cache. Just have two or more Threads running the same task which execution time exceeds lockAcquisitionTimeout
-
7. Re: How to acquire a lock without possible transaction termination ?
dudalov Apr 24, 2012 1:09 PM (in response to dudalov)Any suggestions?
Thanks,
Dmitry
-
8. Re: How to acquire a lock without possible transaction termination ?
galder.zamarreno Apr 26, 2012 6:59 AM (in response to dudalov)I've opened a dev discussion in http://lists.jboss.org/pipermail/infinispan-dev/2012-April/010584.html
-
9. Re: How to acquire a lock without possible transaction termination ?
an1310 Apr 26, 2012 7:48 AM (in response to dudalov)1 of 1 people found this helpfulHi Dimitry,
I've done a TryLock-esque feature like the following:
public boolean tryLock(K key) { boolean success = cache.getAdvancedCache() .withFlags(Flag.FAIL_SILENTLY).lock(key); return success; }
The FAIL_SILENTY flag keeps the transaction from rolling back, and the lock API was enhanced to return a boolean value (in case of this value) back in the 4.2 timeframe.
Hope this helps,
Erik
-
10. Re: How to acquire a lock without possible transaction termination ?
matlach Apr 26, 2012 8:05 AM (in response to an1310)appears to me a nice trick erik,
i'll definitely try it.
do you think this is viable galder ?
-
11. Re: How to acquire a lock without possible transaction termination ?
dudalov Apr 26, 2012 1:25 PM (in response to an1310)Thank you, Erik! That works like a charm.
I tried modified unit test attached to the https://issues.jboss.org/browse/ISPN-2013 and now it showed no problems when executed with .withFlags(Flag.FAIL_SILENTLY). Woot!