On 02/20/2008 01:43 PM, David M. Lloyd wrote:
In the protocol I'm working on, the client and server each need to send
a message immediately upon connection. If I send the message in my
IoHandler.sessionOpened() method, is it safe to say that the message
will be sent before the first IoHandler.messageReceived() occurs? If
so, that fact should be in the javadoc for IoHandler.
An interesting IRC conversation ensued from this question. Here's the
transcript from #mina on irc.freenode.net (slightly edited to remove
unrelated comments):
Cast of characters:
dmlloyd = Me (David M. Lloyd)
tazle = Tuure Laurinolli
mike_heath = Mike Heath
<dmlloyd> hm, even with the IoSessionInitializer there's no way to
guarantee that I can write a message before a message is received
<dmlloyd> it's almost as if there should be a lifecycle for an ioSession
<dmlloyd> created, connected, started
<dmlloyd> created = the session is created but not yet connected (e.g. in
IoSessionInitializer)
<dmlloyd> connected = the session is connected but not added to the
selector/whatever (so the IoHandler is guaranteed not to be invoked yet,
but you can still send)
<mike_heath> IIRC, you can use an the executor service filter and it will
ensure the correct order of events.
<dmlloyd> started = IoHandler receives messages
<mike_heath> The problem is that the connector thread and IoProcessor
threads are different.
<dmlloyd> once the connection is up, sure
<mike_heath> Even before the connection is up, the executor filter will
order the events.
<dmlloyd> yeah but the "starting" event always has to be a read for that to
work
<dmlloyd> e.g. reads will occur in order
<mike_heath> Aaahhh.
<dmlloyd> but you can't insert a write to happen *before* the reads start
<dmlloyd> hm, is sessionOpened() guaranteed to be called before any
messages are received?
<dmlloyd> the docs are unclear
<mike_heath> IMO sessionCreated and sessionOpened should be called before
any message have been received.
<mike_heath> Perhaps we should discuss this on the ML.
<dmlloyd> maybe. I'll look over the source first.
<tazle> dmlloyd: how does "write before any reads" make sense?
<dmlloyd> how does it not?
<dmlloyd> usually a protocol handler sends data in response to receiving data
<tazle> dmlloyd: can't you send in sessionOpened()?
<dmlloyd> in this protocol, the server and client both send an initial
message upon connect
<dmlloyd> on the client side I need to send the initial message before the
server's initial message is received
<dmlloyd> to prevent a different message from being sent before the initial
message
<dmlloyd> I can, but I can't tell if sessionOpened() is guaranteed to run
and complete before any incoming messages are processed
<dmlloyd> I hope it is
<dmlloyd> it's hard to follow what's happening in the MINA codebase though
<tazle> dmlloyd: shouldn't it be enough that sessionOpened() is called on
IoHandler before messageReceived()?
<dmlloyd> yes, that would be sufficient - however there is nothing in the
docs that says that is true
<tazle> dmlloyd: hmm, true
<dmlloyd> I would hope that is the case, otherwise sessionOpened() is not
very useful
<tazle> I guess NioSocketConnector is the most relevant implementation here
<dmlloyd> yeah, that's what I'm using for now
<dmlloyd> though I may try out APR at some future point
<dmlloyd> heh, seriously, I can't find where sessionOpened is called
<mike_heath> DefaultIoFilterChain:677
<dmlloyd> well, yeah
<dmlloyd> but when is the filter chain invoked?
<tazle> hmm
<tazle> tracing the call chain from connect() only gets me to
fireSessionCreated(), which is fired in the same method as the session is
added to its selector
<dmlloyd> where is that?
<tazle> AbstractPollingIoProcessor.java:267 in my (somewhat dated) checkout
<tazle> init(session) earlier registers the underlying SocketChannel to the
Selector of NioProcessor
<dmlloyd> crap
<dmlloyd> well that's no good
<dmlloyd> hm, that's arguably a bug
<dmlloyd> there's no filter chain yet
<dmlloyd> what if a message comes in? it would skip the whole filter chain
<dmlloyd> unless that's guaranteed to be the same thread?
<tazle> dmlloyd: I think there's only one Worker
<tazle> also, fireSessionOpened() may be called from three places, one of
which seems to be vmpipe-specific
* dmlloyd headache
<dmlloyd> this shouldn't be this complicated :)
<tazle> I think it has to be, if the transprot implementations are supposed
to be this pluggable
<tazle> hm, an IoServiceListener fires both sessionCreated() and
sessionOpened() rigth after each other
<tazle> err, IoServiceListenerSupport
<tazle> oh, and I guess it all depends on what is registered in the
NioSocketConnector as IoServiceListener
<tazle> oh wait, the getListeners on line 267 always returns
IoServiceListenerSupport, which fires both sessionCreated and sessionOpened
on the session
<tazle> dmlloyd: right, so apparently both sessionCreated and sessionOpened
are actually fired right after one another from the same method, it seems
<tazle> which makes is puzzling as to why both exist
<dmlloyd> baffling
<tazle> dmlloyd: will you post something to the ML?
<dmlloyd> I did already
<tazle> ok
<dmlloyd> I think I'll reply to it with this whole conversation :)
- DML