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: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]