Search in sources :

Example 1 with WaitSetAccount

use of com.zimbra.cs.session.WaitSetAccount in project zm-mailbox by Zimbra.

the class CreateWaitSet method staticHandle.

public static Element staticHandle(DocumentHandler handler, Element request, Map<String, Object> context, Element response) throws ServiceException {
    ZimbraSoapContext zsc = getZimbraSoapContext(context);
    String defInterestStr = request.getAttribute(MailConstants.A_DEFTYPES);
    Set<MailItem.Type> defaultInterests = WaitSetRequest.parseInterestStr(defInterestStr, EnumSet.noneOf(MailItem.Type.class));
    boolean adminAllowed = zsc.getAuthToken().isAdmin();
    boolean allAccts = request.getAttributeBool(MailConstants.A_ALL_ACCOUNTS, false);
    if (allAccts) {
        WaitSetMgr.checkRightForAllAccounts(zsc);
    }
    List<WaitSetAccount> add = WaitSetRequest.parseAddUpdateAccounts(zsc, request.getOptionalElement(MailConstants.E_WAITSET_ADD), defaultInterests);
    // workaround for 27480: load the mailboxes NOW, before we grab the waitset lock
    List<Mailbox> referencedMailboxes = new ArrayList<Mailbox>();
    for (WaitSetAccount acct : add) {
        try {
            MailboxManager.FetchMode fetchMode = MailboxManager.FetchMode.AUTOCREATE;
            Mailbox mbox = MailboxManager.getInstance().getMailboxByAccountId(acct.getAccountId(), fetchMode);
            referencedMailboxes.add(mbox);
        } catch (ServiceException e) {
            ZimbraLog.session.debug("Caught exception preloading mailbox for waitset", e);
        }
    }
    Pair<String, List<WaitSetError>> result = WaitSetMgr.create(zsc.getRequestedAccountId(), adminAllowed, defaultInterests, allAccts, add);
    String wsId = result.getFirst();
    List<WaitSetError> errors = result.getSecond();
    response.addAttribute(MailConstants.A_WAITSET_ID, wsId);
    response.addAttribute(MailConstants.A_DEFTYPES, WaitSetRequest.interestToStr(defaultInterests));
    response.addAttribute(MailConstants.A_SEQ, 0);
    WaitSetRequest.encodeErrors(response, errors);
    return response;
}
Also used : WaitSetAccount(com.zimbra.cs.session.WaitSetAccount) ArrayList(java.util.ArrayList) WaitSetError(com.zimbra.cs.session.WaitSetError) MailboxManager(com.zimbra.cs.mailbox.MailboxManager) Mailbox(com.zimbra.cs.mailbox.Mailbox) ServiceException(com.zimbra.common.service.ServiceException) ZimbraSoapContext(com.zimbra.soap.ZimbraSoapContext) ArrayList(java.util.ArrayList) List(java.util.List)

Example 2 with WaitSetAccount

use of com.zimbra.cs.session.WaitSetAccount 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)

Example 3 with WaitSetAccount

use of com.zimbra.cs.session.WaitSetAccount in project zm-mailbox by Zimbra.

the class WaitSetRequest method parseAddUpdateAccounts.

/**
     * @param allowedAccountIds NULL means "all allowed" (admin)
     */
static List<WaitSetAccount> parseAddUpdateAccounts(ZimbraSoapContext zsc, Element elt, Set<MailItem.Type> defaultInterest) throws ServiceException {
    List<WaitSetAccount> toRet = new ArrayList<WaitSetAccount>();
    if (elt != null) {
        for (Iterator<Element> iter = elt.elementIterator(MailConstants.E_A); iter.hasNext(); ) {
            Element a = iter.next();
            String id;
            String name = a.getAttribute(MailConstants.A_NAME, null);
            if (name != null) {
                Account acct = Provisioning.getInstance().get(AccountBy.name, name);
                if (acct != null) {
                    id = acct.getId();
                } else {
                    WaitSetError err = new WaitSetError(name, WaitSetError.Type.NO_SUCH_ACCOUNT);
                    continue;
                }
            } else {
                id = a.getAttribute(MailConstants.A_ID);
            }
            WaitSetMgr.checkRightForAdditionalAccount(id, zsc);
            String tokenStr = a.getAttribute(MailConstants.A_TOKEN, null);
            SyncToken token = tokenStr != null ? new SyncToken(tokenStr) : null;
            Set<MailItem.Type> interests = parseInterestStr(a.getAttribute(MailConstants.A_TYPES, null), defaultInterest);
            toRet.add(new WaitSetAccount(id, token, interests));
        }
    }
    return toRet;
}
Also used : WaitSetAccount(com.zimbra.cs.session.WaitSetAccount) Account(com.zimbra.cs.account.Account) SyncToken(com.zimbra.cs.service.util.SyncToken) WaitSetAccount(com.zimbra.cs.session.WaitSetAccount) Element(com.zimbra.common.soap.Element) ArrayList(java.util.ArrayList) WaitSetError(com.zimbra.cs.session.WaitSetError)

