Search in sources :

Example 1 with IORequestProcessor

use of io.questdb.network.IORequestProcessor in project questdb by bluestreak01.

the class IODispatcherTest method testQueuedConnectionTimeout.

@Test
public void testQueuedConnectionTimeout() throws Exception {
    LOG.info().$("started testQueuedConnectionTimeout").$();
    assertMemoryLeak(() -> {
        final int listenBackLog = 10;
        final int activeConnectionLimit = 5;
        final long queuedConnectionTimeoutInMs = 250;
        final IODispatcherConfiguration configuration = new DefaultIODispatcherConfiguration() {

            @Override
            public int getActiveConnectionLimit() {
                return activeConnectionLimit;
            }

            @Override
            public int getListenBacklog() {
                return listenBackLog;
            }

            @Override
            public long getQueuedConnectionTimeout() {
                return queuedConnectionTimeoutInMs;
            }
        };
        final AtomicInteger nConnected = new AtomicInteger();
        final LongHashSet serverConnectedFds = new LongHashSet();
        final LongHashSet clientActiveFds = new LongHashSet();
        IOContextFactory<IOContext> contextFactory = (fd, dispatcher) -> {
            LOG.info().$(fd).$(" connected").$();
            serverConnectedFds.add(fd);
            nConnected.incrementAndGet();
            return new IOContext() {

                @Override
                public boolean invalid() {
                    return !serverConnectedFds.contains(fd);
                }

                @Override
                public long getFd() {
                    return fd;
                }

                @Override
                public IODispatcher<?> getDispatcher() {
                    return dispatcher;
                }

                @Override
                public void close() {
                    LOG.info().$(fd).$(" disconnected").$();
                    serverConnectedFds.remove(fd);
                }
            };
        };
        final String request = "\n";
        long mem = TestUtils.toMemory(request);
        final long sockAddr = Net.sockaddr("127.0.0.1", 9001);
        Thread serverThread;
        final CountDownLatch serverLatch = new CountDownLatch(1);
        try (IODispatcher<IOContext> dispatcher = IODispatchers.create(configuration, contextFactory)) {
            serverThread = new Thread("test-io-dispatcher") {

                @Override
                public void run() {
                    long smem = Unsafe.malloc(1, MemoryTag.NATIVE_DEFAULT);
                    try {
                        IORequestProcessor<IOContext> requestProcessor = (operation, context) -> {
                            long fd = context.getFd();
                            int rc;
                            switch(operation) {
                                case IOOperation.READ:
                                    rc = Net.recv(fd, smem, 1);
                                    if (rc == 1) {
                                        dispatcher.registerChannel(context, IOOperation.WRITE);
                                    } else {
                                        dispatcher.disconnect(context, IODispatcher.DISCONNECT_REASON_TEST);
                                    }
                                    break;
                                case IOOperation.WRITE:
                                    rc = Net.send(fd, smem, 1);
                                    if (rc == 1) {
                                        dispatcher.registerChannel(context, IOOperation.READ);
                                    } else {
                                        dispatcher.disconnect(context, IODispatcher.DISCONNECT_REASON_TEST);
                                    }
                                    break;
                                default:
                                    dispatcher.disconnect(context, IODispatcher.DISCONNECT_REASON_TEST);
                            }
                        };
                        do {
                            dispatcher.run(0);
                            dispatcher.processIOQueue(requestProcessor);
                            Thread.yield();
                        } while (!isInterrupted());
                    } finally {
                        Unsafe.free(smem, 1, MemoryTag.NATIVE_DEFAULT);
                        serverLatch.countDown();
                    }
                }
            };
            serverThread.setDaemon(true);
            serverThread.start();
            // Connect exactly the right amount of clients to fill the active connection and connection backlog, after the
            // queuedConnectionTimeoutInMs the connections in the backlog should get refused
            int nClientConnects = 0;
            int nClientConnectRefused = 0;
            for (int i = 0; i < listenBackLog + activeConnectionLimit; i++) {
                long fd = Net.socketTcp(true);
                Assert.assertTrue(fd > -1);
                clientActiveFds.add(fd);
                if (Net.connect(fd, sockAddr) != 0) {
                    nClientConnectRefused++;
                    continue;
                }
                int rc = Net.send(fd, mem, request.length());
                if (rc < 0) {
                    nClientConnectRefused++;
                    continue;
                }
                rc = Net.recv(fd, mem, request.length());
                if (rc < 0) {
                    nClientConnectRefused++;
                } else {
                    nClientConnects++;
                }
            }
            Assert.assertEquals(activeConnectionLimit, nClientConnects);
            Assert.assertEquals(listenBackLog, nClientConnectRefused);
            Assert.assertFalse(dispatcher.isListening());
            // Close all connections and wait for server to resume listening
            while (clientActiveFds.size() > 0) {
                long fd = clientActiveFds.get(0);
                clientActiveFds.remove(fd);
                Net.close(fd);
            }
            long timeoutMs = System.currentTimeMillis() + TimeUnit.MINUTES.toMillis(1);
            while (!dispatcher.isListening()) {
                if (System.currentTimeMillis() > timeoutMs) {
                    Assert.fail("Timeout waiting for server to start listening again");
                }
            }
            // Try connections again to make sure server is listening
            nClientConnects = 0;
            nClientConnectRefused = 0;
            for (int i = 0; i < listenBackLog + activeConnectionLimit; i++) {
                long fd = Net.socketTcp(true);
                Assert.assertTrue(fd > -1);
                clientActiveFds.add(fd);
                if (Net.connect(fd, sockAddr) != 0) {
                    nClientConnectRefused++;
                    continue;
                }
                int rc = Net.send(fd, mem, request.length());
                if (rc < 0) {
                    nClientConnectRefused++;
                    continue;
                }
                rc = Net.recv(fd, mem, request.length());
                if (rc < 0) {
                    nClientConnectRefused++;
                } else {
                    nClientConnects++;
                }
            }
            Assert.assertEquals(activeConnectionLimit, nClientConnects);
            Assert.assertEquals(listenBackLog, nClientConnectRefused);
            Assert.assertFalse(dispatcher.isListening());
            // Close all remaining client connections
            for (int n = 0; n < clientActiveFds.size(); n++) {
                long fd = clientActiveFds.get(n);
                Net.close(fd);
            }
            serverThread.interrupt();
            if (!serverLatch.await(1, TimeUnit.MINUTES)) {
                Assert.fail("Timeout waiting for server to end");
            }
        } finally {
            Net.freeSockAddr(sockAddr);
            Unsafe.free(mem, request.length(), MemoryTag.NATIVE_DEFAULT);
        }
    });
}
Also used : IOOperation(io.questdb.network.IOOperation) DefaultIODispatcherConfiguration(io.questdb.network.DefaultIODispatcherConfiguration) Log(io.questdb.log.Log) WorkerPoolConfiguration(io.questdb.mp.WorkerPoolConfiguration) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) TestUtils.assertMemoryLeak(io.questdb.test.tools.TestUtils.assertMemoryLeak) WorkerPool(io.questdb.mp.WorkerPool) Timestamps(io.questdb.std.datetime.microtime.Timestamps) TestLatchedCounterFunctionFactory(io.questdb.griffin.engine.functions.test.TestLatchedCounterFunctionFactory) QueryCache(io.questdb.cutlass.http.processors.QueryCache) io.questdb.std(io.questdb.std) IODispatchers(io.questdb.network.IODispatchers) CyclicBarrier(java.util.concurrent.CyclicBarrier) SOCountDownLatch(io.questdb.mp.SOCountDownLatch) LockSupport(java.util.concurrent.locks.LockSupport) StaticContentProcessor(io.questdb.cutlass.http.processors.StaticContentProcessor) CountDownLatch(java.util.concurrent.CountDownLatch) Path(io.questdb.std.str.Path) io.questdb.cairo(io.questdb.cairo) AllowAllCairoSecurityContext(io.questdb.cairo.security.AllowAllCairoSecurityContext) IORequestProcessor(io.questdb.network.IORequestProcessor) NotNull(org.jetbrains.annotations.NotNull) JsonQueryProcessor(io.questdb.cutlass.http.processors.JsonQueryProcessor) TextImportProcessor(io.questdb.cutlass.http.processors.TextImportProcessor) IODispatcher(io.questdb.network.IODispatcher) AbstractCharSequence(io.questdb.std.str.AbstractCharSequence) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) MPSequence(io.questdb.mp.MPSequence) IOContextFactory(io.questdb.network.IOContextFactory) NetUtils(io.questdb.cutlass.NetUtils) SqlException(io.questdb.griffin.SqlException) SCSequence(io.questdb.mp.SCSequence) IOContext(io.questdb.network.IOContext) TestUtils(io.questdb.test.tools.TestUtils) SqlCompiler(io.questdb.griffin.SqlCompiler) LogFactory(io.questdb.log.LogFactory) Metrics(io.questdb.Metrics) HealthCheckProcessor(io.questdb.cutlass.http.processors.HealthCheckProcessor) NetworkFacadeImpl(io.questdb.network.NetworkFacadeImpl) SqlExecutionContextImpl(io.questdb.griffin.SqlExecutionContextImpl) NetworkFacade(io.questdb.network.NetworkFacade) RingQueue(io.questdb.mp.RingQueue) PeerDisconnectedException(io.questdb.network.PeerDisconnectedException) TimeUnit(java.util.concurrent.TimeUnit) SharedRandom(io.questdb.griffin.engine.functions.rnd.SharedRandom) AtomicLong(java.util.concurrent.atomic.AtomicLong) PeerIsSlowToReadException(io.questdb.network.PeerIsSlowToReadException) StringSink(io.questdb.std.str.StringSink) Net(io.questdb.network.Net) MillisecondClock(io.questdb.std.datetime.millitime.MillisecondClock) IODispatcherConfiguration(io.questdb.network.IODispatcherConfiguration) org.junit(org.junit) SqlExecutionContext(io.questdb.griffin.SqlExecutionContext) TemporaryFolder(org.junit.rules.TemporaryFolder) ByteSequence(io.questdb.std.str.ByteSequence) InputStream(java.io.InputStream) DefaultIODispatcherConfiguration(io.questdb.network.DefaultIODispatcherConfiguration) IODispatcherConfiguration(io.questdb.network.IODispatcherConfiguration) IODispatcher(io.questdb.network.IODispatcher) IORequestProcessor(io.questdb.network.IORequestProcessor) SOCountDownLatch(io.questdb.mp.SOCountDownLatch) CountDownLatch(java.util.concurrent.CountDownLatch) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) DefaultIODispatcherConfiguration(io.questdb.network.DefaultIODispatcherConfiguration) IOContext(io.questdb.network.IOContext)

