package org.infinispan.tx;
import static org.testng.AssertJUnit.assertEquals;
import org.infinispan.commands.tx.CommitCommand;
import org.infinispan.commands.tx.PrepareCommand;
import org.infinispan.configuration.cache.CacheMode;
import org.infinispan.configuration.cache.ConfigurationBuilder;
import org.infinispan.context.impl.TxInvocationContext;
import org.infinispan.interceptors.base.CommandInterceptor;
import org.infinispan.test.MultipleCacheManagersTest;
import org.infinispan.test.fwk.CleanupAfterMethod;
import org.testng.annotations.Test;
/**
* @author Mircea.Markus@jboss.org
* @since 5.2
*/
@Test(groups = "functional", testName = "tx.NoRpcOnReadonlyTransactionsTest")
@CleanupAfterMethod
public class NoRpcOnReadonlyTransactionsTest extends MultipleCacheManagersTest {
private TxCheckInterceptor i0;
private TxCheckInterceptor i2;
private TxCheckInterceptor i1;
@Override
protected void createCacheManagers() throws Throwable {
ConfigurationBuilder config = getDefaultClusteredCacheConfig(CacheMode.DIST_SYNC, true);
config.clustering().hash().numOwners(1);
createCluster(config, 3);
waitForClusterToForm();
i0 = new TxCheckInterceptor();
i1 = new TxCheckInterceptor();
i2 = new TxCheckInterceptor();
advancedCache(0).addInterceptor(i0, 1);
advancedCache(1).addInterceptor(i1, 1);
advancedCache(2).addInterceptor(i2, 1);
}
public void testReadOnlyTxNoNetworkCallAtCommit() throws Exception {
Object k0 = getKeyForCache(0);
log.tracef("On address %s adding key %s", address(0), k0);
cache(0).put(k0, "v");
assertEquals(0, i0.remotePrepares);
assertEquals(0, i0.remoteCommits);
assertEquals(0, i1.remotePrepares);
assertEquals(0, i1.remoteCommits);
assertEquals(0, i2.remotePrepares);
assertEquals(0, i2.remoteCommits);
log.trace("Here is where the r-o tx happens.");
tm(1).begin();
assertEquals("v", cache(1).get(k0));
tm(1).commit();
assertEquals(0, i0.remotePrepares);
assertEquals(0, i0.remoteCommits);
assertEquals(0, i1.remotePrepares);
assertEquals(0, i1.remoteCommits);
assertEquals(0, i2.remotePrepares);
assertEquals(0, i2.remoteCommits);
tm(1).begin();
cache(1).put(getKeyForCache(2), "v");
assertEquals("v", cache(1).get(k0));
tm(1).commit();
assertEquals(0, i0.remotePrepares);
assertEquals(0, i0.remoteCommits);
assertEquals(0, i1.remotePrepares);
assertEquals(0, i1.remoteCommits);
assertEquals(1, i2.remotePrepares);
assertEquals(1, i2.remoteCommits);
}
public void testReadOnlyTxNoNetworkCallMultipleCaches() throws Exception {
defineConfigurationOnAllManagers("a", new ConfigurationBuilder().read(manager(0).getDefaultCacheConfiguration()));
cache(0, "a");
cache(1, "a");
cache(2, "a");
waitForClusterToForm("a");
cache(0, "a").put("k", "v");
assertEquals(0, i0.remotePrepares);
assertEquals(0, i0.remoteCommits);
assertEquals(0, i1.remotePrepares);
assertEquals(0, i1.remoteCommits);
assertEquals(0, i2.remotePrepares);
assertEquals(0, i2.remoteCommits);
assertEquals("v", cache(0, "a").get("k"));
assertEquals("v", cache(1, "a").get("k"));
assertEquals("v", cache(2, "a").get("k"));
Object k0 = getKeyForCache(0);
cache(0).put(k0, "v0");
Object k1 = getKeyForCache(1);
cache(1).put(k1, "v0");
Object k2 = getKeyForCache(2);
cache(2).put(k2, "v0");
tm(1).begin();
assertEquals("v", cache(1, "a").put("k", "v2"));
assertEquals("v0", cache(1).get(k0));
assertEquals("v0", cache(1).get(k1));
assertEquals("v0", cache(1).get(k2));
tm(1).commit();
assertEquals(0, i0.remotePrepares);
assertEquals(0, i0.remoteCommits);
assertEquals(0, i1.remotePrepares);
assertEquals(0, i1.remoteCommits);
assertEquals(0, i2.remotePrepares);
assertEquals(0, i2.remoteCommits);
assertEquals("v2", cache(0, "a").get("k"));
assertEquals("v2", cache(1, "a").get("k"));
assertEquals("v2", cache(2, "a").get("k"));
}
private static class TxCheckInterceptor extends CommandInterceptor {
private volatile int remotePrepares;
private volatile int remoteCommits;
@Override
public Object visitPrepareCommand(TxInvocationContext ctx, PrepareCommand command) throws Throwable {
if (!ctx.isOriginLocal()) remotePrepares++;
return super.visitPrepareCommand(ctx, command);
}
@Override
public Object visitCommitCommand(TxInvocationContext ctx, CommitCommand command) throws Throwable {
if (!ctx.isOriginLocal()) remoteCommits++;
return super.visitCommitCommand(ctx, command);
}
void reset() {
remotePrepares = remoteCommits = 0;
}
}
}