mina-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Jeanfrancois Arcand <Jeanfrancois.Arc...@Sun.COM>
Subject Re: [About the Filter Chain] Proposals
Date Mon, 03 Nov 2008 23:47:31 GMT
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


> 

Mime
View raw message