Search in sources :

Example 6 with ScheduledExecutorService

use of java.util.concurrent.ScheduledExecutorService in project pinot by linkedin.

the class NettySingleConnectionIntegrationTest method testServerShutdownLeak.

/*
   * This test attempts to use the connection mechanism the same way as ScatterGatherImpl.SingleRequestHandler does.
   *
   * WARNING: This test has potential failures due to timing.
   */
@Test
public void testServerShutdownLeak() throws Exception {
    final NettyClientMetrics metric = new NettyClientMetrics(null, "abc");
    final Timer timer = new HashedWheelTimer();
    final int minConns = 2;
    final int maxConns = 3;
    // 10M ms.
    final int maxIdleTimeoutMs = 10000000;
    final int maxBacklogPerServer = 1;
    MyServer server = new MyServer();
    Thread.sleep(1000);
    // used as a key to pool. Can be anything.
    final String serverName = "SomeServer";
    final ServerInstance serverInstance = server.getServerInstance();
    final MetricsRegistry metricsRegistry = new MetricsRegistry();
    EventLoopGroup eventLoopGroup = new NioEventLoopGroup();
    PooledNettyClientResourceManager resourceManager = new PooledNettyClientResourceManager(eventLoopGroup, new HashedWheelTimer(), metric);
    ExecutorService executorService = Executors.newCachedThreadPool();
    ScheduledExecutorService timeoutExecutor = new ScheduledThreadPoolExecutor(5);
    AsyncPoolResourceManagerAdapter<ServerInstance, NettyClientConnection> rmAdapter = new AsyncPoolResourceManagerAdapter<ServerInstance, NettyClientConnection>(serverInstance, resourceManager, executorService, metricsRegistry);
    KeyedPool<ServerInstance, NettyClientConnection> keyedPool = new KeyedPoolImpl<ServerInstance, NettyClientConnection>(minConns, maxConns, maxIdleTimeoutMs, maxBacklogPerServer, resourceManager, timeoutExecutor, executorService, metricsRegistry);
    resourceManager.setPool(keyedPool);
    keyedPool.start();
    Field keyedPoolMap = KeyedPoolImpl.class.getDeclaredField("_keyedPool");
    keyedPoolMap.setAccessible(true);
    KeyedFuture<ServerInstance, NettyClientConnection> keyedFuture = keyedPool.checkoutObject(serverInstance);
    // The connection pool for this server is created on demand, so we can now get a reference to the _keyedPool.
    // The act of calling checkoutObject() creates a new AsyncPoolImpl and places a request for a new connection.
    // Since no new connections are available in the beginning, we always end up creating one more than the min.
    Map<ServerInstance, AsyncPool<NettyClientConnection>> poolMap = (Map<ServerInstance, AsyncPool<NettyClientConnection>>) keyedPoolMap.get(keyedPool);
    AsyncPool<NettyClientConnection> asyncPool = poolMap.get(serverInstance);
    Field waiterList = AsyncPoolImpl.class.getDeclaredField("_waiters");
    waiterList.setAccessible(true);
    LinkedDequeue queue = (LinkedDequeue) waiterList.get(asyncPool);
    PoolStats stats;
    // If the number of waiters is = 0, then we will error out because the min connections may not have completed
    // by the time we check one out. If maxWaiters is > 0, then we may end up initiating a fresh connection while the
    // min is still being filled. So, best to sleep a little to make sure that the min pool size is filled out, so that
    // the stats are correct.
    Thread.sleep(2000L);
    stats = asyncPool.getStats();
    Assert.assertEquals(stats.getIdleCount(), minConns);
    Assert.assertEquals(stats.getPoolSize(), minConns + 1);
    NettyClientConnection conn = keyedFuture.getOne();
    LOGGER.debug("Got connection ID " + conn.getConnId());
    Assert.assertEquals(stats.getIdleCount(), minConns);
    Assert.assertEquals(stats.getPoolSize(), minConns + 1);
    // Now get two more connections to the server, since we have 2 idle, we should get those.
    // And leak them.
    keyedFuture = keyedPool.checkoutObject(serverInstance);
    conn = keyedFuture.getOne();
    LOGGER.debug("Got connection ID " + conn.getConnId());
    keyedFuture = keyedPool.checkoutObject(serverInstance);
    conn = keyedFuture.getOne();
    LOGGER.debug("Got connection ID " + conn.getConnId());
    // Now we should have 0 idle, and a pool size of 3 with no waiters.
    stats = asyncPool.getStats();
    Assert.assertEquals(stats.getIdleCount(), 0);
    Assert.assertEquals(stats.getPoolSize(), minConns + 1);
    Assert.assertEquals(queue.size(), 0);
    // Now, we will always get an exception because we don't have a free connection to the server.
    {
        keyedFuture = keyedPool.checkoutObject(serverInstance);
        boolean caughtException = false;
        LOGGER.debug("Will never get a connection here.");
        try {
            conn = keyedFuture.getOne(3, TimeUnit.SECONDS);
        } catch (TimeoutException e) {
            caughtException = true;
        }
        Assert.assertTrue(caughtException);
        keyedFuture.cancel(true);
    }
    // Now if the server goes down, we should release all three connections and be able to get a successful new connection
    LOGGER.info("Shutting down server instance");
    server.shutdown();
    // Give it time to clean up on the client side.
    Thread.sleep(2000L);
    stats = asyncPool.getStats();
    LOGGER.debug(stats.toString());
    // There will be a couple in idleCount in error state.
    Assert.assertEquals(stats.getIdleCount(), minConns);
    Assert.assertEquals(stats.getPoolSize(), minConns);
    LOGGER.debug("Restarting server instance");
    server.restart();
    Thread.sleep(3000);
    LOGGER.debug("Server restart successful\n" + asyncPool.getStats());
    // Now get 3 connections successfully
    for (int i = 0; i < 3; i++) {
        keyedFuture = keyedPool.checkoutObject(serverInstance);
        conn = keyedFuture.getOne();
        Assert.assertNotNull(conn);
    }
    server.shutdown();
}
Also used : ScheduledThreadPoolExecutor(java.util.concurrent.ScheduledThreadPoolExecutor) Field(java.lang.reflect.Field) ServerInstance(com.linkedin.pinot.common.response.ServerInstance) NioEventLoopGroup(io.netty.channel.nio.NioEventLoopGroup) TimeoutException(java.util.concurrent.TimeoutException) MetricsRegistry(com.yammer.metrics.core.MetricsRegistry) ScheduledExecutorService(java.util.concurrent.ScheduledExecutorService) NettyClientMetrics(com.linkedin.pinot.transport.metrics.NettyClientMetrics) AsyncPoolResourceManagerAdapter(com.linkedin.pinot.transport.pool.AsyncPoolResourceManagerAdapter) LinkedDequeue(com.linkedin.pinot.transport.common.LinkedDequeue) HashedWheelTimer(io.netty.util.HashedWheelTimer) KeyedPoolImpl(com.linkedin.pinot.transport.pool.KeyedPoolImpl) PoolStats(com.linkedin.pinot.transport.metrics.PoolStats) EventLoopGroup(io.netty.channel.EventLoopGroup) NioEventLoopGroup(io.netty.channel.nio.NioEventLoopGroup) HashedWheelTimer(io.netty.util.HashedWheelTimer) Timer(io.netty.util.Timer) ScheduledExecutorService(java.util.concurrent.ScheduledExecutorService) ExecutorService(java.util.concurrent.ExecutorService) Map(java.util.Map) AsyncPool(com.linkedin.pinot.transport.pool.AsyncPool) Test(org.testng.annotations.Test)

