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(-)
New commits:
commit 50ad64a442495810a84558c6c17dcc2263b815b6
Author: Mark Reynolds <mreynolds(a)redhat.com>
Date: Thu Jan 16 15:21:28 2014 -0500
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)
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 b46a75b..e37f298 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;
@@ -2776,7 +2777,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);
@@ -2789,24 +2790,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
*/
@@ -3019,19 +3045,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 f1812be..0c5b2ab 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 f459e9d..a0331bb 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 */