]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/result.c
Use a separate mutex for the replication timestamp
[openldap] / servers / slapd / result.c
index fcf1b137e4f51044e44228da62841c297b697d35..b3971d5284a3e8f5c136a657ca8aa217aa0bb235 100644 (file)
@@ -211,31 +211,71 @@ static long send_ldap_ber(
 }
 
 static int
-send_ldap_controls( BerElement *ber, LDAPControl **c )
+send_ldap_control( BerElement *ber, LDAPControl *c )
 {
        int rc;
+
+       assert( c != NULL );
+
+       rc = ber_printf( ber, "{s" /*}*/, c->ldctl_oid );
+
+       if( c->ldctl_iscritical ) {
+               rc = ber_printf( ber, "b",
+                       (ber_int_t) c->ldctl_iscritical ) ;
+               if( rc == -1 ) return rc;
+       }
+
+       if( c->ldctl_value.bv_val != NULL ) {
+               rc = ber_printf( ber, "O", &c->ldctl_value ); 
+               if( rc == -1 ) return rc;
+       }
+
+       rc = ber_printf( ber, /*{*/"N}" );
+       if( rc == -1 ) return rc;
+
+       return 0;
+}
+
+static int
+send_ldap_controls( Operation *o, BerElement *ber, LDAPControl **c )
+{
+       int rc;
+#ifdef LDAP_SLAPI
+       LDAPControl **sctrls = NULL;
+
+       /*
+        * Retrieve any additional controls that may be set by the
+        * plugin.
+        */
+
+       if ( o->o_pb && slapi_pblock_get( o->o_pb, SLAPI_RESCONTROLS, &sctrls ) != 0 ) {
+               sctrls = NULL;
+       }
+
+       if ( c == NULL && sctrls == NULL ) return 0;
+#else
        if( c == NULL ) return 0;
+#endif /* LDAP_SLAPI */
 
        rc = ber_printf( ber, "t{"/*}*/, LDAP_TAG_CONTROLS );
        if( rc == -1 ) return rc;
 
+#ifdef LDAP_SLAPI
+       if ( c != NULL )
+#endif /* LDAP_SLAPI */
        for( ; *c != NULL; c++) {
-               rc = ber_printf( ber, "{s" /*}*/, (*c)->ldctl_oid );
-
-               if( (*c)->ldctl_iscritical ) {
-                       rc = ber_printf( ber, "b",
-                               (ber_int_t) (*c)->ldctl_iscritical ) ;
-                       if( rc == -1 ) return rc;
-               }
+               rc = send_ldap_control( ber, *c );
+               if( rc == -1 ) return rc;
+       }
 
-               if( (*c)->ldctl_value.bv_val != NULL ) {
-                       rc = ber_printf( ber, "O", &((*c)->ldctl_value)); 
+#ifdef LDAP_SLAPI
+       if ( sctrls != NULL ) {
+               for ( c = sctrls; *c != NULL; c++ ) {
+                       rc = send_ldap_control( ber, *c );
                        if( rc == -1 ) return rc;
                }
-
-               rc = ber_printf( ber, /*{*/"N}" );
-               if( rc == -1 ) return rc;
        }
+#endif /* LDAP_SLAPI */
 
        rc = ber_printf( ber, /*{*/"N}" );
 
@@ -249,14 +289,23 @@ send_ldap_response(
 {
        BerElementBuffer berbuf;
        BerElement      *ber = (BerElement *) &berbuf;
-       int             rc;
+       int             rc = LDAP_SUCCESS;
        long    bytes;
 
-       if (op->o_callback && op->o_callback->sc_response) {
-               rc = op->o_callback->sc_response( op, rs );
+       if (op->o_callback) {
+               slap_callback *sc = op->o_callback;
+               rc = SLAP_CB_CONTINUE;
+               for ( ; op->o_callback; ) {
+                       if ( op->o_callback->sc_response ) {
+                               rc = op->o_callback->sc_response( op, rs );
+                               if ( rc != SLAP_CB_CONTINUE ) break;
+                       }
+                       op->o_callback = op->o_callback->sc_next;
+               }
+               op->o_callback = sc;
                if ( rc != SLAP_CB_CONTINUE ) goto cleanup;
        }
-               
+
 #ifdef LDAP_CONNECTIONLESS
        if (op->o_conn && op->o_conn->c_is_udp)
                ber = op->o_res_ber;
@@ -343,8 +392,8 @@ send_ldap_response(
                rc = ber_printf( ber, /*"{"*/ "N}" );
        }
 
-       if( rc != -1 && rs->sr_ctrls != NULL ) {
-               rc = send_ldap_controls( ber, rs->sr_ctrls );
+       if( rc != -1 ) {
+               rc = send_ldap_controls( op, ber, rs->sr_ctrls );
        }
 
        if( rc != -1 ) {
@@ -409,10 +458,20 @@ send_ldap_response(
 
 cleanup:;
        if ( rs->sr_matched && rs->sr_flags & REP_MATCHED_MUSTBEFREED ) {
-               free( rs->sr_matched );
+               free( (char *)rs->sr_matched );
                rs->sr_matched = NULL;
        }
 
+       if (op->o_callback) {
+               slap_callback *sc = op->o_callback;
+               for ( ; op->o_callback; op->o_callback = op->o_callback->sc_next ) {
+                       if ( op->o_callback->sc_cleanup ) {
+                               op->o_callback->sc_cleanup( op, rs );
+                       }
+               }
+               op->o_callback = sc;
+       }
+
        return;
 }
 
@@ -527,7 +586,7 @@ slap_send_ldap_result( Operation *op, SlapReply *rs )
         * result if they wish to change the result.
         */
        if ( op->o_pb ) {
-               slapi_x_pblock_set_operation( op->o_pb, op );
+               slapi_int_pblock_set_operation( op->o_pb, op );
                slapi_pblock_set( op->o_pb, SLAPI_RESULT_CODE, (void *)rs->sr_err );
                slapi_pblock_set( op->o_pb, SLAPI_RESULT_TEXT, (void *)rs->sr_text );
                slapi_pblock_set( op->o_pb, SLAPI_RESULT_MATCHED, (void *)rs->sr_matched );
@@ -650,8 +709,6 @@ slap_send_search_entry( Operation *op, SlapReply *rs )
        computed_attr_context    ctx;
        AttributeName   *anp;
 #endif
-       void            *mark = NULL;
-
        AttributeDescription *ad_entry = slap_schema.si_ad_entry;
 
        /* a_flags: array of flags telling if the i-th element will be
@@ -661,8 +718,17 @@ slap_send_search_entry( Operation *op, SlapReply *rs )
        char **e_flags = NULL;
 
        rs->sr_type = REP_SEARCH;
-       if (op->o_callback && op->o_callback->sc_response) {
-               rc = op->o_callback->sc_response( op, rs );
+       if (op->o_callback) {
+               slap_callback *sc = op->o_callback;
+               rc = SLAP_CB_CONTINUE;
+               for ( ; op->o_callback; ) {
+                       if ( op->o_callback->sc_response ) {
+                               rc = op->o_callback->sc_response( op, rs );
+                               if ( rc != SLAP_CB_CONTINUE ) break;
+                       }
+                       op->o_callback = op->o_callback->sc_next;
+               }
+               op->o_callback = sc;
                if ( rc != SLAP_CB_CONTINUE ) goto error_return;
        }
 
@@ -676,8 +742,6 @@ slap_send_search_entry( Operation *op, SlapReply *rs )
                op->ors_attrsonly ? " (attrsOnly)" : "", 0 );
 #endif
 
-       mark = sl_mark( op->o_tmpmemctx );
-
        if ( !access_allowed( op, rs->sr_entry, ad_entry, NULL, ACL_READ, NULL )) {
 #ifdef NEW_LOGGING
                LDAP_LOG( ACL, INFO, 
@@ -1119,7 +1183,7 @@ slap_send_search_entry( Operation *op, SlapReply *rs )
                if ( rs->sr_attrs != NULL ) {
                        for ( anp = rs->sr_attrs; anp->an_name.bv_val != NULL; anp++ ) {
                                rc = compute_evaluator( &ctx, anp->an_name.bv_val,
-                                       rs->sr_entry, slapi_x_compute_output_ber );
+                                       rs->sr_entry, slapi_int_compute_output_ber );
                                if ( rc == 1 ) {
                                        break;
                                }
@@ -1131,7 +1195,7 @@ slap_send_search_entry( Operation *op, SlapReply *rs )
                         * plugin decide whether to be naughty or not.
                         */
                        rc = compute_evaluator( &ctx, "*",
-                               rs->sr_entry, slapi_x_compute_output_ber );
+                               rs->sr_entry, slapi_int_compute_output_ber );
                }
                if ( rc == 1 ) {
                        if ( op->o_res_ber == NULL ) ber_free_buf( ber );
@@ -1150,8 +1214,8 @@ slap_send_search_entry( Operation *op, SlapReply *rs )
        attrs_free( aa );
        rc = ber_printf( ber, /*{{*/ "}N}" );
 
-       if( rc != -1 && rs->sr_ctrls != NULL ) {
-               rc = send_ldap_controls( ber, rs->sr_ctrls );
+       if( rc != -1 ) {
+               rc = send_ldap_controls( op, ber, rs->sr_ctrls );
        }
 
        if( rc != -1 ) {
@@ -1222,6 +1286,12 @@ slap_send_search_entry( Operation *op, SlapReply *rs )
        rc = 0;
 
 error_return:;
+       /* FIXME: I think rs->sr_type should be explicitly set to
+        * REP_SEARCH here. That's what it was when we entered this
+        * function. send_ldap_error may have changed it, but we
+        * should set it back so that the cleanup functions know
+        * what they're doing.
+        */
        if ( op->o_tag == LDAP_REQ_SEARCH && rs->sr_type == REP_SEARCH 
                && rs->sr_entry 
                && (rs->sr_flags & REP_ENTRY_MUSTBEFREED) ) 
@@ -1231,9 +1301,17 @@ error_return:;
                rs->sr_flags &= ~REP_ENTRY_MUSTBEFREED;
        }
 
-       sl_release( mark, op->o_tmpmemctx );
        if ( e_flags ) sl_free( e_flags, op->o_tmpmemctx );
 
+       if (op->o_callback) {
+               slap_callback *sc = op->o_callback;
+               for ( ; op->o_callback; op->o_callback = op->o_callback->sc_next ) {
+                       if ( op->o_callback->sc_cleanup ) {
+                               op->o_callback->sc_cleanup( op, rs );
+                       }
+               }
+               op->o_callback = sc;
+       }
        return( rc );
 }
 
@@ -1244,19 +1322,25 @@ slap_send_search_reference( Operation *op, SlapReply *rs )
        BerElement      *ber = (BerElement *) &berbuf;
        int rc = 0;
        int bytes;
-       void *mark;
 
        AttributeDescription *ad_ref = slap_schema.si_ad_ref;
        AttributeDescription *ad_entry = slap_schema.si_ad_entry;
 
        rs->sr_type = REP_SEARCHREF;
-       if (op->o_callback && op->o_callback->sc_response) {
-               rc = op->o_callback->sc_response( op, rs );
-               if ( rc != SLAP_CB_CONTINUE ) return rc;
+       if (op->o_callback) {
+               slap_callback *sc = op->o_callback;
+               rc = SLAP_CB_CONTINUE;
+               for ( ; op->o_callback; ) {
+                       if ( op->o_callback->sc_response ) {
+                               rc = op->o_callback->sc_response( op, rs );
+                               if ( rc != SLAP_CB_CONTINUE ) break;
+                       }
+                       op->o_callback = op->o_callback->sc_next;
+               }
+               op->o_callback = sc;
+               if ( rc != SLAP_CB_CONTINUE ) goto rel;
        }
 
-       mark = sl_mark( op->o_tmpmemctx );
-
 #ifdef NEW_LOGGING
        LDAP_LOG( OPERATION, ENTRY, 
                "send_search_reference: conn %lu  dn=\"%s\"\n", 
@@ -1333,12 +1417,12 @@ slap_send_search_reference( Operation *op, SlapReply *rs )
        }
 
        if( op->o_protocol < LDAP_VERSION3 ) {
+               rc = 0;
                /* save the references for the result */
                if( rs->sr_ref[0].bv_val != NULL ) {
                        if( value_add( &rs->sr_v2ref, rs->sr_ref ) )
-                               return LDAP_OTHER;
+                               rc = LDAP_OTHER;
                }
-               rc = 0;
                goto rel;
        }
 
@@ -1355,8 +1439,8 @@ slap_send_search_reference( Operation *op, SlapReply *rs )
        rc = ber_printf( ber, "{it{W}" /*"}"*/ , op->o_msgid,
                LDAP_RES_SEARCH_REFERENCE, rs->sr_ref );
 
-       if( rc != -1 && rs->sr_ctrls != NULL ) {
-               rc = send_ldap_controls( ber, rs->sr_ctrls );
+       if( rc != -1 ) {
+               rc = send_ldap_controls( op, ber, rs->sr_ctrls );
        }
 
        if( rc != -1 ) {
@@ -1407,7 +1491,15 @@ slap_send_search_reference( Operation *op, SlapReply *rs )
 #endif
 
 rel:
-       sl_release( mark, op->o_tmpmemctx );
+       if (op->o_callback) {
+               slap_callback *sc = op->o_callback;
+               for ( ; op->o_callback; op->o_callback = op->o_callback->sc_next ) {
+                       if ( op->o_callback->sc_cleanup ) {
+                               op->o_callback->sc_cleanup( op, rs );
+                       }
+               }
+               op->o_callback = sc;
+       }
        return rc;
 }