+++ /dev/null
-/* 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.
- */
-
-#include "apr_general.h"
-
-#include "mod_cache.h"
-#include "cache_hash.h"
-#include "cache_pqueue.h"
-#include "cache_cache.h"
-
-#if APR_HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#if APR_HAVE_STRING_H
-#include <string.h>
-#endif
-
-APLOG_USE_MODULE(cache);
-
-struct cache_cache_t {
- int max_entries;
- apr_size_t max_size;
- apr_size_t current_size;
- int total_purges;
- long queue_clock;
- cache_hash_t *ht;
- cache_pqueue_t *pq;
- cache_pqueue_set_priority set_pri;
- cache_pqueue_get_priority get_pri;
- cache_cache_inc_frequency *inc_entry;
- cache_cache_get_size *size_entry;
- cache_cache_get_key *key_entry;
- cache_cache_free *free_entry;
-};
-
-cache_cache_t* cache_init(int max_entries,
- apr_size_t max_size,
- cache_pqueue_get_priority get_pri,
- cache_pqueue_set_priority set_pri,
- cache_pqueue_getpos get_pos,
- cache_pqueue_setpos set_pos,
- cache_cache_inc_frequency *inc_entry,
- cache_cache_get_size *size_entry,
- cache_cache_get_key* key_entry,
- cache_cache_free *free_entry)
-{
- cache_cache_t *tmp;
- tmp = ap_malloc(sizeof(cache_cache_t));
- tmp->max_entries = max_entries;
- tmp->max_size = max_size;
- tmp->current_size = 0;
- tmp->total_purges = 0;
- tmp->queue_clock = 0;
- tmp->get_pri = get_pri;
- tmp->set_pri = set_pri;
- tmp->inc_entry = inc_entry;
- tmp->size_entry = size_entry;
- tmp->key_entry = key_entry;
- tmp->free_entry = free_entry;
-
- tmp->ht = cache_hash_make(max_entries);
- tmp->pq = cache_pq_init(max_entries, get_pri, get_pos, set_pos);
-
- return tmp;
-}
-
-void cache_free(cache_cache_t *c)
-{
- cache_pq_free(c->pq);
- cache_hash_free(c->ht);
- free(c);
-}
-
-
-void* cache_find(cache_cache_t* c, const char *key)
-{
- return cache_hash_get(c->ht, key, CACHE_HASH_KEY_STRING);
-}
-
-void cache_update(cache_cache_t* c, void *entry)
-{
- long old_priority;
- long new_priority;
-
- old_priority = c->set_pri(c->queue_clock, entry);
- c->inc_entry(entry);
- new_priority = c->set_pri(c->queue_clock, entry);
- cache_pq_change_priority(c->pq, old_priority, new_priority, entry);
-}
-
-void cache_insert(cache_cache_t* c, void *entry)
-{
- void *ejected = NULL;
- long priority;
-
- c->set_pri(c->queue_clock, entry);
- /* FIX: check if priority of bottom item is greater than inserted one */
- while ((cache_pq_size(c->pq) >= c->max_entries) ||
- ((c->current_size + c->size_entry(entry)) > c->max_size)) {
-
- ejected = cache_pq_pop(c->pq);
- /* FIX: If ejected is NULL, we'll segfault here */
- priority = c->get_pri(ejected);
-
- if (c->queue_clock > priority)
- c->queue_clock = priority;
-
- cache_hash_set(c->ht,
- c->key_entry(ejected),
- CACHE_HASH_KEY_STRING,
- NULL);
-
- c->current_size -= c->size_entry(ejected);
- c->free_entry(ejected);
- c->total_purges++;
- }
- c->current_size += c->size_entry(entry);
-
- cache_pq_insert(c->pq, entry);
- cache_hash_set(c->ht, c->key_entry(entry), CACHE_HASH_KEY_STRING, entry);
-}
-
-void* cache_pop(cache_cache_t *c)
-{
- void *entry;
-
- if (!c)
- return NULL;
-
- entry = cache_pq_pop(c->pq);
-
- if (!entry)
- return NULL;
-
- c->current_size -= c->size_entry(entry);
- cache_hash_set(c->ht, c->key_entry(entry), CACHE_HASH_KEY_STRING, NULL);
-
- return entry;
-}
-
-apr_status_t cache_remove(cache_cache_t *c, void *entry)
-{
- apr_size_t entry_size = c->size_entry(entry);
- apr_status_t rc;
- rc = cache_pq_remove(c->pq, entry);
- if (rc != APR_SUCCESS)
- return rc;
-
- cache_hash_set(c->ht, c->key_entry(entry), CACHE_HASH_KEY_STRING, NULL);
- c->current_size -= entry_size;
-
- return APR_SUCCESS;
-}
+++ /dev/null
-/* 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.
- */
-
-/**
- * @file cache_cache.h
- * @brief Cache Cache Functions
- *
- * @defgroup Cache_cache Cache Functions
- * @ingroup MOD_CACHE
- * @{
- */
-
-#ifndef CACHE_CACHE_H
-#define CACHE_CACHE_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "mod_cache.h"
-
-/** ADT for the cache */
-typedef struct cache_cache_t cache_cache_t;
-
-/** callback to increment the frequency of a item */
-typedef void cache_cache_inc_frequency(void*a);
-/** callback to get the size of a item */
-typedef apr_size_t cache_cache_get_size(void*a);
-/** callback to get the key of a item */
-typedef const char* cache_cache_get_key(void *a);
-/** callback to free an entry */
-typedef void cache_cache_free(void *a);
-
-/**
- * initialize the cache ADT
- * @param max_entries the number of entries in the cache
- * @param max_size the size of the cache
- * @param get_pri callback to get a priority of a entry
- * @param set_pri callback to set a priority of a entry
- * @param get_pos callback to get the position of a entry in the cache
- * @param set_pos callback to set the position of a entry in the cache
- * @param inc_entry callback to increment the frequency of a entry
- * @param size_entry callback to get the size of a entry
- * @param key_entry callback to get the key of a entry
- * @param free_entry callback to free an entry
- */
-cache_cache_t* cache_init(int max_entries,
- apr_size_t max_size,
- cache_pqueue_get_priority get_pri,
- cache_pqueue_set_priority set_pri,
- cache_pqueue_getpos get_pos,
- cache_pqueue_setpos set_pos,
- cache_cache_inc_frequency *inc_entry,
- cache_cache_get_size *size_entry,
- cache_cache_get_key *key_entry,
- cache_cache_free *free_entry);
-
-/**
- * free up the cache
- * @param c the cache
- */
-void cache_free(cache_cache_t *c);
-/**
- * find a entry in the cache, incrementing the frequency if found
- * @param c the cache
- * @param key the key
- */
-void* cache_find(cache_cache_t* c, const char *key);
-/**
- * insert a entry into the cache
- * @param c the cache
- * @param entry the entry
- */
-void cache_update(cache_cache_t* c, void *entry);
-/**
- * insert a entry into the cache
- * @param c the cache
- * @param entry the entry
- */
-void cache_insert(cache_cache_t* c, void *entry);
-/**
- * pop the lowest priority item off
- * @param c the cache
- * @returns the entry or NULL
- */
-void* cache_pop(cache_cache_t* c);
-/**
- * remove an item from the cache
- * @param c the cache
- * @param entry the actual entry (from a find)
- */
-apr_status_t cache_remove(cache_cache_t* c, void *entry);
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* !CACHE_CACHE_H */
-/** @} */
+++ /dev/null
-/* 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.
- */
-
-#include "apr_general.h"
-
-#include "mod_cache.h"
-#include "cache_hash.h"
-
-#if APR_HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#if APR_HAVE_STRING_H
-#include <string.h>
-#endif
-
-
-/*
- * The internal form of a hash table.
- *
- * The table is an array indexed by the hash of the key; collisions
- * are resolved by hanging a linked list of hash entries off each
- * element of the array. Although this is a really simple design it
- * isn't too bad given that pools have a low allocation overhead.
- */
-
-typedef struct cache_hash_entry_t cache_hash_entry_t;
-
-struct cache_hash_entry_t {
- cache_hash_entry_t *next;
- unsigned int hash;
- const void *key;
- apr_ssize_t klen;
- const void *val;
-};
-
-/*
- * Data structure for iterating through a hash table.
- *
- * We keep a pointer to the next hash entry here to allow the current
- * hash entry to be freed or otherwise mangled between calls to
- * cache_hash_next().
- */
-struct cache_hash_index_t {
- cache_hash_t *ht;
- cache_hash_entry_t *this, *next;
- int index;
-};
-
-/*
- * The size of the array is always a power of two. We use the maximum
- * index rather than the size so that we can use bitwise-AND for
- * modular arithmetic.
- * The count of hash entries may be greater depending on the chosen
- * collision rate.
- */
-struct cache_hash_t {
- cache_hash_entry_t **array;
- cache_hash_index_t iterator; /* For cache_hash_first(NULL, ...) */
- int count, max;
-};
-
-/*
- * Hash creation functions.
- */
-static cache_hash_entry_t **alloc_array(cache_hash_t *ht, int max)
-{
- return ap_calloc(1, sizeof(*ht->array) * (max + 1));
-}
-
-cache_hash_t* cache_hash_make(apr_size_t size)
-{
- cache_hash_t *ht;
- ht = ap_malloc(sizeof(cache_hash_t));
- ht->count = 0;
- ht->max = size;
- ht->array = alloc_array(ht, ht->max);
- return ht;
-}
-
-void cache_hash_free(cache_hash_t *ht)
-{
- if (ht) {
- if (ht->array) {
- free (ht->array);
- }
- free (ht);
- }
-}
-/*
- * Hash iteration functions.
- */
-
-cache_hash_index_t* cache_hash_next(cache_hash_index_t *hi)
-{
- hi->this = hi->next;
- while (!hi->this) {
- if (hi->index > hi->ht->max)
- return NULL;
- hi->this = hi->ht->array[hi->index++];
- }
- hi->next = hi->this->next;
- return hi;
-}
-
-cache_hash_index_t* cache_hash_first(cache_hash_t *ht)
-{
- cache_hash_index_t *hi;
-
- hi = &ht->iterator;
- hi->ht = ht;
- hi->index = 0;
- hi->this = NULL;
- hi->next = NULL;
- return cache_hash_next(hi);
-}
-
-void cache_hash_this(cache_hash_index_t *hi,
- const void **key,
- apr_ssize_t *klen,
- void **val)
-{
- if (key) *key = hi->this->key;
- if (klen) *klen = hi->this->klen;
- if (val) *val = (void *)hi->this->val;
-}
-
-
-/*
- * This is where we keep the details of the hash function and control
- * the maximum collision rate.
- *
- * If val is non-NULL it creates and initializes a new hash entry if
- * there isn't already one there; it returns an updatable pointer so
- * that hash entries can be removed.
- */
-
-static cache_hash_entry_t **find_entry(cache_hash_t *ht,
- const void *key,
- apr_ssize_t klen,
- const void *val)
-{
- cache_hash_entry_t **hep, *he;
- const unsigned char *p;
- unsigned int hash;
- apr_ssize_t i;
-
- /*
- * This is the popular `times 33' hash algorithm which is used by
- * perl and also appears in Berkeley DB. This is one of the best
- * known hash functions for strings because it is both computed
- * very fast and distributes very well.
- *
- * The originator may be Dan Bernstein but the code in Berkeley DB
- * cites Chris Torek as the source. The best citation I have found
- * is "Chris Torek, Hash function for text in C, Usenet message
- * <27038@mimsy.umd.edu> in comp.lang.c , October, 1990." in Rich
- * Salz's USENIX 1992 paper about INN which can be found at
- * <http://citeseer.nj.nec.com/salz92internetnews.html>.
- *
- * The magic of number 33, i.e. why it works better than many other
- * constants, prime or not, has never been adequately explained by
- * anyone. So I try an explanation: if one experimentally tests all
- * multipliers between 1 and 256 (as I did while writing a low-level
- * data structure library some time ago) one detects that even
- * numbers are not useable at all. The remaining 128 odd numbers
- * (except for the number 1) work more or less all equally well.
- * They all distribute in an acceptable way and this way fill a hash
- * table with an average percent of approx. 86%.
- *
- * If one compares the chi^2 values of the variants (see
- * Bob Jenkins ``Hashing Frequently Asked Questions'' at
- * http://burtleburtle.net/bob/hash/hashfaq.html for a description
- * of chi^2), the number 33 not even has the best value. But the
- * number 33 and a few other equally good numbers like 17, 31, 63,
- * 127 and 129 have nevertheless a great advantage to the remaining
- * numbers in the large set of possible multipliers: their multiply
- * operation can be replaced by a faster operation based on just one
- * shift plus either a single addition or subtraction operation. And
- * because a hash function has to both distribute good _and_ has to
- * be very fast to compute, those few numbers should be preferred.
- *
- * -- Ralf S. Engelschall <rse@engelschall.com>
- */
- hash = 0;
- if (klen == CACHE_HASH_KEY_STRING) {
- for (p = key; *p; p++) {
- hash = hash * 33 + *p;
- }
- klen = p - (const unsigned char *)key;
- }
- else {
- for (p = key, i = klen; i; i--, p++) {
- hash = hash * 33 + *p;
- }
- }
-
- /* scan linked list */
- for (hep = &ht->array[hash % ht->max], he = *hep;
- he;
- hep = &he->next, he = *hep) {
- if (he->hash == hash &&
- he->klen == klen &&
- memcmp(he->key, key, klen) == 0)
- break;
- }
- if (he || !val)
- return hep;
- /* add a new entry for non-NULL values */
- he = ap_malloc(sizeof(*he));
- he->next = NULL;
- he->hash = hash;
- he->key = key;
- he->klen = klen;
- he->val = val;
- *hep = he;
- ht->count++;
- return hep;
-}
-
-void* cache_hash_get(cache_hash_t *ht,
- const void *key,
- apr_ssize_t klen)
-{
- cache_hash_entry_t *he;
- he = *find_entry(ht, key, klen, NULL);
- if (he)
- return (void *)he->val;
- else
- return NULL;
-}
-
-void* cache_hash_set(cache_hash_t *ht,
- const void *key,
- apr_ssize_t klen,
- const void *val)
-{
- cache_hash_entry_t **hep, *tmp;
- const void *tval;
- hep = find_entry(ht, key, klen, val);
- if (*hep) {
- if (!val) {
- /* delete entry */
- tval = (*hep)->val;
- tmp = *hep;
- *hep = (*hep)->next;
- free(tmp);
- --ht->count;
- }
- else {
- /* replace entry */
- tval = (*hep)->val;
- (*hep)->val = val;
- }
- /* Return the object just removed from the cache to let the
- * caller clean it up. Cast the constness away upon return.
- */
- return (void *) tval;
- }
- /* else key not present and val==NULL */
- return NULL;
-}
-
-int cache_hash_count(cache_hash_t *ht)
-{
- return ht->count;
-}
+++ /dev/null
-/* 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.
- */
-
-/**
- * @file cache_hash.h
- * @brief Cache Hash Tables
- *
- * @defgroup Cache_Hash Hash Tables
- * @ingroup MOD_CACHE
- * @{
- */
-
-#ifndef CACHE_HASH_H
-#define CACHE_HASH_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "mod_cache.h"
-
-/**
- * When passing a key to cache_hash_set or cache_hash_get, this value can be
- * passed to indicate a string-valued key, and have cache_hash compute the
- * length automatically.
- *
- * @remark cache_hash will use strlen(key) for the length. The null-terminator
- * is not included in the hash value (why throw a constant in?).
- * Since the hash table merely references the provided key (rather
- * than copying it), cache_hash_this() will return the null-term'd key.
- */
-#define CACHE_HASH_KEY_STRING (-1)
-
-/**
- * Abstract type for hash tables.
- */
-typedef struct cache_hash_t cache_hash_t;
-
-/**
- * Abstract type for scanning hash tables.
- */
-typedef struct cache_hash_index_t cache_hash_index_t;
-
-/**
- * Create a hash table.
- * @param size
- * @return The hash table just created
- */
-cache_hash_t* cache_hash_make(apr_size_t size);
-
-/**
- * Create a hash table.
- * @param *ht Pointer to the hash table to be freed.
- * @return void
- * @remark The caller should ensure that all objects have been removed
- * from the cache prior to calling cache_hash_free(). Objects
- * not removed from the cache prior to calling cache_hash_free()
- * will be unaccessable.
- */
-void cache_hash_free(cache_hash_t *ht);
-
-
-/**
- * Associate a value with a key in a hash table.
- * @param ht The hash table
- * @param key Pointer to the key
- * @param klen Length of the key. Can be CACHE_HASH_KEY_STRING to use the string length.
- * @param val Value to associate with the key
- * @remark If the value is NULL the hash entry is deleted.
- * @return The value of the deleted cache entry (so the caller can clean it up).
- */
-void* cache_hash_set(cache_hash_t *ht, const void *key,
- apr_ssize_t klen, const void *val);
-
-/**
- * Look up the value associated with a key in a hash table.
- * @param ht The hash table
- * @param key Pointer to the key
- * @param klen Length of the key. Can be CACHE_HASH_KEY_STRING to use the string length.
- * @return Returns NULL if the key is not present.
- */
-void* cache_hash_get(cache_hash_t *ht, const void *key,
- apr_ssize_t klen);
-
-/**
- * Start iterating over the entries in a hash table.
- * @param ht The hash table
- *
- * Here is an example of using this:
- * @code
- * int sum_values(cache_hash_t *ht)
- * {
- * cache_hash_index_t *hi;
- * void *val;
- * int sum = 0;
- * for (hi = cache_hash_first(ht); hi; hi = cache_hash_next(hi)) {
- * cache_hash_this(hi, NULL, NULL, &val);
- * sum += *(int *)val;
- * }
- * return sum;
- * }
- * @endcode
- *
- * There is no restriction on adding or deleting hash entries during an
- * iteration (although the results may be unpredictable unless all you do
- * is delete the current entry) and multiple iterations can be in
- * progress at the same time.
- */
-cache_hash_index_t* cache_hash_first(cache_hash_t *ht);
-
-/**
- * Continue iterating over the entries in a hash table.
- * @param hi The iteration state
- * @return a pointer to the updated iteration state. NULL if there are no more
- * entries.
- */
-cache_hash_index_t* cache_hash_next(cache_hash_index_t *hi);
-
-/**
- * Get the current entry's details from the iteration state.
- * @param hi The iteration state
- * @param key Return pointer for the pointer to the key.
- * @param klen Return pointer for the key length.
- * @param val Return pointer for the associated value.
- * @remark The return pointers should point to a variable that will be set to the
- * corresponding data, or they may be NULL if the data isn't interesting.
- */
-void cache_hash_this(cache_hash_index_t *hi, const void **key,
- apr_ssize_t *klen, void **val);
-
-/**
- * Get the number of key/value pairs in the hash table.
- * @param ht The hash table
- * @return The number of key/value pairs in the hash table.
- */
-int cache_hash_count(cache_hash_t *ht);
-
-
-/** @} */
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* !CACHE_HASH_H */
+++ /dev/null
-/* 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.
- */
-
-#include "apr_general.h"
-
-#if APR_HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#if APR_HAVE_STDIO_H
-#include <stdio.h>
-#endif
-
-#if APR_HAVE_STRING_H
-#include <string.h>
-#endif
-
-#include "cache_pqueue.h"
-#define left(i) (2*(i))
-#define right(i) ((2*(i))+1)
-#define parent(i) ((i)/2)
-/*
- * Priority queue structure
- */
-struct cache_pqueue_t
-{
- apr_ssize_t size;
- apr_ssize_t avail;
- apr_ssize_t step;
- cache_pqueue_get_priority pri;
- cache_pqueue_getpos get;
- cache_pqueue_setpos set;
- void **d;
-};
-
-cache_pqueue_t *cache_pq_init(apr_ssize_t n,
- cache_pqueue_get_priority pri,
- cache_pqueue_getpos get,
- cache_pqueue_setpos set)
-{
- cache_pqueue_t *q = ap_malloc(sizeof(cache_pqueue_t));
- /* Need to allocate n+1 elements since element 0 isn't used. */
- q->d = ap_malloc(sizeof(void*) * (n+1));
- q->avail = q->step = (n+1); /* see comment above about n+1 */
- q->pri = pri;
- q->size = 1;
- q->get = get;
- q->set = set;
- return q;
-}
-/*
- * cleanup
- */
-void cache_pq_free(cache_pqueue_t *q)
-{
- free(q->d);
- free(q);
-}
-/*
- * pqsize: size of the queue.
- */
-apr_ssize_t cache_pq_size(cache_pqueue_t *q)
-{
- /* queue element 0 exists but doesn't count since it isn't used. */
- return (q->size - 1);
-}
-
-static void cache_pq_bubble_up(cache_pqueue_t *q, apr_ssize_t i)
-{
- apr_ssize_t parent_node;
- void *moving_node = q->d[i];
- long moving_pri = q->pri(moving_node);
-
- for (parent_node = parent(i);
- ((i > 1) && (q->pri(q->d[parent_node]) < moving_pri));
- i = parent_node, parent_node = parent(i))
- {
- q->d[i] = q->d[parent_node];
- q->set(q->d[i], i);
- }
-
- q->d[i] = moving_node;
- q->set(moving_node, i);
-}
-
-static apr_ssize_t maxchild(cache_pqueue_t *q, apr_ssize_t i)
-{
- apr_ssize_t child_node = left(i);
-
- if (child_node >= q->size)
- return 0;
-
- if ((child_node+1 < q->size) &&
- (q->pri(q->d[child_node+1]) > q->pri(q->d[child_node])))
- {
- child_node++; /* use right child instead of left */
- }
-
- return child_node;
-}
-
-static void cache_pq_percolate_down(cache_pqueue_t *q, apr_ssize_t i)
-{
- apr_ssize_t child_node;
- void *moving_node = q->d[i];
- long moving_pri = q->pri(moving_node);
-
- while ((child_node = maxchild(q, i)) &&
- (moving_pri < q->pri(q->d[child_node])))
- {
- q->d[i] = q->d[child_node];
- q->set(q->d[i], i);
- i = child_node;
- }
-
- q->d[i] = moving_node;
- q->set(moving_node, i);
-}
-
-apr_status_t cache_pq_insert(cache_pqueue_t *q, void *d)
-{
- void *tmp;
- apr_ssize_t i;
- apr_ssize_t newsize;
-
- if (!q) return APR_EGENERAL;
-
- /* allocate more memory if necessary */
- if (q->size >= q->avail) {
- newsize = q->size + q->step;
- if (!(tmp = ap_realloc(q->d, sizeof(void*) * newsize))) {
- return APR_EGENERAL;
- };
- q->d = tmp;
- q->avail = newsize;
- }
-
- /* insert item */
- i = q->size++;
- q->d[i] = d;
- cache_pq_bubble_up(q, i);
- return APR_SUCCESS;
-}
-
-/*
- * move a existing entry to a new priority
- */
-void cache_pq_change_priority(cache_pqueue_t *q,
- long old_priority,
- long new_priority,
- void *d)
-{
- apr_ssize_t posn;
-
- posn = q->get(d);
- if (new_priority > old_priority)
- cache_pq_bubble_up(q, posn);
- else
- cache_pq_percolate_down(q, posn);
-}
-
-apr_status_t cache_pq_remove(cache_pqueue_t *q, void *d)
-{
- apr_ssize_t posn = q->get(d);
- q->d[posn] = q->d[--q->size];
- if (q->pri(q->d[posn]) > q->pri(d))
- cache_pq_bubble_up(q, posn);
- else
- cache_pq_percolate_down(q, posn);
-
- return APR_SUCCESS;
-}
-
-void *cache_pq_pop(cache_pqueue_t *q)
-{
- void *head;
-
- if (!q || q->size == 1)
- return NULL;
-
- head = q->d[1];
- q->d[1] = q->d[--q->size];
- cache_pq_percolate_down(q, 1);
-
- return head;
-}
-
-void *cache_pq_peek(cache_pqueue_t *q)
-{
- void *d;
- if (!q || q->size == 1)
- return NULL;
- d = q->d[1];
- return d;
-}
-
-static void cache_pq_set_null( void*d, apr_ssize_t val)
-{
- /* do nothing */
-}
-
-/*
- * this is a debug function.. so it's EASY not fast
- */
-void cache_pq_dump(cache_pqueue_t *q,
- FILE*out,
- cache_pqueue_print_entry print)
-{
- int i;
-
- fprintf(stdout,"posn\tleft\tright\tparent\tmaxchild\t...\n");
- for (i = 1; i < q->size ;i++) {
- fprintf(stdout,
- "%d\t%d\t%d\t%d\t%" APR_SSIZE_T_FMT "\t",
- i,
- left(i), right(i), parent(i),
- maxchild(q, i));
- print(out, q->d[i]);
- }
-}
-
-/*
- * this is a debug function.. so it's EASY not fast
- */
-void cache_pq_print(cache_pqueue_t *q,
- FILE*out,
- cache_pqueue_print_entry print)
-{
- cache_pqueue_t *dup;
- dup = cache_pq_init(q->size, q->pri, q->get, cache_pq_set_null);
- dup->size = q->size;
- dup->avail = q->avail;
- dup->step = q->step;
-
- memcpy(dup->d, q->d, q->size*sizeof(void*));
-
- while (cache_pq_size(dup) > 1) {
- void *e = NULL;
- e = cache_pq_pop(dup);
- if (e)
- print(out, e);
- else
- break;
- }
- cache_pq_free(dup);
-}
-
-static int cache_pq_subtree_is_valid(cache_pqueue_t *q, int pos)
-{
- if (left(pos) < q->size) {
- /* has a left child */
- if (q->pri(q->d[pos]) < q->pri(q->d[left(pos)]))
- return 0;
- if (!cache_pq_subtree_is_valid(q, left(pos)))
- return 0;
- }
- if (right(pos) < q->size) {
- /* has a right child */
- if (q->pri(q->d[pos]) < q->pri(q->d[right(pos)]))
- return 0;
- if (!cache_pq_subtree_is_valid(q, right(pos)))
- return 0;
- }
- return 1;
-}
-
-int cache_pq_is_valid(cache_pqueue_t *q)
-{
- return cache_pq_subtree_is_valid(q, 1);
-}
+++ /dev/null
-/* 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.
- */
-
-/**
- * @file cache_pqueue.h
- * @brief Cache Priority Queue function declarations
- *
- * @defgroup MOD_CACHE_QUEUE Priority Queue
- * @ingroup MOD_CACHE
- * @{
- */
-
-#ifndef CACHE_PQUEUE_H
-#define CACHE_PQUEUE_H
-
-#include <apr.h>
-#include <apr_errno.h>
-
-#if APR_HAVE_STDIO_H
-#include <stdio.h>
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/** the cache priority queue handle */
-typedef struct cache_pqueue_t cache_pqueue_t;
-
-/**
- * callback function to assign a priority for a element
- * @param a the element
- * @return the score (the lower the score the longer it is kept int the queue)
- */
-typedef long (*cache_pqueue_set_priority)(long queue_clock, void *a);
-typedef long (*cache_pqueue_get_priority)(void *a);
-
-/** callback function to get a position of a element */
-typedef apr_ssize_t (*cache_pqueue_getpos)(void *a);
-
-/**
- * callback function to set a position of a element
- * @param a the element
- * @param pos the position to set it to
- */
-typedef void (*cache_pqueue_setpos)(void *a, apr_ssize_t pos);
-
-/** debug callback function to print a entry */
-typedef void (*cache_pqueue_print_entry)(FILE *out, void *a);
-
-/**
- * initialize the queue
- *
- * @param n the initial estimate of the number of queue items for which memory
- * should be preallocated
- * @param pri the callback function to run to assign a score to a element
- * @param get the callback function to get the current element's position
- * @param set the callback function to set the current element's position
- *
- * @return the handle or NULL for insufficent memory
- */
-cache_pqueue_t *cache_pq_init(apr_ssize_t n,
- cache_pqueue_get_priority pri,
- cache_pqueue_getpos get,
- cache_pqueue_setpos set);
-/**
- * free all memory used by the queue
- * @param q the queue
- */
-void cache_pq_free(cache_pqueue_t *q);
-/**
- * return the size of the queue.
- * @param q the queue
- */
-apr_ssize_t cache_pq_size(cache_pqueue_t *q);
-
-/**
- * insert an item into the queue.
- * @param q the queue
- * @param d the item
- * @return APR_SUCCESS on success
- */
-apr_status_t cache_pq_insert(cache_pqueue_t *q, void *d);
-
-/*
- * move a existing entry to a different priority
- * @param q the queue
- * @param old the old priority
- * @param d the entry
- */
-void cache_pq_change_priority(cache_pqueue_t *q,
- long old_priority,
- long new_priority,
- void *d);
-
-/**
- * pop the highest-ranking item from the queue.
- * @param q the queue
- * @return NULL on error, otherwise the entry
- */
-void *cache_pq_pop(cache_pqueue_t *q);
-
-/**
- * remove an item from the queue.
- * @param q the queue
- * @param d the entry
- * @return APR_SUCCESS on success
- */
-apr_status_t cache_pq_remove(cache_pqueue_t *q, void *d);
-
-/**
- * access highest-ranking item without removing it.
- * @param q the queue
- * @return NULL on error, otherwise the entry
- */
-void *cache_pq_peek(cache_pqueue_t *q);
-
-/**
- * print the queue
- * @internal
- * DEBUG function only
- * @param q the queue
- * @param out the output handle
- * @param print the callback function to print the entry
- */
-void cache_pq_print(cache_pqueue_t *q,
- FILE *out,
- cache_pqueue_print_entry print);
-
-/**
- * dump the queue and its internal structure
- * @internal
- * debug function only
- * @param q the queue
- * @param out the output handle
- * @param print the callback function to print the entry
- */
-void cache_pq_dump(cache_pqueue_t *q,
- FILE *out,
- cache_pqueue_print_entry print);
-
-/**
- * checks that the pq is in the right order, etc
- * @internal
- * debug function only
- * @param q the queue
- */
-int cache_pq_is_valid(cache_pqueue_t *q);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* !CACHE_PQUEUE_H */
-/** @} */