From: Howard Chu Date: Fri, 7 Dec 2001 12:38:25 +0000 (+0000) Subject: Some fixes for BDB_IDL_MULTI. Experimental back-hdb code. X-Git-Tag: LDBM_PRE_GIANT_RWLOCK~722 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=505a8693e60fa8b9853fc61b2e5dbd491a8e3368;p=openldap Some fixes for BDB_IDL_MULTI. Experimental back-hdb code. --- diff --git a/servers/slapd/back-bdb/back-bdb.h b/servers/slapd/back-bdb/back-bdb.h index d9b38e4399..1f7b3f2579 100644 --- a/servers/slapd/back-bdb/back-bdb.h +++ b/servers/slapd/back-bdb/back-bdb.h @@ -16,7 +16,8 @@ LDAP_BEGIN_DECL #define BDB_FILTER_INDICES 1 -#define BDB_IDL_MULTI 1 +/* #define BDB_IDL_MULTI 1 */ +/* #define BDB_HIER 1 */ #define DN_BASE_PREFIX SLAP_INDEX_EQUALITY_PREFIX #define DN_ONE_PREFIX '%' @@ -32,7 +33,11 @@ LDAP_BEGIN_DECL #define BDB_TXN_RETRIES 16 +#ifdef BDB_HIER +#define BDB_DBENV_HOME LDAP_RUNDIR LDAP_DIRSEP "openldap-hdb" +#else #define BDB_DBENV_HOME LDAP_RUNDIR LDAP_DIRSEP "openldap-bdb" +#endif #ifdef BDB_SUBDIRS #define BDB_TMP_SUBDIR LDAP_DIRSEP "tmp" @@ -42,7 +47,11 @@ LDAP_BEGIN_DECL #define BDB_SUFFIX ".bdb" #define BDB_ID2ENTRY 0 +#ifdef BDB_HIER +#define BDB_ID2PARENT 1 +#else #define BDB_DN2ID 1 +#endif #define BDB_NDB 2 /* The bdb on-disk entry format is pretty space-inefficient. Average @@ -50,7 +59,7 @@ LDAP_BEGIN_DECL * fit into a single database page, more is better. 64K is BDB's * upper bound. The same issues arise with IDLs in the index databases, * but it's nearly impossible to avoid overflows there. - * + * * When using BDB_IDL_MULTI, the IDL size is no longer an issue. Smaller * pages are better for concurrency. */ @@ -89,6 +98,14 @@ struct bdb_info { slap_mask_t bi_defaultmask; Avlnode *bi_attrs; +#ifdef BDB_HIER + Avlnode *bi_tree; + ldap_pvt_thread_rdwr_t bi_tree_rdwr; + void *bi_troot; + int bi_nrdns; + int bi_sufflen; + int bi_nsufflen; +#endif int bi_txn; int bi_txn_cp; @@ -106,7 +123,11 @@ struct bdb_info { }; #define bi_id2entry bi_databases[BDB_ID2ENTRY] +#ifdef BDB_HIER +#define bi_id2parent bi_databases[BDB_ID2PARENT] +#else #define bi_dn2id bi_databases[BDB_DN2ID] +#endif struct bdb_op_info { BackendDB* boi_bdb; diff --git a/servers/slapd/back-bdb/dbcache.c b/servers/slapd/back-bdb/dbcache.c index 3156408e41..9fefd7f287 100644 --- a/servers/slapd/back-bdb/dbcache.c +++ b/servers/slapd/back-bdb/dbcache.c @@ -70,7 +70,7 @@ bdb_db_cache( rc = db->bdi_db->set_pagesize( db->bdi_db, BDB_PAGESIZE ); #ifdef BDB_IDL_MULTI - rc = db->bdi_db->set_flags( db->bdi_db, DB_DUPSORT ); + rc = db->bdi_db->set_flags( db->bdi_db, DB_DUP | DB_DUPSORT ); rc = db->bdi_db->set_dup_compare( db->bdi_db, bdb_bt_compare ); #endif diff --git a/servers/slapd/back-bdb/dn2id.c b/servers/slapd/back-bdb/dn2id.c index 1021446c93..a40663cbae 100644 --- a/servers/slapd/back-bdb/dn2id.c +++ b/servers/slapd/back-bdb/dn2id.c @@ -13,6 +13,7 @@ #include "back-bdb.h" #include "idl.h" +#ifndef BDB_HIER int bdb_dn2id_add( BackendDB *be, @@ -73,7 +74,7 @@ bdb_dn2id_add( int i; ((char *)key.data)[0] = DN_SUBTREE_PREFIX; for( i=0; subtree[i] != NULL; i++ ) { - if (be_issuffix(be, subtree[i])) + if( be_issuffix( be, subtree[i] )) continue; key.size = strlen( subtree[i] ) + 2; AC_MEMCPY( &((char *)key.data)[1], @@ -391,3 +392,527 @@ bdb_dn2idl( ch_free( key.data ); return rc; } +#else /* BDB_HIER */ + +/* Experimental management routines for a hierarchically structured backend. + * + * Unsupported! Use at your own risk! + * + * Instead of a dn2id database, we use an id2parent database. Each entry in + * this database is a struct diskNode, containing the ID of the node's parent + * and the RDN of the node. + */ +typedef struct diskNode { + ID parent; + struct berval rdn; + struct berval nrdn; +} diskNode; + +/* In bdb_db_open() we call bdb_build_tree() which reads the entire id2parent + * database into memory (into an AVL tree). Next we iterate through each node + * of this tree, connecting each child to its parent. The nodes in this AVL + * tree are a struct idNode. The immediate (Onelevel) children of a node are + * referenced in the i_kids AVL tree. With this arrangement, there is no need + * to maintain the DN_ONE_PREFIX or DN_SUBTREE_PREFIX database keys. Note that + * the DN of an entry is constructed by walking up the list of i_parent + * pointers, so no full DN is stored on disk anywhere. This makes modrdn + * extremely efficient, even when operating on a populated subtree. + * + * The idNode tree is searched directly from the root when performing id to + * entry lookups. The tree is traversed using the i_kids subtrees when + * performing dn to id lookups. + */ +typedef struct idNode { + ID i_id; + struct idNode *i_parent; + diskNode *i_rdn; + Avlnode *i_kids; + ldap_pvt_thread_rdwr_t i_kids_rdwr; +} idNode; + +/* strcopy is like strcpy except it returns a pointer to the trailing NUL of + * the result string. This allows fast construction of catenated strings + * without the overhead of strlen/strcat. + */ +char * +bdb_strcopy( + char *a, + char *b +) +{ + if (!a || !b) + return a; + + while (*a++ = *b++) ; + return a-1; +} + +/* The main AVL tree is sorted in ID order. The i_kids AVL trees are + * sorted in lexical order. These are the various helper routines used + * for the searches and sorts. + */ +static int +node_find_cmp( + ID id, + idNode *n +) +{ + return id - n->i_id; +} + +static int +node_frdn_cmp( + char *nrdn, + idNode *n +) +{ + return strcmp(nrdn, n->i_rdn->nrdn.bv_val); +} + +static int +node_add_cmp( + idNode *a, + idNode *b +) +{ + return a->i_id - b->i_id; +} + +static int +node_rdn_cmp( + idNode *a, + idNode *b +) +{ + return strcmp(a->i_rdn->nrdn.bv_val, b->i_rdn->nrdn.bv_val); +} + +idNode * bdb_find_id_node( + ID id, + Avlnode *tree +) +{ + return avl_find(tree, (const void *)id, (AVL_CMP)node_find_cmp); +} + +idNode * bdb_find_rdn_node( + char *nrdn, + Avlnode *tree +) +{ + return avl_find(tree, (const void *)nrdn, (AVL_CMP)node_frdn_cmp); +} + +/* This function links a node into its parent's i_kids tree. */ +int bdb_insert_kid( + idNode *a, + Avlnode *tree +) +{ + int rc; + + if (a->i_rdn->parent == 0) + return 0; + a->i_parent = bdb_find_id_node(a->i_rdn->parent, tree); + if (!a->i_parent) + return -1; + ldap_pvt_thread_rdwr_wlock(&a->i_parent->i_kids_rdwr); + rc = avl_insert( &a->i_parent->i_kids, (caddr_t) a, + (AVL_CMP)node_rdn_cmp, (AVL_DUP) avl_dup_error ); + ldap_pvt_thread_rdwr_wunlock(&a->i_parent->i_kids_rdwr); + return rc; +} + +/* This function adds a node into the main AVL tree */ +idNode *bdb_add_node( + ID id, + char *d, + struct bdb_info *bdb +) +{ + idNode *node; + + node = (idNode *)ch_malloc(sizeof(idNode)); + node->i_id = id; + node->i_parent = NULL; + node->i_kids = NULL; + node->i_rdn = (diskNode *)d; + node->i_rdn->rdn.bv_val += (long)d; + node->i_rdn->nrdn.bv_val += (long)d; + ldap_pvt_thread_rdwr_init(&node->i_kids_rdwr); + avl_insert( &bdb->bi_tree, (caddr_t) node, + (AVL_CMP)node_add_cmp, (AVL_DUP) avl_dup_error ); + if (id == 1) + bdb->bi_troot = node; + return node; +} + +/* This function initializes the trees at startup time. */ +int bdb_build_tree( + Backend *be +) +{ + struct bdb_info *bdb = (struct bdb_info *) be->be_private; + int i, rc; + DBC *cursor; + DBT key, data; + ID id; + idNode *node; + char **rdns; + + bdb->bi_tree = NULL; + + rc = bdb->bi_id2parent->bdi_db->cursor( + bdb->bi_id2parent->bdi_db, NULL, &cursor, + bdb->bi_db_opflags ); + if( rc != 0 ) { + return NOID; + } + + /* When be_suffix is turned into struct berval or LDAPDN + * life will get a lot easier... Since no DNs live on disk, we + * need to operate on the be_suffix to fully qualify our DNs. + * We need to know how many components are in the suffix DN, + * so we can tell where the suffix ends and our nodes begin. + * + * Note that this code always uses be_suffix[0], so defining + * multiple suffixes for a single backend won't work! + */ + bdb->bi_sufflen = strlen(be->be_suffix[0]); + bdb->bi_nsufflen = strlen(be->be_nsuffix[0]); + + rdns = ldap_explode_dn(be->be_nsuffix[0], 0); + for (i=0; rdns[i]; i++); + bdb->bi_nrdns = i; + charray_free(rdns); + + DBTzero( &key ); + DBTzero( &data ); + key.data = (char *)&id; + key.ulen = sizeof( id ); + key.flags = DB_DBT_USERMEM; + data.flags = DB_DBT_MALLOC; + + while (cursor->c_get( cursor, &key, &data, DB_NEXT ) == 0) { + bdb_add_node( id, data.data, bdb ); + } + cursor->c_close( cursor ); + + rc = avl_apply(bdb->bi_tree, (AVL_APPLY)bdb_insert_kid, bdb->bi_tree, + -1, AVL_INORDER ); + + return rc; +} + +/* This function constructs a full DN for a given id. We really should + * be passing idNodes directly, to save some effort... + */ +int bdb_fix_dn( + BackendDB *be, + ID id, + Entry *e +) +{ + struct bdb_info *bdb = (struct bdb_info *) be->be_private; + idNode *n, *o; + int rlen, nrlen; + char *ptr, *nptr; + + ldap_pvt_thread_rdwr_rlock(&bdb->bi_tree_rdwr); + o = bdb_find_id_node(id, bdb->bi_tree); + rlen = bdb->bi_sufflen + 1; + nrlen = bdb->bi_nsufflen + 1; + for (n = o; n; n=n->i_parent) { + rlen += n->i_rdn->rdn.bv_len + 1; + nrlen += n->i_rdn->nrdn.bv_len + 1; + } + e->e_dn = ch_malloc(rlen + nrlen); + e->e_ndn = e->e_dn + rlen; + ptr = e->e_dn; + nptr = e->e_ndn; + for (n = o; n; n=n->i_parent) { + ptr = bdb_strcopy(ptr, n->i_rdn->rdn.bv_val); + *ptr++ = ','; + nptr = bdb_strcopy(nptr, n->i_rdn->nrdn.bv_val); + *nptr++ = ','; + } + ldap_pvt_thread_rdwr_runlock(&bdb->bi_tree_rdwr); + + ptr--; + nptr--; + strcpy(ptr, be->be_suffix[0]); + strcpy(nptr, be->be_nsuffix[0]); + + return 0; +} + +int +bdb_dn2id_add( + BackendDB *be, + DB_TXN *txn, + const char *pdn, + Entry *e ) +{ + struct bdb_info *bdb = (struct bdb_info *) be->be_private; + int rc, rlen, nrlen; + DBT key, data; + DB *db = bdb->bi_id2parent->bdi_db; + char *nrdn = dn_rdn( be, e->e_ndn ); + char *rdn; + diskNode *d; + idNode *n; + + if (nrdn == NULL) { + nrdn = ""; + rdn = ""; + } else { + rdn = dn_rdn( be, e->e_dn ); + } + + nrlen = strlen(nrdn); + rlen = strlen(rdn); + d = ch_malloc(sizeof(diskNode) + rlen + nrlen + 2); + d->rdn.bv_len = rlen; + d->nrdn.bv_len = nrlen; + d->rdn.bv_val = (char *)(d+1); + d->nrdn.bv_val = bdb_strcopy(d->rdn.bv_val, rdn) + 1; + strcpy(d->nrdn.bv_val, nrdn); + d->rdn.bv_val -= (long)d; + d->nrdn.bv_val -= (long)d; + + if (nrdn[0]) free(nrdn); + if (rdn[0]) free(rdn); + + if (pdn) { + bdb_dn2id(be, txn, pdn, &d->parent); + } else { + d->parent = 0; + } + + DBTzero(&key); + DBTzero(&data); + key.data = &e->e_id; + key.size = sizeof(ID); + key.flags = DB_DBT_USERMEM; + + data.data = d; + data.size = sizeof(diskNode) + rlen + nrlen + 2; + data.flags = DB_DBT_USERMEM; + + rc = db->put( db, txn, &key, &data, DB_NOOVERWRITE ); + + if (rc == 0) { + ldap_pvt_thread_rdwr_wlock(&bdb->bi_tree_rdwr); + n = bdb_add_node( e->e_id, data.data, bdb); + ldap_pvt_thread_rdwr_wunlock(&bdb->bi_tree_rdwr); + + if (d->parent) { + ldap_pvt_thread_rdwr_rlock(&bdb->bi_tree_rdwr); + bdb_insert_kid(n, bdb->bi_tree); + ldap_pvt_thread_rdwr_runlock(&bdb->bi_tree_rdwr); + } + } else { + free(d); + } + return rc; +} + +int +bdb_dn2id_delete( + BackendDB *be, + DB_TXN *txn, + const char *pdn, + const char *dn, + ID id ) +{ + struct bdb_info *bdb = (struct bdb_info *) be->be_private; + int rc; + DBT key; + DB *db = bdb->bi_id2parent->bdi_db; + idNode *n; + + DBTzero(&key); + key.size = sizeof(id); + key.data = &id; + + rc = db->del( db, txn, &key, 0); + + ldap_pvt_thread_rdwr_wlock(&bdb->bi_tree_rdwr); + n = avl_delete(&bdb->bi_tree, (void *)id, (AVL_CMP)node_find_cmp); + if (n) { + if (n->i_parent) { + ldap_pvt_thread_rdwr_wlock(&n->i_parent->i_kids_rdwr); + avl_delete(&n->i_parent->i_kids, n->i_rdn->nrdn.bv_val, + (AVL_CMP)node_frdn_cmp); + ldap_pvt_thread_rdwr_wunlock(&n->i_parent->i_kids_rdwr); + } + free(n->i_rdn); + ldap_pvt_thread_rdwr_destroy(&n->i_kids_rdwr); + free(n); + } + if (id == 1) + bdb->bi_troot = NULL; + ldap_pvt_thread_rdwr_wunlock(&bdb->bi_tree_rdwr); + + return rc; +} + +int +bdb_dn2id_matched( + BackendDB *be, + DB_TXN *txn, + const char *in, + ID *id, + char **matchedDN ) +{ + struct bdb_info *bdb = (struct bdb_info *) be->be_private; + int i; + char **rdns; + idNode *n, *p; + + if (!bdb->bi_troot) + return DB_NOTFOUND; + + p = bdb->bi_troot; + if (be_issuffix(be, in)) { + *id = p->i_id; + return 0; + } + + rdns = ldap_explode_dn(in, 0); + for (i=0; rdns[i]; i++); + i -= bdb->bi_nrdns; + if (i < 0) + return -1; + n = p; + ldap_pvt_thread_rdwr_rlock(&bdb->bi_tree_rdwr); + for (--i; i>=0; i--) { + ldap_pvt_thread_rdwr_rlock(&p->i_kids_rdwr); + n = bdb_find_rdn_node(rdns[i], p->i_kids); + ldap_pvt_thread_rdwr_runlock(&p->i_kids_rdwr); + if (!n) break; + p = n; + } + ldap_pvt_thread_rdwr_runlock(&bdb->bi_tree_rdwr); + + if (n) { + *id = n->i_id; + } else if (matchedDN) { + int len = 0, j; + char *ptr; + ++i; + for (j=i; rdns[j]; j++) + len += strlen(rdns[j]) + 1; + ptr = ch_malloc(len); + *matchedDN = ptr; + for (;rdns[i]; i++) { + ptr = bdb_strcopy(ptr, rdns[i]); + *ptr++ = ','; + } + ptr[-1] = '\0'; + } + return n ? 0 : DB_NOTFOUND; +} + +int +bdb_dn2id( + BackendDB *be, + DB_TXN *txn, + const char *dn, + ID *id ) +{ + return bdb_dn2id_matched(be, txn, dn, id, NULL); +} + +int +bdb_dn2id_children( + BackendDB *be, + DB_TXN *txn, + const char *dn ) +{ + int rc; + struct bdb_info *bdb = (struct bdb_info *) be->be_private; + ID id; + idNode *n; + + rc = bdb_dn2id(be, txn, dn, &id); + if (rc != 0) + return rc; + + ldap_pvt_thread_rdwr_rlock(&bdb->bi_tree_rdwr); + n = bdb_find_id_node(id, bdb->bi_tree); + ldap_pvt_thread_rdwr_runlock(&bdb->bi_tree_rdwr); + + if (!n->i_kids) + return DB_NOTFOUND; + else + return 0; +} + +/* Since we don't store IDLs for onelevel or subtree, we have to construct + * them on the fly... Perhaps the i_kids tree ought to just be an IDL? + */ +static int +insert_one( + idNode *n, + ID *ids +) +{ + return bdb_idl_insert(ids, n->i_id); +} + +static int +insert_sub( + idNode *n, + ID *ids +) +{ + int rc; + + rc = bdb_idl_insert(ids, n->i_id); + if (rc == 0) { + ldap_pvt_thread_rdwr_rlock(&n->i_kids_rdwr); + rc = avl_apply(n->i_kids, (AVL_APPLY)insert_sub, ids, -1, + AVL_INORDER); + ldap_pvt_thread_rdwr_runlock(&n->i_kids_rdwr); + } + return rc; +} + +int +bdb_dn2idl( + BackendDB *be, + const char *dn, + int prefix, + ID *ids ) +{ + struct bdb_info *bdb = (struct bdb_info *) be->be_private; + int rc; + ID id; + idNode *n; + + if (prefix == DN_SUBTREE_PREFIX && be_issuffix(be, dn)) { + BDB_IDL_ALL(bdb, ids); + return 0; + } + + rc = bdb_dn2id(be, NULL, dn, &id); + if (rc) return rc; + + ldap_pvt_thread_rdwr_rlock(&bdb->bi_tree_rdwr); + n = bdb_find_id_node(id, bdb->bi_tree); + ldap_pvt_thread_rdwr_runlock(&bdb->bi_tree_rdwr); + + ids[0] = 0; + ldap_pvt_thread_rdwr_rlock(&n->i_kids_rdwr); + if (prefix == DN_ONE_PREFIX) { + rc = avl_apply(n->i_kids, (AVL_APPLY)insert_one, ids, -1, + AVL_INORDER); + } else { + rc = avl_apply(n->i_kids, (AVL_APPLY)insert_sub, ids, -1, + AVL_INORDER); + } + ldap_pvt_thread_rdwr_runlock(&n->i_kids_rdwr); + return rc; +} +#endif /* BDB_HIER */ diff --git a/servers/slapd/back-bdb/id2entry.c b/servers/slapd/back-bdb/id2entry.c index e4851b9c1b..eb40b6bac7 100644 --- a/servers/slapd/back-bdb/id2entry.c +++ b/servers/slapd/back-bdb/id2entry.c @@ -23,12 +23,23 @@ int bdb_id2entry_put( DBT key, data; struct berval bv; int rc; +#ifdef BDB_HIER + char *odn, *ondn; + /* We only store rdns, and they go in the id2parent database. */ + + odn = e->e_dn; ondn = e->e_ndn; + + e->e_dn = ""; e->e_ndn = ""; +#endif DBTzero( &key ); key.data = (char *) &e->e_id; key.size = sizeof(ID); rc = entry_encode( e, &bv ); +#ifdef BDB_HIER + e->e_dn = odn; e->e_ndn = ondn; +#endif if( rc != LDAP_SUCCESS ) { return -1; } @@ -47,7 +58,7 @@ int bdb_id2entry_add( DB_TXN *tid, Entry *e ) { - return bdb_id2entry_put( be, tid, e, DB_NOOVERWRITE ); + return bdb_id2entry_put(be, tid, e, DB_NOOVERWRITE); } int bdb_id2entry_update( @@ -55,7 +66,7 @@ int bdb_id2entry_update( DB_TXN *tid, Entry *e ) { - return bdb_id2entry_put( be, tid, e, 0 ); + return bdb_id2entry_put(be, tid, e, 0); } int bdb_id2entry( @@ -98,6 +109,9 @@ int bdb_id2entry( */ ch_free( data.data ); } +#ifdef BDB_HIER + bdb_fix_dn(be, id, *e); +#endif return rc; } @@ -143,6 +157,7 @@ int bdb_entry_return( return 0; } + int bdb_entry_release( BackendDB *be, Connection *c, diff --git a/servers/slapd/back-bdb/idl.c b/servers/slapd/back-bdb/idl.c index ef0889b0d7..2fb1bef891 100644 --- a/servers/slapd/back-bdb/idl.c +++ b/servers/slapd/back-bdb/idl.c @@ -75,7 +75,7 @@ unsigned bdb_idl_search( ID *ids, ID id ) */ unsigned base = 0; unsigned cursor = 0; - int val; + int val = 0; unsigned n = ids[0]; #if IDL_DEBUG > 0 @@ -123,7 +123,7 @@ unsigned bdb_idl_search( ID *ids, ID id ) #endif } -static int idl_insert( ID *ids, ID id ) +int bdb_idl_insert( ID *ids, ID id ) { unsigned x = bdb_idl_search( ids, id ); @@ -316,6 +316,17 @@ bdb_idl_insert_key( DBTzero( &data ); #ifdef BDB_IDL_MULTI + /* FIXME: We really ought to count how many data items currently exist + * for this key, and cap off with a range when we hit the max. We need + * to use a 0 in the first slot to denote a range - since the data are + * sorted in ascending order, the only way to get a flag into the + * first slot is to use the smallest possible ID value. The fetch + * function above can turn it into a "memory-format" range. We also + * have to delete all of the existing data items when converting from + * a list to a range. And of course, if it's already a range, we need + * to read it in and process it instead of just doing the blind put + * that we do right now... + */ data.data = &id; data.size = sizeof(id); data.flags = DB_DBT_USERMEM; @@ -364,7 +375,7 @@ bdb_idl_insert_key( } } else { - rc = idl_insert( ids, id ); + rc = bdb_idl_insert( ids, id ); if( rc == -1 ) { Debug( LDAP_DEBUG_TRACE, "=> bdb_idl_insert_key: dup\n", @@ -373,7 +384,7 @@ bdb_idl_insert_key( } if( rc != 0 ) { Debug( LDAP_DEBUG_ANY, "=> bdb_idl_insert_key: " - "idl_insert failed (%d)\n", + "bdb_idl_insert failed (%d)\n", rc, 0, 0 ); return rc; diff --git a/servers/slapd/back-bdb/init.c b/servers/slapd/back-bdb/init.c index 41e4c37b77..490baca039 100644 --- a/servers/slapd/back-bdb/init.c +++ b/servers/slapd/back-bdb/init.c @@ -20,7 +20,11 @@ static struct bdbi_database { int flags; } bdbi_databases[] = { { "id2entry" BDB_SUFFIX, "id2entry", DB_BTREE, 0 }, +#ifdef BDB_HIER + { "id2parent" BDB_SUFFIX, "id2parent", DB_BTREE, 0 }, +#else { "dn2id" BDB_SUFFIX, "dn2id", DB_BTREE, 0 }, +#endif { NULL, NULL, 0, 0 } }; @@ -73,6 +77,9 @@ bdb_db_init( BackendDB *be ) ldap_pvt_thread_mutex_init( &bdb->bi_database_mutex ); ldap_pvt_thread_mutex_init( &bdb->bi_lastid_mutex ); +#ifdef BDB_HIER + ldap_pvt_thread_rdwr_init( &bdb->bi_tree_rdwr ); +#endif be->be_private = bdb; return 0; @@ -247,16 +254,19 @@ bdb_db_open( BackendDB *be ) rc = db->bdi_db->set_pagesize( db->bdi_db, BDB_ID2ENTRY_PAGESIZE ); } else { - rc = db->bdi_db->set_pagesize( db->bdi_db, - BDB_PAGESIZE ); - } -#ifdef BDB_IDL_MULTI - if( i == BDB_DN2ID ) { - rc = db->bdi_db->set_flags( db->bdi_db, DB_DUPSORT ); +#ifdef BDB_HIER + rc = db->bdi_db->set_bt_compare( db->bdi_db, + bdb_bt_compare ); +#elif defined(BDB_IDL_MULTI) + rc = db->bdi_db->set_flags( db->bdi_db, + DB_DUP | DB_DUPSORT ); rc = db->bdi_db->set_dup_compare( db->bdi_db, bdb_bt_compare ); - } #endif + rc = db->bdi_db->set_pagesize( db->bdi_db, + BDB_PAGESIZE ); + } + rc = db->bdi_db->open( db->bdi_db, bdbi_databases[i].file, /* bdbi_databases[i].name, */ NULL, @@ -288,6 +298,9 @@ bdb_db_open( BackendDB *be ) } /* open (and create) index databases */ +#ifdef BDB_HIER + rc = bdb_build_tree( be ); +#endif #ifndef NO_THREADS if( bdb->bi_lock_detect != DB_LOCK_NORUN ) { diff --git a/servers/slapd/back-bdb/tools.c b/servers/slapd/back-bdb/tools.c index b85862e5fd..5001506612 100644 --- a/servers/slapd/back-bdb/tools.c +++ b/servers/slapd/back-bdb/tools.c @@ -103,6 +103,10 @@ Entry* bdb_tool_entry_get( BackendDB *be, ID id ) e->e_id = id; } +#ifdef BDB_HIER + bdb_fix_dn(be, id, e); +#endif + return e; }