Details
-
Bug
-
Resolution: Done
-
Blocker
-
5.1.0.CR1
-
None
-
None
Description
Imagine this scenario:
- Call put key=k and value="v1"
- Within transaction tx1, call put for key=k, value="v2" and stop the tx.
- Within a separate transaction tx2, call put with FAIL_SILENT for key=x and value="v3"
- put call in tx2 should fail
- within tx2 call get(k), this should return "v1" since that's the last valid committed value -> currently it returns "v3" which is wrong
Code:
public void testSilentLockFailureAffectsPostOperations() throws Exception { final Cache<Integer, String> cache = cache(0); final TransactionManager tm = cache.getAdvancedCache().getTransactionManager(); final ExecutorService e = Executors.newCachedThreadPool(); final CountDownLatch waitLatch = new CountDownLatch(1); final CountDownLatch continueLatch = new CountDownLatch(1); cache.put(1, "v1"); Future<Void> f1 = e.submit(new Callable<Void>() { @Override public Void call() throws Exception { tm.begin(); try { cache.put(1, "v2"); waitLatch.countDown(); continueLatch.await(); } catch (Exception e) { tm.setRollbackOnly(); throw e; } finally { if (tm.getStatus() == Status.STATUS_ACTIVE) tm.commit(); else tm.rollback(); } return null; } }); Future<Void> f2 = e.submit(new Callable<Void>() { @Override public Void call() throws Exception { waitLatch.await(); tm.begin(); try { AdvancedCache<Integer, String> silentCache = cache.getAdvancedCache().withFlags( Flag.FAIL_SILENTLY, Flag.ZERO_LOCK_ACQUISITION_TIMEOUT); silentCache.put(1, "v3"); assert !silentCache.lock(1); assert "v1".equals(cache.get(1)); } catch (Exception e) { tm.setRollbackOnly(); throw e; } finally { if (tm.getStatus() == Status.STATUS_ACTIVE) tm.commit(); else tm.rollback(); continueLatch.countDown(); } return null; } }); f1.get(); f2.get(); }