00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "config.h"
00026 #include <stdio.h>
00027 #include <stdlib.h>
00028 #include <stdarg.h>
00029 #include <regex.h>
00030 #include <glib.h>
00031 #include <gmodule.h>
00032 #include <errno.h>
00033 #include "qof.h"
00034 #include "qofbackend-p.h"
00035
00036 static QofLogModule log_module = QOF_MOD_BACKEND;
00037
00038 #define QOF_CONFIG_DESC "desc"
00039 #define QOF_CONFIG_TIP "tip"
00040
00041
00042
00043
00044
00045 void
00046 qof_backend_set_error (QofBackend * be, QofBackendError err)
00047 {
00048 if (!be)
00049 return;
00050
00051
00052 if (ERR_BACKEND_NO_ERR != be->last_err)
00053 return;
00054 be->last_err = err;
00055 }
00056
00057 QofBackendError
00058 qof_backend_get_error (QofBackend * be)
00059 {
00060 QofBackendError err;
00061 if (!be)
00062 return ERR_BACKEND_NO_BACKEND;
00063
00064
00065 err = be->last_err;
00066 be->last_err = ERR_BACKEND_NO_ERR;
00067 return err;
00068 }
00069
00070 void
00071 qof_backend_set_message (QofBackend * be, const gchar * format, ...)
00072 {
00073 va_list args;
00074 gchar *buffer;
00075
00076 if (!be)
00077 return;
00078
00079
00080 if (be->error_msg)
00081 g_free (be->error_msg);
00082
00083 if (!format)
00084 {
00085 be->error_msg = NULL;
00086 return;
00087 }
00088
00089 va_start (args, format);
00090 buffer = (gchar *) g_strdup_vprintf (format, args);
00091 va_end (args);
00092
00093 be->error_msg = buffer;
00094 }
00095
00096 gchar *
00097 qof_backend_get_message (QofBackend * be)
00098 {
00099 gchar *msg;
00100
00101 if (!be)
00102 return g_strdup ("ERR_BACKEND_NO_BACKEND");
00103 if (!be->error_msg)
00104 return NULL;
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114 msg = be->error_msg;
00115 be->error_msg = NULL;
00116 return msg;
00117 }
00118
00119
00120
00121 void
00122 qof_backend_init (QofBackend * be)
00123 {
00124 be->session_begin = NULL;
00125 be->session_end = NULL;
00126 be->destroy_backend = NULL;
00127 be->load = NULL;
00128 be->begin = NULL;
00129 be->commit = NULL;
00130 be->rollback = NULL;
00131 be->compile_query = NULL;
00132 be->free_query = NULL;
00133 be->run_query = NULL;
00134 be->sync = NULL;
00135 be->load_config = NULL;
00136 be->events_pending = NULL;
00137 be->process_events = NULL;
00138 be->last_err = ERR_BACKEND_NO_ERR;
00139 if (be->error_msg)
00140 g_free (be->error_msg);
00141 be->error_msg = NULL;
00142 be->percentage = NULL;
00143 be->backend_configuration = kvp_frame_new ();
00144 #ifndef QOF_DISABLE_DEPRECATED
00145
00146 be->price_lookup = NULL;
00148 be->export = NULL;
00149 #endif
00150 }
00151
00152 void
00153 qof_backend_run_begin (QofBackend * be, QofInstance * inst)
00154 {
00155 if (!be || !inst)
00156 return;
00157 if (!be->begin)
00158 return;
00159 (be->begin) (be, inst);
00160 }
00161
00162 gboolean
00163 qof_backend_begin_exists (QofBackend * be)
00164 {
00165 if (be->begin)
00166 return TRUE;
00167 else
00168 return FALSE;
00169 }
00170
00171 void
00172 qof_backend_run_commit (QofBackend * be, QofInstance * inst)
00173 {
00174 if (!be || !inst)
00175 return;
00176 if (!be->commit)
00177 return;
00178 (be->commit) (be, inst);
00179 }
00180
00181
00182
00183 void
00184 qof_backend_prepare_frame (QofBackend * be)
00185 {
00186 g_return_if_fail (be);
00187 if (!kvp_frame_is_empty (be->backend_configuration))
00188 {
00189 kvp_frame_delete (be->backend_configuration);
00190 be->backend_configuration = kvp_frame_new ();
00191 }
00192 be->config_count = 0;
00193 }
00194
00195 void
00196 qof_backend_prepare_option (QofBackend * be,
00197 QofBackendOption * option)
00198 {
00199 KvpValue *value;
00200 gchar *temp;
00201 gint count;
00202
00203 g_return_if_fail (be || option);
00204 count = be->config_count;
00205 count++;
00206 value = NULL;
00207 switch (option->type)
00208 {
00209 case KVP_TYPE_GINT64:
00210 {
00211 value = kvp_value_new_gint64 (*(gint64 *) option->value);
00212 break;
00213 }
00214 case KVP_TYPE_DOUBLE:
00215 {
00216 value = kvp_value_new_double (*(gdouble *) option->value);
00217 break;
00218 }
00219 case KVP_TYPE_NUMERIC:
00220 {
00221 value = kvp_value_new_numeric (*(QofNumeric *) option->value);
00222 break;
00223 }
00224 case KVP_TYPE_STRING:
00225 {
00226 value = kvp_value_new_string ((const gchar *) option->value);
00227 break;
00228 }
00229 case KVP_TYPE_GUID:
00230 {
00231 break;
00232 }
00233 case KVP_TYPE_TIME :
00234 {
00235 value = kvp_value_new_time ((QofTime*) option->value);
00236 break;
00237 }
00238 #ifndef QOF_DISABLE_DEPRECATED
00239 case KVP_TYPE_TIMESPEC:
00240 {
00241 value = kvp_value_new_timespec (*(Timespec *) option->value);
00242 break;
00243 }
00244 #endif
00245 case KVP_TYPE_BINARY:
00246 {
00247 break;
00248 }
00249 case KVP_TYPE_GLIST:
00250 {
00251 break;
00252 }
00253 case KVP_TYPE_FRAME:
00254 {
00255 break;
00256 }
00257 }
00258 if (value)
00259 {
00260 temp = g_strdup_printf ("/%s", option->option_name);
00261 kvp_frame_set_value (be->backend_configuration, temp, value);
00262 g_free (temp);
00263 temp =
00264 g_strdup_printf ("/%s/%s", QOF_CONFIG_DESC,
00265 option->option_name);
00266 kvp_frame_set_string (be->backend_configuration, temp,
00267 option->description);
00268 g_free (temp);
00269 temp =
00270 g_strdup_printf ("/%s/%s", QOF_CONFIG_TIP,
00271 option->option_name);
00272 kvp_frame_set_string (be->backend_configuration, temp,
00273 option->tooltip);
00274 g_free (temp);
00275
00276 be->config_count = count;
00277 }
00278 }
00279
00280 KvpFrame *
00281 qof_backend_complete_frame (QofBackend * be)
00282 {
00283 g_return_val_if_fail (be, NULL);
00284 be->config_count = 0;
00285 return be->backend_configuration;
00286 }
00287
00288 struct config_iterate
00289 {
00290 QofBackendOptionCB fcn;
00291 gpointer data;
00292 gint count;
00293 KvpFrame *recursive;
00294 };
00295
00296
00297
00298
00299
00300 static void
00301 config_foreach_cb (const gchar * key, KvpValue * value, gpointer data)
00302 {
00303 QofBackendOption option;
00304 gint64 int64;
00305 gdouble db;
00306 QofNumeric num;
00307 gchar *parent;
00308 struct config_iterate *helper;
00309
00310 g_return_if_fail (key || value || data);
00311 helper = (struct config_iterate *) data;
00312 if (!helper->recursive)
00313 {
00314 PERR (" no parent frame");
00315 return;
00316 }
00317
00318 if (0 == safe_strcmp (key, QOF_CONFIG_DESC))
00319 {
00320 return;
00321 }
00322 if (0 == safe_strcmp (key, QOF_CONFIG_TIP))
00323 {
00324 return;
00325 }
00326 ENTER (" key=%s", key);
00327 option.option_name = key;
00328 option.type = kvp_value_get_type (value);
00329 if (!option.type)
00330 return;
00331 switch (option.type)
00332 {
00333 case KVP_TYPE_GINT64:
00334 {
00335 int64 = kvp_value_get_gint64 (value);
00336 option.value = (gpointer) & int64;
00337 break;
00338 }
00339 case KVP_TYPE_DOUBLE:
00340 {
00341 db = kvp_value_get_double (value);
00342 option.value = (gpointer) & db;
00343 break;
00344 }
00345 case KVP_TYPE_NUMERIC:
00346 {
00347 num = kvp_value_get_numeric (value);
00348 option.value = (gpointer) & num;
00349 break;
00350 }
00351 case KVP_TYPE_STRING:
00352 {
00353 option.value = (gpointer) kvp_value_get_string (value);
00354 break;
00355 }
00356 case KVP_TYPE_TIME :
00357 {
00358 option.value = (gpointer) kvp_value_get_time (value);
00359 }
00360 #ifndef QOF_DISABLE_DEPRECATED
00361 case KVP_TYPE_TIMESPEC:
00362 {
00363 Timespec ts;
00364 ts = kvp_value_get_timespec (value);
00365 option.value = (gpointer) & ts;
00366 break;
00367 }
00368 #endif
00369 case KVP_TYPE_GUID:
00370 {
00371 break;
00372 }
00373 case KVP_TYPE_BINARY:
00374 {
00375 break;
00376 }
00377 case KVP_TYPE_GLIST:
00378 {
00379 break;
00380 }
00381 case KVP_TYPE_FRAME:
00382 {
00383 break;
00384 }
00385 }
00386 parent = g_strdup_printf ("/%s/%s", QOF_CONFIG_DESC, key);
00387 option.description = kvp_frame_get_string (helper->recursive, parent);
00388 g_free (parent);
00389 parent = g_strdup_printf ("/%s/%s", QOF_CONFIG_TIP, key);
00390 option.tooltip = kvp_frame_get_string (helper->recursive, parent);
00391 g_free (parent);
00392 helper->count++;
00393
00394 helper->fcn (&option, helper->data);
00395 switch (option.type)
00396 {
00397 case KVP_TYPE_GINT64:
00398 {
00399 kvp_frame_set_gint64 (helper->recursive, key,
00400 (*(gint64 *) option.value));
00401 break;
00402 }
00403 case KVP_TYPE_DOUBLE:
00404 {
00405 kvp_frame_set_double (helper->recursive, key,
00406 (*(gdouble *) option.value));
00407 break;
00408 }
00409 case KVP_TYPE_NUMERIC:
00410 {
00411 kvp_frame_set_numeric (helper->recursive, key,
00412 (*(QofNumeric *) option.value));
00413 break;
00414 }
00415 case KVP_TYPE_STRING:
00416 {
00417 kvp_frame_set_string (helper->recursive, key,
00418 (gchar *) option.value);
00419 break;
00420 }
00421 case KVP_TYPE_TIME :
00422 {
00423 kvp_frame_set_time (helper->recursive, key,
00424 (QofTime*) option.value);
00425 break;
00426 }
00427 #ifndef QOF_DISABLE_DEPRECATED
00428 case KVP_TYPE_TIMESPEC:
00429 {
00430 kvp_frame_set_timespec (helper->recursive, key,
00431 (*(Timespec *) option.value));
00432 break;
00433 }
00434 #endif
00435 case KVP_TYPE_GUID:
00436 {
00437 break;
00438 }
00439 case KVP_TYPE_BINARY:
00440 {
00441 break;
00442 }
00443 case KVP_TYPE_GLIST:
00444 {
00445 break;
00446 }
00447 case KVP_TYPE_FRAME:
00448 {
00449 break;
00450 }
00451 }
00452 LEAVE (" ");
00453 }
00454
00455 void
00456 qof_backend_option_foreach (KvpFrame * config,
00457 QofBackendOptionCB cb, gpointer data)
00458 {
00459 struct config_iterate helper;
00460
00461 if (!config || !cb)
00462 return;
00463 ENTER (" ");
00464 helper.fcn = cb;
00465 helper.count = 1;
00466 helper.data = data;
00467 helper.recursive = config;
00468 kvp_frame_for_each_slot (config, config_foreach_cb, &helper);
00469 LEAVE (" ");
00470 }
00471
00472 void
00473 qof_backend_load_config (QofBackend * be, KvpFrame * config)
00474 {
00475 if (!be || !config)
00476 return;
00477 if (!be->load_config)
00478 return;
00479 (be->load_config) (be, config);
00480 }
00481
00482 KvpFrame *
00483 qof_backend_get_config (QofBackend * be)
00484 {
00485 if (!be)
00486 return NULL;
00487 if (!be->get_config)
00488 return NULL;
00489 return (be->get_config) (be);
00490 }
00491
00492 gboolean
00493 qof_backend_commit_exists (QofBackend * be)
00494 {
00495 if (!be)
00496 return FALSE;
00497 if (be->commit)
00498 return TRUE;
00499 else
00500 return FALSE;
00501 }
00502
00503 gboolean
00504 qof_load_backend_library (const gchar * directory,
00505 const gchar * filename, const gchar * init_fcn)
00506 {
00507 gchar *fullpath;
00508 typedef void (*backend_init) (void);
00509 GModule *backend;
00510 backend_init gmod_init;
00511 gpointer g;
00512
00513 g_return_val_if_fail (g_module_supported (), FALSE);
00514 fullpath = g_module_build_path (directory, filename);
00515 backend = g_module_open (fullpath, G_MODULE_BIND_LAZY);
00516 if (!backend)
00517 {
00518 PERR (" No backend found. %s", g_module_error ());
00519 return FALSE;
00520 }
00521 g = &gmod_init;
00522 if (!g_module_symbol (backend, init_fcn, g))
00523 {
00524 PERR (" Backend did not initialise. %s", g_module_error ());
00525 return FALSE;
00526 }
00527 g_module_make_resident (backend);
00528 gmod_init ();
00529 g_free (fullpath);
00530 return TRUE;
00531 }
00532
00533