From f58a646ad6bbdff47071c427a75d5f8a93b9cf86 Mon Sep 17 00:00:00 2001 From: Howard Chu Date: Thu, 23 Dec 2010 00:16:19 +0000 Subject: [PATCH] ITS#6660 preliminary fix. debug additions need to be cleaned up. --- servers/slapd/back-bdb/cache.c | 87 +++++++++++++++++++++--------- servers/slapd/back-bdb/proto-bdb.h | 1 + 2 files changed, 63 insertions(+), 25 deletions(-) diff --git a/servers/slapd/back-bdb/cache.c b/servers/slapd/back-bdb/cache.c index a42db5c5a2..6da6266820 100644 --- a/servers/slapd/back-bdb/cache.c +++ b/servers/slapd/back-bdb/cache.c @@ -257,6 +257,11 @@ bdb_cache_entry_db_unlock ( struct bdb_info *bdb, DB_LOCK *lock ) #endif } +/* These should move behind SLAPD_UNUSED */ +static ldap_pvt_thread_mutex_t bdb_ncmutex; +static int bdb_notcached; +static int bdb_ncfreed; + void bdb_cache_return_entry_rw( struct bdb_info *bdb, Entry *e, int rw, DB_LOCK *lock ) @@ -265,9 +270,10 @@ bdb_cache_return_entry_rw( struct bdb_info *bdb, Entry *e, int free = 0; ei = e->e_private; - if ( ei && - ( ei->bei_state & CACHE_ENTRY_NOT_CACHED ) && - ( bdb_cache_entryinfo_trylock( ei ) == 0 )) { + if ( ei && ( ei->bei_state & CACHE_ENTRY_NOT_CACHED )) { + ldap_pvt_thread_mutex_lock(&bdb_ncmutex); + bdb_notcached++; + bdb_cache_entryinfo_lock( ei ); if ( ei->bei_state & CACHE_ENTRY_NOT_CACHED ) { /* Releasing the entry can only be done when * we know that nobody else is using it, i.e we @@ -282,8 +288,10 @@ bdb_cache_return_entry_rw( struct bdb_info *bdb, Entry *e, ei->bei_e = NULL; ei->bei_state ^= CACHE_ENTRY_NOT_CACHED; free = 1; + bdb_ncfreed++; } bdb_cache_entryinfo_unlock( ei ); + ldap_pvt_thread_mutex_unlock(&bdb_ncmutex); } bdb_cache_entry_db_unlock( bdb, lock ); if ( free ) { @@ -968,20 +976,7 @@ load1: if ( !(*eip)->bei_e && !((*eip)->bei_state & CACHE_ENTRY_LOADING)) { load = 1; (*eip)->bei_state |= CACHE_ENTRY_LOADING; - } - - if ( !load ) { - /* Clear the uncached state if we are not - * loading it, i.e it is already cached or - * another thread is currently loading it. - */ - if ( (*eip)->bei_state & CACHE_ENTRY_NOT_CACHED ) { - (*eip)->bei_state &= ~CACHE_ENTRY_NOT_CACHED; - ldap_pvt_thread_mutex_lock( &bdb->bi_cache.c_count_mutex ); - ++bdb->bi_cache.c_cursize; - ldap_pvt_thread_mutex_unlock( &bdb->bi_cache.c_count_mutex ); - } - flag &= ~ID_NOCACHE; + flag |= ID_CHKPURGE; } if ( flag & ID_LOCKED ) { @@ -1007,21 +1002,24 @@ load1: ldap_pvt_thread_yield(); bdb_fix_dn( ep, 0 ); #endif + bdb_cache_entryinfo_lock( *eip ); + (*eip)->bei_e = ep; #ifdef SLAP_ZONE_ALLOC (*eip)->bei_zseq = *((ber_len_t *)ep - 2); #endif ep = NULL; - bdb_cache_lru_link( bdb, *eip ); - if (( flag & ID_NOCACHE ) && - ( bdb_cache_entryinfo_trylock( *eip ) == 0 )) { + if ( flag & ID_NOCACHE ) { /* Set the cached state only if no other thread * found the info while we were loading the entry. */ - if ( (*eip)->bei_finders == 1 ) + if ( (*eip)->bei_finders == 1 ) { (*eip)->bei_state |= CACHE_ENTRY_NOT_CACHED; - bdb_cache_entryinfo_unlock( *eip ); + flag ^= ID_CHKPURGE; + } } + bdb_cache_entryinfo_unlock( *eip ); + bdb_cache_lru_link( bdb, *eip ); } if ( rc == 0 ) { /* If we succeeded, downgrade back to a readlock. */ @@ -1057,8 +1055,17 @@ load1: } bdb_cache_entryinfo_lock( *eip ); (*eip)->bei_finders--; - if ( load ) + if ( load ) { (*eip)->bei_state ^= CACHE_ENTRY_LOADING; + } else { + /* Clear the uncached state if we didn't + * load it, i.e it was already cached. + */ + if ( (*eip)->bei_state & CACHE_ENTRY_NOT_CACHED ) { + (*eip)->bei_state ^= CACHE_ENTRY_NOT_CACHED; + flag |= ID_CHKPURGE; + } + } bdb_cache_entryinfo_unlock( *eip ); } } @@ -1077,9 +1084,9 @@ load1: if ( rc == 0 ) { int purge = 0; - if (( load && !( flag & ID_NOCACHE )) || bdb->bi_cache.c_eimax ) { + if (( flag & ID_CHKPURGE ) || bdb->bi_cache.c_eimax ) { ldap_pvt_thread_mutex_lock( &bdb->bi_cache.c_count_mutex ); - if ( load && !( flag & ID_NOCACHE )) { + if ( flag & ID_CHKPURGE ) { bdb->bi_cache.c_cursize++; if ( !bdb->bi_cache.c_purging && bdb->bi_cache.c_cursize > bdb->bi_cache.c_maxsize ) { purge = 1; @@ -1533,6 +1540,36 @@ bdb_cache_release_all( Cache *cache ) } #ifdef LDAP_DEBUG +static void +bdb_lru_count( Cache *cache ) +{ + EntryInfo *e; + int ei = 0, ent = 0, nc = 0; + + for ( e = cache->c_lrutail; ; ) { + ei++; + if ( e->bei_e ) { + ent++; + if ( e->bei_state & CACHE_ENTRY_NOT_CACHED ) + nc++; + fprintf( stderr, "ei %d entry %p dn %s\n", ei, e->bei_e, e->bei_e->e_name.bv_val ); + } + e = e->bei_lrunext; + if ( e == cache->c_lrutail ) + break; + } + fprintf( stderr, "counted %d entryInfos and %d entries, %d notcached\n", + ei, ent, nc ); + ei = 0; + for ( e = cache->c_lrutail; ; ) { + ei++; + e = e->bei_lruprev; + if ( e == cache->c_lrutail ) + break; + } + fprintf( stderr, "counted %d entryInfos (on lruprev)\n", ei ); +} + #ifdef SLAPD_UNUSED static void bdb_lru_print( Cache *cache ) diff --git a/servers/slapd/back-bdb/proto-bdb.h b/servers/slapd/back-bdb/proto-bdb.h index b0243553a2..a321dca0b7 100644 --- a/servers/slapd/back-bdb/proto-bdb.h +++ b/servers/slapd/back-bdb/proto-bdb.h @@ -547,6 +547,7 @@ int bdb_cache_find_ndn( #define ID_LOCKED 1 #define ID_NOCACHE 2 #define ID_NOENTRY 4 +#define ID_CHKPURGE 8 int bdb_cache_find_id( Operation *op, DB_TXN *tid, -- 2.39.5