I might need some beers just to cure the headache I get from looking
at that stack trace.

I agree that the "+1" is ugly and the ChainIterator is a much better
solution.  Would a queue work in this situation?

--Mark


On Mon, Nov 10, 2008 at 8:56 AM, Emmanuel Lecharny <[EMAIL PROTECTED]> wrote:
> Hi guys,
>
> I'm still doing some experiment with the new chain (in mina-new-chain2
> branch). It's not totally satisfactory, mainly for two reasons :
> - I have used a List to store the filters, so I have to propagate an integer
> index to jump from one filter to another. This is a bit ugly, as you have
> inex+1 all over the code. I will move to what was suggested by Steve Ulrich
> (passing a ChainIterator instead of an index will mask the ugly +1).
> - The current MINA code is so damn complex that it makes it an order of
> magnitude more complicated to fix than to rewrite it, but this is not
> something I want to jump in, yet. As an example, here is the stack you get
> when you receive a message and send back a response (just for you to realize
> how insane is the current code ...). And we only have three filters : mdc,
> codec and logging.
>
> AbstractPollingIoProcessor$Processor.run()
>  NioProcessor(AbstractPollingIoProcessor<T>).process()
>   NioProcessor(AbstractPollingIoProcessor<T>).process(T)
>     NioProcessor(AbstractPollingIoProcessor<T>).read(T)
>     | DefaultIoFilterChain.fireMessageReceived(java.lang.Object)
>     |   DefaultIoFilterChain.callNextMessageReceived(IoFilterChain$Entry,
> IoSession, Object)
>     |
> DefaultIoFilterChain$HeadFilter(IoFilterAdapter).messageReceived(IoFilter$NextFilter,
> IoSession, Object)
>     |       DefaultIoFilterChain$EntryImpl$1.messageReceived(IoSession,
> Object)
>     |
> DefaultIoFilterChain.callNextMessageReceived(IoFilterChain$Entry, IoSession,
> Object)       |
> MdcInjectionFilter(CommonEventFilter).messageReceived(IoFilter$NextFilter,
> IoSession, Object)
>     |             MdcInjectionFilter.filter(IoFilterEvent)
>     |               IoFilterEvent.fire()
>     |
> DefaultIoFilterChain$EntryImpl$1.messageReceived(IoSession, Object)
>     |
> DefaultIoFilterChain.callNextMessageReceived(IoFilterChain$Entry, IoSession,
> Object)
>     |
> ProtocolCodecFilter.messageReceived(IoFilter$NextFilter, IoSession, Object)
>     |                     | TextLineDecoder.decode(IoSession, IoBuffer,
> ProtocolDecoderOutput)
>     |                     |
> TextLineDecoder.decodeAuto(TextLineDecoder$Context, IoSession, IoBuffer,
> ProtocolDecoderOutput)
>     |                     | <-+
>     |                     |
> ProtocolCodecFilter$ProtocolDecoderOutputImpl.flush()
>     |                     |
> DefaultIoFilterChain$EntryImpl$1.messageReceived(IoSession, Object)
>     |                     |
> DefaultIoFilterChain.callNextMessageReceived(IoFilterChain$Entry, IoSession,
> Object)
>     |                     |
> LoggingFilter.messageReceived(IoFilter$NextFilter, IoSession, Object)
>     |                     |
> DefaultIoFilterChain$EntryImpl$1.messageReceived(IoSession, Object)       |
>                     |
> DefaultIoFilterChain.callNextMessageReceived(IoFilterChain$Entry, IoSession,
> Object)       |                     |
> DefaultIoFilterChain$TailFilter.messageReceived(IoFilter$NextFilter,
> IoSession, Object)       |                     |
> ChatProtocolHandler.messageReceived(IoSession, Object)
>     |                     |
> ChatProtocolHandler.broadcast(String)
>     |                     |
> NioSocketSession(AbstractIoSession).write(Object)       |
>   |                     NioSocketSession(AbstractIoSession).write(Object,
> SocketAddress)
>     |                     |
> DefaultIoFilterChain.fireFilterWrite(WriteRequest)
>     |                     |
> DefaultIoFilterChain.callPreviousFilterWrite(IoFilterChain$Entry, IoSession,
> WriteRequest)
>     |                     |
> DefaultIoFilterChain$TailFilter.filterWrite(IoFilter$NextFilter, IoSession,
> WriteRequest)
>     |                     |
> DefaultIoFilterChain$EntryImpl$1.filterWrite(IoSession, WriteRequest)
>     |                     |
> DefaultIoFilterChain.callPreviousFilterWrite(IoFilterChain$Entry, IoSession,
> WriteRequest)
>     |                     |
> LoggingFilter(IoFilterAdapter).filterWrite(IoFilter$NextFilter, IoSession,
> WriteRequest)
>     |                     |
> DefaultIoFilterChain$EntryImpl$1.filterWrite(IoSession, WriteRequest)
>     |                     |
> DefaultIoFilterChain.callPreviousFilterWrite(IoFilterChain$Entry, IoSession,
> WriteRequest)
>     |                     |
> ProtocolCodecFilter.filterWrite(IoFilter$NextFilter, IoSession,
> WriteRequest)
>     |                     |                                       |
> TextLineEncoder.encode(IoSession, Object, ProtocolEncoderOutput)
>     |                     |                                       |
> ProtocolCodecFilter$ProtocolEncoderOutputImpl(AbstractProtocolEncoderOutput).write(Object)
>     |                     |                                       | <-+
>     |                     |                                       |
> ProtocolCodecFilter$ProtocolEncoderOutputImpl.flushWithoutFuture()
>     |                     |                                       |
> DefaultIoFilterChain$EntryImpl$1.filterWrite(IoSession, WriteRequest)
>     |                     |                                       |
> DefaultIoFilterChain.callPreviousFilterWrite(IoFilterChain$Entry, IoSession,
> WriteRequest)
>     |                     |                                       |
> MdcInjectionFilter(CommonEventFilter).filterWrite(IoFilter$NextFilter,
> IoSession, WriteRequest)       |                     |
>                 |         MdcInjectionFilter.filter(IoFilterEvent)       |
>                   |                                       |
> IoFilterEvent.fire()       |                     |
>             |
> DefaultIoFilterChain$EntryImpl$1.filterWrite(IoSession, WriteRequest)
>     |                     |                                       |
>       DefaultIoFilterChain.callPreviousFilterWrite(IoFilterChain$Entry,
> IoSession, WriteRequest)       |                     |
>                 |
> DefaultIoFilterChain$HeadFilter.filterWrite(IoFilter$NextFilter, IoSession,
> WriteRequest)       |                     |
>       |                   SimpleIoProcessorPool<T>.flush(T)       |
>             |                                       |
> NioProcessor(AbstractPollingIoProcessor<T>).flush(T)       |
>     |                                       |
> NioProcessor.wakeup()       |                     |
>               |                     <-+
>     |                     |                                       |
>           <-+
>     |                     |                                       |
>         <-+
>     |                     |                                       |
>       <-+
>     |                     |                                       |
>     <-+
>     |                     |                                       |
>   <-+
>     |                     |                                       |
> <-+
>     |                     |                                       |
> <-+
>     |                     |                                       |     <-+
>     |                     |                                       |   <-+
>     |                     |                                       | <-+
>     |                     |                                       |
> DefaultIoFilterChain$EntryImpl$1.filterWrite(IoSession, WriteRequest)
>     |                     |                                       |
> DefaultIoFilterChain.callPreviousFilterWrite(IoFilterChain$Entry, IoSession,
> WriteRequest)
>     |                     |                                       |
> CommonEventFilter).filterWrite(IoFilter$NextFilter, IoSession, WriteRequest)
>     |                     |                                       |
> MdcInjectionFilter.filter(IoFilterEvent)
>     |                     |                                       |
> IoFilterEvent.fire()
>     |                     |                                       |
>   DefaultIoFilterChain$EntryImpl$1.filterWrite(IoSession, WriteRequest)
>   |                     |                                       |
>   DefaultIoFilterChain.callPreviousFilterWrite(IoFilterChain$Entry,
> IoSession, WriteRequest)
>     |                     |                                       |
>       DefaultIoFilterChain$HeadFilter.filterWrite(IoFilter$NextFilter,
> IoSession, WriteRequest)
>     |                     |                                       |
>         SimpleIoProcessorPool<T>.flush(T)
>     |                     |                                       |
>
> NioProcessor(org.apache.mina.core.polling.AbstractPollingIoProcessor<T>).flush(T)
>     |                     |                                       |
>         <-+
>     |                     |                                       |
>       <-+
>     |                     |                                       |
>     <-+
>     |                     |                                       |
>   <-+
>     |                     |                                       |
> <-+
>     |                     |                                       |
> <-+
>     |                     |                                       |     <-+
>     |                     |                                       |   <-+
>     |                     |                                       | <-+
>     |                     |                                       <-+
>     |                     |                                     <-+       |
>                     |                                   <-+       |
>             |                                 <-+       |
>   |                               <-+       |                     |
>                     <-+       |                     |
>     <-+       |                     |                         <-+       |
>                   |                       <-+       |                     |
>                     <-+       |                     |                   <-+
>       |                     |                 <-+       |
>   |               <-+       |                     |             <-+       |
>                     |           <-+       |                     |
> <-+       |                     |       <-+       |                     |
>   <-+       |                     |   <-+       |                     | <-+
>       |                     <-+       |                   <-+       |
>           <-+       |               <-+       |             <-+       |
>       <-+       |         <-+       |       <-+       |     <-+
>     |   <-+       | <-+       <-+
>   <-+
>  <-+
>  NioProcessor(AbstractPollingIoProcessor<T>).flush(long)
>   NioProcessor(AbstractPollingIoProcessor<T>).flushNow(T, long)
>     NioProcessor(AbstractPollingIoProcessor<T>).writeBuffer(T, WriteRequest,
> boolean, int, long)
>     | NioProcessor.write(NioSession, IoBuffer, int)  // Actually write data
> into the socket
>     <-+
>       NioProcessor(AbstractPollingIoProcessor<T>).fireMessageSent(T,
> WriteRequest)           DefaultIoFilterChain.fireMessageSent(WriteRequest)
>           DefaultIoFilterChain.callNextMessageSent(IoFilterChain$Entry,
> IoSession, WriteRequest)
> DefaultIoFilterChain$HeadFilter(IoFilterAdapter).messageSent(IoFilter$NextFilter,
> IoSession, WriteRequest)
> DefaultIoFilterChain.callNextMessageSent(IoFilterChain$Entry, IoSession,
> WriteRequest)
> MdcInjectionFilter(org.apache.mina.filter.util.CommonEventFilter).messageSent(IoFilter$NextFilter,
> IoSession, WriteRequest)
> MdcInjectionFilter.filter(IoFilterEvent)
> IoFilterEvent.fire()
> DefaultIoFilterChain$EntryImpl$1.messageSent(IoSession, WriteRequest)
>
> DefaultIoFilterChain.callNextMessageSent(IoFilterChain$Entry, IoSession,
> WriteRequest)
> ProtocolCodecFilter.messageSent(IoFilter$NextFilter, IoSession,
> WriteRequest)
>                         <-+                         <-+
>                     <-+
>                   <-+
>                 <-+
>               <-+
>             <-+
>           <-+
>         <-+
>       <-+
>     <-+
>   <-+
>  <-+
> <-+
>
> You can see that :
> - for each filter, we have at least 3 lines in the stack, and we have 2 more
> filters : Head and Tail, which make a total of 15 lines, before we reach the
> Handler (in fact, 16 because we go through a two-step filter, the MDC
> filter). We should be able to get it done in 4 steps, max (which is what I
> currently get, except that I still have this extra MDC step)
> - The write chain is called twice : once in
> ProtocolCodecFilter$ProtocolEncoderOutputImpl.flushWithoutFuture(), for an
> extra 11 steps, and as the continuation of the write chain (which has
> already been followed into the flushWthoutFuture() method call), for 9 extra
> steps. I have no f**** idea why this call is necessary, so if anyone has an
> idea, please, feel free to tell me. (In my experiment, I have removed this
> last call, and it seems to be useless, but I'm not 100% sure). The only
> difference is that in the first case, we send a WriteRequest, when in the
> second case, we create a MessageSendRequest() object encapsulating the
> WriteRequest (no idea why...)
> - When all this 'usefull' chaining is done, we then call the chain again to
> inform (who ???) that the message has been sent. This seems to be
> overkilling...
>
> Ok, now, whoever thinks that this is manageable and easy to debug, you have
> to offer me a bunch of beers next year in Amsterdam, and may be some of
> those special space cakes those who created this portion of code must have
> obviously abused while coding :) !
>
> I will commit what I came to with the new chain approach, even if it's not
> -yet- working well : I still have some issues when closing the session, it
> seems that the 'close' message does not propagate well in the chat sample.
>
> I will also try to draw a short desription, with some schema, on how a
> server is initialized and session are created, with all the parallel threads
> (but the IdleThread, which is totally a waste for socket).
>
> Thanks !
>
> --
> --
> cordialement, regards,
> Emmanuel Lécharny
> www.iktek.com
> directory.apache.org
>
>
>

Reply via email to