users@grizzly.java.net

RE: Re: [Q] Adding delays to protocol filter

From: Simon Trudeau <strudeau_at_bluetreewireless.com>
Date: Wed, 12 Mar 2008 17:26:28 -0400

Ok... Euhm...

Saving the bytes from the buffer shouldn't be a big problem. So that
should be ok. I am more worried about saving the connection information
for later. What do I need to save? ThreadAttachment is nice but it is
very much NOT thread safe! It contains things such as ByteBuffer and the
likes which will get invalidated the next time a packet is processed by
the ProtocolChain!

Since I am connected to a server, there must be a channel (or something)
establish and maintained between my client and server. I need to get a
hold of that channel at a later point in time and send back my response.

How do you typically do delayed processing like I intend on doing? How
does Grizzly deal with burst? Without a delayed processing mechanism you
cannot deal with request bursts without dropping packets. I am pretty
sure (hoping :.)) that Grizzly has one! You might have the fastest NIO
framework around but the applications built on top of it might just not
keep up with the flow of requests!!! :.)

Simon

-----Original Message-----
From: Jeanfrancois.Arcand_at_Sun.COM [mailto:Jeanfrancois.Arcand_at_Sun.COM]
Sent: March-12-08 1:42 PM
To: users_at_grizzly.dev.java.net
Subject: Re: [Q] Adding delays to protocol filter



Simon Trudeau wrote:
> Now I think that I understand what you mean! :.)
>
> **********
> ctx.setKeyRegistrationState(Context.KeyRegistrationState.NONE);
>
> // Store those values somewhere:
> SelectionKey key = ctx.getSelectionKey();
> Selectorhandler sl = ctx.getSelectorHandler();
> **********
>
>
> In your explanation, the above make sense, but
>
>
> **********
> Once you have flushed the response,
> just do:
>
> sl.getSelectionKeyHandler().register(key);
>
> So you can get other requests that are coming.
> **********
>
> Cannot work since I register my key only after I have processed
(during
> a long time) the received packet, I won't be able to receive and queue
> packets while I am processing! I need to keep the key (or a new key
> maybe?) registered at all time so I can get all packets while my
> application is processing.

I see. Then you need some caching/buffering mechanism and store the read

bytes. My solution doesn't stand :-)


>
> It means that I might be receiving 5 requests but during that time I
> might only be able to process 2!

Right

>
> So How should I set (maybe save) my selectionKey so I can reply to a
> request even after many other requests have arrived and have been
queued
> (at the application level)?

You can't save the SelectionKey, but instead you might want to use the
ThreadAttachment and attach your ByteBuffer to it. Grizzly will re-use
that ByteBuffer every time bytes are read. Once you have all your bytes,

you just need to send the response. Take a look at the proposal I did
(now implemented):

http://www.nabble.com/-Proposal---vote--Adding-a-new-ThreadAttachment-fr
o-partial-read-state-implementation-td11254764.html#a11254764


>
> Also, is there one new Context object per packet received or is that
> object shared among many packets (I know it can be shared when
handling
> truncated messages but are there other cases?).

One per packet received.

A+...pogne dans la neige a Montreal :-)

-- jeanfrancois


>
> Thanks,
>
>
> Simon
>
> -----Original Message-----
> From: Jeanfrancois.Arcand_at_Sun.COM [mailto:Jeanfrancois.Arcand_at_Sun.COM]

> Sent: March-07-08 2:30 PM
> To: users_at_grizzly.dev.java.net
> Subject: Re: [Q] Adding delays to protocol filter
>
> Hi Simon,
>
> Simon Trudeau wrote:
>> I want to test the performance of my application. To do so, I intend
> on
>> building an Echo server with delay. Basically, once my request
reaches
>
>> my server, I want to delay (simulate response processing) the sending
> of
>> a response. My first guess is to wrap the content of the execute
> method
>> of the EchoFilter inside a callable and have it executed by a
> scheduled
>> executor. Is that thread safe?
>
> Yes you can, but make sure you call:
>
>
> ctx.setKeyRegistrationState(
> Context.KeyRegistrationState.NONE);
>
> // Store those values somewhere:
> SelectionKey key = ctx.getSelectionKey();
> Selectorhandler sl = ctx.getSelectorHandler();
>
>
> inside you Filter, because if not, the key will be registered back and

> it will gives unexpected result. Once you have flushed the response,
> just do:
>
>
> sl.getSelectionKeyHandler().register(key);
>
> So you can get other requests that are coming.
>
>
>
>>
>>
>> What happens to the context object if another packet arrives from the

>> same connection while my server is waiting to send back the response?
>>
>>
>>
>> The issue I want to simulate is a fast producer (client), slow
> consumer
>> (server).
>
> Right. Try the above :-)
>
> Thanks
>
> -- Jeanfrancois
>
>
>>
>>
>> Can I just wrap
>>
>>
>>
>> *public* *boolean* execute(Context ctx) *throws* IOException {
>>
>> *final* WorkerThread workerThread =
>> ((WorkerThread)Thread./currentThread/());
>>
>> ByteBuffer buffer = workerThread.getByteBuffer();
>>
>> buffer.flip();
>>
>> *if* (buffer.hasRemaining()) {
>>
>> // Depending on protocol perform echo
>>
>> SelectableChannel channel =
> ctx.getSelectionKey().channel();
>> *try* {
>>
>> *if* (ctx.getProtocol() == Controller.Protocol./TCP/)
> {
>> // TCP case
>>
>> OutputWriter./flushChannel/(channel, buffer);
>>
>> } *else* *if* (ctx.getProtocol() ==
>> Controller.Protocol./UDP/) { // UDP case
>>
>> DatagramChannel datagramChannel =
> (DatagramChannel)
>> channel;
>>
>> SocketAddress address = (SocketAddress)
>>
>>
>> ctx.getAttribute(ReadFilter./UDP_SOCKETADDRESS/);
>>
>> OutputWriter./flushChannel/(datagramChannel,
>> address, buffer);
>>
>> }
>>
>> } *catch* (IOException ex) {
>>
>> // Store incoming data in byte[]
>>
>> *byte*[] data = *new* *byte*[buffer.remaining()];
>>
>> *int* position = buffer.position();
>>
>> buffer.get(data);
>>
>> buffer.position(position);
>>
>>
>>
>> Controller./logger/().log(Level./WARNING/,
>>
>> "Exception. Echo \"" + *new* String(data) +
> "\"");
>> *throw* ex;
>>
>> }
>>
>> }
>>
>>
>>
>> buffer.clear();
>>
>> *return* *false*;
>>
>> }
>>
>>
>>
>> Inside a callable and execute it from a Schedule Executor or are
there
>
>> states that will be messed up (the context maybe...?). What do you
> think?
>>
>>
>> Thanks,
>>
>>
>>
>> Simon
>>
>>
>>
>
> ---------------------------------------------------------------------
> 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
>

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe_at_grizzly.dev.java.net
For additional commands, e-mail: users-help_at_grizzly.dev.java.net