On Thu, Nov 3, 2011 at 3:16 PM, Emmanuel Lecharny <elecharny@gmail.com> wrote:
On 11/3/11 12:54 PM, Alex Karasulu wrote:
Hi all,

Forgive the prepost here: need to report on a off list conversation I just
had with Emmanuel. We generated some very nice ideas on these matters. I'm
going to be very direct with implementation details rather than being high
level and general with these ideas to directly dump the thoughts:

(1)  For each intercepted operation (add, delete, modify etc), the server
maintains an ordered list of core aspect descriptors out of the box
(normalization, access-control, authorization etc) which must be applied in
order to an invocation of an intercepted operation.

To do this we can have an operation expose aspect ordering:

add.getAspects() ... returns order list or array of Aspects like
{Normalization, AccessControl, Authorization, ...}.

Dynamic configuration should allow us to change this ordered list on the
fly to introduce new aspects or remove old ones. Meaning if we like we can
define a new logical aspect like craptastic aspect and have it participate
in various operation invocations in the order we like it to participate.

This is our logical aspect ordering model and exposed as a dynamic
configuration point in the server.

(2) Each Interceptor must publish one and only one aspect it participates
in. The aspect must be in the set of aspects configured in the server via
dynamic configuration so we have a list of aspects managed by the server
without the need for ordering since ordering is operation specific.

normalization
craptastic
authentication
access-control
foobar

...

Interceptor.getAspect()  should return an aspect within this set, and if it
does not then it simply is not considered for injection into the chains
created.

In the configuration area we also manage operation aspects with order:

bind: normalization, authentication
add: normalization ....
del: ...
modify ....
...

The user is constrained to only include aspects in the set of supported
aspects above. No problem though, the user can add his or her custom aspect
to the set, then can start adding that aspect to the operation aspect lists
in the configuration. If no interceptor exists to supply functionality for
that aspect, no problem it's just not injected during actual physical chain
construction time. Once an interceptor appears it can be considered for
injection when calculating the interceptor ordering in chains ... see below.

This is good for the OSGi model where services (interceptors in this case)
can come and go.

(3) The server tracks the actual interceptor implementation execution order
by calculating this order using these aspects on a per operation basis. If
interceptor Foo.getAspect = Normalization and interceptor Bar.getAspect =
Authentication, then for bind the interceptor implementation order would
be:

Foo, Bar

The result of this calculation will be dynamically configurable as
described above by altering configurations for aspect order per operation.
This way we can add new aspects, that have not even been conceived of while
creating ApacheDS. Users will have this freedom. And at chain construction
time the right implementations will be properly selected and injected in
the right order.

(3) At session creation time, the server constructs interceptor reference
lists with actual references to interceptor instances for each operation.
Sessions do not need unique interceptor instances: the interceptors are
shared across sessions and chains. The server uses the aspect information
from an Interceptor and operation aspect lists to determine this reference
list order and construct it.

For Bind operation the interceptor reference list would be Foo, Bar as in
the example above.

Each session has an interceptor reference list calculated for each
operation and this is stored within each session.   This way sessions can
modify their interceptor reference lists for various operations to have
fine grained auditing for example for a single operation in a single
connection without impacting all sessions or the entire server.

The overhead for managing separate interceptor reference lists for each
operation in each session is minimal.

(4) The interceptor chain changes character somewhat. It is modified to not
be statically hardwired but to use the interceptor reference list of the
operation invoked from a session to conduct invocations with the correct
interceptor order.

I think this can be done without causing inefficiencies. I don't have
suggestions on how best we can do this in the code right now.

Thoughts? Additions?

A few additions :

- the default order should be stored in the config (DIT)

Absolutely. The default aspect set must be in the config out of the box. The default aspect application orders must also be defined in the config for all operations.
 
- up to a user to modify this order, but then, it's his responsibility.

+1 
 
- we have to store a aspect <-> interceptor map in the config too (DIT)

-1

Our proposed solution removes the need for this. The aspect an Interceptor implementation is associated with, is directly queried from the Interceptor. There is no need for this mapping at all. The mapping is in the code of the Interceptor. The Interceptor interface needs a getAspect() method that all interceptors must support.
 
- we must get rid of bypasses. They are far too numerous, and probably out of control.

0

I don't know the answer to this myself. We need more discussion for us to see if this is the case. I think each logical aspect managed in the configuration should expose not only a direct aspect list for each operation but also a set of aspects to bypass on re-entrant invocation.  
 
Here is the list of all the bypasses we are using : http://pastebin.com/tYDMvGMZ


Looking ... damn! OK we probably need another thread to clean up this mess but I don't think we can disregard bypass mechanisms all together. We need to clean this up, simplify it and get her done. I don't think we can just scrap bypasses otherwise you'll have incorrect operation and severe levels of inefficiency.
 
SNIP ...

--
Best Regards,
-- Alex