|
|
9e6f2c |
--- java/org/apache/coyote/AbstractProtocol.java.orig 2017-08-18 09:12:05.149568367 -0400
|
|
|
9e6f2c |
+++ java/org/apache/coyote/AbstractProtocol.java 2017-08-18 09:12:55.998699189 -0400
|
|
|
9e6f2c |
@@ -693,10 +693,10 @@
|
|
|
75b9e1 |
release(wrapper, processor, false, true);
|
|
|
75b9e1 |
} else if (state == SocketState.SENDFILE) {
|
|
|
75b9e1 |
// Sendfile in progress. If it fails, the socket will be
|
|
|
75b9e1 |
- // closed. If it works, the socket will be re-added to the
|
|
|
75b9e1 |
- // poller
|
|
|
75b9e1 |
- connections.remove(socket);
|
|
|
75b9e1 |
- release(wrapper, processor, false, false);
|
|
|
75b9e1 |
+ // closed. If it works, the socket either be added to the
|
|
|
75b9e1 |
+ // poller (or equivalent) to await more data or processed
|
|
|
75b9e1 |
+ // if there are any pipe-lined requests remaining.
|
|
|
9e6f2c |
+ connections.put(socket, processor);
|
|
|
75b9e1 |
} else if (state == SocketState.UPGRADED) {
|
|
|
75b9e1 |
// Need to keep the connection associated with the processor
|
|
|
75b9e1 |
connections.put(socket, processor);
|
|
|
867542 |
--- java/org/apache/coyote/http11/Http11AprProcessor.java.orig 2017-06-08 16:23:31.983000742 -0400
|
|
|
867542 |
+++ java/org/apache/coyote/http11/Http11AprProcessor.java 2017-06-08 16:23:31.999000805 -0400
|
|
|
75b9e1 |
@@ -38,6 +38,7 @@
|
|
|
75b9e1 |
import org.apache.tomcat.util.net.AbstractEndpoint.Handler.SocketState;
|
|
|
75b9e1 |
import org.apache.tomcat.util.net.AprEndpoint;
|
|
|
75b9e1 |
import org.apache.tomcat.util.net.SSLSupport;
|
|
|
75b9e1 |
+import org.apache.tomcat.util.net.SendfileKeepAliveState;
|
|
|
75b9e1 |
import org.apache.tomcat.util.net.SocketStatus;
|
|
|
75b9e1 |
import org.apache.tomcat.util.net.SocketWrapper;
|
|
|
75b9e1 |
|
|
|
75b9e1 |
@@ -211,7 +212,15 @@
|
|
|
75b9e1 |
// Do sendfile as needed: add socket to sendfile and end
|
|
|
75b9e1 |
if (sendfileData != null && !getErrorState().isError()) {
|
|
|
75b9e1 |
sendfileData.socket = socketWrapper.getSocket().longValue();
|
|
|
75b9e1 |
- sendfileData.keepAlive = keepAlive;
|
|
|
75b9e1 |
+ if (keepAlive) {
|
|
|
75b9e1 |
+ if (getInputBuffer().available() == 0) {
|
|
|
75b9e1 |
+ sendfileData.keepAliveState = SendfileKeepAliveState.OPEN;
|
|
|
75b9e1 |
+ } else {
|
|
|
75b9e1 |
+ sendfileData.keepAliveState = SendfileKeepAliveState.PIPELINED;
|
|
|
75b9e1 |
+ }
|
|
|
75b9e1 |
+ } else {
|
|
|
75b9e1 |
+ sendfileData.keepAliveState = SendfileKeepAliveState.NONE;
|
|
|
75b9e1 |
+ }
|
|
|
867542 |
switch (((AprEndpoint)endpoint).getSendfile().add(sendfileData)) {
|
|
|
867542 |
case DONE:
|
|
|
867542 |
return false;
|
|
|
867542 |
--- java/org/apache/coyote/http11/Http11NioProcessor.java.orig 2017-06-08 16:23:31.984000746 -0400
|
|
|
867542 |
+++ java/org/apache/coyote/http11/Http11NioProcessor.java 2017-06-08 16:23:32.000000809 -0400
|
|
|
75b9e1 |
@@ -37,6 +37,7 @@
|
|
|
75b9e1 |
import org.apache.tomcat.util.net.NioEndpoint.KeyAttachment;
|
|
|
75b9e1 |
import org.apache.tomcat.util.net.SSLSupport;
|
|
|
75b9e1 |
import org.apache.tomcat.util.net.SecureNioChannel;
|
|
|
75b9e1 |
+import org.apache.tomcat.util.net.SendfileKeepAliveState;
|
|
|
75b9e1 |
import org.apache.tomcat.util.net.SocketStatus;
|
|
|
75b9e1 |
import org.apache.tomcat.util.net.SocketWrapper;
|
|
|
75b9e1 |
|
|
|
75b9e1 |
@@ -275,7 +276,15 @@
|
|
|
75b9e1 |
// Do sendfile as needed: add socket to sendfile and end
|
|
|
75b9e1 |
if (sendfileData != null && !getErrorState().isError()) {
|
|
|
75b9e1 |
((KeyAttachment) socketWrapper).setSendfileData(sendfileData);
|
|
|
75b9e1 |
- sendfileData.keepAlive = keepAlive;
|
|
|
75b9e1 |
+ if (keepAlive) {
|
|
|
75b9e1 |
+ if (getInputBuffer().available() == 0) {
|
|
|
75b9e1 |
+ sendfileData.keepAliveState = SendfileKeepAliveState.OPEN;
|
|
|
75b9e1 |
+ } else {
|
|
|
75b9e1 |
+ sendfileData.keepAliveState = SendfileKeepAliveState.PIPELINED;
|
|
|
75b9e1 |
+ }
|
|
|
75b9e1 |
+ } else {
|
|
|
75b9e1 |
+ sendfileData.keepAliveState = SendfileKeepAliveState.NONE;
|
|
|
75b9e1 |
+ }
|
|
|
75b9e1 |
SelectionKey key = socketWrapper.getSocket().getIOChannel().keyFor(
|
|
|
75b9e1 |
socketWrapper.getSocket().getPoller().getSelector());
|
|
|
75b9e1 |
//do the first write on this thread, might as well
|
|
|
867542 |
--- java/org/apache/tomcat/util/net/AprEndpoint.java.orig 2017-06-08 16:23:31.985000750 -0400
|
|
|
867542 |
+++ java/org/apache/tomcat/util/net/AprEndpoint.java 2017-06-08 16:23:32.001000813 -0400
|
|
|
867542 |
@@ -2106,7 +2106,7 @@
|
|
|
75b9e1 |
// Position
|
|
|
75b9e1 |
public long pos;
|
|
|
75b9e1 |
// KeepAlive flag
|
|
|
75b9e1 |
- public boolean keepAlive;
|
|
|
75b9e1 |
+ public SendfileKeepAliveState keepAliveState = SendfileKeepAliveState.NONE;
|
|
|
75b9e1 |
}
|
|
|
75b9e1 |
|
|
|
75b9e1 |
|
|
|
867542 |
@@ -2349,20 +2349,33 @@
|
|
|
75b9e1 |
state.pos = state.pos + nw;
|
|
|
75b9e1 |
if (state.pos >= state.end) {
|
|
|
75b9e1 |
remove(state);
|
|
|
75b9e1 |
- if (state.keepAlive) {
|
|
|
75b9e1 |
+ switch (state.keepAliveState) {
|
|
|
75b9e1 |
+ case NONE: {
|
|
|
75b9e1 |
+ // Close the socket since this is
|
|
|
75b9e1 |
+ // the end of the not keep-alive request.
|
|
|
75b9e1 |
+ closeSocket(state.socket);
|
|
|
75b9e1 |
+ break;
|
|
|
75b9e1 |
+ }
|
|
|
75b9e1 |
+ case PIPELINED: {
|
|
|
75b9e1 |
+ // Destroy file descriptor pool, which should close the file
|
|
|
75b9e1 |
+ Pool.destroy(state.fdpool);
|
|
|
75b9e1 |
+ Socket.timeoutSet(state.socket, getSoTimeout() * 1000);
|
|
|
75b9e1 |
+ // Process the pipelined request data
|
|
|
75b9e1 |
+ if (!processSocket(state.socket, SocketStatus.OPEN_READ)) {
|
|
|
75b9e1 |
+ closeSocket(state.socket);
|
|
|
75b9e1 |
+ }
|
|
|
75b9e1 |
+ break;
|
|
|
75b9e1 |
+ }
|
|
|
75b9e1 |
+ case OPEN: {
|
|
|
75b9e1 |
// Destroy file descriptor pool, which should close the file
|
|
|
75b9e1 |
Pool.destroy(state.fdpool);
|
|
|
75b9e1 |
- Socket.timeoutSet(state.socket,
|
|
|
75b9e1 |
- getSoTimeout() * 1000);
|
|
|
75b9e1 |
- // If all done put the socket back in the
|
|
|
75b9e1 |
- // poller for processing of further requests
|
|
|
75b9e1 |
- getPoller().add(
|
|
|
75b9e1 |
- state.socket, getKeepAliveTimeout(),
|
|
|
75b9e1 |
+ Socket.timeoutSet(state.socket, getSoTimeout() * 1000);
|
|
|
75b9e1 |
+ // Put the socket back in the poller for
|
|
|
75b9e1 |
+ // processing of further requests
|
|
|
75b9e1 |
+ getPoller().add(state.socket, getKeepAliveTimeout(),
|
|
|
75b9e1 |
true, false);
|
|
|
75b9e1 |
- } else {
|
|
|
75b9e1 |
- // Close the socket since this is
|
|
|
75b9e1 |
- // the end of not keep-alive request.
|
|
|
75b9e1 |
- closeSocket(state.socket);
|
|
|
75b9e1 |
+ break;
|
|
|
75b9e1 |
+ }
|
|
|
75b9e1 |
}
|
|
|
75b9e1 |
}
|
|
|
75b9e1 |
}
|
|
|
867542 |
--- java/org/apache/tomcat/util/net/NioEndpoint.java.orig 2017-06-08 16:23:31.987000757 -0400
|
|
|
867542 |
+++ java/org/apache/tomcat/util/net/NioEndpoint.java 2017-06-08 16:23:32.002000817 -0400
|
|
|
867542 |
@@ -1383,16 +1383,30 @@
|
|
|
75b9e1 |
// responsible for registering the socket for the
|
|
|
75b9e1 |
// appropriate event(s) if sendfile completes.
|
|
|
75b9e1 |
if (!calledByProcessor) {
|
|
|
75b9e1 |
- if ( sd.keepAlive ) {
|
|
|
867542 |
- if (log.isDebugEnabled()) {
|
|
|
867542 |
- log.debug("Connection is keep alive, registering back for OP_READ");
|
|
|
867542 |
- }
|
|
|
867542 |
- reg(sk,attachment,SelectionKey.OP_READ);
|
|
|
867542 |
- } else {
|
|
|
75b9e1 |
+ switch (sd.keepAliveState) {
|
|
|
75b9e1 |
+ case NONE: {
|
|
|
867542 |
if (log.isDebugEnabled()) {
|
|
|
75b9e1 |
log.debug("Send file connection is being closed");
|
|
|
75b9e1 |
}
|
|
|
75b9e1 |
cancelledKey(sk,SocketStatus.STOP,false);
|
|
|
75b9e1 |
+ break;
|
|
|
75b9e1 |
+ }
|
|
|
75b9e1 |
+ case PIPELINED: {
|
|
|
75b9e1 |
+ if (log.isDebugEnabled()) {
|
|
|
75b9e1 |
+ log.debug("Connection is keep alive, processing pipe-lined data");
|
|
|
75b9e1 |
+ }
|
|
|
75b9e1 |
+ if (!processSocket(sc, SocketStatus.OPEN_READ, true)) {
|
|
|
75b9e1 |
+ cancelledKey(sk, SocketStatus.DISCONNECT, false);
|
|
|
75b9e1 |
+ }
|
|
|
75b9e1 |
+ break;
|
|
|
75b9e1 |
+ }
|
|
|
75b9e1 |
+ case OPEN: {
|
|
|
75b9e1 |
+ if (log.isDebugEnabled()) {
|
|
|
75b9e1 |
+ log.debug("Connection is keep alive, registering back for OP_READ");
|
|
|
75b9e1 |
+ }
|
|
|
75b9e1 |
+ reg(sk, attachment, SelectionKey.OP_READ);
|
|
|
75b9e1 |
+ break;
|
|
|
75b9e1 |
+ }
|
|
|
75b9e1 |
}
|
|
|
75b9e1 |
}
|
|
|
75b9e1 |
return SendfileState.DONE;
|
|
|
867542 |
@@ -1836,6 +1850,6 @@
|
|
|
75b9e1 |
public volatile long pos;
|
|
|
75b9e1 |
public volatile long length;
|
|
|
75b9e1 |
// KeepAlive flag
|
|
|
75b9e1 |
- public volatile boolean keepAlive;
|
|
|
75b9e1 |
+ public SendfileKeepAliveState keepAliveState = SendfileKeepAliveState.NONE;
|
|
|
75b9e1 |
}
|
|
|
75b9e1 |
}
|
|
|
867542 |
--- webapps/docs/changelog.xml.orig 2017-06-08 16:23:31.989000765 -0400
|
|
|
867542 |
+++ webapps/docs/changelog.xml 2017-06-08 16:25:23.618440723 -0400
|
|
|
867542 |
@@ -73,6 +73,13 @@
|
|
|
75b9e1 |
</fix>
|
|
|
75b9e1 |
</changelog>
|
|
|
75b9e1 |
</subsection>
|
|
|
75b9e1 |
+ <subsection name="Coyote">
|
|
|
75b9e1 |
+ <changelog>
|
|
|
75b9e1 |
+ <fix>
|
|
|
75b9e1 |
+ Improve sendfile handling when requests are pipelined. (markt)
|
|
|
75b9e1 |
+ </fix>
|
|
|
75b9e1 |
+ </changelog>
|
|
|
75b9e1 |
+ </subsection>
|
|
|
75b9e1 |
</section>
|
|
|
867542 |
<section name="Tomcat 7.0.76 (violetagg)">
|
|
|
867542 |
<subsection name="Catalina">
|
|
|
867542 |
--- java/org/apache/tomcat/util/net/SendfileKeepAliveState.java.orig 2017-06-08 16:23:31.992000777 -0400
|
|
|
867542 |
+++ java/org/apache/tomcat/util/net/SendfileKeepAliveState.java 2017-06-08 16:23:32.000000809 -0400
|
|
|
75b9e1 |
@@ -0,0 +1,39 @@
|
|
|
75b9e1 |
+/*
|
|
|
75b9e1 |
+ * Licensed to the Apache Software Foundation (ASF) under one or more
|
|
|
75b9e1 |
+ * contributor license agreements. See the NOTICE file distributed with
|
|
|
75b9e1 |
+ * this work for additional information regarding copyright ownership.
|
|
|
75b9e1 |
+ * The ASF licenses this file to You under the Apache License, Version 2.0
|
|
|
75b9e1 |
+ * (the "License"); you may not use this file except in compliance with
|
|
|
75b9e1 |
+ * the License. You may obtain a copy of the License at
|
|
|
75b9e1 |
+ *
|
|
|
75b9e1 |
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
|
75b9e1 |
+ *
|
|
|
75b9e1 |
+ * Unless required by applicable law or agreed to in writing, software
|
|
|
75b9e1 |
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
75b9e1 |
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
75b9e1 |
+ * See the License for the specific language governing permissions and
|
|
|
75b9e1 |
+ * limitations under the License.
|
|
|
75b9e1 |
+ */
|
|
|
75b9e1 |
+package org.apache.tomcat.util.net;
|
|
|
75b9e1 |
+
|
|
|
75b9e1 |
+public enum SendfileKeepAliveState {
|
|
|
75b9e1 |
+
|
|
|
75b9e1 |
+ /**
|
|
|
75b9e1 |
+ * Keep-alive is not in use. The socket can be closed when the response has
|
|
|
75b9e1 |
+ * been written.
|
|
|
75b9e1 |
+ */
|
|
|
75b9e1 |
+ NONE,
|
|
|
75b9e1 |
+
|
|
|
75b9e1 |
+ /**
|
|
|
75b9e1 |
+ * Keep-alive is in use and there is pipelined data in the input buffer to
|
|
|
75b9e1 |
+ * be read as soon as the current response has been written.
|
|
|
75b9e1 |
+ */
|
|
|
75b9e1 |
+ PIPELINED,
|
|
|
75b9e1 |
+
|
|
|
75b9e1 |
+ /**
|
|
|
75b9e1 |
+ * Keep-alive is in use. The socket should be added to the poller (or
|
|
|
75b9e1 |
+ * equivalent) to await more data as soon as the current response has been
|
|
|
75b9e1 |
+ * written.
|
|
|
75b9e1 |
+ */
|
|
|
75b9e1 |
+ OPEN
|
|
|
75b9e1 |
+}
|