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 > > >
