util_ldap_cache_mgr.c revision 8c5e6c7678471111589bc199bee1839f8176e8f1
842ae4bd224140319ae7feec1872b93dfd491143fielding/* Copyright 2001-2004 The Apache Software Foundation
842ae4bd224140319ae7feec1872b93dfd491143fielding * Licensed under the Apache License, Version 2.0 (the "License");
842ae4bd224140319ae7feec1872b93dfd491143fielding * you may not use this file except in compliance with the License.
842ae4bd224140319ae7feec1872b93dfd491143fielding * You may obtain a copy of the License at
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * Unless required by applicable law or agreed to in writing, software
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * distributed under the License is distributed on an "AS IS" BASIS,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * See the License for the specific language governing permissions and
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * limitations under the License.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * util_ldap_cache_mgr.c: LDAP cache manager things
e8f95a682820a599fe41b22977010636be5c2717jim * Original code from auth_ldap module for Apache v1.3:
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * Copyright 1998, 1999 Enbridge Pipelines Inc.
e8f95a682820a599fe41b22977010636be5c2717jim * Copyright 1999-2001 Dave Carrigan
11f2c481e1d57bedb3f758565307501e9a2730ddtrawick/* only here until strdup is gone */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes/* here till malloc is gone */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic const unsigned long primes[] =
fa123db15501821e36e513afa78e839775ad2800covenervoid util_ald_free(util_ald_cache_t *cache, const void *ptr)
0568280364eb026393be492ebc732795c4934643jorton /* Free in shared memory */
0568280364eb026393be492ebc732795c4934643jorton apr_rmm_free(cache->rmm_addr, apr_rmm_offset_get(cache->rmm_addr, (void *)ptr));
0568280364eb026393be492ebc732795c4934643jorton /* Cache shm is not used */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesvoid *util_ald_alloc(util_ald_cache_t *cache, unsigned long size)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* allocate from shared memory */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes apr_rmm_off_t block = apr_rmm_calloc(cache->rmm_addr, size);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return block ? (void *)apr_rmm_addr_get(cache->rmm_addr, block) : NULL;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Cache shm is not used */
95b6fe1346805e1731e6e97c15d569c73be22cf7minfrinconst char *util_ald_strdup(util_ald_cache_t *cache, const char *s)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* allocate from shared memory */
95b6fe1346805e1731e6e97c15d569c73be22cf7minfrin apr_rmm_off_t block = apr_rmm_calloc(cache->rmm_addr, strlen(s)+1);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes char *buf = block ? (char *)apr_rmm_addr_get(cache->rmm_addr, block) : NULL;
713a2b68bac4aeb1e9c48785006c0732451039depquerna /* Cache shm is not used */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * Computes the hash on a set of strings. The first argument is the number
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * of strings to hash, the rest of the args are strings.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * Algorithm taken from glibc.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes unsigned long h=0, g;
8113dac419143273351446c3ad653f3fe5ba5cfdwrowe for (i=0; i < nstr; ++i) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes for (p = str; *p; ++p) {
fa123db15501821e36e513afa78e839775ad2800covener h = ( h << 4 ) + *p;
fa123db15501821e36e513afa78e839775ad2800covener if ( ( g = h & 0xf0000000 ) ) {
fa123db15501821e36e513afa78e839775ad2800covener h = h ^ (g >> 24);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes Purges a cache that has gotten full. We keep track of the time that we
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener added the entry that made the cache 3/4 full, then delete all entries
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes that were added before that time. It's pretty simplistic, but time to
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes purge is only O(n), which is more important.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes unsigned long i;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes while (p != NULL) {
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener ((t - cache->last_purge) + (cache->avg_purgetime * (cache->numpurges-1))) /
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim * create caches
6683642c1e0032eeeed5f99e8c14880692ef84c5sfutil_url_node_t *util_ald_create_caches(util_ldap_state_t *st, const char *url)
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener /* create the three caches */
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener /* check that all the caches initialised successfully */
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener if (search_cache && compare_cache && dn_compare_cache) {
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener/*XXX This can be allocated on the stack since it will be copied anyway */
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener curl = (util_url_node_t *)apr_pcalloc(st->pool, sizeof(util_url_node_t));
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesutil_ald_cache_t *util_ald_create_cache(util_ldap_state_t *st,
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes unsigned long (*hashfunc)(void *),
0e05808dc59a321566303084c84b9826a4353cefrederpj int (*comparefunc)(void *, void *),
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes void * (*copyfunc)(util_ald_cache_t *cache, void *),
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes void (*displayfunc)(request_rec *r, util_ald_cache_t *cache, void *))
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim unsigned long i;
55e2e59e5910072e51c870afc68b0907f41a28e0sf apr_rmm_off_t block = apr_rmm_calloc(st->cache_rmm, sizeof(util_ald_cache_t));
55e2e59e5910072e51c870afc68b0907f41a28e0sf cache = block ? (util_ald_cache_t *)apr_rmm_addr_get(st->cache_rmm, block) : NULL;
55e2e59e5910072e51c870afc68b0907f41a28e0sf cache = (util_ald_cache_t *)calloc(sizeof(util_ald_cache_t), 1);
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes for (i = 0; primes[i] && primes[i] < cache->size; ++i) ;
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes cache->nodes = (util_cache_node_t **)util_ald_alloc(cache, cache->size * sizeof(util_cache_node_t *));
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesvoid util_ald_destroy_cache(util_ald_cache_t *cache)
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes unsigned long i;
185aa71728867671e105178b4c66fbc22b65ae26sf while (p != NULL) {
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholesvoid *util_ald_cache_fetch(util_ald_cache_t *cache, void *payload)
55e2e59e5910072e51c870afc68b0907f41a28e0sf if (p != NULL) {
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes * Insert an item into the cache.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * *** Does not catch duplicates!!! ***
b08925593f214f621161742925dcf074a8047e0acovenervoid util_ald_cache_insert(util_ald_cache_t *cache, void *payload)
5f3e4e06f8e23597d2f95e2c2cff1116c522488fcovener /* sanity check */
707f6d077f73cc948deead8df5b40ea42c1eaa78covener /* check if we are full - if so, try purge */
185aa71728867671e105178b4c66fbc22b65ae26sf /* if the purge was not effective, we leave now to avoid an overflow */
707f6d077f73cc948deead8df5b40ea42c1eaa78covener /* should be safe to add an entry */
707f6d077f73cc948deead8df5b40ea42c1eaa78covener if ((node = (util_cache_node_t *)util_ald_alloc(cache, sizeof(util_cache_node_t))) == NULL) {
707f6d077f73cc948deead8df5b40ea42c1eaa78covener /* populate the entry */
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf /* if we reach the full mark, note the time we did so
707f6d077f73cc948deead8df5b40ea42c1eaa78covener * for the benefit of the purge function
707f6d077f73cc948deead8df5b40ea42c1eaa78covenervoid util_ald_cache_remove(util_ald_cache_t *cache, void *payload)
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf /* If p is null, it means that we couldn't find the node, so just return */
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf if (q == NULL) {
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf /* We found the node, and it's the first in the list */
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf /* We found the node and it's not the first in the list */
3dfeb02cfb853d8717ca0cc259b59fea610173f5bnicholeschar *util_ald_cache_display_stats(request_rec *r, util_ald_cache_t *cache, char *name, char *id)
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf unsigned long i;
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf chainlen = nchains? (double)totchainlen / (double)nchains : 0;
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf "<a href=\"%s?%s\">%s</a>",
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes "<tr valign='top'>"
e8f95a682820a599fe41b22977010636be5c2717jim "<td nowrap>%s</td>"
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim "<td align='right' nowrap>%lu (%.0f%% full)</td>"
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim "<td align='right'>%.1f</td>"
96ebb616bbf4ac2a422cc5d9770c9ad07ccecdc0covener "<td align='right'>%lu/%lu</td>"
96ebb616bbf4ac2a422cc5d9770c9ad07ccecdc0covener "<td align='right'>%.0f%%</td>"
96ebb616bbf4ac2a422cc5d9770c9ad07ccecdc0covener "<td align='right'>%lu/%lu</td>",
96ebb616bbf4ac2a422cc5d9770c9ad07ccecdc0covener (double)cache->numentries / (double)cache->maxentries * 100.0,
783874b86bfe13d7a4fe0922f344a3779cdccea3covener (cache->fetches > 0 ? (double)(cache->hits) / (double)(cache->fetches) * 100.0 : 100.0),
7dbf29be626018bc389ef94c1846aeac4b72633bsf "<td align='right'>%lu</td>\n"
7dbf29be626018bc389ef94c1846aeac4b72633bsf "<td align='right' nowrap>%s</td>\n",
7dbf29be626018bc389ef94c1846aeac4b72633bsf "%s<td colspan='2' align='center'>(none)</td>\n",
783874b86bfe13d7a4fe0922f344a3779cdccea3covener buf = apr_psprintf(p, "%s<td align='right'>%.2g</td>\n</tr>", buf, cache->avg_purgetime);
7dbf29be626018bc389ef94c1846aeac4b72633bsfchar *util_ald_cache_display(request_rec *r, util_ldap_state_t *st)
7dbf29be626018bc389ef94c1846aeac4b72633bsf unsigned long i,j;
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes util_ald_cache_t *util_ldap_cache = st->util_ldap_cache;
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes return "<tr valign='top'><td nowrap colspan=7>Cache has not been enabled/initialised.</td></tr>";
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf if ((3 == sscanf(r->args, scanfmt, cachetype, &id, &off, lint)) &&
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes "<table border='0'>\n"
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes "<td bgcolor='#000000'><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Cache Name:</b></font></td>"
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes "<td bgcolor='#ffffff'><font size='-1' face='Arial,Helvetica' color='#000000'><b>%s (%s)</b></font></td>"
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes "</table>\n</p>\n",
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes cachetype[0] == 's' ? "Search" : (cachetype[0] == 'c' ? "Compares" : "DNCompares")), r);
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes switch (cachetype[0]) {
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes "<table border='0'>\n"
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes "<tr bgcolor='#000000'>\n"
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>LDAP Filter</b></font></td>"
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>User Name</b></font></td>"
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Last Bind</b></font></td>"
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "</tr>\n", r
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf for (p = n->search_cache->nodes[i]; p != NULL; p = p->next) {
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf (*n->search_cache->display)(r, n->search_cache, p->payload);
e8f95a682820a599fe41b22977010636be5c2717jim "<table border='0'>\n"
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "<tr bgcolor='#000000'>\n"
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>DN</b></font></td>"
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Attribute</b></font></td>"
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Value</b></font></td>"
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Last Compare</b></font></td>"
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Result</b></font></td>"
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim "</tr>\n", r
7dbf29be626018bc389ef94c1846aeac4b72633bsf for (p = n->compare_cache->nodes[i]; p != NULL; p = p->next) {
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener (*n->compare_cache->display)(r, n->compare_cache, p->payload);
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener "<table border='0'>\n"
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener "<tr bgcolor='#000000'>\n"
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Require DN</b></font></td>"
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Actual DN</b></font></td>"
185aa71728867671e105178b4c66fbc22b65ae26sf "</tr>\n", r
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener for (p = n->dn_compare_cache->nodes[i]; p != NULL; p = p->next) {
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener (*n->dn_compare_cache->display)(r, n->dn_compare_cache, p->payload);
9c63a05713cb83a44a1590b4af33edeebf39f118sf "<table border='0'>\n"
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf "<tr bgcolor='#000000'>\n"
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Cache Name</b></font></td>"
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Entries</b></font></td>"
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Avg. Chain Len.</b></font></td>"
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "<td colspan='2'><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Hits</b></font></td>"
54d22ed1c429b903b029bbd62621f11a9e286137minfrin "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Ins/Rem</b></font></td>"
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "<td colspan='2'><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Purges</b></font></td>"
9c63a05713cb83a44a1590b4af33edeebf39f118sf "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Avg Purge Time</b></font></td>"
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf "</tr>\n", r
307219eca940aa30b873bfd68a44484dd3d3fa88covener buf = util_ald_cache_display_stats(r, st->util_ldap_cache, "LDAP URL Cache", NULL);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes for (p = util_ldap_cache->nodes[i],j=0; p != NULL; p = p->next,j++) {
54d22ed1c429b903b029bbd62621f11a9e286137minfrin util_ald_cache_display_stats(r, n->search_cache, t1, id1),
54d22ed1c429b903b029bbd62621f11a9e286137minfrin util_ald_cache_display_stats(r, n->compare_cache, t2, id2),
54d22ed1c429b903b029bbd62621f11a9e286137minfrin util_ald_cache_display_stats(r, n->dn_compare_cache, t3, id3)
54d22ed1c429b903b029bbd62621f11a9e286137minfrin#endif /* APR_HAS_LDAP */