Author: markt
Date: Fri Jan 31 18:34:18 2014
New Revision: 1563206

URL: http://svn.apache.org/r1563206
Log:
Enable non-blocking reads to take place on non-container threads.

Added:
    tomcat/trunk/java/org/apache/coyote/ContainerThreadMarker.java   (with 
props)
Modified:
    tomcat/trunk/java/org/apache/catalina/connector/CoyoteAdapter.java
    tomcat/trunk/java/org/apache/catalina/connector/InputBuffer.java
    tomcat/trunk/java/org/apache/coyote/AbstractProtocol.java
    tomcat/trunk/java/org/apache/coyote/ajp/AjpNioProcessor.java
    tomcat/trunk/java/org/apache/coyote/http11/Http11NioProcessor.java
    tomcat/trunk/webapps/docs/changelog.xml

Modified: tomcat/trunk/java/org/apache/catalina/connector/CoyoteAdapter.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/connector/CoyoteAdapter.java?rev=1563206&r1=1563205&r2=1563206&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/connector/CoyoteAdapter.java 
(original)
+++ tomcat/trunk/java/org/apache/catalina/connector/CoyoteAdapter.java Fri Jan 
31 18:34:18 2014
@@ -373,7 +373,14 @@ public class CoyoteAdapter implements Ad
                     ClassLoader oldCL = null;
                     try {
                         oldCL = request.getContext().bind(false, null);
-                        readListener.onDataAvailable();
+                        // If data is being read on a non-container thread a
+                        // dispatch with status OPEN_READ will be used to get
+                        // execution back on a container thread for the
+                        // onAllDataRead() event. Therefore, make sure
+                        // onDataAvailable() is not called in this case.
+                        if (!request.isFinished()) {
+                            readListener.onDataAvailable();
+                        }
                         if (request.isFinished() && 
req.sendAllDataReadEvent()) {
                             readListener.onAllDataRead();
                         }

Modified: tomcat/trunk/java/org/apache/catalina/connector/InputBuffer.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/connector/InputBuffer.java?rev=1563206&r1=1563205&r2=1563206&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/connector/InputBuffer.java (original)
+++ tomcat/trunk/java/org/apache/catalina/connector/InputBuffer.java Fri Jan 31 
18:34:18 2014
@@ -27,6 +27,7 @@ import javax.servlet.ReadListener;
 
 import org.apache.catalina.security.SecurityUtil;
 import org.apache.coyote.ActionCode;
+import org.apache.coyote.ContainerThreadMarker;
 import org.apache.coyote.Request;
 import org.apache.tomcat.util.buf.B2CConverter;
 import org.apache.tomcat.util.buf.ByteChunk;
@@ -273,8 +274,19 @@ public class InputBuffer extends Reader
         if (coyoteRequest.getReadListener() == null) {
             throw new IllegalStateException("not in non blocking mode.");
         }
-        int available = available();
-        boolean result = available > 0;
+        // Need to check is finished before we check available() as BIO always
+        // returns 1 for isAvailable()
+        if (isFinished()) {
+            // If this is a non-container thread, need to trigger a read
+            // which will eventually lead to a call to onAllDataRead() via a
+            // container thread.
+            if (!ContainerThreadMarker.isContainerThread()) {
+                coyoteRequest.action(ActionCode.DISPATCH_READ, null);
+                coyoteRequest.action(ActionCode.DISPATCH_EXECUTE, null);
+            }
+            return false;
+        }
+        boolean result = available() > 0;
         if (!result) {
             coyoteRequest.action(ActionCode.NB_READ_INTEREST, null);
         }

Modified: tomcat/trunk/java/org/apache/coyote/AbstractProtocol.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/AbstractProtocol.java?rev=1563206&r1=1563205&r2=1563206&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/AbstractProtocol.java (original)
+++ tomcat/trunk/java/org/apache/coyote/AbstractProtocol.java Fri Jan 31 
18:34:18 2014
@@ -609,6 +609,7 @@ public abstract class AbstractProtocol<S
             }
 
             wrapper.setAsync(false);
