/* * JBoss, Home of Professional Open Source * Copyright 2011 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.client.hotrod; import org.infinispan.affinity.KeyAffinityService; import org.infinispan.affinity.KeyAffinityServiceFactory; import org.infinispan.client.hotrod.impl.RemoteCacheImpl; import org.infinispan.client.hotrod.retry.DistributionRetryTest; import org.infinispan.config.Configuration; import org.infinispan.interceptors.InterceptorChain; import org.infinispan.remoting.transport.Address; import org.infinispan.server.hotrod.HotRodServer; import org.infinispan.test.MultipleCacheManagersTest; import org.infinispan.util.Util; import org.testng.annotations.AfterMethod; import org.testng.annotations.AfterTest; import org.testng.annotations.Test; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * @author Mircea Markus */ @Test (groups = "functional", testName = "client.hotrod.ConsistentHashV1IntegrationTest") public class ConsistentHashV1IntegrationTest extends MultipleCacheManagersTest { private HotRodServer hotRodServer1; private HotRodServer hotRodServer2; private HotRodServer hotRodServer3; private HotRodServer hotRodServer4; //tod add shutdown behaviour private RemoteCacheManager remoteCacheManager; private RemoteCacheImpl remoteCache; private KeyAffinityService kas; private ExecutorService ex; @Override protected void createCacheManagers() throws Throwable { Configuration conf = getDefaultClusteredConfig(Configuration.CacheMode.DIST_SYNC, false); conf.fluent().jmxStatistics(); assert conf.isExposeJmxStatistics(); conf.fluent().hash().numOwners(2); conf.fluent().hash().rehashEnabled(false); addClusterEnabledCacheManager(conf); addClusterEnabledCacheManager(conf); addClusterEnabledCacheManager(conf); addClusterEnabledCacheManager(conf); hotRodServer1 = TestHelper.startHotRodServer(manager(0)); hotRodServer2 = TestHelper.startHotRodServer(manager(1)); hotRodServer3 = TestHelper.startHotRodServer(manager(2)); hotRodServer4 = TestHelper.startHotRodServer(manager(3)); waitForClusterToForm(); Properties clientConfig = new Properties(); clientConfig.put("infinispan.client.hotrod.server_list", "localhost:" + hotRodServer2.getPort()); remoteCacheManager = new RemoteCacheManager(clientConfig); remoteCache = (RemoteCacheImpl) remoteCacheManager.getCache(); assert super.cacheManagers.size() == 4; ex = Executors.newSingleThreadExecutor(); kas = KeyAffinityServiceFactory.newKeyAffinityService(cache(0), ex, new DistributionRetryTest.ByteKeyGenerator(), 2, true); for (int i = 0; i < 4; i++) { advancedCache(i).addInterceptor(new HitsAwareCacheManagersTest.HitCountInterceptor(), 1); } } @AfterMethod @Override protected void clearContent() throws Throwable { } @AfterTest public void cleanUp() { ex.shutdownNow(); kas.stop(); stopServer(hotRodServer1); stopServer(hotRodServer2); stopServer(hotRodServer3); stopServer(hotRodServer4); remoteCache.stop(); remoteCacheManager.stop(); } private void stopServer(HotRodServer hrs) { try { hrs.stop(); } catch (Exception e) { //ignore } } public void testCorrectBalancingOfKeys() { runTest(0); runTest(1); runTest(2); runTest(3); } private void runTest(int cacheIndex) { List<Address> backups = advancedCache(cacheIndex).getDistributionManager().getConsistentHash().locate(address(cacheIndex), 2); assert backups.contains(address(cacheIndex)); Map<Address, Integer> hitNodes = new HashMap<Address, Integer>(); hitNodes.put(backups.get(0), 0); hitNodes.put(backups.get(1), 0); for (int i = 0; i < 1000; i++) { String key = getKey(cacheIndex); remoteCache.put(key, "v"); Address hitServer = getHitServer(); assert backups.contains(hitServer) : String.format("i=%s, backups: %s, hit server: %s, key=%s", i, backups, hitServer, Util.printArray(key.getBytes(), false)); hitNodes.put(hitServer, hitNodes.get(hitServer) + 1); } System.out.println("hitNodes = " + hitNodes); assert backups.containsAll(hitNodes.keySet()) : String.format("Backups %s. hit nodes %s", backups, hitNodes); } private String getKey(int cacheIndex) { byte[] keyBytes = (byte[]) kas.getKeyForAddress(address(cacheIndex)); return DistributionRetryTest.ByteKeyGenerator.getStringObject(keyBytes); } private Address getHitServer() { List<Address> result = new ArrayList<Address>(); for (int i = 0; i < 4; i++) { InterceptorChain ic = advancedCache(i).getComponentRegistry().getComponent(InterceptorChain.class); HitsAwareCacheManagersTest.HitCountInterceptor interceptor = (HitsAwareCacheManagersTest.HitCountInterceptor) ic.getInterceptorsWithClassName(HitsAwareCacheManagersTest.HitCountInterceptor.class.getName()).get(0); if (interceptor.getHits() == 1) { result.add(address(i)); } interceptor.reset(); } if (result.size() > 1) throw new IllegalStateException("More than one hit! : " + result); return result.get(0); } }