1 /********************************************************************\
2 * qofbackend.c -- utility routines for the data backend *
3 * Copyright (C) 2000 Linas Vepstas <linas@linas.org> *
4 * Copyright (C) 2004-2008 Neil Williams <linux@codehelp.co.uk> *
5 * *
6 * This program is free software; you can redistribute it and/or *
7 * modify it under the terms of the GNU General Public License as *
8 * published by the Free Software Foundation; either version 2 of *
9 * the License, or (at your option) any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License*
17 * along with this program; if not, contact: *
18 * *
19 * Free Software Foundation Voice: +1-617-542-5942 *
20 * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
21 * Boston, MA 02110-1301, USA gnu@gnu.org *
22 * *
23 \********************************************************************/
24
25 #include "config.h"
26 #include <glib.h>
27 #include <gmodule.h>
28 #include "qof.h"
29 #include "qofbackend-p.h"
30
31 #define QOF_CONFIG_DESC "desc"
32 #define QOF_CONFIG_TIP "tip"
33
34 static QofLogModule log_module = QOF_MOD_BACKEND;
35
36 void
qof_backend_init(QofBackend * be)37 qof_backend_init (QofBackend * be)
38 {
39 be->session_begin = NULL;
40 be->session_end = NULL;
41 be->destroy_backend = NULL;
42 be->load = NULL;
43 be->begin = NULL;
44 be->commit = NULL;
45 be->rollback = NULL;
46 be->compile_query = NULL;
47 be->free_query = NULL;
48 be->run_query = NULL;
49 be->sync = NULL;
50 be->load_config = NULL;
51 be->events_pending = NULL;
52 be->process_events = NULL;
53 be->percentage = NULL;
54 be->backend_configuration = kvp_frame_new ();
55 }
56
57 void
qof_backend_run_begin(QofBackend * be,QofInstance * inst)58 qof_backend_run_begin (QofBackend * be, QofInstance * inst)
59 {
60 if (!be || !inst)
61 return;
62 if (!be->begin)
63 return;
64 (be->begin) (be, inst);
65 }
66
67 gboolean
qof_backend_begin_exists(QofBackend * be)68 qof_backend_begin_exists (QofBackend * be)
69 {
70 if (be->begin)
71 return TRUE;
72 else
73 return FALSE;
74 }
75
76 void
qof_backend_run_commit(QofBackend * be,QofInstance * inst)77 qof_backend_run_commit (QofBackend * be, QofInstance * inst)
78 {
79 if (!be || !inst)
80 return;
81 if (!be->commit)
82 return;
83 (be->commit) (be, inst);
84 }
85
86 /* =========== Backend Configuration ================ */
87
88 void
qof_backend_prepare_frame(QofBackend * be)89 qof_backend_prepare_frame (QofBackend * be)
90 {
91 g_return_if_fail (be);
92 if (!kvp_frame_is_empty (be->backend_configuration))
93 {
94 kvp_frame_delete (be->backend_configuration);
95 be->backend_configuration = kvp_frame_new ();
96 }
97 be->config_count = 0;
98 }
99
100 void
qof_backend_prepare_option(QofBackend * be,QofBackendOption * option)101 qof_backend_prepare_option (QofBackend * be,
102 QofBackendOption * option)
103 {
104 KvpValue *value;
105 gchar *temp;
106 gint count;
107
108 g_return_if_fail (be || option);
109 count = be->config_count;
110 count++;
111 value = NULL;
112 switch (option->type)
113 {
114 case KVP_TYPE_GINT64:
115 {
116 value = kvp_value_new_gint64 (*(gint64 *) option->value);
117 break;
118 }
119 case KVP_TYPE_DOUBLE:
120 {
121 value = kvp_value_new_double (*(gdouble *) option->value);
122 break;
123 }
124 case KVP_TYPE_NUMERIC:
125 {
126 value = kvp_value_new_numeric (*(QofNumeric *) option->value);
127 break;
128 }
129 case KVP_TYPE_STRING:
130 {
131 value = kvp_value_new_string ((const gchar *) option->value);
132 break;
133 }
134 case KVP_TYPE_BOOLEAN:
135 {
136 break;
137 }
138 case KVP_TYPE_GUID:
139 {
140 break;
141 } /* unsupported */
142 case KVP_TYPE_TIME :
143 {
144 value = kvp_value_new_time ((QofTime*) option->value);
145 break;
146 }
147 case KVP_TYPE_BINARY:
148 {
149 break;
150 } /* unsupported */
151 case KVP_TYPE_GLIST:
152 {
153 break;
154 } /* unsupported */
155 case KVP_TYPE_FRAME:
156 {
157 break;
158 } /* unsupported */
159 }
160 if (value)
161 {
162 temp = g_strdup_printf ("/%s", option->option_name);
163 kvp_frame_set_value (be->backend_configuration, temp, value);
164 g_free (temp);
165 temp =
166 g_strdup_printf ("/%s/%s", QOF_CONFIG_DESC,
167 option->option_name);
168 kvp_frame_set_string (be->backend_configuration, temp,
169 option->description);
170 g_free (temp);
171 temp =
172 g_strdup_printf ("/%s/%s", QOF_CONFIG_TIP,
173 option->option_name);
174 kvp_frame_set_string (be->backend_configuration, temp,
175 option->tooltip);
176 g_free (temp);
177 /* only increment the counter if successful */
178 be->config_count = count;
179 }
180 }
181
182 KvpFrame *
qof_backend_complete_frame(QofBackend * be)183 qof_backend_complete_frame (QofBackend * be)
184 {
185 g_return_val_if_fail (be, NULL);
186 be->config_count = 0;
187 return be->backend_configuration;
188 }
189
190 struct config_iterate
191 {
192 QofBackendOptionCB fcn;
193 gpointer data;
194 gint count;
195 KvpFrame *recursive;
196 };
197
198 /* Set the option with the default KvpValue,
199 manipulate the option in the supplied callback routine
200 then set the value of the option into the KvpValue
201 in the configuration frame. */
202 static void
config_foreach_cb(const gchar * key,KvpValue * value,gpointer data)203 config_foreach_cb (const gchar * key, KvpValue * value, gpointer data)
204 {
205 QofBackendOption option;
206 gint64 int64;
207 gdouble db;
208 QofNumeric num;
209 gchar *parent;
210 struct config_iterate *helper;
211
212 g_return_if_fail (key || value || data);
213 helper = (struct config_iterate *) data;
214 if (!helper->recursive)
215 {
216 PERR (" no parent frame");
217 return;
218 }
219 // skip the presets.
220 if (0 == safe_strcmp (key, QOF_CONFIG_DESC))
221 {
222 return;
223 }
224 if (0 == safe_strcmp (key, QOF_CONFIG_TIP))
225 {
226 return;
227 }
228 ENTER (" key=%s", key);
229 option.option_name = key;
230 option.type = kvp_value_get_type (value);
231 if (!option.type)
232 return;
233 switch (option.type)
234 { /* set the KvpFrame value into the option */
235 case KVP_TYPE_GINT64:
236 {
237 int64 = kvp_value_get_gint64 (value);
238 option.value = (gpointer) & int64;
239 break;
240 }
241 case KVP_TYPE_DOUBLE:
242 {
243 db = kvp_value_get_double (value);
244 option.value = (gpointer) & db;
245 break;
246 }
247 case KVP_TYPE_NUMERIC:
248 {
249 num = kvp_value_get_numeric (value);
250 option.value = (gpointer) & num;
251 break;
252 }
253 case KVP_TYPE_STRING:
254 {
255 option.value = (gpointer) kvp_value_get_string (value);
256 break;
257 }
258 case KVP_TYPE_TIME :
259 {
260 option.value = (gpointer) kvp_value_get_time (value);
261 }
262 case KVP_TYPE_BOOLEAN :
263 {
264 break;
265 }
266 case KVP_TYPE_GUID:
267 {
268 break;
269 } /* unsupported */
270 case KVP_TYPE_BINARY:
271 {
272 break;
273 } /* unsupported */
274 case KVP_TYPE_GLIST:
275 {
276 break;
277 } /* unsupported */
278 case KVP_TYPE_FRAME:
279 {
280 break;
281 } /* unsupported */
282 }
283 parent = g_strdup_printf ("/%s/%s", QOF_CONFIG_DESC, key);
284 option.description = kvp_frame_get_string (helper->recursive, parent);
285 g_free (parent);
286 parent = g_strdup_printf ("/%s/%s", QOF_CONFIG_TIP, key);
287 option.tooltip = kvp_frame_get_string (helper->recursive, parent);
288 g_free (parent);
289 helper->count++;
290 /* manipulate the option */
291 helper->fcn (&option, helper->data);
292 switch (option.type)
293 { /* set the option value into the KvpFrame */
294 case KVP_TYPE_GINT64:
295 {
296 kvp_frame_set_gint64 (helper->recursive, key,
297 (*(gint64 *) option.value));
298 break;
299 }
300 case KVP_TYPE_DOUBLE:
301 {
302 kvp_frame_set_double (helper->recursive, key,
303 (*(gdouble *) option.value));
304 break;
305 }
306 case KVP_TYPE_NUMERIC:
307 {
308 kvp_frame_set_numeric (helper->recursive, key,
309 (*(QofNumeric *) option.value));
310 break;
311 }
312 case KVP_TYPE_STRING:
313 {
314 kvp_frame_set_string (helper->recursive, key,
315 (gchar *) option.value);
316 break;
317 }
318 case KVP_TYPE_TIME :
319 {
320 kvp_frame_set_time (helper->recursive, key,
321 (QofTime*) option.value);
322 break;
323 }
324 case KVP_TYPE_BOOLEAN :
325 {
326 break;
327 }
328 case KVP_TYPE_GUID:
329 {
330 break;
331 } /* unsupported */
332 case KVP_TYPE_BINARY:
333 {
334 break;
335 } /* unsupported */
336 case KVP_TYPE_GLIST:
337 {
338 break;
339 } /* unsupported */
340 case KVP_TYPE_FRAME:
341 {
342 break;
343 } /* unsupported */
344 }
345 LEAVE (" ");
346 }
347
348 void
qof_backend_option_foreach(KvpFrame * config,QofBackendOptionCB cb,gpointer data)349 qof_backend_option_foreach (KvpFrame * config,
350 QofBackendOptionCB cb, gpointer data)
351 {
352 struct config_iterate helper;
353
354 if (!config || !cb)
355 return;
356 ENTER (" ");
357 helper.fcn = cb;
358 helper.count = 1;
359 helper.data = data;
360 helper.recursive = config;
361 kvp_frame_for_each_slot (config, config_foreach_cb, &helper);
362 LEAVE (" ");
363 }
364
365 void
qof_backend_load_config(QofBackend * be,KvpFrame * config)366 qof_backend_load_config (QofBackend * be, KvpFrame * config)
367 {
368 if (!be || !config)
369 return;
370 if (!be->load_config)
371 return;
372 (be->load_config) (be, config);
373 }
374
375 KvpFrame *
qof_backend_get_config(QofBackend * be)376 qof_backend_get_config (QofBackend * be)
377 {
378 if (!be)
379 return NULL;
380 if (!be->get_config)
381 return NULL;
382 return (be->get_config) (be);
383 }
384
385 gboolean
qof_backend_commit_exists(QofBackend * be)386 qof_backend_commit_exists (QofBackend * be)
387 {
388 if (!be)
389 return FALSE;
390 if (be->commit)
391 return TRUE;
392 else
393 return FALSE;
394 }
395
396 gboolean
qof_load_backend_library(const gchar * directory,const gchar * filename,const gchar * init_fcn)397 qof_load_backend_library (const gchar * directory,
398 const gchar * filename, const gchar * init_fcn)
399 {
400 gchar *fullpath;
401 typedef void (*backend_init) (void);
402 GModule *backend;
403 backend_init gmod_init;
404 gpointer g;
405
406 g_return_val_if_fail (g_module_supported (), FALSE);
407 fullpath = g_module_build_path (directory, filename);
408 backend = g_module_open (fullpath, G_MODULE_BIND_LAZY);
409 if (!backend)
410 {
411 PERR (" No backend found. %s", g_module_error ());
412 return FALSE;
413 }
414 g = &gmod_init;
415 if (!g_module_symbol (backend, init_fcn, g))
416 {
417 PERR (" Backend did not initialise. %s", g_module_error ());
418 return FALSE;
419 }
420 g_module_make_resident (backend);
421 gmod_init ();
422 g_free (fullpath);
423 return TRUE;
424 }
425
426 /************************* END OF FILE ********************************/
427