Trim dead BDB_HIER stuff

This commit is contained in:
Howard Chu 2003-04-22 17:06:35 +00:00
parent c9f8d7accb
commit 68822b1e15
6 changed files with 371 additions and 122 deletions

View file

@ -14,8 +14,6 @@
LDAP_BEGIN_DECL
/* #define BDB_HIER 1 */
#define DN_BASE_PREFIX SLAP_INDEX_EQUALITY_PREFIX
#define DN_ONE_PREFIX '%'
#define DN_SUBTREE_PREFIX '@'
@ -40,11 +38,7 @@ 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
@ -90,6 +84,7 @@ typedef struct bdb_entry_info {
int bei_state;
#define CACHE_ENTRY_DELETED 1
#define CACHE_ENTRY_NO_KIDS 2
#define CACHE_ENTRY_NOT_LINKED 4
/*
* remaining fields require backend cache lock to access
@ -146,11 +141,6 @@ struct bdb_info {
Avlnode *bi_attrs;
void *bi_search_stack;
int bi_search_stack_depth;
#ifdef BDB_HIER
Avlnode *bi_tree;
ldap_pvt_thread_rdwr_t bi_tree_rdwr;
void *bi_troot;
#endif
int bi_txn_cp;
u_int32_t bi_txn_cp_min;
@ -159,6 +149,8 @@ struct bdb_info {
int bi_lock_detect;
long bi_shm_key;
int bi_is_hier;
ID bi_lastid;
ldap_pvt_thread_mutex_t bi_lastid_mutex;
#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)

View file

@ -50,6 +50,8 @@ bdb_cache_entry_db_relock(
DBT lockobj;
DB_LOCKREQ list[2];
if ( !lock ) return 0;
lockobj.data = ei;
lockobj.size = sizeof(ei->bei_parent) + sizeof(ei->bei_id);
@ -89,6 +91,8 @@ bdb_cache_entry_db_lock
DBT lockobj;
int db_rw;
if ( !lock ) return 0;
if (rw)
db_rw = DB_LOCK_WRITE;
else
@ -184,9 +188,7 @@ bdb_id_cmp( const void *v_e1, const void *v_e2 )
int
bdb_entryinfo_add_internal(
struct bdb_info *bdb,
EntryInfo *eip,
ID id,
struct berval *nrdn,
EntryInfo *ei,
EntryInfo **res,
u_int32_t locker
)
@ -202,15 +204,15 @@ bdb_entryinfo_add_internal(
*res = NULL;
ldap_pvt_thread_rdwr_wlock( &bdb->bi_cache.c_rwlock );
bdb_cache_entryinfo_lock( eip );
bdb_cache_entryinfo_lock( ei->bei_parent );
/* if parent was previously considered a leaf node,
* it was on the LRU list. Now it's going to have
* kids, take it off the LRU list.
*/
ldap_pvt_thread_mutex_lock( &cache->lru_mutex );
if ( eip->bei_id && !eip->bei_kids ) {
LRU_DELETE( cache, eip );
if ( ei->bei_parent->bei_id && !ei->bei_parent->bei_kids ) {
LRU_DELETE( cache, ei->bei_parent );
incr = 0;
}
@ -265,33 +267,32 @@ bdb_entryinfo_add_internal(
if (!ei2) {
ei2 = bdb_cache_entryinfo_new();
}
ei2->bei_id = id;
ei2->bei_parent = eip;
ei2->bei_id = ei->bei_id;
ei2->bei_parent = ei->bei_parent;
ei2->bei_rdn = ei->bei_rdn;
/* Add to cache ID tree */
if (avl_insert( &cache->c_idtree, ei2, bdb_id_cmp, avl_dup_error )) {
EntryInfo *ei;
ei = avl_find( cache->c_idtree, ei2, bdb_id_cmp );
EntryInfo *eix;
eix = avl_find( cache->c_idtree, ei2, bdb_id_cmp );
bdb_cache_entryinfo_destroy( ei2 );
ei2 = ei;
ei2 = eix;
addkid = 0;
cache->c_cursize -= incr;
if ( ei->bei_rdn.bv_val )
ber_memfree_x( ei->bei_rdn.bv_val, NULL );
} else {
LRU_ADD( cache, ei2 );
ber_dupbv( &ei2->bei_nrdn, nrdn );
ber_dupbv( &ei2->bei_nrdn, &ei->bei_nrdn );
}
if ( addkid ) {
avl_insert( &eip->bei_kids, ei2, bdb_rdn_cmp, avl_dup_error );
avl_insert( &ei->bei_parent->bei_kids, ei2, bdb_rdn_cmp,
avl_dup_error );
}
ldap_pvt_thread_mutex_unlock( &cache->lru_mutex );
#if 0 /* caller must do these frees */
ldap_pvt_thread_rdwr_wunlock( &cache->c_rwlock );
bdb_cache_entryinfo_unlock( eip );
#endif
*res = ei2;
return 0;
}
@ -332,6 +333,7 @@ bdb_cache_find_entry_ndn2id(
}
for ( bdb_cache_entryinfo_lock( eip ); eip; ) {
ei.bei_parent = eip;
ei2 = (EntryInfo *)avl_find( eip->bei_kids, &ei, bdb_rdn_cmp );
if ( !ei2 ) {
int len = ei.bei_nrdn.bv_len;
@ -348,8 +350,8 @@ bdb_cache_find_entry_ndn2id(
/* DN exists but needs to be added to cache */
ei.bei_nrdn.bv_len = len;
rc = bdb_entryinfo_add_internal( bdb,
eip, ei.bei_id, &ei.bei_nrdn, &ei2, locker );
rc = bdb_entryinfo_add_internal( bdb, &ei, &ei2,
locker );
/* add_internal left eip and c_rwlock locked */
ldap_pvt_thread_rdwr_wunlock( &bdb->bi_cache.c_rwlock );
if ( rc ) {
@ -388,6 +390,99 @@ bdb_cache_find_entry_ndn2id(
return rc;
}
#ifdef BDB_HIER
/* Walk up the tree from a child node, looking for an ID that's already
* been linked into the cache.
*/
int
bdb_cache_find_parent(
Backend *be,
DB_TXN *txn,
ID id,
EntryInfo **res,
void *ctx
)
{
struct bdb_info *bdb = (struct bdb_info *) be->be_private;
EntryInfo ei, eip, *ei2 = NULL, *ein = NULL, *eir = NULL;
ID parent;
int rc;
ei.bei_id = id;
ei.bei_kids = NULL;
for (;;) {
rc = bdb_dn2id_parent( be, txn, &ei, &eip.bei_id, ctx );
if ( rc ) break;
/* Save the previous node, if any */
ei2 = ein;
/* Create a new node for the current ID */
ein = bdb_cache_entryinfo_new();
ein->bei_id = ei.bei_id;
ein->bei_nrdn = ei.bei_nrdn;
ein->bei_rdn = ei.bei_rdn;
ein->bei_kids = ei.bei_kids;
/* This node is not fully connected yet */
ein->bei_state = CACHE_ENTRY_NOT_LINKED;
/* If this is the first time, save this node
* to be returned later.
*/
if ( eir == NULL ) eir = ein;
/* Insert this node into the ID tree */
ldap_pvt_thread_rdwr_rlock( &bdb->bi_cache.c_rwlock );
if ( avl_insert( &bdb->bi_cache.c_idtree, (caddr_t)ein,
bdb_id_cmp, avl_dup_error ) ) {
/* Hm, can this really happen? */
bdb_cache_entryinfo_destroy( ein );
ein = (EntryInfo *)avl_find( bdb->bi_cache.c_idtree,
(caddr_t) &ei, bdb_id_cmp );
bdb_cache_entryinfo_lock( ein );
avl_insert( &ein->bei_kids, (caddr_t)ei2, bdb_rdn_cmp,
avl_dup_error );
bdb_cache_entryinfo_unlock( ein );
}
/* If there was a previous node, link it to this one */
if ( ei2 ) ei2->bei_parent = ein;
if ( eip.bei_id ) {
ei2 = (EntryInfo *) avl_find( bdb->bi_cache.c_idtree,
(caddr_t) &eip, bdb_id_cmp );
} else {
ei2 = &bdb->bi_cache.c_dntree;
}
if ( ei2 ) {
ein->bei_parent = ei2;
bdb_cache_entryinfo_lock( ei2 );
avl_insert( &ei2->bei_kids, (caddr_t)ein, bdb_rdn_cmp,
avl_dup_error);
bdb_cache_entryinfo_unlock( ei2 );
*res = eir;
bdb_cache_entryinfo_lock( eir );
}
ldap_pvt_thread_rdwr_runlock( &bdb->bi_cache.c_rwlock );
if ( ei2 ) {
/* Found a link. Reset all the state info */
for (ein = eir; ein != ei2; ein=ein->bei_parent)
ein->bei_state &= ~CACHE_ENTRY_NOT_LINKED;
break;
}
ei.bei_kids = NULL;
ei.bei_id = eip.bei_id;
avl_insert( &ei.bei_kids, (caddr_t)ein, bdb_rdn_cmp,
avl_dup_error );
}
return rc;
}
#endif
/*
* cache_find_entry_id - find an entry in the cache, given id.
* The entry is locked for Read upon return. Call with islocked TRUE if
@ -427,6 +522,7 @@ bdb_cache_find_entry_id(
/* See if the ID exists in the database; add it to the cache if so */
if ( !*eip ) {
#ifndef BDB_HIER
rc = bdb_id2entry( be, tid, id, &ep );
if ( rc == 0 ) {
rc = bdb_cache_find_entry_ndn2id( be, tid,
@ -438,6 +534,11 @@ bdb_cache_find_entry_id(
ep = NULL;
}
}
#else
rc = bdb_cache_find_parent(be, tid, id, eip, ctx );
if ( rc == 0 && *eip )
islocked = 1;
#endif
}
/* Ok, we found the info, do we have the entry? */
@ -451,8 +552,11 @@ bdb_cache_find_entry_id(
if ( rc == 0 ) {
bdb_cache_entry_db_lock( bdb->bi_dbenv, locker,
*eip, 1, 0, lock );
(*eip)->bei_e = ep;
ep->e_private = *eip;
#ifdef BDB_HIER
hdb_fix_dn( ep );
#endif
(*eip)->bei_e = ep;
bdb_cache_entry_db_relock( bdb->bi_dbenv, locker,
*eip, 0, 0, lock );
}
@ -501,21 +605,30 @@ bdb_cache_children(
int
bdb_cache_add(
struct bdb_info *bdb,
EntryInfo *ei,
EntryInfo *eip,
Entry *e,
struct berval *nrdn,
u_int32_t locker
)
{
EntryInfo *new;
EntryInfo *new, ei;
struct berval rdn = e->e_name;
int rc;
rc = bdb_entryinfo_add_internal( bdb, ei, e->e_id, nrdn, &new, locker );
ei.bei_id = e->e_id;
ei.bei_parent = eip;
ei.bei_nrdn = *nrdn;
if ( nrdn->bv_len != e->e_nname.bv_len ) {
char *ptr = strchr( rdn.bv_val, ',' );
rdn.bv_len = ptr - rdn.bv_val;
}
ber_dupbv( &ei.bei_rdn, &rdn );
rc = bdb_entryinfo_add_internal( bdb, &ei, &new, locker );
new->bei_e = e;
e->e_private = new;
new->bei_state = CACHE_ENTRY_NO_KIDS;
ei->bei_state &= ~CACHE_ENTRY_NO_KIDS;
bdb_cache_entryinfo_unlock( ei );
eip->bei_state &= ~CACHE_ENTRY_NO_KIDS;
bdb_cache_entryinfo_unlock( eip );
ldap_pvt_thread_rdwr_wunlock( &bdb->bi_cache.c_rwlock );
return rc;
}
@ -560,6 +673,7 @@ bdb_cache_modrdn(
)
{
EntryInfo *ei = BEI(e), *pei;
struct berval rdn;
int rc = 0;
/* Get write lock on data */
@ -589,7 +703,15 @@ bdb_cache_modrdn(
bdb_cache_entryinfo_lock( pei );
avl_delete( &pei->bei_kids, (caddr_t) ei, bdb_rdn_cmp );
free( ei->bei_nrdn.bv_val );
free( ei->bei_rdn.bv_val );
ber_dupbv( &ei->bei_nrdn, nrdn );
rdn = e->e_name;
if ( nrdn->bv_len != e->e_nname.bv_len ) {
char *ptr = strchr(rdn.bv_val, ',');
rdn.bv_len = ptr - rdn.bv_val;
}
ber_dupbv( &ei->bei_rdn, &rdn );
if (!ein) {
ein = ei->bei_parent;
} else {
@ -702,7 +824,9 @@ static void
bdb_entryinfo_release( void *data )
{
EntryInfo *ei = (EntryInfo *)data;
avl_free( ei->bei_kids, NULL );
if ( ei->bei_kids ) {
avl_free( ei->bei_kids, NULL );
}
if ( ei->bei_e ) {
ei->bei_e->e_private = NULL;
bdb_entry_return( ei->bei_e );

View file

@ -487,9 +487,10 @@ bdb_dn2idl(
* entry in this database is a struct diskNode, keyed by entryID and with
* the data containing the RDN and entryID of the node's children. We use
* a B-Tree with sorted duplicates to store all the children of a node under
* the same key. Also, the first item under the key contains an empty rdn
* and the ID of the node's parent, to allow bottom-up tree traversal as
* well as top-down.
* the same key. Also, the first item under the key contains the entry's own
* rdn and the ID of the node's parent, to allow bottom-up tree traversal as
* well as top-down. To keep this info first in the list, the nrdnlen is set
* to the negative of its value.
*
* The diskNode is a variable length structure. This definition is not
* directly usable for in-memory manipulation.
@ -505,7 +506,7 @@ typedef struct diskNode {
* Sorts based on normalized RDN, in lexical order.
*/
int
bdb_hdb_compare(
hdb_dup_compare(
DB *db,
const DBT *usrkey,
const DBT *curkey
@ -513,30 +514,45 @@ bdb_hdb_compare(
{
diskNode *usr = usrkey->data;
diskNode *cur = curkey->data;
short curlen;
char *ptr = (char *)&cur->nrdnlen;
short curlen, usrlen;
char *ptr;
unsigned char *pt2;
int rc;
curlen = ptr[0] << 8 | ptr[1];
/* Make sure to detect negative values in the nrdnlen */
ptr = (char *)&usr->nrdnlen;
pt2 = (unsigned char *)(ptr+1);
rc = strncmp( usr->nrdn, cur->nrdn, usr->nrdnlen );
usrlen = ptr[0] << 8 | *pt2;
ptr = (char *)&cur->nrdnlen;
pt2 = (unsigned char *)(ptr+1);
curlen = ptr[0] << 8 | *pt2;
if ( usrlen < 0 ) {
if ( curlen < 0 ) return 0;
return -1;
}
if ( curlen < 0 ) return 1;
rc = strncmp( usr->nrdn, cur->nrdn, usrlen );
if ( rc == 0 ) rc = usrlen - curlen;
return rc;
}
/* This function constructs a full DN for a given entry.
*/
int bdb_fix_dn(
BackendDB *be,
int hdb_fix_dn(
Entry *e
)
{
struct bdb_info *bdb = (struct bdb_info *) be->be_private;
EntryInfo *ei;
int rlen = 0, nrlen = 0;
char *ptr, *nptr;
for ( ei = BEI(e); ei; ei=ei->bei_parent ) {
for ( ei = BEI(e); ei && ei->bei_id; ei=ei->bei_parent ) {
rlen += ei->bei_rdn.bv_len + 1;
nrlen += ei->bei_nrdn.bv_len + 1;
}
@ -546,7 +562,7 @@ int bdb_fix_dn(
e->e_nname.bv_val = e->e_name.bv_val + rlen;
ptr = e->e_name.bv_val;
nptr = e->e_nname.bv_val;
for ( ei = BEI(e); ei; ei=ei->bei_parent ) {
for ( ei = BEI(e); ei && ei->bei_id; ei=ei->bei_parent ) {
ptr = lutil_strcopy(ptr, ei->bei_rdn.bv_val);
nptr = lutil_strcopy(nptr, ei->bei_nrdn.bv_val);
if ( ei->bei_parent ) {
@ -554,8 +570,8 @@ int bdb_fix_dn(
*nptr++ = ',';
}
}
*ptr = '\0';
*nptr = '\0';
ptr[-1] = '\0';
nptr[-1] = '\0';
return 0;
}
@ -607,20 +623,17 @@ bdb_dn2id_add(
}
#endif
data.data = d;
data.size = sizeof(diskNode) + rlen + nrlen + 2;
data.size = sizeof(diskNode) + rlen + nrlen;
data.flags = DB_DBT_USERMEM;
rc = db->put( db, txn, &key, &data, DB_NOOVERWRITE );
rc = db->put( db, txn, &key, &data, DB_NODUPDATA );
if (rc == 0) {
key.data = &e->e_id;
d->entryID = eip->bei_id;
d->nrdnlen = 0;
d->nrdn[0] = '\0';
d->rdn[0] = '\0';
data.size = sizeof(diskNode);
d->nrdnlen = 0 - nrlen;
rc = db->put( db, txn, &key, &data, DB_NOOVERWRITE );
rc = db->put( db, txn, &key, &data, DB_NODUPDATA );
}
sl_free( d, ctx );
@ -650,12 +663,7 @@ bdb_dn2id_delete(
key.flags = DB_DBT_USERMEM;
DBTzero(&data);
data.size = sizeof(diskNode) + BEI(e)->nrdn.bv_len;
d = sl_malloc( data.size, ctx );
d->entryID = e->e_id;
d->nrdnlen = BEI(e)->nrdn.bv_len;
strcpy( d->nrdn, BEI(e)->nrdn.bv_val );
data.data = d;
data.size = sizeof(diskNode) + BEI(e)->bei_nrdn.bv_len;
data.ulen = data.size;
data.dlen = data.size;
data.flags = DB_DBT_USERMEM | DB_DBT_PARTIAL;
@ -668,13 +676,28 @@ bdb_dn2id_delete(
rc = db->cursor( db, txn, &cursor, bdb->bi_db_opflags );
if ( rc ) return rc;
d = sl_malloc( data.size, ctx );
d->entryID = e->e_id;
d->nrdnlen = BEI(e)->bei_nrdn.bv_len;
strcpy( d->nrdn, BEI(e)->bei_nrdn.bv_val );
data.data = d;
/* Delete our ID from the parent's list */
rc = cursor->c_get( cursor, &key, &data, DB_GET_BOTH | DB_RMW );
if ( rc == 0 )
rc = cursor->c_del( cursor, 0 );
cursor->c_close( cursor );
key.data = &e->e_id;
rc = db->del( db, txn, &key, 0);
/* Delete our ID from the tree. With sorted duplicates, this
* will leave any child nodes still hanging around. This is OK
* for modrdn, which will add our info back in later.
*/
if ( rc == 0 ) {
key.data = &e->e_id;
rc = cursor->c_get( cursor, &key, &data, DB_SET );
if ( rc == 0 )
rc = cursor->c_del( cursor, 0 );
}
cursor->c_close( cursor );
sl_free( d, ctx );
return rc;
@ -693,38 +716,96 @@ bdb_dn2id(
DBT key, data;
DBC *cursor;
int rc = 0, nrlen;
diskNode *d;
char *ptr;
ID idp = ei->bei_parent->bei_id;
nrlen = dn_rdnlen( be, &in );
nrlen = dn_rdnlen( be, in );
if (!nrlen) nrlen = in->bv_len;
DBTzero(&key);
key.size = sizeof(ID);
key.data = &eip->bei_id;
key.data = &idp;
key.ulen = sizeof(ID);
key.flags = DB_DBT_USERMEM;
DBTzero(&data);
data.size = sizeof(diskNode) + nrlen;
d = sl_malloc( data.size * 3, ctx );
d->nrdnlen = nrlen;
ptr = lutil_strncopy( d->nrdn, BEI(e)->nrdn.bv_val, nrlen );
*ptr = '\0';
data.data = d;
data.ulen = data.size * 3;
data.flags = DB_DBT_USERMEM;
rc = db->cursor( db, txn, &cursor, bdb->bi_db_opflags );
if ( rc ) return rc;
d = sl_malloc( data.size * 3, ctx );
d->nrdnlen = nrlen;
ptr = lutil_strncopy( d->nrdn, in->bv_val, nrlen );
*ptr = '\0';
data.data = d;
rc = cursor->c_get( cursor, &key, &data, DB_GET_BOTH );
cursor->c_close( cursor );
if ( rc == 0 ) {
AC_MEMCPY( &ei->bei_id, &d->entryID, sizeof(ID) );
ei->bei_rdn.bv_len = data.size - sizeof(diskNode) - nrlen;
ptr = d->nrdn + nrlen + 1;
ei->bei_rdn.bv_val = ch_malloc( ei->bei_rdn.bv_len + 1 );
strcpy( ei->bei_rdn.bv_val, ptr );
}
sl_free( d, ctx );
return rc;
}
int
bdb_dn2id_parent(
Backend *be,
DB_TXN *txn,
EntryInfo *ei,
ID *idp,
void *ctx )
{
struct bdb_info *bdb = (struct bdb_info *) be->be_private;
DB *db = bdb->bi_dn2id->bdi_db;
DBT key, data;
DBC *cursor;
int rc = 0;
diskNode *d;
char *ptr;
unsigned char *pt2;
DBTzero(&key);
key.size = sizeof(ID);
key.data = &ei->bei_id;
key.ulen = sizeof(ID);
key.flags = DB_DBT_USERMEM;
DBTzero(&data);
data.flags = DB_DBT_USERMEM;
rc = db->cursor( db, txn, &cursor, bdb->bi_db_opflags );
if ( rc ) return rc;
AC_MEMCPY( &ei->bei_id, &d->entryID, sizeof(ID) );
ei->rdn.bv_len = data.size - sizeof(diskNode) - nrlen;
ptr = d->nrdn + nrlen + 1;
strcpy( ei->rdn.bv_val, ptr );
data.ulen = sizeof(diskNode) + (SLAP_LDAPDN_MAXLEN * 2);
d = sl_malloc( data.ulen, ctx );
data.data = d;
rc = cursor->c_get( cursor, &key, &data, DB_SET );
cursor->c_close( cursor );
if ( rc == 0 ) {
if (d->nrdnlen >= 0) {
return LDAP_OTHER;
}
AC_MEMCPY( idp, &d->entryID, sizeof(ID) );
ei->bei_nrdn.bv_len = 0 - d->nrdnlen;
ber_str2bv( d->nrdn, ei->bei_nrdn.bv_len, 1, &ei->bei_nrdn );
ei->bei_rdn.bv_len = data.size - sizeof(diskNode) -
ei->bei_nrdn.bv_len;
ptr = d->nrdn + ei->bei_nrdn.bv_len + 1;
ber_str2bv( ptr, ei->bei_rdn.bv_len, 1, &ei->bei_rdn );
}
sl_free( d, ctx );
return rc;
}
@ -751,12 +832,12 @@ bdb_dn2id_children(
if ( bdb->bi_idl_cache_size ) {
rc = bdb_idl_cache_get( bdb, db, &key, NULL );
if ( rc != LDAP_NO_SUCH_OBJECT ) {
sl_free( key.data, o->o_tmpmemctx );
return rc;
}
}
#endif
DBTzero(&data);
data.data = &d;
data.ulen = sizeof(d);
data.flags = DB_DBT_USERMEM | DB_DBT_PARTIAL;
data.dlen = sizeof(d);
@ -764,7 +845,7 @@ bdb_dn2id_children(
rc = db->cursor( db, txn, &cursor, bdb->bi_db_opflags );
if ( rc ) return rc;
rc = cursor->c_get( cursor, &key, &data, DB_FIRST );
rc = cursor->c_get( cursor, &key, &data, DB_SET );
if ( rc == 0 ) {
rc = cursor->c_get( cursor, &key, &data, DB_NEXT_DUP );
}
@ -772,6 +853,16 @@ bdb_dn2id_children(
return rc;
}
/* bdb_dn2idl:
* We can't just use bdb_idl_fetch_key because
* 1 - our data items are longer than just an entry ID
* 2 - our data items are sorted alphabetically by nrdn, not by ID.
*
* We descend the tree recursively, so we define this cookie
* to hold our necessary state information. The bdb_dn2idl_internal
* function uses this cookie when calling itself.
*/
struct dn2id_cookie {
struct bdb_info *bdb;
DB *db;
@ -781,25 +872,17 @@ struct dn2id_cookie {
ID dbuf;
ID *ids;
ID tmp[BDB_IDL_DB_SIZE];
ID buf[BDB_IDL_UM_SIZE];
DBT key;
DBT data;
DBC dbc;
void *ptr;
DBC *dbc;
void *ctx;
};
/* We can't just use bdb_idl_fetch_key because
* 1 - our data items are longer than just an entry ID
* 2 - our data items are sorted alphabetically by nrdn, not by ID.
*/
int
bdb_dn2idl_internal(
struct dn2id_cookie *cx
)
{
ID *save, *i;
#ifdef SLAP_IDL_CACHE
if ( cx->bdb->bi_idl_cache_size ) {
cx->rc = bdb_idl_cache_get(cx->bdb, cx->db, &cx->key, cx->tmp);
@ -807,39 +890,60 @@ bdb_dn2idl_internal(
return cx->rc;
}
if ( cx->rc == LDAP_SUCCESS ) {
readit = 0;
goto saveit;
}
}
#endif
cx->data.data = &cx->dbuf;
cx->data.ulen = sizeof(ID);
cx->data.dlen = sizeof(ID);
cx->data.flags = DB_DBT_USERMEM | DB_DBT_PARTIAL;
cx->rc = db->cursor( cx->db, NULL, &cx->dbc, cx->bdb->bi_db_opflags );
cx->rc = cx->db->cursor( cx->db, NULL, &cx->dbc,
cx->bdb->bi_db_opflags );
if ( cx->rc ) return cx->rc;
BDB_IDL_ZERO( cx->tmp );
cx->rc = dbc->c_get( dbc, &cx->key, &cx->data, DB_FIRST );
cx->data.data = &cx->buf;
cx->data.ulen = sizeof(cx->buf);
while ( cx->rc == 0 ) {
u_int8_t *j;
size_t len;
cx->rc = dbc->c_get( dbc, &cx->key, &cx->data, DB_MULTIPLE |
DB_NEXT_DUP );
DB_MULTIPLE_INIT( cx->ptr, &cx->data );
while (cx->ptr) {
DB_MULTIPLE_NEXT( cx->ptr, &cx->data, j, len );
if (j) {
AC_MEMCPY( &cx->dbuf, j, sizeof(ID) );
bdb_idl_insert( cx->tmp, cx->dbuf );
/* The first item holds the parent ID. Ignore it. */
cx->rc = cx->dbc->c_get( cx->dbc, &cx->key, &cx->data, DB_SET );
if ( cx->rc == DB_NOTFOUND ) goto saveit;
if ( cx->rc ) return cx->rc;
/* Fetch the rest of the IDs in a loop... */
while ( (cx->rc = cx->dbc->c_get( cx->dbc, &cx->key, &cx->data,
DB_NEXT_DUP )) == 0 ) {
bdb_idl_insert( cx->tmp, cx->dbuf );
}
cx->dbc->c_close( cx->dbc );
/* If we got some records, treat as success */
if (!BDB_IDL_IS_ZERO(cx->tmp)) {
cx->rc = 0;
}
saveit:
#ifdef SLAP_IDL_CACHE
if ( cx->bdb->bi_idl_cache_max_size ) {
bdb_idl_cache_put( cx->bdb, cx->db, &cx->key, cx->tmp, cx->rc );
}
#endif
if ( cx->rc == 0 ) {
if ( cx->prefix == DN_SUBTREE_PREFIX ) {
ID *save, idcurs;
save = sl_malloc( BDB_IDL_SIZEOF( cx->tmp ), cx->ctx );
BDB_IDL_CPY( save, cx->tmp );
bdb_idl_union( cx->ids, cx->tmp );
idcurs = 0;
for ( cx->id = bdb_idl_first( save, &idcurs );
cx->id != NOID;
cx->id = bdb_idl_next( save, &idcurs )) {
bdb_dn2idl_internal( cx );
}
sl_free( save, cx->ctx );
cx->rc = 0;
} else {
BDB_IDL_CPY( cx->ids, cx->tmp );
}
}
dbc->c_close( dbc );
return cx->rc;
}
int
@ -860,11 +964,22 @@ bdb_dn2idl(
cx.ids = ids;
cx.ctx = ctx;
BDB_IDL_ZERO( ids );
if ( prefix == DN_SUBTREE_PREFIX ) {
bdb_idl_insert( ids, cx.id );
}
DBTzero(&cx.key);
cx.key.data = &cx.id;
cx.key.ulen = sizeof(ID);
cx.key.size = sizeof(ID);
cx.key.flags = DB_DBT_USERMEM;
DBTzero(&cx.data);
cx.data.data = &cx.dbuf;
cx.data.ulen = sizeof(ID);
cx.data.dlen = sizeof(ID);
cx.data.flags = DB_DBT_USERMEM | DB_DBT_PARTIAL;
return bdb_dn2idl_internal(&cx);
}

View file

@ -96,6 +96,7 @@ bdb_db_init( BackendDB *be )
ldap_pvt_thread_mutex_init( &bdb->bi_lastid_mutex );
ldap_pvt_thread_mutex_init( &bdb->bi_cache.lru_mutex );
ldap_pvt_thread_mutex_init( &bdb->bi_cache.c_dntree.bei_kids_mutex );
ldap_pvt_thread_rdwr_init ( &bdb->bi_cache.c_rwlock );
be->be_private = bdb;
@ -363,14 +364,16 @@ bdb_db_open( BackendDB *be )
rc = db->bdi_db->set_pagesize( db->bdi_db,
BDB_ID2ENTRY_PAGESIZE );
} else {
#ifdef BDB_HIER
rc = db->bdi_db->set_bt_compare( db->bdi_db,
bdb_bt_compare );
#else
rc = db->bdi_db->set_flags( db->bdi_db,
DB_DUP | DB_DUPSORT );
#ifndef BDB_HIER
rc = db->bdi_db->set_dup_compare( db->bdi_db,
bdb_bt_compare );
#else
rc = db->bdi_db->set_dup_compare( db->bdi_db,
hdb_dup_compare );
rc = db->bdi_db->set_bt_compare( db->bdi_db,
bdb_bt_compare );
#endif
rc = db->bdi_db->set_pagesize( db->bdi_db,
BDB_PAGESIZE );
@ -519,6 +522,7 @@ bdb_db_destroy( BackendDB *be )
ldap_pvt_thread_rdwr_destroy ( &bdb->bi_cache.c_rwlock );
ldap_pvt_thread_mutex_destroy( &bdb->bi_cache.lru_mutex );
ldap_pvt_thread_mutex_destroy( &bdb->bi_cache.c_dntree.bei_kids_mutex );
ldap_pvt_thread_mutex_destroy( &bdb->bi_lastid_mutex );
#ifdef SLAP_IDL_CACHE
if ( bdb->bi_idl_cache_max_size ) {

View file

@ -93,6 +93,15 @@ bdb_dn2idl(
ID *ids,
void *ctx );
#ifdef BDB_HIER
int hdb_dup_compare(
DB *db,
const DBT *usrkey,
const DBT *curkey );
int hdb_fix_dn( Entry *e );
#endif
/*
* entry.c
*/

View file

@ -113,6 +113,7 @@ Entry* bdb_tool_entry_get( BackendDB *be, ID id )
assert( slapMode & SLAP_TOOL_MODE );
assert( data.data != NULL );
#ifndef BDB_HIER
DBT2bv( &data, &bv );
rc = entry_decode( &bv, &e );
@ -120,11 +121,15 @@ Entry* bdb_tool_entry_get( BackendDB *be, ID id )
if( rc == LDAP_SUCCESS ) {
e->e_id = id;
}
#ifdef BDB_HIER
bdb_fix_dn(be, id, e);
#else
{
EntryInfo *ei = NULL;
rc = bdb_cache_find_entry_id( be, NULL, id, &ei, 0, 0,
NULL, NULL );
if ( rc == LDAP_SUCCESS )
e = ei->bei_e;
}
#endif
return e;
}