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