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 2017/01/04 16:51:22 UTC

svn commit: r1777342 - in /tomcat/tc6.0.x/trunk/java/org/apache: coyote/http11/Http11NioProcessor.java coyote/http11/Http11NioProtocol.java tomcat/util/net/NioEndpoint.java tomcat/util/net/SendfileState.java

Author: markt
Date: Wed Jan  4 16:51:21 2017
New Revision: 1777342

URL: http://svn.apache.org/viewvc?rev=1777342&view=rev
Log:
Align implementation of Poller.processSendFile() in 6.0.x with 7.0.x
Back-port additional changes required to support this.

Added:
    tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/SendfileState.java
      - copied unchanged from r1777213, tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/SendfileState.java
Modified:
    tomcat/tc6.0.x/trunk/java/org/apache/coyote/http11/Http11NioProcessor.java
    tomcat/tc6.0.x/trunk/java/org/apache/coyote/http11/Http11NioProtocol.java
    tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java

Modified: tomcat/tc6.0.x/trunk/java/org/apache/coyote/http11/Http11NioProcessor.java
URL: http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/coyote/http11/Http11NioProcessor.java?rev=1777342&r1=1777341&r2=1777342&view=diff
==============================================================================
--- tomcat/tc6.0.x/trunk/java/org/apache/coyote/http11/Http11NioProcessor.java (original)
+++ tomcat/tc6.0.x/trunk/java/org/apache/coyote/http11/Http11NioProcessor.java Wed Jan  4 16:51:21 2017
@@ -82,7 +82,7 @@ public class Http11NioProcessor implemen
     protected SSLSupport sslSupport;
 
     private int maxCookieCount = 200;
-    
+
     /*
      * Tracks how many internal filters are in the filter library so they
      * are skipped when looking for pluggable filters.
@@ -162,6 +162,13 @@ public class Http11NioProcessor implemen
 
 
     /**
+     * Flag that indicates that send file processing is in progress and that the
+     * socket should not be returned to the poller (where a poller is used).
+     */
+    protected boolean sendfileInProgress = false;
+
+
+    /**
      * HTTP/1.1 flag.
      */
     protected boolean http11 = true;
@@ -796,7 +803,7 @@ public class Http11NioProcessor implemen
         error = false;
         keepAlive = true;
         comet = false;
-
+        sendfileInProgress = false;
 
         int keepAliveLeft = maxKeepAliveRequests;
         long soTimeout = endpoint.getSoTimeout();
@@ -928,20 +935,11 @@ public class Http11NioProcessor implemen
                 outputBuffer.nextRequest();
             }
 
-            // Do sendfile as needed: add socket to sendfile and end
-            if (sendfileData != null && !error) {
-                KeyAttachment ka = (KeyAttachment)socket.getAttachment(false);
-                ka.setSendfileData(sendfileData);
-                sendfileData.keepAlive = keepAlive;
-                SelectionKey key = socket.getIOChannel().keyFor(socket.getPoller().getSelector());
-                //do the first write on this thread, might as well
-                openSocket = socket.getPoller().processSendfile(key,ka,true,true);
-                break;
-            }
-
-
             rp.setStage(org.apache.coyote.Constants.STAGE_KEEPALIVE);
 
+            if (breakKeepAliveLoop(socket)) {
+                break;
+            }
         }
 
         rp.setStage(org.apache.coyote.Constants.STAGE_ENDED);
@@ -953,15 +951,47 @@ public class Http11NioProcessor implemen
             } else {
                 return SocketState.LONG;
             }
+        } else if (sendfileInProgress) {
+            return SocketState.SENDFILE;
         } else {
-            if ( recycle ) recycle();
-            //return (openSocket) ? (SocketState.OPEN) : SocketState.CLOSED;
+            if (recycle) {
+                recycle();
+            }
             return (openSocket) ? (recycle?SocketState.OPEN:SocketState.LONG) : SocketState.CLOSED;
         }
 
     }
 
 
+    private boolean breakKeepAliveLoop(NioChannel socket) {
+        // Do sendfile as needed: add socket to sendfile and end
+        if (sendfileData != null && !error) {
+            KeyAttachment ka = (KeyAttachment)socket.getAttachment(false);
+            ka.setSendfileData(sendfileData);
+            sendfileData.keepAlive = keepAlive;
+            SelectionKey key = socket.getIOChannel().keyFor(socket.getPoller().getSelector());
+            //do the first write on this thread, might as well
+            switch (socket.getPoller().processSendfile(key, ka, true)) {
+            case DONE:
+                // If sendfile is complete, no need to break keep-alive loop
+                sendfileData = null;
+                return false;
+            case PENDING:
+                sendfileInProgress = true;
+                return true;
+            case ERROR:
+                // Write failed
+                if (log.isDebugEnabled()) {
+                    log.debug(sm.getString("http11processor.sendfile.error"));
+                }
+                error = true;
+                return true;
+            }
+        }
+        return false;
+    }
+
+
     public void endRequest() {
 
         // Finish the handling of the request
@@ -1261,7 +1291,7 @@ public class Http11NioProcessor implemen
         this.sslSupport = sslSupport;
     }
 
