You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by fh...@apache.org on 2008/12/09 20:38:44 UTC

svn commit: r724849 - in /tomcat/trunk/java/org/apache: coyote/http11/Http11NioProcessor.java coyote/http11/Http11NioProtocol.java coyote/http11/InternalNioInputBuffer.java tomcat/util/net/NioEndpoint.java

Author: fhanik
Date: Tue Dec  9 11:38:44 2008
New Revision: 724849

URL: http://svn.apache.org/viewvc?rev=724849&view=rev
Log:
Implement keep alive timeout, and while doing this, I realized that keepalive is either on or off, but there is no counter

Modified:
    tomcat/trunk/java/org/apache/coyote/http11/Http11NioProcessor.java
    tomcat/trunk/java/org/apache/coyote/http11/Http11NioProtocol.java
    tomcat/trunk/java/org/apache/coyote/http11/InternalNioInputBuffer.java
    tomcat/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java

Modified: tomcat/trunk/java/org/apache/coyote/http11/Http11NioProcessor.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http11/Http11NioProcessor.java?rev=724849&r1=724848&r2=724849&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http11/Http11NioProcessor.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http11/Http11NioProcessor.java Tue Dec  9 11:38:44 2008
@@ -208,8 +208,7 @@
      * Maximum number of Keep-Alive requests to honor.
      */
     protected int maxKeepAliveRequests = -1;
-
-
+    
     /**
      * SSL enabled ?
      */
