From e1775dcabc1cc88be12703ad62bbaf5341b8f8a4 Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Fri, 19 Dec 2014 16:36:11 -0500
Subject: [PATCH 286/305] Ticket 408 - Backport of Normalized DN Cache
https://fedorahosted.org/389/ticket/408
(cherry picked from commit 2a8da7ea76d15906fdb98b47534fc3447f12c752)
---
ldap/ldif/template-dse.ldif.in | 3 +-
ldap/servers/slapd/attrsyntax.c | 23 --
ldap/servers/slapd/back-ldbm/monitor.c | 26 ++-
ldap/servers/slapd/dn.c | 401 +++++++++++++++++++++++++++++++++
ldap/servers/slapd/libglobs.c | 76 ++++++-
ldap/servers/slapd/main.c | 4 +
ldap/servers/slapd/proto-slap.h | 12 +
ldap/servers/slapd/schema.c | 17 --
ldap/servers/slapd/slap.h | 10 +
ldap/servers/slapd/slapi-private.h | 8 +-
10 files changed, 532 insertions(+), 48 deletions(-)
diff --git a/ldap/ldif/template-dse.ldif.in b/ldap/ldif/template-dse.ldif.in
index ddf2b35..c626726 100644
--- a/ldap/ldif/template-dse.ldif.in
+++ b/ldap/ldif/template-dse.ldif.in
@@ -53,9 +53,10 @@ nsslapd-auditlog-maxlogsize: 100
nsslapd-auditlog-logrotationtime: 1
nsslapd-auditlog-logrotationtimeunit: day
nsslapd-rootdn: %rootdn%
+nsslapd-rootpw: %ds_passwd%
nsslapd-maxdescriptors: 1024
nsslapd-max-filter-nest-level: 40
-nsslapd-rootpw: %ds_passwd%
+nsslapd-ndn-cache-enabled: off
dn: cn=features,cn=config
objectclass: top
diff --git a/ldap/servers/slapd/attrsyntax.c b/ldap/servers/slapd/attrsyntax.c
index 79736b5..75114e0 100644
--- a/ldap/servers/slapd/attrsyntax.c
+++ b/ldap/servers/slapd/attrsyntax.c
@@ -219,29 +219,6 @@ attr_syntax_new()
}
/*
- * hashNocaseString - used for case insensitive hash lookups
- */
-static PLHashNumber
-hashNocaseString(const void *key)
-{
- PLHashNumber h = 0;
- const unsigned char *s;
-
- for (s = key; *s; s++)
- h = (h >> 28) ^ (h << 4) ^ (tolower(*s));
- return h;
-}
-
-/*
- * hashNocaseCompare - used for case insensitive hash key comparisons
- */
-static PRIntn
-hashNocaseCompare(const void *v1, const void *v2)
-{
- return (strcasecmp((char *)v1, (char *)v2) == 0);
-}
-
-/*
* Given an OID, return the syntax info. If there is more than one
* attribute syntax with the same OID (i.e. aliases), the first one
* will be returned. This is usually the "canonical" one, but it may
diff --git a/ldap/servers/slapd/back-ldbm/monitor.c b/ldap/servers/slapd/back-ldbm/monitor.c
index e3e1fb5..52a8ace 100644
--- a/ldap/servers/slapd/back-ldbm/monitor.c
+++ b/ldap/servers/slapd/back-ldbm/monitor.c
@@ -70,8 +70,8 @@ int ldbm_back_monitor_instance_search(Slapi_PBlock *pb, Slapi_Entry *e,
struct berval *vals[2];
char buf[BUFSIZ];
PRUint64 hits, tries;
- long nentries,maxentries;
- size_t size,maxsize;
+ long nentries, maxentries, count;
+ size_t size, maxsize;
/* NPCTE fix for bugid 544365, esc 0. <P.R> <04-Jul-2001> */
struct stat astat;
/* end of NPCTE fix for bugid 544365 */
@@ -145,6 +145,28 @@ int ldbm_back_monitor_instance_search(Slapi_PBlock *pb, Slapi_Entry *e,
sprintf(buf, "%ld", maxentries);
MSET("maxDnCacheCount");
}
+ /* normalized dn cache stats */
+ if(ndn_cache_started()){
+ ndn_cache_get_stats(&hits, &tries, &size, &maxsize, &count);
+ sprintf(buf, "%" NSPRIu64, tries);
+ MSET("normalizedDnCacheTries");
+ sprintf(buf, "%" NSPRIu64, hits);
+ MSET("normalizedDnCacheHits");
+ sprintf(buf, "%" NSPRIu64, tries - hits);
+ MSET("normalizedDnCacheMisses");
+ sprintf(buf, "%lu", (unsigned long)(100.0*(double)hits / (double)(tries > 0 ? tries : 1)));
+ MSET("normalizedDnCacheHitRatio");
+ sprintf(buf, "%lu", size);
+ MSET("currentNormalizedDnCacheSize");
+ if(maxsize == 0){
+ sprintf(buf, "%d", -1);
+ } else {
+ sprintf(buf, "%lu", maxsize);
+ }
+ MSET("maxNormalizedDnCacheSize");
+ sprintf(buf, "%ld", count);
+ MSET("currentNormalizedDnCacheCount");
+ }
#ifdef DEBUG
{
diff --git a/ldap/servers/slapd/dn.c b/ldap/servers/slapd/dn.c
index 804d56e..283f265 100644
--- a/ldap/servers/slapd/dn.c
+++ b/ldap/servers/slapd/dn.c
@@ -51,6 +51,7 @@
#include <sys/socket.h>
#endif
#include "slap.h"
+#include <plhash.h>
#undef SDN_DEBUG
@@ -61,6 +62,53 @@ static void sort_rdn_avs( struct berval *avs, int count, int escape );
static int rdn_av_cmp( struct berval *av1, struct berval *av2 );
static void rdn_av_swap( struct berval *av1, struct berval *av2, int escape );
+/* normalized dn cache related definitions*/
+struct
+ndn_cache_lru
+{
+ struct ndn_cache_lru *prev;
+ struct ndn_cache_lru *next;
+ char *key;
+};
+
+struct
+ndn_cache_ctx
+{
+ struct ndn_cache_lru *head;
+ struct ndn_cache_lru *tail;
+ Slapi_Counter *cache_hits;
+ Slapi_Counter *cache_tries;
+ Slapi_Counter *cache_misses;
+ size_t cache_size;
+ size_t cache_max_size;
+ long cache_count;
+};
+
+struct
+ndn_hash_val
+{
+ char *ndn;
+ size_t len;
+ int size;
+ struct ndn_cache_lru *lru_node; /* used to speed up lru shuffling */
+};
+
+#define NDN_FLUSH_COUNT 10000 /* number of DN's to remove when cache fills up */
+#define NDN_MIN_COUNT 1000 /* the minimum number of DN's to keep in the cache */
+#define NDN_CACHE_BUCKETS 2053 /* prime number */
+
+static PLHashNumber ndn_hash_string(const void *key);
+static int ndn_cache_lookup(char *dn, size_t dn_len, char **result, char **udn, int *rc);
+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;
+static struct ndn_cache_ctx *ndn_cache = NULL;
+static PLHashTable *ndn_cache_hashtable = NULL;
#define ISBLANK(c) ((c) == ' ')
#define ISBLANKSTR(s) (((*(s)) == '2') && (*((s)+1) == '0'))
@@ -487,6 +535,7 @@ slapi_dn_normalize_ext(char *src, size_t src_len, char **dest, size_t *dest_len)
char *ends = NULL;
char *endd = NULL;
char *lastesc = NULL;
+ char *udn;
/* rdn avs for the main DN */
char *typestart = NULL;
int rdn_av_count = 0;
@@ -511,6 +560,14 @@ slapi_dn_normalize_ext(char *src, size_t src_len, char **dest, size_t *dest_len)
if (0 == src_len) {
src_len = strlen(src);
}
+ /*
+ * Check the normalized dn cache
+ */
+ if(ndn_cache_lookup(src, src_len, dest, &udn, &rc)){
+ *dest_len = strlen(*dest);
+ return rc;
+ }
+
s = PL_strnchr(src, '\\', src_len);
if (s) {
*dest_len = src_len * 3;
@@ -1072,6 +1129,10 @@ bail:
/* We terminate the str with NULL only when we allocate the str */
*d = '\0';
}
+ /* add this dn to the normalized dn cache */
+ if(*dest)
+ ndn_cache_add(udn, src_len, *dest, *dest_len);
+
return rc;
}
@@ -2622,3 +2683,343 @@ slapi_sdn_get_size(const Slapi_DN *sdn)
return sz;
}
+/*
+ *
+ * Normalized DN Cache
+ *
+ */
+
+/*
+ * Hashing function using Bernstein's method
+ */
+static PLHashNumber
+ndn_hash_string(const void *key)
+{
+ PLHashNumber hash = 5381;
+ unsigned char *x = (unsigned char *)key;
+ int c;
+
+ while ((c = *x++)){
+ hash = ((hash << 5) + hash) ^ c;
+ }
+ return hash;
+}
+
+void
+ndn_cache_init()
+{
+ 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);
+ ndn_cache = (struct ndn_cache_ctx *)slapi_ch_malloc(sizeof(struct ndn_cache_ctx));
+ ndn_cache->cache_max_size = config_get_ndn_cache_size();
+ ndn_cache->cache_hits = slapi_counter_new();
+ ndn_cache->cache_tries = slapi_counter_new();
+ ndn_cache->cache_misses = slapi_counter_new();
+ ndn_cache->cache_count = 0;
+ 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())) {
+ ndn_cache_destroy();
+ slapi_log_error( SLAPI_LOG_FATAL, "ndn_cache_init", "Failed to create locks. Disabling cache.\n" );
+ }
+}
+
+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
+ */
+static int
+ndn_cache_lookup(char *dn, size_t dn_len, char **result, char **udn, int *rc)
+{
+ struct ndn_hash_val *ndn_ht_val = NULL;
+ char *ndn, *key;
+ int rv = 0;
+
+ if(ndn_started == 0){
+ return rv;
+ }
+ if(dn_len == 0){
+ *result = dn;
+ *rc = 0;
+ return 1;
+ }
+ slapi_counter_increment(ndn_cache->cache_tries);
+ slapi_rwlock_rdlock(ndn_cache_lock);
+ ndn_ht_val = (struct ndn_hash_val *)PL_HashTableLookupConst(ndn_cache_hashtable, dn);
+ if(ndn_ht_val){
+ ndn_cache_update_lru(&ndn_ht_val->lru_node);
+ slapi_counter_increment(ndn_cache->cache_hits);
+ if(ndn_ht_val->len == dn_len ){
+ /* the dn was already normalized, just return the dn as the result */
+ *result = dn;
+ *rc = 0;
+ } else {
+ *rc = 1; /* free result */
+ ndn = slapi_ch_malloc(ndn_ht_val->len + 1);
+ memcpy(ndn, ndn_ht_val->ndn, ndn_ht_val->len);
+ ndn[ndn_ht_val->len] = '\0';
+ *result = ndn;
+ }
+ rv = 1;
+ } else {
+ /* copy/preserve the udn, so we can use it as the key when we add dn's to the hashtable */
+ key = slapi_ch_malloc(dn_len + 1);
+ memcpy(key, dn, dn_len);
+ key[dn_len] = '\0';
+ *udn = key;
+ }
+ slapi_rwlock_unlock(ndn_cache_lock);
+
+ return rv;
+}
+
+/*
+ * Move this lru node to the top of the list
+ */
+static void
+ndn_cache_update_lru(struct ndn_cache_lru **node)
+{
+ struct ndn_cache_lru *prev, *next, *curr_node = *node;
+
+ if(curr_node == NULL){
+ return;
+ }
+ PR_Lock(lru_lock);
+ if(curr_node->prev == NULL){
+ /* already the top node */
+ PR_Unlock(lru_lock);
+ return;
+ }
+ prev = curr_node->prev;
+ next = curr_node->next;
+ if(next){
+ next->prev = prev;
+ prev->next = next;
+ } else {
+ /* this was the tail, so reset the tail */
+ ndn_cache->tail = prev;
+ prev->next = NULL;
+ }
+ curr_node->prev = NULL;
+ curr_node->next = ndn_cache->head;
+ ndn_cache->head->prev = curr_node;
+ ndn_cache->head = curr_node;
+ PR_Unlock(lru_lock);
+}
+
+/*
+ * Add a ndn to the cache. Try and do as much as possible before taking the write lock.
+ */
+static void
+ndn_cache_add(char *dn, size_t dn_len, char *ndn, size_t ndn_len)
+{
+ struct ndn_hash_val *ht_entry;
+ struct ndn_cache_lru *new_node = NULL;
+ PLHashEntry *he;
+ int size;
+
+ if(ndn_started == 0 || dn_len == 0){
+ return;
+ }
+ if(strlen(ndn) > ndn_len){
+ /* we need to null terminate the ndn */
+ *(ndn + ndn_len) = '\0';
+ }
+ /*
+ * Calculate the approximate memory footprint of the hash entry, key, and lru entry.
+ */
+ size = (dn_len * 2) + ndn_len + sizeof(PLHashEntry) + sizeof(struct ndn_hash_val) + sizeof(struct ndn_cache_lru);
+ /*
+ * Create our LRU node
+ */
+ new_node = (struct ndn_cache_lru *)slapi_ch_malloc(sizeof(struct ndn_cache_lru));
+ if(new_node == NULL){
+ slapi_log_error( SLAPI_LOG_FATAL, "ndn_cache_add", "Failed to allocate new lru node.\n");
+ return;
+ }
+ new_node->prev = NULL;
+ new_node->key = dn; /* dn has already been allocated */
+ /*
+ * Its possible this dn was added to the hash by another thread.
+ */
+ slapi_rwlock_wrlock(ndn_cache_lock);
+ ht_entry = (struct ndn_hash_val *)PL_HashTableLookupConst(ndn_cache_hashtable, dn);
+ if(ht_entry){
+ /* already exists, free the node and return */
+ slapi_rwlock_unlock(ndn_cache_lock);
+ slapi_ch_free_string(&new_node->key);
+ slapi_ch_free((void **)&new_node);
+ return;
+ }
+ /*
+ * Create the hash entry
+ */
+ ht_entry = (struct ndn_hash_val *)slapi_ch_malloc(sizeof(struct ndn_hash_val));
+ if(ht_entry == NULL){
+ slapi_rwlock_unlock(ndn_cache_lock);
+ slapi_log_error( SLAPI_LOG_FATAL, "ndn_cache_add", "Failed to allocate new hash entry.\n");
+ slapi_ch_free_string(&new_node->key);
+ slapi_ch_free((void **)&new_node);
+ return;
+ }
+ ht_entry->ndn = slapi_ch_malloc(ndn_len + 1);
+ memcpy(ht_entry->ndn, ndn, ndn_len);
+ ht_entry->ndn[ndn_len] = '\0';
+ ht_entry->len = ndn_len;
+ ht_entry->size = size;
+ ht_entry->lru_node = new_node;
+ /*
+ * Check if our cache is full
+ */
+ PR_Lock(lru_lock); /* grab the lru lock now, as ndn_cache_flush needs it */
+ if(ndn_cache->cache_max_size != 0 && ((ndn_cache->cache_size + size) > ndn_cache->cache_max_size)){
+ ndn_cache_flush();
+ }
+ /*
+ * Set the ndn cache lru nodes
+ */
+ if(ndn_cache->head == NULL && ndn_cache->tail == NULL){
+ /* this is the first node */
+ ndn_cache->head = new_node;
+ ndn_cache->tail = new_node;
+ new_node->next = NULL;
+ } else {
+ new_node->next = ndn_cache->head;
+ ndn_cache->head->prev = new_node;
+ }
+ ndn_cache->head = new_node;
+ PR_Unlock(lru_lock);
+ /*
+ * Add the new object to the hashtable, and update our stats
+ */
+ he = PL_HashTableAdd(ndn_cache_hashtable, new_node->key, (void *)ht_entry);
+ if(he == NULL){
+ slapi_log_error( SLAPI_LOG_FATAL, "ndn_cache_add", "Failed to add new entry to hash(%s)\n",dn);
+ } else {
+ ndn_cache->cache_count++;
+ ndn_cache->cache_size += size;
+ }
+ slapi_rwlock_unlock(ndn_cache_lock);
+}
+
+/*
+ * cache is full, remove the least used dn's. lru_lock/ndn_cache write lock are already taken
+ */
+static void
+ndn_cache_flush()
+{
+ struct ndn_cache_lru *node, *next, *flush_node;
+ int i;
+
+ node = ndn_cache->tail;
+ for(i = 0; node && i < NDN_FLUSH_COUNT && ndn_cache->cache_count > NDN_MIN_COUNT; i++){
+ flush_node = node;
+ /* update the lru */
+ next = node->prev;
+ 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);
+ }
+
+ 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(node && 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_entry;
+
+ 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)
+{
+ slapi_rwlock_rdlock(ndn_cache_lock);
+ *hits = slapi_counter_get_value(ndn_cache->cache_hits);
+ *tries = slapi_counter_get_value(ndn_cache->cache_tries);
+ *size = ndn_cache->cache_size;
+ *max_size = ndn_cache->cache_max_size;
+ *count = ndn_cache->cache_count;
+ slapi_rwlock_unlock(ndn_cache_lock);
+}
+
diff --git a/ldap/servers/slapd/libglobs.c b/ldap/servers/slapd/libglobs.c
index 79ca2bd..3c0c9f4 100644
--- a/ldap/servers/slapd/libglobs.c
+++ b/ldap/servers/slapd/libglobs.c
@@ -1035,7 +1035,15 @@ static struct config_get_and_set {
{CONFIG_IGNORE_TIME_SKEW, config_set_ignore_time_skew,
NULL, 0,
(void**)&global_slapdFrontendConfig.ignore_time_skew,
- CONFIG_ON_OFF, (ConfigGetFunc)config_get_ignore_time_skew, &init_ignore_time_skew}
+ CONFIG_ON_OFF, (ConfigGetFunc)config_get_ignore_time_skew, &init_ignore_time_skew},
+ {CONFIG_NDN_CACHE, config_set_ndn_cache_enabled,
+ NULL, 0,
+ (void**)&global_slapdFrontendConfig.ndn_cache_enabled, CONFIG_INT,
+ (ConfigGetFunc)config_get_ndn_cache_enabled},
+ {CONFIG_NDN_CACHE_SIZE, config_set_ndn_cache_max_size,
+ NULL, 0,
+ (void**)&global_slapdFrontendConfig.ndn_cache_max_size,
+ CONFIG_INT, (ConfigGetFunc)config_get_ndn_cache_size},
#ifdef MEMPOOL_EXPERIMENTAL
,{CONFIG_MEMPOOL_SWITCH_ATTRIBUTE, config_set_mempool_switch,
NULL, 0,
@@ -1053,7 +1061,7 @@ static struct config_get_and_set {
/*
* hashNocaseString - used for case insensitive hash lookups
*/
-static PLHashNumber
+PLHashNumber
hashNocaseString(const void *key)
{
PLHashNumber h = 0;
@@ -1067,7 +1075,7 @@ hashNocaseString(const void *key)
/*
* hashNocaseCompare - used for case insensitive hash key comparisons
*/
-static PRIntn
+PRIntn
hashNocaseCompare(const void *v1, const void *v2)
{
return (strcasecmp((char *)v1, (char *)v2) == 0);
@@ -1463,6 +1471,11 @@ FrontendConfig_init () {
init_malloc_mmap_threshold = cfg->malloc_mmap_threshold = DEFAULT_MALLOC_UNSET;
#endif
+ cfg->disk_logging_critical = LDAP_OFF;
+ cfg->ndn_cache_enabled = LDAP_OFF;
+ cfg->ndn_cache_max_size = NDN_DEFAULT_SIZE;
+
+
#ifdef MEMPOOL_EXPERIMENTAL
init_mempool_switch = cfg->mempool_switch = LDAP_ON;
cfg->mempool_maxfreelist = 1024;
@@ -1694,6 +1707,42 @@ config_set_sasl_maxbufsize(const char *attrname, char *value, char *errorbuf, in
return retVal;
}
+int
+config_set_ndn_cache_enabled(const char *attrname, char *value, char *errorbuf, int apply )
+{
+ slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
+ int retVal;
+
+ retVal = config_set_onoff ( attrname, value, &(slapdFrontendConfig->ndn_cache_enabled), errorbuf, apply);
+
+ return retVal;
+}
+
+int
+config_set_ndn_cache_max_size(const char *attrname, char *value, char *errorbuf, int apply )
+{
+ slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
+ long size;
+ int retVal = LDAP_SUCCESS;
+
+ size = atol(value);
+ if(size < 0){
+ size = 0; /* same as -1 */
+ }
+ if(size > 0 && size < 1024000){
+ PR_snprintf ( errorbuf, SLAPI_DSE_RETURNTEXT_SIZE, "ndn_cache_max_size too low(%d), changing to "
+ "%d bytes.\n",(int)size, NDN_DEFAULT_SIZE);
+ size = NDN_DEFAULT_SIZE;
+ }
+ if(apply){
+ CFG_LOCK_WRITE(slapdFrontendConfig);
+ slapdFrontendConfig->ndn_cache_max_size = size;
+ CFG_UNLOCK_WRITE(slapdFrontendConfig);
+ }
+
+ return retVal;
+}
+
int
config_set_port( const char *attrname, char *port, char *errorbuf, int apply ) {
long nPort;
@@ -5626,6 +5675,27 @@ config_get_max_filter_nest_level()
return retVal;
}
+size_t
+config_get_ndn_cache_size(){
+ slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
+ size_t retVal;
+
+ CFG_LOCK_READ(slapdFrontendConfig);
+ retVal = slapdFrontendConfig->ndn_cache_max_size;
+ CFG_UNLOCK_READ(slapdFrontendConfig);
+ return retVal;
+}
+
+int
+config_get_ndn_cache_enabled(){
+ slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
+ int retVal;
+
+ CFG_LOCK_READ(slapdFrontendConfig);
+ retVal = slapdFrontendConfig->ndn_cache_enabled;
+ CFG_UNLOCK_READ(slapdFrontendConfig);
+ return retVal;
+}
char *
config_get_basedn() {
diff --git a/ldap/servers/slapd/main.c b/ldap/servers/slapd/main.c
index bc07cbb..5d3e7e7 100644
--- a/ldap/servers/slapd/main.c
+++ b/ldap/servers/slapd/main.c
@@ -1046,6 +1046,9 @@ main( int argc, char **argv)
}
}
+ /* initialize the normalized DN cache */
+ ndn_cache_init();
+
/*
* Detach ourselves from the terminal (unless running in debug mode).
* We must detach before we start any threads since detach forks() on
@@ -1267,6 +1270,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/proto-slap.h b/ldap/servers/slapd/proto-slap.h
index ce09260..0891608 100644
--- a/ldap/servers/slapd/proto-slap.h
+++ b/ldap/servers/slapd/proto-slap.h
@@ -389,6 +389,7 @@ int config_set_disk_threshold( const char *attrname, char *value, char *errorbuf
int config_set_disk_grace_period( const char *attrname, char *value, char *errorbuf, int apply );
int config_set_disk_logging_critical( const char *attrname, char *value, char *errorbuf, int apply );
int config_set_auditlog_unhashed_pw(const char *attrname, char *value, char *errorbuf, int apply);
+
int config_set_sasl_maxbufsize(const char *attrname, char *value, char *errorbuf, int apply );
int config_set_listen_backlog_size(const char *attrname, char *value, char *errorbuf, int apply);
int config_set_ignore_time_skew(const char *attrname, char *value, char *errorbuf, int apply);
@@ -398,6 +399,10 @@ int config_set_malloc_trim_threshold(const char *attrname, char *value, char *er
int config_set_malloc_mmap_threshold(const char *attrname, char *value, char *errorbuf, int apply);
#endif
+int config_set_ndn_cache_enabled(const char *attrname, char *value, char *errorbuf, int apply);
+int config_set_ndn_cache_max_size(const char *attrname, char *value, char *errorbuf, int apply);
+
+
#if !defined(_WIN32) && !defined(AIX)
int config_set_maxdescriptors( const char *attrname, char *value, char *errorbuf, int apply );
#endif /* !_WIN_32 && !AIX */
@@ -562,6 +567,13 @@ int config_get_malloc_trim_threshold();
int config_get_malloc_mmap_threshold();
#endif
+int config_get_ndn_cache_count();
+size_t config_get_ndn_cache_size();
+int config_get_ndn_cache_enabled();
+PLHashNumber hashNocaseString(const void *key);
+PRIntn hashNocaseCompare(const void *v1, const void *v2);
+
+
int is_abspath(const char *);
char* rel2abspath( char * );
char* rel2abspath_ext( char *, char * );
diff --git a/ldap/servers/slapd/schema.c b/ldap/servers/slapd/schema.c
index 28c1ffc..18ae152 100644
--- a/ldap/servers/slapd/schema.c
+++ b/ldap/servers/slapd/schema.c
@@ -250,22 +250,6 @@ dont_allow_that(Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* e, int
return SLAPI_DSE_CALLBACK_ERROR;
}
-#if 0
-/*
- * hashNocaseString - used for case insensitive hash lookups
- */
-static PLHashNumber
-hashNocaseString(const void *key)
-{
- PLHashNumber h = 0;
- const unsigned char *s;
-
- for (s = key; *s; s++)
- h = (h >> 28) ^ (h << 4) ^ (tolower(*s));
- return h;
-}
-#endif
-
static const char *
skipWS(const char *s)
{
@@ -278,7 +262,6 @@ skipWS(const char *s)
return s;
}
-
/*
* like strchr() but strings within single quotes are skipped.
*/
diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h
index 33cfeb4..70e8a51 100644
--- a/ldap/servers/slapd/slap.h
+++ b/ldap/servers/slapd/slap.h
@@ -2015,6 +2015,7 @@ typedef struct _slapdEntryPoints {
#define CONFIG_DISK_THRESHOLD "nsslapd-disk-monitoring-threshold"
#define CONFIG_DISK_GRACE_PERIOD "nsslapd-disk-monitoring-grace-period"
#define CONFIG_DISK_LOGGING_CRITICAL "nsslapd-disk-monitoring-logging-critical"
+
#define CONFIG_SASL_MAXBUFSIZE "nsslapd-sasl-max-buffer-size"
#define CONFIG_LISTEN_BACKLOG_SIZE "nsslapd-listen-backlog-size"
#define CONFIG_IGNORE_TIME_SKEW "nsslapd-ignore-time-skew"
@@ -2035,6 +2036,10 @@ typedef struct _slapdEntryPoints {
#define DAEMON_LISTEN_SIZE 128
#endif
+#define CONFIG_NDN_CACHE "nsslapd-ndn-cache-enabled"
+#define CONFIG_NDN_CACHE_SIZE "nsslapd-ndn-cache-max-size"
+
+
#ifdef MEMPOOL_EXPERIMENTAL
#define CONFIG_MEMPOOL_SWITCH_ATTRIBUTE "nsslapd-mempool"
#define CONFIG_MEMPOOL_MAXFREELIST_ATTRIBUTE "nsslapd-mempool-maxfreelist"
@@ -2272,12 +2277,17 @@ typedef struct _slapdFrontendConfig {
PRInt64 disk_threshold;
int disk_grace_period;
int disk_logging_critical;
+
int ignore_time_skew;
#if defined(LINUX)
int malloc_mxfast; /* mallopt M_MXFAST */
int malloc_trim_threshold; /* mallopt M_TRIM_THRESHOLD */
int malloc_mmap_threshold; /* mallopt M_MMAP_THRESHOLD */
#endif
+
+ /* normalized dn cache */
+ int ndn_cache_enabled;
+ size_t ndn_cache_max_size;
} slapdFrontendConfig_t;
/* possible values for slapdFrontendConfig_t.schemareplace */
diff --git a/ldap/servers/slapd/slapi-private.h b/ldap/servers/slapd/slapi-private.h
index 940260f..8507f47 100644
--- a/ldap/servers/slapd/slapi-private.h
+++ b/ldap/servers/slapd/slapi-private.h
@@ -387,12 +387,16 @@ Slapi_DN *slapi_sdn_init_normdn_ndn_passin(Slapi_DN *sdn, const char *dn);
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 */
/* filter.c */
int filter_flag_is_set(const Slapi_Filter *f,unsigned char flag);
char *slapi_filter_to_string(const Slapi_Filter *f, char *buffer, size_t bufsize);
-char *
-slapi_filter_to_string_internal( const struct slapi_filter *f, char *buf, size_t *bufsize );
+char *slapi_filter_to_string_internal( const struct slapi_filter *f, char *buf, size_t *bufsize );
/* operation.c */
--
1.9.3