package org.infinispan.partitionhandling; import static org.testng.AssertJUnit.assertEquals; import static org.testng.AssertJUnit.assertTrue; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import javax.transaction.Status; import org.infinispan.Cache; import org.infinispan.commands.tx.TransactionBoundaryCommand; import org.infinispan.configuration.cache.CacheMode; import org.infinispan.configuration.cache.ConfigurationBuilder; import org.infinispan.transaction.LockingMode; import org.infinispan.transaction.TransactionMode; import org.infinispan.transaction.lookup.EmbeddedTransactionManagerLookup; import org.infinispan.transaction.tm.EmbeddedTransaction; import org.infinispan.transaction.tm.EmbeddedTransactionManager; /** * It tests multiple scenarios where a split can happen during a transaction. * * @author Pedro Ruivo * @since 8.0 */ public abstract class BaseOptimisticTxPartitionAndMergeTest extends BaseTxPartitionAndMergeTest { static final String OPTIMISTIC_TX_CACHE_NAME = "opt-cache"; @Override protected void createCacheManagers() throws Throwable { super.createCacheManagers(); ConfigurationBuilder builder = getDefaultClusteredCacheConfig(CacheMode.DIST_SYNC); builder.clustering().partitionHandling().enabled(true); builder.transaction().lockingMode(LockingMode.OPTIMISTIC).transactionMode(TransactionMode.TRANSACTIONAL).transactionManagerLookup(new EmbeddedTransactionManagerLookup()); defineConfigurationOnAllManagers(OPTIMISTIC_TX_CACHE_NAME, builder); } protected abstract void checkLocksDuringPartition(SplitMode splitMode, KeyInfo keyInfo, boolean discard); protected abstract boolean forceRollback(); protected abstract Class<? extends TransactionBoundaryCommand> getCommandClass(); protected void doTest(final SplitMode splitMode, boolean txFail, boolean discard) throws Exception { waitForClusterToForm(OPTIMISTIC_TX_CACHE_NAME); final KeyInfo keyInfo = createKeys(OPTIMISTIC_TX_CACHE_NAME); final Cache<Object, String> originator = cache(0, OPTIMISTIC_TX_CACHE_NAME); final FilterCollection filterCollection = createFilters(OPTIMISTIC_TX_CACHE_NAME, discard, getCommandClass(), splitMode); Future<Integer> put = fork(() -> { final EmbeddedTransactionManager transactionManager = (EmbeddedTransactionManager) originator.getAdvancedCache().getTransactionManager(); transactionManager.begin(); keyInfo.putFinalValue(originator); final EmbeddedTransaction transaction = transactionManager.getTransaction(); transaction.runPrepare(); transaction.runCommit(forceRollback()); return transaction.getStatus(); }); filterCollection.await(30, TimeUnit.SECONDS); splitMode.split(this); filterCollection.unblock(); try { assertEquals(txFail ? Status.STATUS_ROLLEDBACK : Status.STATUS_COMMITTED, (int) put.get()); } catch (ExecutionException e) { assertTrue(txFail); } checkLocksDuringPartition(splitMode, keyInfo, discard); mergeCluster(OPTIMISTIC_TX_CACHE_NAME); finalAsserts(OPTIMISTIC_TX_CACHE_NAME, keyInfo, txFail ? INITIAL_VALUE : FINAL_VALUE); } }