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 2015/11/04 11:55:12 UTC

svn commit: r1712529 - in /tomcat/tc8.0.x/trunk/java/org/apache: catalina/connector/ catalina/core/ coyote/ coyote/ajp/ coyote/http11/

Author: markt
Date: Wed Nov  4 10:55:12 2015
New Revision: 1712529

URL: http://svn.apache.org/viewvc?rev=1712529&view=rev
Log:
Follow-up to r1712081.
Comet is not-blocking too, so it also needs to trigger a read on a call to available() if no bytes are in the buffer

Modified:
    tomcat/tc8.0.x/trunk/java/org/apache/catalina/connector/CoyoteAdapter.java
    tomcat/tc8.0.x/trunk/java/org/apache/catalina/connector/InputBuffer.java
    tomcat/tc8.0.x/trunk/java/org/apache/catalina/core/StandardWrapperValve.java
    tomcat/tc8.0.x/trunk/java/org/apache/coyote/ActionCode.java
    tomcat/tc8.0.x/trunk/java/org/apache/coyote/ajp/AbstractAjpProcessor.java
    tomcat/tc8.0.x/trunk/java/org/apache/coyote/http11/AbstractHttp11Processor.java

Modified: tomcat/tc8.0.x/trunk/java/org/apache/catalina/connector/CoyoteAdapter.java
URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/java/org/apache/catalina/connector/CoyoteAdapter.java?rev=1712529&r1=1712528&r2=1712529&view=diff
==============================================================================
--- tomcat/tc8.0.x/trunk/java/org/apache/catalina/connector/CoyoteAdapter.java (original)
+++ tomcat/tc8.0.x/trunk/java/org/apache/catalina/connector/CoyoteAdapter.java Wed Nov  4 10:55:12 2015
@@ -519,15 +519,11 @@ public class CoyoteAdapter implements Ad
 
                 if (request.isComet()) {
                     if (!response.isClosed() && !response.isError()) {
+                        comet = true;
+                        res.action(ActionCode.COMET_BEGIN, null);
                         if (request.getAvailable() || (request.getContentLength() > 0 && (!request.isParametersParsed()))) {
                             // Invoke a read event right away if there are available bytes
-                            if (event(req, res, SocketStatus.OPEN_READ)) {
-                                comet = true;
-                                res.action(ActionCode.COMET_BEGIN, null);
-                            }
-                        } else {
-                            comet = true;
-                            res.action(ActionCode.COMET_BEGIN, null);
+                            event(req, res, SocketStatus.OPEN_READ);
                         }
                     } else {
                         // Clear the filter chain, as otherwise it will not be reset elsewhere
@@ -535,8 +531,8 @@ public class CoyoteAdapter implements Ad
                         request.setFilterChain(null);
                     }
                 }
-
             }
+
             AsyncContextImpl asyncConImpl = (AsyncContextImpl)request.getAsyncContext();
             if (asyncConImpl != null) {
                 async = true;

Modified: tomcat/tc8.0.x/trunk/java/org/apache/catalina/connector/InputBuffer.java
URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/java/org/apache/catalina/connector/InputBuffer.java?rev=1712529&r1=1712528&r2=1712529&view=diff
==============================================================================
--- tomcat/tc8.0.x/trunk/java/org/apache/catalina/connector/InputBuffer.java (original)
+++ tomcat/tc8.0.x/trunk/java/org/apache/catalina/connector/InputBuffer.java Wed Nov  4 10:55:12 2015
@@ -22,6 +22,7 @@ import java.security.AccessController;
 import java.security.PrivilegedActionException;
 import java.security.PrivilegedExceptionAction;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicBoolean;
 
 import javax.servlet.ReadListener;
 
@@ -241,7 +242,14 @@ public class InputBuffer extends Reader
             available = cb.getLength();
         }
         if (available == 0) {
-            coyoteRequest.action(ActionCode.AVAILABLE, Boolean.valueOf(coyoteRequest.getReadListener() != null));
+            // Written this way to avoid use of IS_COMET action where possible
+            boolean readForAvailable = coyoteRequest.getReadListener() != null;
+            if (!readForAvailable) {
+                AtomicBoolean isComet = new AtomicBoolean();
+                coyoteRequest.action(ActionCode.IS_COMET, isComet);
+                readForAvailable = isComet.get();
+            }
+            coyoteRequest.action(ActionCode.AVAILABLE, Boolean.valueOf(readForAvailable));
             available = (coyoteRequest.getAvailable() > 0) ? 1 : 0;
         }
         return available;

