[Q] Adding delays to protocol filter

classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

[Q] Adding delays to protocol filter

CigarMan

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?

 

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

 

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

 

Reply | Threaded
Open this post in threaded view
|

Re: [Q] Adding delays to protocol filter

Jeanfrancois Arcand-2
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: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

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

CigarMan
I have tried implementing your solution but I run into some problems,
it's just that I don't know where to save and reattach my keys! ... The
truth of the matter is I understand very little about the
registration/deregistration of keys and their interest! :.)

I have tried implementing an EchoFilter with a delayed response.
Unfortunately, I have screwed up somewhere with the key registration /
deregistration so when I invoke

SocketChannel channel = (SocketChannel)k.channel();

It blocks right there and my protocol filter can't handle any more
packets.

Here's my filter code, let me know what you think. I'm pretty sure it
has to do with the key registration which is screwed up.

Thanks,

Simon

P.S.: Is there a way to send properly formatted source code and the
likes to the mailing list? It must be very hard for you to read our code
snippets without pasting them into an editor.

**********

public class JitterEchoFilter implements ProtocolFilter {

        private ScheduledExecutorService executor =
Executors.newSingleThreadScheduledExecutor();
        private CountDownLatch latch;
       
        public JitterEchoFilter(CountDownLatch latch) {
                this.latch = latch;
        }
       
