Sorry, pls. ignore my last email, the proposed workaround may cause
thread racing, when 2 threads try to work with InputStream, which is not
thread-safe.
The workaround, which would work - is to move current
UploadTask.run(...) method logic to UploadTask.prepare(...) method, so
it would be called from the HttpHandler.handle(...) thread.
Thanks.
WBR,
Alexey.
On 08/09/2011 02:25 PM, Oleksiy Stashok wrote:
> Hi David,
>
>> Thanks for your explanations. It's clear now.
>>
>> As you suggest, I open a Improvement issue on the Grizzly's JIRA here
>> : http://java.net/jira/browse/GRIZZLY-1056
>>
>> Just one comment : I set the priority to "Major". You may be not
>> agree on that, but it is for my use case.
>>
>> I may be the only one that use Grizzly like that, so I would
>> understand if you decide to change the priority.
>>
> No problem.
>
>
>> I can explain briefly how I works with Grizzly :
>>
>> I have a main handler that serve all request and do unconditionally :
>>
>> -Suspend the response
>>
>> -Given the url, find a "RequestProcessor" and delegate the processing
>> to a thread pool
>>
>> It was made like that because it allow us to serve many request in
>> parallel without increasing the Grizzly worker thread (that consume
>> lot of memory in Grizzly 1.9.x)
>>
>> As the request processor is a interface, the main handler don't have
>> any knowledge about what it want to do.
>>
>> It was made to be generic and pluggable for future needs.
>>
>> We have also put some service facilities for RequestProcessor
>> implementor that allow them to download a file with a simple line of
>> code, for example :
>>
>> DonwloadManager.download( request, response, inputstream ) -> it
>> serve the resource input stream to the client in an async manner.
>>
>> And this is inside the Download/Upload Manager I would like to use
>> the new async read/write of Grizzly 2.
>>
>> From a functional point of view, it fit perfectly well.
>>
>> But as it already suspend and run inside my request processor thread,
>> it not possible.
>>
>> So, sorry to bother you with all my stuff, my goal was just to try to
>> argument why I put the priority to "Major"
>>
> As I've mentioned on issue tracker, it's not a problem to work with
> NIO Streams from the custom thread. The problem is that Grizzly needs
> to understand that you want to work with InputStream in non-blocking
> mode, before you exit HttpHandler.handle(...) method.
> Just as workaround you can add
> RequestProcessor.prepare(Request, Response) method and call it before
> delegating Request/Response processing to a custom thread, and in
> Download/UploadManager implement prepare(...) method as:
>
> -------------
> public void prepare(Request request, Response response) throws
> IOException {
> request.getInputStream(false);
> }
> -------------
>
> Once Grizzly understands you want to use InputStream in non-blocking
> mode - the rest of your code should work.
>
> Thanks.
>
> WBR,
> Alexey.
>>
>> Thanks all for your help
>>
>> Regards
>>
>> David
>>
>> *De :*Ryan Lubke [mailto:ryan.lubke_at_oracle.com]
>> *Envoyé :* lundi 8 août 2011 21:25
>> *À :* users_at_grizzly.java.net
>> *Objet :* Re: From Grizzly 1.9.x to 2.x
>>
>> On 8/8/11 11:57 AM, Ryan Lubke wrote:
>>
>> On 8/8/11 8:47 AM, Gay David (Annecy) wrote:
>>
>> Hi Alexey,
>>
>> Yep, I think I got it. See my attached sample test case.
>>
>> It use Grizzly 2.1.2-SNAPSHOT checkout from yesterday.
>>
>> If you run it like that, it works.
>>
>> But if you modified the class UploadTask like that :
>>
>> //--- Constructor
>> ----------------------------------------------------------
>>
>> public UploadTask( Request req, Response res ) throws
>> FileNotFoundException
>>
>> {
>>
>> this.req = req;
>>
>> this.res = res;
>>
>> //this.channel = Channels.newChannel( new
>> FileOutputStream(new File("toto-"+COUNT.getAndIncrement()+".data")) );
>>
>> this.channel = Channels.newChannel( new NullOutputStream() );
>>
>> this.error = null;
>>
>> // Get the non-blocking input stream from the Grizzly thread
>> : IT WORKS
>>
>> *///this.is = req.getInputStream( false );*
>>
>> }
>>
>> //--- Runnable implementation
>> ----------------------------------------------
>>
>> @Override
>>
>> public void run()
>>
>> {
>>
>> // Get the non-blocking input stream from the thread pool :
>> IT DOES NOT WORKS !
>>
>> *this.is = req.getInputStream( false );*
>>
>> is.notifyAvailable( this, PREFERRED_SIZE );
>>
>> }
>>
>> Then, it doesn't work. As I don't know why, I think the only
>> difference is that the getInputStream() call is made in the Grizzly
>> thread in the constructor, while the the same call is made from my
>> executor thread poll. It's not obvious for me what's happen in the
>> Grizzly code.
>>
>> So my questions :
>>
>> Is my theory correct ?
>>
>>
>> Yes. In the working case, the HttpServerFilter is properly
>> configured for async operations when AsyncHandler.service(). This is
>> true because, like you said, getInputStream() was called within the
>> constructor of UploadTask, so the HttpServerFilter had the correct
>> state. When you called getInputStream() within the run() method,
>> AsyncHandler.service() had already exited. Since the async state
>> wasn't present at that time, the HttpServerFilter will only operate
>> in blocking mode.
>>
>>
>> Is it a mistake to call the getInputStream() from thread other than
>> the Grizzly ones ?
>>
>>
>> I think the rule of thumb is that getInputStream() must be called
>> before exiting the service() method of your handler.
>>
>>
>> Or, is it a limitation/bug of the current version ? If so, do you
>> want me to open an issue ?
>>
>>
>> It's a limitation (albeit a minor one). I think we should document
>> this and move on.
>>
>>
>> After further discussion, we've documented the limitation, but we'll
>> try to resolve this in the next release.
>> Please do log an issue.
>>
>> Thanks,
>> -rl
>>
>>
>>
>>
>>
>> Thanks
>>
>> David
>>
>> *De :*Oleksiy Stashok [mailto:oleksiy.stashok_at_oracle.com]
>> *Envoyé :* lundi 8 août 2011 13:45
>> *À :* users_at_grizzly.java.net <mailto:users_at_grizzly.java.net>
>> *Objet :* Re: From Grizzly 1.9.x to 2.x
>>
>> Hi David,
>>
>> the issue is probably in the ReadHander registration code, not in
>> actual ReadHandler.
>> Can you pls. share more code, may be working (or better say
>> non-working) sample?
>>
>> Thanks.
>>
>> WBR,
>> Alexey.
>>
>>
>>
>