/* Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License.
*/
/* * 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
*/
/* * Duplicate a subgroupList from one compare entry to another. * Returns: ptr to a new copy of the subgroupList or NULL if allocation failed.
*/
util_compare_subgroup_t *util_ald_sgl_dup(util_ald_cache_t *cache, util_compare_subgroup_t *sgl_in)
{ int i = 0;
util_compare_subgroup_t *sgl_out = NULL;
if (!sgl_in) { return NULL;
}
sgl_out = (util_compare_subgroup_t *) util_ald_alloc(cache, sizeof(util_compare_subgroup_t)); if (sgl_out) {
sgl_out->subgroupDNs = util_ald_alloc(cache, sizeof(char *) * sgl_in->len); if (sgl_out->subgroupDNs) { for (i = 0; i < sgl_in->len; i++) {
sgl_out->subgroupDNs[i] = util_ald_strdup(cache, sgl_in->subgroupDNs[i]); if (!sgl_out->subgroupDNs[i]) { /* We ran out of SHM, delete the strings we allocated for the SGL */ for (i = (i - 1); i >= 0; i--) {
util_ald_free(cache, sgl_out->subgroupDNs[i]);
}
util_ald_free(cache, sgl_out->subgroupDNs);
util_ald_free(cache, sgl_out);
sgl_out = NULL; break;
}
} /* We were able to allocate new strings for all the subgroups */ if (sgl_out != NULL) {
sgl_out->len = sgl_in->len;
}
}
}
return sgl_out;
}
/* * Delete an entire subgroupList.
*/ void util_ald_sgl_free(util_ald_cache_t *cache, util_compare_subgroup_t **sgl)
{ int i = 0; if (sgl == NULL || *sgl == NULL) { return;
}
for (i = 0; i < (*sgl)->len; i++) {
util_ald_free(cache, (*sgl)->subgroupDNs[i]);
}
util_ald_free(cache, *sgl);
}
/* * 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.
*/ unsignedlong util_ald_hash_string(int nstr, ...)
{ int i;
va_list args; unsignedlong 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)
{ unsignedlong i;
util_cache_node_t *p, *q, **pp;
apr_time_t now;
if (!cache) return;
now = cache->last_purge = apr_time_now();
cache->npurged = 0;
cache->numpurges++;
/* If the marktime is farther back than TTL from now, move the marktime forward to include additional expired entries.
*/ if (now - cache->ttl > cache->marktime) {
cache->marktime = now - cache->ttl;
}
for (i=0; i < cache->size; ++i) {
pp = cache->nodes + i;
p = *pp; while (p != NULL) { if (p->add_time < cache->marktime) {
q = p->next;
(*cache->free)(cache, p->payload);
util_ald_free(cache, p);
cache->numentries--;
cache->npurged++;
p = *pp = q;
} else {
pp = &(p->next);
p = *pp;
}
}
}
/* check that all the caches initialised successfully */ if (search_cache && compare_cache && dn_compare_cache) { /* The contents of this structure will be duplicated in shared memory during the insert. So use stack memory rather than
pool memory to avoid a memory leak. */
memset (&curl, 0, 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;
return util_ald_cache_insert(st->util_ldap_cache, &curl);
} else { /* util_ald_destroy_cache is a noop for a NULL argument. */
util_ald_destroy_cache(search_cache);
util_ald_destroy_cache(compare_cache);
util_ald_destroy_cache(dn_compare_cache);
cache->nodes = (util_cache_node_t **)util_ald_alloc(cache, cache->size * sizeof(util_cache_node_t *)); if (!cache->nodes) { /* This frees cache in the right way even if !APR_HAS_SHARED_MEMORY or !st->cache_rmm */
util_ald_free(cache, cache); return NULL;
}
for (i=0; i < cache->size; ++i)
cache->nodes[i] = NULL;
/* check if we are full - if so, try purge */ if (cache->numentries >= cache->maxentries) {
util_ald_cache_purge(cache); if (cache->numentries >= cache->maxentries) { /* if the purge was not effective, we leave now to avoid an overflow */
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, APLOGNO(01323) "Purge of LDAP cache failed"); return NULL;
}
}
node = (util_cache_node_t *)util_ald_alloc(cache, sizeof(util_cache_node_t)); if (node == NULL) { /* * XXX: The cache management should be rewritten to work * properly when LDAPSharedCacheSize is too small.
*/
ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL, APLOGNO(01324) "LDAPSharedCacheSize is too small. Increase it or " "reduce LDAPCacheEntries/LDAPOpCacheEntries!"); if (cache->numentries < cache->fullmark) { /* * We have not even reached fullmark, trigger a complete purge. * This is still better than not being able to add new entries * at all.
*/
cache->marktime = apr_time_now();
}
util_ald_cache_purge(cache);
node = (util_cache_node_t *)util_ald_alloc(cache, sizeof(util_cache_node_t)); if (node == NULL) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, APLOGNO(01325) "Could not allocate memory for LDAP cache entry"); return NULL;
}
}
/* Take a copy of the payload before proceeding. */
tmp_payload = (*cache->copy)(cache, payload); if (tmp_payload == NULL) { /* * XXX: The cache management should be rewritten to work * properly when LDAPSharedCacheSize is too small.
*/
ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL, APLOGNO(01326) "LDAPSharedCacheSize is too small. Increase it or " "reduce LDAPCacheEntries/LDAPOpCacheEntries!"); if (cache->numentries < cache->fullmark) { /* * We have not even reached fullmark, trigger a complete purge. * This is still better than not being able to add new entries * at all.
*/
cache->marktime = apr_time_now();
}
util_ald_cache_purge(cache);
tmp_payload = (*cache->copy)(cache, payload); if (tmp_payload == NULL) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, APLOGNO(01327) "Could not allocate memory for LDAP cache value");
util_ald_free(cache, node); return NULL;
}
}
payload = tmp_payload;
/* if we reach the full mark, note the time we did so * for the benefit of the purge function
*/ if (++cache->numentries == cache->fullmark) {
cache->marktime=apr_time_now();
}
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)(cache, p->payload);
util_ald_free(cache, p);
cache->numentries--;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.