Modified: tomcat/tc8.0.x/trunk/java/org/apache/catalina/core/StandardWrapperValve.java
URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/java/org/apache/catalina/core/StandardWrapperValve.java?rev=1712529&r1=1712528&r2=1712529&view=diff
==============================================================================
--- tomcat/tc8.0.x/trunk/java/org/apache/catalina/core/StandardWrapperValve.java (original)
+++ tomcat/tc8.0.x/trunk/java/org/apache/catalina/core/StandardWrapperValve.java Wed Nov  4 10:55:12 2015
@@ -181,9 +181,6 @@ final class StandardWrapperValve
         ApplicationFilterChain filterChain =
                 ApplicationFilterFactory.createFilterChain(request, wrapper, servlet);
 
-        // Reset comet flag value after creating the filter chain
-        request.setComet(false);
-
         // Call the filter chain for this request
         // NOTE: This also calls the servlet's service() method
         try {
@@ -196,7 +193,6 @@ final class StandardWrapperValve
                             ((AsyncContextImpl)request.getAsyncContext()).doInternalDispatch();
                         } else if (comet) {
                             filterChain.doFilterEvent(request.getEvent());
-                            request.setComet(true);
                         } else {
                             filterChain.doFilter(request.getRequest(),
                                     response.getResponse());
@@ -211,7 +207,6 @@ final class StandardWrapperValve
                     if (request.isAsyncDispatching()) {
                         ((AsyncContextImpl)request.getAsyncContext()).doInternalDispatch();
                     } else if (comet) {
-                        request.setComet(true);
                         filterChain.doFilterEvent(request.getEvent());
                     } else {
                         filterChain.doFilter

Modified: tomcat/tc8.0.x/trunk/java/org/apache/coyote/ActionCode.java
URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/java/org/apache/coyote/ActionCode.java?rev=1712529&r1=1712528&r2=1712529&view=diff
==============================================================================
--- tomcat/tc8.0.x/trunk/java/org/apache/coyote/ActionCode.java (original)
+++ tomcat/tc8.0.x/trunk/java/org/apache/coyote/ActionCode.java Wed Nov  4 10:55:12 2015
@@ -135,6 +135,11 @@ public enum ActionCode {
     COMET_SETTIMEOUT,
 
     /**
+     * Callback to determine if the current request is a Comet request.
+     */
+    IS_COMET,
+
+    /**
      * Callback for an async request.
      */
     ASYNC_START,

Modified: tomcat/tc8.0.x/trunk/java/org/apache/coyote/ajp/AbstractAjpProcessor.java
URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/java/org/apache/coyote/ajp/AbstractAjpProcessor.java?rev=1712529&r1=1712528&r2=1712529&view=diff
==============================================================================
--- tomcat/tc8.0.x/trunk/java/org/apache/coyote/ajp/AbstractAjpProcessor.java (original)
+++ tomcat/tc8.0.x/trunk/java/org/apache/coyote/ajp/AbstractAjpProcessor.java Wed Nov  4 10:55:12 2015
@@ -617,6 +617,11 @@ public abstract class AbstractAjpProcess
             throw new UnsupportedOperationException(
                     sm.getString("ajpprocessor.comet.notsupported"));
         }
+        case IS_COMET: {
+            // HTTP connections only. Unsupported for AJP.
+            throw new UnsupportedOperationException(
+                    sm.getString("ajpprocessor.comet.notsupported"));
+        }
         case AVAILABLE: {
             if (available()) {
                 request.setAvailable(1);

Modified: tomcat/tc8.0.x/trunk/java/org/apache/coyote/http11/AbstractHttp11Processor.java
URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/java/org/apache/coyote/http11/AbstractHttp11Processor.java?rev=1712529&r1=1712528&r2=1712529&view=diff
==============================================================================
--- tomcat/tc8.0.x/trunk/java/org/apache/coyote/http11/AbstractHttp11Processor.java (original)
+++ tomcat/tc8.0.x/trunk/java/org/apache/coyote/http11/AbstractHttp11Processor.java Wed Nov  4 10:55:12 2015
@@ -920,6 +920,11 @@ public abstract class AbstractHttp11Proc
             endRequest();
             break;
         }
+        case IS_COMET: {
+            AtomicBoolean result = (AtomicBoolean) param;
+            result.set(isComet());
+            break;
+        }
         default: {
             actionInternal(actionCode, param);
             break;



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


Re: svn commit: r1712529 - in /tomcat/tc8.0.x/trunk/java/org/apache: catalina/connector/ catalina/core/ coyote/ coyote/ajp/ coyote/http11/

Posted by Rémy Maucherat <re...@apache.org>.
2015-11-04 11:55 GMT+01:00 <ma...@apache.org>:

> Author: markt
> Date: Wed Nov  4 10:55:12 2015
> New Revision: 1712529
>
> URL: http://svn.apache.org/viewvc?rev=1712529&view=rev
> Log:
> Follow-up to r1712081.
> Comet is not-blocking too, so it also needs to trigger a read on a call to
> available() if no bytes are in the buffer
>
> Sorry I missed that interaction, which is no longer there in 9.

Rémy

Re: svn commit: r1712529 - in /tomcat/tc8.0.x/trunk/java/org/apache: catalina/connector/ catalina/core/ coyote/ coyote/ajp/ coyote/http11/

Posted by Huxing Zhang <hu...@alibaba-inc.com>.
Hi Mark,

Unit test failed because of this commit. Full details can be found in [1].

Test case failure exception stack trace:

Testcase: testZeroLengthRequestBodyPostA took 3.038 sec
    FAILED
expected:<200> but was:<500>
junit.framework.AssertionFailedError: expected:<200> but was:<500>
    at org.apache.coyote.ajp.TestAbstractAjpProcessor.validateResponseHeaders(TestAbstractAjpProcessor.java:830)
    at org.apache.coyote.ajp.TestAbstractAjpProcessor.doTestZeroLengthRequestBody(TestAbstractAjpProcessor.java:743)
    at org.apache.coyote.ajp.TestAbstractAjpProcessor.testZeroLengthRequestBodyPostA(TestAbstractAjpProcessor.java:706)

06-Nov-2015 10:44:32.685 SEVERE [ajp-apr-127.0.0.1-auto-7-exec-1] org.apache.catalina.core.StandardWrapperValve.invoke Servlet.service() for servlet [ReadBody] in context with path [] threw exception
 java.lang.UnsupportedOperationException: The Comet protocol is not supported by this connector
        at org.apache.coyote.ajp.AbstractAjpProcessor.action(AbstractAjpProcessor.java:622)
        at org.apache.coyote.Request.action(Request.java:380)
        at org.apache.catalina.connector.InputBuffer.available(InputBuffer.java:249)
        at org.apache.catalina.connector.CoyoteInputStream.available(CoyoteInputStream.java:124)
        at org.apache.coyote.ajp.TestAbstractAjpProcessor$ReadBodyServlet.doRequest(TestAbstractAjpProcessor.java:968)
        at org.apache.coyote.ajp.TestAbstractAjpProcessor$ReadBodyServlet.doPost(TestAbstractAjpProcessor.java:955)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:648)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:212)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:518)
        at org.apache.coyote.ajp.AbstractAjpProcessor.process(AbstractAjpProcessor.java:849)
        at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:673)
        at org.apache.tomcat.util.net.AprEndpoint$SocketWithOptionsProcessor.run(AprEndpoint.java:2437)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
        at java.lang.Thread.run(Thread.java:745)

