From f649d36ecf04926704add30a9f3179bd862de4c1 Mon Sep 17 00:00:00 2001 From: Mark Reynolds Date: Thu, 16 Jan 2014 15:21:28 -0500 Subject: [PATCH 80/83] Ticket 408 - Fix crash when disabling/enabling the setting Bug Description: Enabling/disabling can lead to crash as the setting was not designed to be dynamically updated. Fix Description: Do not use the actual config setting to determine if the cache is enabled. Instead we record when the cache is initialized. The server still needs to be restarted for the config change to take effect. Also freed the cache at server shtudown. https://fedorahosted.org/389/ticket/408 Reviewed by: rmeggins(Thanks!) (cherry picked from commit 03c90f04065059ee310e9fa7d98228e0aa39fa50) (cherry picked from commit 50ad64a442495810a84558c6c17dcc2263b815b6) (cherry picked from commit e0d85bead832c6aa7a2ec01157ab786a53fb5272) --- ldap/servers/slapd/back-ldbm/monitor.c | 2 +- ldap/servers/slapd/dn.c | 93 +++++++++++++++++++++++++++------- ldap/servers/slapd/main.c | 1 + ldap/servers/slapd/slapi-private.h | 2 + 4 files changed, 78 insertions(+), 20 deletions(-) diff --git a/ldap/servers/slapd/back-ldbm/monitor.c b/ldap/servers/slapd/back-ldbm/monitor.c index 3427809..409c771 100644 --- a/ldap/servers/slapd/back-ldbm/monitor.c +++ b/ldap/servers/slapd/back-ldbm/monitor.c @@ -146,7 +146,7 @@ int ldbm_back_monitor_instance_search(Slapi_PBlock *pb, Slapi_Entry *e, MSET("maxDnCacheCount"); } /* normalized dn cache stats */ - if(config_get_ndn_cache_enabled()){ + if(ndn_cache_started()){ ndn_cache_get_stats(&hits, &tries, &size, &maxsize, &count); sprintf(buf, "%" NSPRIu64, (long long unsigned int)tries); MSET("normalizedDnCacheTries"); diff --git a/ldap/servers/slapd/dn.c b/ldap/servers/slapd/dn.c index 9530b84..1eab631 100644 --- a/ldap/servers/slapd/dn.c +++ b/ldap/servers/slapd/dn.c @@ -103,6 +103,7 @@ static void ndn_cache_update_lru(struct ndn_cache_lru **node); static void ndn_cache_add(char *dn, size_t dn_len, char *ndn, size_t ndn_len); static void ndn_cache_delete(char *dn); static void ndn_cache_flush(); +static void ndn_cache_free(); static int ndn_started = 0; static PRLock *lru_lock = NULL; static Slapi_RWLock *ndn_cache_lock = NULL; @@ -2751,7 +2752,7 @@ ndn_hash_string(const void *key) void ndn_cache_init() { - if(!config_get_ndn_cache_enabled()){ + if(!config_get_ndn_cache_enabled() || ndn_started){ return; } ndn_cache_hashtable = PL_NewHashTable( NDN_CACHE_BUCKETS, ndn_hash_string, PL_CompareStrings, PL_CompareValues, 0, 0); @@ -2764,24 +2765,49 @@ ndn_cache_init() ndn_cache->cache_size = sizeof(struct ndn_cache_ctx) + sizeof(PLHashTable) + sizeof(PLHashTable); ndn_cache->head = NULL; ndn_cache->tail = NULL; - + ndn_started = 1; if ( NULL == ( lru_lock = PR_NewLock()) || NULL == ( ndn_cache_lock = slapi_new_rwlock())) { - char *errorbuf = NULL; - if(ndn_cache_hashtable){ - PL_HashTableDestroy(ndn_cache_hashtable); - } - ndn_cache_hashtable = NULL; - config_set_ndn_cache_enabled(CONFIG_NDN_CACHE, "off", errorbuf, 1 ); - slapi_counter_destroy(&ndn_cache->cache_hits); - slapi_counter_destroy(&ndn_cache->cache_tries); - slapi_counter_destroy(&ndn_cache->cache_misses); - slapi_ch_free((void **)&ndn_cache); + ndn_cache_destroy(); slapi_log_error( SLAPI_LOG_FATAL, "ndn_cache_init", "Failed to create locks. Disabling cache.\n" ); - } else { - ndn_started = 1; } } +void +ndn_cache_destroy() +{ + char *errorbuf = NULL; + + if(!ndn_started){ + return; + } + if(lru_lock){ + PR_DestroyLock(lru_lock); + lru_lock = NULL; + } + if(ndn_cache_lock){ + slapi_destroy_rwlock(ndn_cache_lock); + ndn_cache_lock = NULL; + } + if(ndn_cache_hashtable){ + ndn_cache_free(); + PL_HashTableDestroy(ndn_cache_hashtable); + ndn_cache_hashtable = NULL; + } + config_set_ndn_cache_enabled(CONFIG_NDN_CACHE, "off", errorbuf, 1 ); + slapi_counter_destroy(&ndn_cache->cache_hits); + slapi_counter_destroy(&ndn_cache->cache_tries); + slapi_counter_destroy(&ndn_cache->cache_misses); + slapi_ch_free((void **)&ndn_cache); + + ndn_started = 0; +} + +int +ndn_cache_started() +{ + return ndn_started; +} + /* * Look up this dn in the ndn cache */ @@ -2994,19 +3020,48 @@ ndn_cache_flush() slapi_log_error( SLAPI_LOG_CACHE, "ndn_cache_flush","Flushed cache.\n"); } +static void +ndn_cache_free() +{ + struct ndn_cache_lru *node, *next, *flush_node; + + if(!ndn_cache){ + return; + } + + node = ndn_cache->tail; + while(ndn_cache->cache_count){ + flush_node = node; + /* update the lru */ + next = node->prev; + if(next){ + next->next = NULL; + } + ndn_cache->tail = next; + node = next; + /* now update the hash */ + ndn_cache->cache_count--; + ndn_cache_delete(flush_node->key); + slapi_ch_free_string(&flush_node->key); + slapi_ch_free((void **)&flush_node); + } +} + /* this is already "write" locked from ndn_cache_add */ static void ndn_cache_delete(char *dn) { - struct ndn_hash_val *ht_val; + struct ndn_hash_val *ht_entry; - ht_val = (struct ndn_hash_val *)PL_HashTableLookupConst(ndn_cache_hashtable, dn); - if(ht_val){ - ndn_cache->cache_size -= ht_val->size; - slapi_ch_free_string(&ht_val->ndn); + ht_entry = (struct ndn_hash_val *)PL_HashTableLookupConst(ndn_cache_hashtable, dn); + if(ht_entry){ + ndn_cache->cache_size -= ht_entry->size; + slapi_ch_free_string(&ht_entry->ndn); + slapi_ch_free((void **)&ht_entry); PL_HashTableRemove(ndn_cache_hashtable, dn); } } + /* stats for monitor */ void ndn_cache_get_stats(PRUint64 *hits, PRUint64 *tries, size_t *size, size_t *max_size, long *count) diff --git a/ldap/servers/slapd/main.c b/ldap/servers/slapd/main.c index a17a2c5..ad8dd83 100644 --- a/ldap/servers/slapd/main.c +++ b/ldap/servers/slapd/main.c @@ -1280,6 +1280,7 @@ main( int argc, char **argv) cleanup: SSL_ShutdownServerSessionIDCache(); SSL_ClearSessionCache(); + ndn_cache_destroy(); NSS_Shutdown(); PR_Cleanup(); #ifdef _WIN32 diff --git a/ldap/servers/slapd/slapi-private.h b/ldap/servers/slapd/slapi-private.h index 194f3fd..eaa5f98 100644 --- a/ldap/servers/slapd/slapi-private.h +++ b/ldap/servers/slapd/slapi-private.h @@ -392,6 +392,8 @@ Slapi_DN *slapi_sdn_init_normdn_passin(Slapi_DN *sdn, const char *dn); char *slapi_dn_normalize_original( char *dn ); char *slapi_dn_normalize_case_original( char *dn ); void ndn_cache_init(); +void ndn_cache_destroy(); +int ndn_cache_started(); void ndn_cache_get_stats(PRUint64 *hits, PRUint64 *tries, size_t *size, size_t *max_size, long *count); #define NDN_DEFAULT_SIZE 20971520 /* 20mb - size of normalized dn cache */ -- 1.8.1.4