Example 4 with WaitSetAccount

use of com.zimbra.cs.session.WaitSetAccount in project zm-mailbox by Zimbra.

the class TestWaitSet method runMeFirst.

private void runMeFirst() throws Exception {
    String waitSetId;
    List<WaitSetError> errors;
    {
        Account user1Acct = TestUtil.getAccount(USER_1_NAME);
        List<WaitSetAccount> add = new ArrayList<WaitSetAccount>();
        add.add(new WaitSetAccount(user1Acct.getId(), null, TypeEnum.m.getTypes(), null));
        Pair<String, List<WaitSetError>> result = WaitSetMgr.create(FAKE_ACCOUNT_ID, true, TypeEnum.m.getTypes(), false, add);
        waitSetId = result.getFirst();
        errors = result.getSecond();
    }
    try {
        String curSeqNo = "0";
        assertEquals("Expecting sequence to be 0 when the test starts", 0, errors.size());
        {
            // waitset shouldn't signal until message added to a mailbox
            WaitSetCallback cb = new WaitSetCallback();
            // wait shouldn't find anything yet
            IWaitSet ws = WaitSetMgr.lookup(waitSetId);
            errors = ws.doWait(cb, "0", null, null);
            assertEquals("Expecting sequence to be 0 during first wait", 0, errors.size());
            synchronized (cb) {
                assertEquals("Callback should not be completed yet", false, cb.completed);
            }
            // inserting a message to existing account should trigger waitset
            String sender = TestUtil.getAddress(USER_1_NAME);
            String recipient = TestUtil.getAddress(USER_1_NAME);
            String subject = "testWaitSet 1";
            TestUtil.addMessageLmtp(subject, recipient, sender);
            try {
                Thread.sleep(500);
            } catch (Exception e) {
            }
            synchronized (cb) {
                assertEquals("callback should be completed now", true, cb.completed);
            }
            curSeqNo = cb.seqNo;
        }
        {
            // waitset should pick up added user
            WaitSetCallback cb = new WaitSetCallback();
            IWaitSet ws = WaitSetMgr.lookup(waitSetId);
            // create a new account, shouldn't trigger waitset
            Account user2Acct = TestUtil.getAccount(USER_2_NAME);
            List<WaitSetAccount> add2 = new ArrayList<WaitSetAccount>();
            add2.add(new WaitSetAccount(user2Acct.getId(), null, TypeEnum.m.getTypes(), null));
            errors = ws.doWait(cb, curSeqNo, add2, null);
            // wait shouldn't find anything yet
            assertEquals("Should have no errors", 0, errors.size());
            synchronized (cb) {
                assertEquals("Callback should not be completed before it is triggered by the second account", false, cb.completed);
            }
            // adding a message to the new account SHOULD trigger waitset
            String sender = TestUtil.getAddress(WS_USER_NAME);
            String recipient = TestUtil.getAddress(USER_2_NAME);
            String subject = "testWaitSet 3";
            TestUtil.addMessageLmtp(subject, recipient, sender);
            try {
                Thread.sleep(500);
            } catch (Exception e) {
            }
            synchronized (cb) {
                assertEquals("Callback should be completed after it is triggered by the second account", true, cb.completed);
            }
            curSeqNo = cb.seqNo;
        }
    } finally {
        WaitSetMgr.destroy(null, FAKE_ACCOUNT_ID, waitSetId);
    }
}
Also used : Account(com.zimbra.cs.account.Account) WaitSetAccount(com.zimbra.cs.session.WaitSetAccount) IWaitSet(com.zimbra.cs.session.IWaitSet) WaitSetAccount(com.zimbra.cs.session.WaitSetAccount) WaitSetError(com.zimbra.cs.session.WaitSetError) ArrayList(java.util.ArrayList) List(java.util.List) WaitSetCallback(com.zimbra.cs.session.WaitSetCallback) Pair(com.zimbra.common.util.Pair)

