the trick is to try to write first with the socket configured in non
blocking mode, so if it's congestion controlled , the write will
fail instantaneously so we en-queue the message and set the OP_WRITE flag
on the selection key.


On Tue, Jan 8, 2013 at 3:24 AM, Chad Beaulac <[email protected]> wrote:

>
> On Jan 7, 2013, at 11:58 AM, Emmanuel Lécharny wrote:
>
> > Le 1/7/13 2:19 PM, Chad Beaulac a écrit :
> >> If you don't push the data onto a queue and wait for the selector to
> fire, you could be trying to write data to a socket that is congestion
> controlled, which you shouldn't do. The writer should wait for the selector
> to fire saying the socket is writable before trying to write.
> >
> > The thing is that in any case, we do try to write into the socket. If
> > the socket internal buffer gets full, we won't be able to write any ore
> > data into it, and we will have to wait for the socket to inform the
> > selector when it's ready to accept more data.
> >
> > What I'm proposing is not any different, except that I bypass the queue
> > *if* and only *if* the socket is ready to accept new data. In other
> > words, the algorithm is :
> >  o if there is a queue containing messages waiting for the socket to be
> > ready (OP_WRITE set ti true), then enqueue the new message.
> >  o else try to write the message into the socket
> >    - if we can't write the full message, set the SelectionKey to be
> > interested in OP_WRITE, and enqueue the remaining data.
> >    - Otherwise, the data have already been written anyway, we are done
> >
> > This is the way MINA 2 works since it's inception.
> >
> > Is there anything wrong with that ?
> >
>
> Potentially. You should not attempt to write to the socket unless the
> OP_WRITE selector key says the socket is writable. If the selector has
> fired and says the socket is writable before you try to write, it's not a
> problem. Otherwise, you should queue the data, let the Selector fire and
> then try to write. I don't see any way around queuing the data.
> You never want to try to write to a socket that is writable. If it isn't
> writable, it's closed or congestion controlled. This "edge-triggered" I/O
> approach works well. You don't know what "edge" you're on if you haven't
> registered for an event before you try to write.
>
> Pseudocode Algorithm.
>
> // Client provides data to this class to output onto the socket.
> public synchronized void put(Data data) {
>   if (queue.isEmpty) {
>         register(key, OP_WRITE);  // output queue is empty. We need to
> register for the write event so the OS can tell us when it's ok to write.
>         enqueue(data);  // Put the data onto the ConcurrentLinkedQueue
>   }
>   else {
>         enqueue(data); // Just put the data onto the queue. We're already
> registered for the write event.
>   }
> }
>
> public void runEventLoop() {
>         // handle events on Selector
> }
>
>
> // OP_WRITE fired for key
> public synchronized void writeData(key) {
>         while (!queue.isEmpty()) {
>                 Data data = queue.dequeue();
>                 writeForKey(key,data);
>                 if (data.remaining() > 0) {
>                   enqueue(data);
>                   break; // socket is congestion controlled. We're still
> registered for the write event. When the TCP queue drains, the write event
> will fire again
>                 }
>         }
>         if (queue.isEmpty()) {
>           unregister(key, OP_WRITE);  // We don't have data to write to
> this socket anymore. Unregister for the write event.
>         }
> }
>
>
> >
> > --
> > Regards,
> > Cordialement,
> > Emmanuel Lécharny
> > www.iktek.com
> >
>
> Chad Beaulac
> Objective Solutions, Inc.
> www.objectivesolutions.com
> [email protected]
>
>
>
>
>
>
>

Reply via email to