Example 7 with ScheduledExecutorService

use of java.util.concurrent.ScheduledExecutorService in project pinot by linkedin.

the class KeyedPoolImplTest method testShutdownWhileCheckingOut.

@Test
public void testShutdownWhileCheckingOut() throws Exception {
    ScheduledExecutorService timedExecutor = new ScheduledThreadPoolExecutor(1);
    ExecutorService service = new ThreadPoolExecutor(1, 1, 1, TimeUnit.DAYS, new LinkedBlockingDeque<Runnable>());
    int numKeys = 1;
    int numResourcesPerKey = 1;
    Map<String, List<String>> resources = buildCreateMap(numKeys, numResourcesPerKey);
    BlockingTestResourceManager rm = new BlockingTestResourceManager(resources, null, null, null);
    KeyedPool<String, String> kPool = new KeyedPoolImpl<String, String>(0, 1, 1000L, 1000 * 60 * 60, rm, timedExecutor, service, null);
    kPool.start();
    AsyncResponseFuture<String, String> f = (AsyncResponseFuture<String, String>) kPool.checkoutObject(getKey(0));
    boolean isTimedout = false;
    try {
        f.get(2, TimeUnit.SECONDS);
    } catch (TimeoutException e) {
        isTimedout = true;
    }
    Assert.assertTrue(isTimedout);
    kPool.shutdown().get();
    // Future should have been done with error
    Assert.assertNull(f.get());
    Assert.assertNotNull(f.getError());
    boolean cancelled = f.cancel(false);
    Assert.assertFalse(cancelled);
    Assert.assertFalse(f.isCancelled());
    Assert.assertTrue(f.isDone());
    rm.getCreateBlockLatch().countDown();
    Thread.sleep(5000);
}
Also used : ScheduledExecutorService(java.util.concurrent.ScheduledExecutorService) ScheduledThreadPoolExecutor(java.util.concurrent.ScheduledThreadPoolExecutor) AsyncResponseFuture(com.linkedin.pinot.transport.common.AsyncResponseFuture) ScheduledExecutorService(java.util.concurrent.ScheduledExecutorService) ExecutorService(java.util.concurrent.ExecutorService) ArrayList(java.util.ArrayList) List(java.util.List) ThreadPoolExecutor(java.util.concurrent.ThreadPoolExecutor) ScheduledThreadPoolExecutor(java.util.concurrent.ScheduledThreadPoolExecutor) TimeoutException(java.util.concurrent.TimeoutException) Test(org.testng.annotations.Test)

