From aa897eae900114272259fda8e1240e661c4a5bc5 Mon Sep 17 00:00:00 2001 From: Howard Chu Date: Thu, 8 Sep 2005 15:28:36 +0000 Subject: [PATCH] ITS#4010 fixes complaint, larger problem remains --- servers/slapd/back-bdb/back-bdb.h | 1 + servers/slapd/back-bdb/cache.c | 99 +++++++++++++++++++++---------- 2 files changed, 70 insertions(+), 30 deletions(-) diff --git a/servers/slapd/back-bdb/back-bdb.h b/servers/slapd/back-bdb/back-bdb.h index e28d7c189b..3f3401df5c 100644 --- a/servers/slapd/back-bdb/back-bdb.h +++ b/servers/slapd/back-bdb/back-bdb.h @@ -124,6 +124,7 @@ typedef struct bdb_cache { int c_maxsize; int c_cursize; int c_eiused; /* EntryInfo's in use */ + int c_leaves; /* EntryInfo leaf nodes */ EntryInfo c_dntree; EntryInfo *c_eifree; /* free list */ Avlnode *c_idtree; diff --git a/servers/slapd/back-bdb/cache.c b/servers/slapd/back-bdb/cache.c index d98ed21ecc..efd963a82f 100644 --- a/servers/slapd/back-bdb/cache.c +++ b/servers/slapd/back-bdb/cache.c @@ -257,6 +257,13 @@ bdb_entryinfo_add_internal( } else { bdb->bi_cache.c_eiused++; ber_dupbv( &ei2->bei_nrdn, &ei->bei_nrdn ); + + /* This is a new leaf node. But if parent had no kids, then it was + * a leaf and we would be decrementing that. So, only increment if + * the parent already has kids. + */ + if ( ei->bei_parent->bei_kids || !ei->bei_parent->bei_id ) + bdb->bi_cache.c_leaves++; avl_insert( &ei->bei_parent->bei_kids, ei2, bdb_rdn_cmp, avl_dup_error ); #ifdef BDB_HIER @@ -387,7 +394,7 @@ hdb_cache_find_parent( struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private; EntryInfo ei, eip, *ei2 = NULL, *ein = NULL, *eir = NULL; int rc; - int addlru = 1; + int addlru = 0; ei.bei_id = id; ei.bei_kids = NULL; @@ -435,11 +442,15 @@ hdb_cache_find_parent( ein->bei_ckids++; bdb_cache_entryinfo_unlock( ein ); } + addlru = 0; - if ( !eir ) { - addlru = 0; - } } + if ( addlru ) { + ldap_pvt_thread_mutex_lock( &bdb->bi_cache.lru_mutex ); + LRU_ADD( &bdb->bi_cache, ein ); + ldap_pvt_thread_mutex_unlock( &bdb->bi_cache.lru_mutex ); + } + addlru = 1; /* If this is the first time, save this node * to be returned later. @@ -457,6 +468,8 @@ hdb_cache_find_parent( ei2 = &bdb->bi_cache.c_dntree; } bdb->bi_cache.c_eiused++; + if ( ei2 && ( ei2->bei_kids || !ei2->bei_id )) + bdb->bi_cache.c_leaves++; ldap_pvt_thread_rdwr_wunlock( &bdb->bi_cache.c_rwlock ); /* Got the parent, link in and we're done. */ @@ -555,31 +568,53 @@ bdb_cache_lru_add( */ if ( bdb_cache_entry_db_lock( bdb->bi_dbenv, bdb->bi_cache.c_locker, elru, 1, 1, lockp ) == 0 ) { - int stop = 0; - /* If there's no entry, or this node is in - * the process of linking into the cache, + int stop = 0, decr = 0; + + /* If this node is in the process of linking into the cache, * or this node is being deleted, skip it. */ - if ( !elru->bei_e || (elru->bei_state & - ( CACHE_ENTRY_NOT_LINKED | CACHE_ENTRY_DELETED ))) { + if ( elru->bei_state & + ( CACHE_ENTRY_NOT_LINKED | CACHE_ENTRY_DELETED )) { bdb_cache_entry_db_unlock( bdb->bi_dbenv, lockp ); continue; } - LRU_DELETE( &bdb->bi_cache, elru ); - elru->bei_e->e_private = NULL; + /* Free entry for this node if it's present */ + if ( elru->bei_e ) { + elru->bei_e->e_private = NULL; #ifdef SLAP_ZONE_ALLOC - bdb_entry_return( bdb, elru->bei_e, elru->bei_zseq ); + bdb_entry_return( bdb, elru->bei_e, elru->bei_zseq ); #else - bdb_entry_return( elru->bei_e ); + bdb_entry_return( elru->bei_e ); #endif - elru->bei_e = NULL; + elru->bei_e = NULL; + decr = 1; + } + /* ITS#4010 if we're in slapcat, and this node is a leaf + * node, free it. + * + * FIXME: we need to do this for slapd as well, (which is + * why we compute bi_cache.c_leaves now) but at the moment + * we can't because it causes unresolvable deadlocks. + */ + if ( slapMode & SLAP_TOOL_READONLY ) { + if ( !elru->bei_kids ) { + /* This does LRU_DELETE for us */ + bdb_cache_delete_internal( &bdb->bi_cache, elru, 0 ); + bdb_cache_delete_cleanup( &bdb->bi_cache, elru ); + } + /* Leave node on LRU list for a future pass */ + } else { + LRU_DELETE( &bdb->bi_cache, elru ); + } + bdb_cache_entry_db_unlock( bdb->bi_dbenv, lockp ); + ldap_pvt_thread_rdwr_wlock( &bdb->bi_cache.c_rwlock ); - --bdb->bi_cache.c_cursize; + if ( decr ) + --bdb->bi_cache.c_cursize; if (bdb->bi_cache.c_cursize <= bdb->bi_cache.c_maxsize) stop = 1; ldap_pvt_thread_rdwr_wunlock( &bdb->bi_cache.c_rwlock ); - bdb_cache_entry_db_unlock( bdb->bi_dbenv, lockp ); if (stop) break; } } @@ -1085,7 +1120,15 @@ bdb_cache_delete( /* set lru mutex */ ldap_pvt_thread_mutex_lock( &cache->lru_mutex ); + + /* set cache write lock */ + ldap_pvt_thread_rdwr_wlock( &cache->c_rwlock ); + rc = bdb_cache_delete_internal( cache, e->e_private, 1 ); + + /* free cache write lock */ + ldap_pvt_thread_rdwr_wunlock( &cache->c_rwlock ); + /* free lru mutex */ ldap_pvt_thread_mutex_unlock( &cache->lru_mutex ); @@ -1137,9 +1180,6 @@ bdb_cache_delete_internal( { int rc = 0; /* return code */ - /* set cache write lock */ - ldap_pvt_thread_rdwr_wlock( &cache->c_rwlock ); - /* Lock the parent's kids tree */ bdb_cache_entryinfo_lock( e->bei_parent ); @@ -1153,27 +1193,25 @@ bdb_cache_delete_internal( { rc = -1; } + if ( e->bei_parent->bei_kids ) + cache->c_leaves--; /* id tree */ if ( avl_delete( &cache->c_idtree, (caddr_t) e, bdb_id_cmp ) == NULL ) { rc = -1; } - if (rc != 0) { - return rc; - } - - cache->c_eiused--; + if ( rc == 0 ){ + cache->c_eiused--; - /* lru */ - LRU_DELETE( cache, e ); - if ( e->bei_e ) cache->c_cursize--; + /* lru */ + LRU_DELETE( cache, e ); + if ( e->bei_e ) cache->c_cursize--; + } - /* free cache write lock */ - ldap_pvt_thread_rdwr_wunlock( &cache->c_rwlock ); bdb_cache_entryinfo_unlock( e->bei_parent ); - return( 0 ); + return( rc ); } static void @@ -1212,6 +1250,7 @@ bdb_cache_release_all( Cache *cache ) } cache->c_cursize = 0; cache->c_eiused = 0; + cache->c_leaves = 0; cache->c_idtree = NULL; cache->c_lruhead = NULL; cache->c_lrutail = NULL; -- 2.39.5