package org.infinispan.client.hotrod; import static org.infinispan.client.hotrod.test.HotRodClientTestingUtil.killRemoteCacheManager; import static org.infinispan.client.hotrod.test.HotRodClientTestingUtil.killServers; import static org.infinispan.server.hotrod.test.HotRodTestingUtil.assertHotRodEquals; import static org.infinispan.server.hotrod.test.HotRodTestingUtil.hotRodCacheConfiguration; import static org.infinispan.server.hotrod.test.HotRodTestingUtil.marshall; import static org.infinispan.test.TestingUtil.blockUntilCacheStatusAchieved; import static org.infinispan.test.TestingUtil.blockUntilViewReceived; import static org.testng.AssertJUnit.assertEquals; import static org.testng.AssertJUnit.assertNotNull; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.util.ArrayList; import java.util.List; import java.util.Random; import org.infinispan.client.hotrod.impl.protocol.HotRodConstants; import org.infinispan.client.hotrod.impl.transport.tcp.TcpTransport; import org.infinispan.client.hotrod.impl.transport.tcp.TcpTransportFactory; import org.infinispan.client.hotrod.test.HotRodClientTestingUtil; import org.infinispan.client.hotrod.test.InternalRemoteCacheManager; import org.infinispan.configuration.cache.CacheMode; import org.infinispan.configuration.cache.ConfigurationBuilder; import org.infinispan.distribution.DistributionManager; import org.infinispan.distribution.ch.ConsistentHash; import org.infinispan.lifecycle.ComponentStatus; import org.infinispan.manager.CacheContainer; import org.infinispan.remoting.transport.Address; import org.infinispan.server.hotrod.HotRodServer; import org.infinispan.util.logging.Log; import org.infinispan.util.logging.LogFactory; import org.testng.annotations.AfterClass; import org.testng.annotations.AfterMethod; import org.testng.annotations.Test; /** * @author Mircea.Markus@jboss.com * @since 4.1 */ @Test(groups = "functional", testName = "client.hotrod.CSAIntegrationTest") public class CSAIntegrationTest extends HitsAwareCacheManagersTest { private HotRodServer hotRodServer1; private HotRodServer hotRodServer2; private HotRodServer hotRodServer3; private RemoteCacheManager remoteCacheManager; private RemoteCache<Object, Object> remoteCache; private TcpTransportFactory tcpTransportFactory; private static final Log log = LogFactory.getLog(CSAIntegrationTest.class); @AfterMethod @Override protected void clearContent() throws Throwable { } @Override protected void createCacheManagers() throws Throwable { ConfigurationBuilder builder = hotRodCacheConfiguration( getDefaultClusteredCacheConfig(CacheMode.DIST_SYNC, false)); builder.clustering().hash().numOwners(1); builder.unsafe().unreliableReturnValues(true); addClusterEnabledCacheManager(builder); addClusterEnabledCacheManager(builder); addClusterEnabledCacheManager(builder); hotRodServer1 = HotRodClientTestingUtil.startHotRodServer(manager(0)); addr2hrServer.put(new InetSocketAddress(hotRodServer1.getHost(), hotRodServer1.getPort()), hotRodServer1); hotRodServer2 = HotRodClientTestingUtil.startHotRodServer(manager(1)); addr2hrServer.put(new InetSocketAddress(hotRodServer2.getHost(), hotRodServer2.getPort()), hotRodServer2); hotRodServer3 = HotRodClientTestingUtil.startHotRodServer(manager(2)); addr2hrServer.put(new InetSocketAddress(hotRodServer3.getHost(), hotRodServer3.getPort()), hotRodServer3); assert manager(0).getCache() != null; assert manager(1).getCache() != null; assert manager(2).getCache() != null; blockUntilViewReceived(manager(0).getCache(), 3); blockUntilCacheStatusAchieved(manager(0).getCache(), ComponentStatus.RUNNING, 10000); blockUntilCacheStatusAchieved(manager(1).getCache(), ComponentStatus.RUNNING, 10000); blockUntilCacheStatusAchieved(manager(2).getCache(), ComponentStatus.RUNNING, 10000); //Important: this only connects to one of the two servers! org.infinispan.client.hotrod.configuration.ConfigurationBuilder clientBuilder = new org.infinispan.client.hotrod.configuration.ConfigurationBuilder(); clientBuilder .addServers("localhost:" + hotRodServer2.getPort() + ";localhost:" + hotRodServer2.getPort()); remoteCacheManager = new InternalRemoteCacheManager(clientBuilder.build()); remoteCache = remoteCacheManager.getCache(); tcpTransportFactory = (TcpTransportFactory) ((InternalRemoteCacheManager) remoteCacheManager).getTransportFactory(); } protected void setHotRodProtocolVersion(org.infinispan.client.hotrod.configuration.ConfigurationBuilder clientBuilder) { // No-op, use default Hot Rod protocol version } @AfterClass @Override protected void destroy() { killRemoteCacheManager(remoteCacheManager); killServers(hotRodServer1, hotRodServer2, hotRodServer3); super.destroy(); } public void testHashInfoRetrieved() throws InterruptedException { assertEquals(3, tcpTransportFactory.getServers().size()); for (int i = 0; i < 10; i++) { remoteCache.put("k", "v"); if (tcpTransportFactory.getServers().size() == 3) break; Thread.sleep(1000); } assertEquals(3, tcpTransportFactory.getServers().size()); assertNotNull(tcpTransportFactory.getConsistentHash(HotRodConstants.DEFAULT_CACHE_NAME_BYTES)); } @Test(dependsOnMethods = "testHashInfoRetrieved") public void testCorrectSetup() { remoteCache.put("k", "v"); assert remoteCache.get("k").equals("v"); } @Test(dependsOnMethods = "testCorrectSetup") public void testHashFunctionReturnsSameValues() { for (int i = 0; i < 1000; i++) { byte[] key = generateKey(i); TcpTransport transport = (TcpTransport) tcpTransportFactory.getTransport(key, null, HotRodConstants.DEFAULT_CACHE_NAME_BYTES); SocketAddress serverAddress = transport.getServerAddress(); CacheContainer cacheContainer = addr2hrServer.get(serverAddress).getCacheManager(); assertNotNull("For server address " + serverAddress + " found " + cacheContainer + ". Map is: " + addr2hrServer, cacheContainer); DistributionManager distributionManager = cacheContainer.getCache().getAdvancedCache().getDistributionManager(); Address clusterAddress = cacheContainer.getCache().getAdvancedCache().getRpcManager().getAddress(); ConsistentHash serverCh = distributionManager.getReadConsistentHash(); int numSegments = serverCh.getNumSegments(); int keySegment = serverCh.getSegment(key); Address serverOwner = serverCh.locatePrimaryOwnerForSegment(keySegment); Address serverPreviousOwner = serverCh.locatePrimaryOwnerForSegment((keySegment - 1 + numSegments) % numSegments); assert clusterAddress.equals(serverOwner) || clusterAddress.equals(serverPreviousOwner); tcpTransportFactory.releaseTransport(transport); } } @Test(dependsOnMethods = "testHashFunctionReturnsSameValues") public void testRequestsGoToExpectedServer() throws Exception { addInterceptors(); List<byte[]> keys = new ArrayList<byte[]>(); for (int i = 0; i < 500; i++) { byte[] key = generateKey(i); keys.add(key); String keyStr = new String(key); remoteCache.put(keyStr, "value"); TcpTransport transport = (TcpTransport) tcpTransportFactory.getTransport(marshall(keyStr), null, RemoteCacheManager.cacheNameBytes()); assertHotRodEquals(addr2hrServer.get(transport.getServerAddress()).getCacheManager(), keyStr, "value"); tcpTransportFactory.releaseTransport(transport); } log.info("Right before first get."); for (byte[] key : keys) { resetStats(); String keyStr = new String(key); assert remoteCache.get(keyStr).equals("value"); TcpTransport transport = (TcpTransport) tcpTransportFactory.getTransport(marshall(keyStr), null, HotRodConstants.DEFAULT_CACHE_NAME_BYTES); assertOnlyServerHit(transport.getServerAddress()); tcpTransportFactory.releaseTransport(transport); } } private byte[] generateKey(int i) { Random r = new Random(); byte[] result = new byte[i]; r.nextBytes(result); return result; } }