Author: fhanik
Date: Wed Jan 14 16:13:39 2009
New Revision: 734574

URL: http://svn.apache.org/viewvc?rev=734574&view=rev
Log:
implement last of NIO fixes

Modified:
    tomcat/tc6.0.x/trunk/STATUS.txt
    tomcat/tc6.0.x/trunk/java/org/apache/coyote/http11/Http11NioProtocol.java
    tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/NioChannel.java
    tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java
    tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/SecureNioChannel.java
    tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml

Modified: tomcat/tc6.0.x/trunk/STATUS.txt
URL: 
http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/STATUS.txt?rev=734574&r1=734573&r2=734574&view=diff
==============================================================================
--- tomcat/tc6.0.x/trunk/STATUS.txt (original)
+++ tomcat/tc6.0.x/trunk/STATUS.txt Wed Jan 14 16:13:39 2009
@@ -118,18 +118,6 @@
             really old to me, so where would this come from ?)
   -1: 
 
-* [4] Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=45154 (add 
sendfile support to NIO/SSL) - performance improvement
-  http://svn.apache.org/viewvc?rev=720724&view=rev
-  http://svn.apache.org/viewvc?rev=720728&view=rev 
-  http://svn.apache.org/viewvc?rev=725417&view=rev
-  +1: fhanik, jim, markt
-  -1: 
-  
-* [5] Fix Comet interest registration bug
-  http://people.apache.org/~fhanik/tomcat/comet-ops.patch
-  +1: fhanik, funkman, markt
-  -1: 
-
 * Changes required to run with a security manager
   http://svn.apache.org/viewvc?rev=721286&view=rev
   http://svn.apache.org/viewvc?rev=721704&view=rev

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=734574&r1=734573&r2=734574&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 14 16:13:39 2009
@@ -309,7 +309,6 @@
     public void setUseSendfile(boolean useSendfile) {
         ep.setUseSendfile(useSendfile);
     }
-
     
     // -------------------- Tcp setup --------------------
 

Modified: tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/NioChannel.java
URL: 
http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/NioChannel.java?rev=734574&r1=734573&r2=734574&view=diff
==============================================================================
--- tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/NioChannel.java 
(original)
+++ tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/NioChannel.java Wed 
Jan 14 16:13:39 2009
@@ -47,6 +47,8 @@
     protected ApplicationBufferHandler bufHandler;
 
     protected Poller poller;
