[Date Prev][Date Next] [Chronological] [Thread] [Top]

Re: Move SLAPI in an overlay...

>[moving to -devel, just in case...]

No problem, I seem to have the general case working now (thanks to
Howard for adding overlay_op_walk() to backover.c).

>Not that much, see below.


BTW, do you have any ideas about how to do computed attributes with
overlays (recall that computed attributes aren't stored in the entry,
instead the plugins are called with each requested attribute and a
callback to return the result to the client).

>> Also, I'm not sure whether it will be possible to move the SLAPI code
>> out of result.c, because of the way computed attributes work (they are
>> not stored in the entry) -- but I figure that getting as much of SLAPI
>> out of the frontend as possible is a good start.
>I bet we can; maybe we need to hijack quite a bit
>rs->sr_operational_attrs, which is exactly intended to append generated
>attributes (we need to make sure that, despite the name, it doesn't imply
>attributes have to be operational; I think the change would be of general
>usefulness anyway.

>        /* FIXME: I guess we shouldn't get here if op->o_pb == NULL;
>         * if my understanding is correct, I'd rather put an assert here */
>        if ( op->o_pb == NULL ) {
>                return SLAP_CB_CONTINUE;
>        }

Noted. Instead we test for op->o_extensions == NULL to avoid recursing
for SLAPI internal operations, but we can probably think of a better
way of doing this. (BTW, asserting doesn't appear to work on abandon
as called by connection_closing() because op is zeroed?)

I do like your approach of splitting it. That said, I think I've got
the other case working now, and at least it does have the advantage
of having the same control flow as before. See below.

static int
slapi_op_func( Operation *op, SlapReply *rs )
        Slapi_PBlock    *pb = op->o_pb;
        slap_operation_t        which;
        struct slapi_op_info    *opinfo;
        int             rc, flags = 0;
        slap_overinfo   *oi;
        slap_overinst   *on;
        slap_callback   cb;

         * We check for op->o_extensions to verify that we are not
         * processing a SLAPI internal operation. XXX
        if ( if op->o_pb == NULL || op->o_extensions == NULL ) {
                return SLAP_CB_CONTINUE;

         * Find the SLAPI operation information for this LDAP
         * operation; this will contain the preop and postop
         * plugin types, as well as any additional information
         * we need to complete.
        which = slapi_tag2op( op->o_tag );
        if ( which >= op_last ) {
                return SLAP_CB_CONTINUE;

        opinfo = &slapi_op_dispatch_table[which];
        if ( opinfo == NULL || opinfo->soi_preop == 0 ) {
                return SLAP_CB_CONTINUE;

        slapi_int_pblock_set_operation( pb, op );

        cb.sc_response = slapi_op_response;
        cb.sc_cleanup = NULL;
        cb.sc_private = NULL;
        cb.sc_next = op->o_callback;
        op->o_callback = &cb;

        on = (slap_overinst *)op->o_bd->bd_info;
        oi = on->on_info;

         * soi_init is responsible for setting any operation-specific
         * pblock parameters ("pre-preoperation plugin")
       if ( opinfo->soi_init != NULL ) {
                rs->sr_err = (opinfo->soi_init)( op, rs, pb );
                if ( rs->sr_err != LDAP_SUCCESS )
                        goto cleanup;

         * Call preoperation plugins
        rs->sr_err = slapi_int_call_plugins( op->o_bd, opinfo->soi_preop, pb );

         * soi_callback is responsible for examining the result code
         * of the preoperation plugin and determining whether to
         * abort. This is needed because of special SLAPI behaviour
         * with bind preoperation plugins.
         * The soi_callback function is also used to reset any values
         * returned from the preoperation plugin before calling the
         * backend (for the success case).
        if ( opinfo->soi_callback == NULL ) {
                if ( rs->sr_err < 0 ) {
                        slapi_pblock_get( pb, SLAPI_RESULT_CODE, (void **)&rs->sr_err );
                        goto cleanup;
        } else {
                rc = (opinfo->soi_callback)( op, rs, pb );
                if ( rc )
                        goto cleanup;

        rs->sr_err = overlay_op_walk( op, rs, which, oi, on->on_next );

         * Call postoperation plugins
        slapi_pblock_set( pb, SLAPI_RESULT_CODE, (void *)rs->sr_err );
        slapi_int_call_plugins( op->o_bd, opinfo->soi_postop, pb );

        if ( opinfo->soi_cleanup != NULL ) {
                (opinfo->soi_cleanup)( op, rs, pb );

        op->o_callback = cb.sc_next;

        return rs->sr_err;

-- Luke