Commit 934a6d3f authored by Graham Leggett's avatar Graham Leggett
Browse files

mod_cache: Remove dead code from the legacy mod_mem_cache module.


git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1210892 13f79535-47bb-0310-9956-ffa450edef68
parent f1e44dd9
Loading
Loading
Loading
Loading

modules/cache/cache_cache.c

deleted100644 → 0
+0 −166
Changes for modules/cache/cache_cache.c: 0 added lines, 166 removed lines.
Original line number Diff line number Diff line
/* 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;
}

modules/cache/cache_cache.h

deleted100644 → 0
+0 −111
Changes for modules/cache/cache_cache.h: 0 added lines, 111 removed lines.
Original line number Diff line number Diff line
/* 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 */
/** @} */

modules/cache/cache_hash.c

deleted100644 → 0
+0 −279
Changes for modules/cache/cache_hash.c: 0 added lines, 279 removed lines.
Original line number Diff line number Diff line
/* 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;
}

modules/cache/cache_hash.h

deleted100644 → 0
+0 −157
Changes for modules/cache/cache_hash.h: 0 added lines, 157 removed lines.
Original line number Diff line number Diff line
/* 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 */

modules/cache/cache_pqueue.c

deleted100644 → 0
+0 −282

File deleted.

Preview size limit exceeded, changes collapsed.

Loading