-    
+
     public int getMaxCookieCount() {
         return maxCookieCount;
     }
@@ -1271,7 +1301,7 @@ public class Http11NioProcessor implemen
         this.maxCookieCount = maxCookieCount;
     }
 
-        
+
     /**
      * Get the associated adapter.
      *

Modified: tomcat/tc6.0.x/trunk/java/org/apache/coyote/http11/Http11NioProtocol.java
URL: http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/coyote/http11/Http11NioProtocol.java?rev=1777342&r1=1777341&r2=1777342&view=diff
==============================================================================
--- tomcat/tc6.0.x/trunk/java/org/apache/coyote/http11/Http11NioProtocol.java (original)
+++ tomcat/tc6.0.x/trunk/java/org/apache/coyote/http11/Http11NioProtocol.java Wed Jan  4 16:51:21 2017
@@ -764,6 +764,12 @@ public class Http11NioProtocol extends A
                     // processor. Continue to poll for the next request.
                     release(socket, processor);
                     socket.getPoller().add(socket);
+                } else if (state == SocketState.SENDFILE) {
+                    // Sendfile in progress. If it fails, the socket will be
+                    // closed. If it works, the socket will be re-added to the
+                    // poller
+                    connections.remove(socket);
+                    release(socket, processor);
                 } else {
                     // Connection closed. OK to recycle the processor.
                     release(socket, processor);

Modified: tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java
URL: http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java?rev=1777342&r1=1777341&r2=1777342&view=diff
==============================================================================
--- tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java (original)
+++ tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java Wed Jan  4 16:51:21 2017
@@ -1740,7 +1740,7 @@ public class NioEndpoint extends Abstrac
                     NioChannel channel = attachment.getChannel();
                     if (sk.isReadable() || sk.isWritable() ) {
                         if ( attachment.getSendfileData() != null ) {
-                            processSendfile(sk,attachment,true, false);
+                            processSendfile(sk, attachment, false);
                         } else if ( attachment.getComet() ) {
                             //check if thread is available
                             if ( isWorkerAvailable() ) {
@@ -1785,7 +1785,8 @@ public class NioEndpoint extends Abstrac
             return result;
         }
 
-        public boolean processSendfile(SelectionKey sk, KeyAttachment attachment, boolean reg, boolean event) {
+        public SendfileState processSendfile(SelectionKey sk, KeyAttachment attachment,
+                boolean calledByProcessor) {
             NioChannel sc = null;
             try {
                 unreg(sk, attachment, sk.readyOps());
@@ -1800,7 +1801,7 @@ public class NioEndpoint extends Abstrac
                     File f = new File(sd.fileName);
                     if ( !f.exists() ) {
                         cancelledKey(sk,SocketStatus.ERROR,false);
-                        return false;
+                        return SendfileState.ERROR;
                     }
                     @SuppressWarnings("resource") // Closed when channel is closed
                     FileInputStream fis = new FileInputStream(f);
@@ -1844,7 +1845,7 @@ public class NioEndpoint extends Abstrac
                     // For calls from outside the Poller, the caller is
                     // responsible for registering the socket for the
                     // appropriate event(s) if sendfile completes.
-                    if (!event) {
+                    if (!calledByProcessor) {
                         if ( sd.keepAlive ) {
                             if (log.isDebugEnabled()) {
                                 log.debug("Connection is keep alive, registering back for OP_READ");
@@ -1855,29 +1856,29 @@ public class NioEndpoint extends Abstrac
                                 log.debug("Send file connection is being closed");
                             }
                             cancelledKey(sk,SocketStatus.STOP,false);
-                            return false;
                         }
                     }
+                    return SendfileState.DONE;
                 } else {
                     if (log.isDebugEnabled()) {
                         log.debug("OP_WRITE for sendfile: " + sd.fileName);
                     }
-                    if (event) {
+                    if (calledByProcessor) {
                         add(attachment.getChannel(),SelectionKey.OP_WRITE);
                     } else {
                         reg(sk,attachment,SelectionKey.OP_WRITE);
                     }
+                    return SendfileState.PENDING;
                 }
             }catch ( IOException x ) {
                 if ( log.isDebugEnabled() ) log.debug("Unable to complete sendfile request:", x);
                 cancelledKey(sk,SocketStatus.ERROR,false);
-                return false;
+                return SendfileState.ERROR;
             }catch ( Throwable t ) {
                 log.error("",t);
                 cancelledKey(sk, SocketStatus.ERROR, false);
-                return false;
+                return SendfileState.ERROR;
             }
-            return true;
         }
 
         protected void unreg(SelectionKey sk, KeyAttachment attachment, int readyOps) {
@@ -2245,7 +2246,7 @@ public class NioEndpoint extends Abstrac
      */
     public interface Handler {
         public enum SocketState {
-            OPEN, CLOSED, LONG
+            OPEN, CLOSED, LONG, SENDFILE
         }
         public SocketState process(NioChannel socket);
         public SocketState event(NioChannel socket, SocketStatus status);



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