X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Fbackglue.c;h=b3ca5d48322e997f3a384d0736eb455339b88b80;hb=6044e46ec7af21658829edde47c4c9c904093df3;hp=5cd6c42f80a16628ca101583de3d006acf1ccac3;hpb=da0c0360e4930142dc6c2c0b0512721af065f78a;p=openldap diff --git a/servers/slapd/backglue.c b/servers/slapd/backglue.c index 5cd6c42f80..b3ca5d4832 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-2006 The OpenLDAP Foundation. + * Copyright 2001-2009 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -35,6 +35,7 @@ #define SLAPD_TOOLS #include "slap.h" +#include "config.h" typedef struct gluenode { BackendDB *gn_be; @@ -51,6 +52,8 @@ static slap_overinst glue; static int glueMode; static BackendDB *glueBack; +static BackendDB glueBackDone; +#define GLUEBACK_DONE (&glueBackDone) static slap_response glue_op_response; @@ -65,7 +68,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,13 +81,24 @@ glue_back_select ( typedef struct glue_state { + char *matched; + BerVarray refs; + LDAPControl **ctrls; int err; int matchlen; - char *matched; int nrefs; - BerVarray refs; + int nctrls; } glue_state; +static int +glue_op_cleanup( Operation *op, SlapReply *rs ) +{ + /* This is not a final result */ + if (rs->sr_type == REP_RESULT ) + rs->sr_type = REP_GLUE_RESULT; + return SLAP_CB_CONTINUE; +} + static int glue_op_response ( Operation *op, SlapReply *rs ) { @@ -139,6 +153,55 @@ 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 { + /* Forget old pagedResults response if we're sending + * a new one now + */ + if ( get_pagedresults( op ) > SLAP_CONTROL_IGNORED ) { + int newpage = 0; + for ( k=0; ksr_ctrls[k]->ldctl_oid, + LDAP_CONTROL_PAGEDRESULTS )) { + newpage = 1; + break; + } + } + if ( newpage ) { + for ( k=0; kctrls[k]->ldctl_oid, + LDAP_CONTROL_PAGEDRESULTS )) { + gs->ctrls[k]->ldctl_oid = NULL; + ldap_control_free( gs->ctrls[k] ); + gs->ctrls[k] = gs->ctrls[--j]; + gs->ctrls[j] = NULL; + break; + } + } + } + } + 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; } @@ -154,6 +217,11 @@ glue_op_func ( Operation *op, SlapReply *rs ) 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) { @@ -161,6 +229,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; + case LDAP_REQ_EXTENDED: which = op_extended; break; default: assert( 0 ); break; } @@ -168,13 +237,25 @@ glue_op_func ( Operation *op, SlapReply *rs ) if ( func[which] ) rc = func[which]( op, rs ); else - rc = SLAP_CB_CONTINUE; + rc = SLAP_CB_BYPASS; op->o_bd = b0; op->o_bd->bd_info = bi0; return rc; } +static int +glue_response ( Operation *op, SlapReply *rs ) +{ + BackendDB *be = op->o_bd; + be = glue_back_select (op->o_bd, &op->o_req_ndn); + + /* If we're on the master backend, let overlay framework handle it. + * Otherwise, bail out. + */ + return ( op->o_bd == be ) ? SLAP_CB_CONTINUE : SLAP_CB_BYPASS; +} + static int glue_chk_referrals ( Operation *op, SlapReply *rs ) { @@ -184,6 +265,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 ) @@ -205,6 +289,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() @@ -225,6 +312,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 ) { @@ -234,9 +351,9 @@ 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, NULL, 0, NULL}; - slap_callback cb = { NULL, glue_op_response, NULL, NULL }; + long stoptime = 0, starttime; + glue_state gs = {NULL, NULL, NULL, 0, 0, 0, 0}; + slap_callback cb = { NULL, glue_op_response, glue_op_cleanup, NULL }; int scope0, tlimit0; struct berval dn, ndn, *pdn; @@ -244,6 +361,7 @@ glue_op_search ( Operation *op, SlapReply *rs ) 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); @@ -251,6 +369,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 ); @@ -260,19 +381,6 @@ glue_op_search ( Operation *op, SlapReply *rs ) case LDAP_SCOPE_ONELEVEL: case LDAP_SCOPE_SUBTREE: case LDAP_SCOPE_SUBORDINATE: /* FIXME */ - -#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; @@ -282,7 +390,7 @@ glue_op_search ( Operation *op, SlapReply *rs ) 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 ) { @@ -296,8 +404,19 @@ 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 we remembered which backend we were on before, + * skip down to it now + */ + if ( get_pagedresults( op ) > SLAP_CONTROL_IGNORED && + op->o_conn->c_pagedresults_state.ps_be && + op->o_conn->c_pagedresults_state.ps_be != btmp ) + 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; @@ -318,33 +437,42 @@ glue_op_search ( Operation *op, SlapReply *rs ) if (scope0 == LDAP_SCOPE_ONELEVEL && dn_match(pdn, &ndn)) { + struct berval mdn, mndn; op->ors_scope = LDAP_SCOPE_BASE; - op->o_req_dn = op->o_bd->be_suffix[0]; - op->o_req_ndn = op->o_bd->be_nsuffix[0]; + mdn = op->o_req_dn = op->o_bd->be_suffix[0]; + mndn = 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; + if ( op->o_req_dn.bv_val == mdn.bv_val ) + op->o_req_dn = dn; + if ( op->o_req_ndn.bv_val == mndn.bv_val ) + 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 ); + struct berval mdn, mndn; + mdn = op->o_req_dn = op->o_bd->be_suffix[0]; + mndn = op->o_req_ndn = op->o_bd->be_nsuffix[0]; + 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; + if ( op->o_req_dn.bv_val == mdn.bv_val ) + op->o_req_dn = dn; + if ( op->o_req_ndn.bv_val == mndn.bv_val ) + 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 ) { @@ -361,7 +489,41 @@ glue_op_search ( Operation *op, SlapReply *rs ) case LDAP_X_CANNOT_CHAIN: #endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */ goto end_of_loop; - + + case LDAP_SUCCESS: + if ( get_pagedresults( op ) > SLAP_CONTROL_IGNORED ) { + PagedResultsState *ps = op->o_pagedresults_state; + + /* Assume this backend can be forgotten now */ + op->o_conn->c_pagedresults_state.ps_be = NULL; + + /* If we have a full page, exit the loop. We may + * need to remember this backend so we can continue + * from here on a subsequent request. + */ + if ( rs->sr_nentries >= ps->ps_size ) { + /* Don't bother to remember the first backend. + * Only remember the last one if there's more state left. + */ + if ( op->o_bd != b0 && + ( op->o_conn->c_pagedresults_state.ps_cookie || + op->o_bd != gi->gi_n[0].gn_be )) + op->o_conn->c_pagedresults_state.ps_be = op->o_bd; + goto end_of_loop; + } + + /* This backend has run out of entries, but more responses + * can fit in the page. Fake a reset of the state so the + * next backend will start up properly. Only back-[bh]db + * and back-sql look at this state info. + */ + if ( ps->ps_cookieval.bv_len == sizeof( PagedResultsCookie )) { + ps->ps_cookie = 0; + memset( ps->ps_cookieval.bv_val, 0, + sizeof( PagedResultsCookie )); + } + } + default: break; } @@ -369,8 +531,7 @@ glue_op_search ( Operation *op, SlapReply *rs ) end_of_loop:; op->ors_scope = scope0; op->ors_tlimit = tlimit0; - op->o_req_dn = dn; - op->o_req_ndn = ndn; + op->o_time = starttime; break; } @@ -381,6 +542,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 ); } @@ -391,6 +553,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; } @@ -423,7 +593,7 @@ glue_tool_entry_close ( { int rc = 0; - if (glueBack) { + if (glueBack && glueBack != GLUEBACK_DONE) { if (!glueBack->be_entry_close) return 0; rc = glueBack->be_entry_close (glueBack); @@ -456,6 +626,7 @@ glue_open ( glueinfo *gi = on->on_bi.bi_private; static int glueOpened = 0; int i, j, same, bsame = 0, rc = 0; + ConfigReply cr = {0}; if (glueOpened) return 0; @@ -486,7 +657,7 @@ glue_open ( gi->gi_n[i].gn_be->bd_info ); /* Let backend.c take care of the rest of startup */ if ( !rc ) - rc = backend_startup_one( gi->gi_n[i].gn_be ); + rc = backend_startup_one( gi->gi_n[i].gn_be, &cr ); if ( rc ) break; } if ( !rc && !bsame && on->on_info->oi_orig->bi_open ) @@ -515,6 +686,28 @@ glue_close ( return rc; } +static int +glue_entry_get_rw ( + Operation *op, + struct berval *dn, + ObjectClass *oc, + AttributeDescription *ad, + int rw, + Entry **e ) +{ + int rc; + BackendDB *b0 = op->o_bd; + op->o_bd = glue_back_select( b0, dn ); + + if ( op->o_bd->be_fetch ) { + rc = op->o_bd->be_fetch( op, dn, oc, ad, rw, e ); + } else { + rc = LDAP_UNWILLING_TO_PERFORM; + } + op->o_bd =b0; + return rc; +} + static int glue_entry_release_rw ( Operation *op, @@ -522,13 +715,10 @@ glue_entry_release_rw ( int rw ) { - BackendDB *b0, b2; + BackendDB *b0 = op->o_bd; int rc = -1; - b0 = op->o_bd; - b2 = *op->o_bd; - b2.bd_info = (BackendInfo *)glue_tool_inst( op->o_bd->bd_info ); - op->o_bd = glue_back_select (&b2, &e->e_nname); + op->o_bd = glue_back_select (b0, &e->e_nname); if ( op->o_bd->be_release ) { rc = op->o_bd->be_release( op, e, rw ); @@ -552,6 +742,7 @@ glue_tool_entry_first ( slap_overinst *on = glue_tool_inst( b0->bd_info ); glueinfo *gi = on->on_bi.bi_private; int i; + ID rc; /* If we're starting from scratch, start at the most general */ if (!glueBack) { @@ -571,7 +762,26 @@ glue_tool_entry_first ( glueBack->be_entry_open (glueBack, glueMode) != 0) return NOID; - return glueBack->be_entry_first (glueBack); + rc = glueBack->be_entry_first (glueBack); + while ( rc == NOID ) { + if ( glueBack && glueBack->be_entry_close ) + glueBack->be_entry_close (glueBack); + for (i=0; igi_nodes; i++) { + if (gi->gi_n[i].gn_be == glueBack) + break; + } + if (i == 0) { + glueBack = GLUEBACK_DONE; + break; + } else { + glueBack = gi->gi_n[i-1].gn_be; + rc = glue_tool_entry_first (b0); + if ( glueBack == GLUEBACK_DONE ) { + break; + } + } + } + return rc; } static ID @@ -598,16 +808,62 @@ glue_tool_entry_next ( break; } if (i == 0) { - glueBack = NULL; + glueBack = GLUEBACK_DONE; break; } else { glueBack = gi->gi_n[i-1].gn_be; rc = glue_tool_entry_first (b0); + if ( glueBack == GLUEBACK_DONE ) { + break; + } } } return rc; } +static ID +glue_tool_dn2id_get ( + BackendDB *b0, + struct berval *dn +) +{ + BackendDB *be, b2; + int rc = -1; + + b2 = *b0; + b2.bd_info = (BackendInfo *)glue_tool_inst( b0->bd_info ); + be = glue_back_select (&b2, dn); + if ( be == &b2 ) be = &toolDB; + + if (!be->be_dn2id_get) + return NOID; + + if (!glueBack) { + if ( be->be_entry_open ) { + rc = be->be_entry_open (be, glueMode); + } + if (rc != 0) { + return NOID; + } + } else if (be != glueBack) { + /* If this entry belongs in a different branch than the + * previous one, close the current database and open the + * new one. + */ + if ( glueBack->be_entry_close ) { + glueBack->be_entry_close (glueBack); + } + if ( be->be_entry_open ) { + rc = be->be_entry_open (be, glueMode); + } + if (rc != 0) { + return NOID; + } + } + glueBack = be; + return be->be_dn2id_get (be, dn); +} + static Entry * glue_tool_entry_get ( BackendDB *b0, @@ -664,16 +920,30 @@ glue_tool_entry_put ( return be->be_entry_put (be, e, text); } +static ID +glue_tool_entry_modify ( + BackendDB *b0, + Entry *e, + struct berval *text +) +{ + if (!glueBack || !glueBack->be_entry_modify) + return NOID; + + return glueBack->be_entry_modify (glueBack, e, text); +} + static int glue_tool_entry_reindex ( BackendDB *b0, - ID id + ID id, + AttributeDescription **adv ) { if (!glueBack || !glueBack->be_entry_reindex) return -1; - return glueBack->be_entry_reindex (glueBack, id); + return glueBack->be_entry_reindex (glueBack, id, adv); } static int @@ -697,9 +967,19 @@ glue_tool_sync ( return 0; } +typedef struct glue_Addrec { + struct glue_Addrec *ga_next; + BackendDB *ga_be; +} glue_Addrec; + +/* List of added subordinates */ +static glue_Addrec *ga_list; +static int ga_adding; + static int glue_db_init( - BackendDB *be + BackendDB *be, + ConfigReply *cr ) { slap_overinst *on = (slap_overinst *)be->bd_info; @@ -707,6 +987,13 @@ glue_db_init( 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 ); @@ -717,8 +1004,6 @@ glue_db_init( oi->oi_bi.bi_open = glue_open; oi->oi_bi.bi_close = glue_close; - oi->oi_bi.bi_entry_release_rw = glue_entry_release_rw; - /* 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; @@ -730,26 +1015,31 @@ glue_db_init( 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_dn2id_get ) + oi->oi_bi.bi_tool_dn2id_get = glue_tool_dn2id_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_entry_modify ) + oi->oi_bi.bi_tool_entry_modify = glue_tool_entry_modify; 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; - oi->oi_bi.bi_tool_id2entry_get = 0; - oi->oi_bi.bi_tool_entry_modify = 0; - SLAP_DBFLAGS( be ) |= SLAP_DBFLAG_GLUE_INSTANCE; + if ( ga_list ) { + be->bd_info = (BackendInfo *)oi; + glue_sub_attach( 1 ); + } + return 0; } static int glue_db_destroy ( - BackendDB *be + BackendDB *be, + ConfigReply *cr ) { slap_overinst *on = (slap_overinst *)be->bd_info; @@ -761,7 +1051,8 @@ glue_db_destroy ( static int glue_db_close( - BackendDB *be + BackendDB *be, + ConfigReply *cr ) { slap_overinst *on = (slap_overinst *)be->bd_info; @@ -816,21 +1107,19 @@ glue_sub_del( BackendDB *b0 ) return rc; } -typedef struct glue_Addrec { - struct glue_Addrec *ga_next; - BackendDB *ga_be; -} glue_Addrec; - -/* List of added subordinates */ -static glue_Addrec *ga_list; /* Attach all the subordinate backends to their superior */ int -glue_sub_attach() +glue_sub_attach( int online ) { glue_Addrec *ga, *gnext = NULL; int rc = 0; + if ( ga_adding ) + return 0; + + ga_adding = 1; + /* For all the subordinate backends */ for ( ga=ga_list; ga != NULL; ga = gnext ) { BackendDB *be; @@ -851,7 +1140,7 @@ glue_sub_attach() /* If it's not already configured, set up the overlay */ if ( !SLAP_GLUE_INSTANCE( be )) { - rc = overlay_config( be, glue.on_bi.bi_type ); + rc = overlay_config( be, glue.on_bi.bi_type, -1, NULL, NULL); if ( rc ) break; } @@ -870,11 +1159,20 @@ glue_sub_attach() &gi->gi_n[gi->gi_nodes].gn_pdn ); gi->gi_nodes++; on->on_bi.bi_private = gi; + ga->ga_be->be_flags |= SLAP_DBFLAG_GLUE_LINKED; break; } if ( !be ) { Debug( LDAP_DEBUG_ANY, "glue: no superior found for sub %s!\n", ga->ga_be->be_suffix[0].bv_val, 0, 0 ); + /* allow this for now, assume a superior will + * be added later + */ + if ( online ) { + rc = 0; + gnext = ga_list; + break; + } rc = LDAP_NO_SUCH_OBJECT; } ch_free( ga ); @@ -883,6 +1181,8 @@ glue_sub_attach() ga_list = gnext; + ga_adding = 0; + return rc; } @@ -892,6 +1192,12 @@ 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; @@ -902,7 +1208,7 @@ glue_sub_add( BackendDB *be, int advert, int online ) ga_list = ga; if ( online ) - rc = glue_sub_attach(); + rc = glue_sub_attach( online ); return rc; } @@ -921,9 +1227,14 @@ glue_sub_init() glue.on_bi.bi_op_modrdn = glue_op_func; glue.on_bi.bi_op_add = glue_op_func; glue.on_bi.bi_op_delete = glue_op_func; + glue.on_bi.bi_extended = glue_op_func; glue.on_bi.bi_chk_referrals = glue_chk_referrals; glue.on_bi.bi_chk_controls = glue_chk_controls; + glue.on_bi.bi_entry_get_rw = glue_entry_get_rw; + glue.on_bi.bi_entry_release_rw = glue_entry_release_rw; + + glue.on_response = glue_response; return overlay_register( &glue ); }