Search in sources :

Example 1 with Exchanger

use of java.util.concurrent.Exchanger in project jetty.project by eclipse.

the class FlowControlStrategyTest method testServerFlowControlOneBigWrite.

@Test
public void testServerFlowControlOneBigWrite() throws Exception {
    final int windowSize = 1536;
    final int length = 5 * windowSize;
    final CountDownLatch settingsLatch = new CountDownLatch(1);
    start(new ServerSessionListener.Adapter() {

        @Override
        public void onSettings(Session session, SettingsFrame frame) {
            settingsLatch.countDown();
        }

        @Override
        public Stream.Listener onNewStream(Stream stream, HeadersFrame requestFrame) {
            MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, new HttpFields());
            HeadersFrame responseFrame = new HeadersFrame(stream.getId(), metaData, null, false);
            CompletableFuture<Void> completable = new CompletableFuture<>();
            stream.headers(responseFrame, Callback.from(completable));
            completable.thenRun(() -> {
                DataFrame dataFrame = new DataFrame(stream.getId(), ByteBuffer.allocate(length), true);
                stream.data(dataFrame, Callback.NOOP);
            });
            return null;
        }
    });
    Session session = newClient(new Session.Listener.Adapter());
    Map<Integer, Integer> settings = new HashMap<>();
    settings.put(SettingsFrame.INITIAL_WINDOW_SIZE, windowSize);
    session.settings(new SettingsFrame(settings, false), Callback.NOOP);
    Assert.assertTrue(settingsLatch.await(5, TimeUnit.SECONDS));
    final CountDownLatch dataLatch = new CountDownLatch(1);
    final Exchanger<Callback> exchanger = new Exchanger<>();
    MetaData.Request metaData = newRequest("GET", new HttpFields());
    HeadersFrame requestFrame = new HeadersFrame(metaData, null, true);
    session.newStream(requestFrame, new Promise.Adapter<>(), new Stream.Listener.Adapter() {

        private AtomicInteger dataFrames = new AtomicInteger();

        @Override
        public void onData(Stream stream, DataFrame frame, Callback callback) {
            try {
                int dataFrames = this.dataFrames.incrementAndGet();
                if (dataFrames == 1 || dataFrames == 2) {
                    // Do not consume the data frame.
                    // We should then be flow-control stalled.
                    exchanger.exchange(callback);
                } else if (dataFrames == 3 || dataFrames == 4 || dataFrames == 5) {
                    // Consume totally.
                    callback.succeeded();
                    if (frame.isEndStream())
                        dataLatch.countDown();
                } else {
                    Assert.fail();
                }
            } catch (InterruptedException x) {
                callback.failed(x);
            }
        }
    });
    Callback callback = exchanger.exchange(null, 5, TimeUnit.SECONDS);
    checkThatWeAreFlowControlStalled(exchanger);
    // Consume the first chunk.
    callback.succeeded();
    callback = exchanger.exchange(null, 5, TimeUnit.SECONDS);
    checkThatWeAreFlowControlStalled(exchanger);
    // Consume the second chunk.
    callback.succeeded();
    Assert.assertTrue(dataLatch.await(5, TimeUnit.SECONDS));
}
Also used : ServerSessionListener(org.eclipse.jetty.http2.api.server.ServerSessionListener) HashMap(java.util.HashMap) Exchanger(java.util.concurrent.Exchanger) HeadersFrame(org.eclipse.jetty.http2.frames.HeadersFrame) SettingsFrame(org.eclipse.jetty.http2.frames.SettingsFrame) CompletableFuture(java.util.concurrent.CompletableFuture) MetaData(org.eclipse.jetty.http.MetaData) HttpFields(org.eclipse.jetty.http.HttpFields) HTTP2Stream(org.eclipse.jetty.http2.HTTP2Stream) Stream(org.eclipse.jetty.http2.api.Stream) DataFrame(org.eclipse.jetty.http2.frames.DataFrame) CountDownLatch(java.util.concurrent.CountDownLatch) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) FuturePromise(org.eclipse.jetty.util.FuturePromise) Promise(org.eclipse.jetty.util.Promise) Callback(org.eclipse.jetty.util.Callback) FutureCallback(org.eclipse.jetty.util.FutureCallback) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) ServerSessionListener(org.eclipse.jetty.http2.api.server.ServerSessionListener) HTTP2Session(org.eclipse.jetty.http2.HTTP2Session) Session(org.eclipse.jetty.http2.api.Session) ISession(org.eclipse.jetty.http2.ISession) Test(org.junit.Test)

