ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/hybrid-ircservices-1/databases.c
Revision: 1209
Committed: Thu Aug 25 19:05:49 2011 UTC (14 years, 11 months ago) by michael
Content type: text/x-csrc
File size: 8879 byte(s)
Log Message:
- run everything thru indent
  "-bli0 -di1 -npcs -nut -cdw -bls -nbbo -bap"

File Contents

# Content
1 /* Database core routines.
2 *
3 * IRC Services is copyright (c) 1996-2009 Andrew Church.
4 * E-mail: <achurch@achurch.org>
5 * Parts written by Andrew Kempe and others.
6 * This program is free but copyrighted software; see the file GPL.txt for
7 * details.
8 */
9
10 #include "services.h"
11 #include "databases.h"
12 #include "encrypt.h"
13 #include "modules.h"
14
15 /*************************************************************************/
16
17 /* List of registered tables */
18 typedef struct dbtablenode_ DBTableNode;
19 struct dbtablenode_
20 {
21 DBTableNode *next, *prev;
22 DBTable *table;
23 const Module *owner; /* Which module registered this table? */
24 int loaded; /* Has this table been loaded? */
25 };
26 static DBTableNode *tables = NULL;
27
28 /* Currently active database module */
29 static DBModule *dbmodule = NULL;
30
31
32 /* Local routines: */
33 static int do_unload_module(const Module * module);
34
35 /*************************************************************************/
36 /*************************************************************************/
37
38 /* Initialization/cleanup routines. */
39
40 int
41 database_init(int ac, char **av)
42 {
43 if (!add_callback(NULL, "unload module", do_unload_module))
44 {
45 log("database_init: add_callback() failed");
46 return 0;
47 }
48 return 1;
49 }
50
51 /************************************/
52
53 void
54 database_cleanup(void)
55 {
56 remove_callback(NULL, "unload module", do_unload_module);
57 }
58
59 /************************************/
60
61 /* Check for tables that the module forgot to unload. */
62
63 static int
64 do_unload_module(const Module * module)
65 {
66 DBTableNode *t, *t2;
67
68 LIST_FOREACH_SAFE(t, tables, t2)
69 {
70 if (t->owner == module)
71 {
72 log("database: Module `%s' forgot to unregister table `%s'",
73 get_module_name(module), t->table->name);
74 unregister_dbtable(t->table);
75 }
76 }
77 return 0;
78 }
79
80 /*************************************************************************/
81
82 /* Register a new database table. Returns nonzero on success, zero on
83 * error.
84 */
85
86 int
87 _register_dbtable(DBTable * table, const Module * caller)
88 {
89 DBTableNode *t;
90
91 /* Sanity checks on parameter */
92 if (!table)
93 {
94 log("BUG: register_dbtable() with NULL table!");
95 return 0;
96 }
97 if (!table->name)
98 {
99 log("BUG: register_dbtable(): table->name is NULL!");
100 return 0;
101 }
102 if (!table->fields || !table->newrec || !table->freerec
103 || !table->insert || !table->first || !table->next)
104 {
105 log("BUG: register_dbtable(%s): table->%s is NULL!", table->name,
106 !table->fields ? "fields" :
107 !table->newrec ? "newrec" :
108 !table->freerec ? "freerec" :
109 !table->insert ? "insert" :
110 !table->first ? "first" : !table->next ? "next" : "???");
111 return 0;
112 }
113
114 /* Sanity check: make sure it's not already registered */
115 LIST_FOREACH(t, tables)
116 {
117 if (t->table == table)
118 {
119 log("BUG: register_dbtable(%s): table already registered!",
120 table->name);
121 break;
122 }
123 }
124
125 /* Allocate and append to list (make sure to preserve order, since
126 * later tables may depend on earlier ones); if a database module is
127 * available, load the table ammediately*/
128 t = smalloc(sizeof(*t));
129 t->table = table;
130 t->owner = caller;
131 t->loaded = 0;
132 LIST_APPEND(t, tables);
133 if (dbmodule)
134 t->loaded = (*dbmodule->load_table) (t->table);
135
136 return 1;
137 }
138
139 /*************************************************************************/
140
141 /* Unregister a database table. Does nothing if the table was not
142 * registered in the first place.
143 */
144
145 void
146 unregister_dbtable(DBTable * table)
147 {
148 DBTableNode *t;
149
150 if (!table)
151 {
152 log("BUG: unregister_dbtable() with NULL table!");
153 return;
154 }
155 /* Sanity check: make sure it was registered first */
156 LIST_FOREACH(t, tables)
157 {
158 if (t->table == table)
159 {
160 LIST_REMOVE(t, tables);
161 free(t);
162 break;
163 }
164 }
165 }
166
167 /*************************************************************************/
168
169 /* Save all registered database tables to permanent storage. Returns 1 if
170 * all tables were successfully saved or no tables are registered, 0 if
171 * some tables were successfully saved (but some were not), or -1 if no
172 * tables were successfully saved.
173 */
174
175 int
176 save_all_dbtables(void)
177 {
178 DBTableNode *t;
179 int some_saved = 0;
180 int some_failed = 0;
181
182 if (!tables)
183 return 1;
184 if (!dbmodule)
185 {
186 log("save_all_dbtables(): No database module registered!");
187 return -1;
188 }
189 LIST_FOREACH(t, tables)
190 {
191 if ((*dbmodule->save_table) (t->table))
192 {
193 some_saved = 1;
194 }
195 else
196 {
197 log("save_all_dbtables(): Failed to save table `%s'", t->table->name);
198 some_failed = 1;
199 }
200 }
201 return some_saved - some_failed;
202 }
203
204 /*************************************************************************/
205 /*************************************************************************/
206
207 /* Register a database module. Returns nonzero on success, zero on error.
208 * On success, all registered tables which have not already been loaded
209 * will be loaded from permanent storage. Only one database module can be
210 * registered.
211 */
212
213 int
214 register_dbmodule(DBModule * module)
215 {
216 DBTableNode *t;
217
218 if (!module)
219 {
220 log("BUG: register_dbmodule() with NULL module!");
221 return 0;
222 }
223 if (!module->load_table || !module->save_table)
224 {
225 log("BUG: register_dbmodule(): module->%s is NULL!",
226 !module->load_table ? "load_table" : "save_table");
227 return 0;
228 }
229 if (dbmodule)
230 {
231 if (module == dbmodule)
232 log("BUG: register_dbmodule(): attempt to re-register module!");
233 else
234 log("register_dbmodule(): a database module is already registered");
235 return 0;
236 }
237
238 dbmodule = module;
239 LIST_FOREACH(t, tables)
240 {
241 if (!t->loaded)
242 t->loaded = (*dbmodule->load_table) (t->table);
243 }
244 return 1;
245 }
246
247 /*************************************************************************/
248
249 /* Unregister a database module. Does nothing if the module was not
250 * registered in the first place.
251 */
252
253 void
254 unregister_dbmodule(DBModule * module)
255 {
256 if (!module)
257 {
258 log("BUG: unregister_dbmodule() with NULL module!");
259 return;
260 }
261 if (dbmodule == module)
262 dbmodule = NULL;
263 }
264
265 /*************************************************************************/
266
267 /* Read a value from a database field. The value buffer is assumed to be
268 * large enough to hold the retrieved value.
269 */
270
271 void
272 get_dbfield(const void *record, const DBField * field, void *buffer)
273 {
274 int size;
275
276 if (!record || !field || !buffer)
277 {
278 log("BUG: get_dbfield(): %s is NULL!",
279 !record ? "record" : !field ? "field" : "buffer");
280 return;
281 }
282 if (field->get)
283 {
284 (*field->get) (record, buffer);
285 return;
286 }
287 switch (field->type)
288 {
289 case DBTYPE_INT8:
290 size = 1;
291 break;
292 case DBTYPE_UINT8:
293 size = 1;
294 break;
295 case DBTYPE_INT16:
296 size = 2;
297 break;
298 case DBTYPE_UINT16:
299 size = 2;
300 break;
301 case DBTYPE_INT32:
302 size = 4;
303 break;
304 case DBTYPE_UINT32:
305 size = 4;
306 break;
307 case DBTYPE_TIME:
308 size = sizeof(time_t);
309 break;
310 case DBTYPE_STRING:
311 size = sizeof(char *);
312 break;
313 case DBTYPE_BUFFER:
314 size = field->length;
315 break;
316 case DBTYPE_PASSWORD:
317 size = sizeof(Password);
318 break;
319 default:
320 log("BUG: bad field type %d in get_dbfield()", field->type);
321 return;
322 }
323 if (!size)
324 {
325 return;
326 }
327 memcpy(buffer, (const uint8 *) record + field->offset, size);
328 }
329
330 /*************************************************************************/
331
332 /* Store a value to a database field. */
333
334 void
335 put_dbfield(void *record, const DBField * field, const void *value)
336 {
337 int size;
338
339 if (!record || !field || !value)
340 {
341 log("BUG: get_dbfield(): %s is NULL!",
342 !record ? "record" : !field ? "field" : "value");
343 return;
344 }
345 if (field->put)
346 {
347 (*field->put) (record, value);
348 return;
349 }
350 switch (field->type)
351 {
352 case DBTYPE_INT8:
353 size = 1;
354 break;
355 case DBTYPE_UINT8:
356 size = 1;
357 break;
358 case DBTYPE_INT16:
359 size = 2;
360 break;
361 case DBTYPE_UINT16:
362 size = 2;
363 break;
364 case DBTYPE_INT32:
365 size = 4;
366 break;
367 case DBTYPE_UINT32:
368 size = 4;
369 break;
370 case DBTYPE_TIME:
371 size = sizeof(time_t);
372 break;
373 case DBTYPE_STRING:
374 size = sizeof(char *);
375 break;
376 case DBTYPE_BUFFER:
377 size = field->length;
378 break;
379 case DBTYPE_PASSWORD:
380 size = sizeof(Password);
381 break;
382 default:
383 log("BUG: bad field type %d in get_dbfield()", field->type);
384 return;
385 }
386 if (!size)
387 {
388 return;
389 }
390 memcpy((uint8 *) record + field->offset, value, size);
391 }
392
393 /*************************************************************************/
394
395 /*
396 * Local variables:
397 * c-file-style: "stroustrup"
398 * c-file-offsets: ((case-label . *) (statement-case-intro . *))
399 * indent-tabs-mode: nil
400 * End:
401 *
402 * vim: expandtab shiftwidth=4:
403 */