Search in sources :

Example 6 with Continuation

use of org.eclipse.jetty.continuation.Continuation in project zm-mailbox by Zimbra.

the class ContextPathBasedThreadPoolBalancerFilter method doFilter.

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    // Determine whether to allow or suspend request
    boolean suspend = shouldSuspend(request);
    // Suspend request
    if (suspend) {
        Continuation continuation = ContinuationSupport.getContinuation(request);
        HttpServletRequest hreq = (HttpServletRequest) request;
        ZimbraServlet.addRemoteIpToLoggingContext(hreq);
        ZimbraServlet.addUAToLoggingContext(hreq);
        ZimbraLog.clearContext();
        continuation.setTimeout(suspendMs);
        continuation.suspend();
        return;
    }
    // Allow request
    String contextPath = getContextPath(request);
    try {
        // Start tracking request
        AtomicInteger i = activeRequestsByContextPath.get(contextPath);
        if (i == null) {
            i = new AtomicInteger(1);
            activeRequestsByContextPath.put(contextPath, i);
        } else {
            i.incrementAndGet();
        }
        // ZimbraLog.misc.debug("%s concurrency=%d", contextPath, i.get());
        // Perform default operation
        chain.doFilter(request, response);
    } finally {
        // Stop tracking request
        AtomicInteger i = activeRequestsByContextPath.get(contextPath);
        i.decrementAndGet();
    // ZimbraLog.misc.debug("%s concurrency=%d", contextPath, i.get());
    }
}
Also used : HttpServletRequest(javax.servlet.http.HttpServletRequest) Continuation(org.eclipse.jetty.continuation.Continuation) AtomicInteger(java.util.concurrent.atomic.AtomicInteger)

Example 7 with Continuation

use of org.eclipse.jetty.continuation.Continuation in project Singularity by HubSpot.

the class SingularityS3DownloaderHandler method handle.

@Override
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
    metrics.getRequestsMeter().mark();
    if (!target.equals(s3Configuration.getLocalDownloadPath())) {
        metrics.getClientErrorsMeter().mark();
        response.sendError(404);
        return;
    }
    if (!request.getMethod().equalsIgnoreCase(HttpMethod.POST.name())) {
        metrics.getClientErrorsMeter().mark();
        response.sendError(405);
        return;
    }
    Optional<ArtifactDownloadRequest> artifactOptional = readDownloadRequest(request);
    if (!artifactOptional.isPresent()) {
        metrics.getClientErrorsMeter().mark();
        response.sendError(400);
        return;
    }
    Continuation continuation = ContinuationSupport.getContinuation(request);
    continuation.suspend(response);
    if (artifactOptional.get().getTimeoutMillis().isPresent()) {
        continuation.setTimeout(artifactOptional.get().getTimeoutMillis().get());
    }
    downloaderCoordinator.register(continuation, artifactOptional.get());
}
Also used : Continuation(org.eclipse.jetty.continuation.Continuation) ArtifactDownloadRequest(com.hubspot.singularity.s3.base.ArtifactDownloadRequest)

Example 8 with Continuation

use of org.eclipse.jetty.continuation.Continuation in project zm-mailbox by Zimbra.

the class NoOp method handle.

