do you have an implementation in mind :)
so basicaly I should convert the "[oeq]" into a byte array, and look for
theses values in the BB ? (keep the index, so I don't start fromt he
begining each time).
2008/7/17 Oleksiy Stashok <Oleksiy.Stashok_at_sun.com>:
> Great!!!
>
> One more think it could make sense to improve in your code (IMHO) - it's
> place, where you try to decode ByteBuffer to CharBuffer, then check the
> string for [eoq]... This operation could be expensive and not optimal.
> Just, as idea, you can try to find [eoq] in the ByteBuffer directly and
> make ByteBuffer -> CharBuffer conversion only if [eoq] was found.
> If you didn't find [eoq] in the current ByteBuffer - you can save current
> position and when next portion of data will come - start to search for [eoq]
> not from beginning but from last position.
>
> But these are just possible ways of optimization :)
>
> Thanks.
>
> WBR,
> Alexey.
>
> On Jul 17, 2008, at 14:23 , Survivant 00 wrote:
>
> 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
>>>>
>>>>
>>>>
>>>>
>>>
>>>
>>
>>
>
>