1 /* dn2id.c - routines to deal with the dn2id index */
4 * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
5 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
11 #include <ac/string.h>
24 struct bdb_info *bdb = (struct bdb_info *) be->be_private;
25 DB *db = bdb->bi_dn2id->bdi_db;
29 struct berval ptr, pdn;
32 LDAP_LOG (( "db2id", LDAP_LEVEL_ARGS, "bdb_dn2id_add( \"%s\", 0x%08lx )\n",
33 e->e_ndn, (long) e->e_id ));
35 Debug( LDAP_DEBUG_TRACE, "=> bdb_dn2id_add( \"%s\", 0x%08lx )\n",
36 e->e_ndn, (long) e->e_id, 0 );
38 assert( e->e_id != NOID );
41 key.size = e->e_nname.bv_len + 2;
43 key.flags = DB_DBT_USERMEM;
44 buf = ch_malloc( key.size );
46 buf[0] = DN_BASE_PREFIX;
48 ptr.bv_len = e->e_nname.bv_len;
49 AC_MEMCPY( ptr.bv_val, e->e_nname.bv_val, e->e_nname.bv_len );
50 ptr.bv_val[ptr.bv_len] = '\0';
53 data.data = (char *) &e->e_id;
54 data.size = sizeof( e->e_id );
56 /* store it -- don't override */
57 rc = db->put( db, txn, &key, &data, DB_NOOVERWRITE );
60 LDAP_LOG (( "db2id", LDAP_LEVEL_ERR,
61 "bdb_dn2id_add: put failed: %s %d\n",
62 db_strerror(rc), rc ));
64 Debug( LDAP_DEBUG_ANY, "=> bdb_dn2id_add: put failed: %s %d\n",
65 db_strerror(rc), rc, 0 );
70 if( !be_issuffix( be, &ptr )) {
71 buf[0] = DN_SUBTREE_PREFIX;
72 rc = bdb_idl_insert_key( be, db, txn, &key, e->e_id );
75 LDAP_LOG (( "db2id", LDAP_LEVEL_ERR,
76 "=> bdb_dn2id_add: subtree (%s) insert failed: %d\n",
79 Debug( LDAP_DEBUG_ANY,
80 "=> bdb_dn2id_add: subtree (%s) insert failed: %d\n",
86 dnParent( &ptr, &pdn );
88 key.size = pdn.bv_len + 2;
90 pdn.bv_val[-1] = DN_ONE_PREFIX;
91 key.data = pdn.bv_val-1;
94 rc = bdb_idl_insert_key( be, db, txn, &key, e->e_id );
98 LDAP_LOG (( "db2id", LDAP_LEVEL_ERR,
99 "=> bdb_dn2id_add: parent (%s) insert failed: %d\n",
102 Debug( LDAP_DEBUG_ANY,
103 "=> bdb_dn2id_add: parent (%s) insert failed: %d\n",
110 while( !be_issuffix( be, &ptr )) {
111 ptr.bv_val[-1] = DN_SUBTREE_PREFIX;
113 rc = bdb_idl_insert_key( be, db, txn, &key, e->e_id );
117 LDAP_LOG (( "db2id", LDAP_LEVEL_ERR,
118 "=> bdb_dn2id_add: subtree (%s) insert failed: %d\n",
121 Debug( LDAP_DEBUG_ANY,
122 "=> bdb_dn2id_add: subtree (%s) insert failed: %d\n",
127 dnParent( &ptr, &pdn );
129 key.size = pdn.bv_len + 2;
131 key.data = pdn.bv_val - 1;
138 LDAP_LOG (( "db2id", LDAP_LEVEL_RESULTS,
139 "<= bdb_dn2id_add: %d\n", rc ));
141 Debug( LDAP_DEBUG_TRACE, "<= bdb_dn2id_add: %d\n", rc, 0, 0 );
153 struct bdb_info *bdb = (struct bdb_info *) be->be_private;
154 DB *db = bdb->bi_dn2id->bdi_db;
158 struct berval pdn, ptr;
161 LDAP_LOG (( "db2id", LDAP_LEVEL_ARGS,
162 "=> bdb_dn2id_delete ( \"%s\", 0x08lx )\n",
163 e->e_ndn, e->e_id ));
165 Debug( LDAP_DEBUG_TRACE, "=> bdb_dn2id_delete( \"%s\", 0x%08lx )\n",
166 e->e_ndn, e->e_id, 0 );
170 key.size = e->e_nname.bv_len + 2;
171 buf = ch_malloc( key.size );
173 key.flags = DB_DBT_USERMEM;
174 buf[0] = DN_BASE_PREFIX;
176 ptr.bv_len = e->e_nname.bv_len;
177 AC_MEMCPY( ptr.bv_val, e->e_nname.bv_val, e->e_nname.bv_len );
178 ptr.bv_val[ptr.bv_len] = '\0';
181 rc = db->del( db, txn, &key, 0 );
184 LDAP_LOG (( "db2id", LDAP_LEVEL_ERR,
185 "=> bdb_dn2id_delete: delete failed: %s %d\n",
186 db_strerror(rc), rc ));
188 Debug( LDAP_DEBUG_ANY, "=> bdb_dn2id_delete: delete failed: %s %d\n",
189 db_strerror(rc), rc, 0 );
194 if( !be_issuffix( be, &ptr )) {
195 buf[0] = DN_SUBTREE_PREFIX;
196 rc = db->del( db, txn, &key, 0 );
199 LDAP_LOG (( "db2id", LDAP_LEVEL_ERR,
200 "=> bdb_dn2id_delete: subtree (%s) delete failed: %d\n",
203 Debug( LDAP_DEBUG_ANY,
204 "=> bdb_dn2id_delete: subtree (%s) delete failed: %d\n",
210 dnParent( &ptr, &pdn );
212 key.size = pdn.bv_len + 2;
214 pdn.bv_val[-1] = DN_ONE_PREFIX;
215 key.data = pdn.bv_val - 1;
218 rc = bdb_idl_delete_key( be, db, txn, &key, e->e_id );
222 LDAP_LOG (( "db2id", LDAP_LEVEL_ERR,
223 "=> bdb_dn2id_delete: parent (%s) delete failed: %d\n",
226 Debug( LDAP_DEBUG_ANY,
227 "=> bdb_dn2id_delete: parent (%s) delete failed: %d\n",
234 while( !be_issuffix( be, &ptr )) {
235 ptr.bv_val[-1] = DN_SUBTREE_PREFIX;
237 rc = bdb_idl_delete_key( be, db, txn, &key, e->e_id );
240 LDAP_LOG (( "db2id", LDAP_LEVEL_ERR,
241 "=> bdb_dn2id_delete: subtree (%s) delete failed: %d\n",
244 Debug( LDAP_DEBUG_ANY,
245 "=> bdb_dn2id_delete: subtree (%s) delete failed: %d\n",
250 dnParent( &ptr, &pdn );
252 key.size = pdn.bv_len + 2;
254 key.data = pdn.bv_val - 1;
261 LDAP_LOG (( "db2id", LDAP_LEVEL_RESULTS, "<= bdb_dn2id_delete %d\n", rc ));
263 Debug( LDAP_DEBUG_TRACE, "<= bdb_dn2id_delete %d\n", rc, 0, 0 );
277 struct bdb_info *bdb = (struct bdb_info *) be->be_private;
278 DB *db = bdb->bi_dn2id->bdi_db;
281 LDAP_LOG (( "db2id", LDAP_LEVEL_ARGS, "=> bdb_dn2id( \"%s\" )\n",
284 Debug( LDAP_DEBUG_TRACE, "=> bdb_dn2id( \"%s\" )\n", dn->bv_val, 0, 0 );
289 *id = bdb_cache_find_entry_ndn2id(be, &bdb->bi_cache, dn);
295 key.size = dn->bv_len + 2;
296 key.data = ch_malloc( key.size );
297 ((char *)key.data)[0] = DN_BASE_PREFIX;
298 AC_MEMCPY( &((char *)key.data)[1], dn->bv_val, key.size - 1 );
303 data.ulen = sizeof(ID);
304 data.flags = DB_DBT_USERMEM;
307 rc = db->get( db, txn, &key, &data, bdb->bi_db_opflags );
311 LDAP_LOG (( "db2id", LDAP_LEVEL_ERR,
312 "<= bdb_dn2id: get failed %s (%d)\n",
313 db_strerror(rc), rc ));
315 Debug( LDAP_DEBUG_TRACE, "<= bdb_dn2id: get failed: %s (%d)\n",
316 db_strerror( rc ), rc, 0 );
320 LDAP_LOG (( "db2id", LDAP_LEVEL_RESULTS,
321 "<= bdb_dn2id: got id=0x%08lx\n", *id ));
323 Debug( LDAP_DEBUG_TRACE, "<= bdb_dn2id: got id=0x%08lx\n",
342 struct bdb_info *bdb = (struct bdb_info *) be->be_private;
343 DB *db = bdb->bi_dn2id->bdi_db;
349 LDAP_LOG (( "db2id", LDAP_LEVEL_ARGS,
350 "=> bdb_dn2id_matched( \"%s\" )\n", in->bv_val ));
352 Debug( LDAP_DEBUG_TRACE, "=> bdb_dn2id_matched( \"%s\" )\n", in->bv_val, 0, 0 );
356 key.size = in->bv_len + 2;
357 buf = ch_malloc( key.size );
360 dn.bv_len = key.size - 2;
361 AC_MEMCPY( dn.bv_val, in->bv_val, key.size - 1 );
366 data.ulen = sizeof(ID);
367 data.flags = DB_DBT_USERMEM;
370 dn.bv_val[-1] = DN_BASE_PREFIX;
375 cached_id = bdb_cache_find_entry_ndn2id(be, &bdb->bi_cache, &dn);
377 if (cached_id != NOID) {
380 if ( dn.bv_val != buf+1 ) {
386 rc = db->get(db, txn, &key, &data, bdb->bi_db_opflags );
389 if( rc == DB_NOTFOUND ) {
392 if ( ! be_issuffix( be, &dn ) ) {
393 dnParent( &dn, &pdn );
396 LDAP_LOG (( "db2id", LDAP_LEVEL_DETAIL1,
397 "<= bdb_dn2id_matched: no match\n" ));
399 Debug( LDAP_DEBUG_TRACE,
400 "<= bdb_dn2id_matched: no match\n",
406 key.size = pdn.bv_len + 2;
408 key.data = pdn.bv_val - 1;
410 } else if ( rc == 0 ) {
411 if( data.size != sizeof( ID ) ) {
413 LDAP_LOG (( "db2id", LDAP_LEVEL_DETAIL1,
414 "<= bdb_dn2id_matched: get size mismatch:"
415 "expected %ld, got %ld\n",
416 (long) sizeof(ID), (long) data.size ));
418 Debug( LDAP_DEBUG_ANY,
419 "<= bdb_dn2id_matched: get size mismatch: "
420 "expected %ld, got %ld\n",
421 (long) sizeof(ID), (long) data.size, 0 );
425 if( dn.bv_val != buf+1 ) {
430 LDAP_LOG (( "db2id", LDAP_LEVEL_DETAIL1,
431 "<= bdb_dn2id_matched: id=0x%08lx: %s %s\n",
432 (long) *id, *id2 == 0 ? "entry" : "matched", dn.bv_val ));
434 Debug( LDAP_DEBUG_TRACE,
435 "<= bdb_dn2id_matched: id=0x%08lx: %s %s\n",
436 (long) *id, *id2 == 0 ? "entry" : "matched", dn.bv_val );
442 LDAP_LOG (( "db2id", LDAP_LEVEL_ERR,
443 "<= bdb_dn2id_matched: get failed: %s (%d)\n",
444 db_strerror(rc), rc ));
446 Debug( LDAP_DEBUG_ANY,
447 "<= bdb_dn2id_matched: get failed: %s (%d)\n",
448 db_strerror(rc), rc, 0 );
466 struct bdb_info *bdb = (struct bdb_info *) be->be_private;
467 DB *db = bdb->bi_dn2id->bdi_db;
471 LDAP_LOG (( "db2id", LDAP_LEVEL_ARGS,
472 "=> bdb_dn2id_children( %s )\n", dn->bv_val ));
474 Debug( LDAP_DEBUG_TRACE, "=> bdb_dn2id_children( %s )\n",
479 key.size = dn->bv_len + 2;
480 key.data = ch_malloc( key.size );
481 ((char *)key.data)[0] = DN_ONE_PREFIX;
482 AC_MEMCPY( &((char *)key.data)[1], dn->bv_val, key.size - 1 );
484 /* we actually could do a empty get... */
487 data.ulen = sizeof(id);
488 data.flags = DB_DBT_USERMEM;
490 data.dlen = sizeof(id);
492 rc = db->get( db, txn, &key, &data, bdb->bi_db_opflags );
496 LDAP_LOG (( "db2id", LDAP_LEVEL_DETAIL1,
497 "<= bdb_dn2id_children( %s ): %schildren (%d)\n",
498 dn->bv_val, rc == 0 ? "" : ( rc == DB_NOTFOUND ? "no " :
499 db_strerror(rc)), rc ));
501 Debug( LDAP_DEBUG_TRACE, "<= bdb_dn2id_children( %s ): %schildren (%d)\n",
503 rc == 0 ? "" : ( rc == DB_NOTFOUND ? "no " :
504 db_strerror(rc) ), rc );
519 struct bdb_info *bdb = (struct bdb_info *) be->be_private;
520 DB *db = bdb->bi_dn2id->bdi_db;
523 LDAP_LOG (( "db2id", LDAP_LEVEL_ARGS,
524 "=> bdb_dn2ididl( \"%s\" )\n", dn->bv_val ));
526 Debug( LDAP_DEBUG_TRACE, "=> bdb_dn2idl( \"%s\" )\n", dn->bv_val, 0, 0 );
529 if (prefix == DN_SUBTREE_PREFIX && be_issuffix(be, dn))
531 BDB_IDL_ALL(bdb, ids);
536 key.size = dn->bv_len + 2;
538 key.flags = DB_DBT_USERMEM;
539 key.data = ch_malloc( key.size );
540 ((char *)key.data)[0] = prefix;
541 AC_MEMCPY( &((char *)key.data)[1], dn->bv_val, key.size - 1 );
543 rc = bdb_idl_fetch_key( be, db, NULL, &key, ids );
547 LDAP_LOG (( "db2id", LDAP_LEVEL_ERR,
548 "<= bdb_dn2ididl: get failed: %s (%d)\n",
549 db_strerror(rc), rc ));
551 Debug( LDAP_DEBUG_TRACE,
552 "<= bdb_dn2idl: get failed: %s (%d)\n",
553 db_strerror( rc ), rc, 0 );
558 LDAP_LOG (( "db2id", LDAP_LEVEL_RESULTS,
559 "<= bdb_dn2ididl: id=%ld first=%ld last=%ld\n",
560 (long) ids[0], (long) BDB_IDL_FIRST( ids ),
561 (long) BDB_IDL_LAST( ids ) ));
563 Debug( LDAP_DEBUG_TRACE,
564 "<= bdb_dn2idl: id=%ld first=%ld last=%ld\n",
566 (long) BDB_IDL_FIRST( ids ), (long) BDB_IDL_LAST( ids ) );
575 /* Experimental management routines for a hierarchically structured backend.
577 * Unsupported! Use at your own risk!
579 * Instead of a dn2id database, we use an id2parent database. Each entry in
580 * this database is a struct diskNode, containing the ID of the node's parent
581 * and the RDN of the node.
583 typedef struct diskNode {
589 /* In bdb_db_open() we call bdb_build_tree() which reads the entire id2parent
590 * database into memory (into an AVL tree). Next we iterate through each node
591 * of this tree, connecting each child to its parent. The nodes in this AVL
592 * tree are a struct idNode. The immediate (Onelevel) children of a node are
593 * referenced in the i_kids AVL tree. With this arrangement, there is no need
594 * to maintain the DN_ONE_PREFIX or DN_SUBTREE_PREFIX database keys. Note that
595 * the DN of an entry is constructed by walking up the list of i_parent
596 * pointers, so no full DN is stored on disk anywhere. This makes modrdn
597 * extremely efficient, even when operating on a populated subtree.
599 * The idNode tree is searched directly from the root when performing id to
600 * entry lookups. The tree is traversed using the i_kids subtrees when
601 * performing dn to id lookups.
603 typedef struct idNode {
605 struct idNode *i_parent;
608 ldap_pvt_thread_rdwr_t i_kids_rdwr;
612 /* The main AVL tree is sorted in ID order. The i_kids AVL trees are
613 * sorted in lexical order. These are the various helper routines used
614 * for the searches and sorts.
631 return strcmp(nrdn, n->i_rdn->nrdn.bv_val);
640 return a->i_id - b->i_id;
650 return strcmp(a->i_rdn->nrdn.bv_val, b->i_rdn->nrdn.bv_val);
652 /* should be slightly better without ordering drawbacks */
653 return ber_bvcmp(&a->i_rdn->nrdn, &b->i_rdn->nrdn);
656 idNode * bdb_find_id_node(
661 return avl_find(tree, (const void *)id, (AVL_CMP)node_find_cmp);
664 idNode * bdb_find_rdn_node(
669 return avl_find(tree, (const void *)nrdn, (AVL_CMP)node_frdn_cmp);
672 /* This function links a node into its parent's i_kids tree. */
680 if (a->i_rdn->parent == 0)
682 a->i_parent = bdb_find_id_node(a->i_rdn->parent, tree);
685 ldap_pvt_thread_rdwr_wlock(&a->i_parent->i_kids_rdwr);
686 rc = avl_insert( &a->i_parent->i_kids, (caddr_t) a,
687 (AVL_CMP)node_rdn_cmp, (AVL_DUP) avl_dup_error );
688 ldap_pvt_thread_rdwr_wunlock(&a->i_parent->i_kids_rdwr);
692 /* This function adds a node into the main AVL tree */
693 idNode *bdb_add_node(
701 node = (idNode *)ch_malloc(sizeof(idNode));
703 node->i_parent = NULL;
705 node->i_rdn = (diskNode *)d;
706 node->i_rdn->rdn.bv_val += (long)d;
707 node->i_rdn->nrdn.bv_val += (long)d;
708 ldap_pvt_thread_rdwr_init(&node->i_kids_rdwr);
709 avl_insert( &bdb->bi_tree, (caddr_t) node,
710 (AVL_CMP)node_add_cmp, (AVL_DUP) avl_dup_error );
712 bdb->bi_troot = node;
716 /* This function initializes the trees at startup time. */
721 struct bdb_info *bdb = (struct bdb_info *) be->be_private;
731 rc = bdb->bi_id2parent->bdi_db->cursor(
732 bdb->bi_id2parent->bdi_db, NULL, &cursor,
733 bdb->bi_db_opflags );
738 /* When be_suffix is turned into struct berval or LDAPDN
739 * life will get a lot easier... Since no DNs live on disk, we
740 * need to operate on the be_suffix to fully qualify our DNs.
741 * We need to know how many components are in the suffix DN,
742 * so we can tell where the suffix ends and our nodes begin.
744 * Note that this code always uses be_suffix[0], so defining
745 * multiple suffixes for a single backend won't work!
747 rdns = ldap_explode_dn(be->be_nsuffix[0]->bv_val, 0);
748 for (i=0; rdns[i]; i++);
754 key.data = (char *)&id;
755 key.ulen = sizeof( id );
756 key.flags = DB_DBT_USERMEM;
757 data.flags = DB_DBT_MALLOC;
759 while (cursor->c_get( cursor, &key, &data, DB_NEXT ) == 0) {
760 bdb_add_node( id, data.data, bdb );
762 cursor->c_close( cursor );
764 rc = avl_apply(bdb->bi_tree, (AVL_APPLY)bdb_insert_kid, bdb->bi_tree,
770 /* This function constructs a full DN for a given id. We really should
771 * be passing idNodes directly, to save some effort...
779 struct bdb_info *bdb = (struct bdb_info *) be->be_private;
784 ldap_pvt_thread_rdwr_rlock(&bdb->bi_tree_rdwr);
785 o = bdb_find_id_node(id, bdb->bi_tree);
786 rlen = be->be_suffix[0]->bv_len + 1;
787 nrlen = be->be_nsuffix[0]->bv_len + 1;
788 for (n = o; n && n->i_parent; n=n->i_parent) {
789 rlen += n->i_rdn->rdn.bv_len + 1;
790 nrlen += n->i_rdn->nrdn.bv_len + 1;
792 e->e_name.bv_len = rlen - 1;
793 e->e_nname.bv_len = nrlen - 1;
794 e->e_name.bv_val = ch_malloc(rlen + nrlen);
795 e->e_nname.bv_val = e->e_name.bv_val + rlen;
796 ptr = e->e_name.bv_val;
797 nptr = e->e_nname.bv_val;
798 for (n = o; n && n->i_parent; n=n->i_parent) {
799 ptr = slap_strcopy(ptr, n->i_rdn->rdn.bv_val);
801 nptr = slap_strcopy(nptr, n->i_rdn->nrdn.bv_val);
804 ldap_pvt_thread_rdwr_runlock(&bdb->bi_tree_rdwr);
806 strcpy(ptr, be->be_suffix[0]->bv_val);
807 strcpy(nptr, be->be_nsuffix[0]->bv_val);
819 struct bdb_info *bdb = (struct bdb_info *) be->be_private;
822 DB *db = bdb->bi_id2parent->bdi_db;
826 nrlen = dn_rdnlen( be, &e->e_nname );
828 rlen = dn_rdnlen( be, &e->e_name );
833 d = ch_malloc(sizeof(diskNode) + rlen + nrlen + 2);
834 d->rdn.bv_len = rlen;
835 d->nrdn.bv_len = nrlen;
836 d->rdn.bv_val = (char *)(d+1);
837 d->nrdn.bv_val = d->rdn.bv_val + rlen + 1;
838 strncpy(d->rdn.bv_val, e->e_dn, rlen);
839 d->rdn.bv_val[rlen] = '\0';
840 strncpy(d->nrdn.bv_val, e->e_ndn, nrlen);
841 d->nrdn.bv_val[nrlen] = '\0';
842 d->rdn.bv_val -= (long)d;
843 d->nrdn.bv_val -= (long)d;
846 bdb_dn2id(be, txn, pdn, &d->parent);
854 key.size = sizeof(ID);
855 key.flags = DB_DBT_USERMEM;
858 data.size = sizeof(diskNode) + rlen + nrlen + 2;
859 data.flags = DB_DBT_USERMEM;
861 rc = db->put( db, txn, &key, &data, DB_NOOVERWRITE );
864 ldap_pvt_thread_rdwr_wlock(&bdb->bi_tree_rdwr);
865 n = bdb_add_node( e->e_id, data.data, bdb);
866 ldap_pvt_thread_rdwr_wunlock(&bdb->bi_tree_rdwr);
869 ldap_pvt_thread_rdwr_rlock(&bdb->bi_tree_rdwr);
870 bdb_insert_kid(n, bdb->bi_tree);
871 ldap_pvt_thread_rdwr_runlock(&bdb->bi_tree_rdwr);
886 struct bdb_info *bdb = (struct bdb_info *) be->be_private;
889 DB *db = bdb->bi_id2parent->bdi_db;
893 key.size = sizeof(e->e_id);
896 rc = db->del( db, txn, &key, 0);
898 ldap_pvt_thread_rdwr_wlock(&bdb->bi_tree_rdwr);
899 n = avl_delete(&bdb->bi_tree, (void *)e->e_id, (AVL_CMP)node_find_cmp);
902 ldap_pvt_thread_rdwr_wlock(&n->i_parent->i_kids_rdwr);
903 avl_delete(&n->i_parent->i_kids, n->i_rdn->nrdn.bv_val,
904 (AVL_CMP)node_frdn_cmp);
905 ldap_pvt_thread_rdwr_wunlock(&n->i_parent->i_kids_rdwr);
908 ldap_pvt_thread_rdwr_destroy(&n->i_kids_rdwr);
912 bdb->bi_troot = NULL;
913 ldap_pvt_thread_rdwr_wunlock(&bdb->bi_tree_rdwr);
926 struct bdb_info *bdb = (struct bdb_info *) be->be_private;
935 if (be_issuffix(be, in)) {
940 rdns = ldap_explode_dn(in->bv_val, 0);
941 for (i=0; rdns[i]; i++);
948 ldap_pvt_thread_rdwr_rlock(&bdb->bi_tree_rdwr);
949 for (--i; i>=0; i--) {
950 ldap_pvt_thread_rdwr_rlock(&p->i_kids_rdwr);
951 n = bdb_find_rdn_node(rdns[i], p->i_kids);
952 ldap_pvt_thread_rdwr_runlock(&p->i_kids_rdwr);
956 ldap_pvt_thread_rdwr_runlock(&bdb->bi_tree_rdwr);
964 return n ? 0 : DB_NOTFOUND;
974 return bdb_dn2id_matched(be, txn, dn, id, NULL);
984 struct bdb_info *bdb = (struct bdb_info *) be->be_private;
988 rc = bdb_dn2id(be, txn, dn, &id);
992 ldap_pvt_thread_rdwr_rlock(&bdb->bi_tree_rdwr);
993 n = bdb_find_id_node(id, bdb->bi_tree);
994 ldap_pvt_thread_rdwr_runlock(&bdb->bi_tree_rdwr);
1002 /* Since we don't store IDLs for onelevel or subtree, we have to construct
1003 * them on the fly... Perhaps the i_kids tree ought to just be an IDL?
1011 return bdb_idl_insert(ids, n->i_id);
1022 rc = bdb_idl_insert(ids, n->i_id);
1024 ldap_pvt_thread_rdwr_rlock(&n->i_kids_rdwr);
1025 rc = avl_apply(n->i_kids, (AVL_APPLY)insert_sub, ids, -1,
1027 ldap_pvt_thread_rdwr_runlock(&n->i_kids_rdwr);
1039 struct bdb_info *bdb = (struct bdb_info *) be->be_private;
1044 if (prefix == DN_SUBTREE_PREFIX && be_issuffix(be, dn)) {
1045 BDB_IDL_ALL(bdb, ids);
1049 rc = bdb_dn2id(be, NULL, dn, &id);
1052 ldap_pvt_thread_rdwr_rlock(&bdb->bi_tree_rdwr);
1053 n = bdb_find_id_node(id, bdb->bi_tree);
1054 ldap_pvt_thread_rdwr_runlock(&bdb->bi_tree_rdwr);
1057 ldap_pvt_thread_rdwr_rlock(&n->i_kids_rdwr);
1058 if (prefix == DN_ONE_PREFIX) {
1059 rc = avl_apply(n->i_kids, (AVL_APPLY)insert_one, ids, -1,
1062 rc = avl_apply(n->i_kids, (AVL_APPLY)insert_sub, ids, -1,
1065 ldap_pvt_thread_rdwr_runlock(&n->i_kids_rdwr);
1068 #endif /* BDB_HIER */