From 2a8da7ea76d15906fdb98b47534fc3447f12c752 Mon Sep 17 00:00:00 2001 From: Mark Reynolds Date: Dec 19 2014 21:38:03 +0000 Subject: Ticket 408 - Backport of Normalized DN Cache https://fedorahosted.org/389/ticket/408 --- 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. <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 #endif #include "slap.h" +#include #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 */