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