package org.infinispan.server.hotrod;
import static org.infinispan.server.hotrod.Constants.INTELLIGENCE_HASH_DISTRIBUTION_AWARE;
import static org.infinispan.server.hotrod.OperationStatus.Success;
import static org.infinispan.server.hotrod.test.HotRodTestingUtil.assertHashTopologyReceived;
import static org.infinispan.server.hotrod.test.HotRodTestingUtil.assertStatus;
import static org.infinispan.server.hotrod.test.HotRodTestingUtil.assertSuccess;
import static org.infinispan.server.hotrod.test.HotRodTestingUtil.hotRodCacheConfiguration;
import static org.infinispan.server.hotrod.test.HotRodTestingUtil.k;
import static org.infinispan.server.hotrod.test.HotRodTestingUtil.v;
import static org.testng.AssertJUnit.assertNull;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Optional;
import org.infinispan.configuration.cache.CacheMode;
import org.infinispan.configuration.cache.ConfigurationBuilder;
import org.infinispan.manager.EmbeddedCacheManager;
import org.infinispan.server.core.test.ServerTestingUtil;
import org.infinispan.server.hotrod.test.HotRodClient;
import org.infinispan.server.hotrod.test.HotRodMagicKeyGenerator;
import org.infinispan.server.hotrod.test.TestResponse;
import org.infinispan.test.TestingUtil;
import org.testng.annotations.Test;
/**
* Tests Hot Rod distribution mode when some of the cache managers do not have HotRod servers running.
*
* @author Dan Berindei
* @since 5.2
*/
@Test(groups = "functional", testName = "server.hotrod.HotRod11StorageOnlyNodesTest")
public class HotRod11StorageOnlyNodesTest extends HotRodMultiNodeTest {
@Override
protected String cacheName() {
return "distributed";
}
@Override
protected ConfigurationBuilder createCacheConfig() {
ConfigurationBuilder cfg = hotRodCacheConfiguration(getDefaultClusteredCacheConfig(CacheMode.DIST_SYNC, false));
cfg.clustering().l1().disable(); // Disable L1 explicitly
return cfg;
}
@Override
protected byte protocolVersion() { return 11; }
protected int virtualNodes() { return 1; }
public void testAddingStorageOnlyNode(Method m) throws Exception {
HotRodServer server1 = servers().get(0);
HotRodServer server2 = servers().get(1);
HotRodClient client1 = clients().get(0);
HotRodClient client2 = clients().get(1);
int initialTopologyId = currentServerTopologyId();
TestResponse resp = client1.ping(INTELLIGENCE_HASH_DISTRIBUTION_AWARE, 0);
assertStatus(resp, Success);
assertHashTopologyReceived(resp.topologyResponse, servers(), cacheName(), 2, virtualNodes(), initialTopologyId);
EmbeddedCacheManager newCacheManager = addClusterEnabledCacheManager();
Optional<Integer> leaveTopologyId;
try {
newCacheManager.defineConfiguration(cacheName(), createCacheConfig().build());
newCacheManager.getCache(cacheName());
TestingUtil.blockUntilViewsReceived(50000, true, manager(0), manager(1), manager(2));
TestingUtil.waitForNoRebalance(cache(0, cacheName()), cache(1, cacheName()), cache(2, cacheName()));
int joinTopologyId = currentServerTopologyId();
// The clients receive a new topology (because the rebalance increased the topology id by 2)
// but the storage-only node is not included in the new topology.
byte[] key1 = HotRodMagicKeyGenerator.newKey(cache(0, cacheName()));
resp = client1.put(key1, 0, 0, v(m, "v1-"), INTELLIGENCE_HASH_DISTRIBUTION_AWARE, initialTopologyId);
assertStatus(resp, Success);
assertHashTopologyReceived(resp.topologyResponse, servers(), cacheName(), 2, virtualNodes(), joinTopologyId - 1);
// The clients won't receive another topology (the client topology will stay behind the
// server topology id by 1).
log.trace("Check that the clients do not receive a new topology");
resp = client1.put(key1, 0, 0, v(m, "v1-"), INTELLIGENCE_HASH_DISTRIBUTION_AWARE, joinTopologyId - 1);
assertStatus(resp, Success);
assertNull(resp.topologyResponse);
log.trace("Check that the clients can access a key for which the storage-only node is primary owner");
byte[] key2 = HotRodMagicKeyGenerator.newKey(cache(2, cacheName()));
resp = client1.put(key2, 0, 0, v(m, "v2-"), INTELLIGENCE_HASH_DISTRIBUTION_AWARE, joinTopologyId - 1);
assertStatus(resp, Success);
assertNull(resp.topologyResponse);
assertSuccess(client2.get(key1, 0), v(m, "v1-"));
assertSuccess(client2.get(key2, 0), v(m, "v2-"));
log.trace("Force a topology change by shutting down one of the proper HotRod servers");
ServerTestingUtil.killServer(server2);
TestingUtil.killCacheManagers(servers().get(1).getCacheManager());
TestingUtil.blockUntilViewsReceived(50000, false, manager(0), manager(2));
TestingUtil.waitForNoRebalance(cache(0, cacheName()), cache(2, cacheName()));
leaveTopologyId = Optional.of(currentServerTopologyId());
resp = client1.put(key1, 0, 0, v(m, "v3-"), INTELLIGENCE_HASH_DISTRIBUTION_AWARE, joinTopologyId - 1);
assertStatus(resp, Success);
assertHashTopologyReceived(resp.topologyResponse, Arrays.asList(server1), cacheName(), 2, virtualNodes(),
leaveTopologyId.get() - 1);
} finally {
TestingUtil.killCacheManagers(newCacheManager);
TestingUtil.blockUntilViewsReceived(50000, false, manager(0));
TestingUtil.waitForNoRebalance(cache(0, cacheName()));
}
int storageOnlyLeaveTopologyId = currentServerTopologyId();
log.trace("Check that only the topology id changes after the storage-only server is killed");
resp = client1.put(k(m), 0, 0, v(m, "v4-"), INTELLIGENCE_HASH_DISTRIBUTION_AWARE, leaveTopologyId.get() - 1);
assertStatus(resp, Success);
assertHashTopologyReceived(resp.topologyResponse, Arrays.asList(server1), cacheName(), 2, 1, storageOnlyLeaveTopologyId);
assertSuccess(client1.get(k(m), 0), v(m, "v4-"));
}
}