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