package org.infinispan.partitionhandling;
import static org.testng.AssertJUnit.assertFalse;
import static org.testng.AssertJUnit.assertTrue;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import javax.transaction.Transaction;
import javax.transaction.TransactionManager;
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;
/**
* It tests multiple scenarios where a split can happen during a transaction.
*
* @author Pedro Ruivo
* @since 8.0
*/
public abstract class BasePessimisticTxPartitionAndMergeTest extends BaseTxPartitionAndMergeTest {
protected static final String PESSIMISTIC_TX_CACHE_NAME = "pes-cache";
@Override
protected void createCacheManagers() throws Throwable {
super.createCacheManagers();
ConfigurationBuilder builder = getDefaultClusteredCacheConfig(CacheMode.DIST_SYNC);
builder.clustering().partitionHandling().enabled(true);
builder.transaction().lockingMode(LockingMode.PESSIMISTIC).transactionMode(TransactionMode.TRANSACTIONAL).transactionManagerLookup(new EmbeddedTransactionManagerLookup());
defineConfigurationOnAllManagers(PESSIMISTIC_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(PESSIMISTIC_TX_CACHE_NAME);
final KeyInfo keyInfo = createKeys(PESSIMISTIC_TX_CACHE_NAME);
final Cache<Object, String> originator = cache(0, PESSIMISTIC_TX_CACHE_NAME);
final FilterCollection filterCollection = createFilters(PESSIMISTIC_TX_CACHE_NAME, discard, getCommandClass(), splitMode);
Future<Void> put = fork(() -> {
final TransactionManager transactionManager = originator.getAdvancedCache().getTransactionManager();
transactionManager.begin();
final Transaction tx = transactionManager.getTransaction();
try {
keyInfo.putFinalValue(originator);
if (forceRollback()) {
tx.setRollbackOnly();
}
} finally {
transactionManager.commit();
}
return null;
});
filterCollection.await(30, TimeUnit.SECONDS);
splitMode.split(this);
filterCollection.unblock();
try {
put.get();
assertFalse(txFail);
} catch (ExecutionException e) {
assertTrue(txFail);
}
checkLocksDuringPartition(splitMode, keyInfo, discard);
mergeCluster(PESSIMISTIC_TX_CACHE_NAME);
finalAsserts(PESSIMISTIC_TX_CACHE_NAME, keyInfo, txFail ? INITIAL_VALUE : FINAL_VALUE);
}
}