From: Howard Chu Date: Fri, 3 Oct 2003 02:19:09 +0000 (+0000) Subject: Fix HDB's use of IDL cache X-Git-Tag: OPENLDAP_REL_ENG_2_1_MP~617 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=040a9cf64c5587210c2be80643cc536ac39486d1;p=openldap Fix HDB's use of IDL cache --- diff --git a/servers/slapd/back-bdb/back-bdb.h b/servers/slapd/back-bdb/back-bdb.h index ed32c6b6fc..1a249f41e6 100644 --- a/servers/slapd/back-bdb/back-bdb.h +++ b/servers/slapd/back-bdb/back-bdb.h @@ -87,6 +87,7 @@ typedef struct bdb_entry_info { #define CACHE_ENTRY_DELETED 1 #define CACHE_ENTRY_NO_KIDS 2 #define CACHE_ENTRY_NOT_LINKED 4 +#define CACHE_ENTRY_NO_GRANDKIDS 8 /* * remaining fields require backend cache lock to access diff --git a/servers/slapd/back-bdb/cache.c b/servers/slapd/back-bdb/cache.c index 211715ab51..f18e21ce20 100644 --- a/servers/slapd/back-bdb/cache.c +++ b/servers/slapd/back-bdb/cache.c @@ -531,6 +531,23 @@ bdb_cache_lru_add( ldap_pvt_thread_mutex_unlock( &bdb->bi_cache.lru_mutex ); } +EntryInfo * +bdb_cache_find_info( + struct bdb_info *bdb, + ID id +) +{ + EntryInfo ei, *ei2; + + ei.bei_id = id; + + ldap_pvt_thread_rdwr_rlock( &bdb->bi_cache.c_rwlock ); + ei2 = (EntryInfo *) avl_find( bdb->bi_cache.c_idtree, + (caddr_t) &ei, bdb_id_cmp ); + ldap_pvt_thread_rdwr_runlock( &bdb->bi_cache.c_rwlock ); + return ei2; +} + /* * cache_find_id - find an entry in the cache, given id. * The entry is locked for Read upon return. Call with islocked TRUE if @@ -696,7 +713,7 @@ bdb_cache_children( } rc = bdb_dn2id_children( op, txn, e ); if ( rc == DB_NOTFOUND ) { - BEI(e)->bei_state |= CACHE_ENTRY_NO_KIDS; + BEI(e)->bei_state |= CACHE_ENTRY_NO_KIDS | CACHE_ENTRY_NO_GRANDKIDS; } return rc; } @@ -729,8 +746,9 @@ bdb_cache_add( rc = bdb_entryinfo_add_internal( bdb, &ei, &new ); new->bei_e = e; e->e_private = new; - new->bei_state = CACHE_ENTRY_NO_KIDS; + new->bei_state = CACHE_ENTRY_NO_KIDS | CACHE_ENTRY_NO_GRANDKIDS; eip->bei_state &= ~CACHE_ENTRY_NO_KIDS; + if (eip->bei_parent) eip->bei_parent->bei_state &= ~CACHE_ENTRY_NO_GRANDKIDS; /* set lru mutex */ ldap_pvt_thread_mutex_lock( &bdb->bi_cache.lru_mutex ); diff --git a/servers/slapd/back-bdb/dn2id.c b/servers/slapd/back-bdb/dn2id.c index 0a5d8b6f6a..1ea506b676 100644 --- a/servers/slapd/back-bdb/dn2id.c +++ b/servers/slapd/back-bdb/dn2id.c @@ -899,26 +899,15 @@ struct dn2id_cookie { Operation *op; }; -/* Stuff for iterating over a bei_kids AVL tree and adding the - * IDs to an IDL - */ -struct apply_arg { - ID *idl; - EntryInfo **ei; -}; - static int apply_func( void *data, void *arg ) { EntryInfo *ei = data; - struct apply_arg *ap = arg; + ID *idl = arg; - bdb_idl_insert( ap->idl, ei->bei_id ); - if ( ap->ei ) { - *(ap->ei)++ = ei; - } + bdb_idl_insert( idl, ei->bei_id ); return 0; } @@ -927,7 +916,6 @@ hdb_dn2idl_internal( struct dn2id_cookie *cx ) { - EntryInfo **eilist = NULL, **ptr; #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); @@ -941,6 +929,14 @@ hdb_dn2idl_internal( #endif BDB_IDL_ZERO( cx->tmp ); + if ( !cx->ei ) { + cx->ei = bdb_cache_find_info( cx->bdb, cx->id ); + if ( !cx->ei ) { + cx->rc = DB_NOTFOUND; + goto saveit; + } + } + bdb_cache_entryinfo_lock( cx->ei ); /* If number of kids in the cache differs from on-disk, load @@ -978,14 +974,6 @@ hdb_dn2idl_internal( cx->ei->bei_dkids = dkids; } - /* If there are kids and this is a subtree search, allocate - * temp storage for the list of kids. - */ - if ( cx->prefix == DN_SUBTREE_PREFIX && cx->ei->bei_dkids > 1 ) { - eilist = cx->op->o_tmpalloc( sizeof(EntryInfo *) * cx->ei->bei_dkids, cx->op->o_tmpmemctx ); - ptr = eilist; - } - cx->data.data = cx->buf; cx->data.ulen = BDB_IDL_UM_SIZE * sizeof(ID); cx->data.flags = DB_DBT_USERMEM; @@ -1014,45 +1002,25 @@ hdb_dn2idl_internal( ei.bei_rdn.bv_val = d->nrdn + ei.bei_nrdn.bv_len + 1; bdb_idl_insert( cx->tmp, ei.bei_id ); hdb_cache_load( cx->bdb, &ei, &ei2 ); - if ( eilist ) - *ptr++ = ei2; } } } - cx->dbc->c_close( cx->dbc ); - if ( eilist ) - *ptr = NULL; + cx->rc = cx->dbc->c_close( cx->dbc ); } else { /* The in-memory cache is in sync with the on-disk data. * do we have any kids? */ cx->rc = 0; if ( cx->ei->bei_ckids > 0 ) { - struct apply_arg ap; - - /* Temp storage for subtree search */ - if ( cx->prefix == DN_SUBTREE_PREFIX ) { - eilist = cx->op->o_tmpalloc( sizeof(EntryInfo *) * cx->ei->bei_dkids, cx->op->o_tmpmemctx ); - } /* Walk the kids tree; order is irrelevant since bdb_idl_insert * will insert in sorted order. */ - ap.idl = cx->tmp; - ap.ei = eilist; - avl_apply( cx->ei->bei_kids, apply_func, &ap, -1, AVL_POSTORDER ); - if ( eilist ) { - *ap.ei = NULL; - } + avl_apply( cx->ei->bei_kids, apply_func, cx->tmp, -1, AVL_POSTORDER ); } bdb_cache_entryinfo_unlock( cx->ei ); } - /* 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 ) { @@ -1061,19 +1029,33 @@ saveit: #endif ; gotit: - if ( cx->rc == 0 ) { - /* If eilist is NULL, cx->tmp is empty... */ + if ( !BDB_IDL_IS_ZERO( cx->tmp )) { if ( cx->prefix == DN_SUBTREE_PREFIX ) { - if ( eilist ) { + if (cx->ei->bei_state & CACHE_ENTRY_NO_GRANDKIDS) { + bdb_idl_union( cx->ids, cx->tmp ); + } else { + ID *save, idcurs; + EntryInfo *ei = cx->ei; + int nokids = 1; + save = cx->op->o_tmpalloc( BDB_IDL_SIZEOF( cx->tmp ), + cx->op->o_tmpmemctx ); + BDB_IDL_CPY( save, cx->tmp ); bdb_idl_union( cx->ids, cx->tmp ); - for (ptr = eilist; *ptr; ptr++) { - cx->ei = *ptr; - cx->id = cx->ei->bei_id; + + idcurs = 0; + for ( cx->id = bdb_idl_first( save, &idcurs ); + cx->id != NOID; + cx->id = bdb_idl_next( save, &idcurs )) { + cx->ei = NULL; hdb_dn2idl_internal( cx ); + if ( !BDB_IDL_IS_ZERO( cx->tmp )) + nokids = 0; } - cx->op->o_tmpfree( eilist, cx->op->o_tmpmemctx ); - cx->rc = 0; + cx->op->o_tmpfree( save, cx->op->o_tmpmemctx ); + if ( nokids ) ei->bei_state |= CACHE_ENTRY_NO_GRANDKIDS; } + cx->rc = 0; + } else { BDB_IDL_CPY( cx->ids, cx->tmp ); } diff --git a/servers/slapd/back-bdb/proto-bdb.h b/servers/slapd/back-bdb/proto-bdb.h index ad3888086b..f9e14ee560 100644 --- a/servers/slapd/back-bdb/proto-bdb.h +++ b/servers/slapd/back-bdb/proto-bdb.h @@ -419,6 +419,7 @@ void bdb_unlocked_cache_return_entry_rw( Cache *cache, Entry *e, int rw ); #define bdb_cache_delete BDB_SYMBOL(cache_delete) #define bdb_cache_delete_cleanup BDB_SYMBOL(cache_delete_cleanup) #define bdb_cache_find_id BDB_SYMBOL(cache_find_id) +#define bdb_cache_find_info BDB_SYMBOL(cache_find_info) #define bdb_cache_find_ndn BDB_SYMBOL(cache_find_ndn) #define bdb_cache_modify BDB_SYMBOL(cache_modify) #define bdb_cache_modrdn BDB_SYMBOL(cache_modrdn) @@ -459,6 +460,10 @@ int bdb_cache_find_ndn( struct berval *ndn, EntryInfo **res ); +EntryInfo * bdb_cache_find_info( + struct bdb_info *bdb, + ID id +); int bdb_cache_find_id( Operation *op, DB_TXN *tid,