Search in sources :

Example 1 with ResumeContinuationListener

use of com.zimbra.cs.servlet.continuation.ResumeContinuationListener in project zm-mailbox by Zimbra.

the class ZimbraSoapContext method beginWaitForNotifications.

public boolean beginWaitForNotifications(Continuation continuation, boolean includeDelegates) throws ServiceException {
    mWaitForNotifications = true;
    continuationResume = new ResumeContinuationListener(continuation);
    Session session = SessionCache.lookup(mSessionInfo.sessionId, mAuthTokenAccountId);
    if (!(session instanceof SoapSession))
        return false;
    SoapSession ss = (SoapSession) session;
    SoapSession.RegisterNotificationResult result = ss.registerNotificationConnection(mSessionInfo.getPushChannel(!includeDelegates));
    switch(result) {
        case NO_NOTIFY:
            return false;
        case DATA_READY:
            return false;
        case BLOCKING:
            return true;
        default:
            return false;
    }
}
Also used : SoapSession(com.zimbra.cs.session.SoapSession) ResumeContinuationListener(com.zimbra.cs.servlet.continuation.ResumeContinuationListener) SoapSession(com.zimbra.cs.session.SoapSession) Session(com.zimbra.cs.session.Session)

Example 2 with ResumeContinuationListener

use of com.zimbra.cs.servlet.continuation.ResumeContinuationListener in project zm-mailbox by Zimbra.

the class WaitSetRequest method staticHandle.

public static Element staticHandle(Element request, Map<String, Object> context, Element response, boolean adminAllowed) throws ServiceException {
    ZimbraSoapContext zsc = getZimbraSoapContext(context);
    HttpServletRequest servletRequest = (HttpServletRequest) context.get(SoapServlet.SERVLET_REQUEST);
    String waitSetId = request.getAttribute(MailConstants.A_WAITSET_ID);
    String lastKnownSeqNo = request.getAttribute(MailConstants.A_SEQ);
    boolean block = request.getAttributeBool(MailConstants.A_BLOCK, false);
    Callback cb = (Callback) servletRequest.getAttribute(VARS_ATTR_NAME);
    if (cb == null) {
        // Initial
        Continuation continuation = ContinuationSupport.getContinuation(servletRequest);
        cb = new Callback();
        cb.continuationResume = new ResumeContinuationListener(continuation);
        servletRequest.setAttribute(VARS_ATTR_NAME, cb);
        String defInterestStr = null;
        if (waitSetId.startsWith(WaitSetMgr.ALL_ACCOUNTS_ID_PREFIX)) {
            WaitSetMgr.checkRightForAllAccounts(zsc);
            // default interest types required for "All" waitsets
            defInterestStr = request.getAttribute(MailConstants.A_DEFTYPES);
            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, request.getOptionalElement(MailConstants.E_WAITSET_ADD), cb.ws.getDefaultInterest());
        List<WaitSetAccount> update = parseAddUpdateAccounts(zsc, request.getOptionalElement(MailConstants.E_WAITSET_UPDATE), cb.ws.getDefaultInterest());
        List<String> remove = parseRemoveAccounts(zsc, request.getOptionalElement(MailConstants.E_WAITSET_REMOVE));
        ///////////////////
        // workaround for 27480: load the mailboxes NOW, before we grab the waitset lock
        List<Mailbox> referencedMailboxes = new ArrayList<Mailbox>();
        for (WaitSetAccount acct : add) {
            try {
                Mailbox mbox = MailboxManager.getInstance().getMailboxByAccountId(acct.getAccountId(), MailboxManager.FetchMode.AUTOCREATE);
                referencedMailboxes.add(mbox);
            } catch (ServiceException e) {
                ZimbraLog.session.debug("Caught exception preloading mailbox for waitset", e);
            }
        }
        for (WaitSetAccount acct : update) {
            try {
                Mailbox mbox = MailboxManager.getInstance().getMailboxByAccountId(acct.getAccountId(), MailboxManager.FetchMode.AUTOCREATE);
                referencedMailboxes.add(mbox);
            } catch (ServiceException e) {
                ZimbraLog.session.debug("Caught exception preloading mailbox for waitset", e);
            }
        }
        // the server in a very fast loop (they should be using the 'block' mode)
        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) {
                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) {
            // bit.
            try {
                Thread.sleep(NODATA_SLEEP_TIME_MILLIS);
            } catch (InterruptedException ex) {
            }
            synchronized (cb) {
                if (!cb.completed) {
                    // don't wait if it completed right away
                    long timeout = getTimeoutMillis(request, adminAllowed);
                    if (ZimbraLog.soap.isTraceEnabled())
                        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
    // clear the
    cb.ws.doneWaiting();
    response.addAttribute(MailConstants.A_WAITSET_ID, waitSetId);
    if (cb.canceled) {
        response.addAttribute(MailConstants.A_CANCELED, true);
    } else if (cb.completed) {
        response.addAttribute(MailConstants.A_SEQ, cb.seqNo);
        for (String s : cb.signalledAccounts) {
            Element saElt = response.addElement(MailConstants.E_A);
            saElt.addAttribute(MailConstants.A_ID, s);
        }
    } else {
        // timed out....they should try again
        response.addAttribute(MailConstants.A_SEQ, lastKnownSeqNo);
    }
    encodeErrors(response, cb.errors);
    return response;
}
Also used : Continuation(org.eclipse.jetty.continuation.Continuation) WaitSetAccount(com.zimbra.cs.session.WaitSetAccount) Element(com.zimbra.common.soap.Element) ArrayList(java.util.ArrayList) ResumeContinuationListener(com.zimbra.cs.servlet.continuation.ResumeContinuationListener) HttpServletRequest(javax.servlet.http.HttpServletRequest) WaitSetCallback(com.zimbra.cs.session.WaitSetCallback) Mailbox(com.zimbra.cs.mailbox.Mailbox) ServiceException(com.zimbra.common.service.ServiceException) AdminServiceException(com.zimbra.cs.service.admin.AdminServiceException) ZimbraSoapContext(com.zimbra.soap.ZimbraSoapContext)

Aggregations

ResumeContinuationListener (com.zimbra.cs.servlet.continuation.ResumeContinuationListener)2 ServiceException (com.zimbra.common.service.ServiceException)1 Element (com.zimbra.common.soap.Element)1 Mailbox (com.zimbra.cs.mailbox.Mailbox)1 AdminServiceException (com.zimbra.cs.service.admin.AdminServiceException)1 Session (com.zimbra.cs.session.Session)1 SoapSession (com.zimbra.cs.session.SoapSession)1 WaitSetAccount (com.zimbra.cs.session.WaitSetAccount)1 WaitSetCallback (com.zimbra.cs.session.WaitSetCallback)1 ZimbraSoapContext (com.zimbra.soap.ZimbraSoapContext)1 ArrayList (java.util.ArrayList)1 HttpServletRequest (javax.servlet.http.HttpServletRequest)1 Continuation (org.eclipse.jetty.continuation.Continuation)1