@@ -726,13 +725,15 @@
     public SocketState event(SocketStatus status)
         throws IOException {
 
-        RequestInfo rp = request.getRequestProcessor();
+        long soTimeout = endpoint.getSoTimeout();
+        int keepAliveTimeout = endpoint.getKeepAliveTimeout();
 
+        RequestInfo rp = request.getRequestProcessor();
+        final NioEndpoint.KeyAttachment attach = (NioEndpoint.KeyAttachment)socket.getAttachment(false);
         try {
             rp.setStage(org.apache.coyote.Constants.STAGE_SERVICE);
             error = !adapter.event(request, response, status);
             if ( !error ) {
-                NioEndpoint.KeyAttachment attach = (NioEndpoint.KeyAttachment)socket.getAttachment(false);
                 if (attach != null) {
                     attach.setComet(comet);
                     if (comet) {
@@ -740,7 +741,11 @@
                         if (comettimeout != null) attach.setTimeout(comettimeout.longValue());
                     } else {
                         //reset the timeout
-                        attach.setTimeout(endpoint.getSocketProperties().getSoTimeout());
+                        if (keepAlive && keepAliveTimeout>0) {
+                            attach.setTimeout(keepAliveTimeout);
+                        } else {
+                            attach.setTimeout(soTimeout);
+                        }
                     }
 
                 }
@@ -761,7 +766,6 @@
             return SocketState.CLOSED;
         } else if (!comet) {
             recycle();
-            //pay attention to the keep alive flag set in process()
             return (keepAlive)?SocketState.OPEN:SocketState.CLOSED;
         } else {
             return SocketState.LONG;
@@ -791,15 +795,17 @@
         keepAlive = true;
         comet = false;
         
-
-        int keepAliveLeft = maxKeepAliveRequests;
         long soTimeout = endpoint.getSoTimeout();
+        int keepAliveTimeout = endpoint.getKeepAliveTimeout();
 
         boolean keptAlive = false;
         boolean openSocket = false;
         boolean recycle = true;
+        final KeyAttachment ka = (KeyAttachment)socket.getAttachment(false);
+        
         while (!error && keepAlive && !comet) {
-
+            //always default to our soTimeout
+            ka.setTimeout(soTimeout);
             // Parsing the request header
             try {
                 if( !disableUploadTimeout && keptAlive && soTimeout > 0 ) {
@@ -810,6 +816,10 @@
                     //of the request line, we can't recycle the processor
                     openSocket = true;
                     recycle = false;
+                    if (inputBuffer.getParsingRequestLinePhase()<2) {
+                        //keep alive timeout here
+                        if (keepAliveTimeout>0) ka.setTimeout(keepAliveTimeout);
+                    }
                     break;
                 }
                 keptAlive = true;
@@ -851,8 +861,10 @@
                 response.setStatus(400);
                 error = true;
             }
-
-            if (maxKeepAliveRequests > 0 && --keepAliveLeft == 0)
+            
+            if (maxKeepAliveRequests == 1 )
+                keepAlive = false;
+            if (maxKeepAliveRequests > 0 && ka.decrementKeepAlive() <= 0)
                 keepAlive = false;
 
             // Process the request in the adapter
@@ -916,7 +928,6 @@
             
             // Do sendfile as needed: add socket to sendfile and end
             if (sendfileData != null && !error) {
-                KeyAttachment ka = (KeyAttachment)socket.getAttachment(false);
                 ka.setSendfileData(sendfileData);
                 sendfileData.keepAlive = keepAlive;
                 SelectionKey key = socket.getIOChannel().keyFor(socket.getPoller().getSelector());
@@ -928,10 +939,9 @@
 
             rp.setStage(org.apache.coyote.Constants.STAGE_KEEPALIVE);
 
-        }
+        }//while
 
         rp.setStage(org.apache.coyote.Constants.STAGE_ENDED);
-
         if (comet) {
             if (error) {
                 recycle();
@@ -940,7 +950,9 @@
                 return SocketState.LONG;
             }
         } else {
-            if ( recycle ) recycle();
+            if ( recycle ) {
+                recycle();
+            }
             //return (openSocket) ? (SocketState.OPEN) : SocketState.CLOSED;
             return (openSocket) ? (recycle?SocketState.OPEN:SocketState.LONG) : SocketState.CLOSED;
         }

Modified: tomcat/trunk/java/org/apache/coyote/http11/Http11NioProtocol.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http11/Http11NioProtocol.java?rev=724849&r1=724848&r2=724849&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http11/Http11NioProtocol.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http11/Http11NioProtocol.java Tue Dec  9 11:38:44 2008
@@ -19,6 +19,7 @@
 
 import java.net.InetAddress;
 import java.net.URLEncoder;
+import java.nio.channels.SocketChannel;
 import java.util.Hashtable;
 import java.util.Iterator;
 import java.util.concurrent.ConcurrentHashMap;
@@ -212,7 +213,6 @@
     protected Hashtable<String, Object> attributes =
         new Hashtable<String, Object>();
 
-    private int maxKeepAliveRequests=100; // as in Apache HTTPD server
     private int timeout = 300000;   // 5 minutes as in Apache HTTPD server
     private int maxSavePostSize = 4 * 1024;
     private int maxHttpHeaderSize = 8 * 1024;
@@ -456,6 +456,14 @@
         ep.setSoTimeout(i);
         setAttribute("soTimeout", "" + i);
     }
+    
+    public void setKeepAliveTimeout(int keepAliveTimeout) {
+        ep.setKeepAliveTimeout(keepAliveTimeout);
+    }
+    
+    public int getKeepAliveTimeout() {
+        return ep.getKeepAliveTimeout();
+    }
 
     public String getProtocol() {
         return getProperty("protocol");
@@ -477,13 +485,13 @@
     }
 
     public int getMaxKeepAliveRequests() {
-        return maxKeepAliveRequests;
+        return ep.getMaxKeepAliveRequests();
     }
 
     /** Set the maximum number of Keep-Alive requests that we will honor.
      */
     public void setMaxKeepAliveRequests(int mkar) {
-        maxKeepAliveRequests = mkar;
+        ep.setMaxKeepAliveRequests(mkar);
         setAttribute("maxKeepAliveRequests", "" + mkar);
     }
 
@@ -491,7 +499,7 @@
      * Return the Keep-Alive policy for the connection.
      */
     public boolean getKeepAlive() {
-        return ((maxKeepAliveRequests != 0) && (maxKeepAliveRequests != 1));
+        return ((ep.getMaxKeepAliveRequests() != 0) && (ep.getMaxKeepAliveRequests() != 1));
     }
 
     /**
@@ -638,6 +646,25 @@
             recycledProcessors.clear();
         }
         
+        public void release(SocketChannel socket) {
+            if (log.isDebugEnabled()) 
+                log.debug("Iterating through our connections to release a socket channel:"+socket);
+            boolean released = false;
+            Iterator<java.util.Map.Entry<NioChannel, Http11NioProcessor>> it = connections.entrySet().iterator();
+            while (it.hasNext()) {
+                java.util.Map.Entry<NioChannel, Http11NioProcessor> entry = it.next();
+                if (entry.getKey().getIOChannel()==socket) {
+                    it.remove();
+                    Http11NioProcessor result = entry.getValue();
+                    result.recycle();
+                    released = true;
+                    break;
+                }
+            }
+            if (log.isDebugEnabled()) 
+                log.debug("Done iterating through our connections to release a socket channel:"+socket +" released:"+released);
+        }
+        
         public void release(NioChannel socket) {
             Http11NioProcessor result = connections.remove(socket);
             if ( result != null ) {
@@ -770,7 +797,7 @@
               proto.maxHttpHeaderSize,
               proto.ep);
             processor.setAdapter(proto.adapter);
-            processor.setMaxKeepAliveRequests(proto.maxKeepAliveRequests);
+            processor.setMaxKeepAliveRequests(proto.getMaxKeepAliveRequests());
             processor.setTimeout(proto.timeout);
             processor.setDisableUploadTimeout(proto.disableUploadTimeout);
             processor.setCompressionMinSize(proto.compressionMinSize);

Modified: tomcat/trunk/java/org/apache/coyote/http11/InternalNioInputBuffer.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http11/InternalNioInputBuffer.java?rev=724849&r1=724848&r2=724849&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http11/InternalNioInputBuffer.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http11/InternalNioInputBuffer.java Tue Dec  9 11:38:44 2008
@@ -934,4 +934,9 @@
     }
 
 
+    public int getParsingRequestLinePhase() {
+        return parsingRequestLinePhase;
+    }
+
+
 }

Modified: tomcat/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java?rev=724849&r1=724848&r2=724849&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java Tue Dec  9 11:38:44 2008
@@ -366,6 +366,18 @@
     }
     public int getMaxThreads() { return maxThreads; }
 
+    /**
+     * Max keep alive requests 
+     */
+    protected int maxKeepAliveRequests=100; // as in Apache HTTPD server
+    public int getMaxKeepAliveRequests() {
+        return maxKeepAliveRequests;
+    }
+    public void setMaxKeepAliveRequests(int maxKeepAliveRequests) {
+        this.maxKeepAliveRequests = maxKeepAliveRequests;
+    }
+
+
 
     /**
      * Priority of the worker threads.
@@ -421,6 +433,14 @@
     public void setBacklog(int backlog) { if (backlog > 0) this.backlog = backlog; }
     public int getBacklog() { return backlog; }
 
+    /**
+     * Keepalive timeout, if lesser or equal to 0 then soTimeout will be used.
+     */
+    protected int keepAliveTimeout = 0;
+    public void setKeepAliveTimeout(int keepAliveTimeout) { this.keepAliveTimeout = keepAliveTimeout; }
+    public int getKeepAliveTimeout() { return keepAliveTimeout;}
+
+    
     protected SocketProperties socketProperties = new SocketProperties();
 
     /**
@@ -1367,6 +1387,7 @@
             KeyAttachment key = keyCache.poll();
             final KeyAttachment ka = key!=null?key:new KeyAttachment();
             ka.reset(this,socket,getSocketProperties().getSoTimeout());
+            ka.setKeepAliveLeft(NioEndpoint.this.getMaxKeepAliveRequests());
             PollerEvent r = eventCache.poll();
             ka.interestOps(SelectionKey.OP_READ);//this is what OP_REGISTER turns into.
             if ( r==null) r = new PollerEvent(socket,ka,OP_REGISTER);
@@ -1391,6 +1412,7 @@
                 }
                 
                 if (ka!=null) handler.release(ka.getChannel());
+                else handler.release((SocketChannel)key.channel());
                 if (key.isValid()) key.cancel();
                 if (key.channel().isOpen()) try {key.channel().close();}catch (Exception ignore){}
                 try {ka.channel.close(true);}catch (Exception ignore){}
@@ -1713,6 +1735,7 @@
             cometNotify = false;
             cometOps = SelectionKey.OP_READ;
             sendfileData = null;
+            keepAliveLeft = 100;
         }
         
         public void reset() {
@@ -1759,7 +1782,9 @@
         }
         public void startReadLatch(int cnt) { readLatch = startLatch(readLatch,cnt);}
         public void startWriteLatch(int cnt) { writeLatch = startLatch(writeLatch,cnt);}
-        
+        public int getKeepAliveLeft() { return this.keepAliveLeft; }
+        public void setKeepAliveLeft(int keepAliveLeft) { this.keepAliveLeft = keepAliveLeft;}
+        public int decrementKeepAlive() { return (--keepAliveLeft);}
         
         protected void awaitLatch(CountDownLatch latch, long timeout, TimeUnit unit) throws InterruptedException {
             if ( latch == null ) throw new IllegalStateException("Latch cannot be null");
@@ -1786,6 +1811,7 @@
         protected CountDownLatch writeLatch = null;
         protected long lastRegistered = 0;
         protected SendfileData sendfileData = null;
+        protected int keepAliveLeft = 100;
     }
 
     // ------------------------------------------------ Application Buffer Handler
@@ -1825,6 +1851,7 @@
         public SocketState event(NioChannel socket, SocketStatus status);
         public void releaseCaches();
         public void release(NioChannel socket);
+        public void release(SocketChannel socket);
     }
 
 



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org