1 /* $Id$ */
2
3 /*
4 * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19 #include <sys/types.h>
20 #include <sys/stat.h>
21
22 #include <fcntl.h>
23 #include <signal.h>
24 #include <string.h>
25 #ifndef _PUBLIC_
26 #define _PUBLIC_
27 #endif
28 #include <tdb.h>
29
30 #include "fdm.h"
31
32 int db_print_item(TDB_CONTEXT *, TDB_DATA, TDB_DATA, void *);
33 int db_expire_item(TDB_CONTEXT *, TDB_DATA, TDB_DATA, void *);
34 int db_clear_item(TDB_CONTEXT *, TDB_DATA, TDB_DATA, void *);
35
36 TDB_CONTEXT *
db_open(char * path)37 db_open(char *path)
38 {
39 TDB_CONTEXT *db;
40
41 #ifndef DB_UNSAFE
42 db = tdb_open(path, 0, 0, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR);
43 #else
44 db = tdb_open(path, 0, TDB_NOLOCK, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR);
45 #endif
46 return (db);
47 }
48
49 void
db_close(TDB_CONTEXT * db)50 db_close(TDB_CONTEXT *db)
51 {
52 tdb_close(db);
53 }
54
55 int
db_add(TDB_CONTEXT * db,char * k)56 db_add(TDB_CONTEXT *db, char *k)
57 {
58 TDB_DATA key, value;
59 struct cacheitem v;
60 uint64_t tim;
61
62 memset(&v, 0, sizeof v);
63 tim = time(NULL);
64 v.tim = htole64(tim);
65
66 key.dptr = k;
67 key.dsize = strlen(k);
68
69 value.dptr = (char *) &v;
70 value.dsize = sizeof v;
71
72 return (tdb_store(db, key, value, TDB_REPLACE));
73 }
74
75 int
db_remove(TDB_CONTEXT * db,char * k)76 db_remove(TDB_CONTEXT *db, char *k)
77 {
78 TDB_DATA key;
79
80 key.dptr = k;
81 key.dsize = strlen(k);
82
83 return (tdb_delete(db, key));
84 }
85
86 int
db_contains(TDB_CONTEXT * db,char * k)87 db_contains(TDB_CONTEXT *db, char *k)
88 {
89 TDB_DATA key;
90
91 key.dptr = k;
92 key.dsize = strlen(k);
93
94 return (tdb_exists(db, key));
95 }
96
97 int
db_size(TDB_CONTEXT * db)98 db_size(TDB_CONTEXT *db)
99 {
100 return (tdb_traverse(db, NULL, NULL));
101 }
102
103 int
db_print_item(unused TDB_CONTEXT * tdb,unused TDB_DATA key,TDB_DATA value,void * ptr)104 db_print_item(
105 unused TDB_CONTEXT *tdb, unused TDB_DATA key, TDB_DATA value, void *ptr)
106 {
107 void (*p)(const char *, ...) = ptr;
108 struct cacheitem v;
109 uint64_t tim;
110
111 if (value.dsize != sizeof v)
112 return (-1);
113 memcpy(&v, value.dptr, sizeof v);
114
115 tim = letoh64(v.tim);
116 p("%.*s %llu", key.dsize, key.dptr, (unsigned long long) tim);
117
118 return (0);
119 }
120
121 int
db_print(TDB_CONTEXT * db,void (* p)(const char *,...))122 db_print(TDB_CONTEXT *db, void (*p)(const char *, ...))
123 {
124 if (tdb_traverse(db, db_print_item, p) == -1)
125 return (-1);
126 return (0);
127 }
128
129 int
db_expire_item(TDB_CONTEXT * tdb,TDB_DATA key,TDB_DATA value,void * ptr)130 db_expire_item(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA value, void *ptr)
131 {
132 uint64_t *lim = ptr;
133 struct cacheitem v;
134
135 if (value.dsize != sizeof v)
136 return (-1);
137 memcpy(&v, value.dptr, sizeof v);
138
139 if (letoh64(v.tim) < *lim)
140 return (tdb_delete(tdb, key));
141 return (0);
142 }
143
144 int
db_expire(TDB_CONTEXT * db,uint64_t age)145 db_expire(TDB_CONTEXT *db, uint64_t age)
146 {
147 uint64_t lim;
148
149 lim = time(NULL);
150 if (lim <= age)
151 return (0);
152 lim -= age;
153
154 if (tdb_traverse(db, db_expire_item, &lim) == -1)
155 return (-1);
156 return (0);
157 }
158
159 int
db_clear_item(TDB_CONTEXT * tdb,TDB_DATA key,TDB_DATA value,unused void * ptr)160 db_clear_item(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA value, unused void *ptr)
161 {
162 if (value.dsize != sizeof (struct cacheitem))
163 return (-1);
164
165 return (tdb_delete(tdb, key));
166 }
167
168 int
db_clear(TDB_CONTEXT * db)169 db_clear(TDB_CONTEXT *db)
170 {
171 if (tdb_traverse(db, db_clear_item, NULL) == -1)
172 return (-1);
173 return (0);
174 }
175