tomcat-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ma...@apache.org
Subject svn commit: r1103308 - in /tomcat/trunk/java/org/apache/coyote/ajp: AjpNioProcessor.java LocalStrings.properties
Date Sun, 15 May 2011 10:00:23 GMT
Author: markt
Date: Sun May 15 10:00:22 2011
New Revision: 1103308

URL: http://svn.apache.org/viewvc?rev=1103308&view=rev
Log:
Make AJP-NIO actually use non-blocking reads.
Only the first read of a request is is non-blocking. Any additional reads will block.
The first read of the first request on a new connection will also block.

Modified:
    tomcat/trunk/java/org/apache/coyote/ajp/AjpNioProcessor.java
    tomcat/trunk/java/org/apache/coyote/ajp/LocalStrings.properties

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=1103308&r1=1103307&r2=1103308&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/ajp/AjpNioProcessor.java (original)
+++ tomcat/trunk/java/org/apache/coyote/ajp/AjpNioProcessor.java Sun May 15 10:00:22 2011
@@ -216,6 +216,8 @@ public class AjpNioProcessor extends Abs
         // Error flag
         error = false;
 
+        boolean keptAlive = false;
+
         while (!error && !endpoint.isPaused()) {
 
             // Parsing the request header
@@ -225,8 +227,9 @@ public class AjpNioProcessor extends Abs
                     ka.setTimeout(keepAliveTimeout);
                 }
                 // Get first message of the request
-                if (!readMessage(requestHeaderMessage)) {
-                    // This means a connection timeout
+                int bytesRead = readMessage(requestHeaderMessage, !keptAlive);
+                if (!keptAlive && bytesRead == 0) {
+                    // No bytes on a blocking read - connection timeout
                     rp.setStage(org.apache.coyote.Constants.STAGE_ENDED);
                     break;
                 }
@@ -243,6 +246,8 @@ public class AjpNioProcessor extends Abs
                     } catch (IOException e) {
                         error = true;
                     }
+                    // Should be unnecessary but just in case...
+                    keptAlive = true;
                     recycle();
                     continue;
                 } else if(type != Constants.JK_AJP13_FORWARD_REQUEST) {
@@ -250,6 +255,8 @@ public class AjpNioProcessor extends Abs
                     if(log.isDebugEnabled()) {
                         log.debug("Unexpected message: "+type);
                     }
+                    // Should be unnecessary but just in case...
+                    keptAlive = true;
                     recycle();
                     continue;
                 }
@@ -328,13 +335,18 @@ public class AjpNioProcessor extends Abs
             request.updateCounters();
 
             rp.setStage(org.apache.coyote.Constants.STAGE_KEEPALIVE);
+            keptAlive = true;
             recycle();
         }
         
         rp.setStage(org.apache.coyote.Constants.STAGE_ENDED);
 
-        if (isAsync() && !error && !endpoint.isPaused()) {
-            return SocketState.LONG;
+        if (!error && !endpoint.isPaused()) {
+            if (isAsync()) {
+                return SocketState.LONG;
+            } else {
+                return SocketState.OPEN;
+            }
         } else {
             readBuffer = null;
             writeBuffer = null;
@@ -494,13 +506,13 @@ public class AjpNioProcessor extends Abs
      * Read at least the specified amount of bytes, and place them
      * in the input buffer.
      */
-    protected void read(byte[] buf, int pos, int n)
+    protected int read(byte[] buf, int pos, int n, boolean block)
         throws IOException {
 
         int read = readBufferEnd - pos;
         int res = 0;
         while (read < n) {
-            res = readSocket(buf, read + pos, true);
+            res = readSocket(buf, read + pos, block);
             if (res > 0) {
                 read += res;
             } else {
@@ -508,6 +520,7 @@ public class AjpNioProcessor extends Abs
             }
         }
         readBufferEnd += read;
+        return read;
     }
 
     private int readSocket(byte[] buf, int pos, boolean block) throws IOException {
@@ -555,10 +568,9 @@ public class AjpNioProcessor extends Abs
 
         first = false;
         bodyMessage.reset();
-        if (!readMessage(bodyMessage)) {
-            // Invalid message
-            return false;
-        }
+        
+        readMessage(bodyMessage, true);
+
         // No data received.
         if (bodyMessage.getLen() == 0) {
             // just the header
@@ -607,27 +619,26 @@ public class AjpNioProcessor extends Abs
     /**
      * Read an AJP message.
      *
-     * @return true if the message has been read, false if the short read
-     *         didn't return anything
+     * @return The number of bytes read
      * @throws IOException any other failure, including incomplete reads
      */
-    protected boolean readMessage(AjpMessage message)
+    protected int readMessage(AjpMessage message, boolean block)
         throws IOException {
 
         byte[] buf = message.getBuffer();
         int headerLength = message.getHeaderLength();
 
-        read(buf, 0, headerLength);
+        int bytesRead = read(buf, 0, headerLength, block);
 
         int messageLength = message.processHeader();
         if (messageLength < 0) {
             // Invalid AJP header signature
-            // TODO: Throw some exception and close the connection to frontend.
-            return false;
+            throw new IOException(sm.getString("ajpmessage.invalidLength",
+                    Integer.valueOf(messageLength)));
         }
         else if (messageLength == 0) {
             // Zero length message.
-            return true;
+            return bytesRead;
         }
         else {
             if (messageLength > buf.length) {
@@ -638,8 +649,8 @@ public class AjpNioProcessor extends Abs
                         Integer.valueOf(messageLength),
                         Integer.valueOf(buf.length)));
             }
-            read(buf, headerLength, messageLength);
-            return true;
+            bytesRead += read(buf, headerLength, messageLength, true);
+            return bytesRead;
         }
     }
 

Modified: tomcat/trunk/java/org/apache/coyote/ajp/LocalStrings.properties
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/ajp/LocalStrings.properties?rev=1103308&r1=1103307&r2=1103308&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/ajp/LocalStrings.properties (original)
+++ tomcat/trunk/java/org/apache/coyote/ajp/LocalStrings.properties Sun May 15 10:00:22 2011
@@ -44,4 +44,5 @@ ajpmessage.null=Cannot append null value
 ajpmessage.overflow=Overflow error for buffer adding {0} bytes at position {1}
 ajpmessage.read=Requested {0} bytes exceeds message available data
 ajpmessage.invalid=Invalid message received with signature {0}
+ajpmessage.invalidLength=Invalid message received with length {0}
 



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


Mime
View raw message