import java.io.IOException;
import javax.servlet.ServletException;
+import javax.servlet.Servlet;
/**
* This interface should be implemented by servlets which would like to handle
* Note: When this interface is implemented, the service method of the servlet will
* never be called, and will be replaced with a begin event.
*/
-public interface CometProcessor {
+public interface CometProcessor extends Servlet{
/**
* Process the given Comet event.
import org.apache.catalina.CometEvent;
import org.apache.catalina.util.StringManager;
+import org.apache.coyote.ActionCode;
public class CometEventImpl implements CometEvent {
if (request == null) {
throw new IllegalStateException(sm.getString("cometEvent.nullRequest"));
}
+ boolean iscomet = request.isComet();
request.setComet(false);
response.finishResponse();
+ if (iscomet) request.cometClose();
}
public EventSubType getEventSubType() {
UnsupportedOperationException {
if (request.getAttribute("org.apache.tomcat.comet.timeout.support") == Boolean.TRUE) {
request.setAttribute("org.apache.tomcat.comet.timeout", new Integer(timeout));
+ if (request.isComet()) request.setCometTimeout((long)timeout);
} else {
throw new UnsupportedOperationException();
}
return (inputBuffer.available() > 0);
}
+ public void cometClose() {
+ coyoteRequest.action(ActionCode.ACTION_COMET_CLOSE,getEvent());
+ }
+
+ public void setCometTimeout(long timeout) {
+ coyoteRequest.action(ActionCode.ACTION_COMET_SETTIMEOUT,new Long(timeout));
+ }
// ------------------------------------------------------ Protected Methods
/**
- * Callback for begin Comet processing
+ * Callback for end Comet processing
*/
public static final ActionCode ACTION_COMET_END = new ActionCode(22);
*/
public static final ActionCode ACTION_AVAILABLE = new ActionCode(23);
+ /**
+ * Callback for an asynchronous close of the Comet event
+ */
+ public static final ActionCode ACTION_COMET_CLOSE = new ActionCode(24);
+ /**
+ * Callback for setting the timeout asynchronously
+ */
+ public static final ActionCode ACTION_COMET_SETTIMEOUT = new ActionCode(25);
+
// ----------------------------------------------------------- Constructors
int code;
comet = true;
} else if (actionCode == ActionCode.ACTION_COMET_END) {
comet = false;
+ } else if (actionCode == ActionCode.ACTION_COMET_CLOSE) {
+ //no op
+ } else if (actionCode == ActionCode.ACTION_COMET_SETTIMEOUT) {
+ //no op
}
}
return SocketState.CLOSED;
} else if (!comet) {
recycle();
- return SocketState.OPEN;
+ //pay attention to the keep alive flag set in process()
+ return (keepAlive)?SocketState.OPEN:SocketState.CLOSED;
} else {
return SocketState.LONG;
}
comet = true;
} else if (actionCode == ActionCode.ACTION_COMET_END) {
comet = false;
+ } else if (actionCode == ActionCode.ACTION_COMET_CLOSE) {
+ NioEndpoint.KeyAttachment attach = (NioEndpoint.KeyAttachment)socket.getAttachment(false);
+ attach.setCometOps(NioEndpoint.OP_CALLBACK);
+ //notify poller if not on a tomcat thread
+ RequestInfo rp = request.getRequestProcessor();
+ if ( rp.getStage() != org.apache.coyote.Constants.STAGE_SERVICE ) //async handling
+ socket.getPoller().cometInterest(socket);
+ } else if (actionCode == ActionCode.ACTION_COMET_SETTIMEOUT) {
+ if (param==null) return;
+ 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);
}
}
protected void reg(SelectionKey sk, KeyAttachment attachment, int intops) {
sk.interestOps(intops);
attachment.interestOps(intops);
+ attachment.setCometOps(intops);
}
protected void timeout(int keyCount, boolean hasEvents) {
} else if ( ka.getError() ) {
cancelledKey(key, SocketStatus.ERROR,true);
} else if (ka.getComet() && ka.getCometNotify() ) {
+ ka.setCometNotify(false);
reg(key,ka,0);//avoid multiple calls, this gets reregistered after invokation
//if (!processSocket(ka.getChannel(), SocketStatus.OPEN_CALLBACK)) processSocket(ka.getChannel(), SocketStatus.DISCONNECT);
if (!processSocket(ka.getChannel(), SocketStatus.OPEN)) processSocket(ka.getChannel(), SocketStatus.DISCONNECT);