package org.infinispan.client.hotrod;
import static org.infinispan.client.hotrod.test.HotRodClientTestingUtil.killServers;
import static org.infinispan.distribution.DistributionTestHelper.isFirstOwner;
import static org.infinispan.server.hotrod.test.HotRodTestingUtil.hotRodCacheConfiguration;
import static org.infinispan.test.TestingUtil.blockUntilCacheStatusAchieved;
import static org.infinispan.test.TestingUtil.blockUntilViewReceived;
import static org.testng.AssertJUnit.assertEquals;
import java.net.InetSocketAddress;
import java.util.Random;
import java.util.Set;
import org.infinispan.AdvancedCache;
import org.infinispan.Cache;
import org.infinispan.client.hotrod.test.HotRodClientTestingUtil;
import org.infinispan.commons.util.Util;
import org.infinispan.configuration.cache.CacheMode;
import org.infinispan.configuration.cache.ConfigurationBuilder;
import org.infinispan.distribution.ch.ConsistentHash;
import org.infinispan.lifecycle.ComponentStatus;
import org.infinispan.manager.EmbeddedCacheManager;
import org.infinispan.remoting.transport.Address;
import org.infinispan.server.hotrod.HotRodServer;
import org.infinispan.util.ControlledConsistentHashFactory;
import org.testng.annotations.AfterClass;
import org.testng.annotations.Test;
@Test(groups = "functional", testName = "client.hotrod.AsymmetricRoutingTest")
public class AsymmetricRoutingTest extends HitsAwareCacheManagersTest {
private static final String DIST_ONE_CACHE_NAME = "dist-one-cache";
private static final String DIST_TWO_CACHE_NAME = "dist-two-cache";
HotRodServer server1;
HotRodServer server2;
ConfigurationBuilder defaultBuilder;
ConfigurationBuilder distOneBuilder;
ConfigurationBuilder distTwoBuilder;
RemoteCacheManager rcm;
protected ConfigurationBuilder defaultCacheConfigurationBuilder() {
return hotRodCacheConfiguration(getDefaultClusteredCacheConfig(CacheMode.DIST_SYNC));
}
@Override
protected void createCacheManagers() throws Throwable {
defaultBuilder = defaultCacheConfigurationBuilder();
distOneBuilder = hotRodCacheConfiguration(getDefaultClusteredCacheConfig(CacheMode.DIST_SYNC));
distOneBuilder.clustering().hash().numOwners(1).numSegments(1)
.consistentHashFactory(new ControlledConsistentHashFactory(0));
distTwoBuilder = hotRodCacheConfiguration(getDefaultClusteredCacheConfig(CacheMode.DIST_SYNC));
distTwoBuilder.clustering().hash().numOwners(1).numSegments(1)
.consistentHashFactory(new ControlledConsistentHashFactory(1));
server1 = addHotRodServer();
server2 = addHotRodServer();
blockUntilViewReceived(manager(0).getCache(), 2);
blockUntilCacheStatusAchieved(manager(0).getCache(), ComponentStatus.RUNNING, 10000);
blockUntilCacheStatusAchieved(manager(1).getCache(), ComponentStatus.RUNNING, 10000);
org.infinispan.client.hotrod.configuration.ConfigurationBuilder clientBuilder =
new org.infinispan.client.hotrod.configuration.ConfigurationBuilder();
clientBuilder.addServer().host(server1.getHost()).port(server1.getPort())
.addServer().host(server2.getHost()).port(server2.getPort());
rcm = new RemoteCacheManager(clientBuilder.build());
}
@AfterClass
@Override
protected void destroy() {
killServers(server1, server2);
super.destroy();
}
private HotRodServer addHotRodServer() {
EmbeddedCacheManager cm = addClusterEnabledCacheManager(defaultBuilder);
cm.defineConfiguration(DIST_ONE_CACHE_NAME, distOneBuilder.build());
cm.defineConfiguration(DIST_TWO_CACHE_NAME, distTwoBuilder.build());
HotRodServer server = HotRodClientTestingUtil.startHotRodServer(cm);
addr2hrServer.put(new InetSocketAddress(server.getHost(), server.getPort()), server);
return server;
}
public void testRequestRouting() {
addInterceptors(DIST_ONE_CACHE_NAME);
addInterceptors(DIST_TWO_CACHE_NAME);
byte[] keyDistOne = getKeyForServer(server1, DIST_ONE_CACHE_NAME);
byte[] keyDistTwo = getKeyForServer(server2, DIST_TWO_CACHE_NAME);
assertSegments(DIST_ONE_CACHE_NAME, server1, server1.getCacheManager().getAddress());
assertSegments(DIST_ONE_CACHE_NAME, server2, server1.getCacheManager().getAddress());
assertSegments(DIST_TWO_CACHE_NAME, server1, server2.getCacheManager().getAddress());
assertSegments(DIST_TWO_CACHE_NAME, server2, server2.getCacheManager().getAddress());
assertRequestRouting(keyDistOne, DIST_ONE_CACHE_NAME, server1);
assertRequestRouting(keyDistTwo, DIST_TWO_CACHE_NAME, server2);
}
private void assertSegments(String cacheName, HotRodServer server, Address owner) {
AdvancedCache<Object, Object> cache = server.getCacheManager().getCache(cacheName).getAdvancedCache();
ConsistentHash ch = cache.getDistributionManager().getReadConsistentHash();
assertEquals(1, ch.getNumSegments());
Set<Integer> segments = ch.getSegmentsForOwner(owner);
assertEquals(1, segments.size());
assertEquals(0, segments.iterator().next().intValue());
}
private void assertRequestRouting(byte[] key, String cacheName, HotRodServer server) {
RemoteCache<Object, Object> rcOne = rcm.getCache(cacheName);
InetSocketAddress serverAddress = new InetSocketAddress(server.getHost(), server.getPort());
for (int i = 0; i < 2; i++) {
log.infof("Routing put test for key %s", Util.printArray(key, false));
rcOne.put(key, "value");
assertServerHit(serverAddress, cacheName, i + 1);
}
}
byte[] getKeyForServer(HotRodServer primaryOwner, String cacheName) {
Cache<?, ?> cache = primaryOwner.getCacheManager().getCache(cacheName);
Random r = new Random();
byte[] dummy = new byte[8];
int attemptsLeft = 1000;
do {
r.nextBytes(dummy);
} while (!isFirstOwner(cache, dummy) && attemptsLeft >= 0);
if (attemptsLeft < 0)
throw new IllegalStateException("Could not find any key owned by " + primaryOwner);
log.infof("Binary key %s hashes to [cluster=%s,hotrod=%s]",
Util.printArray(dummy, false), primaryOwner.getCacheManager().getAddress(),
primaryOwner.getAddress());
return dummy;
}
}