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