> I was thinking about something like that, but more developer friendly,
> for example :
>
> * Have an annotation on my RequestProcessor like @ASync
>
> * And modify the main handler :
>
> public service( Request req, Response res )
>
> {
>
> RequestProcessor rp = find( req, res );
>
> if( hasAsyncAnnotation(rp) )
>
> {
>
> req.getInputStream( false );
>
> }
>
> res.suspend( … )
>
> executor.execute( rp );
>
> }
>
> As I don’t really understand the problem you point me out, will this
> code be affected by the same problem ?
>
Yes, the code above wouldn't work properly as well due to possible
thread collision on InputStream.
Looking at your UploadTask - IMO there is no reason to execute its run()
method logic in the separate thread, you pay pretty significant price
when switching thread context just to initiate asynchronous reading.
Specifically in this situation executor.execute(rp) for UploadTask looks
redundant.
May be you solution may look like:
Have annotation in RequestProcessor like @Blocking
So:
public service( Request req, Response res ) {
RequestProcessor rp = find( req, res );
res.suspend( …);
if( isBlokcking(rp) ) {
executor.execute( rp );
} else {
rp.run();
}
}
Thanks.
WBR,
Alexey.
> Thanks
>
> David
>
> *De :*Oleksiy Stashok [mailto:oleksiy.stashok_at_oracle.com]
> *Envoyé :* mardi 9 août 2011 14:41
> *À :* users_at_grizzly.java.net
> *Objet :* Re: From Grizzly 1.9.x to 2.x
>
> 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 <mailto: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.
>
>
>
>