Search in sources :

Example 31 with AsyncListener

use of javax.servlet.AsyncListener in project fabric8 by jboss-fuse.

the class MavenDownloadProxyServlet method doGet.

@Override
protected void doGet(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException {
    String tpath = req.getPathInfo();
    if (tpath == null) {
        resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        return;
    }
    if (tpath.startsWith("/")) {
        tpath = tpath.substring(1);
    }
    final String path = tpath;
    // state to help synchronize between async timeout handler and ArtifactDownloadFuture ready handler
    final AtomicInteger timeoutOrReady = new AtomicInteger(ASYNC_STARTED);
    final AsyncContext asyncContext = req.startAsync();
    // timeout higher than the one set in:
    // org.eclipse.aether.DefaultRepositorySystemSession.setConfigProperty("aether.connector.requestTimeout", N)
    asyncContext.setTimeout(this.timeout);
    asyncContext.addListener(new AsyncListener() {

        @Override
        public void onComplete(AsyncEvent event) throws IOException {
        }

        @Override
        public void onTimeout(AsyncEvent event) throws IOException {
            if (timeoutOrReady.compareAndSet(ASYNC_STARTED, ASYNC_TIMEOUT)) {
                LOGGER.warn("Timeout handling " + ((HttpServletRequest) event.getSuppliedRequest()).getRequestURI());
                ((HttpServletResponse) event.getAsyncContext().getResponse()).sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Async timeout when downloading Maven artifact");
                event.getAsyncContext().complete();
            } else {
                LOGGER.debug("Timeout handling " + ((HttpServletRequest) event.getSuppliedRequest()).getRequestURI() + ", but download thread completed, continuing process of download.");
            }
        }

        @Override
        public void onError(AsyncEvent event) throws IOException {
        }

        @Override
        public void onStartAsync(AsyncEvent event) throws IOException {
        }
    });
    final AsynchronousFileChannel channel = (AsynchronousFileChannel) req.getAttribute(AsynchronousFileChannel.class.getName());
    if (channel != null) /*&& req.getDispatcherType() == DispatcherType.ASYNC*/
    {
        long size = (Long) req.getAttribute(AsynchronousFileChannel.class.getName() + ".size");
        long pos = (Long) req.getAttribute(AsynchronousFileChannel.class.getName() + ".position");
        int read = (Integer) req.getAttribute(AsynchronousFileChannel.class.getName() + ".read");
        ByteBuffer buffer = (ByteBuffer) req.getAttribute(ByteBuffer.class.getName());
        ByteBuffer secondBuffer = (ByteBuffer) req.getAttribute(ByteBuffer.class.getName() + ".second");
        if (read > 0) {
            pos += read;
            if (pos < size) {
                req.setAttribute(AsynchronousFileChannel.class.getName() + ".position", pos);
                req.setAttribute(ByteBuffer.class.getName(), secondBuffer);
                req.setAttribute(ByteBuffer.class.getName() + ".second", buffer);
                channel.read(secondBuffer, pos, asyncContext, new CompletionHandler<Integer, AsyncContext>() {

                    @Override
                    public void completed(Integer result, AsyncContext attachment) {
                        req.setAttribute(AsynchronousFileChannel.class.getName() + ".read", result);
                        // dispatch again, buffers are switched
                        attachment.dispatch();
                    }

                    @Override
                    public void failed(Throwable exc, AsyncContext attachment) {
                        Closeables.closeQuietly(channel);
                        resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
                        attachment.complete();
                    }
                });
            }
            buffer.flip();
            resp.getOutputStream().write(buffer.array(), 0, buffer.remaining());
            resp.flushBuffer();
            if (pos == size) {
                Closeables.closeQuietly(channel);
                asyncContext.complete();
            }
        } else {
            Closeables.closeQuietly(channel);
            resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            asyncContext.complete();
        }
        return;
    }
    final ArtifactDownloadFuture future = new ArtifactDownloadFuture(path);
    ArtifactDownloadFuture masterFuture = requestMap.putIfAbsent(path, future);
    if (masterFuture == null) {
        masterFuture = future;
        masterFuture.lock();
        executorService.execute(new Runnable() {

            @Override
            public void run() {
                try {
                    File file = download(path);
                    future.setValue(file);
                } catch (Throwable t) {
                    future.setValue(t);
                }
            }
        });
    } else {
        masterFuture.lock();
    }
    masterFuture.addListener(new FutureListener<ArtifactDownloadFuture>() {

        @Override
        public void operationComplete(ArtifactDownloadFuture future) {
            Object value = future.getValue();
            if (value instanceof Throwable) {
                LOGGER.warn("Error while downloading artifact: {}", ((Throwable) value).getMessage(), value);
                resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            } else if (value instanceof File) {
                if (!timeoutOrReady.compareAndSet(ASYNC_STARTED, ASYNC_ARTIFACT_READY)) {
                    LOGGER.warn("Download thread completed, but asynchronous timeout occurred. Downloading interrupted.");
                } else {
                    File artifactFile = (File) value;
                    AsynchronousFileChannel channel = null;
                    try {
                        channel = AsynchronousFileChannel.open(artifactFile.toPath(), StandardOpenOption.READ);
                        LOGGER.info("Writing response for file : {}", path);
                        resp.setStatus(HttpServletResponse.SC_OK);
                        resp.setContentType("application/octet-stream");
                        resp.setDateHeader("Date", System.currentTimeMillis());
                        resp.setHeader("Connection", "close");
                        resp.setHeader("Server", "MavenProxy Proxy/" + FabricConstants.FABRIC_VERSION);
                        long size = artifactFile.length();
                        if (size < Integer.MAX_VALUE) {
                            resp.setContentLength((int) size);
                        }
                        if ("GET".equals(req.getMethod())) {
                            // Store attributes and start reading
                            req.setAttribute(AsynchronousFileChannel.class.getName(), channel);
                            ByteBuffer buffer = ByteBuffer.allocate(1024 * 64);
                            ByteBuffer secondBuffer = ByteBuffer.allocate(1024 * 64);
                            req.setAttribute(ByteBuffer.class.getName(), secondBuffer);
                            req.setAttribute(ByteBuffer.class.getName() + ".second", buffer);
                            req.setAttribute(AsynchronousFileChannel.class.getName() + ".position", 0l);
                            req.setAttribute(AsynchronousFileChannel.class.getName() + ".size", size);
                            channel.read(secondBuffer, 0, asyncContext, new CompletionHandler<Integer, AsyncContext>() {

                                @Override
                                public void completed(Integer result, AsyncContext attachment) {
                                    req.setAttribute(AsynchronousFileChannel.class.getName() + ".read", result);
                                    attachment.dispatch();
                                }

                                @Override
                                public void failed(Throwable exc, AsyncContext attachment) {
                                    resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
                                    attachment.complete();
                                }
                            });
                        } else if ("HEAD".equals(req.getMethod())) {
                            asyncContext.complete();
                        }
                        future.release();
                        return;
                    } catch (Exception e) {
                        Closeables.closeQuietly(channel);
                        LOGGER.warn("Error while sending artifact: {}", e.getMessage(), e);
                        resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
                    }
                }
            } else {
                resp.setStatus(HttpServletResponse.SC_NOT_FOUND);
            }
            future.release();
            try {
                asyncContext.complete();
            } catch (IllegalStateException e) {
            // Ignore, the response must have already been sent with an error
            }
        }
    });
}
Also used : AsyncContext(javax.servlet.AsyncContext) IOException(java.io.IOException) AsyncEvent(javax.servlet.AsyncEvent) ByteBuffer(java.nio.ByteBuffer) ServletException(javax.servlet.ServletException) IOException(java.io.IOException) HttpServletRequest(javax.servlet.http.HttpServletRequest) AsynchronousFileChannel(java.nio.channels.AsynchronousFileChannel) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) AsyncListener(javax.servlet.AsyncListener) File(java.io.File)

