Remy Maucherat wrote:
Filip Hanik - Dev Lists wrote:
ok, here we go, I have thought about this and have two different
proposals.
1. Add non blocking support to Coyote(In|Out)putStream
The servlet can cast request.getInputStream() to a CoyoteInputStream
Example:
//perform a non blocking read.
int read = ((CoyoteInputStream)request.getInputStream()).nbRead(buf);
if ( read > 0 ) //we have data
else if ( read == -1 ) //eof, in NIO it actually throws EOFException
else // move on, read returned 0
Same support for writing.
Basically, the CoyoteInputStream.read would return the actual number
of bytes available to the servlet. not the number of bytes by the
socket.
So the read would have to filter through the chain, and the entire
buffer chain would have to support this, I think this is all doable.
2. Alternative - expose nbRead through available() method
If we don't want to expose nbRead or nbWrite by casting to an
interface, we could always make
available() as a non blocking read. available() would return the
actual number of bytes for the servlet.
should available() return >0, then request.getInputStream().read()
should return the same number of bytes the return value for available().
Basically, available() invokes a non blocking read from the socket.
then the bytes get passed through the buffers.
If some buffer requires additional data, it will not invoke a
blocking read, instead available() will return 0.
request.getInputStream().read() - if the top most buffer has data, it
will return it immediately, and not invoke the chain down.
If there is no data, this becomes a regular read.
This solution lets us do a non blocking read using the existing API,
but has no solution for a non blocking write.
I'd be happy to take a stab at this, and if we don't like it, we can
throw it away. I think it is easier for me to show it through code,
than through an essay in an email.
Just give me a feel for option 1 or 2, and I will take one of them,
and do it this week, by the end of week I can have one option
completed for testing.
This is interesting, and it's giving me some (basic) ideas. I think it
(at least part 2) is too much about reading, where non blocking and
blocking are functionally equivalent due to the events which allow
knowing when read will not block.
In theory, 1 is more interesting, but not with the casting and API
hacking. It is perfectly legitimate to use Reader/Writer, so adding
calls which bypass the standard does not seem like a good idea. Maybe
it could work with an IO control feature on the event (a canWrite
method or something; the low level would use non blocking writes,
buffer a little bit, and expect the user to use canWrite to check the
result of the last real write to the socket; if the user keeps on
writing without checking canWrite, throw an exception), to go along
write events (which is a problem: I don't know how to request to be
placed in a poller, although maybe another method on the event could
work), and maybe it would be enough.
To get it to the poller one could do
event.notify(OP_WRITE) -> notify me when I can do a write. this would
result in an event with EventType=NOTIFY EventSubType=WRITE
same to get notified of a READ event in the case of not being registered
with the poller.
I thought about the canWrite idea earlier, and there is a difficult
problem to get around. the steps are
1. canWrite - returns true
2. response.getOutputStream().write(8k byte array)
3. only 2k gets written during the non blocking write
so what does one do? does it issue a blocking write for the remainder?
it gets quite tricky.
that is why the cast/API hack (which can be done for both reader/writer
as well as input/output streams) is a clearer way.
so non blocking read, is pretty easy to accomplish, but non blocking
write is very difficult using the regular API as you may write partial
data, regardless of what method we use to do this.
any thoughts on this.
Filip
> got it, the extra bytes, if that is a new request, ie "GET /
> HTTP/1.1..." will that work?
Yes, that's pipelining. The extra bytes are supposed to be a new request.
Rémy
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]