Example 8 with ScheduledExecutorService

use of java.util.concurrent.ScheduledExecutorService in project pinot by linkedin.

the class KeyedPoolImplTest method testPoolImpl1.

@Test
public /**
   * Pool contains 5 inner pools with 5 resources as max capacity
   * Checkout all of them. Verify checked out is expected. Verify aggregated stats
   * Checkin all of them. At each step check stats
   * Checkout one from each inner pool and destroy them. Check stats
   * Shutdown. Ensure clean shutdown.
   * @throws Exception
   */
void testPoolImpl1() throws Exception {
    ScheduledExecutorService timedExecutor = new ScheduledThreadPoolExecutor(1);
    ExecutorService service = MoreExecutors.sameThreadExecutor();
    int numKeys = 5;
    int numResourcesPerKey = 5;
    TestResourceManager rm = new TestResourceManager(buildCreateMap(numKeys, numResourcesPerKey), null, null, null);
    KeyedPool<String, String> kPool = new KeyedPoolImpl<String, String>(5, 5, 1000 * 60 * 60L, 100, rm, timedExecutor, service, null);
    kPool.start();
    AggregatedPoolStats s = (AggregatedPoolStats) kPool.getStats();
    int c = 1;
    for (int j = 0; j < numResourcesPerKey; j++) {
        for (int i = 0; i < numKeys; i++) {
            KeyedFuture<String, String> rFuture = kPool.checkoutObject(getKey(i));
            String resource = rFuture.getOne();
            Assert.assertEquals(resource, getResource(i, j));
            s.refresh();
            Assert.assertEquals(s.getCheckedOut(), c++);
        }
    }
    s = (AggregatedPoolStats) kPool.getStats();
    Assert.assertEquals(s.getTotalCreated(), numKeys * numResourcesPerKey);
    int checkedOut = c - 1;
    // checkin back all
    for (int j = 0; j < numResourcesPerKey; j++) {
        for (int i = 0; i < numKeys; i++) {
            kPool.checkinObject(getKey(i), getResource(i, j));
            s.refresh();
            Assert.assertEquals(s.getCheckedOut(), --checkedOut);
        }
    }
    s = (AggregatedPoolStats) kPool.getStats();
    // checkout one from each and destroy them
    c = 1;
    int d = 1;
    for (int i = 0; i < numKeys; i++) {
        KeyedFuture<String, String> rFuture = kPool.checkoutObject(getKey(i));
        String resource = rFuture.getOne();
        Assert.assertEquals(resource, getResource(i, 0));
        CountDownLatch latch = new CountDownLatch(1);
        rm.setCountDownLatch(latch);
        kPool.destroyObject(getKey(i), resource);
        latch.await();
        Thread.sleep(1000);
        s.refresh();
        Assert.assertEquals(s.getCheckedOut(), 0);
        Assert.assertEquals(s.getTotalDestroyed(), d++);
    }
    Future<Map<String, NoneType>> f = kPool.shutdown();
    f.get();
    //Verify all objects are destroyed
    Map<String, List<String>> destroyedMap = rm.getDestroyedMap();
    Assert.assertEquals(destroyedMap.keySet().size(), numKeys);
    for (int i = 0; i < numKeys; i++) {
        List<String> r = destroyedMap.get(getKey(i));
        Assert.assertEquals(r.size(), numResourcesPerKey, "Resource for Key (" + getKey(i) + ")");
        for (int j = 0; j < numResourcesPerKey; j++) {
            Assert.assertTrue(r.contains(getResource(i, j)));
        }
    }
}
Also used : ScheduledExecutorService(java.util.concurrent.ScheduledExecutorService) ScheduledThreadPoolExecutor(java.util.concurrent.ScheduledThreadPoolExecutor) CountDownLatch(java.util.concurrent.CountDownLatch) AggregatedPoolStats(com.linkedin.pinot.transport.metrics.AggregatedPoolStats) ScheduledExecutorService(java.util.concurrent.ScheduledExecutorService) ExecutorService(java.util.concurrent.ExecutorService) ArrayList(java.util.ArrayList) List(java.util.List) HashMap(java.util.HashMap) Map(java.util.Map) Test(org.testng.annotations.Test)

