From 21b048b6f0bcdec7dad6cb69a29cadcb57729c48 Mon Sep 17 00:00:00 2001 From: fhanik Date: Wed, 24 Mar 2010 21:26:47 +0000 Subject: [PATCH] Add in a slightly different behavior for dispatch. dispatch() will return immediately, according to spec. But if dispatch is called from the tomcat worker thread, then the dispatch will not happen until the worker thread has backed out of the call. This prevents multiple threads being launched into the same request/response and causing potential concurrency issues. The Async state machine guarantees that multiple dispatch can not be called. git-svn-id: https://svn.apache.org/repos/asf/tomcat/trunk@927182 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/catalina/connector/CoyoteAdapter.java | 72 ++++++++++++++-------- java/org/apache/catalina/connector/Request.java | 9 +++ .../apache/catalina/core/StandardWrapperValve.java | 4 +- .../apache/coyote/http11/Http11NioProcessor.java | 4 +- java/org/apache/coyote/http11/Http11Processor.java | 4 +- 5 files changed, 63 insertions(+), 30 deletions(-) diff --git a/java/org/apache/catalina/connector/CoyoteAdapter.java b/java/org/apache/catalina/connector/CoyoteAdapter.java index 188694633..d8e8d2226 100644 --- a/java/org/apache/catalina/connector/CoyoteAdapter.java +++ b/java/org/apache/catalina/connector/CoyoteAdapter.java @@ -270,26 +270,48 @@ public class CoyoteAdapter implements Adapter { boolean success = true; try { - // Calling the container - try { - if (status==SocketStatus.TIMEOUT) { - AsyncContextImpl asyncConImpl = (AsyncContextImpl)request.getAsyncContext(); - //TODO SERVLET3 - async - //configure settings for timed out - asyncConImpl.setTimeoutState(); - } - if (status==SocketStatus.ERROR || status==SocketStatus.STOP || status==SocketStatus.DISCONNECT) { - AsyncContextImpl asyncConImpl = (AsyncContextImpl)request.getAsyncContext(); + if (status==SocketStatus.TIMEOUT) { + AsyncContextImpl asyncConImpl = (AsyncContextImpl)request.getAsyncContext(); + //TODO SERVLET3 - async + //configure settings for timed out + asyncConImpl.setTimeoutState(); + } + if (status==SocketStatus.ERROR || status==SocketStatus.STOP || status==SocketStatus.DISCONNECT) { + AsyncContextImpl asyncConImpl = (AsyncContextImpl)request.getAsyncContext(); + //TODO SERVLET3 - async + //configure settings for timed out + asyncConImpl.setErrorState(); + } + while (success) { + AsyncContextImpl impl = (AsyncContextImpl)request.getAsyncContext(); + // Calling the container + if (impl.getState()==AsyncContextImpl.AsyncState.DISPATCHED) { + // Calling the container + try { + impl.complete(); + connector.getContainer().getPipeline().getFirst().invoke(request, response); + } finally { + success = false; + } + } else if (impl.getState()==AsyncContextImpl.AsyncState.STARTED){ //TODO SERVLET3 - async - //configure settings for timed out - asyncConImpl.setErrorState(); + res.action(ActionCode.ACTION_ASYNC_START, request.getAsyncContext()); + async = true; + break; + } else if (impl.getState()==AsyncContextImpl.AsyncState.NOT_STARTED){ + //TODO SERVLET3 - async + async = false; + break; + } else { + try { + connector.getContainer().getPipeline().getFirst().invoke(request, response); + }catch (RuntimeException x) { + success = false; + } finally { + } } - connector.getContainer().getPipeline().getFirst().invoke(request, response); - }catch (RuntimeException x) { - success = false; - } finally { } - + if (request.isComet()) { if (!response.isClosed() && !response.isError()) { if (request.getAvailable() || (request.getContentLength() > 0 && (!request.isParametersParsed()))) { @@ -308,12 +330,7 @@ public class CoyoteAdapter implements Adapter { request.setFilterChain(null); } } - - if (request.isAsyncStarted()) { - //TODO SERVLET3 - async - res.action(ActionCode.ACTION_ASYNC_START, request.getAsyncContext()); - async = true; - } else if (!comet) { + if (!async && !comet) { response.finishResponse(); req.action(ActionCode.ACTION_POST_REQUEST , null); } @@ -410,11 +427,16 @@ public class CoyoteAdapter implements Adapter { } } - + AsyncContextImpl asyncConImpl = (AsyncContextImpl)request.getAsyncContext(); if (request.isAsyncStarted()) { - //TODO SERVLET3 - async res.action(ActionCode.ACTION_ASYNC_START, request.getAsyncContext()); async = true; + } else if (asyncConImpl!=null && + (asyncConImpl.getState()==AsyncContextImpl.AsyncState.DISPATCHING || + asyncConImpl.getState()==AsyncContextImpl.AsyncState.COMPLETING || + asyncConImpl.getState()==AsyncContextImpl.AsyncState.TIMING_OUT || + asyncConImpl.getState()==AsyncContextImpl.AsyncState.ERROR_DISPATCHING)) { + asyncDispatch(req, res, SocketStatus.OPEN); } else if (!comet) { response.finishResponse(); req.action(ActionCode.ACTION_POST_REQUEST , null); diff --git a/java/org/apache/catalina/connector/Request.java b/java/org/apache/catalina/connector/Request.java index 65d4091e5..36c15c35f 100644 --- a/java/org/apache/catalina/connector/Request.java +++ b/java/org/apache/catalina/connector/Request.java @@ -1539,6 +1539,15 @@ public class Request else return asyncContext.isStarted(); } + public boolean isAsyncDispatching() { + if (asyncContext==null) return false; + else return (asyncContext.getState()==AsyncContextImpl.AsyncState.DISPATCHING || + asyncContext.getState()==AsyncContextImpl.AsyncState.TIMING_OUT || + asyncContext.getState()==AsyncContextImpl.AsyncState.STARTED || + asyncContext.getState()==AsyncContextImpl.AsyncState.ERROR_DISPATCHING || + asyncContext.getState()==AsyncContextImpl.AsyncState.COMPLETING); + } + public boolean isAsyncSupported() { // TODO SERVLET3 - async if (this.asyncSupported==null) { diff --git a/java/org/apache/catalina/core/StandardWrapperValve.java b/java/org/apache/catalina/core/StandardWrapperValve.java index 01fd140ba..6d11baccc 100644 --- a/java/org/apache/catalina/core/StandardWrapperValve.java +++ b/java/org/apache/catalina/core/StandardWrapperValve.java @@ -217,7 +217,7 @@ final class StandardWrapperValve if (context.getSwallowOutput()) { try { SystemLogHandler.startCapture(); - if (request.isAsyncStarted()) { + if (request.isAsyncDispatching()) { //TODO SERVLET3 - async ((AsyncContextImpl)request.getAsyncContext()).doInternalDispatch(); } else if (comet) { @@ -234,7 +234,7 @@ final class StandardWrapperValve } } } else { - if (request.isAsyncStarted()) { + if (request.isAsyncDispatching()) { //TODO SERVLET3 - async ((AsyncContextImpl)request.getAsyncContext()).doInternalDispatch(); } else if (comet) { diff --git a/java/org/apache/coyote/http11/Http11NioProcessor.java b/java/org/apache/coyote/http11/Http11NioProcessor.java index 5c313728e..b27a00561 100644 --- a/java/org/apache/coyote/http11/Http11NioProcessor.java +++ b/java/org/apache/coyote/http11/Http11NioProcessor.java @@ -777,6 +777,8 @@ public class Http11NioProcessor extends AbstractHttp11Processor implements Actio if ( rp.getStage() != org.apache.coyote.Constants.STAGE_SERVICE ) { //async handling dispatch.set(true); endpoint.processSocket(this.socket, SocketStatus.STOP, true); + } else { + dispatch.set(true); } } else if (actionCode == ActionCode.ACTION_ASYNC_SETTIMEOUT) { //TODO SERVLET3 - async @@ -793,7 +795,7 @@ public class Http11NioProcessor extends AbstractHttp11Processor implements Actio endpoint.processSocket(this.socket, SocketStatus.OPEN, true); dispatch.set(true); } else { - + dispatch.set(true); } } } diff --git a/java/org/apache/coyote/http11/Http11Processor.java b/java/org/apache/coyote/http11/Http11Processor.java index af76297d4..b195dd21d 100644 --- a/java/org/apache/coyote/http11/Http11Processor.java +++ b/java/org/apache/coyote/http11/Http11Processor.java @@ -621,7 +621,7 @@ public class Http11Processor extends AbstractHttp11Processor implements ActionHo dispatch.set(true); endpoint.processSocket(this.socket, SocketStatus.STOP); } else { - //TODO SERVLET3 async=false + dispatch.set(true); } } else if (actionCode == ActionCode.ACTION_ASYNC_SETTIMEOUT) { //TODO SERVLET3 - async @@ -636,7 +636,7 @@ public class Http11Processor extends AbstractHttp11Processor implements ActionHo endpoint.processSocket(this.socket, SocketStatus.OPEN); dispatch.set(true); } else { - //TODO SERVLET3 - do nothing? + dispatch.set(true); } } -- 2.11.0