+            ContainerThreadMarker.markAsContainerThread();
 
             try {
                 if (processor == null) {

Added: tomcat/trunk/java/org/apache/coyote/ContainerThreadMarker.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/ContainerThreadMarker.java?rev=1563206&view=auto
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/ContainerThreadMarker.java (added)
+++ tomcat/trunk/java/org/apache/coyote/ContainerThreadMarker.java Fri Jan 31 
18:34:18 2014
@@ -0,0 +1,35 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.coyote;
+
+public class ContainerThreadMarker {
+
+    private static final ThreadLocal<Boolean> marker = new ThreadLocal<>();
+
+    public static boolean isContainerThread() {
+        Boolean flag = marker.get();
+        if (flag == null) {
+            return false;
+        } else {
+            return flag.booleanValue();
+        }
+    }
+
+    public static void markAsContainerThread() {
+        marker.set(Boolean.TRUE);
+    }
+}

Propchange: tomcat/trunk/java/org/apache/coyote/ContainerThreadMarker.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: tomcat/trunk/java/org/apache/coyote/ajp/AjpNioProcessor.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/ajp/AjpNioProcessor.java?rev=1563206&r1=1563205&r2=1563206&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/ajp/AjpNioProcessor.java (original)
+++ tomcat/trunk/java/org/apache/coyote/ajp/AjpNioProcessor.java Fri Jan 31 
18:34:18 2014
@@ -59,17 +59,20 @@ public class AjpNioProcessor extends Abs
 
     @Override
     protected void registerForEvent(boolean read, boolean write) {
+        final NioChannel socket = socketWrapper.getSocket();
         final NioEndpoint.KeyAttachment attach =
-                
(NioEndpoint.KeyAttachment)socketWrapper.getSocket().getAttachment(
-                        false);
+                (NioEndpoint.KeyAttachment) socket.getAttachment(false);
         if (attach == null) {
             return;
         }
+        SelectionKey key = 
socket.getIOChannel().keyFor(socket.getPoller().getSelector());
         if (read) {
             attach.interestOps(attach.interestOps() | SelectionKey.OP_READ);
+            key.interestOps(key.interestOps() | SelectionKey.OP_READ);
         }
         if (write) {
             attach.interestOps(attach.interestOps() | SelectionKey.OP_WRITE);
+            key.interestOps(key.interestOps() | SelectionKey.OP_READ);
         }
     }
 

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=1563206&r1=1563205&r2=1563206&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http11/Http11NioProcessor.java 
(original)
+++ tomcat/trunk/java/org/apache/coyote/http11/Http11NioProcessor.java Fri Jan 
31 18:34:18 2014
@@ -154,17 +154,20 @@ public class Http11NioProcessor extends 
 
     @Override
     protected void registerForEvent(boolean read, boolean write) {
+        final NioChannel socket = socketWrapper.getSocket();
         final NioEndpoint.KeyAttachment attach =
-                
(NioEndpoint.KeyAttachment)socketWrapper.getSocket().getAttachment(
-                        false);
+                (NioEndpoint.KeyAttachment) socket.getAttachment(false);
         if (attach == null) {
             return;
         }
+        SelectionKey key = 
socket.getIOChannel().keyFor(socket.getPoller().getSelector());
         if (read) {
             attach.interestOps(attach.interestOps() | SelectionKey.OP_READ);
+            key.interestOps(key.interestOps() | SelectionKey.OP_READ);
         }
         if (write) {
             attach.interestOps(attach.interestOps() | SelectionKey.OP_WRITE);
+            key.interestOps(key.interestOps() | SelectionKey.OP_WRITE);
         }
     }
 

Modified: tomcat/trunk/webapps/docs/changelog.xml
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/changelog.xml?rev=1563206&r1=1563205&r2=1563206&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/changelog.xml (original)
+++ tomcat/trunk/webapps/docs/changelog.xml Fri Jan 31 18:34:18 2014
@@ -58,6 +58,14 @@
       </fix>
     </changelog>
   </subsection>
+  <subsection name="Coyote">
+    <changelog>
+      <fix>
+        Enable non-blocking reads to take place on non-container threads.
+        (markt)
+      </fix>
+    </changelog>
+  </subsection>
   <subsection name="Cluster">
     <changelog>
       <scode>



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

Reply via email to