Example 5 with WaitSetAccount

use of com.zimbra.cs.session.WaitSetAccount in project zm-mailbox by Zimbra.

the class CreateWaitSet method staticHandle.

public static void staticHandle(DocumentHandler handler, CreateWaitSetReq request, Map<String, Object> context, CreateWaitSetResp response) throws ServiceException {
    ZimbraSoapContext zsc = getZimbraSoapContext(context);
    String defInterestStr = request.getDefaultInterests();
    Set<MailItem.Type> defaultInterests = WaitSetRequest.parseInterestStr(defInterestStr, EnumSet.noneOf(MailItem.Type.class));
    boolean adminAllowed = zsc.getAuthToken().isAdmin();
    boolean allAccts = request.getAllAccounts();
    if (allAccts) {
        WaitSetMgr.checkRightForAllAccounts(zsc);
    }
    List<WaitSetAccount> add = WaitSetRequest.parseAddUpdateAccounts(zsc, request.getAccounts(), defaultInterests);
    // workaround for 27480: load the mailboxes NOW, before we grab the waitset lock
    List<Mailbox> referencedMailboxes = new ArrayList<Mailbox>();
    for (WaitSetAccount acct : add) {
        try {
            MailboxManager.FetchMode fetchMode = MailboxManager.FetchMode.AUTOCREATE;
            Mailbox mbox = MailboxManager.getInstance().getMailboxByAccountId(acct.getAccountId(), fetchMode);
            referencedMailboxes.add(mbox);
        } catch (ServiceException e) {
            ZimbraLog.session.debug("Caught exception preloading mailbox for waitset", e);
        }
    }
    Pair<String, List<WaitSetError>> result = WaitSetMgr.create(zsc.getRequestedAccountId(), adminAllowed, defaultInterests, allAccts, add);
    String wsId = result.getFirst();
    List<WaitSetError> errors = result.getSecond();
    response.setWaitSetId(wsId);
    response.setDefaultInterests(WaitSetRequest.interestToStr(defaultInterests));
    response.setSequence(0);
    response.setErrors(WaitSetRequest.encodeErrors(errors));
}
Also used : WaitSetAccount(com.zimbra.cs.session.WaitSetAccount) ArrayList(java.util.ArrayList) WaitSetError(com.zimbra.cs.session.WaitSetError) MailboxManager(com.zimbra.cs.mailbox.MailboxManager) Mailbox(com.zimbra.cs.mailbox.Mailbox) ServiceException(com.zimbra.common.service.ServiceException) ZimbraSoapContext(com.zimbra.soap.ZimbraSoapContext) ArrayList(java.util.ArrayList) List(java.util.List)

Aggregations

WaitSetAccount (com.zimbra.cs.session.WaitSetAccount)7 ArrayList (java.util.ArrayList)6 WaitSetError (com.zimbra.cs.session.WaitSetError)5 ZimbraSoapContext (com.zimbra.soap.ZimbraSoapContext)4 ServiceException (com.zimbra.common.service.ServiceException)3 Account (com.zimbra.cs.account.Account)3 Mailbox (com.zimbra.cs.mailbox.Mailbox)3 WaitSetCallback (com.zimbra.cs.session.WaitSetCallback)3 List (java.util.List)3 Element (com.zimbra.common.soap.Element)2 MailboxManager (com.zimbra.cs.mailbox.MailboxManager)2 SyncToken (com.zimbra.cs.service.util.SyncToken)2 ResumeContinuationListener (com.zimbra.cs.servlet.continuation.ResumeContinuationListener)2 IdAndType (com.zimbra.soap.type.IdAndType)2 HttpServletRequest (javax.servlet.http.HttpServletRequest)2 Continuation (org.eclipse.jetty.continuation.Continuation)2 Pair (com.zimbra.common.util.Pair)1 AdminServiceException (com.zimbra.cs.service.admin.AdminServiceException)1 IWaitSet (com.zimbra.cs.session.IWaitSet)1 WaitSetAddSpec (com.zimbra.soap.type.WaitSetAddSpec)1