jsr340-experts@servlet-spec.java.net

[jsr340-experts] Re: Servlet 3.1 EDR updated draft

From: Rajiv Mordani <rajiv.mordani_at_oracle.com>
Date: Mon, 04 Jun 2012 15:34:52 -0700

On 6/1/12 5:02 AM, Greg Wilkins wrote:
> On 1 June 2012 02:49, Rajiv Mordani<rajiv.mordani_at_oracle.com> wrote:
>> We have discussed this in the past and what we said was b above.
> It was discussed, but I must have missed the decision to go for b, nor
> is it clear in the document or javadoc.
>
> I think this is poor choice as it means that a container and
> application cannot control their memory footprint. Consider an
> application that allocates some large byte arrays in some kind of
> content cache. It can be configured with a maximum memory usage and
> can be constrained. But when it starts sending these buffers
> asynchronously, it does not know if a write will copy the data. It
> might right the same content to an unlimited number of connections, so
> it may do an unlimited number of copies. Such an application would
> always be vulnerable to OOM and there is nothing the container or
> application can do to prevent it other than limit the number of
> connections - but the whole point of async IO is to increase
> scalability not to limit connections!

I think that Remy had mentioned earlier the notion of sendFile for
sending large data with essentially zero copying of buffers on the
ServletResponse. We can look at adding that kind of an api after the EDR
but for the async io I think that this approach will make programming to
the API simpler.

>
>
>
>> I have clarified this earlier as well and I think it is in the spec too -
>> but the onWritePossible is called once for every write possible. Once
>> invoked, it will not be invoked till a write operation is performed or the
>> canWrite is flipped.
>
> The document says:
>
> void onWritePossible(). This method will be invoked by the container for
> the associated NonBlockingOutputSink object when it is possible to write data.
> This method will be invoked once for every write operation possible. Once a
> write operation is performed, this method will subsequently be invoked by the
> container when further writes are possible.
>
> The javadoc says:
> void onWritePossible(ServletResponse response)
> This callback will be invoked when data can be written without blocking.

First this is the incorrect signature. I will fix this. Secondly - I am
open to suggestions how to make this more clear.

>
> Neither those descriptions nor the one you gave in your response make
> it very clear exactly what is meant. You say "will not be invoked
> till a write operation is performed" and the document says "invoked
> once for every write operation possible"
> So all of these imply that onWritePossible will be called after every
> write operations - is this correct?


No - not after every write operation.

> I thought the NIO.2 style was
> rejected because of the expense of callbacks, yet this proposal will
> have a callback per write?
>
> I had thought that the intention was that it would only be called if a
> write had causes canWrite status to flip from true to false.

If canWrite is called and it returns false, the onWritePossible will be
called.

> However, thinking about this now, that represents a horrible race
> condition as canWrite might flip to false during the call to write,
> but then might flip back to true before it is called, so the caller
> will not know if onWritePossilble will be called or not. If the
> intention is to have the callback happen only if the status is
> flipped, then to avoid the race then I think we need to say that
> onWritePossible is called ONLY if a call to canWrite() has returned
> false. ie if the internal canWrite status momentarily is false,
> that does not mean onWritePossible will be called, because if the
> write completes before canWrite() is called, then there is no need for
> the callback.
>
> Also the document and javadoc has no text explaining the context of
> the callback thread. I assume that it is a thread fully anointed
> with servletcontext scope an security stuff?

Yes that is correct.

> But for a suspended
> request that may have passed through several contexts, which context
> will this be? Also if the model really is a callback after every
> write, then many such IO frameworks will use the thread that called
> write to do the callback if the write completed. If we allow this,
> then we may have to do similar stuff to NIO.2 to prevent unconstrained
> stack growth if the callback does another write that does another
> callback etc. This problem is avoided if onWritePossible is only
> called if canWrite returns false.
>
> Is there a reference implementation of this available anywhere?
> What about some sample code that uses this API?

We are working on an implementation for this.

>
>
> regards
>
>
>
> Also