Example 2 with Exchanger

use of java.util.concurrent.Exchanger in project jetty.project by eclipse.

the class FlowControlStrategyTest method testClientFlowControlOneBigWrite.

@Test
public void testClientFlowControlOneBigWrite() throws Exception {
    final int windowSize = 1536;
    final Exchanger<Callback> exchanger = new Exchanger<>();
    final CountDownLatch settingsLatch = new CountDownLatch(1);
    final CountDownLatch dataLatch = new CountDownLatch(1);
    start(new ServerSessionListener.Adapter() {

        @Override
        public Map<Integer, Integer> onPreface(Session session) {
            Map<Integer, Integer> settings = new HashMap<>();
            settings.put(SettingsFrame.INITIAL_WINDOW_SIZE, windowSize);
            return settings;
        }

        @Override
        public Stream.Listener onNewStream(Stream stream, HeadersFrame requestFrame) {
            MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, new HttpFields());
            HeadersFrame responseFrame = new HeadersFrame(stream.getId(), metaData, null, true);
            stream.headers(responseFrame, Callback.NOOP);
            return new Stream.Listener.Adapter() {

                private AtomicInteger dataFrames = new AtomicInteger();

                @Override
                public void onData(Stream stream, DataFrame frame, Callback callback) {
                    try {
                        int dataFrames = this.dataFrames.incrementAndGet();
                        if (dataFrames == 1 || dataFrames == 2) {
                            // Do not consume the data frame.
                            // We should then be flow-control stalled.
                            exchanger.exchange(callback);
                        } else if (dataFrames == 3 || dataFrames == 4 || dataFrames == 5) {
                            // Consume totally.
                            callback.succeeded();
                            if (frame.isEndStream())
                                dataLatch.countDown();
                        } else {
                            Assert.fail();
                        }
                    } catch (InterruptedException x) {
                        callback.failed(x);
                    }
                }
            };
        }
    });
    Session session = newClient(new Session.Listener.Adapter() {

        @Override
        public void onSettings(Session session, SettingsFrame frame) {
            settingsLatch.countDown();
        }
    });
    Assert.assertTrue(settingsLatch.await(5, TimeUnit.SECONDS));
    MetaData.Request metaData = newRequest("GET", new HttpFields());
    HeadersFrame requestFrame = new HeadersFrame(metaData, null, false);
    FuturePromise<Stream> streamPromise = new FuturePromise<>();
    session.newStream(requestFrame, streamPromise, null);
    Stream stream = streamPromise.get(5, TimeUnit.SECONDS);
    final int length = 5 * windowSize;
    DataFrame dataFrame = new DataFrame(stream.getId(), ByteBuffer.allocate(length), true);
    stream.data(dataFrame, Callback.NOOP);
    Callback callback = exchanger.exchange(null, 5, TimeUnit.SECONDS);
    checkThatWeAreFlowControlStalled(exchanger);
    // Consume the first chunk.
    callback.succeeded();
    callback = exchanger.exchange(null, 5, TimeUnit.SECONDS);
    checkThatWeAreFlowControlStalled(exchanger);
    // Consume the second chunk.
    callback.succeeded();
    Assert.assertTrue(dataLatch.await(5, TimeUnit.SECONDS));
}
Also used : ServerSessionListener(org.eclipse.jetty.http2.api.server.ServerSessionListener) Exchanger(java.util.concurrent.Exchanger) HeadersFrame(org.eclipse.jetty.http2.frames.HeadersFrame) SettingsFrame(org.eclipse.jetty.http2.frames.SettingsFrame) MetaData(org.eclipse.jetty.http.MetaData) HttpFields(org.eclipse.jetty.http.HttpFields) HTTP2Stream(org.eclipse.jetty.http2.HTTP2Stream) Stream(org.eclipse.jetty.http2.api.Stream) FuturePromise(org.eclipse.jetty.util.FuturePromise) DataFrame(org.eclipse.jetty.http2.frames.DataFrame) CountDownLatch(java.util.concurrent.CountDownLatch) Callback(org.eclipse.jetty.util.Callback) FutureCallback(org.eclipse.jetty.util.FutureCallback) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Map(java.util.Map) HashMap(java.util.HashMap) ServerSessionListener(org.eclipse.jetty.http2.api.server.ServerSessionListener) HTTP2Session(org.eclipse.jetty.http2.HTTP2Session) Session(org.eclipse.jetty.http2.api.Session) ISession(org.eclipse.jetty.http2.ISession) Test(org.junit.Test)

