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" | |
4265e5d3 | 27 | #include "syscalls.h" |
460b9539 | 28 | #include "cache.h" |
29 | ||
d7b6f0d1 | 30 | /** @brief The global cache */ |
460b9539 | 31 | static hash *h; |
32 | ||
d7b6f0d1 | 33 | /** @brief One cache entry */ |
460b9539 | 34 | struct cache_entry { |
d7b6f0d1 | 35 | /** @brief What type of object this is */ |
460b9539 | 36 | const struct cache_type *type; |
d7b6f0d1 | 37 | |
38 | /** @brief Pointer to object value */ | |
460b9539 | 39 | const void *value; |
d7b6f0d1 | 40 | |
41 | /** @brief Time that object was inserted into cache */ | |
460b9539 | 42 | time_t birth; |
43 | }; | |
44 | ||
d7b6f0d1 | 45 | /** @brief Return true if object @p c has expired */ |
460b9539 | 46 | static int expired(const struct cache_entry *c, time_t now) { |
47 | return now - c->birth > c->type->lifetime; | |
48 | } | |
49 | ||
d7b6f0d1 | 50 | /** @brief Insert an object into the cache |
51 | * @param type Pointer to object type | |
52 | * @param key Unique key | |
53 | * @param value Pointer to value | |
54 | */ | |
460b9539 | 55 | void cache_put(const struct cache_type *type, |
56 | const char *key, const void *value) { | |
57 | struct cache_entry *c; | |
58 | ||
59 | if(!h) | |
60 | h = hash_new(sizeof (struct cache_entry)); | |
61 | c = xmalloc(sizeof *c); | |
62 | c->type = type; | |
63 | c->value = value; | |
4265e5d3 | 64 | xtime(&c->birth); |
460b9539 | 65 | hash_add(h, key, c, HASH_INSERT_OR_REPLACE); |
66 | } | |
67 | ||
d7b6f0d1 | 68 | /** @brief Look up an object in the cache |
69 | * @param type Pointer to object type | |
70 | * @param key Unique key | |
71 | * @return Pointer to object value or NULL if not found | |
72 | */ | |
460b9539 | 73 | const void *cache_get(const struct cache_type *type, const char *key) { |
74 | const struct cache_entry *c; | |
75 | ||
76 | if(h | |
77 | && (c = hash_find(h, key)) | |
78 | && c->type == type | |
4265e5d3 | 79 | && !expired(c, xtime(0))) |
460b9539 | 80 | return c->value; |
81 | else | |
82 | return 0; | |
83 | } | |
84 | ||
0e4472a0 | 85 | /** @brief Call used by from cache_expire() */ |
460b9539 | 86 | static int expiry_callback(const char *key, void *value, void *u) { |
87 | const struct cache_entry *c = value; | |
88 | const time_t *now = u; | |
89 | ||
90 | if(expired(c, *now)) | |
91 | hash_remove(h, key); | |
92 | return 0; | |
93 | } | |
94 | ||
d7b6f0d1 | 95 | /** @brief Expire the cache |
96 | * | |
97 | * Called from time to time to expire cache entries. */ | |
460b9539 | 98 | void cache_expire(void) { |
99 | time_t now; | |
100 | ||
101 | if(h) { | |
4265e5d3 | 102 | xtime(&now); |
460b9539 | 103 | hash_foreach(h, expiry_callback, &now); |
104 | } | |
105 | } | |
106 | ||
0e4472a0 | 107 | /** @brief Callback used by cache_clean() */ |
460b9539 | 108 | static int clean_callback(const char *key, void *value, void *u) { |
109 | const struct cache_entry *c = value; | |
110 | const struct cache_type *type = u; | |
111 | ||
112 | if(!type || c->type == type) | |
113 | hash_remove(h, key); | |
114 | return 0; | |
115 | } | |
116 | ||
d7b6f0d1 | 117 | /** @brief Clean the cache |
118 | * @param type Pointer to type to clean | |
119 | * | |
120 | * Removes all entries of type @p type from the cache. | |
121 | */ | |
460b9539 | 122 | void cache_clean(const struct cache_type *type) { |
123 | if(h) | |
124 | hash_foreach(h, clean_callback, (void *)type); | |
125 | } | |
126 | ||
d7b6f0d1 | 127 | /** @brief Report cache size |
128 | * | |
129 | * Returns the number of objects in the cache | |
130 | */ | |
0b7c8909 | 131 | size_t cache_count(void) { |
132 | return h ? hash_count(h) : 0; | |
133 | } | |
134 | ||
460b9539 | 135 | /* |
136 | Local Variables: | |
137 | c-basic-offset:2 | |
138 | comment-column:40 | |
139 | fill-column:79 | |
140 | indent-tabs-mode:nil | |
141 | End: | |
142 | */ |