You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by re...@apache.org on 2006/05/18 20:29:08 UTC

svn commit: r407605 - in /tomcat/tc6.0.x/trunk/java/org/apache: catalina/ catalina/connector/ catalina/servlets/ coyote/ coyote/http11/ tomcat/util/net/

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: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org