Example 3 with Exchanger

use of java.util.concurrent.Exchanger in project jetty.project by eclipse.

the class ConnectorTimeoutTest method testMaxIdleWithRequest10NoClientClose.

@Test(timeout = 60000)
public void testMaxIdleWithRequest10NoClientClose() throws Exception {
    final Exchanger<EndPoint> exchanger = new Exchanger<>();
    configureServer(new HelloWorldHandler() {

        @Override
        public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
            try {
                exchanger.exchange(baseRequest.getHttpChannel().getEndPoint());
            } catch (Exception e) {
                e.printStackTrace();
            }
            super.handle(target, baseRequest, request, response);
        }
    });
    Socket client = newSocket(_serverURI.getHost(), _serverURI.getPort());
    client.setSoTimeout(10000);
    Assert.assertFalse(client.isClosed());
    OutputStream os = client.getOutputStream();
    InputStream is = client.getInputStream();
    os.write(("GET / HTTP/1.0\r\n" + "host: " + _serverURI.getHost() + ":" + _serverURI.getPort() + "\r\n" + "connection: close\r\n" + "\r\n").getBytes("utf-8"));
    os.flush();
    // Get the server side endpoint
    EndPoint endPoint = exchanger.exchange(null, 10, TimeUnit.SECONDS);
    if (endPoint instanceof SslConnection.DecryptedEndPoint)
        endPoint = endPoint.getConnection().getEndPoint();
    // read the response
    String result = IO.toString(is);
    Assert.assertThat("OK", result, Matchers.containsString("200 OK"));
    // check client reads EOF
    Assert.assertEquals(-1, is.read());
    // wait for idle timeout
    TimeUnit.MILLISECONDS.sleep(3 * MAX_IDLE_TIME);
    // further writes will get broken pipe or similar
    try {
        for (int i = 0; i < 1000; i++) {
            os.write(("GET / HTTP/1.0\r\n" + "host: " + _serverURI.getHost() + ":" + _serverURI.getPort() + "\r\n" + "connection: keep-alive\r\n" + "\r\n").getBytes("utf-8"));
            os.flush();
        }
        Assert.fail("half close should have timed out");
    } catch (SocketException e) {
    // expected
    }
    // check the server side is closed
    Assert.assertFalse(endPoint.isOpen());
}
Also used : SocketException(java.net.SocketException) Exchanger(java.util.concurrent.Exchanger) InputStream(java.io.InputStream) OutputStream(java.io.OutputStream) HttpServletRequest(javax.servlet.http.HttpServletRequest) HttpServletResponse(javax.servlet.http.HttpServletResponse) EndPoint(org.eclipse.jetty.io.EndPoint) IOException(java.io.IOException) ServletException(javax.servlet.ServletException) SocketException(java.net.SocketException) IOException(java.io.IOException) SSLException(javax.net.ssl.SSLException) EndPoint(org.eclipse.jetty.io.EndPoint) HttpServletRequest(javax.servlet.http.HttpServletRequest) ServletException(javax.servlet.ServletException) Socket(java.net.Socket) Test(org.junit.Test)

Example 4 with Exchanger

use of java.util.concurrent.Exchanger in project jetty.project by eclipse.

the class ThreadStarvationTest method testDefaultServletSuccess.

