I think I need to have my vision checked. When I first looked, I saw
register(SelectionKey, ..) but not register(SocketChannel, ..).
Thanks Alexey!
I have keep-alive support implemented now, it still needs a bit of
polishing, but it's functional.
thanks again,
Igor
On Jan 18, 2010, at 1:22 PM, Oleksiy Stashok wrote:
> Hi Igor,
>
> did you try:
>
> selectorHandler.register(...)?
>
> Alexey.
>
> On Jan 18, 2010, at 21:34 , Igor Minar wrote:
>
>> This has turned out to be a bit more complicated than we originally
>> thought.
>>
>> This is what I tried:
>>
>> version 1) using SocketChannel#register directly in my own thread:
>>
>> channel.register(grizzlySelector, SelectionKey.OP_READ,
>> System.currentTimeMillis());
>>
>>
>> version 2) using SelectorHandler#addPendingIO:
>>
>> boolean origVal = ((TCPSelectorHandler)
>> selectorHandler).isFinishIOUsingCurrentThread();
>> ((TCPSelectorHandler)
>> selectorHandler).setFinishIOUsingCurrentThread(false);
>>
>> selectorHandler.addPendingIO(
>> new Runnable() {
>>
>> public void run() {
>> try {
>> channel.register(selectorHandler.getSelector(),
>> SelectionKey.OP_READ,
>> System.currentTimeMillis());
>> } catch (ClosedChannelException ex) {
>> //channel is already closed
>> }
>> }
>> }
>> );
>>
>> ((TCPSelectorHandler)
>> selectorHandler).setFinishIOUsingCurrentThread(origVal);
>>
>>
>> both work when there are no concurrent requests, but under load
>> both of them result in:
>>
>> java.util.ConcurrentModificationException
>> at java.util.HashMap$HashIterator.nextEntry(HashMap.java:793)
>> at java.util.HashMap$KeyIterator.next(HashMap.java:828)
>> at java.util.Collections$UnmodifiableCollection
>> $1.next(Collections.java:1010)
>> at
>> com
>> .sun
>> .grizzly
>> .http.SelectorThreadKeyHandler.expire(SelectorThreadKeyHandler.java:
>> 115)
>> at
>> com
>> .sun.grizzly.TCPSelectorHandler.postSelect(TCPSelectorHandler.java:
>> 556)
>>
>>
>> This is because both versions register the channel with the
>> selector in a thread that is not the SelectorThread, which is not
>> thread safe.
>>
>> Unfortunately I don't see a way to register a channel with the
>> selector in a thread safe manner without modifying
>> TCPSelectorHandler and adding a concurrent queue to it for
>> operations that will get executed by the thread handling
>> Selector#select operations.
>>
>> Thoughts?
>>
>> /i
>>
>>
>> On Jan 14, 2010, at 9:57 AM, Igor Minar wrote:
>>
>>> Hi Alexey,
>>>
>>> You are just proving that I'm not familiar with all the details of
>>> the grizzly apis I'm using. I did not know that returning false
>>> from the filter has this effect. I'll give it a shot tonight!
>>>
>>> thanks,
>>> Igor
>>>
>>>
>>> On Jan 14, 2010, at 9:48 AM, Oleksiy Stashok wrote:
>>>
>>>> Hi Igor,
>>>>
>>>> probably you've already tried that.... anyway
>>>> IMO, when you decide to intercept connection to execute sendfile
>>>> asynchronously, you can return false from AsyncFilter. This way
>>>> you'll be able to keep ProcessorTask, so at time when sendfile
>>>> will complete its task - you can register Channel back to the
>>>> main SelectorThread and resume connection using saved
>>>> ProcessorTask.
>>>>
>>>> Please correct me, if something is missed.
>>>>
>>>> Thanks.
>>>>
>>>> WBR,
>>>> Alexey.
>>>>
>>>>> As I mentioned in my previous email, I expect that support for
>>>>> http keep-alive (persistent connections) is another major
>>>>> feature that could push the performance of grizzly-sendfile even
>>>>> further. I believe that with the current grizzly (1.9) api, it
>>>>> is not possible for me to get this done, but I might be wrong.
>>>>> In any case, I'd appreciate help with either pointing me to the
>>>>> right api or discussing changes to grizzly needed in order to
>>>>> make this possible.
>>>>>
>>>>>
>>>>> How grizzly-sendfile integrates with grizzly:
>>>>>
>>>>> grizzly-sendfile works as an async filter for grizzly, which
>>>>> intercepts all the http requests and when it determines that it
>>>>> is being requested to download a static file, it deregisters the
>>>>> current socket channel from the grizzly's selector, returns from
>>>>> the filter and asynchronously does its best to efficiently send
>>>>> the requested file to the client and then closes the connection.
>>>>>
>>>>>
>>>>> The problem:
>>>>>
>>>>> Ending the transmission like this results in non-persistent
>>>>> connections (Connection: close), which come with a significant
>>>>> performance penalty compared to keep-alive (persistent)
>>>>> connections.
>>>>>
>>>>> I'd much rather return the connection back to grizzly and put it
>>>>> in its keep alive queue or list, so that it could be reused for
>>>>> future transmissions. However because of the async
>>>>> implementation by the time when the download is finished, the
>>>>> ProcessorTask that was provided to my filter is long gone
>>>>> (recycled, or possibly in use by a different request), and the
>>>>> only thing I'm left with is the actual socket channel.
>>>>>
>>>>>
>>>>> The question:
>>>>>
>>>>> Is there a way for me to take a channel and make grizzly accept
>>>>> it as a channel that should be monitored for further requests?
>>>>> Or is there a better way to integrate with grizzly that would
>>>>> allow me to achieve my keep-alive goal?
>>>>>
>>>>> To get an idea of what I'm doing without digging through all of
>>>>> the grizzly-sendfile's code, I suggest that you have a look at
>>>>> my async filter [1], which is the integration point between
>>>>> grizzly and grizzly-sendfile. Just keep in mind that when a
>>>>> Download[2] is prepared in the filter and registered with my
>>>>> selector thread, the filter returns. The Download is then
>>>>> processed asynchronously by grizzly-sendfile threads.
>>>>>
>>>>> thanks,
>>>>> Igor
>>>>>
>>>>>
>>>>> [1] https://hg.kenai.com/hg/grizzly-sendfile~main/file/
>>>>> a68e8b200193/grizzly-sendfile-g19/src/main/java/com/igorminar/
>>>>> grizzlysendfile/SendfileFilter.java#l1
>>>>> [2] https://hg.kenai.com/hg/grizzly-sendfile~main/file/
>>>>> a68e8b200193/sendfile-core/src/main/java/com/igorminar/
>>>>> grizzlysendfile/Download.java#l1
>>>>>
>>>>> ---------------------------------------------------------------------
>>>>> To unsubscribe, e-mail: dev-unsubscribe_at_grizzly.dev.java.net
>>>>> For additional commands, e-mail: dev-help_at_grizzly.dev.java.net
>>>>>
>>>>
>>>>
>>>> ---------------------------------------------------------------------
>>>> To unsubscribe, e-mail: dev-unsubscribe_at_grizzly.dev.java.net
>>>> For additional commands, e-mail: dev-help_at_grizzly.dev.java.net
>>>>
>>>
>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: dev-unsubscribe_at_grizzly.dev.java.net
>> For additional commands, e-mail: dev-help_at_grizzly.dev.java.net
>>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe_at_grizzly.dev.java.net
> For additional commands, e-mail: dev-help_at_grizzly.dev.java.net
>