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 #define _GNU_SOURCE
00026 #include "config.h"
00027 #include <stdio.h>
00028 #include <stdlib.h>
00029 #include <stdarg.h>
00030 #include <regex.h>
00031 #include <glib.h>
00032 #include <gmodule.h>
00033 #include <errno.h>
00034 #include "qof.h"
00035 #include "qofbackend-p.h"
00036
00037 static QofLogModule log_module = QOF_MOD_BACKEND;
00038
00039 #define QOF_CONFIG_DESC "desc"
00040 #define QOF_CONFIG_TIP "tip"
00041
00042
00043
00044
00045
00046 void
00047 qof_backend_set_error (QofBackend *be, QofBackendError err)
00048 {
00049 if (!be) return;
00050
00051
00052 if (ERR_BACKEND_NO_ERR != be->last_err) return;
00053 be->last_err = err;
00054 }
00055
00056 QofBackendError
00057 qof_backend_get_error (QofBackend *be)
00058 {
00059 QofBackendError err;
00060 if (!be) return ERR_BACKEND_NO_BACKEND;
00061
00062
00063 err = be->last_err;
00064 be->last_err = ERR_BACKEND_NO_ERR;
00065 return err;
00066 }
00067
00068 void
00069 qof_backend_set_message (QofBackend *be, const char *format, ...)
00070 {
00071 va_list args;
00072 char * buffer;
00073
00074 if (!be) return;
00075
00076
00077 if (be->error_msg) g_free(be->error_msg);
00078
00079 if (!format) {
00080 be->error_msg = NULL;
00081 return;
00082 }
00083
00084 va_start(args, format);
00085 buffer = (char *)g_strdup_vprintf(format, args);
00086 va_end(args);
00087
00088 be->error_msg = buffer;
00089 }
00090
00091 char *
00092 qof_backend_get_message (QofBackend *be)
00093 {
00094 char * msg;
00095
00096 if (!be) return g_strdup("ERR_BACKEND_NO_BACKEND");
00097 if (!be->error_msg) return NULL;
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107 msg = be->error_msg;
00108 be->error_msg = NULL;
00109 return msg;
00110 }
00111
00112
00113
00114 void
00115 qof_backend_init(QofBackend *be)
00116 {
00117 be->session_begin = NULL;
00118 be->session_end = NULL;
00119 be->destroy_backend = NULL;
00120
00121 be->load = NULL;
00122
00123 be->begin = NULL;
00124 be->commit = NULL;
00125 be->rollback = NULL;
00126
00127 be->compile_query = NULL;
00128 be->free_query = NULL;
00129 be->run_query = NULL;
00130
00131 be->sync = NULL;
00132 be->load_config = NULL;
00133
00134 be->events_pending = NULL;
00135 be->process_events = NULL;
00136
00137 be->last_err = ERR_BACKEND_NO_ERR;
00138 if (be->error_msg) g_free (be->error_msg);
00139 be->error_msg = NULL;
00140 be->percentage = NULL;
00141 be->backend_configuration = kvp_frame_new();
00142
00143
00144 be->price_lookup = NULL;
00145 be->export = NULL;
00146 }
00147
00148 void
00149 qof_backend_run_begin(QofBackend *be, QofInstance *inst)
00150 {
00151 if(!be || !inst) { return; }
00152 if(!be->begin) { return; }
00153 (be->begin) (be, inst);
00154 }
00155
00156 gboolean
00157 qof_backend_begin_exists(QofBackend *be)
00158 {
00159 if(be->begin) { return TRUE; }
00160 else { return FALSE; }
00161 }
00162
00163 void
00164 qof_backend_run_commit(QofBackend *be, QofInstance *inst)
00165 {
00166 if(!be || !inst) { return; }
00167 if(!be->commit) { return; }
00168 (be->commit) (be, inst);
00169 }
00170
00171
00172
00173 void qof_backend_prepare_frame(QofBackend *be)
00174 {
00175 g_return_if_fail(be);
00176 if(!kvp_frame_is_empty(be->backend_configuration)) {
00177 kvp_frame_delete(be->backend_configuration);
00178 be->backend_configuration = kvp_frame_new();
00179 }
00180 be->config_count = 0;
00181 }
00182
00183 void qof_backend_prepare_option(QofBackend *be, QofBackendOption *option)
00184 {
00185 KvpValue *value;
00186 gchar *temp;
00187 gint count;
00188
00189 g_return_if_fail(be || option);
00190 count = be->config_count;
00191 count++;
00192 value = NULL;
00193 switch (option->type)
00194 {
00195 case KVP_TYPE_GINT64 : {
00196 value = kvp_value_new_gint64(*(gint64*)option->value);
00197 break;
00198 }
00199 case KVP_TYPE_DOUBLE : {
00200 value = kvp_value_new_double(*(double*)option->value);
00201 break;
00202 }
00203 case KVP_TYPE_NUMERIC : {
00204 value = kvp_value_new_numeric(*(gnc_numeric*)option->value);
00205 break;
00206 }
00207 case KVP_TYPE_STRING : {
00208 value = kvp_value_new_string((const char*)option->value);
00209 break;
00210 }
00211 case KVP_TYPE_GUID : { break; }
00212 case KVP_TYPE_TIMESPEC : {
00213 value = kvp_value_new_timespec(*(Timespec*)option->value);
00214 break;
00215 }
00216 case KVP_TYPE_BINARY : { break; }
00217 case KVP_TYPE_GLIST : { break; }
00218 case KVP_TYPE_FRAME : { break; }
00219 }
00220 if(value) {
00221 temp = g_strdup_printf("/%s", option->option_name);
00222 kvp_frame_set_value(be->backend_configuration, temp, value);
00223 g_free(temp);
00224 temp = g_strdup_printf("/%s/%s", QOF_CONFIG_DESC, option->option_name);
00225 kvp_frame_set_string(be->backend_configuration, temp, option->description);
00226 g_free(temp);
00227 temp = g_strdup_printf("/%s/%s", QOF_CONFIG_TIP, option->option_name);
00228 kvp_frame_set_string(be->backend_configuration, temp, option->tooltip);
00229 g_free(temp);
00230
00231 be->config_count = count;
00232 }
00233 }
00234
00235 KvpFrame* qof_backend_complete_frame(QofBackend *be)
00236 {
00237 g_return_val_if_fail(be, NULL);
00238 be->config_count = 0;
00239 return be->backend_configuration;
00240 }
00241
00242 struct config_iterate {
00243 QofBackendOptionCB fcn;
00244 gpointer data;
00245 gint count;
00246 KvpFrame *recursive;
00247 };
00248
00249
00250
00251
00252
00253 static void
00254 config_foreach_cb (const char *key, KvpValue *value, gpointer data)
00255 {
00256 QofBackendOption option;
00257 gint64 int64;
00258 double db;
00259 gnc_numeric num;
00260 Timespec ts;
00261 gchar *parent;
00262 struct config_iterate *helper;
00263
00264 g_return_if_fail(key || value || data);
00265 helper = (struct config_iterate*)data;
00266 if(!helper->recursive) { PERR (" no parent frame"); return; }
00267
00268 if(0 == safe_strcmp(key, QOF_CONFIG_DESC)) { return; }
00269 if(0 == safe_strcmp(key, QOF_CONFIG_TIP)) { return; }
00270 ENTER (" key=%s", key);
00271 option.option_name = key;
00272 option.type = kvp_value_get_type(value);
00273 if(!option.type) { return; }
00274 switch (option.type)
00275 {
00276 case KVP_TYPE_GINT64 : {
00277 int64 = kvp_value_get_gint64(value);
00278 option.value = (gpointer)&int64;
00279 break;
00280 }
00281 case KVP_TYPE_DOUBLE : {
00282 db = kvp_value_get_double(value);
00283 option.value = (gpointer)&db;
00284 break;
00285 }
00286 case KVP_TYPE_NUMERIC : {
00287 num = kvp_value_get_numeric(value);
00288 option.value = (gpointer)#
00289 break;
00290 }
00291 case KVP_TYPE_STRING : {
00292 option.value = (gpointer)kvp_value_get_string(value);
00293 break;
00294 }
00295 case KVP_TYPE_TIMESPEC : {
00296 ts = kvp_value_get_timespec(value);
00297 option.value = (gpointer)&ts;
00298 break;
00299 }
00300 case KVP_TYPE_GUID : { break; }
00301 case KVP_TYPE_BINARY : { break; }
00302 case KVP_TYPE_GLIST : { break; }
00303 case KVP_TYPE_FRAME : { break; }
00304 }
00305 parent = g_strdup_printf("/%s/%s", QOF_CONFIG_DESC, key);
00306 option.description = kvp_frame_get_string(helper->recursive, parent);
00307 g_free(parent);
00308 parent = g_strdup_printf("/%s/%s", QOF_CONFIG_TIP, key);
00309 option.tooltip = kvp_frame_get_string(helper->recursive, parent);
00310 g_free(parent);
00311 helper->count++;
00312
00313 helper->fcn (&option, helper->data);
00314 switch (option.type)
00315 {
00316 case KVP_TYPE_GINT64 : {
00317 kvp_frame_set_gint64(helper->recursive, key,
00318 (*(gint64*)option.value));
00319 break;
00320 }
00321 case KVP_TYPE_DOUBLE : {
00322 kvp_frame_set_double(helper->recursive, key,
00323 (*(double*)option.value));
00324 break;
00325 }
00326 case KVP_TYPE_NUMERIC : {
00327 kvp_frame_set_numeric(helper->recursive, key,
00328 (*(gnc_numeric*)option.value));
00329 break;
00330 }
00331 case KVP_TYPE_STRING : {
00332 kvp_frame_set_string(helper->recursive, key,
00333 (gchar*)option.value);
00334 break;
00335 }
00336 case KVP_TYPE_TIMESPEC : {
00337 kvp_frame_set_timespec(helper->recursive, key,
00338 (*(Timespec*)option.value));
00339 break;
00340 }
00341 case KVP_TYPE_GUID : { break; }
00342 case KVP_TYPE_BINARY : { break; }
00343 case KVP_TYPE_GLIST : { break; }
00344 case KVP_TYPE_FRAME : { break; }
00345 }
00346 LEAVE (" ");
00347 }
00348
00349 void qof_backend_option_foreach(KvpFrame *config, QofBackendOptionCB cb, gpointer data)
00350 {
00351 struct config_iterate helper;
00352
00353 if(!config || !cb) { return; }
00354 ENTER (" ");
00355 helper.fcn = cb;
00356 helper.count = 1;
00357 helper.data = data;
00358 helper.recursive = config;
00359 kvp_frame_for_each_slot(config, config_foreach_cb, &helper);
00360 LEAVE (" ");
00361 }
00362
00363 void
00364 qof_backend_load_config(QofBackend *be, KvpFrame *config)
00365 {
00366 if(!be || !config) { return; }
00367 if(!be->load_config) { return; }
00368 (be->load_config) (be, config);
00369 }
00370
00371 KvpFrame*
00372 qof_backend_get_config(QofBackend *be)
00373 {
00374 if(!be) { return NULL; }
00375 if(!be->get_config) { return NULL; }
00376 return (be->get_config) (be);
00377 }
00378
00379 gboolean
00380 qof_backend_commit_exists(QofBackend *be)
00381 {
00382 if(!be) { return FALSE; }
00383 if(be->commit) { return TRUE; }
00384 else { return FALSE; }
00385 }
00386
00387 gboolean
00388 qof_load_backend_library (const char *directory,
00389 const char* filename, const char* init_fcn)
00390 {
00391 gchar *fullpath;
00392 typedef void (* backend_init) (void);
00393 GModule *backend;
00394 backend_init gmod_init;
00395 gpointer g;
00396
00397 g_return_val_if_fail(g_module_supported(), FALSE);
00398 fullpath = g_module_build_path(directory, filename);
00399 backend = g_module_open(fullpath, G_MODULE_BIND_LAZY);
00400 if(!backend) {
00401 g_message ("%s: %s\n", PACKAGE, g_module_error ());
00402 return FALSE;
00403 }
00404 g = &gmod_init;
00405 if (!g_module_symbol (backend, init_fcn, g))
00406 {
00407 g_message ("%s: %s\n", PACKAGE, g_module_error ());
00408 return FALSE;
00409 }
00410 g_module_make_resident(backend);
00411 gmod_init();
00412 return TRUE;
00413 }
00414
00415