Steve Ulrich wrote:
Hi!
AFAIK, the messageSent is the only way to react when a message is finally
sent.
Yes, but because no alternate solution was discussed. And even if it was
the only solution, it's a pretty atrocious one : having to go through
the chain a second time just to get some stats sounds silly to me. So
let's try to find a better way. And the fact that this is closely linked
to a filter is even worse (what if you don't use a ProtocolCodecFilter ?).
filterWrite is already called *before* the message is passed to the
cable.
How can I implement timings, like request/response timeout filters?
Using filterWrite for this could be problematic for decoding will consume
some undefined/-able amount of the time(out).
If there's another way to do this, let me know.
So let's think a second time about the way the protocolCodecFilter
works, when a message is to b sent back to the client. It receives a
Message, encode it, and write it to the cient. If you look at the
current implementation :
public void flushWithoutFuture(int index) throws Exception {
Queue<Object> bufferQueue = getMessageQueue();
for (;;) {
Object encodedMessage = bufferQueue.poll();
if (encodedMessage == null) {
break;
}
// Flush only when the buffer has remaining.
if (!(encodedMessage instanceof IoBuffer) ||
((IoBuffer) encodedMessage).hasRemaining()) {
SocketAddress destination =
writeRequest.getDestination();
WriteRequest writeRequest = new EncodedWriteRequest(
encodedMessage, null, destination);
IoFilter nextFilter = session.getFilterOut(index+1);
nextFilter.filterWrite(index+1, session, writeRequest);
}
}
}
you can see that we loop on the message Queue, flushing every message
one by one. Three things :
- first, if we have more than one message one the queue, I don't see how
we can generate this MessageSent message.
- second, as the encoder will generate a full IoBuffer for each separate
message, I don't see how it's necessary to send it again.
- third, this is not because we have generated an empty message and
faked to send it that the message has been sent. It's just a damn hack
to pretend the message has been sent.
Now, it's all about semantic : when do we want to *know* that a message
has been sent ? When the client has sent an ack ? There is no way to
enforce this.
What about considering that the message is sent as soon as we have
written in the chjain, associated with a writeFuture marked as 'done' ?
The problem is that the codec just send the data without creating a future.
At some point, we will need to get a feedback from the low level layers
telling us that the message (being a IoBuffer at this point) has been
successfully sent : a WriteFutuer in a 'completed' state should do the
trick. A filter checking able to check this write future when it's set
to 'don' should do the trick.
This is not simple : if we consider that we send data on a non-blocking
IO, we have to assume that the message has been sent even if the socket
is full, and we may perfectly write in a socket which will be close
before the full message has been sent. Let's say that it's a best effort
approach.
Anyway, I think it's feasible with a WriteFuture.
As usual, I may be wrong. May be I'm totally off rail, just tell me then :)
--
--
cordialement, regards,
Emmanuel Lécharny
www.iktek.com
directory.apache.org