X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Fbackglue.c;h=b2665549b07810dccf4057f2985b9b8d419a6c56;hb=27cb98d28d60b1f258ea12852b22bfdfec6380f6;hp=cd2363ee97221ccaeffe008d29a58461d284739a;hpb=abd9be4def262989fda50137a75b2cb34868ab2b;p=openldap diff --git a/servers/slapd/backglue.c b/servers/slapd/backglue.c index cd2363ee97..b2665549b0 100644 --- a/servers/slapd/backglue.c +++ b/servers/slapd/backglue.c @@ -1,7 +1,7 @@ /* backglue.c - backend glue routines */ /* $OpenLDAP$ */ /* - * Copyright 2001 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 2001-2002 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ @@ -10,14 +10,12 @@ * All of the glued backends must share a common suffix. E.g., you * can glue o=foo and ou=bar,o=foo but you can't glue o=foo and o=bar. * - * The only configuration items that are needed for this backend are - * the suffixes, and they should be identical to suffixes of other - * backends that are being configured. The suffixes must be listed - * in order from longest to shortest, (most-specific to least-specific) - * in order for the selection to work. Every backend that is being glued - * must be fully configured as usual. + * This uses the backend structures and routines extensively, but is + * not an actual backend of its own. To use it you must add a "subordinate" + * keyword to the configuration of other backends. Subordinates will + * automatically be connected to their parent backend. * - * The purpose of this backend is to allow you to split a single database + * The purpose of these functions is to allow you to split a single database * into pieces (for load balancing purposes, whatever) but still be able * to treat it as a single database after it's been split. As such, each * of the glued backends should have identical rootdn and rootpw. @@ -38,14 +36,18 @@ typedef struct gluenode { BackendDB *be; - char *pdn; + struct berval pdn; } gluenode; typedef struct glueinfo { + BackendDB *be; int nodes; gluenode n[1]; } glueinfo; +static int glueMode; +static BackendDB *glueBack; + /* Just like select_backend, but only for our backends */ static BackendDB * glue_back_select ( @@ -54,134 +56,111 @@ glue_back_select ( ) { glueinfo *gi = (glueinfo *) be->be_private; + struct berval bv; int i; - for (i = 0; be->be_nsuffix[i]; i++) { - if (dn_issuffix (dn, be->be_nsuffix[i]->bv_val)) + bv.bv_len = strlen(dn); + bv.bv_val = (char *) dn; + + for (i = 0; inodes; i++) { + if (dnIsSuffix(&bv, &gi->n[i].be->be_nsuffix[0])) { return gi->n[i].be; + } } return NULL; } +/* This function will only be called in tool mode */ static int -glue_back_db_open ( - BackendDB *be +glue_back_open ( + BackendInfo *bi ) { - glueinfo *gi; - int i, j, k; - int ok; - - /* - * Done already? - */ - if (be->be_private) - return 0; + int rc = 0; + static int glueOpened = 0; - for (i = 0; be->be_nsuffix[i]; i++); + if (glueOpened) return 0; - gi = (struct glueinfo *) ch_calloc (1, sizeof (glueinfo) + - (i-1) * sizeof (gluenode) ); + glueOpened = 1; - be->be_private = gi; + /* If we were invoked in tool mode, open all the underlying backends */ + if (slapMode & SLAP_TOOL_MODE) { + rc = backend_startup (NULL); + } /* other case is impossible */ + return rc; +} - if (!gi) - return 1; +/* This function will only be called in tool mode */ +static int +glue_back_close ( + BackendInfo *bi +) +{ + static int glueClosed = 0; + int rc = 0; - gi->nodes = i; - be->be_glueflags = SLAP_GLUE_INSTANCE; + if (glueClosed) return 0; - /* - * For each of our suffixes, find the real backend that handles this - * suffix. - */ - for (i = 0; be->be_nsuffix[i]; i++) { - for (j = 0; j < nbackends; j++) { - if (be == &backends[j]) - continue; - ok = 0; - for (k = 0; backends[j].be_nsuffix && - backends[j].be_nsuffix[k]; k++) { - if (be->be_nsuffix[i]->bv_len != - backends[j].be_nsuffix[k]->bv_len) - continue; - if (!strcmp (backends[j].be_nsuffix[k]->bv_val, - be->be_nsuffix[i]->bv_val)) { - ok = 1; - break; - } - } - if (ok) { - gi->n[i].be = &backends[j]; - gi->n[i].pdn = dn_parent (NULL, - be->be_nsuffix[i]->bv_val); - if (i < gi->nodes - 1) - gi->n[i].be->be_glueflags = - SLAP_GLUE_SUBORDINATE; - break; - } - } - } + glueClosed = 1; - /* If we were invoked in tool mode, open all the underlying backends */ if (slapMode & SLAP_TOOL_MODE) { - for (i = 0; be->be_nsuffix[i]; i++) { - backend_startup (gi->n[i].be); - } + rc = backend_shutdown (NULL); } - return 0; + return rc; } static int -glue_back_db_close ( +glue_back_db_open ( BackendDB *be ) { - glueinfo *gi = (glueinfo *) be->be_private; + glueinfo *gi = (glueinfo *)be->be_private; + static int glueOpened = 0; + int rc = 0; - if (slapMode & SLAP_TOOL_MODE) { - int i; - for (i = 0; be->be_nsuffix[i]; i++) { - backend_shutdown (gi->n[i].be); - } - } - return 0; + if (glueOpened) return 0; + + glueOpened = 1; + + gi->be->be_acl = be->be_acl; + + if (gi->be->bd_info->bi_db_open) + rc = gi->be->bd_info->bi_db_open(gi->be); + + return rc; } -int -glue_back_db_destroy ( + +static int +glue_back_db_close ( BackendDB *be ) { - free (be->be_private); + glueinfo *gi = (glueinfo *)be->be_private; + static int glueClosed = 0; + + if (glueClosed) return 0; + + glueClosed = 1; + + /* Close the master */ + if (gi->be->bd_info->bi_db_close) + gi->be->bd_info->bi_db_close( gi->be ); + return 0; } -int -glue_back_bind ( - BackendDB *b0, - Connection *conn, - Operation *op, - const char *dn, - const char *ndn, - int method, - struct berval *cred, - char **edn +static int +glue_back_db_destroy ( + BackendDB *be ) { - BackendDB *be; - int rc; - - be = glue_back_select (b0, ndn); + glueinfo *gi = (glueinfo *)be->be_private; - if (be && be->be_bind) { - conn->c_authz_backend = be; - rc = be->be_bind (be, conn, op, dn, ndn, method, cred, edn); - } else { - rc = LDAP_UNWILLING_TO_PERFORM; - send_ldap_result (conn, op, rc, NULL, "No bind target found", - NULL, NULL); - } - return rc; + if (gi->be->bd_info->bi_db_destroy) + gi->be->bd_info->bi_db_destroy( gi->be ); + free (gi->be); + free (gi); + return 0; } typedef struct glue_state { @@ -189,9 +168,12 @@ typedef struct glue_state { int nentries; int matchlen; char *matched; + int nrefs; + BerVarray refs; + slap_callback *prevcb; } glue_state; -void +static void glue_back_response ( Connection *conn, Operation *op, @@ -200,14 +182,14 @@ glue_back_response ( ber_int_t err, const char *matched, const char *text, - struct berval **ref, + BerVarray ref, const char *resoid, struct berval *resdata, struct berval *sasldata, LDAPControl **ctrls ) { - glue_state *gs = op->o_glue; + glue_state *gs = op->o_callback->sc_private; if (err == LDAP_SUCCESS || gs->err != LDAP_SUCCESS) gs->err = err; @@ -225,58 +207,110 @@ glue_back_response ( gs->matchlen = len; } } + if (ref) { + int i, j, k; + BerVarray new; + + for (i=0; ref[i].bv_val; i++); + + j = gs->nrefs; + if (!j) { + new = ch_malloc ((i+1)*sizeof(struct berval)); + } else { + new = ch_realloc(gs->refs, + (j+i+1)*sizeof(struct berval)); + } + for (k=0; knrefs = j; + gs->refs = new; + } } -void +static void glue_back_sresult ( Connection *c, Operation *op, ber_int_t err, const char *matched, const char *text, - struct berval **refs, + BerVarray refs, LDAPControl **ctrls, int nentries ) { - glue_state *gs = op->o_glue; + glue_state *gs = op->o_callback->sc_private; gs->nentries += nentries; glue_back_response (c, op, 0, 0, err, matched, text, refs, NULL, NULL, NULL, ctrls); } -int +static int +glue_back_sendentry ( + BackendDB *be, + Connection *c, + Operation *op, + Entry *e, + AttributeName *an, + int ao, + LDAPControl **ctrls +) +{ + slap_callback *tmp = op->o_callback; + glue_state *gs = tmp->sc_private; + int rc; + + op->o_callback = gs->prevcb; + if (op->o_callback && op->o_callback->sc_sendentry) { + rc = op->o_callback->sc_sendentry(be, c, op, e, an, ao, ctrls); + } else { + rc = send_search_entry(be, c, op, e, an, ao, ctrls); + } + op->o_callback = tmp; + return rc; +} + +static int glue_back_search ( BackendDB *b0, Connection *conn, Operation *op, - const char *dn, - const char *ndn, + struct berval *dn, + struct berval *ndn, int scope, int deref, int slimit, int tlimit, Filter *filter, - const char *filterstr, - char **attrs, + struct berval *filterstr, + AttributeName *attrs, int attrsonly ) { - glueinfo *gi = (glueinfo *) b0->be_private; + glueinfo *gi = (glueinfo *)b0->be_private; BackendDB *be; - int i, rc, t2limit = 0, s2limit = 0; + int i, rc = 0, t2limit = 0, s2limit = 0; long stoptime = 0; - glue_state gs = - {0}; + glue_state gs = {0}; + slap_callback cb; + cb.sc_response = glue_back_response; + cb.sc_sresult = glue_back_sresult; + cb.sc_sendentry = glue_back_sendentry; + cb.sc_private = &gs; - if (tlimit) + gs.prevcb = op->o_callback; + + if (tlimit) { stoptime = slap_get_time () + tlimit; + } switch (scope) { case LDAP_SCOPE_BASE: - be = glue_back_select (b0, ndn); + be = glue_back_select (b0, ndn->bv_val); if (be && be->be_search) { rc = be->be_search (be, conn, op, dn, ndn, scope, @@ -290,193 +324,192 @@ glue_back_search ( return rc; case LDAP_SCOPE_ONELEVEL: - op->o_glue = &gs; - op->o_sresult = glue_back_sresult; - op->o_response = glue_back_response; + case LDAP_SCOPE_SUBTREE: + op->o_callback = &cb; + rc = gs.err = LDAP_UNWILLING_TO_PERFORM; /* * Execute in reverse order, most general first */ for (i = gi->nodes-1; i >= 0; i--) { - if (!gi->n[i].be->be_search) + if (!gi->n[i].be || !gi->n[i].be->be_search) continue; if (tlimit) { t2limit = stoptime - slap_get_time (); - if (t2limit <= 0) + if (t2limit <= 0) { + rc = gs.err = LDAP_TIMELIMIT_EXCEEDED; break; + } } if (slimit) { s2limit = slimit - gs.nentries; - if (s2limit <= 0) + if (s2limit <= 0) { + rc = gs.err = LDAP_SIZELIMIT_EXCEEDED; break; + } } + rc = 0; /* * check for abandon */ - ldap_pvt_thread_mutex_lock (&op->o_abandonmutex); - rc = op->o_abandon; - ldap_pvt_thread_mutex_unlock (&op->o_abandonmutex); - if (rc) { - rc = 0; + if (op->o_abandon) { goto done; } - if (!strcmp (gi->n[i].pdn, ndn)) { - be = gi->n[i].be; - rc = be->be_search (be, conn, op, - b0->be_suffix[i], - b0->be_nsuffix[i]->bv_val, - LDAP_SCOPE_BASE, deref, - s2limit, t2limit, filter, filterstr, - attrs, attrsonly); - } else if (dn_issuffix (ndn, b0->be_nsuffix[i]->bv_val)) { - be = gi->n[i].be; + be = gi->n[i].be; + if (scope == LDAP_SCOPE_ONELEVEL && + dn_match(&gi->n[i].pdn, ndn)) { rc = be->be_search (be, conn, op, - dn, ndn, scope, deref, + &be->be_suffix[0], &be->be_nsuffix[0], + LDAP_SCOPE_BASE, deref, s2limit, t2limit, filter, filterstr, - attrs, attrsonly); - } - } - break; + attrs, attrsonly); - case LDAP_SCOPE_SUBTREE: - op->o_glue = &gs; - op->o_sresult = glue_back_sresult; - op->o_response = glue_back_response; - - /* - * Execute in reverse order, most general first - */ - for (i = gi->nodes-1; i >= 0; i--) { - if (!gi->n[i].be->be_search) - continue; - if (tlimit) { - t2limit = stoptime - slap_get_time (); - if (t2limit <= 0) - break; - } - if (slimit) { - s2limit = slimit - gs.nentries; - if (s2limit <= 0) - break; - } - /* - * check for abandon - */ - ldap_pvt_thread_mutex_lock (&op->o_abandonmutex); - rc = op->o_abandon; - ldap_pvt_thread_mutex_unlock (&op->o_abandonmutex); - if (rc) { - rc = 0; - goto done; - } - if (dn_issuffix (ndn, b0->be_nsuffix[i]->bv_val)) { - be = gi->n[i].be; + } else if (scope == LDAP_SCOPE_SUBTREE && + dnIsSuffix(&be->be_nsuffix[0], ndn)) { rc = be->be_search (be, conn, op, - dn, ndn, scope, deref, + &be->be_suffix[0], &be->be_nsuffix[0], + scope, deref, s2limit, t2limit, filter, filterstr, - attrs, attrsonly); - } else if (dn_issuffix (b0->be_nsuffix[i]->bv_val, ndn)) { - be = gi->n[i].be; - rc = be->be_search (be, conn, op, - b0->be_suffix[i], - b0->be_nsuffix[i]->bv_val, - scope, deref, + attrs, attrsonly); + + } else if (dnIsSuffix(ndn, &be->be_nsuffix[0])) { + rc = be->be_search (be, conn, op, dn, ndn, + scope, deref, s2limit, t2limit, filter, filterstr, - attrs, attrsonly); + attrs, attrsonly); } } break; } - op->o_sresult = NULL; - op->o_response = NULL; - op->o_glue = NULL; + op->o_callback = gs.prevcb; - send_search_result (conn, op, gs.err, gs.matched, NULL, NULL, - NULL, gs.nentries); - done: + send_search_result (conn, op, gs.err, gs.matched, NULL, + gs.refs, NULL, gs.nentries); + +done: if (gs.matched) free (gs.matched); + if (gs.refs) + ber_bvarray_free(gs.refs); return rc; } -int +static int +glue_back_bind ( + BackendDB *b0, + Connection *conn, + Operation *op, + struct berval *dn, + struct berval *ndn, + int method, + struct berval *cred, + struct berval *edn +) +{ + BackendDB *be; + int rc; + + be = glue_back_select (b0, ndn->bv_val); + + if (be && be->be_bind) { + rc = be->be_bind (be, conn, op, dn, ndn, method, cred, edn); + + if( rc == LDAP_SUCCESS ) { + ldap_pvt_thread_mutex_lock( &conn->c_mutex ); + if( conn->c_authz_backend == NULL ) { + conn->c_authz_backend = be; + } + ldap_pvt_thread_mutex_unlock( &conn->c_mutex ); + } + } else { + rc = LDAP_UNWILLING_TO_PERFORM; + send_ldap_result (conn, op, rc, NULL, "No bind target found", + NULL, NULL); + } + return rc; +} + +static int glue_back_compare ( BackendDB *b0, Connection *conn, Operation *op, - const char *dn, - const char *ndn, + struct berval *dn, + struct berval *ndn, AttributeAssertion *ava ) { BackendDB *be; int rc; - be = glue_back_select (b0, ndn); + be = glue_back_select (b0, ndn->bv_val); if (be && be->be_compare) { rc = be->be_compare (be, conn, op, dn, ndn, ava); } else { rc = LDAP_UNWILLING_TO_PERFORM; send_ldap_result (conn, op, rc, NULL, "No compare target found", - NULL, NULL); + NULL, NULL); } return rc; } -int +static int glue_back_modify ( BackendDB *b0, Connection *conn, Operation *op, - const char *dn, - const char *ndn, + struct berval *dn, + struct berval *ndn, Modifications *mod ) { BackendDB *be; int rc; - be = glue_back_select (b0, ndn); + be = glue_back_select (b0, ndn->bv_val); if (be && be->be_modify) { rc = be->be_modify (be, conn, op, dn, ndn, mod); } else { rc = LDAP_UNWILLING_TO_PERFORM; - send_ldap_result (conn, op, rc, NULL, "No modify target found", - NULL, NULL); + send_ldap_result (conn, op, rc, NULL, + "No modify target found", NULL, NULL); } return rc; } -int +static int glue_back_modrdn ( BackendDB *b0, Connection *conn, Operation *op, - const char *dn, - const char *ndn, - const char *newrdn, + struct berval *dn, + struct berval *ndn, + struct berval *newrdn, + struct berval *nnewrdn, int del, - const char *newsup + struct berval *newsup, + struct berval *nnewsup ) { BackendDB *be; int rc; - be = glue_back_select (b0, ndn); + be = glue_back_select (b0, ndn->bv_val); if (be && be->be_modrdn) { - rc = be->be_modrdn (be, conn, op, dn, ndn, newrdn, del, newsup); + rc = be->be_modrdn (be, conn, op, dn, ndn, + newrdn, nnewrdn, del, newsup, nnewsup ); } else { rc = LDAP_UNWILLING_TO_PERFORM; - send_ldap_result (conn, op, rc, NULL, "No modrdn target found", - NULL, NULL); + send_ldap_result (conn, op, rc, NULL, + "No modrdn target found", NULL, NULL); } return rc; } -int +static int glue_back_add ( BackendDB *b0, Connection *conn, @@ -499,19 +532,19 @@ glue_back_add ( return rc; } -int +static int glue_back_delete ( BackendDB *b0, Connection *conn, Operation *op, - const char *dn, - const char *ndn + struct berval *dn, + struct berval *ndn ) { BackendDB *be; int rc; - be = glue_back_select (b0, ndn); + be = glue_back_select (b0, ndn->bv_val); if (be && be->be_delete) { rc = be->be_delete (be, conn, op, dn, ndn); @@ -523,7 +556,7 @@ glue_back_delete ( return rc; } -int +static int glue_back_release_rw ( BackendDB *b0, Connection *conn, @@ -546,14 +579,14 @@ glue_back_release_rw ( return rc; } -int +static int glue_back_group ( BackendDB *b0, Connection *conn, Operation *op, Entry *target, - const char *ndn, - const char *ondn, + struct berval *ndn, + struct berval *ondn, ObjectClass *oc, AttributeDescription * ad ) @@ -561,7 +594,7 @@ glue_back_group ( BackendDB *be; int rc; - be = glue_back_select (b0, ndn); + be = glue_back_select (b0, ndn->bv_val); if (be && be->be_group) { rc = be->be_group (be, conn, op, target, ndn, ondn, oc, ad); @@ -571,21 +604,21 @@ glue_back_group ( return rc; } -int +static int glue_back_attribute ( BackendDB *b0, Connection *conn, Operation *op, Entry *target, - const char *ndn, + struct berval *ndn, AttributeDescription *ad, - struct berval ***vals + BerVarray *vals ) { BackendDB *be; int rc; - be = glue_back_select (b0, ndn); + be = glue_back_select (b0, ndn->bv_val); if (be && be->be_attribute) { rc = be->be_attribute (be, conn, op, target, ndn, ad, vals); @@ -595,20 +628,20 @@ glue_back_attribute ( return rc; } -int +static int glue_back_referrals ( BackendDB *b0, Connection *conn, Operation *op, - const char *dn, - const char *ndn, + struct berval *dn, + struct berval *ndn, const char **text ) { BackendDB *be; int rc; - be = glue_back_select (b0, ndn); + be = glue_back_select (b0, ndn->bv_val); if (be && be->be_chk_referrals) { rc = be->be_chk_referrals (be, conn, op, dn, ndn, text); @@ -618,10 +651,7 @@ glue_back_referrals ( return rc; } -static int glueMode; -static int glueBack; - -int +static int glue_tool_entry_open ( BackendDB *b0, int mode @@ -632,30 +662,27 @@ glue_tool_entry_open ( */ glueMode = mode; - glueBack = -1; + glueBack = NULL; return 0; } -int +static int glue_tool_entry_close ( BackendDB *b0 ) { - glueinfo *gi = (glueinfo *) b0->be_private; - int i, rc = 0; + int rc = 0; - i = glueBack; - if (i >= 0) { - if (!gi->n[i].be->be_entry_close) + if (glueBack) { + if (!glueBack->be_entry_close) return 0; - rc = gi->n[i].be->be_entry_close (gi->n[i].be); - glueBack = -1; + rc = glueBack->be_entry_close (glueBack); } return rc; } -ID +static ID glue_tool_entry_first ( BackendDB *b0 ) @@ -664,112 +691,111 @@ glue_tool_entry_first ( int i; /* If we're starting from scratch, start at the most general */ - if (glueBack == -1) { + if (!glueBack) { for (i = gi->nodes-1; i >= 0; i--) { if (gi->n[i].be->be_entry_open && - gi->n[i].be->be_entry_first) + gi->n[i].be->be_entry_first) { + glueBack = gi->n[i].be; break; + } } - } else { - i = glueBack; + } - if (gi->n[i].be->be_entry_open (gi->n[i].be, glueMode) != 0) + if (!glueBack || glueBack->be_entry_open (glueBack, glueMode) != 0) return NOID; - glueBack = i; - return gi->n[i].be->be_entry_first (gi->n[i].be); + return glueBack->be_entry_first (glueBack); } -ID +static ID glue_tool_entry_next ( BackendDB *b0 ) { glueinfo *gi = (glueinfo *) b0->be_private; - int i, rc; + int i; + ID rc; + + if (!glueBack || !glueBack->be_entry_next) + return NOID; - i = glueBack; - rc = gi->n[i].be->be_entry_next (gi->n[i].be); + rc = glueBack->be_entry_next (glueBack); /* If we ran out of entries in one database, move on to the next */ if (rc == NOID) { - gi->n[i].be->be_entry_close (gi->n[i].be); - i--; - glueBack = i; - if (i < 0) + glueBack->be_entry_close (glueBack); + for (i=0; inodes; i++) { + if (gi->n[i].be == glueBack) + break; + } + if (i == 0) { + glueBack = NULL; rc = NOID; - else + } else { + glueBack = gi->n[i-1].be; rc = glue_tool_entry_first (b0); + } } return rc; } -Entry * +static Entry * glue_tool_entry_get ( BackendDB *b0, ID id ) { - glueinfo *gi = (glueinfo *) b0->be_private; - int i = glueBack; + if (!glueBack || !glueBack->be_entry_get) + return NULL; - return gi->n[i].be->be_entry_get (gi->n[i].be, id); + return glueBack->be_entry_get (glueBack, id); } -ID +static ID glue_tool_entry_put ( BackendDB *b0, - Entry *e + Entry *e, + struct berval *text ) { - glueinfo *gi = (glueinfo *) b0->be_private; BackendDB *be; - int i, rc; + int rc; be = glue_back_select (b0, e->e_ndn); if (!be->be_entry_put) return NOID; - i = glueBack; - if (i < 0) { + if (!glueBack) { rc = be->be_entry_open (be, glueMode); if (rc != 0) return NOID; - glueBack = i; - } else if (be != gi->n[i].be) { + } 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. */ - gi->n[i].be->be_entry_close (gi->n[i].be); - glueBack = -1; - for (i = 0; b0->be_nsuffix[i]; i++) - if (gi->n[i].be == be) - break; + glueBack->be_entry_close (glueBack); rc = be->be_entry_open (be, glueMode); if (rc != 0) return NOID; - glueBack = i; } - return be->be_entry_put (be, e); + glueBack = be; + return be->be_entry_put (be, e, text); } -int +static int glue_tool_entry_reindex ( BackendDB *b0, ID id ) { - glueinfo *gi = (glueinfo *) b0->be_private; - int i = glueBack; - - if (!gi->n[i].be->be_entry_reindex) + if (!glueBack || !glueBack->be_entry_reindex) return -1; - return gi->n[i].be->be_entry_reindex (gi->n[i].be, id); + return glueBack->be_entry_reindex (glueBack, id); } -int +static int glue_tool_sync ( BackendDB *b0 ) @@ -778,59 +804,112 @@ glue_tool_sync ( int i; /* just sync everyone */ - for (i = 0; b0->be_nsuffix[i]; i++) + for (i = 0; inodes; i++) if (gi->n[i].be->be_sync) gi->n[i].be->be_sync (gi->n[i].be); return 0; } int -glue_back_initialize ( - BackendInfo *bi -) +glue_sub_init( ) { - bi->bi_open = 0; - bi->bi_config = 0; - bi->bi_close = 0; - bi->bi_destroy = 0; - - bi->bi_db_init = 0; - bi->bi_db_config = 0; - bi->bi_db_open = glue_back_db_open; - bi->bi_db_close = glue_back_db_close; - bi->bi_db_destroy = glue_back_db_destroy; - - bi->bi_op_bind = glue_back_bind; - bi->bi_op_unbind = 0; - bi->bi_op_search = glue_back_search; - bi->bi_op_compare = glue_back_compare; - bi->bi_op_modify = glue_back_modify; - bi->bi_op_modrdn = glue_back_modrdn; - bi->bi_op_add = glue_back_add; - bi->bi_op_delete = glue_back_delete; - bi->bi_op_abandon = 0; - - bi->bi_extended = 0; - - bi->bi_entry_release_rw = glue_back_release_rw; - bi->bi_acl_group = glue_back_group; - bi->bi_acl_attribute = glue_back_attribute; - bi->bi_chk_referrals = glue_back_referrals; - - /* - * hooks for slap tools - */ - bi->bi_tool_entry_open = glue_tool_entry_open; - bi->bi_tool_entry_close = glue_tool_entry_close; - bi->bi_tool_entry_first = glue_tool_entry_first; - bi->bi_tool_entry_next = glue_tool_entry_next; - bi->bi_tool_entry_get = glue_tool_entry_get; - bi->bi_tool_entry_put = glue_tool_entry_put; - bi->bi_tool_entry_reindex = glue_tool_entry_reindex; - bi->bi_tool_sync = glue_tool_sync; - - bi->bi_connection_init = 0; - bi->bi_connection_destroy = 0; + int i, j; + int cont = num_subordinates; + BackendDB *b1, *be; + BackendInfo *bi = NULL; + glueinfo *gi; - return 0; + /* While there are subordinate backends, search backwards through the + * backends and connect them to their superior. + */ + for (i = nBackendDB - 1, b1=&backendDB[i]; cont && i>=0; b1--,i--) { + if (b1->be_flags & SLAP_BFLAG_GLUE_SUBORDINATE) { + /* The last database cannot be a subordinate of noone */ + if (i == nBackendDB - 1) { + b1->be_flags ^= SLAP_BFLAG_GLUE_SUBORDINATE; + } + continue; + } + gi = NULL; + for (j = i-1, be=&backendDB[j]; j>=0; be--,j--) { + if (!(be->be_flags & SLAP_BFLAG_GLUE_SUBORDINATE)) { + continue; + } + /* We will only link it once */ + if (be->be_flags & SLAP_BFLAG_GLUE_LINKED) { + continue; + } + if (!dnIsSuffix(&be->be_nsuffix[0], &b1->be_nsuffix[0])) { + continue; + } + cont--; + be->be_flags |= SLAP_BFLAG_GLUE_LINKED; + if (gi == NULL) { + /* We create a copy of the superior's be + * structure, pointing to all of its original + * information. Then we replace elements of + * the superior's info with our own. The copy + * is used whenever we have operations to pass + * down to the real database. + */ + b1->be_flags |= SLAP_BFLAG_GLUE_INSTANCE; + gi = (glueinfo *)ch_malloc(sizeof(glueinfo)); + gi->be = (BackendDB *)ch_malloc( + sizeof(BackendDB) + sizeof(BackendInfo)); + bi = (BackendInfo *)(gi->be+1); + *gi->be = *b1; + gi->nodes = 0; + *bi = *b1->bd_info; + bi->bi_open = glue_back_open; + bi->bi_close = glue_back_close; + bi->bi_db_open = glue_back_db_open; + bi->bi_db_close = glue_back_db_close; + bi->bi_db_destroy = glue_back_db_destroy; + + bi->bi_op_bind = glue_back_bind; + bi->bi_op_search = glue_back_search; + bi->bi_op_compare = glue_back_compare; + bi->bi_op_modify = glue_back_modify; + bi->bi_op_modrdn = glue_back_modrdn; + bi->bi_op_add = glue_back_add; + bi->bi_op_delete = glue_back_delete; + + bi->bi_entry_release_rw = glue_back_release_rw; + bi->bi_acl_group = glue_back_group; + bi->bi_acl_attribute = glue_back_attribute; + bi->bi_chk_referrals = glue_back_referrals; + + /* + * hooks for slap tools + */ + bi->bi_tool_entry_open = glue_tool_entry_open; + bi->bi_tool_entry_close = glue_tool_entry_close; + bi->bi_tool_entry_first = glue_tool_entry_first; + bi->bi_tool_entry_next = glue_tool_entry_next; + bi->bi_tool_entry_get = glue_tool_entry_get; + bi->bi_tool_entry_put = glue_tool_entry_put; + bi->bi_tool_entry_reindex = glue_tool_entry_reindex; + bi->bi_tool_sync = glue_tool_sync; + } else { + gi = (glueinfo *)ch_realloc(gi, + sizeof(glueinfo) + + gi->nodes * sizeof(gluenode)); + } + gi->n[gi->nodes].be = be; + dnParent( &be->be_nsuffix[0], &gi->n[gi->nodes].pdn ); + gi->nodes++; + } + if (gi) { + /* One more node for the master */ + gi = (glueinfo *)ch_realloc(gi, + sizeof(glueinfo) + gi->nodes * sizeof(gluenode)); + gi->n[gi->nodes].be = gi->be; + dnParent( &b1->be_nsuffix[0], &gi->n[gi->nodes].pdn ); + gi->nodes++; + b1->be_private = gi; + b1->bd_info = bi; + } + } + /* If there are any unresolved subordinates left, something is wrong */ + return cont; }