package org.infinispan.client.hotrod.stress.near; import static org.infinispan.client.hotrod.test.HotRodClientTestingUtil.killRemoteCacheManagers; import static org.infinispan.client.hotrod.test.HotRodClientTestingUtil.withRemoteCacheManager; import static org.infinispan.server.hotrod.test.HotRodTestingUtil.hotRodCacheConfiguration; import static org.testng.AssertJUnit.assertNotNull; import static org.testng.AssertJUnit.assertNull; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.Callable; import java.util.concurrent.CyclicBarrier; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.ThreadLocalRandom; import org.infinispan.client.hotrod.RemoteCache; import org.infinispan.client.hotrod.RemoteCacheManager; import org.infinispan.client.hotrod.configuration.ConfigurationBuilder; import org.infinispan.client.hotrod.configuration.NearCacheMode; import org.infinispan.client.hotrod.test.InternalRemoteCacheManager; import org.infinispan.client.hotrod.test.RemoteCacheManagerCallable; import org.infinispan.manager.EmbeddedCacheManager; import org.infinispan.test.TestingUtil; import org.infinispan.test.fwk.TestCacheManagerFactory; import org.testng.annotations.AfterClass; import org.testng.annotations.Test; /** * Manual test, requires external Hot Rod server. */ @Test(groups = "manual", testName = "client.hotrod.stress.near.EagerNearCacheStressTest") public class EagerNearCacheStressTest { static int NUM_CLIENTS = 3; static int NUM_THREADS_PER_CLIENT = 10; static ExecutorService EXEC = Executors.newCachedThreadPool(); static final int NUM_OPERATIONS = 10_000_000; static final int NUM_KEYS_PRELOAD = 1_000; static final int KEY_RANGE = 1_000; @AfterClass public static void shutdownExecutor() { EXEC.shutdown(); } EmbeddedCacheManager createCacheManager() { return TestCacheManagerFactory.createCacheManager(hotRodCacheConfiguration()); } RemoteCacheManager getRemoteCacheManager(int port) { return getRemoteCacheManager(port, NearCacheMode.DISABLED, -1); } RemoteCacheManager getRemoteCacheManager(int port, NearCacheMode nearCacheMode, int maxEntries) { ConfigurationBuilder builder = new ConfigurationBuilder(); builder.nearCache().mode(nearCacheMode).maxEntries(maxEntries); builder.addServer().host("127.0.0.1").port(port); return new InternalRemoteCacheManager(builder.build()); } public void testLocalPreloadAndGetPut10to1() { runPreloadAndOps(NearCacheMode.INVALIDATED, -1, 0.90); } void runPreloadAndOps(NearCacheMode nearCacheMode, int maxEntries, double getRatio) { EmbeddedCacheManager cm = createCacheManager(); //HotRodServer server = createHotRodServer(cm); int port = 11222; preloadData(port); RemoteCacheManager[] remotecms = new RemoteCacheManager[NUM_CLIENTS]; for (int i = 0; i < NUM_CLIENTS; i++) remotecms[i] = getRemoteCacheManager(port, nearCacheMode, maxEntries); try { ops(remotecms, getRatio); } finally { killRemoteCacheManagers(remotecms); //killServers(server); TestingUtil.killCacheManagers(cm); } } void ops(RemoteCacheManager[] remotecms, double getRatio) { CyclicBarrier barrier = new CyclicBarrier((NUM_CLIENTS * NUM_THREADS_PER_CLIENT) + 1); List<Future<Void>> futures = new ArrayList<>(NUM_CLIENTS * NUM_THREADS_PER_CLIENT); for (RemoteCacheManager remotecm : remotecms) { RemoteCache<Integer, String> remote = remotecm.getCache(); for (int i = 0; i < NUM_THREADS_PER_CLIENT; i++) { Callable<Void> call = new Main(barrier, remote, getRatio); futures.add(EXEC.submit(call)); } } barrierAwait(barrier); // wait for all threads to be ready barrierAwait(barrier); // wait for all threads to finish for (Future<Void> f : futures) futureGet(f); } void preloadData(int port) { // Preload data withRemoteCacheManager(new RemoteCacheManagerCallable(getRemoteCacheManager(port)) { @Override public void call() { RemoteCache<Integer, String> remote = rcm.getCache(); Map<Integer, String> map = new HashMap<>(); for (int i = 0; i < NUM_KEYS_PRELOAD; ++i) map.put(i, TestingUtil.generateRandomString(512)); remote.putAll(map); } }); } static abstract class Runner implements Callable<Void> { final CyclicBarrier barrier; final RemoteCache<Integer, String> remote; final double getRatio; Runner(CyclicBarrier barrier, RemoteCache<Integer, String> remote, double getRatio) { this.barrier = barrier; this.remote = remote; this.getRatio = getRatio; } @Override public Void call() throws Exception { barrierAwait(barrier); try { run(); return null; } finally { barrierAwait(barrier); } } abstract void run(); } final static class Main extends Runner { static final ThreadLocalRandom R = ThreadLocalRandom.current(); Main(CyclicBarrier barrier, RemoteCache<Integer, String> remote, double getRatio) { super(barrier, remote, getRatio); } @Override void run() { double maxGetKey = KEY_RANGE * getRatio; for (int i = 0; i < NUM_OPERATIONS; i++) { int key = R.nextInt(KEY_RANGE); if (key < maxGetKey) { String value = remote.get(key); assertNotNull(value); } else { String prev = remote.put(key, TestingUtil.generateRandomString(512)); assertNull(prev); } } } } static int barrierAwait(CyclicBarrier barrier) { try { return barrier.await(); } catch (InterruptedException | BrokenBarrierException e) { throw new AssertionError(e); } } <T> T futureGet(Future<T> future) { try { return future.get(); } catch (InterruptedException | ExecutionException e) { throw new AssertionError(e); } } }