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
>
>