        private static int counter = 0;
        public boolean execute(Context ctx) throws IOException {
                final WorkerThread workerThread =
((WorkerThread)Thread.currentThread());
        ByteBuffer buffer = workerThread.getByteBuffer();
        buffer.flip();

        System.err.println("executing filter: " + counter++);
        System.err.println("buffer has remaining:
"+buffer.hasRemaining() + " remainingSize: "+ buffer.remaining());
        /*
                SelectionKey k = ctx.getSelectionKey();
                InetAddress localAddress =
((SocketChannel)k.channel()).socket().getLocalAddress();
                int localPort =
((SocketChannel)k.channel()).socket().getLocalPort();
                byte[] buf = new byte[buffer.remaining()];
                //System.err.println("remaining: "+buffer.remaining());
                buffer.get(buf);
                System.err.println("processing response --> ctx
instance: " + ctx + " Buffer content: " + new String(buf) + " Received
at: " +  localAddress.getHostAddress() +":"+ localPort);
        System.err.println("buffer.hasRemaining:
"+buffer.hasRemaining());
        */
       
        if (buffer.hasRemaining()) {
       
        /*
                         * Since response processing is performed
asynchronously, we need to
                         * save Grizzly's buffer into a new buffer for
response processing
                         * so we can release the buffer for message
reception.
                         */
        ByteBuffer duplicate = buffer.duplicate();
        byte[] bufferAsBytes = new byte[duplicate.remaining()];
        duplicate.get(bufferAsBytes);
    ByteBuffer copyBuffer = ByteBuffer.wrap(bufferAsBytes);
   
 
ctx.setKeyRegistrationState(Context.KeyRegistrationState.NONE);
    System.err.println("copyBuffer remaining: " +
copyBuffer.remaining());
    executor.schedule(new BusinessLogicResponseHandler(ctx,
copyBuffer), 3, TimeUnit.SECONDS);
        }
       
        buffer.clear();
        return false;
        }

        private class BusinessLogicResponseHandler implements
Callable<Void>
        {
                private Context ctx;
                private ByteBuffer buffer;
               
                public BusinessLogicResponseHandler(Context ctx,
ByteBuffer buffer) {
                        this.ctx = ctx;
                        this.buffer = buffer;
                }
               
                @Override
                public Void call() throws Exception{
                        System.err.println("calling!");
                        ByteBuffer buffer = processResponse(ctx,
this.buffer);
                        /*
                         * Send the response back to the requester
                         */
                        SelectionKey key = ctx.getSelectionKey();
                SelectorHandler sl = ctx.getSelectorHandler();
                sl.getSelectionKeyHandler().register(key, 15000L);
//Hasn't this method been deprecated?
                       
                        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();
                            this.buffer.get(data);
                            this.buffer.position(position);
                           
                            Controller.logger().log(Level.WARNING,
"Exception. Echo \"" + new String(data) + "\"");
                            throw ex;
                        }
                        System.err.println("has returned!");
                        return null;
                }
               
                protected ByteBuffer processResponse(Context ctx,
ByteBuffer buffer)
                {
                        System.err.println("processing!");
                        /*
                         * This implements an Echo operation but with
delay!
                         */
                       
                        SelectionKey k = ctx.getSelectionKey();
                        System.err.println("obtaining selectionKey");
                        SocketChannel channel =
(SocketChannel)k.channel();
                        System.err.println("obtaining channel");
                        InetAddress localAddress =
channel.socket().getLocalAddress();
                        System.err.println("obtaining localAddress");
                        int localPort =
((SocketChannel)k.channel()).socket().getLocalPort();
                        System.err.println("obtaining local port");
                        byte[] buf = new byte[buffer.remaining()];
                        System.err.println("remaining:
"+buffer.remaining());
                        buffer.get(buf);
                        System.err.println("processing response --> ctx
instance: " + ctx + " Buffer content: " + new String(buf) + " Received
at: " +  localAddress.getHostAddress() +":"+ localPort);

                        System.err.println("latch.countDown():
"+latch.getCount());
                        System.err.println("Buffer hasRemaining:
"+buffer.hasRemaining());
                        latch.countDown();
                       
                        return buffer;
                }
        }
       

        public boolean postExecute(Context ctx) throws IOException {
                return true;
        }

}

-----Original Message-----
From: [hidden email] [mailto:[hidden email]]
Sent: March-07-08 2:30 PM
To: [hidden email]
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: [hidden email]
For additional commands, e-mail: [hidden email]


---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

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

CigarMan
Sorry about that, seems I haven't been precise enough as to where in my
code the problem lies. It is when I invoke

System.err.println("obtaining channel");
InetAddress localAddress = channel.socket().getLocalAddress();

It is in the BusinessLogicResponseHandler.processResponse() method.

Thanks,



Simon

-----Original Message-----
From: Simon Trudeau [mailto:[hidden email]]
Sent: March-11-08 10:49 AM
To: [hidden email]
Subject: RE: Re: [Q] Adding delays to protocol filter

I have tried implementing your solution but I run into some problems,
it's just that I don't know where to save and reattach my keys! ... The
truth of the matter is I understand very little about the
registration/deregistration of keys and their interest! :.)

I have tried implementing an EchoFilter with a delayed response.
Unfortunately, I have screwed up somewhere with the key registration /
deregistration so when I invoke

SocketChannel channel = (SocketChannel)k.channel();

It blocks right there and my protocol filter can't handle any more
packets.

Here's my filter code, let me know what you think. I'm pretty sure it
has to do with the key registration which is screwed up.

Thanks,

Simon

P.S.: Is there a way to send properly formatted source code and the
likes to the mailing list? It must be very hard for you to read our code
snippets without pasting them into an editor.

**********

public class JitterEchoFilter implements ProtocolFilter {

        private ScheduledExecutorService executor =
Executors.newSingleThreadScheduledExecutor();
        private CountDownLatch latch;
       
        public JitterEchoFilter(CountDownLatch latch) {
                this.latch = latch;
        }
       
        private static int counter = 0;
        public boolean execute(Context ctx) throws IOException {
                final WorkerThread workerThread =
((WorkerThread)Thread.currentThread());
        ByteBuffer buffer = workerThread.getByteBuffer();
        buffer.flip();

        System.err.println("executing filter: " + counter++);
        System.err.println("buffer has remaining:
"+buffer.hasRemaining() + " remainingSize: "+ buffer.remaining());
        /*
                SelectionKey k = ctx.getSelectionKey();
                InetAddress localAddress =
((SocketChannel)k.channel()).socket().getLocalAddress();
                int localPort =
((SocketChannel)k.channel()).socket().getLocalPort();
                byte[] buf = new byte[buffer.remaining()];
                //System.err.println("remaining: "+buffer.remaining());
                buffer.get(buf);
                System.err.println("processing response --> ctx
instance: " + ctx + " Buffer content: " + new String(buf) + " Received
at: " +  localAddress.getHostAddress() +":"+ localPort);
        System.err.println("buffer.hasRemaining:
"+buffer.hasRemaining());
        */
       
        if (buffer.hasRemaining()) {
       
        /*
                         * Since response processing is performed
asynchronously, we need to
                         * save Grizzly's buffer into a new buffer for
response processing
                         * so we can release the buffer for message
reception.
                         */
        ByteBuffer duplicate = buffer.duplicate();
        byte[] bufferAsBytes = new byte[duplicate.remaining()];
        duplicate.get(bufferAsBytes);
    ByteBuffer copyBuffer = ByteBuffer.wrap(bufferAsBytes);
   
 
ctx.setKeyRegistrationState(Context.KeyRegistrationState.NONE);
    System.err.println("copyBuffer remaining: " +
copyBuffer.remaining());
    executor.schedule(new BusinessLogicResponseHandler(ctx,
copyBuffer), 3, TimeUnit.SECONDS);
        }
       
        buffer.clear();
        return false;
        }

        private class BusinessLogicResponseHandler implements
Callable<Void>
        {
                private Context ctx;
                private ByteBuffer buffer;
               
                public BusinessLogicResponseHandler(Context ctx,
ByteBuffer buffer) {
                        this.ctx = ctx;
                        this.buffer = buffer;
                }
               
                @Override
                public Void call() throws Exception{
                        System.err.println("calling!");
                        ByteBuffer buffer = processResponse(ctx,
this.buffer);
                        /*
                         * Send the response back to the requester
                         */
                        SelectionKey key = ctx.getSelectionKey();
                SelectorHandler sl = ctx.getSelectorHandler();
                sl.getSelectionKeyHandler().register(key, 15000L);
//Hasn't this method been deprecated?
                       
                        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();
                            this.buffer.get(data);
                            this.buffer.position(position);
                           
                            Controller.logger().log(Level.WARNING,
"Exception. Echo \"" + new String(data) + "\"");
                            throw ex;
                        }
                        System.err.println("has returned!");
                        return null;
                }
               
                protected ByteBuffer processResponse(Context ctx,
ByteBuffer buffer)
                {
                        System.err.println("processing!");
                        /*
                         * This implements an Echo operation but with
delay!
                         */
                       
                        SelectionKey k = ctx.getSelectionKey();
                        System.err.println("obtaining selectionKey");
                        SocketChannel channel =
(SocketChannel)k.channel();
                        System.err.println("obtaining channel");
                        InetAddress localAddress =
channel.socket().getLocalAddress();
                        System.err.println("obtaining localAddress");
                        int localPort =
((SocketChannel)k.channel()).socket().getLocalPort();
                        System.err.println("obtaining local port");
                        byte[] buf = new byte[buffer.remaining()];
                        System.err.println("remaining:
"+buffer.remaining());
                        buffer.get(buf);
                        System.err.println("processing response --> ctx
instance: " + ctx + " Buffer content: " + new String(buf) + " Received
at: " +  localAddress.getHostAddress() +":"+ localPort);

                        System.err.println("latch.countDown():
"+latch.getCount());
                        System.err.println("Buffer hasRemaining:
"+buffer.hasRemaining());
                        latch.countDown();
                       
                        return buffer;
                }
        }
       

        public boolean postExecute(Context ctx) throws IOException {
                return true;
        }

}

-----Original Message-----
From: [hidden email] [mailto:[hidden email]]
Sent: March-07-08 2:30 PM
To: [hidden email]
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: [hidden email]
For additional commands, e-mail: [hidden email]


---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]


---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

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

CigarMan
In reply to this post by Jeanfrancois Arcand-2
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.

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

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

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?).

Thanks,


Simon

-----Original Message-----
From: [hidden email] [mailto:[hidden email]]
Sent: March-07-08 2:30 PM
To: [hidden email]
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: [hidden email]
For additional commands, e-mail: [hidden email]


---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: [Q] Adding delays to protocol filter

Jeanfrancois Arcand-2


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-fro-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: [hidden email] [mailto:[hidden email]]
> Sent: March-07-08 2:30 PM
> To: [hidden email]
> 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: [hidden email]
> For additional commands, e-mail: [hidden email]
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

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

CigarMan
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: [hidden email] [mailto:[hidden email]]
Sent: March-12-08 1:42 PM
To: [hidden email]
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: [hidden email] [mailto:[hidden email]]

> Sent: March-07-08 2:30 PM
> To: [hidden email]
> 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: [hidden email]
> For additional commands, e-mail: [hidden email]
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]


---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: [Q] Adding delays to protocol filter

Jeanfrancois Arcand-2


Simon Trudeau wrote:
> 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!

No, that's the idea. If you get a ThreadAttachment from a Thread, the
ByteBuffer will be detached from its thread (a new one will be created).
So you should not have any concurrency issues or any invalidation.


>
> 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!!! :.)

The way Grizzly works is the following (just to recap):

1. Client open a connection to Server
2. Server accept the connection
3. Server disable OP_READ operation (all upcoming packet are buffered by
the OS)
3. Server spawn a new Thread which execute the ProtocolChain
4. The first ProtocolFilter (read) reads the available bytes on the channel
5. The next Filter is invoked. The 'next" filter is usually parsing the
bytes, and decide:
    5.1 If a response need to be send *and/or*
    5.2 If it is time to get more bytes (enable OP_READ)
        ctx.setRegistrationState(KeyRegistrationState.REGISTER); *or*
    5.3 If the connection needs to be closed
         ctx.setRegistrationState(KeyRegistrationState.CANCEL);  *or*
    5.4 If the connection needs to suspended
         ctx.setRegistrationState(KeyRegistrationState.NONE);

If you set the KeyRegistrationState.NONE, you need to cache/store the
SelectionKey and then, let say 10 minutes after, get back that
SelectionKey and do:

    5.5 Send the response ( key.channel().write() ) and
    5.6 Either close the connection or re-enable the read operations.

During the suspended state, the OS will buffer some packets but
eventually will stop accepting them. Is that the problem you are
explaining? If you read all the packets without suspending, you might
run in a out of memory error if you need to buffer in memory all of them.

On the different note, I'm working right now on a
SuspendableProtocolFilter (should have it next week) that will make the
suspend() operation easier to handle.

A+

-- Jeanfrancois



>
> Simon
>
> -----Original Message-----
> From: [hidden email] [mailto:[hidden email]]
> Sent: March-12-08 1:42 PM
> To: [hidden email]
> 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: [hidden email] [mailto:[hidden email]]
>
>> Sent: March-07-08 2:30 PM
>> To: [hidden email]
>> 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: [hidden email]
>> For additional commands, e-mail: [hidden email]
>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: [hidden email]
>> For additional commands, e-mail: [hidden email]
>>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]