package org.infinispan.distribution.rehash;
import static org.testng.AssertJUnit.assertTrue;
import java.util.Set;
import org.infinispan.Cache;
import org.infinispan.configuration.cache.CacheMode;
import org.infinispan.configuration.cache.Configuration;
import org.infinispan.configuration.cache.ConfigurationBuilder;
import org.infinispan.container.DataContainer;
import org.infinispan.distribution.DistributionManager;
import org.infinispan.manager.EmbeddedCacheManager;
import org.infinispan.persistence.dummy.DummyInMemoryStoreConfigurationBuilder;
import org.infinispan.test.MultipleCacheManagersTest;
import org.infinispan.util.logging.Log;
import org.infinispan.util.logging.LogFactory;
import org.testng.annotations.Test;
/**
* Test with a distributed cache (numOwners=1), a shared cache store and 'preload' enabled
* (ISPN-1964).
*
* @author Carsten Lohmann
*/
@Test(testName = "distribution.rehash.RehashAfterJoinWithPreloadTest", groups = "functional")
public class RehashAfterJoinWithPreloadTest extends MultipleCacheManagersTest {
private static final Log log = LogFactory.getLog(RehashAfterJoinWithPreloadTest.class);
public static final int NUM_KEYS = 20;
private final String testCacheName = "testCache" + getClass().getSimpleName();
@Override
protected void createCacheManagers() {
// cacheManagers started one after another in test()
}
private void addNewCacheManagerAndWaitForRehash() {
EmbeddedCacheManager cacheManager = addClusterEnabledCacheManager(getDefaultClusteredCacheConfig(
CacheMode.DIST_SYNC, false));
cacheManager.defineConfiguration(testCacheName, buildCfg(true));
log.debugf("\n\nstarted CacheManager #%d", getCacheManagers().size() - 1);
waitForClusterToForm(testCacheName);
}
private Configuration buildCfg(boolean clustered) {
ConfigurationBuilder cb = new ConfigurationBuilder();
cb.persistence()
.addStore(DummyInMemoryStoreConfigurationBuilder.class)
.storeName(testCacheName)
.preload(true)
.shared(true)
.purgeOnStartup(false);
cb.persistence().passivation(false);
if (clustered) {
cb.clustering().l1().disable();
cb.clustering().cacheMode(CacheMode.DIST_SYNC);
cb.clustering().hash().numOwners(1); // one owner!
cb.clustering().stateTransfer().fetchInMemoryState(true);
cb.clustering().hash().groups().enabled();
}
return cb.build(true);
}
public void test() {
// start a cluster that uses this cache store
// add 1st member
addNewCacheManagerAndWaitForRehash();
// insert the data in the cache and check the contents
putTestDataInCacheStore();
printCacheContents();
// stop the 1st member
killMember(0);
// re-add the 1st member
addNewCacheManagerAndWaitForRehash();
printCacheContents();
assertEvenDistribution();
// add 2nd member
addNewCacheManagerAndWaitForRehash();
printCacheContents();
assertEvenDistribution();
// add 3rd member
addNewCacheManagerAndWaitForRehash();
printCacheContents();
assertEvenDistribution();
}
private void assertEvenDistribution() {
for (int i = 0; i < getCacheManagers().size(); i++) {
Cache<String, String> testCache = manager(i).getCache(testCacheName);
DistributionManager dm = testCache.getAdvancedCache().getDistributionManager();
DataContainer dataContainer = testCache.getAdvancedCache().getDataContainer();
// Note there is stale data in the cache store that this owner no longer owns
for (int j = 0; j < NUM_KEYS; j++) {
String key = "key" + j;
// each key must only occur once (numOwners is one)
if (dm.getLocality(key).isLocal()) {
assertTrue("Key '" + key + "' is owned by node " + address(i) + " but it doesn't appear there",
dataContainer.containsKey(key));
} else {
assertTrue("Key '" + key + "' is not owned by node " + address(i) + " but it still appears there",
!dataContainer.containsKey(key));
}
}
}
}
private void putTestDataInCacheStore() {
Cache<String, String> cache = manager(0).getCache(testCacheName);
for (int i = 0; i < NUM_KEYS; i++) {
cache.put("key" + i, Integer.toString(i));
}
log.debugf("added %d entries to test cache", NUM_KEYS);
}
private void printCacheContents() {
log.debugf("%d cache manager(s)", getCacheManagers().size());
for (int i = 0; i < getCacheManagers().size(); i++) {
Cache<String, String> testCache = manager(i).getCache(testCacheName);
log.debugf(" Contents of Cache with CacheManager #%d (%s, all members: %s)", i, address(i),
testCache.getAdvancedCache().getRpcManager().getMembers());
Set<String> keySet = testCache.keySet();
log.debugf(" keySet = %s", keySet);
for (String key : keySet) {
log.debugf(" key: %s value: %s", key, testCache.get(key));
}
}
}
}