/*
* JBoss, Home of Professional Open Source
* Copyright 2010 Red Hat Inc. and/or its affiliates and other
* contributors as indicated by the @author tags. All rights reserved.
* See the copyright.txt in the distribution for a full listing of
* individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.infinispan.distribution.topologyaware;
import org.infinispan.Cache;
import org.infinispan.config.Configuration;
import org.infinispan.config.GlobalConfiguration;
import org.infinispan.distribution.ch.ConsistentHash;
import org.infinispan.distribution.ch.TopologyAwareConsistentHash;
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;
import java.util.List;
import java.util.Set;
/**
* @author Mircea.Markus@jboss.com
* @since 4.2
*/
@Test(groups = "functional", testName = "topologyaware.TopologyAwareStateTransferTest")
@CleanupAfterTest
public class TopologyAwareStateTransferTest extends MultipleCacheManagersTest {
private Address[] addresses;
@Override
protected void createCacheManagers() throws Throwable {
Configuration defaultConfig = getDefaultClusteredConfig(Configuration.CacheMode.DIST_SYNC);
log.debug("defaultConfig = " + defaultConfig.getNumOwners());
defaultConfig.setL1CacheEnabled(false);
createClusteredCaches(5, defaultConfig);
TopologyAwareConsistentHash hash =
(TopologyAwareConsistentHash) cache(0).getAdvancedCache().getDistributionManager().getConsistentHash();
Set<Address> addressSet = hash.getCaches();
addresses = addressSet.toArray(new Address[addressSet.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.waitForRehashToComplete(caches());
log.info("Here is where ST ends");
Set<Address> addressList = cache(addresses[0]).getAdvancedCache().getDistributionManager().getConsistentHash().getCaches();
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.waitForRehashToComplete(caches());
Set<Address> addressList = cache(addresses[0]).getAdvancedCache().getDistributionManager().getConsistentHash().getCaches();
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.waitForRehashToComplete(caches());
Set<Address> addressList = cache(addresses[0]).getAdvancedCache().getDistributionManager().getConsistentHash().getCaches();
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 void assertExistence(final Object key) {
ConsistentHash hash = cache(addresses[0]).getAdvancedCache().getDistributionManager().getConsistentHash();
final List<Address> addresses = hash.locate(key, 2);
log.debug(key + " should be present on = " + addresses);
int count = 0;
for (Cache c : caches()) {
if (c.getAdvancedCache().getDataContainer().containsKey(key, null)) {
log.debug("It is here = " + address(c));
count++;
}
}
log.debug("count = " + count);
assert count == 2;
for (Cache c : caches()) {
if (addresses.contains(address(c))) {
assert c.getAdvancedCache().getDataContainer().containsKey(key, null);
} else {
assert !c.getAdvancedCache().getDataContainer().containsKey(key, null);
}
}
}
@Override
protected EmbeddedCacheManager addClusterEnabledCacheManager(Configuration deConfiguration) {
EmbeddedCacheManager cm = TestCacheManagerFactory.createClusteredCacheManager(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!");
}
}
GlobalConfiguration globalConfiguration = cm.getGlobalConfiguration();
globalConfiguration.setRackId(rack);
globalConfiguration.setMachineId(machine);
cacheManagers.add(cm);
return cm;
}
}