package org.infinispan.tx; import static org.infinispan.tx.recovery.RecoveryTestUtil.beginAndSuspendTx; import static org.infinispan.tx.recovery.RecoveryTestUtil.commitTransaction; import static org.infinispan.tx.recovery.RecoveryTestUtil.prepareTransaction; import static org.testng.Assert.assertEquals; import java.util.ArrayList; import java.util.Collection; import java.util.List; import org.infinispan.Cache; import org.infinispan.configuration.cache.CacheMode; import org.infinispan.configuration.cache.ConfigurationBuilder; import org.infinispan.remoting.transport.Address; import org.infinispan.test.MultipleCacheManagersTest; import org.infinispan.test.TestingUtil; import org.infinispan.transaction.lookup.EmbeddedTransactionManagerLookup; import org.infinispan.transaction.tm.EmbeddedTransaction; import org.testng.annotations.Test; /** * @author Mircea Markus */ @Test(groups = "functional", testName = "tx.ParticipantFailsAfterPrepareTest") public class ParticipantFailsAfterPrepareTest extends MultipleCacheManagersTest { @Override protected void createCacheManagers() throws Throwable { ConfigurationBuilder configuration = getDefaultClusteredCacheConfig(CacheMode.DIST_SYNC, true); configuration .locking() .useLockStriping(false) .transaction() .transactionManagerLookup(new EmbeddedTransactionManagerLookup()) .useSynchronization(false) .recovery() .disable() .clustering() .stateTransfer() .fetchInMemoryState(false) .hash() .numOwners(3); createCluster(configuration, 4); waitForClusterToForm(); } public void testNonOriginatorFailsAfterPrepare() throws Exception { final Object key = getKeyForCache(0); EmbeddedTransaction dummyTransaction = beginAndSuspendTx(cache(0), key); prepareTransaction(dummyTransaction); int indexToKill = -1; //this tx spreads over 3 out of 4 nodes, let's find one that has the tx and kill it final Collection<Address> locate = advancedCache(0).getDistributionManager().getCacheTopology().getWriteOwners(key); for (int i = 3; i > 0; i--) { if (locate.contains(address(i))) { indexToKill = i; break; } } log.debug("indexToKill = " + indexToKill); assert indexToKill > 0; Address toKill = address(indexToKill); TestingUtil.killCacheManagers(manager(indexToKill)); List<Cache> participants; participants = getAliveParticipants(indexToKill); TestingUtil.blockUntilViewsReceived(60000, false, participants); TestingUtil.waitForNoRebalance(participants); //one of the participants must not have a prepare on it boolean noLocks = false; for (Cache c : participants) { if (TestingUtil.extractLockManager(c).getNumberOfLocksHeld() == 0) noLocks = true; } assert noLocks; log.trace("About to commit. Killed node is: " + toKill); try { commitTransaction(dummyTransaction); } finally { //now check weather all caches have the same content and no locks acquired for (Cache c : participants) { assertEquals(TestingUtil.extractLockManager(c).getNumberOfLocksHeld(), 0); assertEquals(c.keySet().size(), 1); } } } private List<Cache> getAliveParticipants(int indexToKill) { List<Cache> participants = new ArrayList<>(); for (int i = 0; i < 4; i++) { if (i == indexToKill) continue; participants.add(cache(i)); } return participants; } }