You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2018/06/19 11:58:55 UTC

svn commit: r1833825 - in /tomcat/trunk: java/org/apache/coyote/ java/org/apache/coyote/http11/upgrade/ webapps/docs/

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