+++ /dev/null
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-/*
- * util_ldap_cache_mgr.c: LDAP cache manager things
- *
- * Original code from auth_ldap module for Apache v1.3:
- * Copyright 1998, 1999 Enbridge Pipelines Inc.
- * Copyright 1999-2001 Dave Carrigan
- */
-
-#include <apr_ldap.h>
-#include "util_ldap.h"
-#include "util_ldap_cache.h"
-#include <apr_strings.h>
-
-#ifdef APU_HAS_LDAP
-
-/* only here until strdup is gone */
-#include <string.h>
-
-/* here till malloc is gone */
-#include <stdlib.h>
-
-static const int primes[] =
-{
- 11,
- 19,
- 37,
- 73,
- 109,
- 163,
- 251,
- 367,
- 557,
- 823,
- 1237,
- 1861,
- 2777,
- 4177,
- 6247,
- 9371,
- 14057,
- 21089,
- 31627,
- 47431,
- 71143,
- 106721,
- 160073,
- 240101,
- 360163,
- 540217,
- 810343,
- 1215497,
- 1823231,
- 2734867,
- 4102283,
- 6153409,
- 9230113,
- 13845163,
- 0
-};
-
-void util_ald_free(const void *ptr)
-{
-#if APR_HAS_SHARED_MEMORY
- if (util_ldap_shm) {
- if (ptr)
- apr_shm_free(util_ldap_shm, (void *)ptr);
- } else {
- if (ptr)
- free((void *)ptr);
- }
-#else
- if (ptr)
- free((void *)ptr);
-#endif
-}
-
-void *util_ald_alloc(unsigned long size)
-{
- if (0 == size)
- return NULL;
-#if APR_HAS_SHARED_MEMORY
- if (util_ldap_shm) {
- return (void *)apr_shm_calloc(util_ldap_shm, size);
- } else {
- return (void *)calloc(sizeof(char), size);
- }
-#else
- return (void *)calloc(sizeof(char), size);
-#endif
-}
-
-const char *util_ald_strdup(const char *s)
-{
-#if APR_HAS_SHARED_MEMORY
- if (util_ldap_shm) {
- char *buf = apr_shm_malloc(util_ldap_shm, strlen(s)+1);
- if (buf) {
- strcpy(buf, s);
- return buf;
- }
- else {
- return NULL;
- }
- } else {
- return strdup(s);
- }
-#else
- return strdup(s);
-#endif
-}
-
-
-/*
- * Computes the hash on a set of strings. The first argument is the number
- * of strings to hash, the rest of the args are strings.
- * Algorithm taken from glibc.
- */
-unsigned long util_ald_hash_string(int nstr, ...)
-{
- int i;
- va_list args;
- unsigned long h=0, g;
- char *str, *p;
-
- va_start(args, nstr);
- for (i=0; i < nstr; ++i) {
- str = va_arg(args, char *);
- for (p = str; *p; ++p) {
- h = ( h << 4 ) + *p;
- if ( ( g = h & 0xf0000000 ) ) {
- h = h ^ (g >> 24);
- h = h ^ g;
- }
- }
- }
- va_end(args);
-
- return h;
-}
-
-
-/*
- Purges a cache that has gotten full. We keep track of the time that we
- added the entry that made the cache 3/4 full, then delete all entries
- that were added before that time. It's pretty simplistic, but time to
- purge is only O(n), which is more important.
-*/
-void util_ald_cache_purge(util_ald_cache_t *cache)
-{
- int i;
- util_cache_node_t *p, *q;
- apr_time_t t;
-
- if (!cache)
- return;
-
- cache->last_purge = apr_time_now();
- cache->npurged = 0;
- cache->numpurges++;
-
- for (i=0; i < cache->size; ++i) {
- p = cache->nodes[i];
- while (p != NULL) {
- if (p->add_time < cache->marktime) {
- q = p->next;
- (*cache->free)(p->payload);
- util_ald_free(p);
- cache->numentries--;
- cache->npurged++;
- p = q;
- }
- else {
- p = p->next;
- }
- }
- }
-
- t = apr_time_now();
- cache->avg_purgetime =
- ((t - cache->last_purge) + (cache->avg_purgetime * (cache->numpurges-1))) /
- cache->numpurges;
-}
-
-
-/*
- * create caches
- */
-util_url_node_t *util_ald_create_caches(util_ldap_state_t *st, const char *url)
-{
- util_url_node_t *curl = NULL;
- util_ald_cache_t *search_cache;
- util_ald_cache_t *compare_cache;
- util_ald_cache_t *dn_compare_cache;
-
- /* create the three caches */
- search_cache = util_ald_create_cache(st->search_cache_size,
- util_ldap_search_node_hash,
- util_ldap_search_node_compare,
- util_ldap_search_node_copy,
- util_ldap_search_node_free);
- compare_cache = util_ald_create_cache(st->compare_cache_size,
- util_ldap_compare_node_hash,
- util_ldap_compare_node_compare,
- util_ldap_compare_node_copy,
- util_ldap_compare_node_free);
- dn_compare_cache = util_ald_create_cache(st->compare_cache_size,
- util_ldap_dn_compare_node_hash,
- util_ldap_dn_compare_node_compare,
- util_ldap_dn_compare_node_copy,
- util_ldap_dn_compare_node_free);
-
- /* check that all the caches initialised successfully */
- if (search_cache && compare_cache && dn_compare_cache) {
-
- curl = (util_url_node_t *)apr_pcalloc(st->pool, sizeof(util_url_node_t));
- curl->url = url;
- curl->search_cache = search_cache;
- curl->compare_cache = compare_cache;
- curl->dn_compare_cache = dn_compare_cache;
-
- util_ald_cache_insert(util_ldap_cache, curl);
-
- }
-
- return curl;
-}
-
-
-util_ald_cache_t *util_ald_create_cache(unsigned long maxentries,
- unsigned long (*hashfunc)(void *),
- int (*comparefunc)(void *, void *),
- void * (*copyfunc)(void *),
- void (*freefunc)(void *))
-{
- util_ald_cache_t *cache;
- int i;
-
- if (maxentries <= 0)
- return NULL;
-
- cache = (util_ald_cache_t *)util_ald_alloc(sizeof(util_ald_cache_t));
- if (!cache)
- return NULL;
-
- cache->maxentries = maxentries;
- cache->numentries = 0;
- cache->size = maxentries / 3;
- if (cache->size < 64) cache->size = 64;
- for (i = 0; primes[i] && primes[i] < cache->size; ++i) ;
- cache->size = primes[i]? primes[i] : primes[i-1];
-
- cache->nodes = (util_cache_node_t **)util_ald_alloc(cache->size * sizeof(util_cache_node_t *));
- if (!cache->nodes) {
- util_ald_free(cache);
- return NULL;
- }
-
- for (i=0; i < cache->size; ++i)
- cache->nodes[i] = NULL;
-
- cache->hash = hashfunc;
- cache->compare = comparefunc;
- cache->copy = copyfunc;
- cache->free = freefunc;
-
- cache->fullmark = cache->maxentries / 4 * 3;
- cache->marktime = 0;
- cache->avg_purgetime = 0.0;
- cache->numpurges = 0;
- cache->last_purge = 0;
- cache->npurged = 0;
-
- cache->fetches = 0;
- cache->hits = 0;
- cache->inserts = 0;
- cache->removes = 0;
-
- return cache;
-}
-
-void util_ald_destroy_cache(util_ald_cache_t *cache)
-{
- int i;
- util_cache_node_t *p, *q;
-
- if (cache == NULL)
- return;
-
- for (i = 0; i < cache->size; ++i) {
- p = cache->nodes[i];
- q = NULL;
- while (p != NULL) {
- q = p->next;
- (*cache->free)(p->payload);
- util_ald_free(p);
- p = q;
- }
- }
- util_ald_free(cache->nodes);
-}
-
-void *util_ald_cache_fetch(util_ald_cache_t *cache, void *payload)
-{
- int hashval;
- util_cache_node_t *p;
-
- if (cache == NULL)
- return NULL;
-
- cache->fetches++;
-
- hashval = (*cache->hash)(payload) % cache->size;
- for (p = cache->nodes[hashval];
- p && !(*cache->compare)(p->payload, payload);
- p = p->next) ;
-
- if (p != NULL) {
- cache->hits++;
- return p->payload;
- }
- else {
- return NULL;
- }
-}
-
-/*
- * Insert an item into the cache.
- * *** Does not catch duplicates!!! ***
- */
-void util_ald_cache_insert(util_ald_cache_t *cache, void *payload)
-{
- int hashval;
- util_cache_node_t *node;
-
- if (cache == NULL || payload == NULL)
- return;
-
- cache->inserts++;
- hashval = (*cache->hash)(payload) % cache->size;
- node = (util_cache_node_t *)util_ald_alloc(sizeof(util_cache_node_t));
- node->add_time = apr_time_now();
- node->payload = (*cache->copy)(payload);
- node->next = cache->nodes[hashval];
- cache->nodes[hashval] = node;
- if (++cache->numentries == cache->fullmark)
- cache->marktime=apr_time_now();
- if (cache->numentries >= cache->maxentries)
- util_ald_cache_purge(cache);
-}
-
-void util_ald_cache_remove(util_ald_cache_t *cache, void *payload)
-{
- int hashval;
- util_cache_node_t *p, *q;
-
- if (cache == NULL)
- return;
-
- cache->removes++;
- hashval = (*cache->hash)(payload) % cache->size;
- for (p = cache->nodes[hashval], q=NULL;
- p && !(*cache->compare)(p->payload, payload);
- p = p->next) {
- q = p;
- }
-
- /* If p is null, it means that we couldn't find the node, so just return */
- if (p == NULL)
- return;
-
- if (q == NULL) {
- /* We found the node, and it's the first in the list */
- cache->nodes[hashval] = p->next;
- }
- else {
- /* We found the node and it's not the first in the list */
- q->next = p->next;
- }
- (*cache->free)(p->payload);
- util_ald_free(p);
- cache->numentries--;
-}
-
-char *util_ald_cache_display_stats(apr_pool_t *p, util_ald_cache_t *cache, char *name)
-{
- int i;
- int totchainlen = 0;
- int nchains = 0;
- double chainlen;
- util_cache_node_t *n;
- char *buf;
-
- if (cache == NULL) {
- return "";
- }
-
- for (i=0; i < cache->size; ++i) {
- if (cache->nodes[i] != NULL) {
- nchains++;
- for (n = cache->nodes[i]; n != NULL; n = n->next)
- totchainlen++;
- }
- }
- chainlen = nchains? (double)totchainlen / (double)nchains : 0;
-
- buf = apr_psprintf(p,
- "<tr valign='top'>"
- "<td nowrap>%s</td>"
- "<td align='right' nowrap>%lu (%.0f%% full)</td>"
- "<td align='right'>%.1f</td>"
- "<td align='right'>%lu/%lu</td>"
- "<td align='right'>%.0f%%</td>"
- "<td align='right'>%lu/%lu</td>",
- name,
- cache->numentries,
- (double)cache->numentries / (double)cache->maxentries * 100.0,
- chainlen,
- cache->hits,
- cache->fetches,
- (cache->fetches > 0 ? (double)(cache->hits) / (double)(cache->fetches) * 100.0 : 100.0),
- cache->inserts,
- cache->removes);
-
- if (cache->numpurges) {
- char str_ctime[APR_CTIME_LEN];
-
- apr_ctime(str_ctime, cache->last_purge);
- buf = apr_psprintf(p,
- "%s"
- "<td align='right'>%lu</td>\n"
- "<td align='right' nowrap>%s</td>\n",
- buf,
- cache->numpurges,
- str_ctime);
- }
- else {
- buf = apr_psprintf(p,
- "%s<td colspan='2' align='center'>(none)</td>\n",
- buf);
- }
-
- buf = apr_psprintf(p, "%s<td align='right'>%.2g</td>\n</tr>", buf, cache->avg_purgetime);
-
- return buf;
-}
-
-char *util_ald_cache_display(apr_pool_t *pool)
-{
- int i;
- char *buf, *t1, *t2, *t3;
-
- if (!util_ldap_cache) {
- return "<tr valign='top'><td nowrap colspan=7>Cache has not been enabled/initialised.</td></tr>";
- }
-
- buf = util_ald_cache_display_stats(pool, util_ldap_cache, "LDAP URL Cache");
-
- for (i=0; i < util_ldap_cache->size; ++i) {
- util_cache_node_t *p;
- for (p = util_ldap_cache->nodes[i]; p != NULL; p = p->next) {
- util_url_node_t *n;
-
- n = (util_url_node_t *)p->payload;
-
- t1 = apr_psprintf(pool, "%s (Searches)", n->url);
- t2 = apr_psprintf(pool, "%s (Compares)", n->url);
- t3 = apr_psprintf(pool, "%s (DNCompares)", n->url);
-
- buf = apr_psprintf(pool, "%s\n\n"
- "%s\n\n"
- "%s\n\n"
- "%s\n\n",
- buf,
- util_ald_cache_display_stats(pool, n->search_cache, t1),
- util_ald_cache_display_stats(pool, n->compare_cache, t2),
- util_ald_cache_display_stats(pool, n->dn_compare_cache, t3)
- );
- }
- }
- return buf;
-}
-
-#endif /* APU_HAS_LDAP */