users@grizzly.java.net

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

From: Survivant 00 <survivant00_at_gmail.com>
Date: Thu, 17 Jul 2008 08:23:00 -0400

thanks for your explanation.. it helped.

I did return true when the buffer is full, but I still got a exception
(buffer full) (I was able to fix that by clearing the buffer).


It could be done by returning true from hasNextMessage().And parser's
getNextMessage() method implementation should return some Error message, so
your next filter will get it and be able to parse.

here the changes that I made :

I check if the buffer size reach the max value, and if it's YES, I return
true. and in the function getNextMessage() I return a string MAX that I
will evaluate in the next filter.

 // Check if buffer is full
                if (processingBuffer.remaining() ==
processingBuffer.capacity()) {
                    // If full - reallocate

                    // but check if the max length is attein
                    if(processingBuffer.capacity() +
processingBuffer.remaining()<LIMITBB){
                        ByteBuffer newBB = ByteBufferFactory.allocateView(
                                processingBuffer.capacity() * 2,
                                processingBuffer.isDirect());
                        newBB.put(processingBuffer);
                        processingBuffer = newBB;
                        WorkerThread workerThread = (WorkerThread)
Thread.currentThread();
                        workerThread.setByteBuffer(processingBuffer);
                    } else {
                        System.out.println("BUFFER MAX ATTEIND.. LE CLIENT
ENVOYE DE LA JUNK OU LE BUFFER EST TROP PETIT!");

                        processingBuffer.clear();

                        maxBufferReached = true;

                        return maxBufferReached;
                    }
                }


public String getNextMessage() {
        //System.out.println("getNextMessage");
        if(maxBufferReached){
            return "MAX";
        }
        return query;
    }


in the next filter in the excute(...) I add that


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

        if(query.equals("MAX")){
            clientConnectionHandler.close(); // close the connection
because the client issending junk
            return false;
        }



now I think I have a more complete example that's actually works.


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

> Hi,
> On Jul 16, 2008, at 21:14 , Survivant 00 wrote:
>
> just one more question.
>
> suppose this case.
>
> a client go rampage.. it send invalid data for X reason..
>
> with the actual code, when the capacity is reach, it will create a new
> buffer (2x size), but I want to aloid a max size.. like 20 000. the default
> is 8192(somthing like that) I did a system,out of processingbuffer.capacity
>
> what is the clean way to exit the parsing loop and return a state or
> exception to the next filter ? The next filter should be able to detect
> this error and close the client connection.
>
> It could be done by returning true from hasNextMessage().
> And parser's getNextMessage() method implementation should return some
> Error message, so your next filter will get it and be able to parse.
>
>
> and just for my information.
>
> I tought the the buffer could be flush between the loop in the filter.
> That's why I put the remaining data in the buffer into the WorkerThread.
>
> With ParserProtocolFilter you don't need to care about ByteBuffer...
> Once isExpectingMoreData() returns true - filter will save the ByteBuffer
> and reuse it only with current connection next time.
>
>
> but I suppose it's only when we create a new buffer (like double size)
> right ?
>
> WorkerThread workerThread = (WorkerThread) Thread.currentThread();
> workerThread.setByteBuffer(processingBuffer);
>
> startBuffer() method is called first, where we associate current Thread's
> ByteBuffer with parser's processingBuffer...
> So we need this:
>
> WorkerThread workerThread = (WorkerThread) Thread.currentThread();
> workerThread.setByteBuffer(processingBuffer);
>
>
> only, when we create new ByteBuffer.
>
> Thanks.
>
> WBR,
> Alexey.
>
>
>
>
>
> 2008/7/16 Oleksiy Stashok <Oleksiy.Stashok_at_sun.com>:
>
>> Ok, once it works, I can describe the changes.
>> + First of all I don't use internal buffer in the parser to store
>> temporary data there.
>> + Fixed parser logic... I know we don't have good tutorial on that yet, so
>> your blog could help
>> hasMoreBytesToParse: should return true only if one message was
>> parsed successfully, but there is still some remaining data in the buffer.
>> releaseBuffer(): should compact the buffer, not clear... as possibly
>> there is some remaining. Buffer should become ready for next read operation
>> (unflipped).
>>
>>
>>
>> do you have a good link or documentation about the code behind the
>> ByteBufferFactory ?
>>
>> ByteBufferFactory is Factory class for creating ByteBuffers. It's actually
>> wrapper on top of ByteBuffer.allocate(...)/allocateDirect()...
>> But it also implements ByteBuffer views functionality. It means
>> ByteBufferFactory preallocates very big ByteBuffer(4M) and then, when
>> ByteBufferFactory.allocateView(...) is called - it basically doesn't
>> allocate new buffer, but just cuts the chunk of big preallocated buffer and
>> returns this chunk.
>>
>> Seems that's it.
>>
>> Thanks.
>>
>> WBR,
>> Alexey.
>>
>> I want to know what it's done under the hood, suppose that I want to do it
>> in a project that doesn't use grizzly.. could be usefull to understand that.
>>
>> and thanks again for your help.
>>
>> now I'm almost ready to blog all about this.
>>
>>
>> 2008/7/16 Oleksiy Stashok <Oleksiy.Stashok_at_sun.com>:
>>
>>> Pls. try attached version.
>>>
>>> WBR,
>>> Alexey.
>>>
>>>
>>>
>>> On Jul 16, 2008, at 15:45 , Survivant 00 wrote:
>>>
>>> I got a exception when I send the second request
>>>
>>> it's really simple to reproduce
>>>
>>> start the main class
>>>
>>> GrizzlyGateway
>>>
>>> it will listen on the port 5000
>>>
>>>
>>> open a telnet localhost 5000
>>>
>>> in the console.. send theses 2 requests.. One by one
>>>
>>> feed|aaa[eoq]
>>> feed|bbb[eoq]
>>>
>>>
>>> you will see that in the server console
>>>
>>>
>>> GrizzlyGateway started
>>> Simulate a disconnection from the 3th party
>>> Reconnecting...
>>> listening for incomming TCP Connections on port : 5000
>>> query = feed|aaa
>>> SENDING FEED TO CLIENT = [SYMBOL=[aaa] BID = 31.46111239671892| ASK =
>>> 41.85483961272104]
>>> SENDING FEED TO CLIENT = [SYMBOL=[aaa] BID = 19.410604221055426| ASK =
>>> 40.98782811588009]
>>> 2008-07-16 09:41:07 com.sun.grizzly.DefaultProtocolChain
>>> executeProtocolFilter
>>> GRAVE: ProtocolChain exception
>>> java.lang.IllegalStateException: ByteBuffer is full:
>>> java.nio.HeapByteBuffer[pos=0 lim=0 cap=8192]
>>> at com.sun.grizzly.filter.ReadFilter.execute(ReadFilter.java:120)
>>> at com.sun.grizzly.filter.ReadFilter.execute(ReadFilter.java:95)
>>> at
>>> com.sun.grizzly.filter.ParserProtocolFilter.execute(ParserProtocolFilter.java:108)
>>> at
>>> com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:137)
>>> at
>>> com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:104)
>>> at
>>> com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:90)
>>> at
>>> com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:67)
>>> at
>>> com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:56)
>>> at
>>> com.sun.grizzly.util.WorkerThreadImpl.run(WorkerThreadImpl.java:169)
>>> SENDING FEED TO CLIENT = [SYMBOL=[aaa] BID = 10.932414591862527| ASK =
>>> 25.136572649558214]
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>> 2008/7/16 Oleksiy Stashok <Oleksiy.Stashok_at_sun.com>:
>>>
>>>> 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.
>>>>
>>>>
>>>>
>>> <nio_quotestock_demo_v3.zip>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: users-unsubscribe_at_grizzly.dev.java.net
>>> For additional commands, e-mail: users-help_at_grizzly.dev.java.net
>>>
>>>
>>>
>>>
>>
>>
>
>