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-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org