users@grizzly.java.net

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

From: John ROM <snake-john_at_gmx.de>
Date: Thu, 17 Jul 2008 16:39:04 +0200

You take a look at source of
com.sun.grizzly.util.Utils.findBytes(ByteBuffer byteBuffer, byte[] b)

byte[] b would be [eoq].getBytes()
>
>
>
> 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(DefaultProtoc
> olChain.java:137)
> at
> com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:1
> 04)
> at
> com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:9
> 0)
> at
> com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask
> .java:67)
> at
> com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.jav
> a: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
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

-- 
Psssst! Schon vom neuen GMX MultiMessenger gehört?
Der kann`s mit allen: http://www.gmx.net/de/go/multimessenger