Author: remm Date: Thu May 18 11:29:07 2006 New Revision: 407605 URL: http://svn.apache.org/viewvc?rev=407605&view=rev Log: - Ok, it seems to work at least a little bit (hopefully, nobody tried it before this). Overall, the changes are fairly limited. - In the end, I prefer adding a new method in Adapter, although it is easy to change back. - I'll try to add the examples webapp back, and add the obligatory chat servlet (so lame ...).
Modified: tomcat/tc6.0.x/trunk/java/org/apache/catalina/CometProcessor.java tomcat/tc6.0.x/trunk/java/org/apache/catalina/connector/CoyoteAdapter.java tomcat/tc6.0.x/trunk/java/org/apache/catalina/servlets/CometServlet.java tomcat/tc6.0.x/trunk/java/org/apache/coyote/Adapter.java tomcat/tc6.0.x/trunk/java/org/apache/coyote/http11/Http11AprProcessor.java tomcat/tc6.0.x/trunk/java/org/apache/coyote/http11/Http11AprProtocol.java tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java Modified: tomcat/tc6.0.x/trunk/java/org/apache/catalina/CometProcessor.java URL: http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/catalina/CometProcessor.java?rev=407605&r1=407604&r2=407605&view=diff ============================================================================== --- tomcat/tc6.0.x/trunk/java/org/apache/catalina/CometProcessor.java (original) +++ tomcat/tc6.0.x/trunk/java/org/apache/catalina/CometProcessor.java Thu May 18 11:29:07 2006 @@ -1,3 +1,20 @@ +/* + * Copyright 2006 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + package org.apache.catalina; import java.io.IOException; @@ -8,13 +25,56 @@ public interface CometProcessor { + /** + * Begin will be called by the main service method of the servlet at the beginning + * of the processing of the connection. It can be used to initialize any relevant + * fields using the request and response objects. + * + * @param request + * @param response + * @throws IOException + * @throws ServletException + */ public void begin(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException; + + /** + * End may be called to end the processing of the request. Fields that have + * been initialized in the begin method should be reset. + * + * @param request + * @param response + * @throws IOException + * @throws ServletException + */ public void end(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException; + /** + * Error will be called by the container in the case where an IO exception + * or a similar unrecoverable error occurs on the connection. Fields that have + * been initialized in the begin method should be reset. + * + * @param request + * @param response + * @throws IOException + * @throws ServletException + */ public void error(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException; + + /** + * This indicates that input data is available, and that one read can be made + * without blocking. The available and ready methods of the InputStream or + * Reader may be used to determine if there is a risk of blocking: the servlet + * should read while data is reported available, and can make one additional read + * without blocking. + * + * @param request + * @param response + * @throws IOException + * @throws ServletException + */ public void read(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException; Modified: tomcat/tc6.0.x/trunk/java/org/apache/catalina/connector/CoyoteAdapter.java URL: http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/catalina/connector/CoyoteAdapter.java?rev=407605&r1=407604&r2=407605&view=diff ============================================================================== --- tomcat/tc6.0.x/trunk/java/org/apache/catalina/connector/CoyoteAdapter.java (original) +++ tomcat/tc6.0.x/trunk/java/org/apache/catalina/connector/CoyoteAdapter.java Thu May 18 11:29:07 2006 @@ -103,6 +103,56 @@ // -------------------------------------------------------- Adapter Methods + + /** + * Event method. + * + * @return false to indicate an error, expected or not + */ + public boolean event(org.apache.coyote.Request req, + org.apache.coyote.Response res, boolean error) { + + Request request = (Request) req.getNote(ADAPTER_NOTES); + Response response = (Response) res.getNote(ADAPTER_NOTES); + + if (request.getWrapper() != null) { + CometProcessor servlet = null; + try { + servlet = (CometProcessor) request.getWrapper().allocate(); + } catch (Throwable t) { + log.error(sm.getString("coyoteAdapter.service"), t); + request.removeAttribute("org.apache.tomcat.comet"); + return false; + } + try { + if (error) { + servlet.error(request.getRequest(), response.getResponse()); + } else { + servlet.read(request.getRequest(), response.getResponse()); + } + return (!error); + } catch (Throwable t) { + if (!(t instanceof IOException)) { + log.error(sm.getString("coyoteAdapter.service"), t); + } + request.removeAttribute("org.apache.tomcat.comet"); + try { + servlet.error(request.getRequest(), response.getResponse()); + } catch (Throwable th) { + log.error(sm.getString("coyoteAdapter.service"), th); + } + return false; + } finally { + // Recycle the wrapper request and response + if (request.getAttribute("org.apache.tomcat.comet") == null) { + request.recycle(); + response.recycle(); + } + } + } + return true; + } + /** * Service method. @@ -136,29 +186,6 @@ } - // Comet processing - if (request.getWrapper() != null - && request.getWrapper() instanceof CometProcessor) { - try { - if (request.getAttribute("org.apache.tomcat.comet.error") != null) { - ((CometProcessor) request.getWrapper()).error(request.getRequest(), response.getResponse()); - } else { - ((CometProcessor) request.getWrapper()).read(request.getRequest(), response.getResponse()); - } - } catch (IOException e) { - ; - } catch (Throwable t) { - log.error(sm.getString("coyoteAdapter.service"), t); - } finally { - // Recycle the wrapper request and response - if (request.getAttribute("org.apache.tomcat.comet") == null) { - request.recycle(); - response.recycle(); - } - } - return; - } - if (connector.getXpoweredBy()) { response.addHeader("X-Powered-By", "Servlet/2.5"); } @@ -174,9 +201,8 @@ connector.getContainer().getPipeline().getFirst().invoke(request, response); } - if (request.getAttribute("org.apache.tomcat.comet.support") == Boolean.TRUE - && request.getWrapper() instanceof CometProcessor) { - request.setAttribute("org.apache.tomcat.comet", Boolean.TRUE); + if (request.getAttribute("org.apache.tomcat.comet") == Boolean.TRUE + && request.getWrapper().allocate() instanceof CometProcessor) { comet = true; } Modified: tomcat/tc6.0.x/trunk/java/org/apache/catalina/servlets/CometServlet.java URL: http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/catalina/servlets/CometServlet.java?rev=407605&r1=407604&r2=407605&view=diff ============================================================================== --- tomcat/tc6.0.x/trunk/java/org/apache/catalina/servlets/CometServlet.java (original) +++ tomcat/tc6.0.x/trunk/java/org/apache/catalina/servlets/CometServlet.java Thu May 18 11:29:07 2006 @@ -21,8 +21,6 @@ import java.io.IOException; import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -38,7 +36,7 @@ public void begin(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { - + request.setAttribute("org.apache.tomcat.comet", Boolean.TRUE); } public void end(HttpServletRequest request, HttpServletResponse response) Modified: tomcat/tc6.0.x/trunk/java/org/apache/coyote/Adapter.java URL: http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/coyote/Adapter.java?rev=407605&r1=407604&r2=407605&view=diff ============================================================================== --- tomcat/tc6.0.x/trunk/java/org/apache/coyote/Adapter.java (original) +++ tomcat/tc6.0.x/trunk/java/org/apache/coyote/Adapter.java Thu May 18 11:29:07 2006 @@ -45,5 +45,7 @@ public void service(Request req, Response res) throws Exception; + public boolean event(Request req, Response res, boolean error) + throws Exception; } Modified: tomcat/tc6.0.x/trunk/java/org/apache/coyote/http11/Http11AprProcessor.java URL: http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/coyote/http11/Http11AprProcessor.java?rev=407605&r1=407604&r2=407605&view=diff ============================================================================== --- tomcat/tc6.0.x/trunk/java/org/apache/coyote/http11/Http11AprProcessor.java (original) +++ tomcat/tc6.0.x/trunk/java/org/apache/coyote/http11/Http11AprProcessor.java Thu May 18 11:29:07 2006 @@ -743,15 +743,9 @@ try { rp.setStage(org.apache.coyote.Constants.STAGE_SERVICE); - if (error) { - request.setAttribute("org.apache.tomcat.comet.error", Boolean.TRUE); - } - // FIXME: It is also possible to add a new "event" method in the adapter - // or something similar - adapter.service(request, response); + error = !adapter.event(request, response, error); if (request.getAttribute("org.apache.tomcat.comet") == null) { comet = false; - endpoint.getCometPoller().remove(socket); } } catch (InterruptedIOException e) { error = true; @@ -772,6 +766,7 @@ endpoint.getPoller().add(socket); return SocketState.OPEN; } else { + endpoint.getCometPoller().add(socket); return SocketState.LONG; } } @@ -815,7 +810,7 @@ boolean keptAlive = false; boolean openSocket = false; - while (!error && keepAlive) { + while (!error && keepAlive && !comet) { // Parsing the request header try { @@ -927,7 +922,6 @@ recycle(); return SocketState.CLOSED; } else { - endpoint.getCometPoller().add(socket); return SocketState.LONG; } } else { Modified: tomcat/tc6.0.x/trunk/java/org/apache/coyote/http11/Http11AprProtocol.java URL: http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/coyote/http11/Http11AprProtocol.java?rev=407605&r1=407604&r2=407605&view=diff ============================================================================== --- tomcat/tc6.0.x/trunk/java/org/apache/coyote/http11/Http11AprProtocol.java (original) +++ tomcat/tc6.0.x/trunk/java/org/apache/coyote/http11/Http11AprProtocol.java Thu May 18 11:29:07 2006 @@ -617,6 +617,7 @@ public SocketState event(long socket, boolean error) { Http11AprProcessor result = connections.get(socket); + SocketState state = SocketState.CLOSED; if (result != null) { boolean recycle = error; @@ -708,10 +709,11 @@ // processor. connections.put(socket, processor); localProcessor.set(null); + proto.ep.getCometPoller().add(socket); } return state; - } catch(java.net.SocketException e) { + } catch (java.net.SocketException e) { // SocketExceptions are normal Http11AprProtocol.log.debug (sm.getString Modified: tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java URL: http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java?rev=407605&r1=407604&r2=407605&view=diff ============================================================================== --- tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java (original) +++ tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java Thu May 18 11:29:07 2006 @@ -796,6 +796,10 @@ pollers[i].destroy(); } pollers = null; + for (int i = 0; i < cometPollers.length; i++) { + cometPollers[i].destroy(); + } + cometPollers = null; if (useSendfile) { for (int i = 0; i < sendfiles.length; i++) { sendfiles[i].destroy(); @@ -1107,8 +1111,6 @@ protected long[] addS; protected int addCount = 0; - protected long[] removeS; - protected int removeCount = 0; protected boolean comet = true; @@ -1145,10 +1147,6 @@ keepAliveCount = 0; addS = new long[size]; addCount = 0; - if (comet) { - removeS = new long[size]; - } - removeCount = 0; } /** @@ -1159,15 +1157,9 @@ for (int i = 0; i < addCount; i++) { if (comet) { processSocket(addS[i], true); + } else { + Socket.destroy(addS[i]); } - Socket.destroy(addS[i]); - } - // Close all sockets in the remove queue - for (int i = 0; i < removeCount; i++) { - if (comet) { - processSocket(removeS[i], true); - } - Socket.destroy(removeS[i]); } // Close all sockets still in the poller int rv = Poll.pollset(serverPollset, desc); @@ -1175,14 +1167,14 @@ for (int n = 0; n < rv; n++) { if (comet) { processSocket(desc[n*2+1], true); + } else { + Socket.destroy(desc[n*2+1]); } - Socket.destroy(desc[n*2+1]); } } Pool.destroy(pool); keepAliveCount = 0; addCount = 0; - removeCount = 0; } /** @@ -1201,8 +1193,9 @@ // Can't do anything: close the socket right away if (comet) { processSocket(socket, true); + } else { + Socket.destroy(socket); } - Socket.destroy(socket); return; } addS[addCount] = socket; @@ -1212,30 +1205,6 @@ } /** - * Remove specified socket and associated pool from the poller. The socket will - * be added to a temporary array, and polled first after a maximum amount - * of time equal to pollTime (in most cases, latency will be much lower, - * however). Note that this is automatic, except if the poller is used for - * comet. - * - * @param socket to remove from the poller - */ - public void remove(long socket) { - synchronized (this) { - // Add socket to the list. Newly added sockets will wait - // at most for pollTime before being polled - if (removeCount >= removeS.length) { - // Normally, it cannot happen ... - Socket.destroy(socket); - return; - } - removeS[removeCount] = socket; - removeCount++; - this.notify(); - } - } - - /** * The background thread that listens for incoming TCP/IP connections and * hands them off to an appropriate processor. */ @@ -1279,26 +1248,18 @@ // Can't do anything: close the socket right away if (comet) { processSocket(addS[i], true); + } else { + Socket.destroy(addS[i]); } - Socket.destroy(addS[i]); } } addCount = 0; } } - // Remove sockets which are waiting to the poller - if (removeCount > 0) { - synchronized (this) { - for (int i = 0; i < removeCount; i++) { - int rv = Poll.remove(serverPollset, removeS[i]); - } - removeCount = 0; - } - } maintainTime += pollTime; // Pool for the specified interval - int rv = Poll.poll(serverPollset, pollTime, desc, !comet); + int rv = Poll.poll(serverPollset, pollTime, desc, true); if (rv > 0) { keepAliveCount -= rv; for (int n = 0; n < rv; n++) { @@ -1306,13 +1267,13 @@ if (((desc[n*2] & Poll.APR_POLLHUP) == Poll.APR_POLLHUP) || ((desc[n*2] & Poll.APR_POLLERR) == Poll.APR_POLLERR) || (comet && (!processSocket(desc[n*2+1], false))) - || (!processSocket(desc[n*2+1]))) { + || (!comet && (!processSocket(desc[n*2+1])))) { // Close socket and clear pool if (comet) { processSocket(desc[n*2+1], true); - Poll.remove(serverPollset, desc[n*2+1]); + } else { + Socket.destroy(desc[n*2+1]); } - Socket.destroy(desc[n*2+1]); continue; } } @@ -1343,8 +1304,9 @@ // FIXME: should really close in case of timeout ? // FIXME: maybe comet should use an extended timeout processSocket(desc[n], true); + } else { + Socket.destroy(desc[n]); } - Socket.destroy(desc[n]); } } } @@ -1467,7 +1429,7 @@ // Close socket and pool Socket.destroy(socket); socket = 0; - } else if (handler.process(socket) == Handler.SocketState.CLOSED) { + } else if ((!event) && (handler.process(socket) == Handler.SocketState.CLOSED)) { // Close socket and pool Socket.destroy(socket); socket = 0; --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]