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;
}
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;
}
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;
}
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);
}
}
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));
}
Aggregations