users@grizzly.java.net

Re: Should I use Context to store the clients references ?

From: Survivant 00 <survivant00_at_gmail.com>
Date: Tue, 15 Jul 2008 12:31:36 -0400

thanks for #2

for #1.. if I use a breakpoiunt.. it will always be parsed.

if I try 10-12 times.. it will be parsed sometime.. but most of the time..
it's never parsed

2008/7/15 Oleksiy Stashok <Oleksiy.Stashok_at_sun.com>:

> #2 is easy
> in the Grizzly initialization code add this:
>
> selectorHandler.setSelectionKeyHandler(new BaseSelectionKeyHandler());
>
> because DefaultSelectionKeyHandler implementation has expiration logic,
> which is actually useful against DoS attacks etc...
>
> #1 not sure... I need some time to take a look closer at the parser code.
> just one question to be sure... 2nd message never gets parsed, or sometimes
> it works, sometimes not?
>
> Thanks.
>
> WBR,
> Alexey.
>
> On Jul 15, 2008, at 17:46 , Survivant 00 wrote:
>
> thanks it works.. but my problems are not done yet.
>
> #1 -
> I'm able to send multiple request to the server, but there is a bug.
>
> The first filter taht parse the query doesn't parse the second query.
>
> I'm able to test with.. in DEBUG.. I put a breakpoint on the method
> isExpectingMoreData
>
> and when I resume.. it will parse the next query.. that's wierd..
>
> I reset my flag in the method
> public boolean releaseBuffer() {
> //System.out.println("releaseBuffer");
>
> if(f_cumulatifBB != null) {
> f_cumulatifBB.clear();
> }
> f_cumulatifBB = null;
>
> eoqFound = false;
>
> return false;
> }
>
>
> maybe this is not called when I return the message with getMessage();
>
>
> #2 -
>
> I got disconnected after 30 sec. why ? is it the default timeout value in
> grizzly ?
>
> what do I need to do to get never expired ?
>
>
>
>
>
>
> 2008/7/15 Oleksiy Stashok <Oleksiy.Stashok_at_sun.com>:
>
>> Thanks for sources.
>> In your implementation you define ClientConnectionHandler to represent one
>> single client connection during its life-cycle.
>> Probably in this case I would suggest to use attachments
>> (ThreadAttachment).
>> Here what I'm proposing...
>>
>> private ClientConnectionHandler retrieveConnectionHandler(Context
>> context) {
>> ClientConnectionHandler clientConnectionHandler = null;
>>
>> AttributeHolder connectionAttrs =
>> ctx.getAttributeHolderByScope(AttributeScope.CONNECTION);
>> if (connectionAttrs != null) {
>> clientConnectionHandler = (ClientConnectionHandler)
>> connectionAttrs.getAttribute(CLIENT_CONNECTION_HANDLER_ATTR);
>> } else {
>> WorkerThread workerThread = (WorkerThread)
>> Thread.currentThread(); // Detach the current Thread data.
>> connectionAttrs = workerThread.getAttachment();
>> // Attach it to the SelectionKey so the it can be resumed
>> latter.
>> key.attach(connectionAttrs);
>> }
>>
>> if (clientConnectionHandler == null) {
>> clientConnectionHandler = new
>> ClientConnectionHandler(manager, context.getSelectionKey(),
>> context.getSelectorHandler());
>>
>> connectionAttrs.setAttribute(CLIENT_CONNECTION_HANDLER_ATTR,
>> clientConnectionHandler);
>> }
>>
>> return clientConnectionHandler;
>> }
>>
>> this could be the way how to get ClientConnectionHandler associated with
>> the specific connection or create new if required.
>> See complete QuoteQueryManagerFilter source.
>>
>> Not sure this will work as it is... as I didn't try to compile it - but
>> hope it's clear enough to understand what I meant :)
>>
>> Thanks.
>>
>> WBR,
>> Alexey.
>>
>> package org.sample.nio.connection.handler.filter;
>>
>> import java.io.IOException;
>> import java.net.SocketAddress;
>> import java.nio.ByteBuffer;
>> import java.nio.channels.DatagramChannel;
>> import java.nio.channels.SelectableChannel;
>> import java.nio.channels.SelectionKey;
>> import java.util.logging.Level;
>>
>> import org.sample.nio.QuoteManager;
>> import org.sample.nio.connection.handler.ClientConnectionHandler;
>>
>> import com.sun.grizzly.Context;
>> import com.sun.grizzly.Controller;
>> import com.sun.grizzly.ProtocolFilter;
>> import com.sun.grizzly.ProtocolParser;
>> import com.sun.grizzly.SelectorHandler;
>> import com.sun.grizzly.TCPSelectorHandler;
>> import com.sun.grizzly.filter.ReadFilter;
>> import com.sun.grizzly.util.OutputWriter;
>>
>> public class QuoteQueryManagerFilter implements ProtocolFilter {
>> private static final String CLIENT_CONNECTION_HANDLER_ATTR =
>> "connection-handler";
>>
>> private QuoteManager manager;
>>
>> public QuoteQueryManagerFilter(QuoteManager manager) {
>> this.manager = manager;
>> }
>>
>> public boolean execute(Context context) throws IOException {
>> String query = (String)
>> context.removeAttribute(ProtocolParser.MESSAGE);
>>
>> if(query==null || query.trim().length()==0){
>> return false;
>> }
>>
>> System.out.println("query = " + query);
>>
>> //here should be the parsed query command string with
>> // which query should be able to create a command
>> // I have no time to rewrite ClientConnectionHandler
>> // Basically you have in context a link to client connection
>> //with that and for example TCPSelectorHandler your commands can
>> //send data to client
>>
>> /*
>> * For now instead of keeping whole Context, you can just keep
>> SelectionKey as reference to the client,
>> * and send response back using:
>> selectorHandler.getAsyncQueueWriter().write(SelectionKey, ...);
>> */
>>
>> // on va chercher le ClientConnectionHandler si il existe
>>
>> ClientConnectionHandler clientConnectionHandler =
>> retrieveConnectionHandler(context);
>>
>> manager.processQuery(clientConnectionHandler, query);
>>
>>
>> // // Depending on protocol perform echo
>> // //SelectableChannel channel =
>> context.getSelectionKey().channel();
>> // try {
>> //
>> // ByteBuffer writeBuffer =
>> ByteBuffer.allocateDirect(query.length());
>> //
>> // writeBuffer.put(query.getBytes());
>> //
>> // writeBuffer.flip();
>> //
>> // SelectionKey key = context.getSelectionKey();
>> //
>> // SelectorHandler selectorHandler =
>> context.getSelectorHandler();
>> //
>> //
>> selectorHandler.getAsyncQueueWriter().write(key,writeBuffer);
>> //
>> // /*
>> // if (context.getProtocol() == Controller.Protocol.TCP) { //
>> TCP case
>> // OutputWriter.flushChannel(channel, writeBuffer);
>> // }
>> // */
>> //
>> //context.getAsyncQueueWritable().writeToAsyncQueue(writeBuffer, null,
>> null, true);
>> // } catch (IOException ex) {
>> // throw ex;
>> // }
>>
>> /*
>> * The former will block until all the bytes are written. When I
>> say block,
>> * I mean the calling Thread will block. The OutputWriter
>> internally use a pool of
>> * temporary Selector to make sure writes are always executed
>> entirely.
>>
>> With async queue write (the later), the calling thread will
>> not block. instead,
>> the async queue mechanism will make sure your write
>> operation is successful.
>> Depending on the protocol, picking one or the other make a
>> big difference.
>> HTTP use OutputWriter, SIP use async queue.
>>
>> */
>>
>> return true;
>> }
>>
>> public boolean postExecute(Context context) throws IOException {
>> return true;
>> }
>>
>> private ClientConnectionHandler retrieveConnectionHandler(Context
>> context) {
>> ClientConnectionHandler clientConnectionHandler = null;
>>
>> AttributeHolder connectionAttrs =
>> ctx.getAttributeHolderByScope(AttributeScope.CONNECTION);
>> if (connectionAttrs != null) {
>> clientConnectionHandler = (ClientConnectionHandler)
>> connectionAttrs.getAttribute(CLIENT_CONNECTION_HANDLER_ATTR);
>> } else {
>> WorkerThread workerThread = (WorkerThread)
>> Thread.currentThread(); // Detach the current Thread data.
>> connectionAttrs = workerThread.getAttachment();
>> // Attach it to the SelectionKey so the it can be resumed
>> latter.
>> key.attach(connectionAttrs);
>> }
>>
>> if (clientConnectionHandler == null) {
>> clientConnectionHandler = new
>> ClientConnectionHandler(manager, context.getSelectionKey(),
>> context.getSelectorHandler());
>>
>> connectionAttrs.setAttribute(CLIENT_CONNECTION_HANDLER_ATTR,
>> clientConnectionHandler);
>> }
>>
>> return clientConnectionHandler;
>>
>> }
>> }
>>
>> On Jul 15, 2008, at 15:00 , Survivant 00 wrote:
>>
>>
>>>
>>> 2008/7/15 Oleksiy Stashok <Oleksiy.Stashok_at_sun.com>:
>>> Ok :))
>>>
>>> Can you pls. attach all Grizzly related sources - it will help a lot :)
>>>
>>> Thanks.
>>>
>>> WBR,
>>> Alexey.
>>>
>>> On Jul 15, 2008, at 14:52 , Survivant 00 wrote:
>>>
>>> euh, sorry it was the only way that I found a sample. That why I asked
>>>> the questions.. maybe the problem is there, but like I didn't know other
>>>> way..
>>>>
>>>>
>>>>
>>>> 2008/7/15 Oleksiy Stashok <Oleksiy.Stashok_at_sun.com>:
>>>>
>>>>> I'll explain my needs from the start.
>>>>>
>>>>> it's for a stock quote simulator.
>>>>>
>>>>> when a client connect to the server, it will send requests.
>>>>>
>>>>> like that
>>>>>
>>>>> client 1 -> - want the feed for the symbol | aaa
>>>>> - want the feed for the symbol | bbb
>>>>>
>>>>> client 2 -> - want the feed for the symbol | aaa
>>>>>
>>>>>
>>>>> In the server using grizzly :
>>>>>
>>>>> I have 2 filters in the chains.
>>>>>
>>>>> - the first for parsing the messages
>>>>> - the second for processing the message
>>>>>
>>>>> I need to keep a reference for all the clients and know which feed they
>>>>> register to.
>>>>>
>>>>> When I process to message, I'll receive the response from a 3th party
>>>>> later, and I 'll receive it on a callback method, and I'll send back the
>>>>> response to the client register as soon as the response arrive.
>>>>>
>>>>>
>>>>> The main problem that I had was that in the second filter, I need to
>>>>> know if the client already ask for a feed and I need to know how to send it
>>>>> back to data. That why I wanted to use a ClientConnectionHandler ( before
>>>>> using grizzly, I created the cleintconnectionhandler just after the
>>>>> socketserver.accept() ) to keep the selectionKey and the channel to send the
>>>>> data back.
>>>>>
>>>>>
>>>>> if I loop into your sample.. it will create a pool each time the client
>>>>> send a message.
>>>>>
>>>> Why? You're using stateful ProtocolChain? In other words you have
>>>> protocol chain, associated with each client connection?
>>>>
>>>> WBR,
>>>> Alexey.
>>>>
>>>>
>>>>>
>>>>>
>>>>>
>>>>> 2008/7/15 Oleksiy Stashok <Oleksiy.Stashok_at_sun.com>:
>>>>> Hi,
>>>>>
>>>>> your implementation is ok.
>>>>> Though if having the map of all client connections is not must - then
>>>>> you can create ClientConnectionHandler pool like inline...
>>>>>
>>>>> public class QuoteQueryManagerFilter implements ProtocolFilter {
>>>>>>
>>>>>> ConcurrentLinkedQueue<ClientConnectionHandler> pool = new
>>>>> ConcurrentLinkedQueue<ClientConnectionHandler>();
>>>>>
>>>>>> private QuoteManager manager;
>>>>>>
>>>>>> public QuoteQueryManagerFilter(QuoteManager manager) {
>>>>>> this.manager = manager;
>>>>>> }
>>>>>>
>>>>>> public boolean execute(Context context) throws IOException {
>>>>>> String query = (String)
>>>>>> context.removeAttribute(ProtocolParser.MESSAGE);
>>>>>>
>>>>>> if(query==null || query.trim().length()==0){
>>>>>> return false;
>>>>>> }
>>>>>>
>>>>>> System.out.println("query = " + query);
>>>>>>
>>>>>> //here should be the parsed query command string with
>>>>>> // which query should be able to create a command
>>>>>> // I have no time to rewrite ClientConnectionHandler
>>>>>> // Basically you have in context a link to client connection
>>>>>> //with that and for example TCPSelectorHandler your commands
>>>>>> can
>>>>>> //send data to client
>>>>>>
>>>>>> /*
>>>>>> * For now instead of keeping whole Context, you can just keep
>>>>>> SelectionKey as reference to the client,
>>>>>> * and send response back using:
>>>>>> selectorHandler.getAsyncQueueWriter().write(SelectionKey, ...);
>>>>>> */
>>>>>>
>>>>>> // on va chercher le ClientConnectionHandler si il existe
>>>>>>
>>>>>> ClientConnectionHandler clientConnectionHandler =
>>>>> pool.poll();
>>>>> if (clientConnectionHandler != null) {
>>>>> clientConnectionHandler.init(manager,
>>>>> context.getSelectionKey(), context.getSelectorHandler());
>>>>> } else {
>>>>> clientConnectionHandler = new
>>>>> ClientConnectionHandler(manager, context.getSelectionKey(),
>>>>> context.getSelectorHandler());
>>>>> }
>>>>>
>>>>> // ClientConnectionHandler clientConnectionHandler = null;
>>>>>>
>>>>>> //
>>>>>> if(manager.selectionKeyMap.containsKey(context.getSelectionKey())){
>>>>>> // clientConnectionHandler =
>>>>>> manager.selectionKeyMap.get(context.getSelectionKey());
>>>>>> // } else {
>>>>>> // clientConnectionHandler = new
>>>>>> ClientConnectionHandler(manager, context.getSelectionKey(),
>>>>>> context.getSelectorHandler());
>>>>>> // }
>>>>>>
>>>>>> manager.processQuery(clientConnectionHandler, query);
>>>>>>
>>>>>>
>>>>>>
>>>>> and then return ClientConnectionHandler to the pool from processing
>>>>> thread.
>>>>> In example above single ClientConnectionHandler could be associated
>>>>> with different client connections, but not at the same time.
>>>>>
>>>>> If you need to associate ClientConnectionHandler with just one client
>>>>> connection during its life-cycle - may be it makes sense to use
>>>>> ThreadAttachment's attributes.
>>>>> Let me know if this is required.
>>>>>
>>>>> Thanks.
>>>>>
>>>>> WBR,
>>>>> Alexey.
>>>>>
>>>>>
>>>>>
>>>>>> 2008/7/15 Oleksiy Stashok <Oleksiy.Stashok_at_sun.com>:
>>>>>> Hi,
>>>>>>
>>>>>>
>>>>>> I have a chain of 2 filters.
>>>>>>
>>>>>> #1 - parsing the request
>>>>>> #2 - processing the request
>>>>>>
>>>>>> and loop until the client quit.
>>>>>>
>>>>>> I want to kept the info about the connection like :
>>>>>> context.getSelectionKey(), context.getSelectorHandler() in a Object like :
>>>>>>
>>>>>> ClientTracker(SelectionKey key, SelectorHandler selectorHandler)
>>>>>>
>>>>>> and I'll send data back to the client using the key and the
>>>>>> selectorhandler.
>>>>>>
>>>>>> but I don't know where to create that class (ClientTracker) and where
>>>>>> to put it to use it later.
>>>>>>
>>>>>> if I create the ClientTracker into the 2 filters.. a new reference
>>>>>> will be created each time the client send a request.. it's not what I want.
>>>>>>
>>>>>> I tought of putting the ClientTracker in the context and check if the
>>>>>> class exist in the context.. but like the context could be invalidate, I
>>>>>> could lose the info..
>>>>>>
>>>>>> Normally, I would have created the ClientTracker equivalent class,
>>>>>> after the socketserver.accept();
>>>>>>
>>>>>> Do you want to store somewhere complete map of clients
>>>>>> (ClientTracker), which are currently connected?
>>>>>> Also, can you pls. provide more details how you want to use
>>>>>> ClientTracker class? Some code snippets...
>>>>>>
>>>>>> Thank you.
>>>>>>
>>>>>> WBR,
>>>>>> Alexey.
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> ---------------------------------------------------------------------
>>>>>> To unsubscribe, e-mail: users-unsubscribe_at_grizzly.dev.java.net
>>>>>> For additional commands, e-mail: users-help_at_grizzly.dev.java.net
>>>>>>
>>>>>>
>>>>>>
>>>>>
>>>>>
>>>>
>>>>
>>>
>>>
>>> <demo3.zip>---------------------------------------------------------------------
>>> To unsubscribe, e-mail: users-unsubscribe_at_grizzly.dev.java.net
>>> For additional commands, e-mail: users-help_at_grizzly.dev.java.net
>>>
>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: users-unsubscribe_at_grizzly.dev.java.net
>> For additional commands, e-mail: users-help_at_grizzly.dev.java.net
>>
>>
>
>