package org.infinispan.persistence.file; import static org.infinispan.atomic.AtomicMapLookup.getAtomicMap; import static org.infinispan.test.fwk.TestCacheManagerFactory.createClusteredCacheManager; import static org.testng.AssertJUnit.assertEquals; import java.io.File; import java.lang.reflect.Method; import javax.transaction.TransactionManager; import org.infinispan.Cache; import org.infinispan.atomic.AtomicMap; import org.infinispan.commons.util.Util; import org.infinispan.configuration.cache.CacheMode; import org.infinispan.configuration.cache.ConfigurationBuilder; import org.infinispan.configuration.global.GlobalConfigurationBuilder; import org.infinispan.manager.EmbeddedCacheManager; import org.infinispan.test.MultipleCacheManagersTest; import org.infinispan.test.TestingUtil; import org.testng.annotations.AfterClass; import org.testng.annotations.Test; /** * @author Galder ZamarreƱo * @since 4.1 */ @Test(groups = "unit", testName = "persistence.file.ClusterFileStoreFunctionalTest") public class ClusterFileStoreFunctionalTest extends MultipleCacheManagersTest { // createCacheManager executes before any @BeforeClass defined in the class, so simply use standard tmp folder. private final String tmpDirectory = TestingUtil.tmpDirectory(this.getClass()); private static final String CACHE_NAME = "clusteredFileCacheStore"; private Cache<Object, ?> cache1, cache2; @AfterClass protected void clearTempDir() { Util.recursiveFileRemove(tmpDirectory); new File(tmpDirectory).mkdirs(); } @Override protected void createCacheManagers() throws Throwable { EmbeddedCacheManager cacheManager1 = createClusteredCacheManager(GlobalConfigurationBuilder.defaultClusteredBuilder(), new ConfigurationBuilder()); EmbeddedCacheManager cacheManager2 = createClusteredCacheManager(GlobalConfigurationBuilder.defaultClusteredBuilder(), new ConfigurationBuilder()); registerCacheManager(cacheManager1, cacheManager2); ConfigurationBuilder builder1 = getDefaultClusteredCacheConfig(CacheMode.REPL_SYNC, true); addCacheStoreConfig(builder1, 1); ConfigurationBuilder builder2 = getDefaultClusteredCacheConfig(CacheMode.REPL_SYNC, true); addCacheStoreConfig(builder2, 2); cacheManager1.defineConfiguration(CACHE_NAME, builder1.build()); cacheManager2.defineConfiguration(CACHE_NAME, builder2.build()); cache1 = cache(0, CACHE_NAME); cache2 = cache(1, CACHE_NAME); } public void testRestoreTransactionalAtomicMap(Method m) throws Exception { final Object mapKey = m.getName(); TransactionManager tm = cache1.getAdvancedCache().getTransactionManager(); tm.begin(); final AtomicMap<String, String> map = getAtomicMap(cache1, mapKey); map.put("a", "b"); tm.commit(); //ISPN-3161 => the eviction tries to acquire the lock, however the TxCompletionNotificationCommand is sent async // and the deliver can be delayed resulting in a delay releasing the lock and a TimeoutException // when the evict tries to acquire the lock. assertEventuallyNoLocksAcquired(mapKey); //evict from memory cache1.evict(mapKey); // now re-retrieve the map and make sure we see the diffs assertEquals("Wrong value for key [a] in atomic map.", "b", getAtomicMap(cache1, mapKey).get("a")); assertEquals("Wrong value for key [a] in atomic map.", "b", getAtomicMap(cache2, mapKey).get("a")); cache2.evict(mapKey); assertEquals("Wrong value for key [a] in atomic map.", "b", getAtomicMap(cache1, mapKey).get("a")); assertEquals("Wrong value for key [a] in atomic map.", "b", getAtomicMap(cache2, mapKey).get("a")); } protected void addCacheStoreConfig(ConfigurationBuilder builder, int index) { builder.persistence().addSingleFileStore().location(tmpDirectory + "/" + index); } protected void assertEventuallyNoLocksAcquired(final Object key) { eventually(new Condition() { @Override public boolean isSatisfied() throws Exception { return !TestingUtil.extractLockManager(cache1).isLocked(key); } }); eventually(new Condition() { @Override public boolean isSatisfied() throws Exception { return !TestingUtil.extractLockManager(cache2).isLocked(key); } }); } }