If protocol is AJP, AbstractAjpProcessor.action will throw UnsupportedOperationException.

In org.apache.catalina.connector.InputBuffer#avaliable(), readForAvailable is not enough to avoid IS_COMET action.
I think we should also check the protocol, since IS_COMET only support HTTP.

The only way to I can figure out is to use Thread.currentThread.getName().isStartsWith("http"), but maybe there is something better.

[1] http://vmgump.apache.org/gump/public/tomcat-8.0.x/tomcat-tc8.0.x-test-bio/index.html

Thanks,
Huxing Zhang
------------------------------------------------------------------
From:markt <ma...@apache.org>
Time:2015 Nov 4 (Wed) 18:55
To:dev <de...@tomcat.apache.org>
Subject:svn commit: r1712529 - in /tomcat/tc8.0.x/trunk/java/org/apache: catalina/connector/ catalina/core/ coyote/ coyote/ajp/ coyote/http11/


Author: markt
Date: Wed Nov  4 10:55:12 2015
New Revision: 1712529

URL: http://svn.apache.org/viewvc?rev=1712529&view=rev
Log:
Follow-up to r1712081.
Comet is not-blocking too, so it also needs to trigger a read on a call to available() if no bytes are in the buffer

Modified:
    tomcat/tc8.0.x/trunk/java/org/apache/catalina/connector/CoyoteAdapter.java
    tomcat/tc8.0.x/trunk/java/org/apache/catalina/connector/InputBuffer.java
    tomcat/tc8.0.x/trunk/java/org/apache/catalina/core/StandardWrapperValve.java
    tomcat/tc8.0.x/trunk/java/org/apache/coyote/ActionCode.java
    tomcat/tc8.0.x/trunk/java/org/apache/coyote/ajp/AbstractAjpProcessor.java
    tomcat/tc8.0.x/trunk/java/org/apache/coyote/http11/AbstractHttp11Processor.java

