Hi,
I would like to introduce a set of new APIs for handling the case when
an ReadFilter is used and the temporary Selector trick for doing extra
reads cannot be used. The use case is the following:
+ Inside a "ReadFilter", the socketChannel.read(...) reads some bytes
and then starts returning 0 (no more bytes available). In that case, the
SelectionKey must be registered back to its SelectorHandler, and the
state of the transaction needs to be persisted. By state here I means
the byteBuffer that contains the partial read (bytes) and maybe some
application specific data.
To support that use case, I would like to add two new method to the
WorkerThread interface:
> 49 /**
> 50 * Detach the current set of attributes (state) associated with this instance.
> 51 * Invoking detach(true) will re-create all the ByteBuffer associated with
> 52 * this thread, hence this method must be called only when required. If
> 53 * you only need to invoke the object, call detach(false) instead but make
> 54 * sure you aren't caching or re-using the ThreadAttachment with another
> 55 * thread.
> 56 * @param true to copy the attributes into the ThreadAttachment and re-create
> 57 * them
> 58 * @return a new ThreadAttachment
> 59 */
> 60 public ThreadAttachment detach(boolean copyState);
> 61
> 62
> 63 /**
> 64 * Attach the ThreadAttachment to this instance. This will configure this
> 65 * Thread attributes like ByteBuffer, SSLEngine, etc.
> 66 * @param ThreadAttachment the attachment.
> 67 */
> 68 public void attach(ThreadAttachment threadAttachment);
Hence when an application needs more bytes and need to register back to
the SelectorHandler:
public class MyReadFilter{
public boolean execute(Context ctx){
....
WorkerThread wt = ((WorkerThread)Thread.currentThread());
ByteBuffer bb = wt.getByteBuffer();
int length = socketChannel.read(bb);
...
if (length == 0){
ThreadAttachment ta = wt.detach(true);
ctx.getSelectionKey().attach(ta);
....
ctx.setKeyRegistrationState(
Context.KeyRegistrationState.REGISTER);
...
}
}
Internally, the SelectorHandler will do, once bytes are available:
WorkerThread wt = ((WorkerThread)Thread.currentThread());
wt.attach((ThreadAttachment)selectionKey.attachment());
and then invoke the Filter Again. Calling wt.attach() will properly
configure the Thread attribute so when MyReadFilter.execute is called,
the previously read bytes will be already available inside the ByteBuffer.
I will apply the solution to the SSLReadFilter as well, which currentlt
use the SSLSession to store the state of the transaction. I'm attaching
the diff of the changes.
Let me know what you think.
Thanks
-- Jeanfrancois