@Override
public Element handle(Element request, Map<String, Object> context) throws ServiceException {
    ZimbraSoapContext zsc = getZimbraSoapContext(context);
    boolean wait = request.getAttributeBool(MailConstants.A_WAIT, false);
    boolean includeDelegates = request.getAttributeBool(MailConstants.A_DELEGATE, true);
    HttpServletRequest servletRequest = (HttpServletRequest) context.get(SoapServlet.SERVLET_REQUEST);
    boolean enforceLimit = request.getAttributeBool(MailConstants.A_LIMIT_TO_ONE_BLOCKED, false);
    boolean blockingUnsupported = false;
    // gets the <refresh> block
    if (zsc.hasCreatedSession())
        wait = false;
    if (wait) {
        if (!zsc.hasSession()) {
            throw ServiceException.INVALID_REQUEST("Cannot execute a NoOpRequest with wait=\"1\" without a session." + "  Set the <session> flag in the <context> of your request", null);
        }
        ZimbraSoapContext origContext = (ZimbraSoapContext) (servletRequest.getAttribute("nop_origcontext"));
        if (origContext == null) {
            // Initial
            servletRequest.setAttribute("nop_origcontext", zsc);
            // NOT a resumed request -- block if necessary
            Continuation continuation = ContinuationSupport.getContinuation(servletRequest);
            if (zsc.beginWaitForNotifications(continuation, includeDelegates)) {
                if (enforceLimit) {
                    ZimbraSoapContext otherContext = sBlockedNops.put(zsc.getAuthtokenAccountId(), zsc);
                    if (otherContext != null) {
                        otherContext.signalNotification(true);
                    }
                }
                synchronized (zsc) {
                    if (zsc.waitingForNotifications()) {
                        // assert (!(continuation instanceof WaitingContinuation) || ((WaitingContinuation) continuation).getMutex() == zsc);
                        long timeout = parseTimeout(request);
                        if (ZimbraLog.soap.isTraceEnabled())
                            ZimbraLog.soap.trace("Suspending <NoOpRequest> for %dms", timeout);
                        zsc.suspendAndUndispatch(timeout);
                    }
                    if (zsc.isCanceledWaitForNotifications())
                        blockingUnsupported = true;
                }
            }
            if (enforceLimit) {
                // remove this soap context from the blocked-conext hash, but only
                // if it hasn't already been removed by someone else...
                sBlockedNops.remove(zsc.getAuthtokenAccountId(), zsc);
            }
        } else {
            // Resumed
            if (origContext.isCanceledWaitForNotifications())
                blockingUnsupported = true;
            if (enforceLimit) {
                // remove this soap context from the blocked-conext hash, but only
                // if it hasn't already been removed by someone else...
                sBlockedNops.remove(origContext.getAuthtokenAccountId(), origContext);
            }
        }
    }
    Element toRet = zsc.createElement(MailConstants.NO_OP_RESPONSE);
    if (blockingUnsupported) {
        toRet.addAttribute(MailConstants.A_WAIT_DISALLOWED, true);
    }
    return toRet;
}
Also used : HttpServletRequest(javax.servlet.http.HttpServletRequest) Continuation(org.eclipse.jetty.continuation.Continuation) ZimbraSoapContext(com.zimbra.soap.ZimbraSoapContext) Element(com.zimbra.common.soap.Element)

Example 9 with Continuation

use of org.eclipse.jetty.continuation.Continuation in project zm-mailbox by Zimbra.

the class WaitSetRequest method staticHandle.

public static void staticHandle(WaitSetReq req, Map<String, Object> context, WaitSetResp resp, boolean adminAllowed) throws ServiceException {
    ZimbraSoapContext zsc = getZimbraSoapContext(context);
    HttpServletRequest servletRequest = (HttpServletRequest) context.get(SoapServlet.SERVLET_REQUEST);
    String waitSetId = req.getWaitSetId();
    String lastKnownSeqNo = req.getLastKnownSeqNo();
    boolean block = req.getBlock();
    boolean expand = req.getExpand();
    WaitSetCallback cb = (WaitSetCallback) servletRequest.getAttribute(VARS_ATTR_NAME);
    if (cb == null) {
        // Initial
        Continuation continuation = ContinuationSupport.getContinuation(servletRequest);
        cb = new WaitSetCallback();
        cb.continuationResume = new ResumeContinuationListener(continuation);
        servletRequest.setAttribute(VARS_ATTR_NAME, cb);
        servletRequest.setAttribute(ZimbraSoapContext.soapRequestIdAttr, zsc.getSoapRequestId());
        String defInterestStr = null;
        if (waitSetId.startsWith(WaitSetMgr.ALL_ACCOUNTS_ID_PREFIX)) {
            WaitSetMgr.checkRightForAllAccounts(zsc);
            // default interest types required for "All" waitsets
            defInterestStr = req.getDefaultInterests();
            Set<MailItem.Type> defaultInterests = WaitSetRequest.parseInterestStr(defInterestStr, EnumSet.noneOf(MailItem.Type.class));
            cb.ws = WaitSetMgr.lookupOrCreateForAllAccts(zsc.getRequestedAccountId(), waitSetId, defaultInterests, lastKnownSeqNo);
        } else {
            cb.ws = WaitSetMgr.lookup(waitSetId);
        }
        if (cb.ws == null)
            throw AdminServiceException.NO_SUCH_WAITSET(waitSetId);
        WaitSetMgr.checkRightForOwnerAccount(cb.ws, zsc.getRequestedAccountId());
        List<WaitSetAccount> add = parseAddUpdateAccounts(zsc, req.getAddAccounts(), cb.ws.getDefaultInterest());
        List<WaitSetAccount> update = parseAddUpdateAccounts(zsc, req.getUpdateAccounts(), cb.ws.getDefaultInterest());
        List<String> remove = parseRemoveAccounts(zsc, req.getRemoveAccounts());
        // /////////////////
        // workaround for 27480: load the mailboxes NOW, before we grab the waitset lock
        preloadMailboxes(add);
        preloadMailboxes(update);
        // the server in a very fast loop (they should be using the 'block' mode)
        if (!block && !adminAllowed) {
            try {
                Thread.sleep(INITIAL_SLEEP_TIME_MILLIS);
            } catch (InterruptedException ex) {
            }
        }
        cb.errors.addAll(cb.ws.removeAccounts(remove));
        synchronized (cb.ws) {
            // bug 28190: always grab the WS lock before the CB lock.
            synchronized (cb) {
                // note that doWait for AllAccountsWaitSet ignores 'add' and 'update'
                cb.errors.addAll(cb.ws.doWait(cb, lastKnownSeqNo, add, update));
                // the ws until we release the cb lock!
                if (cb.completed) {
                    block = false;
                }
            }
        }
        if (block) {
            noDataSleep(cb);
            synchronized (cb) {
                if (!cb.completed) {
                    // don't wait if it completed right away
                    long timeout = getTimeoutMillis(req.getTimeout(), adminAllowed);
                    ZimbraLog.soap.trace("Suspending <WaitSetRequest> for %dms", timeout);
                    cb.continuationResume.suspendAndUndispatch(timeout);
                }
            }
        }
    }
    // if we got here, then we did *not* execute a jetty RetryContinuation,
    // soooo, we'll fall through and finish up at the bottom
    processCallback(resp, cb, waitSetId, lastKnownSeqNo, expand);
}
Also used : Continuation(org.eclipse.jetty.continuation.Continuation) WaitSetAccount(com.zimbra.cs.session.WaitSetAccount) ResumeContinuationListener(com.zimbra.cs.servlet.continuation.ResumeContinuationListener) HttpServletRequest(javax.servlet.http.HttpServletRequest) IdAndType(com.zimbra.soap.type.IdAndType) ZimbraSoapContext(com.zimbra.soap.ZimbraSoapContext) WaitSetCallback(com.zimbra.cs.session.WaitSetCallback)