+    
+    protected boolean sendFile = false;
 
     public NioChannel(SocketChannel channel, ApplicationBufferHandler 
bufHandler) throws IOException {
         this.sc = channel;
@@ -56,6 +58,7 @@
     public void reset() throws IOException {
         bufHandler.getReadBuffer().clear();
         bufHandler.getWriteBuffer().clear();
+        this.sendFile = false;
     }
     
     public int getBufferSize() {
@@ -191,5 +194,27 @@
     public String toString() {
         return super.toString()+":"+this.sc.toString();
     }
+    
+    public int getOutboundRemaining() {
+        return 0;
+    }
+    
+    /**
+     * Return true if the buffer wrote data
+     * @return
+     * @throws IOException
+     */
+    public boolean flushOutbound() throws IOException {
+        return false;
+    }
+    
+    public boolean isSendFile() {
+        return sendFile;
+    }
+    
+    public void setSendFile(boolean s) {
+        this.sendFile = s;
+    }
+    
 
 }

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=734574&r1=734573&r2=734574&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 14 16:13:39 2009
@@ -30,6 +30,7 @@
 import java.nio.channels.Selector;
 import java.nio.channels.ServerSocketChannel;
 import java.nio.channels.SocketChannel;
+import java.nio.channels.WritableByteChannel;
 import java.security.KeyStore;
 import java.util.Collection;
 import java.util.Iterator;
@@ -491,7 +492,7 @@
     /**
      * Poller thread count.
      */
-    protected int pollerThreadCount = 1;
+    protected int pollerThreadCount = 
Runtime.getRuntime().availableProcessors();
     public void setPollerThreadCount(int pollerThreadCount) { 
this.pollerThreadCount = pollerThreadCount; }
     public int getPollerThreadCount() { return pollerThreadCount; }
 
@@ -501,9 +502,15 @@
     /**
      * The socket poller.
      */
-    protected Poller poller = null;
+    protected Poller[] pollers = null;
+    protected AtomicInteger pollerRotater = new AtomicInteger(0);
+    /**
+     * Return an available poller in true round robin fashion
+     * @return
+     */
     public Poller getPoller0() {
-        return poller;
+        int idx = Math.abs(pollerRotater.incrementAndGet()) % pollers.length;
+        return pollers[idx];
     }
 
     /**
@@ -652,7 +659,6 @@
     }
 
     public void setUseSendfile(boolean useSendfile) {
-
         this.useSendfile = useSendfile;
     }
 
@@ -703,10 +709,14 @@
      * Number of keepalive sockets.
      */
     public int getKeepAliveCount() {
-        if (poller == null) {
+        if (pollers == null) {
             return 0;
         } else {
-                return poller.selector.keys().size();
+            int sum = 0;
+            for (int i=0; i<pollers.length; i++) {
+                sum += pollers[i].selector.keys().size();
+            }
+            return sum;
         }
     }
 
@@ -861,12 +871,15 @@
                 workers = new WorkerStack(maxThreads);
             }
 
-            // Start poller thread
-            poller = new Poller();
-            Thread pollerThread = new Thread(poller, getName() + 
"-ClientPoller");
-            pollerThread.setPriority(threadPriority);
-            pollerThread.setDaemon(true);
-            pollerThread.start();
+            // Start poller threads
+            pollers = new Poller[getPollerThreadCount()];
+            for (int i=0; i<pollers.length; i++) {
+                pollers[i] = new Poller();
+                Thread pollerThread = new Thread(pollers[i], getName() + 
"-ClientPoller-"+i);
+                pollerThread.setPriority(threadPriority);
+                pollerThread.setDaemon(true);
+                pollerThread.start();
+            }
 
             // Start acceptor threads
             for (int i = 0; i < acceptorThreadCount; i++) {
@@ -908,8 +921,11 @@
         if (running) {
             running = false;
             unlockAccept();
-                poller.destroy();
-            poller = null;
+            for (int i=0; pollers!=null && i<pollers.length; i++) {
+                if (pollers[i]==null) continue;
+                pollers[i].destroy();
+                pollers[i] = null;
+            }
         }
         eventCache.clear();
         keyCache.clear();
@@ -974,8 +990,7 @@
     }
 
     public boolean getUseSendfile() {
-        //send file doesn't work with SSL
-        return useSendfile && (!isSSLEnabled());
+        return useSendfile;
     }
 
     public int getOomParachute() {
@@ -1345,10 +1360,10 @@
                     } else {
                         cancel = true;
                     }
-                    if ( cancel ) 
getPoller0().cancelledKey(key,SocketStatus.ERROR,false);
+                    if ( cancel ) 
socket.getPoller().cancelledKey(key,SocketStatus.ERROR,false);
                 }catch (CancelledKeyException ckx) {
                     try {
-                        
getPoller0().cancelledKey(key,SocketStatus.DISCONNECT,true);
+                        
socket.getPoller().cancelledKey(key,SocketStatus.DISCONNECT,true);
                     }catch (Exception ignore) {}
                 }
             }//end if
@@ -1645,6 +1660,7 @@
         }
         
         public boolean processSendfile(SelectionKey sk, KeyAttachment 
attachment, boolean reg, boolean event) {
+            NioChannel sc = null;
             try {
                 //unreg(sk,attachment);//only do this if we do process send 
file on a separate thread
                 SendfileData sd = attachment.getSendfileData();
@@ -1656,13 +1672,23 @@
                     }
                     sd.fchannel = new FileInputStream(f).getChannel();
                 }
