Salut,

Emmanuel Lecharny wrote:
Jeanfrancois Arcand wrote:
Salut,
Bonsoir,

Emmanuel Lecharny wrote:
<snip/>
- The filter chain is not static, but it should be thread safe, so any kind of modification must *not* lead to some exception (NPE or inconsistent state)

Can you made this behavior configurable? In a project I'm working on :-) we made this configurable. e.g. a filters can be thread safe or not. When not safe, we internally pool filters. That might sound a weird design, but we have seen application that needed to write 'statefull'/thread unsafe filter. The performance penalty is limited to WorkerThread that poll for instance of those filters...which is not that significant.
My first understanding was that once the chain is defined, it never changes. It's somehow pretty much always true. But if you dig a bit, you might have cases where it would be a cool feature to make this chain configurable. Now it leads to some decision : should this chain be thread safe ? The chain is associated with a session, and as you may have more than one message processed on this session (as we may have an executorFilter in front of the chain to dispatch the processing to a pool of thread), this may be a problem. On the other side, that's a penalty we would like not to pay in all the case we don't need to change the chain.

If we implement the chain using an simple pointer to the next filter in each filter, obvioulsy, if this pointer (reference to the next filter, 'pointer' is not to be understood as if MINA was written in C :), it could be volatile, protecting the chain from NPE. Another option, and it's not a bad idea, would be to define a threadSafe chain, which can be modified, or a not synchronized chain, which can't be changed. We have to dig those ideas.

Just for my understanding, does the chain be modified by the user? Would it be too demanding to ask the user to sync its filter itself. That's one of the reason why we have 2 mode in Grizzly, but that might not be a good idea :-)




- Passing to the next filter should be possible in the middle of a filter processing (ie, in a specific filter, you can do some pre-processing, call the next filter, and do some post-processing)

Would it make it "too" complicated for users? What I did in Grizzly was to split the task into 2 operations (Filter.execute(), Filter.postExecute()). The execute() method return a boolean to telling the chain to invoke the next filter or not. Then, in reverse order, we invoke the postExecute() on the previously invoked filters. But I might be wrong here :-)
We discussed about this option : having preExecute(), callNext() and postExecute() methods. At first sight, sounds interesting. But there is a couple of problems with this approach : - this is quite heavy for the user, as he has to implement potentially 3 methids for each event, instead of one

Agree.


- it does not cover the case where you have some branching in the preExecute method. Let me explain with a small piece of pseudo-code :

if ( message meets condition )
 then callNext filter
 else
   do some processing on the message
   if ( processed message meets some other condition )
     then callNext filter
      ...

In this case, having a preExecute() method does not help a lot. Something better would be to have a getNext() method which compute the next filter (or possibly this filter is already fixed when the chain is built, for instance if you have an immutable chain), then you can do whatever processing and eventually call the next filter when you want.

Of course, I'm talking with a one-way chain in mind, not a two ways chain.

But this is only what I have in mind, and I think we can ellaborate a bit more, possibly discarding my crazy ideas :)

The getNext() approach is promising. At least in Tomcat they moved their internal Valve architecture to exactly use that approach. GlassFish forked Tomcat and the approach used is preExecute/postExecute. There is pro and con for both (preExecute/postExecute was faster when we measured long time ago) but I would think for user is it simple using the getNext() (strange I say that as I've implemented the pre/post :-)). I think it is simpler.





- We should be able to use different pipelines depending on the service (filters can be arranged differently on the same server for 2 different services)

That one sound interesting. I'm curious to find how you will detect which pipeline to invoke. You will need some Mapper right?
yeah. For instance, if you are building a kind of proxy, you will most certainly have more than one service, but you may share filters. Each service will proxy for a specific protocol, thus will have its own chain. Now, the service is associated with an established connection, which means you can define which service to invoke depending on the port the connection is connected to.

Another idea is that you may have a demuxer which will determinate which chain to invoke depending on the encapsulating protocol elements. This is something we use in LDAP, as we know which message we are dealing with only after having decoded a part of the message, then we chain to many different handlers, but we could also have more protocolCodecFilters for the encapsulated protocol element.

But this is going a bit too far from the initial discussion here :)

- Even for two different sessions, we may have different chain of filters (one session might use a Audit filter while the next is just fine without this filter) - We want to decouple the message processing from the socket processor, using a special filter which use an executor to process the message in its own thread

Yes that one will for sure improve performance :-)
FYI, we already have this filter.
Proposition (d) The Protocolhandler should be a filter, like any other one.


We had the same discussion in Grizzly and we came with the same conclusion :-)
Pfewww !!! I'm not alone in the dark ;)
PS : All those changes need to be validated, as I may have missed some points. I also suggest that some prototype be written, in a sandbox. This will be the best way to check if those ideas are sane or insane, and also to correctly evaluate the impact on existing code.

So, wdyt, guys ?

From an outlier view, that looks promising (and dangerous for the outlier project :-))
I'm more concerned by the time it will take to implement this in MINA, than by the harm it may cause to other projects, especially to Grizzly :) All in all, we benefit from each others, and this is good for our users.

Agree.



-- Jeanfrancois
Thanks Jean-François ! This is a pleasure to have you around. I feel so comfortable to have such guys like you or Howard Chu (OpenLdap) because you guys are sharing ideas. This is a rare quality !

Thanks :-)

-- Jeanfrancois



Reply via email to