package org.infinispan.statetransfer; import static org.infinispan.statetransfer.StateTransferTestingUtil.verifyInitialData; import static org.infinispan.statetransfer.StateTransferTestingUtil.verifyInitialDataOnLoader; import static org.infinispan.statetransfer.StateTransferTestingUtil.verifyNoData; import static org.infinispan.statetransfer.StateTransferTestingUtil.verifyNoDataOnLoader; import static org.infinispan.statetransfer.StateTransferTestingUtil.writeInitialData; import java.lang.reflect.Method; import java.util.concurrent.Callable; import java.util.concurrent.Future; import org.infinispan.Cache; import org.infinispan.configuration.cache.CacheMode; import org.infinispan.configuration.cache.ConfigurationBuilder; import org.infinispan.context.Flag; import org.infinispan.manager.CacheContainer; import org.infinispan.manager.EmbeddedCacheManager; import org.infinispan.persistence.dummy.DummyInMemoryStoreConfigurationBuilder; import org.infinispan.test.MultipleCacheManagersTest; import org.infinispan.test.TestingUtil; import org.infinispan.transaction.LockingMode; import org.infinispan.util.logging.Log; import org.infinispan.util.logging.LogFactory; import org.testng.annotations.Test; /** * StateTransferFileCacheStoreFunctionalTest. * * @author Galder ZamarreƱo * @since 4.0 */ @Test(groups = "functional", testName = "statetransfer.StateTransferFileCacheLoaderFunctionalTest") public class StateTransferFileCacheLoaderFunctionalTest extends MultipleCacheManagersTest { static final Log log = LogFactory.getLog(StateTransferFileCacheLoaderFunctionalTest.class); static String cacheName = "nbst-with-file-loader"; volatile int testCount = 0; ThreadLocal<Boolean> sharedCacheLoader = new ThreadLocal<Boolean>() { @Override protected Boolean initialValue() { return false; } }; ConfigurationBuilder configurationBuilder; @Override protected void createCacheManagers() throws Throwable { // This impl only really sets up a configuration for use later. configurationBuilder = getDefaultClusteredCacheConfig(CacheMode.REPL_SYNC, true); configurationBuilder.transaction().lockingMode(LockingMode.PESSIMISTIC); configurationBuilder.clustering().remoteTimeout(30000); configurationBuilder.clustering().stateTransfer().fetchInMemoryState(true); configurationBuilder.locking().useLockStriping(false); // reduces the odd chance of a key collision and deadlock } protected EmbeddedCacheManager createCacheManager() { configurationBuilder.persistence().clearStores(); configurationBuilder.persistence() .addStore(DummyInMemoryStoreConfigurationBuilder.class) .fetchPersistentState(true) .purgeOnStartup(false) .shared(sharedCacheLoader.get()); EmbeddedCacheManager cm = addClusterEnabledCacheManager(); cm.defineConfiguration(cacheName, configurationBuilder.build()); return cm; } public void testSharedLoader() throws Exception { CacheContainer cm1 = null, cm2 = null; try { sharedCacheLoader.set(true); cm1 = createCacheManager(); Cache c1 = cm1.getCache(cacheName); verifyNoDataOnLoader(c1); verifyNoData(c1); writeInitialData(c1); // starting the second cache would initialize an in-memory state transfer but not a persistent one since the loader is shared cm2 = createCacheManager(); Cache c2 = cm2.getCache(cacheName); TestingUtil.blockUntilViewsReceived(60000, c1, c2); verifyInitialDataOnLoader(c1); verifyInitialData(c1); verifyNoDataOnLoader(c2); // There shouldn't be any data locally since there was no entries in memory and the shared loader doesn't // actually share entries verifyNoData(c2.getAdvancedCache().withFlags(Flag.CACHE_MODE_LOCAL)); } finally { if (cm1 != null) cm1.stop(); if (cm2 != null) cm2.stop(); sharedCacheLoader.set(false); } } public void testInitialStateTransfer() throws Exception { testCount++; log.info("testInitialStateTransfer start - " + testCount); CacheContainer cm1 = null, cm2 = null; try { Cache<Object, Object> cache1, cache2; cm1 = createCacheManager(); cache1 = cm1.getCache(cacheName); writeInitialData(cache1); cm2 = createCacheManager(); cache2 = cm2.getCache(cacheName); // Pause to give caches time to see each other TestingUtil.blockUntilViewsReceived(60000, cache1, cache2); verifyInitialData(cache2); log.info("testInitialStateTransfer end - " + testCount); } finally { if (cm1 != null) cm1.stop(); if (cm2 != null) cm2.stop(); } } public void testInitialStateTransferInDifferentThread(Method m) throws Exception { testCount++; log.info(m.getName() + " start - " + testCount); CacheContainer cm1 = null, cm2 = null, cm30 = null; try { Cache<Object, Object> cache1 = null, cache2 = null, cache3 = null; cm1 = createCacheManager(); cache1 = cm1.getCache(cacheName); writeInitialData(cache1); cm2 = createCacheManager(); cache2 = cm2.getCache(cacheName); cache1.put("delay", new StateTransferFunctionalTest.DelayTransfer()); // Pause to give caches time to see each other TestingUtil.blockUntilViewsReceived(60000, cache1, cache2); verifyInitialData(cache2); final CacheContainer cm3 = createCacheManager(); cm30 = cm3; Future<Void> f1 = fork(new Callable<Void>() { @Override public Void call() throws Exception { cm3.getCache(cacheName); return null; } }); f1.get(); cache3 = cm3.getCache(cacheName); TestingUtil.blockUntilViewsReceived(120000, cache1, cache2, cache3); verifyInitialData(cache3); log.info("testConcurrentStateTransfer end - " + testCount); } finally { if (cm1 != null) cm1.stop(); if (cm2 != null) cm2.stop(); if (cm30 != null) cm30.stop(); } } public void testConcurrentStateTransfer() throws Exception { testCount++; log.info("testConcurrentStateTransfer start - " + testCount); CacheContainer cm1 = null, cm2 = null, cm30 = null, cm40 = null; try { Cache<Object, Object> cache1 = null, cache2 = null, cache3 = null, cache4 = null; cm1 = createCacheManager(); cache1 = cm1.getCache(cacheName); writeInitialData(cache1); cm2 = createCacheManager(); cache2 = cm2.getCache(cacheName); cache1.put("delay", new StateTransferFunctionalTest.DelayTransfer()); // Pause to give caches time to see each other TestingUtil.blockUntilViewsReceived(60000, cache1, cache2); verifyInitialData(cache2); final CacheContainer cm3 = createCacheManager(); final CacheContainer cm4 = createCacheManager(); cm30 = cm3; cm40 = cm4; Future<Void> f1 = fork(new Callable<Void>() { @Override public Void call() throws Exception { cm3.getCache(cacheName); return null; } }); Future<Void> f2 = fork(new Callable<Void>() { @Override public Void call() throws Exception { cm4.getCache(cacheName); return null; } }); f1.get(); f2.get(); cache3 = cm3.getCache(cacheName); cache4 = cm4.getCache(cacheName); TestingUtil.blockUntilViewsReceived(120000, cache1, cache2, cache3, cache4); verifyInitialData(cache3); verifyInitialData(cache4); log.info("testConcurrentStateTransfer end - " + testCount); } finally { if (cm1 != null) cm1.stop(); if (cm2 != null) cm2.stop(); if (cm30 != null) cm30.stop(); if (cm40 != null) cm40.stop(); } } }