public class AsyncContextImpl implements AsyncContext {
public static enum AsyncState {
- NOT_STARTED, STARTED, DISPATCHING, DISPATCHED, COMPLETING
+ NOT_STARTED, STARTED, DISPATCHING, DISPATCHED, COMPLETING, TIMING_OUT
}
protected static Log log = LogFactory.getLog(AsyncContextImpl.class);
}
public void doInternalDispatch() throws ServletException, IOException {
- if (this.state.compareAndSet(AsyncState.DISPATCHING, AsyncState.DISPATCHED)) {
+ if (this.state.compareAndSet(AsyncState.TIMING_OUT, AsyncState.DISPATCHED)) {
+ for (AsyncListenerWrapper listener : listeners) {
+ listener.fireOnTimeout();
+ }
+ } else if (this.state.compareAndSet(AsyncState.DISPATCHING, AsyncState.DISPATCHED)) {
if (this.dispatch!=null) {
try {
dispatch.run();
throw new IllegalStateException("Complete illegal. Invalid state:"+state.get());
}
}
+
+ public AsyncState getState() {
+ return state.get();
+ }
+
+ protected void setState(AsyncState st) {
+ state.set(st);
+ }
}
}
}
- public boolean asyncDispatch(org.apache.coyote.Request req,org.apache.coyote.Response res) throws Exception {
+ public boolean asyncDispatch(org.apache.coyote.Request req,org.apache.coyote.Response res, SocketStatus status) throws Exception {
Request request = (Request) req.getNote(ADAPTER_NOTES);
Response response = (Response) res.getNote(ADAPTER_NOTES);
request.setAttribute(Globals.DISPATCHER_TYPE_ATTR, DispatcherType.ASYNC);
// Calling the container
try {
+ if (status==SocketStatus.TIMEOUT) {
+ AsyncContextImpl asyncConImpl = (AsyncContextImpl)request.getAsyncContext();
+ //TODO SERVLET3 - async
+ //configure settings for timed out
+ asyncConImpl.setState(AsyncContextImpl.AsyncState.TIMING_OUT);
+ }
connector.getContainer().getPipeline().getFirst().invoke(request, response);
}catch (RuntimeException x) {
success = false;
public boolean event(Request req, Response res, SocketStatus status)
throws Exception;
- public boolean asyncDispatch(Request req,Response res) throws Exception;
+ public boolean asyncDispatch(Request req,Response res, SocketStatus status) throws Exception;
}
final NioEndpoint.KeyAttachment attach = (NioEndpoint.KeyAttachment)socket.getAttachment(false);
try {
rp.setStage(org.apache.coyote.Constants.STAGE_SERVICE);
- error = !adapter.asyncDispatch(request, response);
+ error = !adapter.asyncDispatch(request, response, status);
if ( !error ) {
if (attach != null) {
attach.setComet(comet);
error = false;
keepAlive = true;
comet = false;
+ async = false;
long soTimeout = endpoint.getSoTimeout();
int keepAliveTimeout = endpoint.getKeepAliveTimeout();
boolean recycle = true;
final KeyAttachment ka = (KeyAttachment)socket.getAttachment(false);
- while (!error && keepAlive && !comet) {
+ while (!error && keepAlive && !comet && !async) {
//always default to our soTimeout
ka.setTimeout(soTimeout);
// Parsing the request header
NioEndpoint.KeyAttachment attach = (NioEndpoint.KeyAttachment)socket.getAttachment(false);
long timeout = ((Long)param).longValue();
//if we are not piggy backing on a worker thread, set the timeout
- RequestInfo rp = request.getRequestProcessor();
- if ( rp.getStage() != org.apache.coyote.Constants.STAGE_SERVICE ) //async handling
- attach.setTimeout(timeout);
+ attach.setTimeout(timeout);
} else if (actionCode == ActionCode.ACTION_ASYNC_DISPATCH) {
RequestInfo rp = request.getRequestProcessor();
if ( rp.getStage() != org.apache.coyote.Constants.STAGE_SERVICE ) {//async handling
long nextTime = now+(timeout-delta);
nextExpiration = (nextTime < nextExpiration)?nextTime:nextExpiration;
}
+ }else if (ka.isAsync()) {
+ long delta = now - ka.getLastAccess();
+ long timeout = (ka.getTimeout()==-1)?((long) socketProperties.getSoTimeout()):(ka.getTimeout());
+ boolean isTimedout = delta > timeout;
+ if (isTimedout) {
+ processSocket(ka.getChannel(), SocketStatus.TIMEOUT, true);
+ }
}//end if
}catch ( CancelledKeyException ckx ) {
cancelledKey(key, SocketStatus.ERROR,false);