1 /*
2 * Copyright (c) 2010 William Pitcock <nenolod@atheme.org>
3 * Rights to this code are as documented in doc/LICENSE.
4 *
5 * Platform-agnostic database backend layer.
6 */
7
8 #include "atheme.h"
9
10 database_module_t *db_mod = NULL;
11 mowgli_patricia_t *db_types = NULL;
12
13 database_handle_t *
db_open(const char * filename,database_transaction_t txn)14 db_open(const char *filename, database_transaction_t txn)
15 {
16 return_val_if_fail(db_mod != NULL, NULL);
17 return_val_if_fail(db_mod->db_open != NULL, NULL);
18
19 return db_mod->db_open(filename, txn);
20 }
21
22 void
db_close(database_handle_t * db)23 db_close(database_handle_t *db)
24 {
25 return_if_fail(db_mod != NULL);
26 return_if_fail(db_mod->db_close != NULL);
27
28 return db_mod->db_close(db);
29 }
30
31 void
db_parse(database_handle_t * db)32 db_parse(database_handle_t *db)
33 {
34 return_if_fail(db_mod != NULL);
35 return_if_fail(db_mod->db_parse != NULL);
36
37 return db_mod->db_parse(db);
38 }
39
40 bool
db_read_next_row(database_handle_t * db)41 db_read_next_row(database_handle_t *db)
42 {
43 return_val_if_fail(db != NULL, NULL);
44 return_val_if_fail(db->vt != NULL, NULL);
45 return_val_if_fail(db->vt->read_next_row != NULL, NULL);
46
47 return db->vt->read_next_row(db);
48 }
49
50 const char *
db_read_word(database_handle_t * db)51 db_read_word(database_handle_t *db)
52 {
53 return_val_if_fail(db != NULL, NULL);
54 return_val_if_fail(db->vt != NULL, NULL);
55 return_val_if_fail(db->vt->read_word != NULL, NULL);
56
57 return db->vt->read_word(db);
58 }
59
60 const char *
db_read_str(database_handle_t * db)61 db_read_str(database_handle_t *db)
62 {
63 return_val_if_fail(db != NULL, NULL);
64 return_val_if_fail(db->vt != NULL, NULL);
65 return_val_if_fail(db->vt->read_str != NULL, NULL);
66
67 return db->vt->read_str(db);
68 }
69
70 bool
db_read_int(database_handle_t * db,int * r)71 db_read_int(database_handle_t *db, int *r)
72 {
73 return_val_if_fail(db != NULL, false);
74 return_val_if_fail(db->vt != NULL, false);
75 return_val_if_fail(db->vt->read_int != NULL, false);
76
77 return db->vt->read_int(db, r);
78 }
79
80 bool
db_read_uint(database_handle_t * db,unsigned int * r)81 db_read_uint(database_handle_t *db, unsigned int *r)
82 {
83 return_val_if_fail(db != NULL, false);
84 return_val_if_fail(db->vt != NULL, false);
85 return_val_if_fail(db->vt->read_uint != NULL, false);
86
87 return db->vt->read_uint(db, r);
88 }
89
90 bool
db_read_time(database_handle_t * db,time_t * r)91 db_read_time(database_handle_t *db, time_t *r)
92 {
93 return_val_if_fail(db != NULL, false);
94 return_val_if_fail(db->vt != NULL, false);
95 return_val_if_fail(db->vt->read_time != NULL, false);
96
97 return db->vt->read_time(db, r);
98 }
99
100 const char *
db_sread_word(database_handle_t * db)101 db_sread_word(database_handle_t *db)
102 {
103 const char *w = db_read_word(db);
104 if (!w)
105 {
106 slog(LG_ERROR, "db-sread-word: needed word at file %s line %d token %d", db->file, db->line, db->token);
107 slog(LG_ERROR, "db-sread-word: exiting to avoid data loss");
108 exit(EXIT_FAILURE);
109 }
110 return w;
111 }
112
113 const char *
db_sread_str(database_handle_t * db)114 db_sread_str(database_handle_t *db)
115 {
116 const char *w = db_read_str(db);
117 if (!w)
118 {
119 slog(LG_ERROR, "db-sread-multiword: needed multiword at file %s line %d token %d", db->file, db->line, db->token);
120 slog(LG_ERROR, "db-sread-multiword: exiting to avoid data loss");
121 exit(EXIT_FAILURE);
122 }
123 return w;
124 }
125
126 int
db_sread_int(database_handle_t * db)127 db_sread_int(database_handle_t *db)
128 {
129 int r;
130 bool ok = db_read_int(db, &r);
131
132 if (!ok)
133 {
134 slog(LG_ERROR, "db-read-int: needed int at file %s line %d token %d", db->file, db->line, db->token);
135 slog(LG_ERROR, "db-read-int: exiting to avoid data loss");
136 exit(EXIT_FAILURE);
137 }
138 return r;
139 }
140
141 unsigned int
db_sread_uint(database_handle_t * db)142 db_sread_uint(database_handle_t *db)
143 {
144 unsigned int r;
145 bool ok = db_read_uint(db, &r);
146
147 if (!ok)
148 {
149 slog(LG_ERROR, "db-read-uint: needed int at file %s line %d token %d", db->file, db->line, db->token);
150 slog(LG_ERROR, "db-read-uint: exiting to avoid data loss");
151 exit(EXIT_FAILURE);
152 }
153 return r;
154 }
155
156 time_t
db_sread_time(database_handle_t * db)157 db_sread_time(database_handle_t *db)
158 {
159 time_t r;
160 bool ok = db_read_time(db, &r);
161
162 if (!ok)
163 {
164 slog(LG_ERROR, "db-read-time: needed int at file %s line %d token %d", db->file, db->line, db->token);
165 slog(LG_ERROR, "db-read-time: exiting to avoid data loss");
166 exit(EXIT_FAILURE);
167 }
168 return r;
169 }
170
171 bool
db_start_row(database_handle_t * db,const char * type)172 db_start_row(database_handle_t *db, const char *type)
173 {
174 return_val_if_fail(db != NULL, false);
175 return_val_if_fail(db->vt != NULL, false);
176 return_val_if_fail(db->vt->start_row != NULL, false);
177
178 return db->vt->start_row(db, type);
179 }
180
181 bool
db_write_word(database_handle_t * db,const char * word)182 db_write_word(database_handle_t *db, const char *word)
183 {
184 return_val_if_fail(db != NULL, false);
185 return_val_if_fail(db->vt != NULL, false);
186 return_val_if_fail(db->vt->write_word != NULL, false);
187
188 return db->vt->write_word(db, word);
189 }
190
191 bool
db_write_str(database_handle_t * db,const char * str)192 db_write_str(database_handle_t *db, const char *str)
193 {
194 return_val_if_fail(db != NULL, false);
195 return_val_if_fail(db->vt != NULL, false);
196 return_val_if_fail(db->vt->write_str != NULL, false);
197
198 return db->vt->write_str(db, str);
199 }
200
201 bool
db_write_int(database_handle_t * db,int num)202 db_write_int(database_handle_t *db, int num)
203 {
204 return_val_if_fail(db != NULL, false);
205 return_val_if_fail(db->vt != NULL, false);
206 return_val_if_fail(db->vt->write_int != NULL, false);
207
208 return db->vt->write_int(db, num);
209 }
210
211 bool
db_write_uint(database_handle_t * db,unsigned int num)212 db_write_uint(database_handle_t *db, unsigned int num)
213 {
214 return_val_if_fail(db != NULL, false);
215 return_val_if_fail(db->vt != NULL, false);
216 return_val_if_fail(db->vt->write_uint != NULL, false);
217
218 return db->vt->write_uint(db, num);
219 }
220
221 bool
db_write_time(database_handle_t * db,time_t tm)222 db_write_time(database_handle_t *db, time_t tm)
223 {
224 return_val_if_fail(db != NULL, false);
225 return_val_if_fail(db->vt != NULL, false);
226 return_val_if_fail(db->vt->write_time != NULL, false);
227
228 return db->vt->write_time(db, tm);
229 }
230
231 bool
db_commit_row(database_handle_t * db)232 db_commit_row(database_handle_t *db)
233 {
234 return_val_if_fail(db != NULL, false);
235 return_val_if_fail(db->vt != NULL, false);
236 return_val_if_fail(db->vt->commit_row != NULL, false);
237
238 return db->vt->commit_row(db);
239 }
240
241 void
db_register_type_handler(const char * type,database_handler_f fun)242 db_register_type_handler(const char *type, database_handler_f fun)
243 {
244 return_if_fail(db_types != NULL);
245 return_if_fail(type != NULL);
246 return_if_fail(fun != NULL);
247
248 mowgli_patricia_add(db_types, type, fun);
249 }
250
251 void
db_unregister_type_handler(const char * type)252 db_unregister_type_handler(const char *type)
253 {
254 return_if_fail(db_types != NULL);
255 return_if_fail(type != NULL);
256
257 mowgli_patricia_delete(db_types, type);
258 }
259
260 void
db_process(database_handle_t * db,const char * type)261 db_process(database_handle_t *db, const char *type)
262 {
263 database_handler_f fun;
264
265 return_if_fail(db_types != NULL);
266 return_if_fail(db != NULL);
267 return_if_fail(type != NULL);
268
269 fun = mowgli_patricia_retrieve(db_types, type);
270
271 if (!fun)
272 {
273 fun = mowgli_patricia_retrieve(db_types, "???");
274 }
275
276 fun(db, type);
277 }
278
279 bool
db_write_format(database_handle_t * db,const char * fmt,...)280 db_write_format(database_handle_t *db, const char *fmt, ...)
281 {
282 va_list va;
283 char buf[BUFSIZE];
284
285 va_start(va, fmt);
286 vsnprintf(buf, BUFSIZE, fmt, va);
287 va_end(va);
288
289 return db_write_word(db, buf);
290 }
291
292 void
db_init(void)293 db_init(void)
294 {
295 db_types = mowgli_patricia_create(strcasecanon);
296
297 if (db_types == NULL)
298 {
299 slog(LG_ERROR, "db_init(): object allocator failure");
300 exit(EXIT_FAILURE);
301 }
302 }
303