package org.infinispan.lock.singlelock.replicated.pessimistic; import java.util.concurrent.CountDownLatch; import org.infinispan.configuration.cache.CacheMode; import org.infinispan.distribution.MagicKey; import org.infinispan.lock.singlelock.replicated.optimistic.InitiatorCrashOptimisticReplTest; import org.infinispan.test.fwk.CleanupAfterMethod; import org.infinispan.transaction.LockingMode; import org.testng.annotations.Test; /** * @author Mircea Markus * @since 5.1 */ @Test(groups = "unstable", testName = "lock.singlelock.replicated.pessimistic.InitiatorCrashPessimisticReplTest", description = "See ISPN-2161 -- original group: functional") @CleanupAfterMethod public class InitiatorCrashPessimisticReplTest extends InitiatorCrashOptimisticReplTest { public InitiatorCrashPessimisticReplTest() { super(CacheMode.REPL_SYNC, LockingMode.PESSIMISTIC, false); } public void testInitiatorNodeCrashesBeforeCommit() throws Exception { TxControlInterceptor txControlInterceptor = new TxControlInterceptor(); txControlInterceptor.prepareProgress.countDown(); advancedCache(1).addInterceptor(txControlInterceptor, 1); MagicKey key = new MagicKey("k", cache(0)); beginAndCommitTx(key, 1); txControlInterceptor.preparedReceived.await(); assertLocked(cache(0), key); assertEventuallyNotLocked(cache(1), key); assertEventuallyNotLocked(cache(2), key); checkTxCount(0, 0, 1); checkTxCount(1, 1, 0); checkTxCount(2, 0, 1); killMember(1); assertNotLocked(key); eventually(new Condition() { @Override public boolean isSatisfied() throws Exception { return checkTxCount(0, 0, 0) && checkTxCount(1, 0, 0); } }); } public void testInitiatorCrashesBeforeReleasingLock() throws Exception { final CountDownLatch releaseLocksLatch = new CountDownLatch(1); prepareCache(releaseLocksLatch); MagicKey key = new MagicKey("k", cache(0)); beginAndCommitTx(key, 1); releaseLocksLatch.await(); assert checkTxCount(0, 0, 1); assert checkTxCount(1, 0, 0); assert checkTxCount(2, 0, 1); assertLocked(cache(0), key); assertEventuallyNotLocked(cache(1), key); assertEventuallyNotLocked(cache(2), key); killMember(1); eventually(new Condition() { @Override public boolean isSatisfied() throws Exception { return checkTxCount(0, 0, 0) && checkTxCount(1, 0, 0); } }); assertNotLocked(key); assert cache(0).get(key).equals("v"); assert cache(1).get(key).equals("v"); } public void testInitiatorNodeCrashesBeforePrepare() throws Exception { MagicKey key = new MagicKey("a", cache(0)); cache(0).put(key, "b"); assert cache(0).get(key).equals("b"); assert cache(1).get(key).equals("b"); assert cache(2).get(key).equals("b"); TxControlInterceptor txControlInterceptor = new TxControlInterceptor(); advancedCache(1).addInterceptor(txControlInterceptor, 1); //prepare is sent, but is not precessed on other nodes because of the txControlInterceptor.preparedReceived beginAndPrepareTx("k", 1); eventually(new Condition() { @Override public boolean isSatisfied() throws Exception { return checkTxCount(0, 0, 1) && checkTxCount(1, 1, 0) && checkTxCount(2, 0, 1); } }); killMember(1); assert caches().size() == 2; txControlInterceptor.prepareProgress.countDown(); assertNotLocked("k"); eventually(new Condition() { @Override public boolean isSatisfied() throws Exception { return checkTxCount(0, 0, 0) && checkTxCount(1, 0, 0); } }); } }