Example 32 with AsyncListener

use of javax.servlet.AsyncListener in project presto by prestodb.

the class AsyncPageTransportServlet method processRequest.

protected void processRequest(String requestURI, TaskId taskId, OutputBufferId bufferId, long token, HttpServletRequest request, HttpServletResponse response) throws IOException {
    DataSize maxSize = DataSize.valueOf(request.getHeader(PRESTO_MAX_SIZE));
    AsyncContext asyncContext = request.startAsync(request, response);
    // wait time to get results
    Duration waitTime = randomizeWaitTime(DEFAULT_MAX_WAIT_TIME);
    asyncContext.setTimeout(waitTime.toMillis() + pageTransportTimeout.toMillis());
    asyncContext.addListener(new AsyncListener() {

        public void onComplete(AsyncEvent event) {
        }

        public void onError(AsyncEvent event) throws IOException {
            String errorMessage = format("Server error to process task result request %s : %s", requestURI, event.getThrowable().getMessage());
            log.error(event.getThrowable(), errorMessage);
            response.sendError(SC_INTERNAL_SERVER_ERROR, errorMessage);
        }

        public void onStartAsync(AsyncEvent event) {
        }

        public void onTimeout(AsyncEvent event) throws IOException {
            String errorMessage = format("Server timeout to process task result request: %s", requestURI);
            log.error(event.getThrowable(), errorMessage);
            response.sendError(SC_INTERNAL_SERVER_ERROR, errorMessage);
        }
    });
    ListenableFuture<BufferResult> bufferResultFuture = taskManager.getTaskResults(taskId, bufferId, token, maxSize);
    bufferResultFuture = addTimeout(bufferResultFuture, () -> BufferResult.emptyResults(taskManager.getTaskInstanceId(taskId), token, false), waitTime, timeoutExecutor);
    ServletOutputStream out = response.getOutputStream();
    addCallback(bufferResultFuture, new FutureCallback<BufferResult>() {

        @Override
        public void onSuccess(BufferResult bufferResult) {
            response.setHeader(CONTENT_TYPE, PRESTO_PAGES);
            response.setHeader(PRESTO_TASK_INSTANCE_ID, bufferResult.getTaskInstanceId());
            response.setHeader(PRESTO_PAGE_TOKEN, String.valueOf(bufferResult.getToken()));
            response.setHeader(PRESTO_PAGE_NEXT_TOKEN, String.valueOf(bufferResult.getNextToken()));
            response.setHeader(PRESTO_BUFFER_COMPLETE, String.valueOf(bufferResult.isBufferComplete()));
            List<SerializedPage> serializedPages = bufferResult.getSerializedPages();
            if (serializedPages.isEmpty()) {
                response.setStatus(SC_NO_CONTENT);
                asyncContext.complete();
            } else {
                int contentLength = (serializedPages.size() * PAGE_METADATA_SIZE) + serializedPages.stream().mapToInt(SerializedPage::getSizeInBytes).sum();
                response.setHeader(CONTENT_LENGTH, String.valueOf(contentLength));
                out.setWriteListener(new SerializedPageWriteListener(serializedPages, asyncContext, out));
            }
        }

        @Override
        public void onFailure(Throwable thrown) {
            String errorMessage = format("Error getting task result from TaskManager for request %s : %s", requestURI, thrown.getMessage());
            log.error(thrown, errorMessage);
            try {
                response.sendError(SC_INTERNAL_SERVER_ERROR, errorMessage);
            } catch (IOException e) {
                log.error(e, "Failed to send response with error code: %s", e.getMessage());
            }
            asyncContext.complete();
        }
    }, responseExecutor);
}
Also used : ServletOutputStream(javax.servlet.ServletOutputStream) AsyncContext(javax.servlet.AsyncContext) Duration(io.airlift.units.Duration) IOException(java.io.IOException) AsyncEvent(javax.servlet.AsyncEvent) BufferResult(com.facebook.presto.execution.buffer.BufferResult) DataSize(io.airlift.units.DataSize) AsyncListener(javax.servlet.AsyncListener) List(java.util.List)

