users@grizzly.java.net

(no subject)

From: <eric.peiffer_at_alcatel-lucent.fr>
Date: Tue, 7 Feb 2012 14:10:59 +0000 (GMT)

Hi I'm new in the grizzly framework, I use the grizzly framework
release 1.9.45 in order to develope an IMAP server.
In order to wite data to IMAP clients i use the following sample code:

getSelectorHandler().getAsyncQueueWriter().write(key, b,
callbackHandler, response.getDataProcessor());

the write method call the method doWrite in the class
TCPAsyncQueueWriter. here is the implementation if the doWrite method:

    protected OperationResult doWrite(WritableByteChannel channel,
            SocketAddress dstAddress, ByteBuffer byteBuffer,
            OperationResult dstResult) throws IOException {
        int written = 0;
        int lastWriteBytes = 0;
            try{
            do {
                lastWriteBytes = channel.write(byteBuffer);
                if (lastWriteBytes > 0) {
                    written += lastWriteBytes;
                }

            } while(lastWriteBytes > 0 && byteBuffer.hasRemaining());
        } catch (IOException ex){
            lastWriteBytes = -1;
            throw ex;
        } finally {
             if (lastWriteBytes == -1){
                SelectionKeyHandler skh =
selectorHandler.getSelectionKeyHandler();
                if (skh instanceof BaseSelectionKeyHandler){
      
                    ((BaseSelectionKeyHandler)skh).notifyRemotlyClose(
                           
selectorHandler.keyFor((SelectableChannel)channel));
                }
            }
        }
        dstResult.bytesProcessed = written;
        return dstResult;
    }

Under a heavy load,call to channel.write(byteBuffer) might be return
0.
Therefor data that are not sent are lost. in order to fix this I have
wrote the following code in the doWrite method:

...
do {
                int remaining = byteBuffer.remaining();
                lastWriteBytes = channel.write(byteBuffer);
                if (lastWriteBytes == 0 && remaining != 0) {
                    try {
                        counter++;
                        logger.error("Can not send data wait 100ms");
                        Thread.sleep(100);
                    } catch (InterruptedException ex) {
                        
                    }
                }
                if (lastWriteBytes > 0) {
                    written += lastWriteBytes;
                }
                
            } while (lastWriteBytes >= 0 && counter < 100 &&
byteBuffer.hasRemaining());
.....

With this fix we try to resent data that was not sent..

Other solution more "clean" would be to register an OP_WRITE interest
opt to a temporary Selector and wait for the temporary Selector to tell
you when the SocketChannel is ready for a write operation. but I d'ont
know how to implement this solution in the grizzly framework

Are you any ohter Idee?