Author: remy.maucherat(a)jboss.com
Date: 2008-03-03 21:31:01 -0500 (Mon, 03 Mar 2008)
New Revision: 463
Modified:
trunk/java/org/apache/catalina/connector/CoyoteAdapter.java
trunk/java/org/apache/catalina/connector/InputBuffer.java
trunk/java/org/apache/catalina/connector/Request.java
trunk/java/org/apache/coyote/http11/Http11AprProcessor.java
trunk/java/org/apache/coyote/http11/InternalAprInputBuffer.java
Log:
- Fix some glitches that did not allow reads to read 0 bytes.
- Add blocking reads when available is not being used (more complex than I thought ...).
- Two problems found:
- read timeout glitch in blocking mode (it doesn't timeout)
- a read on a nonblocking socket returns immediately (good), but with an EAGAIN rather
than returning
it has read 0 bytes (not good ?); now that I know about it, I can code for it
Modified: trunk/java/org/apache/catalina/connector/CoyoteAdapter.java
===================================================================
--- trunk/java/org/apache/catalina/connector/CoyoteAdapter.java 2008-03-04 00:36:11 UTC
(rev 462)
+++ trunk/java/org/apache/catalina/connector/CoyoteAdapter.java 2008-03-04 02:31:01 UTC
(rev 463)
@@ -215,7 +215,7 @@
/*if (response.isClosed() || !request.isComet()) {
res.action(ActionCode.ACTION_COMET_END, null);
} else*/
- if (!error && read && request.isReadable()) {
+ if (!error && read && request.ready()) {
// If this was a read and not all bytes have been read, or if no
data
// was read from the connector, then it is an error
log.error(sm.getString("coyoteAdapter.read"));
@@ -297,7 +297,7 @@
if (request.isComet()) {
if (!response.isClosed() && !response.isError()) {
res.action(ActionCode.ACTION_COMET_BEGIN, null);
- if (request.isReadable()) {
+ if (request.ready()) {
// Invoke a read event right away if there are available
bytes
if (event(req, res, SocketStatus.OPEN_READ)) {
comet = true;
Modified: trunk/java/org/apache/catalina/connector/InputBuffer.java
===================================================================
--- trunk/java/org/apache/catalina/connector/InputBuffer.java 2008-03-04 00:36:11 UTC (rev
462)
+++ trunk/java/org/apache/catalina/connector/InputBuffer.java 2008-03-04 02:31:01 UTC (rev
463)
@@ -270,6 +270,7 @@
available = bb.getLength();
if (request.isComet() && available == 0) {
try {
+ coyoteRequest.action(ActionCode.ACTION_AVAILABLE, null);
available = realReadBytes(null, 0, 0);
} catch (IOException e) {
// Ignore, will return 0, and another error
@@ -280,6 +281,7 @@
available = cb.getLength();
if (request.isComet() && available == 0) {
try {
+ coyoteRequest.action(ActionCode.ACTION_AVAILABLE, null);
available = realReadChars(null, 0, cb.getBuffer().length);
} catch (IOException e) {
// Ignore, will return 0, and another error
Modified: trunk/java/org/apache/catalina/connector/Request.java
===================================================================
--- trunk/java/org/apache/catalina/connector/Request.java 2008-03-04 00:36:11 UTC (rev
462)
+++ trunk/java/org/apache/catalina/connector/Request.java 2008-03-04 02:31:01 UTC (rev
463)
@@ -2257,7 +2257,7 @@
/**
* Return true if bytes are available.
*/
- public boolean isReadable() {
+ public boolean ready() {
return (inputBuffer.available() > 0);
}
Modified: trunk/java/org/apache/coyote/http11/Http11AprProcessor.java
===================================================================
--- trunk/java/org/apache/coyote/http11/Http11AprProcessor.java 2008-03-04 00:36:11 UTC
(rev 462)
+++ trunk/java/org/apache/coyote/http11/Http11AprProcessor.java 2008-03-04 02:31:01 UTC
(rev 463)
@@ -1267,19 +1267,22 @@
internalBuffer.addActiveFilter(savedBody);
} else if (actionCode == ActionCode.ACTION_AVAILABLE) {
- request.setAvailable(inputBuffer.available());
+ //request.setAvailable(inputBuffer.available());
+ inputBuffer.useAvailable();
} else if (actionCode == ActionCode.ACTION_COMET_BEGIN) {
comet = true;
// Set socket to non blocking mode
Socket.optSet(socket, Socket.APR_SO_NONBLOCK, 1);
Socket.timeoutSet(socket, 0);
outputBuffer.setNonBlocking(true);
+ inputBuffer.setNonBlocking(true);
} else if (actionCode == ActionCode.ACTION_COMET_END) {
comet = false;
// End non blocking mode
Socket.optSet(socket, Socket.APR_SO_NONBLOCK, 0);
Socket.timeoutSet(socket, endpoint.getSoTimeout());
outputBuffer.setNonBlocking(false);
+ inputBuffer.setNonBlocking(false);
} else if (actionCode == ActionCode.ACTION_COMET_SUSPEND) {
readNotifications = false;
} else if (actionCode == ActionCode.ACTION_COMET_RESUME) {
Modified: trunk/java/org/apache/coyote/http11/InternalAprInputBuffer.java
===================================================================
--- trunk/java/org/apache/coyote/http11/InternalAprInputBuffer.java 2008-03-04 00:36:11
UTC (rev 462)
+++ trunk/java/org/apache/coyote/http11/InternalAprInputBuffer.java 2008-03-04 02:31:01
UTC (rev 463)
@@ -174,6 +174,18 @@
protected int lastActiveFilter;
+ /**
+ * Non blocking mode.
+ */
+ protected boolean nonBlocking = false;
+
+
+ /**
+ * Non blocking mode.
+ */
+ protected boolean available = false;
+
+
// ------------------------------------------------------------- Properties
@@ -195,6 +207,22 @@
/**
+ * Set the non blocking flag.
+ */
+ public void setNonBlocking(boolean nonBlocking) {
+ this.nonBlocking = nonBlocking;
+ }
+
+
+ /**
+ * Get the non blocking flag value.
+ */
+ public boolean getNonBlocking() {
+ return nonBlocking;
+ }
+
+
+ /**
* Add an input filter to the filter library.
*/
public void addFilter(InputFilter filter) {
@@ -319,6 +347,7 @@
lastActiveFilter = -1;
parsingHeader = true;
swallowInput = true;
+ nonBlocking = false;
}
@@ -677,7 +706,8 @@
/**
* Available bytes (note that due to encoding, this may not correspond )
*/
- public int available() {
+ public void useAvailable() {
+ /*
int result = (lastValid - pos);
if ((result == 0) && (lastActiveFilter >= 0)) {
for (int i = 0; (result == 0) && (i <= lastActiveFilter); i++) {
@@ -685,6 +715,8 @@
}
}
return result;
+ */
+ available = true;
}
@@ -759,6 +791,33 @@
} else if (nRead < 0) {
if ((-nRead) == Status.ETIMEDOUT || (-nRead) == Status.TIMEUP) {
throw new
SocketTimeoutException(sm.getString("iib.failedread"));
+ } else if ((-nRead) == Status.EAGAIN && nonBlocking) {
+ // FIXME: I don't understand why the result is not nRead = 0
+ /* As asynchronous reads are forbidden, this test is not useful
*/
+ /*&& (Http11AprProcessor.containerThread.get() ==
Boolean.TRUE)*/
+ if (available) {
+ nRead = 0;
+ } else {
+ // In this specific situation, perform the read again in blocking
mode (the user is not
+ // using available and simply wants to read all data)
+ Socket.optSet(socket, Socket.APR_SO_NONBLOCK, 0);
+ // Also use the usual timeout
+ Socket.timeoutSet(socket, 20000*1000);
+ nRead = Socket.recvbb(socket, 0, buf.length - lastValid);
+ Socket.optSet(socket, Socket.APR_SO_NONBLOCK, 1);
+ Socket.timeoutSet(socket, 0);
+ if (nRead > 0) {
+ bbuf.limit(nRead);
+ bbuf.get(buf, pos, nRead);
+ lastValid = pos + nRead;
+ } else if (nRead < 0) {
+ if ((-nRead) == Status.ETIMEDOUT || (-nRead) ==
Status.TIMEUP) {
+ throw new
SocketTimeoutException(sm.getString("iib.failedread"));
+ } else {
+ throw new
IOException(sm.getString("iib.failedread"));
+ }
+ }
+ }
} else {
throw new IOException(sm.getString("iib.failedread"));
}
@@ -766,7 +825,7 @@
}
- return (nRead > 0);
+ return (nRead >= 0);
}