Example 33 with AsyncListener

use of javax.servlet.AsyncListener in project pinpoint by naver.

the class RequestStartAsyncInterceptor method doInAfterTrace.

@Override
protected void doInAfterTrace(SpanEventRecorder recorder, Object target, Object[] args, Object result, Throwable throwable) {
    if (validate(target, result, throwable)) {
        // Add async listener. Servlet 3.0
        final AsyncContext asyncContext = (AsyncContext) result;
        final AsyncListener asyncListener = new JbossAsyncListener(this.traceContext, recorder.recordNextAsyncContext(true));
        asyncContext.addListener(asyncListener);
        if (isDebug) {
            logger.debug("Add async listener {}", asyncListener);
        }
    }
    recorder.recordServiceType(JbossConstants.JBOSS_METHOD);
    recorder.recordApi(methodDescriptor);
    recorder.recordException(throwable);
}
Also used : JbossAsyncListener(com.navercorp.pinpoint.plugin.jboss.JbossAsyncListener) AsyncListener(javax.servlet.AsyncListener) JbossAsyncListener(com.navercorp.pinpoint.plugin.jboss.JbossAsyncListener) AsyncContext(javax.servlet.AsyncContext)

Example 34 with AsyncListener

use of javax.servlet.AsyncListener in project pinpoint by naver.

