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
00146 be->price_lookup = NULL;
00148 be->export = NULL;
00149 }
00150
00151 void
00152 qof_backend_run_begin (QofBackend * be, QofInstance * inst)
00153 {
00154 if (!be || !inst)
00155 return;
00156 if (!be->begin)
00157 return;
00158 (be->begin) (be, inst);
00159 }
00160
00161 gboolean
00162 qof_backend_begin_exists (QofBackend * be)
00163 {
00164 if (be->begin)
00165 return TRUE;
00166 else
00167 return FALSE;
00168 }
00169
00170 void
00171 qof_backend_run_commit (QofBackend * be, QofInstance * inst)
00172 {
00173 if (!be || !inst)
00174 return;
00175 if (!be->commit)
00176 return;
00177 (be->commit) (be, inst);
00178 }
00179
00180
00181
00182 void
00183 qof_backend_prepare_frame (QofBackend * be)
00184 {
00185 g_return_if_fail (be);
00186 if (!kvp_frame_is_empty (be->backend_configuration))
00187 {
00188 kvp_frame_delete (be->backend_configuration);
00189 be->backend_configuration = kvp_frame_new ();
00190 }
00191 be->config_count = 0;
00192 }
00193
00194 void
00195 qof_backend_prepare_option (QofBackend * be,
00196 QofBackendOption * option)
00197 {
00198 KvpValue *value;
00199 gchar *temp;
00200 gint count;
00201
00202 g_return_if_fail (be || option);
00203 count = be->config_count;
00204 count++;
00205 value = NULL;
00206 switch (option->type)
00207 {
00208 case KVP_TYPE_GINT64:
00209 {
00210 value = kvp_value_new_gint64 (*(gint64 *) option->value);
00211 break;
00212 }
00213 case KVP_TYPE_DOUBLE:
00214 {
00215 value = kvp_value_new_double (*(double *) option->value);
00216 break;
00217 }
00218 case KVP_TYPE_NUMERIC:
00219 {
00220 value = kvp_value_new_numeric (*(gnc_numeric *) option->value);
00221 break;
00222 }
00223 case KVP_TYPE_STRING:
00224 {
00225 value = kvp_value_new_string ((const char *) option->value);
00226 break;
00227 }
00228 case KVP_TYPE_GUID:
00229 {
00230 break;
00231 }
00232 case KVP_TYPE_TIME :
00233 {
00234 value = kvp_value_new_time ((QofTime*) option->value);
00235 break;
00236 }
00237 #ifndef QOF_DISABLE_DEPRECATED
00238 case KVP_TYPE_TIMESPEC:
00239 {
00240 value = kvp_value_new_timespec (*(Timespec *) option->value);
00241 break;
00242 }
00243 #endif
00244 case KVP_TYPE_BINARY:
00245 {
00246 break;
00247 }
00248 case KVP_TYPE_GLIST:
00249 {
00250 break;
00251 }
00252 case KVP_TYPE_FRAME:
00253 {
00254 break;
00255 }
00256 }
00257 if (value)
00258 {
00259 temp = g_strdup_printf ("/%s", option->option_name);
00260 kvp_frame_set_value (be->backend_configuration, temp, value);
00261 g_free (temp);
00262 temp =
00263 g_strdup_printf ("/%s/%s", QOF_CONFIG_DESC,
00264 option->option_name);
00265 kvp_frame_set_string (be->backend_configuration, temp,
00266 option->description);
00267 g_free (temp);
00268 temp =
00269 g_strdup_printf ("/%s/%s", QOF_CONFIG_TIP,
00270 option->option_name);
00271 kvp_frame_set_string (be->backend_configuration, temp,
00272 option->tooltip);
00273 g_free (temp);
00274
00275 be->config_count = count;
00276 }
00277 }
00278
00279 KvpFrame *
00280 qof_backend_complete_frame (QofBackend * be)
00281 {
00282 g_return_val_if_fail (be, NULL);
00283 be->config_count = 0;
00284 return be->backend_configuration;
00285 }
00286
00287 struct config_iterate
00288 {
00289 QofBackendOptionCB fcn;
00290 gpointer data;
00291 gint count;
00292 KvpFrame *recursive;
00293 };
00294
00295
00296
00297
00298
00299 static void
00300 config_foreach_cb (const gchar * key, KvpValue * value, gpointer data)
00301 {
00302 QofBackendOption option;
00303 gint64 int64;
00304 double db;
00305 gnc_numeric num;
00306 gchar *parent;
00307 struct config_iterate *helper;
00308
00309 g_return_if_fail (key || value || data);
00310 helper = (struct config_iterate *) data;
00311 if (!helper->recursive)
00312 {
00313 PERR (" no parent frame");
00314 return;
00315 }
00316
00317 if (0 == safe_strcmp (key, QOF_CONFIG_DESC))
00318 {
00319 return;
00320 }
00321 if (0 == safe_strcmp (key, QOF_CONFIG_TIP))
00322 {
00323 return;
00324 }
00325 ENTER (" key=%s", key);
00326 option.option_name = key;
00327 option.type = kvp_value_get_type (value);
00328 if (!option.type)
00329 return;
00330 switch (option.type)
00331 {
00332 case KVP_TYPE_GINT64:
00333 {
00334 int64 = kvp_value_get_gint64 (value);
00335 option.value = (gpointer) & int64;
00336 break;
00337 }
00338 case KVP_TYPE_DOUBLE:
00339 {
00340 db = kvp_value_get_double (value);
00341 option.value = (gpointer) & db;
00342 break;
00343 }
00344 case KVP_TYPE_NUMERIC:
00345 {
00346 num = kvp_value_get_numeric (value);
00347 option.value = (gpointer) & num;
00348 break;
00349 }
00350 case KVP_TYPE_STRING:
00351 {
00352 option.value = (gpointer) kvp_value_get_string (value);
00353 break;
00354 }
00355 case KVP_TYPE_TIME :
00356 {
00357 option.value = (gpointer) kvp_value_get_time (value);
00358 }
00359 #ifndef QOF_DISABLE_DEPRECATED
00360 case KVP_TYPE_TIMESPEC:
00361 {
00362 Timespec ts;
00363 ts = kvp_value_get_timespec (value);
00364 option.value = (gpointer) & ts;
00365 break;
00366 }
00367 #endif
00368 case KVP_TYPE_GUID:
00369 {
00370 break;
00371 }
00372 case KVP_TYPE_BINARY:
00373 {
00374 break;
00375 }
00376 case KVP_TYPE_GLIST:
00377 {
00378 break;
00379 }
00380 case KVP_TYPE_FRAME:
00381 {
00382 break;
00383 }
00384 }
00385 parent = g_strdup_printf ("/%s/%s", QOF_CONFIG_DESC, key);
00386 option.description = kvp_frame_get_string (helper->recursive, parent);
00387 g_free (parent);
00388 parent = g_strdup_printf ("/%s/%s", QOF_CONFIG_TIP, key);
00389 option.tooltip = kvp_frame_get_string (helper->recursive, parent);
00390 g_free (parent);
00391 helper->count++;
00392
00393 helper->fcn (&option, helper->data);
00394 switch (option.type)
00395 {
00396 case KVP_TYPE_GINT64:
00397 {
00398 kvp_frame_set_gint64 (helper->recursive, key,
00399 (*(gint64 *) option.value));
00400 break;
00401 }
00402 case KVP_TYPE_DOUBLE:
00403 {
00404 kvp_frame_set_double (helper->recursive, key,
00405 (*(double *) option.value));
00406 break;
00407 }
00408 case KVP_TYPE_NUMERIC:
00409 {
00410 kvp_frame_set_numeric (helper->recursive, key,
00411 (*(gnc_numeric *) option.value));
00412 break;
00413 }
00414 case KVP_TYPE_STRING:
00415 {
00416 kvp_frame_set_string (helper->recursive, key,
00417 (gchar *) option.value);
00418 break;
00419 }
00420 case KVP_TYPE_TIME :
00421 {
00422 kvp_frame_set_time (helper->recursive, key,
00423 (QofTime*) option.value);
00424 break;
00425 }
00426 #ifndef QOF_DISABLE_DEPRECATED
00427 case KVP_TYPE_TIMESPEC:
00428 {
00429 kvp_frame_set_timespec (helper->recursive, key,
00430 (*(Timespec *) option.value));
00431 break;
00432 }
00433 #endif
00434 case KVP_TYPE_GUID:
00435 {
00436 break;
00437 }
00438 case KVP_TYPE_BINARY:
00439 {
00440 break;
00441 }
00442 case KVP_TYPE_GLIST:
00443 {
00444 break;
00445 }
00446 case KVP_TYPE_FRAME:
00447 {
00448 break;
00449 }
00450 }
00451 LEAVE (" ");
00452 }
00453
00454 void
00455 qof_backend_option_foreach (KvpFrame * config,
00456 QofBackendOptionCB cb, gpointer data)
00457 {
00458 struct config_iterate helper;
00459
00460 if (!config || !cb)
00461 return;
00462 ENTER (" ");
00463 helper.fcn = cb;
00464 helper.count = 1;
00465 helper.data = data;
00466 helper.recursive = config;
00467 kvp_frame_for_each_slot (config, config_foreach_cb, &helper);
00468 LEAVE (" ");
00469 }
00470
00471 void
00472 qof_backend_load_config (QofBackend * be, KvpFrame * config)
00473 {
00474 if (!be || !config)
00475 return;
00476 if (!be->load_config)
00477 return;
00478 (be->load_config) (be, config);
00479 }
00480
00481 KvpFrame *
00482 qof_backend_get_config (QofBackend * be)
00483 {
00484 if (!be)
00485 return NULL;
00486 if (!be->get_config)
00487 return NULL;
00488 return (be->get_config) (be);
00489 }
00490
00491 gboolean
00492 qof_backend_commit_exists (QofBackend * be)
00493 {
00494 if (!be)
00495 return FALSE;
00496 if (be->commit)
00497 return TRUE;
00498 else
00499 return FALSE;
00500 }
00501
00502 gboolean
00503 qof_load_backend_library (const gchar * directory,
00504 const gchar * filename, const gchar * init_fcn)
00505 {
00506 gchar *fullpath;
00507 typedef void (*backend_init) (void);
00508 GModule *backend;
00509 backend_init gmod_init;
00510 gpointer g;
00511
00512 g_return_val_if_fail (g_module_supported (), FALSE);
00513 fullpath = g_module_build_path (directory, filename);
00514 backend = g_module_open (fullpath, G_MODULE_BIND_LAZY);
00515 if (!backend)
00516 {
00517 g_message ("%s: %s\n", PACKAGE, g_module_error ());
00518 return FALSE;
00519 }
00520 g = &gmod_init;
00521 if (!g_module_symbol (backend, init_fcn, g))
00522 {
00523 g_message ("%s: %s\n", PACKAGE, g_module_error ());
00524 return FALSE;
00525 }
00526 g_module_make_resident (backend);
00527 gmod_init ();
00528 g_free (fullpath);
00529 return TRUE;
00530 }
00531
00532