Example 10 with Continuation

use of org.eclipse.jetty.continuation.Continuation in project zm-mailbox by Zimbra.

the class ZimbraQoSFilter method doFilter.

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    try {
        String user = extractUserId(request);
        int max = LC.servlet_max_concurrent_http_requests_per_account.intValue();
        if (user == null || max <= 0) {
            chain.doFilter(request, response);
            return;
        }
        Semaphore pass = passes.putIfAbsent(user, new Semaphore(max, true));
        if (pass == null) {
            pass = passes.get(user);
        }
        if (pass.tryAcquire(waitMs, TimeUnit.MILLISECONDS)) {
            try {
                chain.doFilter(request, response);
            } finally {
                pass.release();
            }
        } else {
            Continuation continuation = ContinuationSupport.getContinuation(request);
            HttpServletRequest hreq = (HttpServletRequest) request;
            ZimbraServlet.addRemoteIpToLoggingContext(hreq);
            ZimbraServlet.addUAToLoggingContext(hreq);
            ZimbraLog.misc.warn("Exceeded the max requests limit. Suspending " + continuation);
            ZimbraLog.clearContext();
            continuation.setTimeout(suspendMs);
            continuation.suspend();
            return;
        }
    } catch (InterruptedException e) {
        ((HttpServletResponse) response).sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
        return;
    }
}
Also used : HttpServletRequest(javax.servlet.http.HttpServletRequest) Continuation(org.eclipse.jetty.continuation.Continuation) Semaphore(java.util.concurrent.Semaphore)

Aggregations

Continuation (org.eclipse.jetty.continuation.Continuation)10 HttpServletRequest (javax.servlet.http.HttpServletRequest)6 ZimbraSoapContext (com.zimbra.soap.ZimbraSoapContext)3 Element (com.zimbra.common.soap.Element)2 ResumeContinuationListener (com.zimbra.cs.servlet.continuation.ResumeContinuationListener)2 WaitSetAccount (com.zimbra.cs.session.WaitSetAccount)2 WaitSetCallback (com.zimbra.cs.session.WaitSetCallback)2 IOException (java.io.IOException)2 ArtifactDownloadRequest (com.hubspot.singularity.s3.base.ArtifactDownloadRequest)1 ServiceException (com.zimbra.common.service.ServiceException)1 Mailbox (com.zimbra.cs.mailbox.Mailbox)1 AdminServiceException (com.zimbra.cs.service.admin.AdminServiceException)1 IdAndType (com.zimbra.soap.type.IdAndType)1 ByteArrayInputStream (java.io.ByteArrayInputStream)1 InputStream (java.io.InputStream)1 ArrayList (java.util.ArrayList)1 Semaphore (java.util.concurrent.Semaphore)1 TimeoutException (java.util.concurrent.TimeoutException)1 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)1 GZIPInputStream (java.util.zip.GZIPInputStream)1