the class HttpServletRequestImplInterceptor method doInAfterTrace.

@Override
protected void doInAfterTrace(SpanEventRecorder recorder, Object target, Object[] args, Object result, Throwable throwable) {
    if (validate(target, result, throwable)) {
        final AsyncContext asyncContext = (AsyncContext) result;
        final AsyncListener asyncListener = new ResinAsyncListener(this.traceContext, recorder.recordNextAsyncContext(true));
        asyncContext.addListener(asyncListener);
        if (isDebug) {
            logger.debug("Add async listener {}", asyncListener);
        }
    }
    recorder.recordServiceType(ResinConstants.RESIN_METHOD);
    recorder.recordApi(methodDescriptor);
    recorder.recordException(throwable);
}
Also used : ResinAsyncListener(com.navercorp.pinpoint.plugin.resin.ResinAsyncListener) AsyncListener(javax.servlet.AsyncListener) ResinAsyncListener(com.navercorp.pinpoint.plugin.resin.ResinAsyncListener) AsyncContext(javax.servlet.AsyncContext)

Example 35 with AsyncListener

use of javax.servlet.AsyncListener in project pinpoint by naver.

the class WCCRequestImplStartAsyncInterceptor method doInAfterTrace.

@Override
protected void doInAfterTrace(SpanEventRecorder recorder, Object target, Object[] args, Object result, Throwable throwable) {
    if (validate(target, result, throwable)) {
        final AsyncContext asyncContext = (AsyncContext) result;
        final AsyncListener asyncListener = new WebsphereAsyncListener(this.traceContext, recorder.recordNextAsyncContext(true));
        asyncContext.addListener(asyncListener);
        if (isDebug) {
            logger.debug("Add async listener {}", asyncListener);
        }
    }
    recorder.recordServiceType(WebsphereConstants.WEBSPHERE_METHOD);
    recorder.recordApi(methodDescriptor);
    recorder.recordException(throwable);
}
Also used : AsyncListener(javax.servlet.AsyncListener) WebsphereAsyncListener(com.navercorp.pinpoint.plugin.websphere.WebsphereAsyncListener) WebsphereAsyncListener(com.navercorp.pinpoint.plugin.websphere.WebsphereAsyncListener) AsyncContext(javax.servlet.AsyncContext)

Aggregations

AsyncListener (javax.servlet.AsyncListener)45 AsyncContext (javax.servlet.AsyncContext)32 AsyncEvent (javax.servlet.AsyncEvent)30 IOException (java.io.IOException)28 HttpServletResponse (javax.servlet.http.HttpServletResponse)16 HttpServletRequest (javax.servlet.http.HttpServletRequest)14 ServletException (javax.servlet.ServletException)12 Test (org.junit.Test)12 AtomicReference (java.util.concurrent.atomic.AtomicReference)7 CountDownLatch (java.util.concurrent.CountDownLatch)5 HttpServlet (javax.servlet.http.HttpServlet)5 OutputStream (java.io.OutputStream)4 Socket (java.net.Socket)3 URISyntaxException (java.net.URISyntaxException)3 CyclicBarrier (java.util.concurrent.CyclicBarrier)3 Request (org.eclipse.jetty.server.Request)3 Locker (org.eclipse.jetty.util.thread.Locker)3 RequestContext (com.linkedin.r2.message.RequestContext)2 TransportCallback (com.linkedin.r2.transport.common.bridge.common.TransportCallback)2 TransportResponse (com.linkedin.r2.transport.common.bridge.common.TransportResponse)2