package org.infinispan.distribution.topologyaware;
import java.util.List;
import org.infinispan.Cache;
import org.infinispan.configuration.cache.CacheMode;
import org.infinispan.configuration.cache.ConfigurationBuilder;
import org.infinispan.configuration.global.GlobalConfigurationBuilder;
import org.infinispan.distribution.LocalizedCacheTopology;
import org.infinispan.distribution.ch.ConsistentHash;
import org.infinispan.manager.EmbeddedCacheManager;
import org.infinispan.remoting.transport.Address;
import org.infinispan.test.MultipleCacheManagersTest;
import org.infinispan.test.TestingUtil;
import org.infinispan.test.fwk.CleanupAfterTest;
import org.infinispan.test.fwk.TestCacheManagerFactory;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.Test;
/**
* @author Mircea.Markus@jboss.com
* @since 4.2
*/
@Test(groups = "functional", testName = "distribution.topologyaware.TopologyAwareStateTransferTest")
@CleanupAfterTest
public class TopologyAwareStateTransferTest extends MultipleCacheManagersTest {
private Address[] addresses;
@Override
protected void createCacheManagers() throws Throwable {
ConfigurationBuilder defaultConfig = getDefaultClusteredCacheConfig(CacheMode.DIST_SYNC);
log.debug("defaultConfig = " + defaultConfig.build().clustering().hash().numOwners());
defaultConfig.clustering().l1().disable().stateTransfer().fetchInMemoryState(true);
createClusteredCaches(5, defaultConfig);
ConsistentHash hash = cache(0).getAdvancedCache().getDistributionManager().getWriteConsistentHash();
List<Address> members = hash.getMembers();
addresses = members.toArray(new Address[members.size()]);
}
@AfterMethod
@Override
protected void clearContent() throws Throwable {
}
Cache<?, ?> cache(Address addr) {
for (Cache<?, ?> c : caches()) {
if (c.getAdvancedCache().getRpcManager().getAddress().equals(addr)) return c;
}
throw new RuntimeException("Address: " + addr);
}
public void testInitialState() {
cache(0).put(addresses[0],"v0");
cache(0).put(addresses[1],"v1");
cache(0).put(addresses[2],"v2");
cache(0).put(addresses[3],"v3");
cache(0).put(addresses[4],"v4");
log.debugf("Cache on node %s: %s", addresses[0], TestingUtil.printCache(cache(addresses[0])));
log.debugf("Cache on node %s: %s", addresses[1], TestingUtil.printCache(cache(addresses[1])));
log.debugf("Cache on node %s: %s", addresses[2], TestingUtil.printCache(cache(addresses[2])));
log.debugf("Cache on node %s: %s", addresses[3], TestingUtil.printCache(cache(addresses[3])));
assertExistence(addresses[0]);
assertExistence(addresses[1]);
assertExistence(addresses[2]);
assertExistence(addresses[3]);
assertExistence(addresses[4]);
}
@Test (dependsOnMethods = "testInitialState")
public void testNodeDown() {
EmbeddedCacheManager cm = cache(addresses[4]).getCacheManager();
log.info("Here is where ST starts");
TestingUtil.killCacheManagers(cm);
cacheManagers.remove(cm);
TestingUtil.blockUntilViewsReceived(60000, false, caches());
TestingUtil.waitForNoRebalance(caches());
log.info("Here is where ST ends");
List<Address> addressList = cache(addresses[0]).getAdvancedCache().getDistributionManager()
.getWriteConsistentHash().getMembers();
log.debug("After shutting down " + addresses[4] + " caches are " + addressList);
log.debugf("Cache on node %s: %s", addresses[0], TestingUtil.printCache(cache(addresses[0])));
log.debugf("Cache on node %s: %s", addresses[1], TestingUtil.printCache(cache(addresses[1])));
log.debugf("Cache on node %s: %s", addresses[2], TestingUtil.printCache(cache(addresses[2])));
log.debugf("Cache on node %s: %s", addresses[3], TestingUtil.printCache(cache(addresses[3])));
assertExistence(addresses[0]);
assertExistence(addresses[1]);
assertExistence(addresses[2]);
assertExistence(addresses[3]);
assertExistence(addresses[4]);
}
@Test (dependsOnMethods = "testNodeDown")
public void testNodeDown2() {
EmbeddedCacheManager cm = cache(addresses[2]).getCacheManager();
TestingUtil.killCacheManagers(cm);
cacheManagers.remove(cm);
TestingUtil.blockUntilViewsReceived(60000, false, caches());
TestingUtil.waitForNoRebalance(caches());
List<Address> addressList = cache(addresses[0]).getAdvancedCache().getDistributionManager()
.getWriteConsistentHash().getMembers();
log.debug("After shutting down " + addresses[2] + " caches are " + addressList);
log.debugf("Cache on node %s: %s", addresses[0], TestingUtil.printCache(cache(addresses[0])));
log.debugf("Cache on node %s: %s", addresses[1], TestingUtil.printCache(cache(addresses[1])));
log.debugf("Cache on node %s: %s", addresses[3], TestingUtil.printCache(cache(addresses[3])));
assertExistence(addresses[0]);
assertExistence(addresses[1]);
assertExistence(addresses[2]);
assertExistence(addresses[3]);
assertExistence(addresses[4]);
}
@Test (dependsOnMethods = "testNodeDown2")
public void testNodeDown3() {
EmbeddedCacheManager cm = cache(addresses[1]).getCacheManager();
TestingUtil.killCacheManagers(cm);
cacheManagers.remove(cm);
TestingUtil.blockUntilViewsReceived(60000, false, caches());
TestingUtil.waitForNoRebalance(caches());
List<Address> addressList = cache(addresses[0]).getAdvancedCache().getDistributionManager()
.getWriteConsistentHash().getMembers();
log.debug("After shutting down " + addresses[1] + " caches are " + addressList);
log.debugf("Cache on node %s: %s", addresses[0], TestingUtil.printCache(cache(addresses[0])));
log.debugf("Cache on node %s: %s", addresses[3], TestingUtil.printCache(cache(addresses[3])));
assertExistence(addresses[0]);
assertExistence(addresses[1]);
assertExistence(addresses[2]);
assertExistence(addresses[3]);
assertExistence(addresses[4]);
}
private <K> void assertExistence(final K key) {
LocalizedCacheTopology cacheTopology =
cache(addresses[0]).getAdvancedCache().getDistributionManager().getCacheTopology();
final List<Address> addresses = cacheTopology.getDistribution(key).writeOwners();
log.debug(key + " should be present on = " + addresses);
for (Cache<? super K, ?> c : caches()) {
eventuallyEquals("Failure for key " + key + " on cache " + address(c), addresses.contains(address(c)),
() -> c.getAdvancedCache().getDataContainer().containsKey(key));
}
}
@Override
protected EmbeddedCacheManager addClusterEnabledCacheManager(ConfigurationBuilder deConfiguration) {
int index = cacheManagers.size();
String rack;
String machine;
switch (index) {
case 0 : {
rack = "r0";
machine = "m0";
break;
}
case 1 : {
rack = "r0";
machine = "m1";
break;
}
case 2 : {
rack = "r1";
machine = "m0";
break;
}
case 3 : {
rack = "r2";
machine = "m0";
break;
}
case 4 : {
rack = "r2";
machine = "m0";
break;
}
default : {
throw new RuntimeException("Bad!");
}
}
GlobalConfigurationBuilder gcb = GlobalConfigurationBuilder.defaultClusteredBuilder();
gcb.transport().rackId(rack).machineId(machine);
EmbeddedCacheManager cm = TestCacheManagerFactory.createClusteredCacheManager(gcb, deConfiguration);
cacheManagers.add(cm);
return cm;
}
}