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);
}
});
}
}