Author: markt Date: Tue Jun 19 11:58:55 2018 New Revision: 1833825 URL: http://svn.apache.org/viewvc?rev=1833825&view=rev Log: Avoid unnecessary processing of async timeouts.
Modified: tomcat/trunk/java/org/apache/coyote/AbstractProcessor.java tomcat/trunk/java/org/apache/coyote/AbstractProtocol.java tomcat/trunk/java/org/apache/coyote/AsyncStateMachine.java tomcat/trunk/java/org/apache/coyote/Processor.java tomcat/trunk/java/org/apache/coyote/http11/upgrade/UpgradeProcessorBase.java tomcat/trunk/webapps/docs/changelog.xml Modified: tomcat/trunk/java/org/apache/coyote/AbstractProcessor.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/AbstractProcessor.java?rev=1833825&r1=1833824&r2=1833825&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/coyote/AbstractProcessor.java (original) +++ tomcat/trunk/java/org/apache/coyote/AbstractProcessor.java Tue Jun 19 11:58:55 2018 @@ -51,6 +51,7 @@ public abstract class AbstractProcessor protected final Adapter adapter; protected final AsyncStateMachine asyncStateMachine; private volatile long asyncTimeout = -1; + private volatile long asyncTimeoutGeneration = 0; protected final Request request; protected final Response response; protected volatile SocketWrapperBase<?> socketWrapper = null; @@ -620,10 +621,17 @@ public abstract class AbstractProcessor private void doTimeoutAsync() { // Avoid multiple timeouts setAsyncTimeout(-1); + asyncTimeoutGeneration = asyncStateMachine.getCurrentGeneration(); processSocketEvent(SocketEvent.TIMEOUT, true); } + @Override + public boolean checkAsyncTimeoutGeneration() { + return asyncTimeoutGeneration == asyncStateMachine.getCurrentGeneration(); + } + + public void setAsyncTimeout(long timeout) { asyncTimeout = timeout; } Modified: tomcat/trunk/java/org/apache/coyote/AbstractProtocol.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/AbstractProtocol.java?rev=1833825&r1=1833824&r2=1833825&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/coyote/AbstractProtocol.java (original) +++ tomcat/trunk/java/org/apache/coyote/AbstractProtocol.java Tue Jun 19 11:58:55 2018 @@ -683,6 +683,16 @@ public abstract class AbstractProtocol<S processor, socket)); } + // Async timeouts are calculated on a dedicated thread and then + // dispatched. Because of delays in the dispatch process, the + // timeout may no longer be required. Check here and avoid + // unnecessary processing. + if (SocketEvent.TIMEOUT == status && (processor == null || + !processor.isAsync() || !processor.checkAsyncTimeoutGeneration())) { + // This is effectively a NO-OP + return SocketState.OPEN; + } + if (processor != null) { // Make sure an async timeout doesn't fire getProtocol().removeWaitingProcessor(processor); Modified: tomcat/trunk/java/org/apache/coyote/AsyncStateMachine.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/AsyncStateMachine.java?rev=1833825&r1=1833824&r2=1833825&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/coyote/AsyncStateMachine.java [UTF-8] (original) +++ tomcat/trunk/java/org/apache/coyote/AsyncStateMachine.java [UTF-8] Tue Jun 19 11:58:55 2018 @@ -18,6 +18,7 @@ package org.apache.coyote; import java.security.AccessController; import java.security.PrivilegedAction; +import java.util.concurrent.atomic.AtomicLong; import org.apache.tomcat.util.net.AbstractEndpoint.Handler.SocketState; import org.apache.tomcat.util.res.StringManager; @@ -189,6 +190,7 @@ class AsyncStateMachine { private volatile AsyncState state = AsyncState.DISPATCHED; private volatile long lastAsyncStart = 0; + private AtomicLong generation = new AtomicLong(0); // Need this to fire listener on complete private AsyncContextCallback asyncCtxt = null; private final AbstractProcessor processor; @@ -234,8 +236,13 @@ class AsyncStateMachine { return lastAsyncStart; } + long getCurrentGeneration() { + return generation.get(); + } + synchronized void asyncStart(AsyncContextCallback asyncCtxt) { if (state == AsyncState.DISPATCHED) { + generation.incrementAndGet(); state = AsyncState.STARTING; this.asyncCtxt = asyncCtxt; lastAsyncStart = System.currentTimeMillis(); Modified: tomcat/trunk/java/org/apache/coyote/Processor.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/Processor.java?rev=1833825&r1=1833824&r2=1833825&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/coyote/Processor.java (original) +++ tomcat/trunk/java/org/apache/coyote/Processor.java Tue Jun 19 11:58:55 2018 @@ -110,4 +110,15 @@ public interface Processor { * an existing multiplexed connection. */ void pause(); + + /** + * Check to see if the async generation (each cycle of async increments the + * generation of the AsyncStateMachine) is the same as the generation when + * the most recent async timeout was triggered. This is intended to be used + * to avoid unnecessary processing. + * + * @return {@code true} If the async generation has not changed since the + * async timeout was triggered + */ + boolean checkAsyncTimeoutGeneration(); } Modified: tomcat/trunk/java/org/apache/coyote/http11/upgrade/UpgradeProcessorBase.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http11/upgrade/UpgradeProcessorBase.java?rev=1833825&r1=1833824&r2=1833825&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/coyote/http11/upgrade/UpgradeProcessorBase.java (original) +++ tomcat/trunk/java/org/apache/coyote/http11/upgrade/UpgradeProcessorBase.java Tue Jun 19 11:58:55 2018 @@ -94,4 +94,10 @@ public abstract class UpgradeProcessorBa public void timeoutAsync(long now) { // NO-OP } + + + @Override + public boolean checkAsyncTimeoutGeneration() { + return false; + } } Modified: tomcat/trunk/webapps/docs/changelog.xml URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/changelog.xml?rev=1833825&r1=1833824&r2=1833825&view=diff ============================================================================== --- tomcat/trunk/webapps/docs/changelog.xml (original) +++ tomcat/trunk/webapps/docs/changelog.xml Tue Jun 19 11:58:55 2018 @@ -211,6 +211,9 @@ Fix <code>NullPointerException</code> thrown from <code> replaceSystemProperties()</code> when trying to log messages. (csutherl) </fix> + <fix> + Avoid unnecessary processing of async timeouts. (markt) + </fix> </changelog> </subsection> <subsection name="Jasper"> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org