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/01/23 20:03:12 UTC

svn commit: r1654323 - in /tomcat/trunk/java/org/apache: coyote/http11/ tomcat/util/net/

Author: markt
Date: Fri Jan 23 19:03:11 2015
New Revision: 1654323

URL: http://svn.apache.org/r1654323
Log:
Push socket type specific sendfile code down to SocketWrapper

Modified:
    tomcat/trunk/java/org/apache/coyote/http11/Http11AprProcessor.java
    tomcat/trunk/java/org/apache/coyote/http11/Http11Nio2Processor.java
    tomcat/trunk/java/org/apache/coyote/http11/Http11NioProcessor.java
    tomcat/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java
    tomcat/trunk/java/org/apache/tomcat/util/net/Nio2Endpoint.java
    tomcat/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java
    tomcat/trunk/java/org/apache/tomcat/util/net/SocketWrapperBase.java

Modified: tomcat/trunk/java/org/apache/coyote/http11/Http11AprProcessor.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http11/Http11AprProcessor.java?rev=1654323&r1=1654322&r2=1654323&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http11/Http11AprProcessor.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http11/Http11AprProcessor.java Fri Jan 23 19:03:11 2015
@@ -96,22 +96,19 @@ public class Http11AprProcessor extends
         // Do sendfile as needed: add socket to sendfile and end
         if (sendfileData != null && !getErrorState().isError()) {
             sendfileData.keepAlive = keepAlive;
-            sendfileData.socket = socketWrapper.getSocket().longValue();
-            if (!((AprEndpoint)endpoint).getSendfile().add(sendfileData)) {
-                // Didn't send all of the data to sendfile.
-                if (sendfileData.socket == 0) {
-                    // The socket is no longer set. Something went wrong.
-                    // Close the connection. Too late to set status code.
-                    if (log.isDebugEnabled()) {
-                        log.debug(sm.getString(
-                                "http11processor.sendfile.error"));
-                    }
-                    setErrorState(ErrorState.CLOSE_NOW, null);
-                } else {
-                    // The sendfile Poller will add the socket to the main
-                    // Poller once sendfile processing is complete
-                    sendfileInProgress = true;
+            switch (socketWrapper.processSendfile(sendfileData)) {
+            case DONE:
+                // If sendfile is complete, no need to break keep-alive loop
+                return false;
+            case PENDING:
+                sendfileInProgress = true;
+                return true;
+            case ERROR:
+                // Write failed
+                if (log.isDebugEnabled()) {
+                    log.debug(sm.getString("http11processor.sendfile.error"));
                 }
+                setErrorState(ErrorState.CLOSE_NOW, null);
                 return true;
             }
         }

Modified: tomcat/trunk/java/org/apache/coyote/http11/Http11Nio2Processor.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http11/Http11Nio2Processor.java?rev=1654323&r1=1654322&r2=1654323&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http11/Http11Nio2Processor.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http11/Http11Nio2Processor.java Fri Jan 23 19:03:11 2015
@@ -120,17 +120,18 @@ public class Http11Nio2Processor extends
 
 
     @Override
-    protected boolean breakKeepAliveLoop(
-            SocketWrapperBase<Nio2Channel> socketWrapper) {
+    protected boolean breakKeepAliveLoop(SocketWrapperBase<Nio2Channel> socketWrapper) {
         openSocket = keepAlive;
         // Do sendfile as needed: add socket to sendfile and end
         if (sendfileData != null && !getErrorState().isError()) {
             sendfileData.keepAlive = keepAlive;
-            ((Nio2Endpoint.Nio2SocketWrapper) socketWrapper).setSendfileData(sendfileData);
-            switch (((Nio2Endpoint) endpoint)
-                    .processSendfile((Nio2Endpoint.Nio2SocketWrapper) socketWrapper)) {
+            switch (socketWrapper.processSendfile(sendfileData)) {
             case DONE:
+                // If sendfile is complete, no need to break keep-alive loop
                 return false;
+            case PENDING:
+                sendfileInProgress = true;
+                return true;
             case ERROR:
                 // Write failed
                 if (log.isDebugEnabled()) {
@@ -138,9 +139,6 @@ public class Http11Nio2Processor extends
                 }
                 setErrorState(ErrorState.CLOSE_NOW, null);
                 return true;
-            case PENDING:
-                sendfileInProgress = true;
-                return true;
             }
         }
         return false;
@@ -155,7 +153,6 @@ public class Http11Nio2Processor extends
 
     // ----------------------------------------------------- ActionHook Methods
 
-
     /**
      * Send an action to the connector.
      *

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=1654323&r1=1654322&r2=1654323&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http11/Http11NioProcessor.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http11/Http11NioProcessor.java Fri Jan 23 19:03:11 2015
@@ -30,7 +30,6 @@ import org.apache.juli.logging.LogFactor
 import org.apache.tomcat.util.net.AbstractEndpoint;
 import org.apache.tomcat.util.net.NioChannel;
 import org.apache.tomcat.util.net.NioEndpoint;
-import org.apache.tomcat.util.net.NioEndpoint.NioSocketWrapper;
 import org.apache.tomcat.util.net.SSLSupport;
 import org.apache.tomcat.util.net.SecureNioChannel;
 import org.apache.tomcat.util.net.SocketWrapperBase;
@@ -119,21 +118,21 @@ public class Http11NioProcessor extends
         // Do sendfile as needed: add socket to sendfile and end
         if (sendfileData != null && !getErrorState().isError()) {
             sendfileData.keepAlive = keepAlive;
-            ((NioSocketWrapper) socketWrapper).setSendfileData(sendfileData);
-            SelectionKey key = socketWrapper.getSocket().getIOChannel().keyFor(
-                    socketWrapper.getSocket().getPoller().getSelector());
-            //do the first write on this thread, might as well
-            if (socketWrapper.getSocket().getPoller().processSendfile(key,
-                    (NioSocketWrapper) socketWrapper, true)) {
+            switch (socketWrapper.processSendfile(sendfileData)) {
+            case DONE:
+                // If sendfile is complete, no need to break keep-alive loop
+                return false;
+            case PENDING:
                 sendfileInProgress = true;
-            } else {
+                return true;
+            case ERROR:
                 // Write failed
                 if (log.isDebugEnabled()) {
                     log.debug(sm.getString("http11processor.sendfile.error"));
                 }
                 setErrorState(ErrorState.CLOSE_NOW, null);
+                return true;
             }
-            return true;
         }
         return false;
     }

Modified: tomcat/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java?rev=1654323&r1=1654322&r2=1654323&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java Fri Jan 23 19:03:11 2015
@@ -1919,10 +1919,10 @@ public class AprEndpoint extends Abstrac
      */
     public static class SendfileData extends SendfileDataBase {
         // File
-        public long fd;
-        public long fdpool;
+        protected long fd;
+        protected long fdpool;
         // Socket and socket pool
-        public long socket;
+        protected long socket;
     }
 
 
@@ -2010,7 +2010,7 @@ public class AprEndpoint extends Abstrac
          * @return true if all the data has been sent right away, and false
          *              otherwise
          */
-        public boolean add(SendfileData data) {
+        public SendfileState add(SendfileData data) {
             // Initialize fd from data given
             try {
                 data.fdpool = Socket.pool(data.socket);
@@ -2027,7 +2027,7 @@ public class AprEndpoint extends Abstrac
                         if (!(-nw == Status.EAGAIN)) {
                             Pool.destroy(data.fdpool);
                             data.socket = 0;
-                            return false;
+                            return SendfileState.ERROR;
                         } else {
                             // Break the loop and add the socket to poller.
                             break;
@@ -2039,15 +2039,14 @@ public class AprEndpoint extends Abstrac
                             // Entire file has been sent
                             Pool.destroy(data.fdpool);
                             // Set back socket to blocking mode
-                            Socket.timeoutSet(
-                                    data.socket, getSoTimeout() * 1000);
-                            return true;
+                            Socket.timeoutSet(data.socket, getSoTimeout() * 1000);
+                            return SendfileState.DONE;
                         }
                     }
                 }
             } catch (Exception e) {
                 log.warn(sm.getString("endpoint.sendfile.error"), e);
-                return false;
+                return SendfileState.ERROR;
             }
             // Add socket to the list. Newly added sockets will wait
             // at most for pollTime before being polled
@@ -2055,7 +2054,7 @@ public class AprEndpoint extends Abstrac
                 addS.add(data);
                 this.notify();
             }
-            return false;
+            return SendfileState.PENDING;
         }
 
         /**
@@ -2643,5 +2642,12 @@ public class AprEndpoint extends Abstrac
             ((AprEndpoint) getEndpoint()).getPoller().add(
                     getSocket().longValue(), -1, read, write);
         }
+
+
+        @Override
+        public SendfileState processSendfile(SendfileDataBase sendfileData) {
+            ((SendfileData) sendfileData).socket = getSocket().longValue();
+            return ((AprEndpoint) getEndpoint()).getSendfile().add((SendfileData) sendfileData);
+        }
     }
 }

Modified: tomcat/trunk/java/org/apache/tomcat/util/net/Nio2Endpoint.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/Nio2Endpoint.java?rev=1654323&r1=1654322&r2=1654323&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/Nio2Endpoint.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/Nio2Endpoint.java Fri Jan 23 19:03:11 2015
@@ -1291,6 +1291,7 @@ public class Nio2Endpoint extends Abstra
             // NO-OP. Appropriate handlers will already have been registered.
         }
 
+
         public void awaitBytes() {
             if (getSocket() == null) {
                 return;
@@ -1304,6 +1305,12 @@ public class Nio2Endpoint extends Abstra
             }
         }
 
+
+        @Override
+        public SendfileState processSendfile(SendfileDataBase sendfileData) {
+            setSendfileData((SendfileData) sendfileData);
+            return ((Nio2Endpoint) getEndpoint()).processSendfile(this);
+        }
     }
 
 
@@ -1612,7 +1619,7 @@ public class Nio2Endpoint extends Abstra
      * SendfileData class.
      */
     public static class SendfileData extends SendfileDataBase {
-        public FileChannel fchannel;
+        protected FileChannel fchannel;
         // Internal use only
         private Nio2SocketWrapper socket;
         private ByteBuffer buffer;

Modified: tomcat/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java?rev=1654323&r1=1654322&r2=1654323&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java Fri Jan 23 19:03:11 2015
@@ -1114,45 +1114,51 @@ public class NioEndpoint extends Abstrac
             return result;
         }
 
-        public boolean processSendfile(SelectionKey sk, NioSocketWrapper attachment, boolean event) {
+        public SendfileState processSendfile(SelectionKey sk, NioSocketWrapper socketWrapper, boolean event) {
             NioChannel sc = null;
             try {
-                unreg(sk, attachment, sk.readyOps());
-                SendfileData sd = attachment.getSendfileData();
+                unreg(sk, socketWrapper, sk.readyOps());
+                SendfileData sd = socketWrapper.getSendfileData();
 
                 if (log.isTraceEnabled()) {
                     log.trace("Processing send file for: " + sd.fileName);
                 }
 
-                //setup the file channel
-                if ( sd.fchannel == null ) {
+                // This method is called by the Http11Processor for the first
+                // execution and then subsequent executions are via the Poller.
+                // This boolean keeps track of the current caller as the
+                // required behaviour varies slightly.
+                boolean calledByProcessor = (sd.fchannel == null);
+
+                if (calledByProcessor) {
+                    // Setup the file channel
                     File f = new File(sd.fileName);
-                    if ( !f.exists() ) {
+                    if (!f.exists()) {
                         cancelledKey(sk);
-                        return false;
+                        return SendfileState.ERROR;
                     }
                     @SuppressWarnings("resource") // Closed when channel is closed
                     FileInputStream fis = new FileInputStream(f);
                     sd.fchannel = fis.getChannel();
                 }
 
-                //configure output channel
-                sc = attachment.getSocket();
+                // Configure output channel
+                sc = socketWrapper.getSocket();
                 sc.setSendFile(true);
-                //ssl channel is slightly different
+                // TLS/SSL channel is slightly different
                 WritableByteChannel wc = ((sc instanceof SecureNioChannel)?sc:sc.getIOChannel());
 
-                //we still have data in the buffer
+                // We still have data in the buffer
                 if (sc.getOutboundRemaining()>0) {
                     if (sc.flushOutbound()) {
-                        attachment.access();
+                        socketWrapper.access();
                     }
                 } else {
                     long written = sd.fchannel.transferTo(sd.pos,sd.length,wc);
-                    if ( written > 0 ) {
+                    if (written > 0) {
                         sd.pos += written;
                         sd.length -= written;
-                        attachment.access();
+                        socketWrapper.access();
                     } else {
                         // Unusual not to be able to transfer any bytes
                         // Check the length was set correctly
@@ -1162,53 +1168,57 @@ public class NioEndpoint extends Abstrac
                         }
                     }
                 }
-                if ( sd.length <= 0 && sc.getOutboundRemaining()<=0) {
+                if (sd.length <= 0 && sc.getOutboundRemaining()<=0) {
                     if (log.isDebugEnabled()) {
                         log.debug("Send file complete for: "+sd.fileName);
                     }
-                    attachment.setSendfileData(null);
+                    socketWrapper.setSendfileData(null);
                     try {
                         sd.fchannel.close();
                     } catch (Exception ignore) {
                     }
-                    if ( sd.keepAlive ) {
+                    if (!calledByProcessor) {
+                        if (sd.keepAlive) {
                             if (log.isDebugEnabled()) {
                                 log.debug("Connection is keep alive, registering back for OP_READ");
                             }
                             if (event) {
-                                this.add(attachment.getSocket(),SelectionKey.OP_READ);
+                                this.add(socketWrapper.getSocket(),SelectionKey.OP_READ);
                             } else {
-                                reg(sk,attachment,SelectionKey.OP_READ);
+                                reg(sk,socketWrapper,SelectionKey.OP_READ);
                             }
-                    } else {
-                        if (log.isDebugEnabled()) {
-                            log.debug("Send file connection is being closed");
+                        } else {
+                            if (log.isDebugEnabled()) {
+                                log.debug("Send file connection is being closed");
+                            }
+                            cancelledKey(sk);
                         }
-                        cancelledKey(sk);
-                        return false;
                     }
+                    return SendfileState.DONE;
                 } else {
-                    if (log.isDebugEnabled()) {
-                        log.debug("OP_WRITE for sendfile: " + sd.fileName);
-                    }
-                    if (event) {
-                        add(attachment.getSocket(),SelectionKey.OP_WRITE);
-                    } else {
-                        reg(sk,attachment,SelectionKey.OP_WRITE);
+                    if (!calledByProcessor) {
+                        if (log.isDebugEnabled()) {
+                            log.debug("OP_WRITE for sendfile: " + sd.fileName);
+                        }
+                        if (event) {
+                            add(socketWrapper.getSocket(),SelectionKey.OP_WRITE);
+                        } else {
+                            reg(sk,socketWrapper,SelectionKey.OP_WRITE);
+                        }
                     }
+                    return SendfileState.PENDING;
                 }
-            }catch ( IOException x ) {
-                if ( log.isDebugEnabled() ) log.debug("Unable to complete sendfile request:", x);
+            } catch (IOException x) {
+                if (log.isDebugEnabled()) log.debug("Unable to complete sendfile request:", x);
                 cancelledKey(sk);
-                return false;
-            }catch ( Throwable t ) {
-                log.error("",t);
+                return SendfileState.ERROR;
+            } catch (Throwable t) {
+                log.error("", t);
                 cancelledKey(sk);
-                return false;
-            }finally {
+                return SendfileState.ERROR;
+            } finally {
                 if (sc!=null) sc.setSendFile(false);
             }
-            return true;
         }
 
         protected void unreg(SelectionKey sk, NioSocketWrapper attachment, int readyOps) {
@@ -1575,6 +1585,16 @@ public class NioEndpoint extends Abstrac
                 key.interestOps(key.interestOps() | SelectionKey.OP_READ);
             }
         }
+
+
+        @Override
+        public SendfileState processSendfile(SendfileDataBase sendfileData) {
+            setSendfileData((SendfileData) sendfileData);
+            SelectionKey key = getSocket().getIOChannel().keyFor(
+                    getSocket().getPoller().getSelector());
+            // Might as well do the first write on this thread
+            return getSocket().getPoller().processSendfile(key, this, true);
+        }
     }
 
 
@@ -1756,6 +1776,6 @@ public class NioEndpoint extends Abstrac
      * SendfileData class.
      */
     public static class SendfileData extends SendfileDataBase {
-        public volatile FileChannel fchannel;
+        protected volatile FileChannel fchannel;
     }
 }

Modified: tomcat/trunk/java/org/apache/tomcat/util/net/SocketWrapperBase.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/SocketWrapperBase.java?rev=1654323&r1=1654322&r2=1654323&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/SocketWrapperBase.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/SocketWrapperBase.java Fri Jan 23 19:03:11 2015
@@ -511,6 +511,8 @@ public abstract class SocketWrapperBase<
 
     public abstract void regsiterForEvent(boolean read, boolean write);
 
+    public abstract SendfileState processSendfile(SendfileDataBase sendfileData);
+
 
     // --------------------------------------------------------- Utility methods
 



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