squash before commiting to master. this is the initial revert to v2
[pwmd.git] / src / cache.c
bloba4546e5aab41c93a7be1d7d3483d05a1e3471c44
1 /* vim:tw=78:ts=8:sw=4:set ft=c: */
2 /*
3 Copyright (C) 2006-2009 Ben Kibbey <bjk@luxsci.net>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
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.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02110-1301 USA
19 #include <stdio.h>
20 #include <unistd.h>
21 #include <glib.h>
22 #include <string.h>
23 #include <sys/mman.h>
24 #include <errno.h>
26 #ifdef HAVE_CONFIG_H
27 #include <config.h>
28 #endif
30 #include "cache.h"
31 #include "status.h"
32 #include "mem.h"
34 void log_write(const gchar *fmt, ...);
36 static gboolean valid_key(const guchar *key, gsize len)
38 gint b;
40 for (b = 0; b < len; b++) {
41 if (key[b])
42 return TRUE;
45 return FALSE;
48 static file_cache_t *get_entry(const guchar *md5file)
50 gint t = g_slist_length(key_cache);
51 gint i;
53 if (!md5file)
54 return NULL;
56 for (i = 0; i < t; i++) {
57 file_cache_t *p = g_slist_nth_data(key_cache, i);
59 if (!memcmp(p->filename, md5file, sizeof(p->filename)))
60 return p;
63 return NULL;
66 gboolean cache_get_mutex(const guchar *md5file, pth_mutex_t **result)
68 file_cache_t *p = get_entry(md5file);
70 if (p)
71 *result = p->mutex;
73 return p ? TRUE : FALSE;
76 gint cache_file_count()
78 gint t = g_slist_length(key_cache);
79 gint i;
80 gint n = 0;
82 for (i = 0; i < t; i++) {
83 file_cache_t *p = g_slist_nth_data(key_cache, i);
85 if (valid_key(p->key, sizeof(p->key)) == TRUE)
86 n++;
89 return n;
92 void cache_adjust_timer()
94 gint t = g_slist_length(key_cache);
95 gint i;
97 for (i = 0; i < t; i++) {
98 file_cache_t *p = g_slist_nth_data(key_cache, i);
100 if (p->reset >= 0) {
101 if (p->timeout > 0)
102 p->timeout--;
104 if (p->timeout == 0) {
105 if (valid_key(p->key, sizeof(p->key)) == TRUE) {
106 memset(&p->key, 0, sizeof(p->key));
107 send_status_all(STATUS_CACHE);
110 p->timeout = -1;
116 gboolean cache_add_file(const guchar *md5file, const guchar *shakey)
118 file_cache_t *p = g_malloc0(sizeof(file_cache_t));
119 GSList *new;
121 if (!p) {
122 log_write("%s(%i): %s", __FUNCTION__, __LINE__, strerror(ENOMEM));
123 return FALSE;
126 p->mutex = g_malloc(sizeof(pth_mutex_t));
128 if (!p->mutex) {
129 log_write("%s(%i): %s", __FUNCTION__, __LINE__, strerror(ENOMEM));
130 g_free(p);
131 return FALSE;
134 pth_mutex_init(p->mutex);
135 memcpy(p->filename, md5file, sizeof(p->filename));
137 if (shakey)
138 memcpy(p->key, shakey, sizeof(p->key));
140 p->reset = p->timeout = -2;
142 if (mlock(p, sysconf(_SC_PAGESIZE)))
143 log_write("mlock(): %s", strerror(errno));
145 new = g_slist_append(key_cache, p);
147 if (!new) {
148 log_write("%s(%i): %s", __FUNCTION__, __LINE__, strerror(ENOMEM));
149 g_free(p->mutex);
150 memset(p, 0, sizeof(file_cache_t));
151 g_free(p);
152 return FALSE;
155 key_cache = new;
156 return TRUE;
159 static void free_entry(file_cache_t *p)
161 if (!p)
162 return;
164 if (p->mutex)
165 g_free(p->mutex);
167 memset(p, 0, sizeof(file_cache_t));
168 munlock(p, sysconf(_SC_PAGESIZE));
169 key_cache = g_slist_remove(key_cache, p);
170 g_free(p);
173 void cache_free()
175 for (;;) {
176 file_cache_t *p = g_slist_nth_data(key_cache, 0);
178 if (!p)
179 break;
181 free_entry(p);
185 static void reset_entry(file_cache_t *p)
187 if (p && !p->refcount)
188 free_entry(p);
189 else if (p)
190 memset(p->key, 0, sizeof(p->key));
193 gboolean cache_clear(const guchar *md5file, gint which)
195 file_cache_t *p = md5file ? get_entry(md5file) : NULL;
197 if (which == 1) {
198 if (!p)
199 return FALSE;
201 reset_entry(p);
202 send_status_all(STATUS_CACHE);
203 return TRUE;
206 do {
207 file_cache_t *p = g_slist_nth_data(key_cache, 0);
209 if (!p)
210 break;
212 reset_entry(p);
213 } while (cache_file_count());
215 send_status_all(STATUS_CACHE);
216 return TRUE;
219 gboolean cache_iscached(const guchar *md5file)
221 file_cache_t *p = get_entry(md5file);
223 return p ? valid_key(p->key, sizeof(p->key)) : FALSE;
226 gboolean cache_reset_timeout(const guchar *md5file, glong timeout)
228 file_cache_t *p = get_entry(md5file);
230 if (!p)
231 return FALSE;
233 if (p->reset == -2)
234 return cache_set_timeout(md5file, timeout);
236 return cache_set_timeout(md5file, p->reset);
239 gboolean cache_set_timeout(const guchar *md5file, glong timeout)
241 file_cache_t *p = get_entry(md5file);
243 if (!p)
244 return FALSE;
246 if (timeout == -2)
247 p->timeout = p->reset;
248 else
249 p->reset = p->timeout = timeout;
251 return TRUE;
254 gboolean cache_update_key(const guchar *md5file, const guchar *shakey)
256 file_cache_t *p = get_entry(md5file);
258 if (!p)
259 return cache_add_file(md5file, shakey);
261 if (p->reset)
262 memcpy(p->key, shakey, sizeof(p->key));
264 return TRUE;
267 gboolean cache_get_key(const guchar *md5file, guchar *shakey)
269 file_cache_t *p = get_entry(md5file);
271 if (!p || valid_key(p->key, sizeof(p->key)) == FALSE)
272 return FALSE;
274 memcpy(shakey, p->key, sizeof(p->key));
275 return TRUE;
278 gboolean cache_has_file(const guchar *md5file)
280 file_cache_t *p = get_entry(md5file);
282 return p ? TRUE : FALSE;
285 gboolean cache_decr_refcount(const guchar *md5file)
287 file_cache_t *p = get_entry(md5file);
289 if (!p)
290 return FALSE;
292 p->refcount--;
294 if (p->refcount < 0)
295 p->refcount = 0;
297 return TRUE;
300 gboolean cache_incr_refcount(const guchar *md5file)
302 file_cache_t *p = get_entry(md5file);
304 if (!p)
305 return FALSE;
307 p->refcount++;
308 return TRUE;