users@grizzly.java.net

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

From: Oleksiy Stashok <Oleksiy.Stashok_at_Sun.COM>
Date: Mon, 21 Jul 2008 10:34:50 +0200

Hi,


> quit.. I mean if the client close is connection.. like closing the
> telnet , or a tcp client. If the client send a "quit|xxx[eoq]"
>
> the server will close the client connection and everything will be
> fine.
>
> look like a disconnect from a client is not reconized by the server.
Not sure I understand how exactly server should recognize this? :) You
need some API to be called, when client closes the connection... or?
>
>
>
> 2008/7/18 Survivant 00 <survivant00_at_gmail.com>:
> I found a bug.. in QuoteQueryProtocolParser
>
> if the client connect to the server.. and quit. the
> QuoteQueryProtocolParser will enter in a loop.
can you pls. provide details on where the loop will occur?

Thanks.

WBR,
Alexey.
>
>
> isExpectingMoreData
> startBuffer
> capacity=8192
> hasMoreBytesToParse
> isExpectingMoreData
> releaseBuffer
> isExpectingMoreData
> startBuffer
> capacity=8192
> hasMoreBytesToParse
> isExpectingMoreData
> releaseBuffer
> isExpectingMoreData
> startBuffer
>
> I,ll try to figure out what we miss.
>
>
> 2008/7/17 John ROM <snake-john_at_gmx.de>:
>
> 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
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe_at_grizzly.dev.java.net
> For additional commands, e-mail: users-help_at_grizzly.dev.java.net
>
>
>