Aggregations

Metrics (io.questdb.Metrics)1 io.questdb.cairo (io.questdb.cairo)1 AllowAllCairoSecurityContext (io.questdb.cairo.security.AllowAllCairoSecurityContext)1 NetUtils (io.questdb.cutlass.NetUtils)1 HealthCheckProcessor (io.questdb.cutlass.http.processors.HealthCheckProcessor)1 JsonQueryProcessor (io.questdb.cutlass.http.processors.JsonQueryProcessor)1 QueryCache (io.questdb.cutlass.http.processors.QueryCache)1 StaticContentProcessor (io.questdb.cutlass.http.processors.StaticContentProcessor)1 TextImportProcessor (io.questdb.cutlass.http.processors.TextImportProcessor)1 SqlCompiler (io.questdb.griffin.SqlCompiler)1 SqlException (io.questdb.griffin.SqlException)1 SqlExecutionContext (io.questdb.griffin.SqlExecutionContext)1 SqlExecutionContextImpl (io.questdb.griffin.SqlExecutionContextImpl)1 SharedRandom (io.questdb.griffin.engine.functions.rnd.SharedRandom)1 TestLatchedCounterFunctionFactory (io.questdb.griffin.engine.functions.test.TestLatchedCounterFunctionFactory)1 Log (io.questdb.log.Log)1 LogFactory (io.questdb.log.LogFactory)1 MPSequence (io.questdb.mp.MPSequence)1 RingQueue (io.questdb.mp.RingQueue)1 SCSequence (io.questdb.mp.SCSequence)1