Example 9 with ScheduledExecutorService

use of java.util.concurrent.ScheduledExecutorService in project pinot by linkedin.

the class KeyedPoolImplTest method testInvalidCheckinDestroy.

@Test
public void testInvalidCheckinDestroy() throws Exception {
    ScheduledExecutorService timedExecutor = new ScheduledThreadPoolExecutor(1);
    ExecutorService service = new ThreadPoolExecutor(1, 1, 1, TimeUnit.DAYS, new LinkedBlockingDeque<Runnable>());
    int numKeys = 1;
    int numResourcesPerKey = 1;
    Map<String, List<String>> resources = buildCreateMap(numKeys, numResourcesPerKey);
    TestResourceManager rm = new TestResourceManager(resources, null, null, null);
    KeyedPool<String, String> kPool = new KeyedPoolImpl<String, String>(0, 1, 1000L, 1000 * 60 * 60, rm, timedExecutor, service, null);
    kPool.start();
    AsyncResponseFuture<String, String> f = (AsyncResponseFuture<String, String>) kPool.checkoutObject(getKey(0));
    String s1 = f.getOne();
    // checkin with invalid key
    boolean isException = false;
    try {
        kPool.checkinObject(getKey(1), s1);
    } catch (IllegalStateException e) {
        isException = true;
    }
    Assert.assertTrue(isException);
    // destroy with invalid key
    isException = false;
    try {
        kPool.destroyObject(getKey(1), s1);
    } catch (IllegalStateException e) {
        isException = true;
    }
    Assert.assertTrue(isException);
}
Also used : ScheduledExecutorService(java.util.concurrent.ScheduledExecutorService) ScheduledThreadPoolExecutor(java.util.concurrent.ScheduledThreadPoolExecutor) AsyncResponseFuture(com.linkedin.pinot.transport.common.AsyncResponseFuture) ScheduledExecutorService(java.util.concurrent.ScheduledExecutorService) ExecutorService(java.util.concurrent.ExecutorService) ArrayList(java.util.ArrayList) List(java.util.List) ThreadPoolExecutor(java.util.concurrent.ThreadPoolExecutor) ScheduledThreadPoolExecutor(java.util.concurrent.ScheduledThreadPoolExecutor) Test(org.testng.annotations.Test)

