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

# User Rev Content
1 michael 1194 /* 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 michael 1209 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 michael 1194 };
26     static DBTableNode *tables = NULL;
27    
28     /* Currently active database module */
29     static DBModule *dbmodule = NULL;
30    
31    
32     /* Local routines: */
33 michael 1209 static int do_unload_module(const Module * module);
34 michael 1194
35     /*************************************************************************/
36     /*************************************************************************/
37    
38     /* Initialization/cleanup routines. */
39    
40 michael 1209 int
41     database_init(int ac, char **av)
42 michael 1194 {
43 michael 1209 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 michael 1194 }
50    
51     /************************************/
52    
53 michael 1209 void
54     database_cleanup(void)
55 michael 1194 {
56 michael 1209 remove_callback(NULL, "unload module", do_unload_module);
57 michael 1194 }
58    
59     /************************************/
60    
61     /* Check for tables that the module forgot to unload. */
62    
63 michael 1209 static int
64     do_unload_module(const Module * module)
65 michael 1194 {
66 michael 1209 DBTableNode *t, *t2;
67 michael 1194
68 michael 1209 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 michael 1194 }
76 michael 1209 }
77     return 0;
78 michael 1194 }
79    
80     /*************************************************************************/
81    
82     /* Register a new database table. Returns nonzero on success, zero on
83     * error.
84     */
85    
86 michael 1209 int
87     _register_dbtable(DBTable * table, const Module * caller)
88 michael 1194 {
89 michael 1209 DBTableNode *t;
90 michael 1194
91 michael 1209 /* 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 michael 1194
114 michael 1209 /* 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 michael 1194 }
123 michael 1209 }
124 michael 1194
125 michael 1209 /* 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 michael 1194
136 michael 1209 return 1;
137 michael 1194 }
138    
139     /*************************************************************************/
140    
141     /* Unregister a database table. Does nothing if the table was not
142     * registered in the first place.
143     */
144    
145 michael 1209 void
146     unregister_dbtable(DBTable * table)
147 michael 1194 {
148 michael 1209 DBTableNode *t;
149 michael 1194
150 michael 1209 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 michael 1194 }
164 michael 1209 }
165 michael 1194 }
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 michael 1209 int
176     save_all_dbtables(void)
177 michael 1194 {
178 michael 1209 DBTableNode *t;
179     int some_saved = 0;
180     int some_failed = 0;
181 michael 1194
182 michael 1209 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 michael 1194 }
195 michael 1209 else
196     {
197     log("save_all_dbtables(): Failed to save table `%s'", t->table->name);
198     some_failed = 1;
199 michael 1194 }
200 michael 1209 }
201     return some_saved - some_failed;
202 michael 1194 }
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 michael 1209 int
214     register_dbmodule(DBModule * module)
215 michael 1194 {
216 michael 1209 DBTableNode *t;
217 michael 1194
218 michael 1209 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 michael 1194
238 michael 1209 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 michael 1194 }
246    
247     /*************************************************************************/
248    
249     /* Unregister a database module. Does nothing if the module was not
250     * registered in the first place.
251     */
252    
253 michael 1209 void
254     unregister_dbmodule(DBModule * module)
255 michael 1194 {
256 michael 1209 if (!module)
257     {
258     log("BUG: unregister_dbmodule() with NULL module!");
259     return;
260     }
261     if (dbmodule == module)
262     dbmodule = NULL;
263 michael 1194 }
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 michael 1209 void
272     get_dbfield(const void *record, const DBField * field, void *buffer)
273 michael 1194 {
274 michael 1209 int size;
275 michael 1194
276 michael 1209 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 michael 1194 }
329    
330     /*************************************************************************/
331    
332     /* Store a value to a database field. */
333    
334 michael 1209 void
335     put_dbfield(void *record, const DBField * field, const void *value)
336 michael 1194 {
337 michael 1209 int size;
338 michael 1194
339 michael 1209 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 michael 1194 }
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     */