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 2011/09/08 11:07:34 UTC
svn commit: r1166576 - in /tomcat/tc7.0.x/trunk: ./
java/org/apache/coyote/http11/ java/org/apache/tomcat/util/net/
webapps/docs/config/
Author: markt
Date: Thu Sep 8 09:07:34 2011
New Revision: 1166576
URL: http://svn.apache.org/viewvc?rev=1166576&view=rev
Log:
Merge re-factoring from trunk that pulled up HttpXXXProcessor.process(), better aligned the behaviour of the HTTP connectors and provided better support for infinite connection and/or keep-alive timeouts
Modified:
tomcat/tc7.0.x/trunk/ (props changed)
tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/AbstractHttp11Processor.java
tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11AprProcessor.java
tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11NioProcessor.java
tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11Processor.java
tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/AbstractEndpoint.java
tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java
tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/JIoEndpoint.java
tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java
tomcat/tc7.0.x/trunk/webapps/docs/config/http.xml
Propchange: tomcat/tc7.0.x/trunk/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Thu Sep 8 09:07:34 2011
@@ -1 +1 @@
-/tomcat/trunk:1156171,1156276,1156304,1156530,1156602,1157015,1157018,1157151,1157198,1157204,1157810,1157832,1157834,1157847,1157908,1157939,1158155,1158160,1158176,1158195,1158198-1158199,1158227,1158331,1158334-1158335,1158426,1160347,1160592,1160611,1160619,1160626,1160639,1160652,1160720-1160721,1160772,1160774,1160776,1161303,1161310,1161322,1161339,1161486,1161540,1161549,1161584,1162082,1162149,1162169,1162721,1162769,1162836,1162932,1163630,1164419,1164438,1164469,1164480,1164567,1165234,1166077,1166290,1166366
+/tomcat/trunk:1156171,1156276,1156304,1156530,1156602,1157015,1157018,1157151,1157198,1157204,1157810,1157832,1157834,1157847,1157908,1157939,1158155,1158160,1158176,1158195,1158198-1158199,1158227,1158331,1158334-1158335,1158426,1160347,1160592,1160611,1160619,1160626,1160639,1160652,1160720-1160721,1160772,1160774,1160776,1161303,1161310,1161322,1161339,1161486,1161540,1161549,1161584,1162082,1162149,1162169,1162721,1162769,1162836,1162932,1163630,1164419,1164438,1164469,1164480,1164567,1165234,1165247-1165248,1165253,1165273,1165282,1165309,1165331,1165338,1165347,1165360-1165361,1165367-1165368,1165602,1165608,1165677,1165693,1165721,1165723,1165728,1165730,1165738,1165746,1165765,1165777,1165918,1165921,1166077,1166150-1166151,1166290,1166366
Modified: tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/AbstractHttp11Processor.java
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/AbstractHttp11Processor.java?rev=1166576&r1=1166575&r2=1166576&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/AbstractHttp11Processor.java (original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/AbstractHttp11Processor.java Thu Sep 8 09:07:34 2011
@@ -47,6 +47,7 @@ import org.apache.tomcat.util.http.MimeH
import org.apache.tomcat.util.net.AbstractEndpoint;
import org.apache.tomcat.util.net.AbstractEndpoint.Handler.SocketState;
import org.apache.tomcat.util.net.SocketStatus;
+import org.apache.tomcat.util.net.SocketWrapper;
import org.apache.tomcat.util.res.StringManager;
public abstract class AbstractHttp11Processor<S> extends AbstractProcessor<S> {
@@ -79,6 +80,36 @@ public abstract class AbstractHttp11Proc
/**
+ * Flag used to indicate that the socket should be kept open (e.g. for keep
+ * alive or send file.
+ */
+ protected boolean openSocket = false;
+
+
+ /**
+ * Flag used to indicate that the socket should treat the next request
+ * processed like a keep-alive connection - i.e. one where there may not be
+ * any data to process. The initial value of this flag on entering the
+ * process method is different for connectors that use polling (NIO / APR -
+ * data is always expected) compared to those that use blocking (BIO - data
+ * is only expected if the connection isn't in the keep-alive state).
+ */
+ protected boolean keptAlive;
+
+
+ /**
+ * 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;
+
+
+ /**
+ * Flag that indicates if the request headers have been completely read.
+ */
+ protected boolean readComplete = true;
+
+ /**
* HTTP/1.1 flag.
*/
protected boolean http11 = true;
@@ -607,6 +638,12 @@ public abstract class AbstractHttp11Proc
status == 501 /* SC_NOT_IMPLEMENTED */;
}
+
+ /**
+ * Allows the super class to set the socket wrapper being used.
+ */
+ protected abstract void setSocketWrapper(SocketWrapper<S> socketWrapper);
+
/**
* Exposes input buffer to super class to allow better code re-use.
@@ -786,6 +823,232 @@ public abstract class AbstractHttp11Proc
/**
+ * Configures the timeout to be used for reading the request line.
+ */
+ protected abstract void setRequestLineReadTimeout() throws IOException;
+
+
+ /**
+ * Defines how a connector handles an incomplete request line read.
+ *
+ * @returns <code>true</code> if the processor should break out of the
+ * processing loop, otherwise <code>false</code>.
+ */
+ protected abstract boolean handleIncompleteRequestLineRead();
+
+
+ /**
+ * Set the socket timeout.
+ */
+ protected abstract void setSocketTimeout(int timeout) throws IOException;
+
+
+ /**
+ * Process pipelined HTTP requests using the specified input and output
+ * streams.
+ *
+ * @param socketWrapper Socket from which the HTTP requests will be read
+ * and the HTTP responses will be written.
+ *
+ * @throws IOException error during an I/O operation
+ */
+ @Override
+ public SocketState process(SocketWrapper<S> socketWrapper)
+ throws IOException {
+ RequestInfo rp = request.getRequestProcessor();
+ rp.setStage(org.apache.coyote.Constants.STAGE_PARSE);
+
+ // Setting up the I/O
+ setSocketWrapper(socketWrapper);
+ getInputBuffer().init(socketWrapper, endpoint);
+ getOutputBuffer().init(socketWrapper, endpoint);
+
+ // Flags
+ error = false;
+ keepAlive = true;
+ comet = false;
+ openSocket = false;
+ sendfileInProgress = false;
+ readComplete = true;
+ if (endpoint.getUsePolling()) {
+ keptAlive = false;
+ } else {
+ keptAlive = socketWrapper.isKeptAlive();
+ }
+
+ if (disableKeepAlive()) {
+ socketWrapper.setKeepAliveLeft(0);
+ }
+
+ while (!error && keepAlive && !comet && !isAsync() &&
+ !endpoint.isPaused()) {
+
+ // Parsing the request header
+ try {
+ setRequestLineReadTimeout();
+
+ if (!getInputBuffer().parseRequestLine(keptAlive)) {
+ if (handleIncompleteRequestLineRead()) {
+ break;
+ }
+ }
+
+ if (endpoint.isPaused()) {
+ // 503 - Service unavailable
+ response.setStatus(503);
+ adapter.log(request, response, 0);
+ error = true;
+ } else {
+ request.setStartTime(System.currentTimeMillis());
+ keptAlive = true;
+ // Currently only NIO will ever return false here
+ if (!getInputBuffer().parseHeaders()) {
+ // We've read part of the request, don't recycle it
+ // instead associate it with the socket
+ openSocket = true;
+ readComplete = false;
+ break;
+ }
+ if (!disableUploadTimeout) {
+ setSocketTimeout(connectionUploadTimeout);
+ }
+ }
+ } catch (IOException e) {
+ if (getLog().isDebugEnabled()) {
+ getLog().debug(
+ sm.getString("http11processor.header.parse"), e);
+ }
+ error = true;
+ break;
+ } catch (Throwable t) {
+ ExceptionUtils.handleThrowable(t);
+ if (getLog().isDebugEnabled()) {
+ getLog().debug(
+ sm.getString("http11processor.header.parse"), t);
+ }
+ // 400 - Bad Request
+ response.setStatus(400);
+ adapter.log(request, response, 0);
+ error = true;
+ }
+
+ if (!error) {
+ // Setting up filters, and parse some request headers
+ rp.setStage(org.apache.coyote.Constants.STAGE_PREPARE);
+ try {
+ prepareRequest();
+ } catch (Throwable t) {
+ ExceptionUtils.handleThrowable(t);
+ if (getLog().isDebugEnabled()) {
+ getLog().debug(sm.getString(
+ "http11processor.request.prepare"), t);
+ }
+ // 400 - Internal Server Error
+ response.setStatus(400);
+ adapter.log(request, response, 0);
+ error = true;
+ }
+ }
+
+ if (maxKeepAliveRequests == 1) {
+ keepAlive = false;
+ } else if (maxKeepAliveRequests > 0 &&
+ socketWrapper.decrementKeepAlive() <= 0) {
+ keepAlive = false;
+ }
+
+ // Process the request in the adapter
+ if (!error) {
+ try {
+ rp.setStage(org.apache.coyote.Constants.STAGE_SERVICE);
+ adapter.service(request, response);
+ // Handle when the response was committed before a serious
+ // error occurred. Throwing a ServletException should both
+ // set the status to 500 and set the errorException.
+ // If we fail here, then the response is likely already
+ // committed, so we can't try and set headers.
+ if(keepAlive && !error) { // Avoid checking twice.
+ error = response.getErrorException() != null ||
+ (!isAsync() &&
+ statusDropsConnection(response.getStatus()));
+ }
+ setCometTimeouts(socketWrapper);
+ } catch (InterruptedIOException e) {
+ error = true;
+ } catch (Throwable t) {
+ ExceptionUtils.handleThrowable(t);
+ getLog().error(sm.getString(
+ "http11processor.request.process"), t);
+ // 500 - Internal Server Error
+ response.setStatus(500);
+ adapter.log(request, response, 0);
+ error = true;
+ }
+ }
+
+ // Finish the handling of the request
+ rp.setStage(org.apache.coyote.Constants.STAGE_ENDINPUT);
+
+ if (!isAsync() && !comet) {
+ if (error) {
+ // If we know we are closing the connection, don't drain
+ // input. This way uploading a 100GB file doesn't tie up the
+ // thread if the servlet has rejected it.
+ getInputBuffer().setSwallowInput(false);
+ }
+ endRequest();
+ }
+
+ rp.setStage(org.apache.coyote.Constants.STAGE_ENDOUTPUT);
+
+ // If there was an error, make sure the request is counted as
+ // and error, and update the statistics counter
+ if (error) {
+ response.setStatus(500);
+ }
+ request.updateCounters();
+
+ if (!isAsync() && !comet || error) {
+ getInputBuffer().nextRequest();
+ getOutputBuffer().nextRequest();
+ }
+
+ if (!disableUploadTimeout) {
+ setSocketTimeout(endpoint.getSoTimeout());
+ }
+
+ rp.setStage(org.apache.coyote.Constants.STAGE_KEEPALIVE);
+
+ if (breakKeepAliveLoop(socketWrapper)) {
+ break;
+ }
+ }
+
+ rp.setStage(org.apache.coyote.Constants.STAGE_ENDED);
+
+ if (error || endpoint.isPaused()) {
+ return SocketState.CLOSED;
+ } else if (isAsync() || comet) {
+ return SocketState.LONG;
+ } else {
+ if (sendfileInProgress) {
+ return SocketState.SENDFILE;
+ } else {
+ if (openSocket) {
+ if (readComplete) {
+ return SocketState.OPEN;
+ } else {
+ return SocketState.LONG;
+ }
+ } else {
+ return SocketState.CLOSED;
+ }
+ }
+ }
+ }
+
+
+ /**
* After reading the request headers, we have to setup the request filters.
*/
protected void prepareRequest() {
@@ -1271,6 +1534,12 @@ public abstract class AbstractHttp11Proc
protected abstract void resetTimeouts();
+ /**
+ * Provides a mechanism for those connectors (currently only NIO) that need
+ * that need to set comet timeouts.
+ */
+ protected abstract void setCometTimeouts(SocketWrapper<S> socketWrapper);
+
public void endRequest() {
// Finish the handling of the request
@@ -1297,7 +1566,18 @@ public abstract class AbstractHttp11Proc
}
}
-
+
+
+ /**
+ * Checks to see of the keep-alive loop should be broken, performing any
+ * processing (e.g. send file handling) that may have an impact on whether
+ * or not the keep-alive loop should be broken.
+ * @return
+ */
+ protected abstract boolean breakKeepAliveLoop(
+ SocketWrapper<S> socketWrapper);
+
+
public final void recycle() {
getInputBuffer().recycle();
getOutputBuffer().recycle();
Modified: tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11AprProcessor.java
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11AprProcessor.java?rev=1166576&r1=1166575&r2=1166576&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11AprProcessor.java (original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11AprProcessor.java Thu Sep 8 09:07:34 2011
@@ -157,207 +157,91 @@ public class Http11AprProcessor extends
}
}
- /**
- * Process pipelined HTTP requests using the specified input and output
- * streams.
- *
- * @param socketWrapper Socket from which the HTTP requests will be read
- * and the HTTP responses will be written.
- *
- * @throws IOException error during an I/O operation
- */
@Override
- public SocketState process(SocketWrapper<Long> socketWrapper)
- throws IOException {
- RequestInfo rp = request.getRequestProcessor();
- rp.setStage(org.apache.coyote.Constants.STAGE_PARSE);
+ protected boolean disableKeepAlive() {
+ return false;
+ }
- // Setting up the socket
- this.socket = socketWrapper;
- inputBuffer.init(socketWrapper, endpoint);
- outputBuffer.init(socketWrapper, endpoint);
- // Error flag
- error = false;
- keepAlive = true;
- comet = false;
+ @Override
+ protected void setRequestLineReadTimeout() throws IOException {
+ // Timeouts while in the poller are handled entirely by the poller
+ // Only need to be concerned with socket timeouts
- int soTimeout = endpoint.getSoTimeout();
+ // APR uses simulated blocking so if some request line data is present
+ // then it must all be presented (with the normal socket timeout).
+
+ // When entering the processing loop for the first time there will
+ // always be some data to read so the keep-alive timeout is not required
+
+ // For the second and subsequent executions of the processing loop, if
+ // there is no request line data present then no further data will be
+ // read from the socket. If there is request line data present then it
+ // must all be presented (with the normal socket timeout)
+
+ // When the socket is created it is given the correct timeout.
+ // sendfile may change the timeout but will restore it
+ // This processor may change the timeout for uploads but will restore it
+
+ // NO-OP
+ }
- if (disableKeepAlive()) {
- socketWrapper.setKeepAliveLeft(0);
- }
- boolean keptAlive = false;
- boolean openSocket = false;
- boolean sendfileInProgress = false;
+ @Override
+ protected boolean handleIncompleteRequestLineRead() {
+ // This means that no data is available right now
+ // (long keepalive), so that the processor should be recycled
+ // and the method should return true
+ openSocket = true;
+ if (endpoint.isPaused()) {
+ // 503 - Service unavailable
+ response.setStatus(503);
+ adapter.log(request, response, 0);
+ error = true;
+ } else {
+ return true;
+ }
+ return false;
+ }
- long socketRef = socketWrapper.getSocket().longValue();
- while (!error && keepAlive && !comet && !isAsync() && !endpoint.isPaused()) {
+ @Override
+ protected void setSocketTimeout(int timeout) {
+ Socket.timeoutSet(socket.getSocket().longValue(), timeout * 1000);
+ }
+
+
+ @Override
+ protected void setCometTimeouts(SocketWrapper<Long> socketWrapper) {
+ // NO-OP for APR/native
+ }
- // Parsing the request header
- try {
- if( !disableUploadTimeout && keptAlive && soTimeout > 0 ) {
- Socket.timeoutSet(socketRef, soTimeout * 1000);
- }
- if (!inputBuffer.parseRequestLine(keptAlive)) {
- // This means that no data is available right now
- // (long keepalive), so that the processor should be recycled
- // and the method should return true
- openSocket = true;
- if (endpoint.isPaused()) {
- // 503 - Service unavailable
- response.setStatus(503);
- adapter.log(request, response, 0);
- error = true;
- } else {
- break;
- }
- }
- if (!endpoint.isPaused()) {
- request.setStartTime(System.currentTimeMillis());
- keptAlive = true;
- if (!disableUploadTimeout) {
- Socket.timeoutSet(socketRef,
- connectionUploadTimeout * 1000);
- }
- inputBuffer.parseHeaders();
- }
- } catch (IOException e) {
- error = true;
- break;
- } catch (Throwable t) {
- ExceptionUtils.handleThrowable(t);
- if (log.isDebugEnabled()) {
- log.debug(sm.getString("http11processor.header.parse"), t);
- }
- // 400 - Bad Request
- response.setStatus(400);
- adapter.log(request, response, 0);
- error = true;
- }
- if (!error) {
- // Setting up filters, and parse some request headers
- rp.setStage(org.apache.coyote.Constants.STAGE_PREPARE);
- try {
- prepareRequest();
- } catch (Throwable t) {
- ExceptionUtils.handleThrowable(t);
+ @Override
+ protected boolean breakKeepAliveLoop(SocketWrapper<Long> socketWrapper) {
+ openSocket = keepAlive;
+ // Do sendfile as needed: add socket to sendfile and end
+ if (sendfileData != null && !error) {
+ sendfileData.socket = socketWrapper.getSocket().longValue();
+ sendfileData.keepAlive = keepAlive;
+ 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.request.prepare"), t);
+ log.debug(sm.getString(
+ "http11processor.sendfile.error"));
}
- // 400 - Internal Server Error
- response.setStatus(400);
- adapter.log(request, response, 0);
error = true;
+ } else {
+ // The sendfile Poller will add the socket to the main
+ // Poller once sendfile processing is complete
+ sendfileInProgress = true;
}
+ return true;
}
-
- if (maxKeepAliveRequests == 1) {
- keepAlive = false;
- } else if (maxKeepAliveRequests > 0 &&
- socketWrapper.decrementKeepAlive() <= 0) {
- keepAlive = false;
- }
-
- // Process the request in the adapter
- if (!error) {
- try {
- rp.setStage(org.apache.coyote.Constants.STAGE_SERVICE);
- adapter.service(request, response);
- // Handle when the response was committed before a serious
- // error occurred. Throwing a ServletException should both
- // set the status to 500 and set the errorException.
- // If we fail here, then the response is likely already
- // committed, so we can't try and set headers.
- if(keepAlive && !error) { // Avoid checking twice.
- error = response.getErrorException() != null ||
- (!isAsync() &&
- statusDropsConnection(response.getStatus()));
- }
- } catch (InterruptedIOException e) {
- error = true;
- } catch (Throwable t) {
- ExceptionUtils.handleThrowable(t);
- log.error(sm.getString("http11processor.request.process"), t);
- // 500 - Internal Server Error
- response.setStatus(500);
- adapter.log(request, response, 0);
- error = true;
- }
- }
-
- // Finish the handling of the request
- if (!comet && !isAsync()) {
- // If we know we are closing the connection, don't drain input.
- // This way uploading a 100GB file doesn't tie up the thread
- // if the servlet has rejected it.
- if(error)
- inputBuffer.setSwallowInput(false);
- endRequest();
- }
-
- // If there was an error, make sure the request is counted as
- // and error, and update the statistics counter
- if (error) {
- response.setStatus(500);
- }
- request.updateCounters();
-
- if (!comet && !isAsync()) {
- // Next request
- inputBuffer.nextRequest();
- outputBuffer.nextRequest();
- }
-
- // Do sendfile as needed: add socket to sendfile and end
- if (sendfileData != null && !error) {
- sendfileData.socket = socketRef;
- sendfileData.keepAlive = keepAlive;
- 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"));
- }
- error = true;
- } else {
- // The sendfile Poller will add the socket to the main
- // Poller once sendfile processing is complete
- sendfileInProgress = true;
- }
- break;
- }
- }
-
- rp.setStage(org.apache.coyote.Constants.STAGE_KEEPALIVE);
-
}
-
- rp.setStage(org.apache.coyote.Constants.STAGE_ENDED);
-
- if (error || endpoint.isPaused()) {
- return SocketState.CLOSED;
- } else if (comet || isAsync()) {
- return SocketState.LONG;
- } else {
- if (sendfileInProgress) {
- return SocketState.SENDFILE;
- } else {
- return (openSocket) ? SocketState.OPEN : SocketState.CLOSED;
- }
- }
-
- }
-
-
- @Override
- protected boolean disableKeepAlive() {
return false;
}
@@ -633,6 +517,11 @@ public class Http11AprProcessor extends
}
@Override
+ protected void setSocketWrapper(SocketWrapper<Long> socketWrapper) {
+ this.socket = socketWrapper;
+ }
+
+ @Override
protected AbstractInputBuffer<Long> getInputBuffer() {
return inputBuffer;
}
Modified: tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11NioProcessor.java
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11NioProcessor.java?rev=1166576&r1=1166575&r2=1166576&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11NioProcessor.java (original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11NioProcessor.java Thu Sep 8 09:07:34 2011
@@ -137,7 +137,7 @@ public class Http11NioProcessor extends
if (comettimeout != null) attach.setTimeout(comettimeout.longValue());
} else {
//reset the timeout
- if (keepAlive && keepAliveTimeout>0) {
+ if (keepAlive) {
attach.setTimeout(keepAliveTimeout);
} else {
attach.setTimeout(soTimeout);
@@ -177,7 +177,7 @@ public class Http11NioProcessor extends
long soTimeout = endpoint.getSoTimeout();
//reset the timeout
- if (keepAlive && keepAliveTimeout>0) {
+ if (keepAlive) {
attach.setTimeout(keepAliveTimeout);
} else {
attach.setTimeout(soTimeout);
@@ -186,224 +186,102 @@ public class Http11NioProcessor extends
}
- /**
- * Process pipelined HTTP requests using the specified input and output
- * streams.
- *
- * @param socketWrapper Socket from which the HTTP requests will be read
- * and the HTTP responses will be written.
- *
- * @throws IOException error during an I/O operation
- */
@Override
- public SocketState process(SocketWrapper<NioChannel> socketWrapper)
- throws IOException {
- RequestInfo rp = request.getRequestProcessor();
- rp.setStage(org.apache.coyote.Constants.STAGE_PARSE);
-
- // Setting up the socket
- this.socket = socketWrapper;
- inputBuffer.init(socketWrapper, endpoint);
- outputBuffer.init(socketWrapper, endpoint);
+ protected boolean disableKeepAlive() {
+ return false;
+ }
- // Error flag
- error = false;
- keepAlive = true;
- comet = false;
-
- int soTimeout = endpoint.getSoTimeout();
- if (disableKeepAlive()) {
- socketWrapper.setKeepAliveLeft(0);
- }
+ @Override
+ protected void setRequestLineReadTimeout() throws IOException {
+ // socket.setTimeout()
+ // - timeout used by poller
+ // socket.getSocket().getIOChannel().socket().setSoTimeout()
+ // - timeout used for blocking reads
- boolean keptAlive = false;
- boolean openSocket = false;
- boolean readComplete = true;
+ // When entering the processing loop there will always be data to read
+ // so no point changing timeouts at this point
- while (!error && keepAlive && !comet && !isAsync() && !endpoint.isPaused()) {
- //always default to our soTimeout
- socketWrapper.setTimeout(soTimeout);
- // Parsing the request header
- try {
- if( !disableUploadTimeout && keptAlive && soTimeout > 0 ) {
- socketWrapper.getSocket().getIOChannel().socket().setSoTimeout(soTimeout);
- }
- if (!inputBuffer.parseRequestLine(keptAlive)) {
- // Haven't finished reading the request so keep the socket
- // open
- openSocket = true;
- // Check to see if we have read any of the request line yet
- if (inputBuffer.getParsingRequestLinePhase()<2) {
- // No data read, OK to recycle the processor
- // Continue to use keep alive timeout
- if (keepAliveTimeout>0) {
- socketWrapper.setTimeout(keepAliveTimeout);
- }
- } else {
- // Started to read request line. Need to keep processor
- // associated with socket
- readComplete = false;
- }
- if (endpoint.isPaused()) {
- // 503 - Service unavailable
- response.setStatus(503);
- adapter.log(request, response, 0);
- error = true;
- } else {
- break;
- }
- }
- if (!endpoint.isPaused()) {
- keptAlive = true;
- if ( !inputBuffer.parseHeaders() ) {
- //we've read part of the request, don't recycle it
- //instead associate it with the socket
- openSocket = true;
- readComplete = false;
- break;
- }
- request.setStartTime(System.currentTimeMillis());
- if (!disableUploadTimeout) { //only for body, not for request headers
- socketWrapper.getSocket().getIOChannel().socket().setSoTimeout(
- connectionUploadTimeout);
- }
- }
- } catch (IOException e) {
- if (log.isDebugEnabled()) {
- log.debug(sm.getString("http11processor.header.parse"), e);
- }
- error = true;
- break;
- } catch (Throwable t) {
- ExceptionUtils.handleThrowable(t);
- if (log.isDebugEnabled()) {
- log.debug(sm.getString("http11processor.header.parse"), t);
- }
- // 400 - Bad Request
- response.setStatus(400);
- adapter.log(request, response, 0);
- error = true;
- }
-
- if (!error) {
- // Setting up filters, and parse some request headers
- rp.setStage(org.apache.coyote.Constants.STAGE_PREPARE);
- try {
- prepareRequest();
- } catch (Throwable t) {
- ExceptionUtils.handleThrowable(t);
- if (log.isDebugEnabled()) {
- log.debug(sm.getString("http11processor.request.prepare"), t);
- }
- // 400 - Internal Server Error
- response.setStatus(400);
- adapter.log(request, response, 0);
- error = true;
- }
- }
-
- if (maxKeepAliveRequests == 1) {
- keepAlive = false;
- } else if (maxKeepAliveRequests > 0 &&
- socketWrapper.decrementKeepAlive() <= 0) {
- keepAlive = false;
- }
+ // For the second and subsequent executions of the processing loop, a
+ // non-blocking read is used so again no need to set the timeouts
+
+ // Because NIO supports non-blocking reading of the request line and
+ // headers the timeouts need to be set when returning the socket to
+ // the poller rather than here.
+
+ // NO-OP
+ }
- // Process the request in the adapter
- if (!error) {
- try {
- rp.setStage(org.apache.coyote.Constants.STAGE_SERVICE);
- adapter.service(request, response);
- // Handle when the response was committed before a serious
- // error occurred. Throwing a ServletException should both
- // set the status to 500 and set the errorException.
- // If we fail here, then the response is likely already
- // committed, so we can't try and set headers.
- if(keepAlive && !error) { // Avoid checking twice.
- error = response.getErrorException() != null ||
- (!isAsync() &&
- statusDropsConnection(response.getStatus()));
- }
- // Comet support
- SelectionKey key = socketWrapper.getSocket().getIOChannel().keyFor(
- socketWrapper.getSocket().getPoller().getSelector());
- if (key != null) {
- NioEndpoint.KeyAttachment attach = (NioEndpoint.KeyAttachment) key.attachment();
- if (attach != null) {
- attach.setComet(comet);
- if (comet) {
- Integer comettimeout = (Integer) request.getAttribute("org.apache.tomcat.comet.timeout");
- if (comettimeout != null) attach.setTimeout(comettimeout.longValue());
- }
- }
- }
- } catch (InterruptedIOException e) {
- error = true;
- } catch (Throwable t) {
- ExceptionUtils.handleThrowable(t);
- log.error(sm.getString("http11processor.request.process"), t);
- // 500 - Internal Server Error
- response.setStatus(500);
- adapter.log(request, response, 0);
- error = true;
- }
- }
- // Finish the handling of the request
- if (!comet && !isAsync()) {
- // If we know we are closing the connection, don't drain input.
- // This way uploading a 100GB file doesn't tie up the thread
- // if the servlet has rejected it.
- if(error)
- inputBuffer.setSwallowInput(false);
- endRequest();
- }
-
- // If there was an error, make sure the request is counted as
- // and error, and update the statistics counter
- if (error) {
- response.setStatus(500);
- }
- request.updateCounters();
-
- if (!comet && !isAsync()) {
- // Next request
- inputBuffer.nextRequest();
- outputBuffer.nextRequest();
- }
-
- // Do sendfile as needed: add socket to sendfile and end
- if (sendfileData != null && !error) {
- ((KeyAttachment) socketWrapper).setSendfileData(sendfileData);
- sendfileData.keepAlive = keepAlive;
- SelectionKey key = socketWrapper.getSocket().getIOChannel().keyFor(
- socketWrapper.getSocket().getPoller().getSelector());
- //do the first write on this thread, might as well
- openSocket = socketWrapper.getSocket().getPoller().processSendfile(key,
- (KeyAttachment) socketWrapper, true, true);
- break;
+ @Override
+ protected boolean handleIncompleteRequestLineRead() {
+ // Haven't finished reading the request so keep the socket
+ // open
+ openSocket = true;
+ // Check to see if we have read any of the request line yet
+ if (inputBuffer.getParsingRequestLinePhase() < 2) {
+ if (socket.getLastAccess() > -1 || keptAlive) {
+ // Haven't read the request line and have previously processed a
+ // request. Must be keep-alive. Make sure poller uses keepAlive.
+ socket.setTimeout(endpoint.getKeepAliveTimeout());
}
+ } else {
+ // Started to read request line. Need to keep processor
+ // associated with socket
+ readComplete = false;
+ // Make sure poller uses soTimeout from here onwards
+ socket.setTimeout(endpoint.getSoTimeout());
+ }
+ if (endpoint.isPaused()) {
+ // 503 - Service unavailable
+ response.setStatus(503);
+ adapter.log(request, response, 0);
+ error = true;
+ } else {
+ return true;
+ }
+ return false;
+ }
- rp.setStage(org.apache.coyote.Constants.STAGE_KEEPALIVE);
-
- }//while
+ @Override
+ protected void setSocketTimeout(int timeout) throws IOException {
+ socket.getSocket().getIOChannel().socket().setSoTimeout(timeout);
+ }
- rp.setStage(org.apache.coyote.Constants.STAGE_ENDED);
- if (error || endpoint.isPaused()) {
- return SocketState.CLOSED;
- } else if (comet || isAsync()) {
- return SocketState.LONG;
- } else {
- return (openSocket) ? (readComplete?SocketState.OPEN:SocketState.LONG) : SocketState.CLOSED;
+
+ @Override
+ protected void setCometTimeouts(SocketWrapper<NioChannel> socketWrapper) {
+ // Comet support
+ SelectionKey key = socketWrapper.getSocket().getIOChannel().keyFor(
+ socketWrapper.getSocket().getPoller().getSelector());
+ if (key != null) {
+ NioEndpoint.KeyAttachment attach = (NioEndpoint.KeyAttachment) key.attachment();
+ if (attach != null) {
+ attach.setComet(comet);
+ if (comet) {
+ Integer comettimeout = (Integer) request.getAttribute("org.apache.tomcat.comet.timeout");
+ if (comettimeout != null) attach.setTimeout(comettimeout.longValue());
+ }
+ }
}
-
}
@Override
- protected boolean disableKeepAlive() {
+ protected boolean breakKeepAliveLoop(
+ SocketWrapper<NioChannel> socketWrapper) {
+ // Do sendfile as needed: add socket to sendfile and end
+ if (sendfileData != null && !error) {
+ ((KeyAttachment) socketWrapper).setSendfileData(sendfileData);
+ sendfileData.keepAlive = keepAlive;
+ SelectionKey key = socketWrapper.getSocket().getIOChannel().keyFor(
+ socketWrapper.getSocket().getPoller().getSelector());
+ //do the first write on this thread, might as well
+ openSocket = socketWrapper.getSocket().getPoller().processSendfile(key,
+ (KeyAttachment) socketWrapper, true, true);
+ return true;
+ }
return false;
}
@@ -654,6 +532,11 @@ public class Http11NioProcessor extends
}
@Override
+ protected void setSocketWrapper(SocketWrapper<NioChannel> socketWrapper) {
+ this.socket = socketWrapper;
+ }
+
+ @Override
protected AbstractInputBuffer<NioChannel> getInputBuffer() {
return inputBuffer;
}
Modified: tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11Processor.java
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11Processor.java?rev=1166576&r1=1166575&r2=1166576&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11Processor.java (original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11Processor.java Thu Sep 8 09:07:34 2011
@@ -18,16 +18,13 @@ package org.apache.coyote.http11;
import java.io.EOFException;
import java.io.IOException;
-import java.io.InterruptedIOException;
import java.net.InetAddress;
import java.net.Socket;
import org.apache.coyote.ActionCode;
-import org.apache.coyote.RequestInfo;
import org.apache.coyote.http11.filters.BufferedInputFilter;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
-import org.apache.tomcat.util.ExceptionUtils;
import org.apache.tomcat.util.net.AbstractEndpoint.Handler.SocketState;
import org.apache.tomcat.util.net.JIoEndpoint;
import org.apache.tomcat.util.net.SSLSupport;
@@ -121,254 +118,98 @@ public class Http11Processor extends Abs
}
- /**
- * Process pipelined HTTP requests using the specified input and output
- * streams.
- *
- * @param socketWrapper Socket from which the HTTP requests will be read
- * and the HTTP responses will be written.
- *
- * @throws IOException error during an I/O operation
- */
@Override
- public SocketState process(SocketWrapper<Socket> socketWrapper)
- throws IOException {
- RequestInfo rp = request.getRequestProcessor();
- rp.setStage(org.apache.coyote.Constants.STAGE_PARSE);
-
- // Setting up the I/O
- this.socket = socketWrapper;
- inputBuffer.init(socketWrapper, endpoint);
- outputBuffer.init(socketWrapper, endpoint);
-
- // Error flag
- error = false;
- keepAlive = true;
- comet = false;
-
- int soTimeout = endpoint.getSoTimeout();
-
- if (disableKeepAlive()) {
- socketWrapper.setKeepAliveLeft(0);
+ protected boolean disableKeepAlive() {
+ int threadRatio = -1;
+ // These may return zero or negative values
+ // Only calculate a thread ratio when both are >0 to ensure we get a
+ // sensible result
+ if (endpoint.getCurrentThreadsBusy() >0 &&
+ endpoint.getMaxThreads() >0) {
+ threadRatio = (endpoint.getCurrentThreadsBusy() * 100)
+ / endpoint.getMaxThreads();
+ }
+ // Disable keep-alive if we are running low on threads
+ if (threadRatio > getDisableKeepAlivePercentage()) {
+ return true;
}
+
+ return false;
+ }
- boolean keptAlive = socketWrapper.isKeptAlive();
-
- while (!error && keepAlive && !endpoint.isPaused()) {
- // Parsing the request header
- try {
- int standardTimeout = 0;
- if (keptAlive) {
- if (keepAliveTimeout > 0) {
- standardTimeout = keepAliveTimeout;
- } else if (soTimeout > 0) {
- standardTimeout = soTimeout;
- }
- }
- /*
- * When there is no data in the buffer and this is not the first
- * request on this connection and timeouts are being used the
- * first read for this request may need a different timeout to
- * take account of time spent waiting for a processing thread.
- *
- * This is a little hacky but better than exposing the socket
- * and the timeout info to the InputBuffer
- */
- if (inputBuffer.lastValid == 0 &&
- socketWrapper.getLastAccess() > -1 &&
- standardTimeout > 0) {
-
- long queueTime = System.currentTimeMillis() -
- socketWrapper.getLastAccess();
- int firstReadTimeout;
- if (queueTime >= standardTimeout) {
- // Queued for longer than timeout but there might be
- // data so use shortest possible timeout
- firstReadTimeout = 1;
- } else {
- // Cast is safe since queueTime must be less than
- // standardTimeout which is an int
- firstReadTimeout = standardTimeout - (int) queueTime;
- }
- socket.getSocket().setSoTimeout(firstReadTimeout);
- if (!inputBuffer.fill()) {
- throw new EOFException(sm.getString("iib.eof.error"));
- }
- }
- if (standardTimeout > 0) {
- socket.getSocket().setSoTimeout(standardTimeout);
- }
+ @Override
+ protected void setRequestLineReadTimeout() throws IOException {
+
+ /*
+ * When there is no data in the buffer and this is not the first
+ * request on this connection and timeouts are being used the
+ * first read for this request may need a different timeout to
+ * take account of time spent waiting for a processing thread.
+ *
+ * This is a little hacky but better than exposing the socket
+ * and the timeout info to the InputBuffer
+ */
+ if (inputBuffer.lastValid == 0 && socket.getLastAccess() > -1) {
+ int firstReadTimeout;
+ if (keepAliveTimeout == -1) {
+ firstReadTimeout = 0;
+ } else {
+ long queueTime =
+ System.currentTimeMillis() - socket.getLastAccess();
- inputBuffer.parseRequestLine(false);
- if (endpoint.isPaused()) {
- // 503 - Service unavailable
- response.setStatus(503);
- adapter.log(request, response, 0);
- error = true;
+ if (queueTime >= keepAliveTimeout) {
+ // Queued for longer than timeout but there might be
+ // data so use shortest possible timeout
+ firstReadTimeout = 1;
} else {
- request.setStartTime(System.currentTimeMillis());
- keptAlive = true;
- if (disableUploadTimeout) {
- socket.getSocket().setSoTimeout(soTimeout);
- } else {
- socket.getSocket().setSoTimeout(connectionUploadTimeout);
- }
- inputBuffer.parseHeaders();
- }
- } catch (IOException e) {
- error = true;
- break;
- } catch (Throwable t) {
- ExceptionUtils.handleThrowable(t);
- if (log.isDebugEnabled()) {
- log.debug(sm.getString("http11processor.header.parse"), t);
- }
- // 400 - Bad Request
- response.setStatus(400);
- adapter.log(request, response, 0);
- error = true;
- }
-
- if (!error) {
- // Setting up filters, and parse some request headers
- rp.setStage(org.apache.coyote.Constants.STAGE_PREPARE);
- try {
- prepareRequest();
- } catch (Throwable t) {
- ExceptionUtils.handleThrowable(t);
- if (log.isDebugEnabled()) {
- log.debug(sm.getString("http11processor.request.prepare"), t);
- }
- // 400 - Internal Server Error
- response.setStatus(400);
- adapter.log(request, response, 0);
- error = true;
+ // Cast is safe since queueTime must be less than
+ // keepAliveTimeout which is an int
+ firstReadTimeout = keepAliveTimeout - (int) queueTime;
}
}
+ socket.getSocket().setSoTimeout(firstReadTimeout);
+ if (!inputBuffer.fill()) {
+ throw new EOFException(sm.getString("iib.eof.error"));
+ }
+ // Once the first byte has been read, the standard timeout should be
+ // used so restore it here.
+ socket.getSocket().setSoTimeout(endpoint.getSoTimeout());
+ }
+ }
- if (maxKeepAliveRequests == 1) {
- keepAlive = false;
- } else if (maxKeepAliveRequests > 0 &&
- socketWrapper.decrementKeepAlive() <= 0) {
- keepAlive = false;
- }
-
- // Process the request in the adapter
- if (!error) {
- try {
- rp.setStage(org.apache.coyote.Constants.STAGE_SERVICE);
- adapter.service(request, response);
- // Handle when the response was committed before a serious
- // error occurred. Throwing a ServletException should both
- // set the status to 500 and set the errorException.
- // If we fail here, then the response is likely already
- // committed, so we can't try and set headers.
- if(keepAlive && !error) { // Avoid checking twice.
- error = response.getErrorException() != null ||
- (!isAsync() &&
- statusDropsConnection(response.getStatus()));
- }
-
- } catch (InterruptedIOException e) {
- error = true;
- } catch (Throwable t) {
- ExceptionUtils.handleThrowable(t);
- log.error(sm.getString("http11processor.request.process"), t);
- // 500 - Internal Server Error
- response.setStatus(500);
- adapter.log(request, response, 0);
- error = true;
- }
- }
- // Finish the handling of the request
- try {
- rp.setStage(org.apache.coyote.Constants.STAGE_ENDINPUT);
- // If we know we are closing the connection, don't drain input.
- // This way uploading a 100GB file doesn't tie up the thread
- // if the servlet has rejected it.
-
- if(error && !isAsync())
- inputBuffer.setSwallowInput(false);
- if (!isAsync())
- endRequest();
- } catch (Throwable t) {
- ExceptionUtils.handleThrowable(t);
- log.error(sm.getString("http11processor.request.finish"), t);
- // 500 - Internal Server Error
- response.setStatus(500);
- adapter.log(request, response, 0);
- error = true;
- }
- try {
- rp.setStage(org.apache.coyote.Constants.STAGE_ENDOUTPUT);
- } catch (Throwable t) {
- ExceptionUtils.handleThrowable(t);
- log.error(sm.getString("http11processor.response.finish"), t);
- error = true;
- }
+ @Override
+ protected boolean handleIncompleteRequestLineRead() {
+ // Not used with BIO since it uses blocking reads
+ return false;
+ }
- // If there was an error, make sure the request is counted as
- // and error, and update the statistics counter
- if (error) {
- response.setStatus(500);
- }
- request.updateCounters();
-
- rp.setStage(org.apache.coyote.Constants.STAGE_KEEPALIVE);
-
- // Don't reset the param - we'll see it as ended. Next request
- // will reset it
- // thrA.setParam(null);
- // Next request
- if (!isAsync() || error) {
- inputBuffer.nextRequest();
- outputBuffer.nextRequest();
- }
-
- // If we don't have a pipe-lined request allow this thread to be
- // used by another connection
- if (isAsync() || error || inputBuffer.lastValid == 0) {
- break;
- }
- }
- rp.setStage(org.apache.coyote.Constants.STAGE_ENDED);
- if (error || endpoint.isPaused()) {
- return SocketState.CLOSED;
- } else if (isAsync()) {
- return SocketState.LONG;
- } else {
- if (!keepAlive) {
- return SocketState.CLOSED;
- } else {
- return SocketState.OPEN;
- }
- }
+ @Override
+ protected void setSocketTimeout(int timeout) throws IOException {
+ socket.getSocket().setSoTimeout(timeout);
}
@Override
- protected boolean disableKeepAlive() {
- int threadRatio = -1;
- // These may return zero or negative values
- // Only calculate a thread ratio when both are >0 to ensure we get a
- // sensible result
- if (endpoint.getCurrentThreadsBusy() >0 &&
- endpoint.getMaxThreads() >0) {
- threadRatio = (endpoint.getCurrentThreadsBusy() * 100)
- / endpoint.getMaxThreads();
- }
- // Disable keep-alive if we are running low on threads
- if (threadRatio > getDisableKeepAlivePercentage()) {
+ protected void setCometTimeouts(SocketWrapper<Socket> socketWrapper) {
+ // NO-OP for BIO
+ }
+
+
+ @Override
+ protected boolean breakKeepAliveLoop(SocketWrapper<Socket> socketWrapper) {
+ openSocket = keepAlive;
+ // If we don't have a pipe-lined request allow this thread to be
+ // used by another connection
+ if (inputBuffer.lastValid == 0) {
return true;
}
-
return false;
}
-
+
@Override
protected void resetTimeouts() {
// NOOP for BIO
@@ -556,6 +397,11 @@ public class Http11Processor extends Abs
}
@Override
+ protected void setSocketWrapper(SocketWrapper<Socket> socketWrapper) {
+ this.socket = socketWrapper;
+ }
+
+ @Override
protected AbstractInputBuffer<Socket> getInputBuffer() {
return inputBuffer;
}
Modified: tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/AbstractEndpoint.java
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/AbstractEndpoint.java?rev=1166576&r1=1166575&r2=1166576&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/AbstractEndpoint.java (original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/AbstractEndpoint.java Thu Sep 8 09:07:34 2011
@@ -170,12 +170,18 @@ public abstract class AbstractEndpoint {
private BindState bindState = BindState.UNBOUND;
/**
- * Keepalive timeout, if lesser or equal to 0 then soTimeout will be used.
+ * Keepalive timeout, if not set the soTimeout is used.
*/
- private int keepAliveTimeout = -1;
- public int getKeepAliveTimeout() { return keepAliveTimeout;}
+ private Integer keepAliveTimeout = null;
+ public int getKeepAliveTimeout() {
+ if (keepAliveTimeout == null) {
+ return getSoTimeout();
+ } else {
+ return keepAliveTimeout.intValue();
+ }
+ }
public void setKeepAliveTimeout(int keepAliveTimeout) {
- this.keepAliveTimeout = keepAliveTimeout;
+ this.keepAliveTimeout = Integer.valueOf(keepAliveTimeout);
}
@@ -559,9 +565,12 @@ public abstract class AbstractEndpoint {
protected abstract Log getLog();
// Flags to indicate optional feature support
+ // Some of these are always hard-coded, some are hard-coded to false (i.e.
+ // the endpoint does not support them) and some are configurable.
public abstract boolean getUseSendfile();
public abstract boolean getUseComet();
public abstract boolean getUseCometTimeout();
+ public abstract boolean getUsePolling();
protected LimitLatch initializeConnectionLatch() {
if (connectionLimitLatch==null) {
Modified: tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java?rev=1166576&r1=1166575&r2=1166576&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java (original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java Thu Sep 8 09:07:34 2011
@@ -160,6 +160,8 @@ public class AprEndpoint extends Abstrac
public boolean getUseComet() { return useComet; }
@Override
public boolean getUseCometTimeout() { return false; } // Not supported
+ @Override
+ public boolean getUsePolling() { return true; } // Always supported
/**
@@ -750,8 +752,7 @@ public class AprEndpoint extends Abstrac
Socket.optSet(socket, Socket.APR_SO_LINGER, socketProperties.getSoLingerTime());
if (socketProperties.getTcpNoDelay())
Socket.optSet(socket, Socket.APR_TCP_NODELAY, (socketProperties.getTcpNoDelay() ? 1 : 0));
- if (socketProperties.getSoTimeout() > 0)
- Socket.timeoutSet(socket, socketProperties.getSoTimeout() * 1000);
+ Socket.timeoutSet(socket, socketProperties.getSoTimeout() * 1000);
// 2: SSL handshake
step = 2;
@@ -1128,7 +1129,7 @@ public class AprEndpoint extends Abstrac
int size = getMaxConnections() / pollerThreadCount;
int keepAliveTimeout = getKeepAliveTimeout();
int socketTimeout = socketProperties.getSoTimeout();
- if (keepAliveTimeout > 0 && !comet) {
+ if (keepAliveTimeout != socketTimeout && !comet) {
separateKeepAlive = true;
}
connectionPollset = allocatePoller(size, pool, socketTimeout);
Modified: tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/JIoEndpoint.java
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/JIoEndpoint.java?rev=1166576&r1=1166575&r2=1166576&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/JIoEndpoint.java (original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/JIoEndpoint.java Thu Sep 8 09:07:34 2011
@@ -108,6 +108,8 @@ public class JIoEndpoint extends Abstrac
public boolean getUseCometTimeout() { return false; } // Not supported
@Override
public boolean getDeferAccept() { return false; } // Not supported
+ @Override
+ public boolean getUsePolling() { return false; } // Not supported
// ------------------------------------------------ Handler Inner Interface
Modified: tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java?rev=1166576&r1=1166575&r2=1166576&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java (original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java Thu Sep 8 09:07:34 2011
@@ -332,6 +332,8 @@ public class NioEndpoint extends Abstrac
public boolean getUseComet() { return useComet; }
@Override
public boolean getUseCometTimeout() { return getUseComet(); }
+ @Override
+ public boolean getUsePolling() { return true; } // Always supported
/**
@@ -1338,7 +1340,7 @@ public class NioEndpoint extends Abstrac
(ka.interestOps()&SelectionKey.OP_WRITE) == SelectionKey.OP_WRITE) {
//only timeout sockets that we are waiting for a read from
long delta = now - ka.getLastAccess();
- long timeout = (ka.getTimeout()==-1)?((long) socketProperties.getSoTimeout()):(ka.getTimeout());
+ long timeout = ka.getTimeout();
boolean isTimedout = timeout > 0 && delta > timeout;
if ( close ) {
key.interestOps(0);
@@ -1348,7 +1350,7 @@ public class NioEndpoint extends Abstrac
key.interestOps(0);
ka.interestOps(0); //avoid duplicate timeout calls
cancelledKey(key, SocketStatus.TIMEOUT,true);
- } else {
+ } else if (timeout > -1) {
long nextTime = now+(timeout-delta);
nextExpiration = (nextTime < nextExpiration)?nextTime:nextExpiration;
}
Modified: tomcat/tc7.0.x/trunk/webapps/docs/config/http.xml
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/webapps/docs/config/http.xml?rev=1166576&r1=1166575&r2=1166576&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/webapps/docs/config/http.xml (original)
+++ tomcat/tc7.0.x/trunk/webapps/docs/config/http.xml Thu Sep 8 09:07:34 2011
@@ -317,7 +317,10 @@
<attribute name="connectionTimeout" required="false">
<p>The number of milliseconds this <strong>Connector</strong> will wait,
after accepting a connection, for the request URI line to be
- presented. The default value is 60000 (i.e. 60 seconds).</p>
+ presented. Use a value of -1 to indicate no (i.e. infinite) timeout.
+ The default value is 60000 (i.e. 60 seconds) but note that the standard
+ server.xml that ships with Tomcat sets this to 20000 (i.e. 20 seconds).
+ </p>
</attribute>
<attribute name="connectionUploadTimeout" required="false">
@@ -347,7 +350,8 @@
<p>The number of milliseconds this <strong>Connector</strong> will wait
for another HTTP request before closing the connection. The default value
is to use the value that has been set for the
- <strong>connectionTimeout</strong> attribute.</p>
+ <strong>connectionTimeout</strong> attribute.
+ Use a value of -1 to indicate no (i.e. infinite) timeout.</p>
</attribute>
<attribute name="maxConnections" required="false">
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org