From bd871d710d8b33e2eb832008f888226e3a3a67a3 Mon Sep 17 00:00:00 2001 From: Howard Chu Date: Tue, 22 Apr 2003 05:14:27 +0000 Subject: [PATCH] Moved IDL cache code to standalone functions. Use IDL cache in bdb_dn2id_children. --- servers/slapd/back-bdb/dn2id.c | 122 ++++++------- servers/slapd/back-bdb/idl.c | 280 +++++++++++++++-------------- servers/slapd/back-bdb/proto-bdb.h | 20 +++ 3 files changed, 227 insertions(+), 195 deletions(-) diff --git a/servers/slapd/back-bdb/dn2id.c b/servers/slapd/back-bdb/dn2id.c index 24c958145d..aebec37282 100644 --- a/servers/slapd/back-bdb/dn2id.c +++ b/servers/slapd/back-bdb/dn2id.c @@ -376,6 +376,15 @@ bdb_dn2id_children( ((char *)key.data)[0] = DN_ONE_PREFIX; AC_MEMCPY( &((char *)key.data)[1], e->e_nname.bv_val, key.size - 1 ); +#ifdef SLAP_IDL_CACHE + 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 /* we actually could do a empty get... */ DBTzero( &data ); data.data = &id; @@ -513,26 +522,21 @@ bdb_hdb_compare( return rc; } -/* This function constructs a full DN for a given id. +/* This function constructs a full DN for a given entry. */ 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; + EntryInfo *ei; + int rlen = 0, nrlen = 0; char *ptr, *nptr; - ldap_pvt_thread_rdwr_rlock(&bdb->bi_tree_rdwr); - o = bdb_find_id_node(id, bdb->bi_tree); - rlen = be->be_suffix[0].bv_len + 1; - nrlen = be->be_nsuffix[0].bv_len + 1; - for (n = o; n && n->i_parent; n=n->i_parent) { - rlen += n->i_rdn->rdn.bv_len + 1; - nrlen += n->i_rdn->nrdn.bv_len + 1; + for ( ei = BEI(e); ei; ei=ei->bei_parent ) { + rlen += ei->bei_rdn.bv_len + 1; + nrlen += ei->bei_nrdn.bv_len + 1; } e->e_name.bv_len = rlen - 1; e->e_nname.bv_len = nrlen - 1; @@ -540,16 +544,16 @@ 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 (n = o; n && n->i_parent; n=n->i_parent) { - ptr = lutil_strcopy(ptr, n->i_rdn->rdn.bv_val); - *ptr++ = ','; - nptr = lutil_strcopy(nptr, n->i_rdn->nrdn.bv_val); - *nptr++ = ','; + for ( ei = BEI(e); ei; 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 ) { + *ptr++ = ','; + *nptr++ = ','; + } } - ldap_pvt_thread_rdwr_runlock(&bdb->bi_tree_rdwr); - - strcpy(ptr, be->be_suffix[0].bv_val); - strcpy(nptr, be->be_nsuffix[0].bv_val); + *ptr = '\0'; + *nptr = '\0'; return 0; } @@ -594,6 +598,11 @@ bdb_dn2id_add( key.size = sizeof(ID); key.flags = DB_DBT_USERMEM; +#ifdef SLAP_IDL_CACHE + if ( bdb->bi_idl_cache_size ) { + bdb_idl_cache_del( bdb, db, &key ); + } +#endif data.data = d; data.size = sizeof(diskNode) + rlen + nrlen + 2; data.flags = DB_DBT_USERMEM; @@ -648,6 +657,11 @@ bdb_dn2id_delete( data.dlen = data.size; data.flags = DB_DBT_USERMEM | DB_DBT_PARTIAL; +#ifdef SLAP_IDL_CACHE + if ( bdb->bi_idl_cache_size ) { + bdb_idl_cache_del( bdb, db, &key ); + } +#endif rc = db->cursor( db, txn, &cursor, bdb->bi_db_opflags ); if ( rc ) return rc; @@ -717,54 +731,40 @@ bdb_dn2id_children( Entry *e ) { struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private; + DB *db = bdb->bi_dn2id->bdi_db; + DBT key, data; + DBC *cursor; int rc; ID id; - idNode *n; - - rc = bdb_dn2id(be, txn, dn, &id, flags); - 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); + diskNode d; - if (!n->i_kids) - return DB_NOTFOUND; - else - return 0; -} + DBTzero(&key); + key.size = sizeof(ID); + key.data = &e->e_id; + key.flags = DB_DBT_USERMEM; -/* 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( - void *v_n, - void *v_ids -) -{ - idNode *n = v_n; - ID *ids = v_ids; - return bdb_idl_insert(ids, n->i_id); -} +#ifdef SLAP_IDL_CACHE + 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.ulen = sizeof(d); + data.flags = DB_DBT_USERMEM | DB_DBT_PARTIAL; + data.dlen = sizeof(d); -static int -insert_sub( - void *v_n, - void *v_ids -) -{ - idNode *n = v_n; - ID *ids = v_ids; - int rc; + rc = db->cursor( db, txn, &cursor, bdb->bi_db_opflags ); + if ( rc ) return 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, insert_sub, ids, -1, AVL_INORDER); - ldap_pvt_thread_rdwr_runlock(&n->i_kids_rdwr); + rc = cursor->c_get( cursor, &key, &data, DB_FIRST ); + if ( rc == 0 ) { + rc = cursor->c_get( cursor, &key, &data, DB_NEXT_DUP ); } + cursor->c_close( cursor ); return rc; } diff --git a/servers/slapd/back-bdb/idl.c b/servers/slapd/back-bdb/idl.c index 17e56241e8..42bd02dbe2 100644 --- a/servers/slapd/back-bdb/idl.c +++ b/servers/slapd/back-bdb/idl.c @@ -295,6 +295,146 @@ bdb_show_key( } } +#ifdef SLAP_IDL_CACHE + +/* Find a db/key pair in the IDL cache. If ids is non-NULL, + * copy the cached IDL into it, otherwise just return the status. + */ +int +bdb_idl_cache_get( + struct bdb_info *bdb, + DB *db, + DBT *key, + ID *ids ) +{ + bdb_idl_cache_entry_t idl_tmp; + bdb_idl_cache_entry_t *matched_idl_entry; + + DBT2bv( key, &idl_tmp.kstr ); + idl_tmp.db = db; + ldap_pvt_thread_rdwr_rlock( &bdb->bi_idl_tree_rwlock ); + matched_idl_entry = avl_find( bdb->bi_idl_tree, &idl_tmp, + bdb_idl_entry_cmp ); + if ( matched_idl_entry != NULL ) { + if ( matched_idl_entry->idl && ids ) + BDB_IDL_CPY( ids, matched_idl_entry->idl ); + ldap_pvt_thread_rdwr_runlock( &bdb->bi_idl_tree_rwlock ); + ldap_pvt_thread_mutex_lock( &bdb->bi_idl_tree_lrulock ); + IDL_LRU_DELETE( bdb, matched_idl_entry ); + IDL_LRU_ADD( bdb, matched_idl_entry ); + ldap_pvt_thread_mutex_unlock( &bdb->bi_idl_tree_lrulock ); + if ( matched_idl_entry->idl ) + return LDAP_SUCCESS; + else + return DB_NOTFOUND; + } + ldap_pvt_thread_rdwr_runlock( &bdb->bi_idl_tree_rwlock ); + + return LDAP_NO_SUCH_OBJECT; +} + +void +bdb_idl_cache_put( + struct bdb_info *bdb, + DB *db, + DBT *key, + ID *ids, + int rc ) +{ + bdb_idl_cache_entry_t idl_tmp; + bdb_idl_cache_entry_t *ee; + + ee = (bdb_idl_cache_entry_t *) ch_malloc( + sizeof( bdb_idl_cache_entry_t ) ); + ee->db = db; + if ( rc == DB_NOTFOUND) { + ee->idl = NULL; + } else { + ee->idl = (ID*) ch_malloc( BDB_IDL_SIZEOF ( ids ) ); + BDB_IDL_CPY( ee->idl, ids ); + } + ee->idl_lru_prev = NULL; + ee->idl_lru_next = NULL; + ber_dupbv( &ee->kstr, &idl_tmp.kstr ); + ldap_pvt_thread_rdwr_wlock( &bdb->bi_idl_tree_rwlock ); + if ( avl_insert( &bdb->bi_idl_tree, (caddr_t) ee, + bdb_idl_entry_cmp, avl_dup_error )) + { + ch_free( ee->kstr.bv_val ); + ch_free( ee->idl ); + ch_free( ee ); + ldap_pvt_thread_rdwr_wunlock( &bdb->bi_idl_tree_rwlock ); + return; + } + ldap_pvt_thread_mutex_lock( &bdb->bi_idl_tree_lrulock ); + IDL_LRU_ADD( bdb, ee ); + if ( ++bdb->bi_idl_cache_size > bdb->bi_idl_cache_max_size ) { + int i = 0; + while ( bdb->bi_idl_lru_tail != NULL && i < 10 ) { + ee = bdb->bi_idl_lru_tail; + if ( avl_delete( &bdb->bi_idl_tree, (caddr_t) ee, + bdb_idl_entry_cmp ) == NULL ) { +#ifdef NEW_LOGGING + LDAP_LOG( INDEX, ERR, + "bdb_idl_cache_put: AVL delete failed\n", + 0, 0, 0 ); +#else + Debug( LDAP_DEBUG_ANY, "=> bdb_idl_cache_put: " + "AVL delete failed\n", + 0, 0, 0 ); +#endif + } + IDL_LRU_DELETE( bdb, ee ); + i++; + --bdb->bi_idl_cache_size; + ch_free( ee->kstr.bv_val ); + ch_free( ee->idl ); + ch_free( ee ); + } + } + + ldap_pvt_thread_mutex_unlock( &bdb->bi_idl_tree_lrulock ); + ldap_pvt_thread_rdwr_wunlock( &bdb->bi_idl_tree_rwlock ); +} + +void +bdb_idl_cache_del( + struct bdb_info *bdb, + DB *db, + DBT *key ) +{ + bdb_idl_cache_entry_t *matched_idl_entry, idl_tmp; + DBT2bv( key, &idl_tmp.kstr ); + idl_tmp.db = db; + ldap_pvt_thread_rdwr_wlock( &bdb->bi_idl_tree_rwlock ); + matched_idl_entry = avl_find( bdb->bi_idl_tree, &idl_tmp, + bdb_idl_entry_cmp ); + if ( matched_idl_entry != NULL ) { + if ( avl_delete( &bdb->bi_idl_tree, (caddr_t) matched_idl_entry, + bdb_idl_entry_cmp ) == NULL ) { +#ifdef NEW_LOGGING + LDAP_LOG( INDEX, ERR, + "bdb_idl_cache_del: AVL delete failed\n", + 0, 0, 0 ); +#else + Debug( LDAP_DEBUG_ANY, "=> bdb_idl_cache_del: " + "AVL delete failed\n", + 0, 0, 0 ); +#endif + } + --bdb->bi_idl_cache_size; + ldap_pvt_thread_mutex_lock( &bdb->bi_idl_tree_lrulock ); + IDL_LRU_DELETE( bdb, matched_idl_entry ); + ldap_pvt_thread_mutex_unlock( &bdb->bi_idl_tree_lrulock ); + free( matched_idl_entry->kstr.bv_val ); + if ( matched_idl_entry->idl ) + free( matched_idl_entry->idl ); + free( matched_idl_entry ); + } + ldap_pvt_thread_rdwr_wunlock( &bdb->bi_idl_tree_rwlock ); +} +#endif + int bdb_idl_fetch_key( BackendDB *be, @@ -312,9 +452,6 @@ bdb_idl_fetch_key( size_t len; int rc2; int flags = bdb->bi_db_opflags | DB_MULTIPLE; -#ifdef SLAP_IDL_CACHE - bdb_idl_cache_entry_t idl_tmp; -#endif /* If using BerkeleyDB 4.0, the buf must be large enough to * grab the entire IDL in one get(), otherwise BDB will leak @@ -348,27 +485,9 @@ bdb_idl_fetch_key( assert( ids != NULL ); #ifdef SLAP_IDL_CACHE - if ( bdb->bi_idl_cache_max_size ) { - bdb_idl_cache_entry_t *matched_idl_entry; - DBT2bv( key, &idl_tmp.kstr ); - idl_tmp.db = db; - ldap_pvt_thread_rdwr_rlock( &bdb->bi_idl_tree_rwlock ); - matched_idl_entry = avl_find( bdb->bi_idl_tree, &idl_tmp, - bdb_idl_entry_cmp ); - if ( matched_idl_entry != NULL ) { - if ( matched_idl_entry->idl ) - BDB_IDL_CPY( ids, matched_idl_entry->idl ); - ldap_pvt_thread_rdwr_runlock( &bdb->bi_idl_tree_rwlock ); - ldap_pvt_thread_mutex_lock( &bdb->bi_idl_tree_lrulock ); - IDL_LRU_DELETE( bdb, matched_idl_entry ); - IDL_LRU_ADD( bdb, matched_idl_entry ); - ldap_pvt_thread_mutex_unlock( &bdb->bi_idl_tree_lrulock ); - if ( matched_idl_entry->idl ) - return LDAP_SUCCESS; - else - return DB_NOTFOUND; - } - ldap_pvt_thread_rdwr_runlock( &bdb->bi_idl_tree_rwlock ); + if ( bdb->bi_idl_cache_size ) { + rc = bdb_idl_cache_get( bdb, db, key, ids ); + if ( rc != LDAP_NO_SUCH_OBJECT ) return rc; } #endif @@ -491,58 +610,7 @@ bdb_idl_fetch_key( #ifdef SLAP_IDL_CACHE if ( bdb->bi_idl_cache_max_size ) { - bdb_idl_cache_entry_t *ee; - ee = (bdb_idl_cache_entry_t *) ch_malloc( - sizeof( bdb_idl_cache_entry_t ) ); - ee->db = db; - if ( rc == DB_NOTFOUND) { - ee->idl = NULL; - } else { - ee->idl = (ID*) ch_malloc( BDB_IDL_SIZEOF ( ids ) ); - BDB_IDL_CPY( ee->idl, ids ); - } - ee->idl_lru_prev = NULL; - ee->idl_lru_next = NULL; - ber_dupbv( &ee->kstr, &idl_tmp.kstr ); - ldap_pvt_thread_rdwr_wlock( &bdb->bi_idl_tree_rwlock ); - if ( avl_insert( &bdb->bi_idl_tree, (caddr_t) ee, - bdb_idl_entry_cmp, avl_dup_error )) - { - ch_free( ee->kstr.bv_val ); - ch_free( ee->idl ); - ch_free( ee ); - ldap_pvt_thread_rdwr_wunlock( &bdb->bi_idl_tree_rwlock ); - return rc; - } - ldap_pvt_thread_mutex_lock( &bdb->bi_idl_tree_lrulock ); - IDL_LRU_ADD( bdb, ee ); - if ( ++bdb->bi_idl_cache_size > bdb->bi_idl_cache_max_size ) { - int i = 0; - while ( bdb->bi_idl_lru_tail != NULL && i < 10 ) { - ee = bdb->bi_idl_lru_tail; - if ( avl_delete( &bdb->bi_idl_tree, (caddr_t) ee, - bdb_idl_entry_cmp ) == NULL ) { -#ifdef NEW_LOGGING - LDAP_LOG( INDEX, ERR, - "bdb_idl_fetch_key: AVL delete failed\n", - 0, 0, 0 ); -#else - Debug( LDAP_DEBUG_ANY, "=> bdb_idl_fetch_key: " - "AVL delete failed\n", - 0, 0, 0 ); -#endif - } - IDL_LRU_DELETE( bdb, ee ); - i++; - --bdb->bi_idl_cache_size; - ch_free( ee->kstr.bv_val ); - ch_free( ee->idl ); - ch_free( ee ); - } - } - - ldap_pvt_thread_mutex_unlock( &bdb->bi_idl_tree_lrulock ); - ldap_pvt_thread_rdwr_wunlock( &bdb->bi_idl_tree_rwlock ); + bdb_idl_cache_put( bdb, db, key, ids, rc ); } #endif @@ -582,35 +650,7 @@ bdb_idl_insert_key( #ifdef SLAP_IDL_CACHE if ( bdb->bi_idl_cache_size ) { - bdb_idl_cache_entry_t *matched_idl_entry, idl_tmp; - DBT2bv( key, &idl_tmp.kstr ); - idl_tmp.db = db; - ldap_pvt_thread_rdwr_wlock( &bdb->bi_idl_tree_rwlock ); - matched_idl_entry = avl_find( bdb->bi_idl_tree, &idl_tmp, - bdb_idl_entry_cmp ); - if ( matched_idl_entry != NULL ) { - if ( avl_delete( &bdb->bi_idl_tree, (caddr_t) matched_idl_entry, - bdb_idl_entry_cmp ) == NULL ) { -#ifdef NEW_LOGGING - LDAP_LOG( INDEX, ERR, - "bdb_idl_fetch_key: AVL delete failed\n", - 0, 0, 0 ); -#else - Debug( LDAP_DEBUG_ANY, "=> bdb_idl_fetch_key: " - "AVL delete failed\n", - 0, 0, 0 ); -#endif - } - --bdb->bi_idl_cache_size; - ldap_pvt_thread_mutex_lock( &bdb->bi_idl_tree_lrulock ); - IDL_LRU_DELETE( bdb, matched_idl_entry ); - ldap_pvt_thread_mutex_unlock( &bdb->bi_idl_tree_lrulock ); - free( matched_idl_entry->kstr.bv_val ); - if ( matched_idl_entry->idl ) - free( matched_idl_entry->idl ); - free( matched_idl_entry ); - } - ldap_pvt_thread_rdwr_wunlock( &bdb->bi_idl_tree_rwlock ); + bdb_idl_cache_del( bdb, db, key ); } #endif @@ -807,35 +847,7 @@ bdb_idl_delete_key( #ifdef SLAP_IDL_CACHE if ( bdb->bi_idl_cache_max_size ) { - bdb_idl_cache_entry_t *matched_idl_entry, idl_tmp; - DBT2bv( key, &idl_tmp.kstr ); - idl_tmp.db = db; - ldap_pvt_thread_rdwr_wlock( &bdb->bi_idl_tree_rwlock ); - matched_idl_entry = avl_find( bdb->bi_idl_tree, &idl_tmp, - bdb_idl_entry_cmp ); - if ( matched_idl_entry != NULL ) { - if ( avl_delete( &bdb->bi_idl_tree, (caddr_t) matched_idl_entry, - bdb_idl_entry_cmp ) == NULL ) { -#ifdef NEW_LOGGING - LDAP_LOG( INDEX, ERR, - "bdb_idl_fetch_key: AVL delete failed\n", - 0, 0, 0 ); -#else - Debug( LDAP_DEBUG_ANY, "=> bdb_idl_fetch_key: " - "AVL delete failed\n", - 0, 0, 0 ); -#endif - } - --bdb->bi_idl_cache_size; - ldap_pvt_thread_mutex_lock( &bdb->bi_idl_tree_lrulock ); - IDL_LRU_DELETE( bdb, matched_idl_entry ); - ldap_pvt_thread_mutex_unlock( &bdb->bi_idl_tree_lrulock ); - free( matched_idl_entry->kstr.bv_val ); - if ( matched_idl_entry->idl ) - free( matched_idl_entry->idl ); - free( matched_idl_entry ); - } - ldap_pvt_thread_rdwr_wunlock( &bdb->bi_idl_tree_rwlock ); + bdb_idl_cache_del( bdb, db, key ); } #endif diff --git a/servers/slapd/back-bdb/proto-bdb.h b/servers/slapd/back-bdb/proto-bdb.h index bbfa5b4d20..43a6f54869 100644 --- a/servers/slapd/back-bdb/proto-bdb.h +++ b/servers/slapd/back-bdb/proto-bdb.h @@ -145,6 +145,26 @@ void bdb_entry_free ( Entry *e ); */ #ifdef SLAP_IDL_CACHE int bdb_idl_entry_cmp( const void*, const void* ); + +int bdb_idl_cache_get( + struct bdb_info *bdb, + DB *db, + DBT *key, + ID *ids ); + +void +bdb_idl_cache_put( + struct bdb_info *bdb, + DB *db, + DBT *key, + ID *ids, + int rc ); + +void +bdb_idl_cache_del( + struct bdb_info *bdb, + DB *db, + DBT *key ); #endif unsigned bdb_idl_search( ID *ids, ID id ); -- 2.39.5