X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Fbackglue.c;h=cce5905ee1b827595b6ea2bd2a8037e8765a0804;hb=fb2d3926ce4714b83f76c059a18a0d67d12b8019;hp=936d617fdef43541c1bcc3b284e8e9f1a4c0a6cd;hpb=4a1eabf257473d8eadf0c14d72d77a83e73ff09d;p=openldap diff --git a/servers/slapd/backglue.c b/servers/slapd/backglue.c index 936d617fde..cce5905ee1 100644 --- a/servers/slapd/backglue.c +++ b/servers/slapd/backglue.c @@ -2,7 +2,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 2001-2005 The OpenLDAP Foundation. + * Copyright 2001-2006 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -65,7 +65,7 @@ glue_back_select ( glueinfo *gi = (glueinfo *)on->on_bi.bi_private; int i; - for (i = 0; igi_nodes; i++) { + for (i = gi->gi_nodes-1; i >= 0; i--) { assert( gi->gi_n[i].gn_be->be_nsuffix != NULL ); if (dnIsSuffix(dn, &gi->gi_n[i].gn_be->be_nsuffix[0])) { @@ -78,12 +78,13 @@ glue_back_select ( typedef struct glue_state { + char *matched; + BerVarray refs; + LDAPControl **ctrls; int err; - int slimit; int matchlen; - char *matched; int nrefs; - BerVarray refs; + int nctrls; } glue_state; static int @@ -93,14 +94,8 @@ glue_op_response ( Operation *op, SlapReply *rs ) switch(rs->sr_type) { case REP_SEARCH: - if ( gs->slimit != SLAP_NO_LIMIT - && rs->sr_nentries >= gs->slimit ) - { - rs->sr_err = gs->err = LDAP_SIZELIMIT_EXCEEDED; - return -1; - } - /* fallthru */ case REP_SEARCHREF: + case REP_INTERMEDIATE: return SLAP_CB_CONTINUE; default: @@ -146,6 +141,30 @@ glue_op_response ( Operation *op, SlapReply *rs ) gs->nrefs = j; gs->refs = new; } + if (rs->sr_ctrls) { + int i, j, k; + LDAPControl **newctrls; + + for (i=0; rs->sr_ctrls[i]; i++); + + j = gs->nctrls; + if (!j) { + newctrls = ch_malloc((i+1)*sizeof(LDAPControl *)); + } else { + newctrls = ch_realloc(gs->ctrls, + (j+i+1)*sizeof(LDAPControl *)); + } + for (k=0; ksr_ctrls[k]; + if ( !BER_BVISNULL( &rs->sr_ctrls[k]->ldctl_value )) + ber_dupbv( &newctrls[j]->ldctl_value, + &rs->sr_ctrls[k]->ldctl_value ); + } + newctrls[j] = NULL; + gs->nctrls = j; + gs->ctrls = newctrls; + } } return 0; } @@ -157,10 +176,15 @@ glue_op_func ( Operation *op, SlapReply *rs ) BackendDB *b0 = op->o_bd; BackendInfo *bi0 = op->o_bd->bd_info; BI_op_modify **func; - slap_operation_t which; + slap_operation_t which = op_bind; int rc; op->o_bd = glue_back_select (b0, &op->o_req_ndn); + + /* If we're on the master backend, let overlay framework handle it */ + if ( op->o_bd == b0 ) + return SLAP_CB_CONTINUE; + b0->bd_info = on->on_info->oi_orig; switch(op->o_tag) { @@ -168,6 +192,7 @@ glue_op_func ( Operation *op, SlapReply *rs ) case LDAP_REQ_DELETE: which = op_delete; break; case LDAP_REQ_MODIFY: which = op_modify; break; case LDAP_REQ_MODRDN: which = op_modrdn; break; + default: assert( 0 ); break; } func = &op->o_bd->bd_info->bi_op_bind; @@ -190,6 +215,9 @@ glue_chk_referrals ( Operation *op, SlapReply *rs ) int rc; op->o_bd = glue_back_select (b0, &op->o_req_ndn); + if ( op->o_bd == b0 ) + return SLAP_CB_CONTINUE; + b0->bd_info = on->on_info->oi_orig; if ( op->o_bd->bd_info->bi_chk_referrals ) @@ -211,6 +239,9 @@ glue_chk_controls ( Operation *op, SlapReply *rs ) int rc = SLAP_CB_CONTINUE; op->o_bd = glue_back_select (b0, &op->o_req_ndn); + if ( op->o_bd == b0 ) + return SLAP_CB_CONTINUE; + b0->bd_info = on->on_info->oi_orig; /* if the subordinate database has overlays, the bi_chk_controls() @@ -231,6 +262,36 @@ glue_chk_controls ( Operation *op, SlapReply *rs ) return rc; } +/* ITS#4615 - overlays configured above the glue overlay should be + * invoked for the entire glued tree. Overlays configured below the + * glue overlay should only be invoked on the master backend. + * So, if we're searching on any subordinates, we need to force the + * current overlay chain to stop processing, without stopping the + * overall callback flow. + */ +static int +glue_sub_search( Operation *op, SlapReply *rs, BackendDB *b0, + slap_overinst *on ) +{ + /* Process any overlays on the master backend */ + if ( op->o_bd == b0 && on->on_next ) { + BackendInfo *bi = op->o_bd->bd_info; + int rc = SLAP_CB_CONTINUE; + for ( on=on->on_next; on; on=on->on_next ) { + op->o_bd->bd_info = (BackendInfo *)on; + if ( on->on_bi.bi_op_search ) { + rc = on->on_bi.bi_op_search( op, rs ); + if ( rc != SLAP_CB_CONTINUE ) + break; + } + } + op->o_bd->bd_info = bi; + if ( rc != SLAP_CB_CONTINUE ) + return rc; + } + return op->o_bd->be_search( op, rs ); +} + static int glue_op_search ( Operation *op, SlapReply *rs ) { @@ -240,16 +301,17 @@ glue_op_search ( Operation *op, SlapReply *rs ) BackendDB *b1 = NULL, *btmp; BackendInfo *bi0 = op->o_bd->bd_info; int i; - long stoptime = 0; - glue_state gs = {0, 0, 0, NULL, 0, NULL}; + long stoptime = 0, starttime; + glue_state gs = {NULL, NULL, NULL, 0, 0, 0, 0}; slap_callback cb = { NULL, glue_op_response, NULL, NULL }; - int scope0, slimit0, tlimit0; + int scope0, tlimit0; struct berval dn, ndn, *pdn; cb.sc_private = &gs; cb.sc_next = op->o_callback; + starttime = op->o_time; stoptime = slap_get_time () + op->ors_tlimit; op->o_bd = glue_back_select (b0, &op->o_req_ndn); @@ -257,6 +319,9 @@ glue_op_search ( Operation *op, SlapReply *rs ) switch (op->ors_scope) { case LDAP_SCOPE_BASE: + if ( op->o_bd == b0 ) + return SLAP_CB_CONTINUE; + rs->sr_err = LDAP_UNWILLING_TO_PERFORM; if (op->o_bd && op->o_bd->be_search) { rs->sr_err = op->o_bd->be_search( op, rs ); @@ -265,33 +330,17 @@ glue_op_search ( Operation *op, SlapReply *rs ) case LDAP_SCOPE_ONELEVEL: case LDAP_SCOPE_SUBTREE: -#ifdef LDAP_SCOPE_SUBORDINATE case LDAP_SCOPE_SUBORDINATE: /* FIXME */ -#endif - -#if 0 - if ( op->o_sync ) { - if (op->o_bd && op->o_bd->be_search) { - rs->sr_err = op->o_bd->be_search( op, rs ); - } else { - send_ldap_error(op, rs, LDAP_UNWILLING_TO_PERFORM, - "No search target found"); - } - return rs->sr_err; - } -#endif - op->o_callback = &cb; rs->sr_err = gs.err = LDAP_UNWILLING_TO_PERFORM; scope0 = op->ors_scope; - slimit0 = gs.slimit = op->ors_slimit; tlimit0 = op->ors_tlimit; dn = op->o_req_dn; ndn = op->o_req_ndn; b1 = op->o_bd; /* - * Execute in reverse order, most general first + * Execute in reverse order, most specific first */ for (i = gi->gi_nodes; i >= 0; i--) { if ( i == gi->gi_nodes ) { @@ -305,20 +354,17 @@ glue_op_search ( Operation *op, SlapReply *rs ) continue; if (!dnIsSuffix(&btmp->be_nsuffix[0], &b1->be_nsuffix[0])) continue; + if (get_no_subordinate_glue(op) && btmp != b1) + continue; + if (tlimit0 != SLAP_NO_LIMIT) { - op->ors_tlimit = stoptime - slap_get_time (); + op->o_time = slap_get_time(); + op->ors_tlimit = stoptime - op->o_time; if (op->ors_tlimit <= 0) { rs->sr_err = gs.err = LDAP_TIMELIMIT_EXCEEDED; break; } } - if (slimit0 != SLAP_NO_LIMIT) { - op->ors_slimit = slimit0 - rs->sr_nentries; - if (op->ors_slimit < 0) { - rs->sr_err = gs.err = LDAP_SIZELIMIT_EXCEEDED; - break; - } - } rs->sr_err = 0; /* * check for abandon @@ -338,24 +384,32 @@ glue_op_search ( Operation *op, SlapReply *rs ) op->o_req_dn = op->o_bd->be_suffix[0]; op->o_req_ndn = op->o_bd->be_nsuffix[0]; rs->sr_err = op->o_bd->be_search(op, rs); + if ( rs->sr_err == LDAP_NO_SUCH_OBJECT ) { + gs.err = LDAP_SUCCESS; + } + op->ors_scope = LDAP_SCOPE_ONELEVEL; + op->o_req_dn = dn; + op->o_req_ndn = ndn; } else if (scope0 == LDAP_SCOPE_SUBTREE && dn_match(&op->o_bd->be_nsuffix[0], &ndn)) { - rs->sr_err = op->o_bd->be_search( op, rs ); + rs->sr_err = glue_sub_search( op, rs, b0, on ); } else if (scope0 == LDAP_SCOPE_SUBTREE && dnIsSuffix(&op->o_bd->be_nsuffix[0], &ndn)) { op->o_req_dn = op->o_bd->be_suffix[0]; op->o_req_ndn = op->o_bd->be_nsuffix[0]; - rs->sr_err = op->o_bd->be_search( op, rs ); + rs->sr_err = glue_sub_search( op, rs, b0, on ); if ( rs->sr_err == LDAP_NO_SUCH_OBJECT ) { gs.err = LDAP_SUCCESS; } + op->o_req_dn = dn; + op->o_req_ndn = ndn; } else if (dnIsSuffix(&ndn, &op->o_bd->be_nsuffix[0])) { - rs->sr_err = op->o_bd->be_search( op, rs ); + rs->sr_err = glue_sub_search( op, rs, b0, on ); } switch ( gs.err ) { @@ -369,7 +423,7 @@ glue_op_search ( Operation *op, SlapReply *rs ) case LDAP_ADMINLIMIT_EXCEEDED: case LDAP_NO_SUCH_OBJECT: #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR - case LDAP_CANNOT_CHAIN: + case LDAP_X_CANNOT_CHAIN: #endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */ goto end_of_loop; @@ -379,8 +433,8 @@ glue_op_search ( Operation *op, SlapReply *rs ) } end_of_loop:; op->ors_scope = scope0; - op->ors_slimit = slimit0; op->ors_tlimit = tlimit0; + op->o_time = starttime; op->o_req_dn = dn; op->o_req_ndn = ndn; @@ -393,6 +447,7 @@ end_of_loop:; rs->sr_err = gs.err; rs->sr_matched = gs.matched; rs->sr_ref = gs.refs; + rs->sr_ctrls = gs.ctrls; send_ldap_result( op, rs ); } @@ -403,6 +458,14 @@ end_of_loop:; free (gs.matched); if (gs.refs) ber_bvarray_free(gs.refs); + if (gs.ctrls) { + for (i = gs.nctrls; --i >= 0; ) { + if (!BER_BVISNULL( &gs.ctrls[i]->ldctl_value )) + free(gs.ctrls[i]->ldctl_value.bv_val); + free(gs.ctrls[i]); + } + free(gs.ctrls); + } return rs->sr_err; } @@ -477,16 +540,17 @@ glue_open ( if (slapMode & SLAP_TOOL_MODE) { for (i = 0; igi_nodes; i++) { same = 0; - /* Same type as our main backend? */ - if ( gi->gi_n[i].gn_be->bd_info == on->on_info->oi_orig ) + /* Same bi_open as our main backend? */ + if ( gi->gi_n[i].gn_be->bd_info->bi_open == + on->on_info->oi_orig->bi_open ) bsame = 1; /* Loop thru the bd_info's and make sure we only * invoke their bi_open functions once each. */ for ( j = 0; jgi_n[i].gn_be->bd_info == - gi->gi_n[j].gn_be->bd_info ) { + if ( gi->gi_n[i].gn_be->bd_info->bi_open == + gi->gi_n[j].gn_be->bd_info->bi_open ) { same = 1; break; } @@ -715,8 +779,16 @@ glue_db_init( { slap_overinst *on = (slap_overinst *)be->bd_info; slap_overinfo *oi = on->on_info; + BackendInfo *bi = oi->oi_orig; glueinfo *gi; + if ( SLAP_GLUE_SUBORDINATE( be )) { + Debug( LDAP_DEBUG_ANY, "glue: backend %s is already subordinate, " + "cannot have glue overlay!\n", + be->be_suffix[0].bv_val, 0, 0 ); + return LDAP_OTHER; + } + gi = ch_calloc( 1, sizeof(glueinfo)); on->on_bi.bi_private = gi; dnParent( be->be_nsuffix, &gi->gi_pdn ); @@ -729,14 +801,23 @@ glue_db_init( oi->oi_bi.bi_entry_release_rw = glue_entry_release_rw; - oi->oi_bi.bi_tool_entry_open = glue_tool_entry_open; - oi->oi_bi.bi_tool_entry_close = glue_tool_entry_close; - oi->oi_bi.bi_tool_entry_first = glue_tool_entry_first; - oi->oi_bi.bi_tool_entry_next = glue_tool_entry_next; - oi->oi_bi.bi_tool_entry_get = glue_tool_entry_get; - oi->oi_bi.bi_tool_entry_put = glue_tool_entry_put; - oi->oi_bi.bi_tool_entry_reindex = glue_tool_entry_reindex; - oi->oi_bi.bi_tool_sync = glue_tool_sync; + /* Only advertise these if the root DB supports them */ + if ( bi->bi_tool_entry_open ) + oi->oi_bi.bi_tool_entry_open = glue_tool_entry_open; + if ( bi->bi_tool_entry_close ) + oi->oi_bi.bi_tool_entry_close = glue_tool_entry_close; + if ( bi->bi_tool_entry_first ) + oi->oi_bi.bi_tool_entry_first = glue_tool_entry_first; + if ( bi->bi_tool_entry_next ) + oi->oi_bi.bi_tool_entry_next = glue_tool_entry_next; + if ( bi->bi_tool_entry_get ) + oi->oi_bi.bi_tool_entry_get = glue_tool_entry_get; + if ( bi->bi_tool_entry_put ) + oi->oi_bi.bi_tool_entry_put = glue_tool_entry_put; + if ( bi->bi_tool_entry_reindex ) + oi->oi_bi.bi_tool_entry_reindex = glue_tool_entry_reindex; + if ( bi->bi_tool_sync ) + oi->oi_bi.bi_tool_sync = glue_tool_sync; /*FIXME : need to add support */ oi->oi_bi.bi_tool_dn2id_get = 0; @@ -767,7 +848,7 @@ glue_db_close( { slap_overinst *on = (slap_overinst *)be->bd_info; - on->on_info->oi_bi.bi_db_close = NULL; + on->on_info->oi_bi.bi_db_close = 0; return 0; } @@ -779,7 +860,7 @@ glue_sub_del( BackendDB *b0 ) /* Find the top backend for this subordinate */ be = b0; - while ( be=LDAP_STAILQ_NEXT( be, be_next )) { + while ( (be=LDAP_STAILQ_NEXT( be, be_next )) != NULL ) { slap_overinfo *oi; slap_overinst *on; glueinfo *gi; @@ -826,7 +907,7 @@ typedef struct glue_Addrec { static glue_Addrec *ga_list; /* Attach all the subordinate backends to their superior */ -static int +int glue_sub_attach() { glue_Addrec *ga, *gnext = NULL; @@ -840,7 +921,7 @@ glue_sub_attach() /* Find the top backend for this subordinate */ be = ga->ga_be; - while ( be=LDAP_STAILQ_NEXT( be, be_next )) { + while ( (be=LDAP_STAILQ_NEXT( be, be_next )) != NULL ) { slap_overinfo *oi; slap_overinst *on; glueinfo *gi; @@ -893,21 +974,20 @@ glue_sub_add( BackendDB *be, int advert, int online ) glue_Addrec *ga; int rc = 0; + if ( overlay_is_inst( be, "glue" )) { + Debug( LDAP_DEBUG_ANY, "glue: backend %s already has glue overlay, " + "cannot be a subordinate!\n", + be->be_suffix[0].bv_val, 0, 0 ); + return LDAP_OTHER; + } SLAP_DBFLAGS( be ) |= SLAP_DBFLAG_GLUE_SUBORDINATE; if ( advert ) SLAP_DBFLAGS( be ) |= SLAP_DBFLAG_GLUE_ADVERTISE; ga = ch_malloc( sizeof( glue_Addrec )); - ga->ga_next = NULL; + ga->ga_next = ga_list; ga->ga_be = be; - if ( ga_list ) { - glue_Addrec *g2 = ga_list; - - for ( ; g2 && g2->ga_next; g2=g2->ga_next ); - g2->ga_next = ga; - } else { - ga_list = ga; - } + ga_list = ga; if ( online ) rc = glue_sub_attach(); @@ -918,8 +998,6 @@ glue_sub_add( BackendDB *be, int advert, int online ) int glue_sub_init() { - int rc; - glue.on_bi.bi_type = "glue"; glue.on_bi.bi_db_init = glue_db_init; @@ -935,8 +1013,5 @@ glue_sub_init() glue.on_bi.bi_chk_referrals = glue_chk_referrals; glue.on_bi.bi_chk_controls = glue_chk_controls; - rc = overlay_register( &glue ); - if ( rc ) return rc; - - return glue_sub_attach(); + return overlay_register( &glue ); }