[389-devel] Review of plugin code

William Brown william at blackhats.net.au
Fri Aug 7 23:18:33 UTC 2015


On Thu, 2015-08-06 at 14:25 -0700, Noriko Hosoi wrote:
> Hi William,
> 
> Very interesting plug-in!

Thanks. As a plugin, it's value is quite useless due to the nsDS5ReplicaType
flags. But it's a nice simple exercise to get ones head around how the plugin
architecture works from scratch. It's one thing to patch a plugin, compared to
writing one from nothing.

> 
> Regarding betxn plug-in, it is for putting the entire operation -- the 
> primary update + associated updates by the enabled plug-ins -- in one 
> transaction.  By doing so, the entire updates are committed to the DB if 
> and only if all of the updates are successful. Otherwise, all of them 
> are rolled back.  That guarantees there will be no consistency among 
> entries.

Okay, so if I can be a pain, how to betxn handle reads? Do reads come from
within the transaction? Or is there a way to read from the database outside the
transaction. 

Say for example:

begin
add some object Y
read Y
commit

Does read Y see the object within the transaction? Is there a way to make the
search happen so that it occurs outside the transaction, IE it doesn't see Y?

> 
> In that sense, your read-only plug-in is not a good example for betxn 
> since it does not do any updates. :)  Considering the purpose of the 
> "read-only" plug-in, invoking it at the pre-op timing (before the 
> transaction) would be the best.

Very true! I kind of knew what betxn did, but I wanted to confirm more
completely in my mind. So I think what my read-only plugin does at the moment
works quite nicely then outside of betxn.

Is there a piece of documentation (perhaps the plugin guide) that lists the
order in which these operations are called? 

> 
> Since MEP requires the updates on the DB, it's supposed to be called in 
> betxn.  That way, what was done in the MEP plug-in is committed or 
> rolled back together with the primary updates.

Makes sense. 

> 
> The toughest part is the deadlock prevention.  At the start transaction, 
> it holds a DB lock.  And most plug-ins maintain its own mutex to protect 
> its resource.  It'd easily cause deadlock situation especially when 
> multiple plug-ins are enabled (which is common :). So, please be careful 
> not to acquire/free locks in the wrong order...

Of course. This is always an issue in multi-threaded code and anything with
locking. Stress tests are probably good to find these deadlocks, no?

> 
> About your commented out code in read_only.c, I guess you copied the 
> part from mep.c and are wondering what it is for?

> 
> There are various type of plug-ins.
> 
>     $ egrep nsslapd-pluginType dse.ldif | sort | uniq
>     nsslapd-pluginType: accesscontrol
>     nsslapd-pluginType: bepreoperation
>     nsslapd-pluginType: betxnpostoperation
>     nsslapd-pluginType: betxnpreoperation
>     nsslapd-pluginType: database
>     nsslapd-pluginType: extendedop
>     nsslapd-pluginType: internalpreoperation
>     nsslapd-pluginType: matchingRule
>     nsslapd-pluginType: object
>     nsslapd-pluginType: preoperation
>     nsslapd-pluginType: pwdstoragescheme
>     nsslapd-pluginType: reverpwdstoragescheme
>     nsslapd-pluginType: syntax
> 
> The reason why slapi_register_plugin and slapi_register_plugin_ext were 
> implemented was:
> 
>     /*
>       * Allows a plugin to register a plugin.
>       * This was added so that 'object' plugins could register all
>       * the plugin interfaces that it supports.
>       */
> 
> On the other hand, MEP has this type.
> 
>     nsslapd-pluginType: betxnpreoperation
> 
> The type is not "object", but the MEP plug-in is implemented as having 
> the type.  Originally, it might have been "object"...  Then, we 
> introduced the support for "betxn".  To make the transition to "betxn" 
> smoothly, we put the code to check "betxn" is in the type. If there is 
> "betxn" as in "betxnpreoperation", call the plug-in in betxn, otherwise 
> call them outside of the transaction.  Having the switch in the 
> configuration, we could go back to the original position without 
> rebuilding the plug-in.
> 
> Since we do not go back to pre-betxn era, the switch may not be too 
> important.  But keeping it would be a good idea for the consistency with 
> the other plug-ins.
> 
> Does this answer you question?  Please feel free to let us know if it 
> does not.

That answers some of my question. I guess the larger part of the question is how
the plugin subsystem treats each pluginType differently and the value of having
a plugin register to more than one pluginType. Are there some documents you can
point me to about this?

Additionally, with betxn, this seems quite black-or-white. It's either on a ds
instance that has betxn support, so every update will be betxn capable, or it's
not on such a system so you fall back to other methods. Is this correct? With
new plugins is it even worth writing them without betxn support? 


> I'm sure our team is interested in your idea and work, so let me share 
> your test plug-in with them.

Sure. It's not really that useful, like I said, nsDS5ReplicaType already does
this job. It was just an exercise to get my head more into the framework before
I work on http://directory.fedoraproject.org/docs/389ds/design/mep-rework.html

Thanks for the review, and for answering my questions. Your advice has helped a
lot! 

Sincerely,



More information about the 389-devel mailing list