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: [email protected]
For additional commands, e-mail: [email protected]