-                SocketChannel sc = attachment.getChannel().getIOChannel();
-                long written = sd.fchannel.transferTo(sd.pos,sd.length,sc);
-                if ( written > 0 ) {
-                    sd.pos += written;
-                    sd.length -= written;
+                sc = attachment.getChannel();
+                sc.setSendFile(true);
+                WritableByteChannel wc =(WritableByteChannel) ((sc instanceof 
SecureNioChannel)?sc:sc.getIOChannel());
+                
+                if (sc.getOutboundRemaining()>0) {
+                    if (sc.flushOutbound()) {
+                        attachment.access();
+                    }
+                } else {
+                    long written = sd.fchannel.transferTo(sd.pos,sd.length,wc);
+                    if ( written > 0 ) {
+                        sd.pos += written;
+                        sd.length -= written;
+                        attachment.access();
+                    }
                 }
-                if ( sd.length <= 0 ) {
+                if ( sd.length <= 0 && sc.getOutboundRemaining()<=0) {
                     if (log.isDebugEnabled()) {
                         log.debug("Send file complete for:"+sd.fileName);
                     }
@@ -1703,6 +1729,8 @@
                 log.error("",t);
                 cancelledKey(sk, SocketStatus.ERROR, false);
                 return false;
+            }finally {
+                if (sc!=null) sc.setSendFile(false);
             }
             return true;
         }
@@ -1738,14 +1766,15 @@
                     if ( ka == null ) {
                         cancelledKey(key, SocketStatus.ERROR,false); //we 
don't support any keys without attachments
                     } else if ( ka.getError() ) {
-                        cancelledKey(key, SocketStatus.ERROR,true);
+                        cancelledKey(key, SocketStatus.ERROR,true);//TODO this 
is not yet being used
                     } else if (ka.getComet() && ka.getCometNotify() ) {
                         ka.setCometNotify(false);
                         reg(key,ka,0);//avoid multiple calls, this gets 
reregistered after invokation
                         //if (!processSocket(ka.getChannel(), 
SocketStatus.OPEN_CALLBACK)) processSocket(ka.getChannel(), 
SocketStatus.DISCONNECT);
                         if (!processSocket(ka.getChannel(), 
SocketStatus.OPEN)) processSocket(ka.getChannel(), SocketStatus.DISCONNECT);
-                    }else if ((ka.interestOps()&SelectionKey.OP_READ) == 
SelectionKey.OP_READ) {
-                        //only timeout sockets that we are waiting for a read 
from
+                    }else if ((ka.interestOps()&SelectionKey.OP_READ) == 
SelectionKey.OP_READ ||
+                                 (ka.interestOps()&SelectionKey.OP_WRITE) == 
SelectionKey.OP_WRITE) {
+                        //only timeout sockets that we are waiting for a read 
from - or write (send file)
                         long delta = now - ka.getLastAccess();
                         long timeout = (ka.getTimeout()==-1)?((long) 
socketProperties.getSoTimeout()):(ka.getTimeout());
                         boolean isTimedout = delta > timeout;

Modified: 
tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/SecureNioChannel.java
URL: 
http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/SecureNioChannel.java?rev=734574&r1=734573&r2=734574&view=diff
==============================================================================
--- tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/SecureNioChannel.java 
(original)
+++ tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/SecureNioChannel.java 
Wed Jan 14 16:13:39 2009
@@ -400,7 +400,7 @@
             return written;
         } else {
             //make sure we can handle expand, and that we only use on buffer
-            if ( src != bufHandler.getWriteBuffer() ) throw new 
IllegalArgumentException("You can only write using the application write buffer 
provided by the handler.");
+            if ( (!this.isSendFile()) && (src != bufHandler.getWriteBuffer()) 
) throw new IllegalArgumentException("You can only write using the application 
write buffer provided by the handler.");
             //are we closing or closed?
             if ( closing || closed) throw new IOException("Channel is in 
closing state.");
 
@@ -434,6 +434,20 @@
         }
     }
     
+    @Override
+    public int getOutboundRemaining() {
+        return netOutBuffer.remaining();
+    }
+    
+    @Override
+    public boolean flushOutbound() throws IOException {
+        int remaining = netOutBuffer.remaining();
+        flush(netOutBuffer);
+        int remaining2= netOutBuffer.remaining();
+        return remaining2 < remaining;
+    }
+
+    
     /**
      * Callback interface to be able to expand buffers
      * when buffer overflow exceptions happen

Modified: tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml
URL: 
http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml?rev=734574&r1=734573&r2=734574&view=diff
==============================================================================
--- tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml (original)
+++ tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml Wed Jan 14 16:13:39 2009
@@ -237,6 +237,9 @@
   </subsection>
   <subsection name="Coyote">
     <changelog>
+      <fix><bug>45154</bug>
+        Implement SEND_FILE behavior for SSL connections using NIO (fhanik)
+      </fix>
       <update>
         Fix file descriptor leak during NIO send file behavior. (fhanik)
       </update>



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

Reply via email to