package org.infinispan.atomic; import static org.testng.AssertJUnit.assertEquals; import java.util.Arrays; import java.util.HashSet; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import org.infinispan.Cache; import org.infinispan.configuration.cache.CacheMode; import org.infinispan.configuration.cache.ConfigurationBuilder; import org.infinispan.distribution.MagicKey; import org.infinispan.manager.EmbeddedCacheManager; import org.infinispan.remoting.rpc.RpcManager; import org.infinispan.statetransfer.StateResponseCommand; import org.infinispan.test.MultipleCacheManagersTest; import org.infinispan.test.TestingUtil; import org.infinispan.transaction.TransactionMode; import org.infinispan.tx.dld.ControlledRpcManager; import org.testng.annotations.Test; /** * Test modifications to an AtomicMap during state transfer are consistent. * * @author Dan Berindei * @since 7.0 */ @Test(groups = "functional", testName = "atomic.AtomicMapStateTransferTest") public class AtomicMapStateTransferTest extends MultipleCacheManagersTest { public static final String CACHE_NAME = "atomic"; protected void createCacheManagers() throws Throwable { ConfigurationBuilder c = getConfigurationBuilder(); createClusteredCaches(1, CACHE_NAME, c); } private ConfigurationBuilder getConfigurationBuilder() { ConfigurationBuilder c = new ConfigurationBuilder(); c.clustering().cacheMode(CacheMode.DIST_SYNC); c.transaction().transactionMode(TransactionMode.TRANSACTIONAL); return c; } public void testAtomicMapPutDuringJoin() throws ExecutionException, InterruptedException { Cache cache = cache(0, CACHE_NAME); ControlledRpcManager crm = new ControlledRpcManager(cache.getAdvancedCache().getRpcManager()); TestingUtil.replaceComponent(cache, RpcManager.class, crm, true); MagicKey atomicMapKey = new MagicKey("atomicMapKey", cache); AtomicMap atomicMap = AtomicMapLookup.getAtomicMap(cache, atomicMapKey); atomicMap.put("key1", "value1"); crm.blockBefore(StateResponseCommand.class); ConfigurationBuilder c = getConfigurationBuilder(); final EmbeddedCacheManager joiner = addClusterEnabledCacheManager(c); joiner.defineConfiguration(CACHE_NAME, c.build()); Future<Cache> future = fork(new Callable<Cache>() { @Override public Cache call() throws Exception { return joiner.getCache(CACHE_NAME); } }); crm.waitForCommandToBlock(); // Now we know state transfer will try to create an AtomicMap(key1=value1) on cache2 // Insert another key in the atomic map, and check that cache2 has both keys after the state transfer atomicMap.put("key2", "value2"); crm.stopBlocking(); Cache cache2 = future.get(); AtomicMap atomicMap2 = AtomicMapLookup.getAtomicMap(cache2, atomicMapKey); assertEquals(new HashSet<String>(Arrays.asList("key1", "key2")), atomicMap2.keySet()); } }