Example 10 with ScheduledExecutorService

use of java.util.concurrent.ScheduledExecutorService in project pinot by linkedin.

the class KeyedPoolImplTest method testCancelAfterCheckingOut.

@Test
public void testCancelAfterCheckingOut() throws Exception {
    ScheduledExecutorService timedExecutor = new ScheduledThreadPoolExecutor(1);
    ExecutorService service = new ThreadPoolExecutor(1, 1, 1, TimeUnit.DAYS, new LinkedBlockingDeque<Runnable>());
    int numKeys = 1;
    int numResourcesPerKey = 1;
    Map<String, List<String>> resources = buildCreateMap(numKeys, numResourcesPerKey);
    BlockingTestResourceManager rm = new BlockingTestResourceManager(resources, null, null, null);
    KeyedPool<String, String> kPool = new KeyedPoolImpl<String, String>(0, 1, 1000L, 1000 * 60 * 60, rm, timedExecutor, service, null);
    kPool.start();
    AsyncResponseFuture<String, String> f = (AsyncResponseFuture<String, String>) kPool.checkoutObject(getKey(0));
    boolean isTimedout = false;
    try {
        f.get(2, TimeUnit.SECONDS);
    } catch (TimeoutException e) {
        isTimedout = true;
    }
    Assert.assertTrue(isTimedout);
    boolean cancelled = f.cancel(false);
    Assert.assertTrue(cancelled);
    Assert.assertTrue(f.isCancelled());
    Assert.assertTrue(f.isDone());
    rm.getCreateBlockLatch().countDown();
    kPool.shutdown().get();
}
Also used : ScheduledExecutorService(java.util.concurrent.ScheduledExecutorService) ScheduledThreadPoolExecutor(java.util.concurrent.ScheduledThreadPoolExecutor) AsyncResponseFuture(com.linkedin.pinot.transport.common.AsyncResponseFuture) ScheduledExecutorService(java.util.concurrent.ScheduledExecutorService) ExecutorService(java.util.concurrent.ExecutorService) ArrayList(java.util.ArrayList) List(java.util.List) ThreadPoolExecutor(java.util.concurrent.ThreadPoolExecutor) ScheduledThreadPoolExecutor(java.util.concurrent.ScheduledThreadPoolExecutor) TimeoutException(java.util.concurrent.TimeoutException) Test(org.testng.annotations.Test)

Aggregations

ScheduledExecutorService (java.util.concurrent.ScheduledExecutorService)821 Test (org.junit.Test)267 CountDownLatch (java.util.concurrent.CountDownLatch)79 ArrayList (java.util.ArrayList)72 Test (org.testng.annotations.Test)72 IOException (java.io.IOException)71 ExecutorService (java.util.concurrent.ExecutorService)70 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)65 HashMap (java.util.HashMap)57 ScheduledThreadPoolExecutor (java.util.concurrent.ScheduledThreadPoolExecutor)53 List (java.util.List)51 Map (java.util.Map)51 TimeUnit (java.util.concurrent.TimeUnit)44 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)43 ThreadFactory (java.util.concurrent.ThreadFactory)40 CompletableFuture (java.util.concurrent.CompletableFuture)35 UUID (java.util.UUID)34 Cleanup (lombok.Cleanup)31 ExecutionException (java.util.concurrent.ExecutionException)30 HashSet (java.util.HashSet)25