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 | 347 +++++++++++++++++++++++++++++++++
ldap/servers/slapd/libglobs.c | 71 ++++++
ldap/servers/slapd/main.c | 3
ldap/servers/slapd/proto-slap.h | 7
ldap/servers/slapd/schema.c | 17 -
ldap/servers/slapd/slap.h | 6
ldap/servers/slapd/slapi-private.h | 6
10 files changed, 462 insertions(+), 47 deletions(-)
New commits:
commit 1d6dd39fb8b0ef8eb42ec9ef8c3d325e27a3d3c1
Author: Mark Reynolds <mreynolds(a)redhat.com>
Date: Thu Sep 13 10:00:56 2012 -0400
Ticket 408 - create a normalized dn cache
Description: When we call slapi_dn_normalize_ext, first check if the dn is
in the cache. If it is, return the normalized dn(ndn), otherwise
make a copy of the raw/unnormalized dn so we can use it as the hash
key. We need to copy it because the normalize process consumes/modifys
the string. Then at the end of the slapi_dn_normalize_ext, we add the
ndn to the hash using the rawdn as the key.
This feature is configurable, and the max size can also be set. The
default is 20mb for max size. You can also monitor the cache searching
on the ldbm monitor(cn=monitor,cn=userRoot,cn=ldbm
database,cn=plugins,cn=config).
https://fedorahosted.org/389/ticket/408
Reviewed by: richm & noriko (Thanks!)
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 62dfea1..36ed768 100644
--- a/ldap/servers/slapd/attrsyntax.c
+++ b/ldap/servers/slapd/attrsyntax.c
@@ -202,29 +202,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 075a48f..ee4f01a 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(config_get_ndn_cache_enabled()){
+ 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 568871f..11e56a9 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,52 @@ 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 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 +534,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 +559,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 +1128,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;
}
@@ -2567,3 +2627,290 @@ slapi_sdn_get_size(const Slapi_DN *sdn)
sz += strlen(sdn->dn) + 1;
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()){
+ 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;
+
+ 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);
+ slapi_log_error( SLAPI_LOG_FATAL, "ndn_cache_init", "Failed to
create locks. Disabling cache.\n" );
+ } else {
+ ndn_started = 1;
+ }
+}
+
+/*
+ * 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; 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");
+}
+
+/* this is already "write" locked from ndn_cache_add */
+static void
+ndn_cache_delete(char *dn)
+{
+ struct ndn_hash_val *ht_val;
+
+ 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);
+ 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 3226ede..dc8452a 100644
--- a/ldap/servers/slapd/libglobs.c
+++ b/ldap/servers/slapd/libglobs.c
@@ -691,6 +691,14 @@ static struct config_get_and_set {
NULL, 0,
(void**)&global_slapdFrontendConfig.disk_preserve_logging,
CONFIG_ON_OFF, (ConfigGetFunc)config_get_disk_preserve_logging},
+ {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,
@@ -704,7 +712,7 @@ static struct config_get_and_set {
/*
* hashNocaseString - used for case insensitive hash lookups
*/
-static PLHashNumber
+PLHashNumber
hashNocaseString(const void *key)
{
PLHashNumber h = 0;
@@ -718,7 +726,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);
@@ -1092,6 +1100,8 @@ FrontendConfig_init () {
cfg->disk_grace_period = 60; /* 1 hour */
cfg->disk_preserve_logging = LDAP_OFF;
cfg->disk_logging_critical = LDAP_OFF;
+ cfg->ndn_cache_enabled = LDAP_OFF;
+ cfg->ndn_cache_max_size = NDN_DEFAULT_SIZE;
#ifdef MEMPOOL_EXPERIMENTAL
cfg->mempool_switch = LDAP_ON;
@@ -1310,6 +1320,42 @@ config_set_disk_grace_period( const char *attrname, char *value,
char *errorbuf,
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;
@@ -5213,6 +5259,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 69314cc..03d7086 100644
--- a/ldap/servers/slapd/main.c
+++ b/ldap/servers/slapd/main.c
@@ -1042,6 +1042,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
diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h
index cdd5eec..55c3a78 100644
--- a/ldap/servers/slapd/proto-slap.h
+++ b/ldap/servers/slapd/proto-slap.h
@@ -388,6 +388,8 @@ int config_set_disk_grace_period( const char *attrname, char *value,
char *error
int config_set_disk_preserve_logging( 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_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 );
@@ -543,6 +545,11 @@ long config_get_disk_threshold();
int config_get_disk_grace_period();
int config_get_disk_preserve_logging();
int config_get_disk_logging_critical();
+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 * );
diff --git a/ldap/servers/slapd/schema.c b/ldap/servers/slapd/schema.c
index ba76b65..c66c320 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 ca1cb87..33607cb 100644
--- a/ldap/servers/slapd/slap.h
+++ b/ldap/servers/slapd/slap.h
@@ -2012,6 +2012,8 @@ typedef struct _slapdEntryPoints {
#define CONFIG_DISK_GRACE_PERIOD "nsslapd-disk-monitoring-grace-period"
#define CONFIG_DISK_PRESERVE_LOGGING
"nsslapd-disk-monitoring-preserve-logging"
#define CONFIG_DISK_LOGGING_CRITICAL
"nsslapd-disk-monitoring-logging-critical"
+#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"
@@ -2247,6 +2249,10 @@ typedef struct _slapdFrontendConfig {
int disk_grace_period;
int disk_preserve_logging;
int disk_logging_critical;
+
+ /* 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 a57b453..6c2781c 100644
--- a/ldap/servers/slapd/slapi-private.h
+++ b/ldap/servers/slapd/slapi-private.h
@@ -384,12 +384,14 @@ 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_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 */