@Test
@Slow
public void testDefaultServletSuccess() throws Exception {
    int maxThreads = 10;
    QueuedThreadPool threadPool = new QueuedThreadPool(maxThreads, maxThreads);
    threadPool.setDetailedDump(true);
    _server = new Server(threadPool);
    // Prepare a big file to download.
    File directory = MavenTestingUtils.getTargetTestingDir();
    Files.createDirectories(directory.toPath());
    String resourceName = "resource.bin";
    Path resourcePath = Paths.get(directory.getPath(), resourceName);
    try (OutputStream output = Files.newOutputStream(resourcePath, StandardOpenOption.CREATE, StandardOpenOption.WRITE)) {
        byte[] chunk = new byte[1024];
        Arrays.fill(chunk, (byte) 'X');
        chunk[chunk.length - 2] = '\r';
        chunk[chunk.length - 1] = '\n';
        for (int i = 0; i < 256 * 1024; ++i) output.write(chunk);
    }
    final CountDownLatch writePending = new CountDownLatch(1);
    ServerConnector connector = new ServerConnector(_server, 0, 1) {

        @Override
        protected ChannelEndPoint newEndPoint(SocketChannel channel, ManagedSelector selectSet, SelectionKey key) throws IOException {
            return new SocketChannelEndPoint(channel, selectSet, key, getScheduler()) {

                @Override
                protected void onIncompleteFlush() {
                    super.onIncompleteFlush();
                    writePending.countDown();
                }
            };
        }
    };
    connector.setIdleTimeout(Long.MAX_VALUE);
    _server.addConnector(connector);
    ServletContextHandler context = new ServletContextHandler(_server, "/");
    context.setResourceBase(directory.toURI().toString());
    context.addServlet(DefaultServlet.class, "/*").setAsyncSupported(false);
    _server.setHandler(context);
    _server.start();
    List<Socket> sockets = new ArrayList<>();
    for (int i = 0; i < maxThreads * 2; ++i) {
        Socket socket = new Socket("localhost", connector.getLocalPort());
        sockets.add(socket);
        OutputStream output = socket.getOutputStream();
        String request = "" + "GET /" + resourceName + " HTTP/1.1\r\n" + "Host: localhost\r\n" + "\r\n";
        output.write(request.getBytes(StandardCharsets.UTF_8));
        output.flush();
        Thread.sleep(100);
    }
    // Wait for a the servlet to block.
    Assert.assertTrue(writePending.await(5, TimeUnit.SECONDS));
    long expected = Files.size(resourcePath);
    byte[] buffer = new byte[48 * 1024];
    List<Exchanger<Long>> totals = new ArrayList<>();
    for (Socket socket : sockets) {
        final Exchanger<Long> x = new Exchanger<>();
        totals.add(x);
        final InputStream input = socket.getInputStream();
        new Thread() {

            @Override
            public void run() {
                long total = 0;
                try {
                    // look for CRLFCRLF
                    StringBuilder header = new StringBuilder();
                    int state = 0;
                    while (state < 4 && header.length() < 2048) {
                        int ch = input.read();
                        if (ch < 0)
                            break;
                        header.append((char) ch);
                        switch(state) {
                            case 0:
                                if (ch == '\r')
                                    state = 1;
                                break;
                            case 1:
                                if (ch == '\n')
                                    state = 2;
                                else
                                    state = 0;
                                break;
                            case 2:
                                if (ch == '\r')
                                    state = 3;
                                else
                                    state = 0;
                                break;
                            case 3:
                                if (ch == '\n')
                                    state = 4;
                                else
                                    state = 0;
                                break;
                        }
                    }
                    while (total < expected) {
                        int read = input.read(buffer);
                        if (read < 0)
                            break;
                        total += read;
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    try {
                        x.exchange(total);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }.start();
    }
    for (Exchanger<Long> x : totals) {
        Long total = x.exchange(-1L, 10000, TimeUnit.SECONDS);
        Assert.assertEquals(expected, total.longValue());
    }
    // We could read everything, good.
    for (Socket socket : sockets) socket.close();
}
Also used : ManagedSelector(org.eclipse.jetty.io.ManagedSelector) SocketChannel(java.nio.channels.SocketChannel) Server(org.eclipse.jetty.server.Server) Exchanger(java.util.concurrent.Exchanger) OutputStream(java.io.OutputStream) ArrayList(java.util.ArrayList) ServerConnector(org.eclipse.jetty.server.ServerConnector) QueuedThreadPool(org.eclipse.jetty.util.thread.QueuedThreadPool) DefaultServlet(org.eclipse.jetty.servlet.DefaultServlet) Path(java.nio.file.Path) SelectionKey(java.nio.channels.SelectionKey) InputStream(java.io.InputStream) IOException(java.io.IOException) CountDownLatch(java.util.concurrent.CountDownLatch) ChannelEndPoint(org.eclipse.jetty.io.ChannelEndPoint) SocketChannelEndPoint(org.eclipse.jetty.io.SocketChannelEndPoint) ServletContextHandler(org.eclipse.jetty.servlet.ServletContextHandler) File(java.io.File) SocketChannelEndPoint(org.eclipse.jetty.io.SocketChannelEndPoint) Socket(java.net.Socket) Test(org.junit.Test) Slow(org.eclipse.jetty.toolchain.test.annotation.Slow)

Example 5 with Exchanger

use of java.util.concurrent.Exchanger in project camel by apache.

the class InOutProducer method sendMessage.

/**
     * TODO time out is actually double as it waits for the producer and then
     * waits for the response. Use an atomic long to manage the countdown
     */
@Override
public void sendMessage(final Exchange exchange, final AsyncCallback callback, final MessageProducerResources producer, final ReleaseProducerCallback releaseProducerCallback) throws Exception {
    Message request = getEndpoint().getBinding().makeJmsMessage(exchange, producer.getSession());
    String correlationId = exchange.getIn().getHeader(JmsConstants.JMS_CORRELATION_ID, String.class);
    if (correlationId == null) {
        // we append the 'Camel-' prefix to know it was generated by us
        correlationId = GENERATED_CORRELATION_ID_PREFIX + getUuidGenerator().generateUuid();
    }
    Object responseObject = null;
    Exchanger<Object> messageExchanger = new Exchanger<Object>();
    JmsMessageHelper.setCorrelationId(request, correlationId);
    EXCHANGERS.put(correlationId, messageExchanger);
    MessageConsumerResources consumer = consumers.borrowObject();
    JmsMessageHelper.setJMSReplyTo(request, consumer.getReplyToDestination());
    consumers.returnObject(consumer);
    producer.getMessageProducer().send(request);
    // without waiting on us to complete the exchange
    try {
        releaseProducerCallback.release(producer);
    } catch (Exception exception) {
    // thrown if the pool is full. safe to ignore.
    }
    try {
        responseObject = messageExchanger.exchange(null, getResponseTimeOut(), TimeUnit.MILLISECONDS);
        EXCHANGERS.remove(correlationId);
    } catch (InterruptedException e) {
        log.debug("Exchanger was interrupted while waiting on response", e);
        exchange.setException(e);
    } catch (TimeoutException e) {
        log.debug("Exchanger timed out while waiting on response", e);
        exchange.setException(e);
    }
    if (exchange.getException() == null) {
        if (responseObject instanceof Throwable) {
            exchange.setException((Throwable) responseObject);
        } else if (responseObject instanceof Message) {
            Message message = (Message) responseObject;
            SjmsMessage response = new SjmsMessage(message, consumer.getSession(), getEndpoint().getBinding());
            // the JmsBinding is designed to be "pull-based": it will populate the Camel message on demand
            // therefore, we link Exchange and OUT message before continuing, so that the JmsBinding has full access
            // to everything it may need, and can populate headers, properties, etc. accordingly (solves CAMEL-6218).
            exchange.setOut(response);
        } else {
            exchange.setException(new CamelException("Unknown response type: " + responseObject));
        }
    }
    callback.done(isSynchronous());
}
Also used : Message(javax.jms.Message) SjmsMessage(org.apache.camel.component.sjms.SjmsMessage) Exchanger(java.util.concurrent.Exchanger) CamelException(org.apache.camel.CamelException) SjmsMessage(org.apache.camel.component.sjms.SjmsMessage) MessageConsumerResources(org.apache.camel.component.sjms.MessageConsumerResources) TimeoutException(java.util.concurrent.TimeoutException) CamelException(org.apache.camel.CamelException) TimeoutException(java.util.concurrent.TimeoutException)

Aggregations

Exchanger (java.util.concurrent.Exchanger)22 CountDownLatch (java.util.concurrent.CountDownLatch)10 Test (org.junit.Test)9 IOException (java.io.IOException)6 InputStream (java.io.InputStream)5 OutputStream (java.io.OutputStream)5 Socket (java.net.Socket)5 Test (org.junit.jupiter.api.Test)5 Channel (io.netty.channel.Channel)4 ChannelHandlerContext (io.netty.channel.ChannelHandlerContext)4 ChannelInboundHandlerAdapter (io.netty.channel.ChannelInboundHandlerAdapter)4 EmbeddedChannel (io.netty.channel.embedded.EmbeddedChannel)4 NioServerSocketChannel (io.netty.channel.socket.nio.NioServerSocketChannel)4 NioSocketChannel (io.netty.channel.socket.nio.NioSocketChannel)4 TimeoutException (java.util.concurrent.TimeoutException)4 ServletException (javax.servlet.ServletException)4 HttpServletRequest (javax.servlet.http.HttpServletRequest)4 HttpServletResponse (javax.servlet.http.HttpServletResponse)4 SocketException (java.net.SocketException)3 HashMap (java.util.HashMap)3