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]

Reply via email to