Commit | Line | Data |
---|---|---|
460b9539 | 1 | /* |
2 | * This file is part of DisOrder | |
5aff007d | 3 | * Copyright (C) 2006-2008 Richard Kettlewell |
460b9539 | 4 | * |
e7eb3a27 | 5 | * This program is free software: you can redistribute it and/or modify |
460b9539 | 6 | * it under the terms of the GNU General Public License as published by |
e7eb3a27 | 7 | * the Free Software Foundation, either version 3 of the License, or |
460b9539 | 8 | * (at your option) any later version. |
e7eb3a27 RK |
9 | * |
10 | * This program is distributed in the hope that it will be useful, | |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | * GNU General Public License for more details. | |
14 | * | |
460b9539 | 15 | * You should have received a copy of the GNU General Public License |
e7eb3a27 | 16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
460b9539 | 17 | */ |
14ad73b9 | 18 | /** @file lib/cache.c @brief Object caching */ |
460b9539 | 19 | |
05b75f8d | 20 | #include "common.h" |
460b9539 | 21 | |
22 | #include <time.h> | |
23 | ||
24 | #include "hash.h" | |
25 | #include "mem.h" | |
26 | #include "log.h" | |
27 | #include "cache.h" | |
28 | ||
d7b6f0d1 | 29 | /** @brief The global cache */ |
460b9539 | 30 | static hash *h; |
31 | ||
d7b6f0d1 | 32 | /** @brief One cache entry */ |
460b9539 | 33 | struct cache_entry { |
d7b6f0d1 | 34 | /** @brief What type of object this is */ |
460b9539 | 35 | const struct cache_type *type; |
d7b6f0d1 | 36 | |
37 | /** @brief Pointer to object value */ | |
460b9539 | 38 | const void *value; |
d7b6f0d1 | 39 | |
40 | /** @brief Time that object was inserted into cache */ | |
460b9539 | 41 | time_t birth; |
42 | }; | |
43 | ||
d7b6f0d1 | 44 | /** @brief Return true if object @p c has expired */ |
460b9539 | 45 | static int expired(const struct cache_entry *c, time_t now) { |
46 | return now - c->birth > c->type->lifetime; | |
47 | } | |
48 | ||
d7b6f0d1 | 49 | /** @brief Insert an object into the cache |
50 | * @param type Pointer to object type | |
51 | * @param key Unique key | |
52 | * @param value Pointer to value | |
53 | */ | |
460b9539 | 54 | void cache_put(const struct cache_type *type, |
55 | const char *key, const void *value) { | |
56 | struct cache_entry *c; | |
57 | ||
58 | if(!h) | |
59 | h = hash_new(sizeof (struct cache_entry)); | |
60 | c = xmalloc(sizeof *c); | |
61 | c->type = type; | |
62 | c->value = value; | |
63 | time(&c->birth); | |
64 | hash_add(h, key, c, HASH_INSERT_OR_REPLACE); | |
65 | } | |
66 | ||
d7b6f0d1 | 67 | /** @brief Look up an object in the cache |
68 | * @param type Pointer to object type | |
69 | * @param key Unique key | |
70 | * @return Pointer to object value or NULL if not found | |
71 | */ | |
460b9539 | 72 | const void *cache_get(const struct cache_type *type, const char *key) { |
73 | const struct cache_entry *c; | |
74 | ||
75 | if(h | |
76 | && (c = hash_find(h, key)) | |
77 | && c->type == type | |
78 | && !expired(c, time(0))) | |
79 | return c->value; | |
80 | else | |
81 | return 0; | |
82 | } | |
83 | ||
0e4472a0 | 84 | /** @brief Call used by from cache_expire() */ |
460b9539 | 85 | static int expiry_callback(const char *key, void *value, void *u) { |
86 | const struct cache_entry *c = value; | |
87 | const time_t *now = u; | |
88 | ||
89 | if(expired(c, *now)) | |
90 | hash_remove(h, key); | |
91 | return 0; | |
92 | } | |
93 | ||
d7b6f0d1 | 94 | /** @brief Expire the cache |
95 | * | |
96 | * Called from time to time to expire cache entries. */ | |
460b9539 | 97 | void cache_expire(void) { |
98 | time_t now; | |
99 | ||
100 | if(h) { | |
101 | time(&now); | |
102 | hash_foreach(h, expiry_callback, &now); | |
103 | } | |
104 | } | |
105 | ||
0e4472a0 | 106 | /** @brief Callback used by cache_clean() */ |
460b9539 | 107 | static int clean_callback(const char *key, void *value, void *u) { |
108 | const struct cache_entry *c = value; | |
109 | const struct cache_type *type = u; | |
110 | ||
111 | if(!type || c->type == type) | |
112 | hash_remove(h, key); | |
113 | return 0; | |
114 | } | |
115 | ||
d7b6f0d1 | 116 | /** @brief Clean the cache |
117 | * @param type Pointer to type to clean | |
118 | * | |
119 | * Removes all entries of type @p type from the cache. | |
120 | */ | |
460b9539 | 121 | void cache_clean(const struct cache_type *type) { |
122 | if(h) | |
123 | hash_foreach(h, clean_callback, (void *)type); | |
124 | } | |
125 | ||
d7b6f0d1 | 126 | /** @brief Report cache size |
127 | * | |
128 | * Returns the number of objects in the cache | |
129 | */ | |
0b7c8909 | 130 | size_t cache_count(void) { |
131 | return h ? hash_count(h) : 0; | |
132 | } | |
133 | ||
460b9539 | 134 | /* |
135 | Local Variables: | |
136 | c-basic-offset:2 | |
137 | comment-column:40 | |
138 | fill-column:79 | |
139 | indent-tabs-mode:nil | |
140 | End: | |
141 | */ |