Modified: tomcat/tc8.0.x/trunk/java/org/apache/catalina/connector/CoyoteAdapter.java
URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/java/org/apache/catalina/connector/CoyoteAdapter.java?rev=1712529&r1=1712528&r2=1712529&view=diff
==============================================================================
--- tomcat/tc8.0.x/trunk/java/org/apache/catalina/connector/CoyoteAdapter.java (original)
+++ tomcat/tc8.0.x/trunk/java/org/apache/catalina/connector/CoyoteAdapter.java Wed Nov  4 10:55:12 2015
@@ -519,15 +519,11 @@ public class CoyoteAdapter implements Ad
 
                 if (request.isComet()) {
                     if (!response.isClosed() && !response.isError()) {
+                        comet = true;
+                        res.action(ActionCode.COMET_BEGIN, null);
                         if (request.getAvailable() || (request.getContentLength() > 0 && (!request.isParametersParsed()))) {
                             // Invoke a read event right away if there are available bytes
-                            if (event(req, res, SocketStatus.OPEN_READ)) {
-                                comet = true;
-                                res.action(ActionCode.COMET_BEGIN, null);
-                            }
-                        } else {
-                            comet = true;
-                            res.action(ActionCode.COMET_BEGIN, null);
+                            event(req, res, SocketStatus.OPEN_READ);
                         }
                     } else {
                         // Clear the filter chain, as otherwise it will not be reset elsewhere
@@ -535,8 +531,8 @@ public class CoyoteAdapter implements Ad
                         request.setFilterChain(null);
                     }
                 }
-
             }
+
             AsyncContextImpl asyncConImpl = (AsyncContextImpl)request.getAsyncContext();
             if (asyncConImpl != null) {
                 async = true;

Modified: tomcat/tc8.0.x/trunk/java/org/apache/catalina/connector/InputBuffer.java
URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/java/org/apache/catalina/connector/InputBuffer.java?rev=1712529&r1=1712528&r2=1712529&view=diff
==============================================================================
--- tomcat/tc8.0.x/trunk/java/org/apache/catalina/connector/InputBuffer.java (original)
+++ tomcat/tc8.0.x/trunk/java/org/apache/catalina/connector/InputBuffer.java Wed Nov  4 10:55:12 2015
@@ -22,6 +22,7 @@ import java.security.AccessController;
 import java.security.PrivilegedActionException;
 import java.security.PrivilegedExceptionAction;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicBoolean;
 
 import javax.servlet.ReadListener;
 
@@ -241,7 +242,14 @@ public class InputBuffer extends Reader
             available = cb.getLength();
         }
         if (available == 0) {
-            coyoteRequest.action(ActionCode.AVAILABLE, Boolean.valueOf(coyoteRequest.getReadListener() != null));
+            // Written this way to avoid use of IS_COMET action where possible
+            boolean readForAvailable = coyoteRequest.getReadListener() != null;
+            if (!readForAvailable) {
+                AtomicBoolean isComet = new AtomicBoolean();
+                coyoteRequest.action(ActionCode.IS_COMET, isComet);
+                readForAvailable = isComet.get();
+            }
+            coyoteRequest.action(ActionCode.AVAILABLE, Boolean.valueOf(readForAvailable));
             available = (coyoteRequest.getAvailable() > 0) ? 1 : 0;
         }
         return available;

