users@grizzly.java.net

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

From: Oleksiy Stashok <Oleksiy.Stashok_at_Sun.COM>
Date: Wed, 16 Jul 2008 15:24:01 +0200

Hi,

I made some changes to the parser code - please try it.
The idea is to not use internal bytebuffer in the parser, but reuse
one from WorkerThread...
Let me know if it works, if not - please provide some unit test, using
which I can test the parser myself.

Thank you.

WBR,
Alexey.


On Jul 15, 2008, at 18:31 , Survivant 00 wrote:

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