"Grizzly 1.7.0 presents"... Part I: Asynchronous write queues
By oleksiys on Jan 16, 2008
Finanlly Grizzly 1.7.0 is released and we have implemented feature, which was asked long time ago: Asyncronous write queues.
Before it was possible to use async. NIO nature in Grizzly, but developer needed to implement and control such queue himself. Or as alternative write operation could be done in blocking manner: OutputWriter.flushChannel(...).
With newly implemented Async. write queue it's possible to register ByteBuffer for writing and get notification via a callback listener, when ByteBuffer will be written. Also it's possible together with ByteBuffer register some custom ByteBuffer Processor, which will be called before writing ByteBuffer, and will be able to process/change/encrypt ByteBuffer data before writing it on a wire. Grizzly itself uses ByteBuffer Processor for SSL Async. write queue implementation.
Async. write queue API is represented by the interface com.sun.grizzly.async.AsyncQueueWritable.
Grizzly client side connector handlers: TCPConnectorHandler, UDPConnectorHandler, SSLConnectorHandler, implement AsyncQueueWritable interface. However it's possible to use Async. write queue functionality inside ProtocolFilter - Context.getAsyncQueueWritable().
What are the features Async. write queue API proposes?
1) public void writeToAsyncQueue(ByteBuffer buffer) throws IOException;
Just register buffer on a write queue. Completion notification is not needed.
2) public void writeToAsyncQueue(ByteBuffer buffer, AsyncWriteCallbackHandler callbackHandler) throws IOException;
Registers buffer on a write queue, and provides callback handler, which will be notified on buffer write completion, or if any error will happen during buffer write operation.
3) public void writeToAsyncQueue(ByteBuffer buffer, AsyncWriteCallbackHandler callbackHandler, AsyncQueueDataProcessor writePreProcessor) throws IOException;
Does the same as (2), but also registers buffer associated writePreProcessor, which will be called, for buffer, when it comes its turn to be written. WritePreProcessor can change buffer content, can substitute buffer with different one. I found this feature useful, when implemented SSL async. write queue support. So I'm registering buffer with raw data, and SSLWritePreProcessor, which is called before buffer is going to be written and encrypts buffer's content according to SSL requirements.
4) public void writeToAsyncQueue(ByteBuffer buffer, AsyncWriteCallbackHandler callbackHandler, AsyncQueueDataProcessor writePreProcessor, boolean isCloneByteBuffer) throws IOException;
Method extends functionality of (3), by adding possibility to clone source buffer before adding it to a queue, so actually buffer clone will be added to a queue. "Cloning" could be useful for situations, when we don't want to care much about memory management. So it's possible to call this method with clone set to "true", and continue to work with the passed buffer (clear it, modify...) on next step.
But for better memory management, I would suggest to not use cloning, and release allocated buffer using AsyncWriteCallbackHandler.
There are other operations, provided with API, which are similar to (1)-(4), but has one more parameter: SocketAddress dstAddress. These operations are not supported for TCP, SSL transports, as they always implemented using connected channels, but with UDP transport, where channel could be not connected, it's possible to set destination address, where buffer will be sent.
\*If queue is empty, all write operations first try to write buffer directly to the destination channel on the same thread.
Looking forward to hear feedback, so we will be able to fix/improve our current implementation :)
Next time I'll try to describe Grizzly Asynchronous read queue feature...