From: fhanik Date: Fri, 14 Jul 2006 03:27:06 +0000 (+0000) Subject: Optimize timeout handling, thanks to a suggestion from Jeanfrancois.Arcand@Sun.COM, X-Git-Url: https://git.internetallee.de/?a=commitdiff_plain;h=808686067dd940c989cb314e1eef38e349d0e459;p=tomcat7.0 Optimize timeout handling, thanks to a suggestion from Jeanfrancois.Arcand@Sun.COM, although this does put a gap in the timeout check, even in those cases where there shouldn't be, ie, a socket can be closed immediately git-svn-id: https://svn.apache.org/repos/asf/tomcat/tc6.0.x/trunk@421791 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/java/org/apache/coyote/http11/InternalNioInputBuffer.java b/java/org/apache/coyote/http11/InternalNioInputBuffer.java index d8765c353..76f26dd82 100644 --- a/java/org/apache/coyote/http11/InternalNioInputBuffer.java +++ b/java/org/apache/coyote/http11/InternalNioInputBuffer.java @@ -572,21 +572,7 @@ public class InternalNioInputBuffer implements InputBuffer { boolean addToQueue = false; try { addToQueue = ((key.interestOps()&SelectionKey.OP_READ) != SelectionKey.OP_READ); } catch ( CancelledKeyException ignore ){} if ( addToQueue ) { - att.setWakeUp(true); - poller.addEvent( - new Runnable() { - public void run() { - try { - if (key != null) key.interestOps(SelectionKey.OP_READ); - } catch (CancelledKeyException ckx) { - try { - socket.socket().close(); - socket.close(); - att.setWakeUp(false); - } catch (Exception ignore) {} - } - } - }); + addToReadQueue(key, att); }//end if synchronized (att.getMutex()) { if ( att.getWakeUp() ) att.getMutex().wait(25); @@ -598,6 +584,28 @@ public class InternalNioInputBuffer implements InputBuffer { throw new IOException("read timed out."); } + private void addToReadQueue(final SelectionKey key, final KeyAttachment att) { + att.setWakeUp(true); + poller.addEvent( + new Runnable() { + public void run() { + try { + if (key != null) key.interestOps(SelectionKey.OP_READ); + } catch (CancelledKeyException ckx) { + try { + if ( key != null && key.attachment() != null ) { + KeyAttachment ka = (KeyAttachment)key.attachment(); + ka.setError(true); //set to collect this socket immediately + } + socket.socket().close(); + socket.close(); + att.setWakeUp(false); + } catch (Exception ignore) {} + } + } + }); + } + /** * Parse the HTTP headers. diff --git a/java/org/apache/tomcat/util/net/NioEndpoint.java b/java/org/apache/tomcat/util/net/NioEndpoint.java index 64c4f4bc0..8301cbd6d 100644 --- a/java/org/apache/tomcat/util/net/NioEndpoint.java +++ b/java/org/apache/tomcat/util/net/NioEndpoint.java @@ -967,6 +967,7 @@ public class NioEndpoint { protected Selector selector; protected LinkedList events = new LinkedList(); protected boolean close = false; + protected long nextExpiration = 0;//optimize expiration handling protected int keepAliveCount = 0; public int getKeepAliveCount() { return keepAliveCount; } @@ -1029,6 +1030,10 @@ public class NioEndpoint { if (key != null) key.interestOps(SelectionKey.OP_READ); }catch ( CancelledKeyException ckx ) { try { + if ( key != null && key.attachment() != null ) { + KeyAttachment ka = (KeyAttachment)key.attachment(); + ka.setError(true); //set to collect this socket immediately + } socket.socket().close(); socket.close(); } catch ( Exception ignore ) {} @@ -1075,7 +1080,7 @@ public class NioEndpoint { try { KeyAttachment ka = (KeyAttachment) key.attachment(); key.cancel(); - if (ka.getComet()) processSocket( (SocketChannel) key.channel(), true); + if (ka != null && ka.getComet()) processSocket( (SocketChannel) key.channel(), true); key.channel().close(); } catch (IOException e) { if ( log.isDebugEnabled() ) log.debug("",e); @@ -1156,34 +1161,45 @@ public class NioEndpoint { log.error("",t); } }//while - - //timeout - Set keys = selector.keys(); - long now = System.currentTimeMillis(); - for (Iterator iter = keys.iterator(); iter.hasNext(); ) { - SelectionKey key = iter.next(); - try { - if (key.interestOps() == SelectionKey.OP_READ) { - //only timeout sockets that we are waiting for a read from - KeyAttachment ka = (KeyAttachment) key.attachment(); - long delta = now - ka.getLastAccess(); - boolean isTimedout = (ka.getTimeout()==-1)?(delta > (long) soTimeout):(delta>ka.getTimeout()); - if (isTimedout) { - cancelledKey(key); - } - } - }catch ( CancelledKeyException ckx ) { - cancelledKey(key); - } - } - + //process timeouts + timeout(); } synchronized (this) { this.notifyAll(); } } - + protected void timeout() { + long now = System.currentTimeMillis(); + if ( now < nextExpiration ) return; + nextExpiration = now + (long)soTimeout; + //timeout + Set keys = selector.keys(); + for (Iterator iter = keys.iterator(); iter.hasNext(); ) { + SelectionKey key = iter.next(); + try { + KeyAttachment ka = (KeyAttachment) key.attachment(); + if ( ka == null ) { + cancelledKey(key); //we don't support any keys without attachments + } else if ( ka.getError() ) { + cancelledKey(key); + }else if ((key.interestOps()&SelectionKey.OP_READ) == SelectionKey.OP_READ) { + //only timeout sockets that we are waiting for a read from + long delta = now - ka.getLastAccess(); + long timeout = (ka.getTimeout()==-1)?((long) soTimeout):(ka.getTimeout()); + boolean isTimedout = delta > timeout; + if (isTimedout) { + cancelledKey(key); + } else { + long nextTime = now+(timeout-delta); + nextExpiration = (nextTime < nextExpiration)?nextTime:nextExpiration; + } + }//end if + }catch ( CancelledKeyException ckx ) { + cancelledKey(key); + } + }//for + } } public static class KeyAttachment { @@ -1200,12 +1216,15 @@ public class NioEndpoint { public Object getMutex() {return mutex;} public void setTimeout(long timeout) {this.timeout = timeout;} public long getTimeout() {return this.timeout;} + public boolean getError() { return error; } + public void setError(boolean error) { this.error = error; } protected Object mutex = new Object(); protected boolean wakeUp = false; protected long lastAccess = System.currentTimeMillis(); protected boolean currentAccess = false; protected boolean comet = false; protected long timeout = -1; + protected boolean error = false; }