Remy Maucherat wrote:
Filip Hanik - Dev Lists wrote:
Here are some changes.
1. The background thread should not have to call notifyWrite, since
we provide READ event, we can also provide
an automatic event is thrown when a write completes
EventType=NOTIFY EventSubType=WRITE_COMPLETE, as soon as the write
does complete
One exception, if the write completes on the first write attempt,
canWrite returns true immediately after outputstream/writer.write(...)
It is easier to implement, as we don't have to keep track of if
they want to be notified or not.
So basically, outputstream.write() -> canWrite==true -> we finished
writing everything
and in the same fashion, outputstream.write() -> canWrite==false ->
we can expect a NOTIFY event
canWrite should measure the length of bbuf, that's the easiest way
to know if we can write or not
I agree, but I don't understand how you can know if you can write
without a write polling. If there are no events on read, I have the
impression writing could be suspended for an indefinite amount of
time. So if it works, I am fine with this process.
In NIO, you basically can call SocketChannel.write anytime you want, it
will return 0 if you can't. At the time of returning 0, you simply
register it with the poller so that the poller notifies you when a
SocketChannel.write actually will succeed. ie, you don't need a poller,
you could do a spinning SocketChannel.write until it succeeds, of course
this will suck up your CPU. Does that make sense?
3. Since a write can timeout, and event ERROR/TIMEOUT might happen
instead of NOTIFY/WRITE_COMPLETE.
This is one case where ERROR/TIMEOUT should close the socket, and
that is why I think it should always do it
regardless of have we do it now. Keeping a connection open after a
TIMEOUT is not good, cause it makes it so much harder to clean up
In a write timeout, we have data left in a buffer
I don't want to do any special funky tracking of writes in the APR
connector, so I disagree with this (feel free to keep it in the NIO
connector if you want to, I'm fine with that). It's also a gratuitous
action which does not provide a real benefit.
funky tracking? ie, as keeping track of timeouts? Not sure how you are
gonna implement "per-connection" timeouts without it?
Definitely a write should not be indefinite, it should timeout, just
like a servlet write does today for servlets.
4. Implementation detail, in TC 6 the buffers are sent in a separate
flush to the socket
Can we just merge this with the first servlet flush or automatic flush
This will simply send the response headers with the first data for
the response, hence be included in the
"non block" write logic without further workarounds for that.
I believe the number of writes should be kept as low as possible.
Exactly, today you are doing two when it can be done using one write.
5. non block read
After thinking about it, and since we send "events" when data is
available on the socket
I don't think we should enable them.
The only time a non block read, would be in Comet connections that
are in:
a) the connection is non block mode &&
b) the connection is not registered for a OP_READ with the Poller
Because of the concurrency problems that can arise from non-block
read and the connection being registered for READ with the poller,
this feature is actually better if it is left implemented as it is
today.
6. READ event
However, there is a need to modify the read, currently the
CoyoteAdapter will end up in a blocking read if not enough data
has been fetched that is needed for the filter.
The filter should be able to back out, so that the connection gets
returned to the poller to retrieve more data
Bottom line is that Comet threads should never call
inputstream.read() unless it is a READ event
If we feel there is a need, we can make non block read available to
the servlet, although I see that lower priority than the write
stuff and the blocking CoyoteAdapter.read
I don't think you can have non blocking writes and blocking reads (at
least I don't know how to do it with APR). I wanted to point out that
non blocking reads and blocking reads were almost equivalent.
NIO you can, but I'd like for the connectors to be consistent. blocking
and non blocking reads are very different.
For example, CoyoteAdapter.read today, locks up in a blocking read, easy
to reproduce, if a filter needs more data to do processing upon a READ
event.
You can easily lock up a whole server, making it a subject to a denial
of service.
What I am saying is that we shouldn't allow the servlet to do a
event.getHttpServletRequest().getInputStream().read() if the socket is
registed for a READ event. non blocking mode is fine, as you can
instantly return a 0 if that is the case. Blocking mode, when the poller
wakes up,
the async thread will most likely get the data, then the READ event will
proceed into the CoyoteAdapter on the worker thread, and get blocked in
the CoyoteAdapter.read
and voila, you are screwed.
see the problem I am trying to describe. I'm all for non blocking read,
for the servlet programmer I find it useless, but for the rest of tomcat
it is necessary in order for comet to work well.
1 background thread
Ah, the "feel good" factor ;)
you can't do anything without it ;)
Filip
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]