1 /* $Id: tdx-cache.c 5394 2002-04-04 22:55:24Z rra $
3 ** Cache functions for open overview data files.
5 ** This code maintains a cache of open overview data files to avoid some of
6 ** the overhead involved in closing and reopening files. All opens and
7 ** closes should go through this code, and the hit ratio is tracked to check
8 ** cache effectiveness.
15 #include "inn/hashtab.h"
16 #include "inn/messages.h"
19 #include "tdx-private.h"
21 /* Returned to callers as an opaque data type, this struct holds all of the
22 information about the cache. */
24 struct hash *hashtable;
27 unsigned long queries;
31 /* A cache entry, holding a group_data struct and some additional information
32 used to do cache lookups and to choose what to drop from the cache. */
34 struct group_data *data;
41 ** The hash function for a cache_entry. Just return as much of the group
42 ** hash as can fit in an unsigned long.
45 entry_hash(const void *key)
47 const HASH *hash = key;
50 memcpy(&bucket, hash, sizeof(bucket));
56 ** Given a cache_entry, return its key.
59 entry_key(const void *data)
61 const struct cache_entry *entry = (const struct cache_entry *) data;
68 ** Check to see if two entries are equal.
71 entry_equal(const void *key, const void *data)
73 const HASH *hash = (const HASH *) key;
74 const struct cache_entry *entry = (const struct cache_entry *) data;
76 return (memcmp(hash, &entry->hash, sizeof(HASH)) == 0);
81 ** Free a cache entry.
84 entry_delete(void *data)
86 struct cache_entry *entry = (struct cache_entry *) data;
88 entry->data->refcount--;
89 if (entry->data->refcount == 0)
90 tdx_data_close(entry->data);
96 ** Called by hash_traverse, this function finds the oldest entry with the
97 ** smallest refcount and stores it in the provided pointer so that it can be
98 ** freed. This is used when the cache is full to drop the least useful
102 entry_find_oldest(void *data, void *cookie)
104 struct cache_entry *entry = (struct cache_entry *) data;
105 struct cache_entry **oldest = (struct cache_entry **) cookie;
107 if (*oldest == NULL) {
111 if (entry->data->refcount > (*oldest)->data->refcount)
113 if (entry->lastused > (*oldest)->lastused)
120 ** Create a new cache with the given size.
123 tdx_cache_create(unsigned int size)
127 cache = xmalloc(sizeof(struct cache));
132 cache->hashtable = hash_create(size * 4 / 3, entry_hash, entry_key,
133 entry_equal, entry_delete);
139 ** Look up a particular entry and return it.
142 tdx_cache_lookup(struct cache *cache, HASH hash)
144 struct cache_entry *entry;
147 entry = hash_lookup(cache->hashtable, &hash);
150 entry->lastused = time(NULL);
152 return (entry == NULL) ? NULL : entry->data;
157 ** Insert a new entry, clearing out the oldest entry if the cache is
161 tdx_cache_insert(struct cache *cache, HASH hash, struct group_data *data)
163 struct cache_entry *entry;
165 if (cache->count == cache->max) {
166 struct cache_entry *oldest = NULL;
168 hash_traverse(cache->hashtable, entry_find_oldest, &oldest);
169 if (oldest == NULL) {
170 warn("tradindexed: unable to find oldest cache entry");
173 if (!hash_delete(cache->hashtable, &oldest->hash)) {
174 warn("tradindexed: cannot delete oldest cache entry");
180 entry = xmalloc(sizeof(struct cache_entry));
183 entry->lastused = time(NULL);
184 if (!hash_insert(cache->hashtable, &entry->hash, entry)) {
185 warn("tradindexed: duplicate cache entry for %s", HashToText(hash));
188 entry->data->refcount++;
195 ** Delete an entry from the cache.
198 tdx_cache_delete(struct cache *cache, HASH hash)
200 if (!hash_delete(cache->hashtable, &hash))
201 warn("tradindexed: unable to remove cache entry for %s",
207 ** Delete the cache and all of the resources that it's holding open.
210 tdx_cache_free(struct cache *cache)
212 hash_free(cache->hashtable);