Modified: tomcat/tc8.0.x/trunk/java/org/apache/catalina/core/StandardWrapperValve.java
URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/java/org/apache/catalina/core/StandardWrapperValve.java?rev=1712529&r1=1712528&r2=1712529&view=diff
==============================================================================
--- tomcat/tc8.0.x/trunk/java/org/apache/catalina/core/StandardWrapperValve.java (original)
+++ tomcat/tc8.0.x/trunk/java/org/apache/catalina/core/StandardWrapperValve.java Wed Nov  4 10:55:12 2015
@@ -181,9 +181,6 @@ final class StandardWrapperValve
         ApplicationFilterChain filterChain =
                 ApplicationFilterFactory.createFilterChain(request, wrapper, servlet);
 
-        // Reset comet flag value after creating the filter chain
-        request.setComet(false);
-
         // Call the filter chain for this request
         // NOTE: This also calls the servlet's service() method
         try {
@@ -196,7 +193,6 @@ final class StandardWrapperValve
                             ((AsyncContextImpl)request.getAsyncContext()).doInternalDispatch();
                         } else if (comet) {
                             filterChain.doFilterEvent(request.getEvent());
-                            request.setComet(true);
                         } else {
                             filterChain.doFilter(request.getRequest(),
                                     response.getResponse());
@@ -211,7 +207,6 @@ final class StandardWrapperValve
                     if (request.isAsyncDispatching()) {
                         ((AsyncContextImpl)request.getAsyncContext()).doInternalDispatch();
                     } else if (comet) {
-                        request.setComet(true);
                         filterChain.doFilterEvent(request.getEvent());
                     } else {
                         filterChain.doFilter

Modified: tomcat/tc8.0.x/trunk/java/org/apache/coyote/ActionCode.java
URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/java/org/apache/coyote/ActionCode.java?rev=1712529&r1=1712528&r2=1712529&view=diff
==============================================================================
--- tomcat/tc8.0.x/trunk/java/org/apache/coyote/ActionCode.java (original)
+++ tomcat/tc8.0.x/trunk/java/org/apache/coyote/ActionCode.java Wed Nov  4 10:55:12 2015
@@ -135,6 +135,11 @@ public enum ActionCode {
     COMET_SETTIMEOUT,
 
     /**
+     * Callback to determine if the current request is a Comet request.
+     */
+    IS_COMET,
+
+    /**
      * Callback for an async request.
      */
     ASYNC_START,

Modified: tomcat/tc8.0.x/trunk/java/org/apache/coyote/ajp/AbstractAjpProcessor.java
URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/java/org/apache/coyote/ajp/AbstractAjpProcessor.java?rev=1712529&r1=1712528&r2=1712529&view=diff
==============================================================================
--- tomcat/tc8.0.x/trunk/java/org/apache/coyote/ajp/AbstractAjpProcessor.java (original)
+++ tomcat/tc8.0.x/trunk/java/org/apache/coyote/ajp/AbstractAjpProcessor.java Wed Nov  4 10:55:12 2015
@@ -617,6 +617,11 @@ public abstract class AbstractAjpProcess
             throw new UnsupportedOperationException(
                     sm.getString("ajpprocessor.comet.notsupported"));
         }
+        case IS_COMET: {
+            // HTTP connections only. Unsupported for AJP.
+            throw new UnsupportedOperationException(
+                    sm.getString("ajpprocessor.comet.notsupported"));
+        }
         case AVAILABLE: {
             if (available()) {
                 request.setAvailable(1);

Modified: tomcat/tc8.0.x/trunk/java/org/apache/coyote/http11/AbstractHttp11Processor.java
URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/java/org/apache/coyote/http11/AbstractHttp11Processor.java?rev=1712529&r1=1712528&r2=1712529&view=diff
==============================================================================
--- tomcat/tc8.0.x/trunk/java/org/apache/coyote/http11/AbstractHttp11Processor.java (original)
+++ tomcat/tc8.0.x/trunk/java/org/apache/coyote/http11/AbstractHttp11Processor.java Wed Nov  4 10:55:12 2015
@@ -920,6 +920,11 @@ public abstract class AbstractHttp11Proc
             endRequest();
             break;
         }
+        case IS_COMET: {
+            AtomicBoolean result = (AtomicBoolean) param;
+            result.set(isComet());
+            break;
+        }
         default: {
             actionInternal(actionCode, param);
             break;



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

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