00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00034 #include "config.h"
00035
00036 #include <dlfcn.h>
00037 #include <stdlib.h>
00038 #include <string.h>
00039 #include <sys/types.h>
00040 #include <sys/stat.h>
00041 #include <unistd.h>
00042
00043 #include <glib.h>
00044 #include "qofla-dir.h"
00045 #include "gnc-trace.h"
00046 #include "gnc-engine-util.h"
00047 #include "gnc-event.h"
00048 #include "qofsession.h"
00049 #include "qofbackend-p.h"
00050 #include "qof-be-utils.h"
00051 #include "qofbook.h"
00052 #include "qofbook-p.h"
00053 #include "qofobject.h"
00054 #include "qofsession-p.h"
00055
00057 static QofSession * current_session = NULL;
00058 static GHookList * session_closed_hooks = NULL;
00059 static QofLogModule log_module = QOF_MOD_SESSION;
00060 static GSList *provider_list = NULL;
00061
00062
00063
00064 void
00065 qof_backend_register_provider (QofBackendProvider *prov)
00066 {
00067 provider_list = g_slist_prepend (provider_list, prov);
00068 }
00069
00070
00071
00072
00073
00074 void
00075 qof_session_add_close_hook (GFunc fn, gpointer data)
00076 {
00077 GHook *hook;
00078
00079 if (session_closed_hooks == NULL) {
00080 session_closed_hooks = malloc(sizeof(GHookList));
00081 g_hook_list_init (session_closed_hooks, sizeof(GHook));
00082 }
00083
00084 hook = g_hook_alloc(session_closed_hooks);
00085 if (!hook)
00086 return;
00087
00088 hook->func = (GHookFunc)fn;
00089 hook->data = data;
00090 g_hook_append(session_closed_hooks, hook);
00091 }
00092
00093 void
00094 qof_session_call_close_hooks (QofSession *session)
00095 {
00096 GHook *hook;
00097 GFunc fn;
00098
00099 if (session_closed_hooks == NULL)
00100 return;
00101
00102 hook = g_hook_first_valid (session_closed_hooks, FALSE);
00103 while (hook) {
00104 fn = (GFunc)hook->func;
00105 fn(session, hook->data);
00106 hook = g_hook_next_valid (session_closed_hooks, hook, FALSE);
00107 }
00108 }
00109
00110
00111
00112
00113 static void
00114 qof_session_clear_error (QofSession *session)
00115 {
00116 QofBackendError err;
00117
00118 session->last_err = ERR_BACKEND_NO_ERR;
00119 g_free(session->error_message);
00120 session->error_message = NULL;
00121
00122
00123 if (session->backend)
00124 {
00125 do
00126 {
00127 err = qof_backend_get_error (session->backend);
00128 } while (ERR_BACKEND_NO_ERR != err);
00129 }
00130 }
00131
00132 void
00133 qof_session_push_error (QofSession *session, QofBackendError err,
00134 const char *message)
00135 {
00136 if (!session) return;
00137
00138 g_free (session->error_message);
00139
00140 session->last_err = err;
00141 session->error_message = g_strdup (message);
00142 }
00143
00144 QofBackendError
00145 qof_session_get_error (QofSession * session)
00146 {
00147 QofBackendError err;
00148
00149 if (!session) return ERR_BACKEND_NO_BACKEND;
00150
00151
00152 if (ERR_BACKEND_NO_ERR != session->last_err)
00153 {
00154 return session->last_err;
00155 }
00156
00157
00158 if (! session->backend) return ERR_BACKEND_NO_ERR;
00159
00160 err = qof_backend_get_error (session->backend);
00161 session->last_err = err;
00162 return err;
00163 }
00164
00165 static const char *
00166 get_default_error_message(QofBackendError err)
00167 {
00168 return "";
00169 }
00170
00171 const char *
00172 qof_session_get_error_message(QofSession *session)
00173 {
00174 if(!session) return "";
00175 if(!session->error_message)
00176 return get_default_error_message(session->last_err);
00177 return session->error_message;
00178 }
00179
00180 QofBackendError
00181 qof_session_pop_error (QofSession * session)
00182 {
00183 QofBackendError err;
00184
00185 if (!session) return ERR_BACKEND_NO_BACKEND;
00186
00187 err = qof_session_get_error(session);
00188 qof_session_clear_error(session);
00189
00190 return err;
00191 }
00192
00193
00194
00195 static void
00196 qof_session_init (QofSession *session)
00197 {
00198 if (!session) return;
00199
00200 session->entity.e_type = QOF_ID_SESSION;
00201 session->books = g_list_append (NULL, qof_book_new ());
00202 session->book_id = NULL;
00203 session->backend = NULL;
00204
00205 qof_session_clear_error (session);
00206 }
00207
00208 QofSession *
00209 qof_session_new (void)
00210 {
00211 QofSession *session = g_new0(QofSession, 1);
00212 qof_session_init(session);
00213 return session;
00214 }
00215
00218 QofSession *
00219 qof_session_get_current_session (void)
00220 {
00221 if (!current_session)
00222 {
00223 gnc_engine_suspend_events ();
00224 current_session = qof_session_new ();
00225 gnc_engine_resume_events ();
00226 }
00227
00228 return current_session;
00229 }
00230
00233 void
00234 qof_session_set_current_session (QofSession *session)
00235 {
00236 current_session = session;
00237 }
00238
00239 QofBook *
00240 qof_session_get_book (QofSession *session)
00241 {
00242 GList *node;
00243 if (!session) return NULL;
00244
00245 for (node=session->books; node; node=node->next)
00246 {
00247 QofBook *book = node->data;
00248 if ('y' == book->book_open) return book;
00249 }
00250 return NULL;
00251 }
00252
00253 void
00254 qof_session_add_book (QofSession *session, QofBook *addbook)
00255 {
00256 GList *node;
00257 if (!session) return;
00258
00259 ENTER (" sess=%p book=%p", session, addbook);
00260
00261
00262 for (node=session->books; node; node=node->next)
00263 {
00264 QofBook *book = node->data;
00265 if (addbook == book) return;
00266 }
00267
00268 if ('y' == addbook->book_open)
00269 {
00270
00271
00272
00273
00274 g_list_free (session->books);
00275 session->books = g_list_append (NULL, addbook);
00276 }
00277 else
00278 {
00279
00280 session->books = g_list_append (session->books, addbook);
00281 }
00282
00283 qof_book_set_backend (addbook, session->backend);
00284 LEAVE (" ");
00285 }
00286
00287 QofBackend *
00288 qof_session_get_backend (QofSession *session)
00289 {
00290 if (!session) return NULL;
00291 return session->backend;
00292 }
00293
00294 const char *
00295 qof_session_get_file_path (QofSession *session)
00296 {
00297 if (!session) return NULL;
00298 if (!session->backend) return NULL;
00299 return session->backend->fullpath;
00300 }
00301
00302 const char *
00303 qof_session_get_url (QofSession *session)
00304 {
00305 if (!session) return NULL;
00306 return session->book_id;
00307 }
00308
00309
00310
00311 typedef struct qof_entity_copy_data {
00312 QofEntity *from;
00313 QofEntity *to;
00314 GList *referenceList;
00315 GSList *param_list;
00316 QofSession *new_session;
00317 gboolean error;
00318 }QofEntityCopyData;
00319
00320 static void
00321 qof_book_set_partial(QofBook *book)
00322 {
00323 gboolean partial;
00324
00325 partial =
00326 (gboolean)GPOINTER_TO_INT(qof_book_get_data(book, PARTIAL_QOFBOOK));
00327 if(!partial) {
00328 qof_book_set_data(book, PARTIAL_QOFBOOK, (gboolean*)TRUE);
00329 }
00330 }
00331
00332 void
00333 qof_session_update_reference_list(QofSession *session, QofEntityReference *reference)
00334 {
00335 QofBook *book;
00336 GList *book_ref_list;
00337
00338 book = qof_session_get_book(session);
00339 book_ref_list = (GList*)qof_book_get_data(book, ENTITYREFERENCE);
00340 book_ref_list = g_list_append(book_ref_list, reference);
00341 qof_book_set_data(book, ENTITYREFERENCE, book_ref_list);
00342 qof_book_set_partial(book);
00343 }
00344
00345 static void
00346 qof_entity_param_cb(QofParam *param, gpointer data)
00347 {
00348 QofEntityCopyData *qecd;
00349
00350 g_return_if_fail(data != NULL);
00351 qecd = (QofEntityCopyData*)data;
00352 g_return_if_fail(param != NULL);
00353 if((param->param_getfcn != NULL)&&(param->param_setfcn != NULL)) {
00354 qecd->param_list = g_slist_prepend(qecd->param_list, param);
00355 }
00356 }
00357
00358 QofEntityReference*
00359 qof_entity_get_reference_from(QofEntity *ent, const QofParam *param)
00360 {
00361 QofEntityReference *reference;
00362 QofEntity *ref_ent;
00363 const GUID *cm_guid;
00364 char cm_sa[GUID_ENCODING_LENGTH + 1];
00365 gchar *cm_string;
00366
00367 g_return_val_if_fail(param, NULL);
00368 ref_ent = (QofEntity*)param->param_getfcn(ent, param);
00369 if(ref_ent != NULL) {
00370 reference = g_new0(QofEntityReference, 1);
00371 reference->type = ent->e_type;
00372 reference->ref_guid = g_new(GUID, 1);
00373 reference->ent_guid = &ent->guid;
00374 reference->param = qof_class_get_parameter(ent->e_type, param->param_name);
00375 cm_guid = qof_entity_get_guid(ref_ent);
00376 guid_to_string_buff(cm_guid, cm_sa);
00377 cm_string = g_strdup(cm_sa);
00378 if(TRUE == string_to_guid(cm_string, reference->ref_guid)) {
00379 return reference;
00380 }
00381 }
00382 return NULL;
00383 }
00384
00385 static void
00386 qof_entity_foreach_copy(gpointer data, gpointer user_data)
00387 {
00388 QofEntity *importEnt, *targetEnt, *referenceEnt;
00389 QofEntityCopyData *context;
00390 QofEntityReference *reference;
00391 gboolean registered_type;
00392
00393 QofParam *cm_param;
00394 gchar *cm_string, *cm_char;
00395 const GUID *cm_guid;
00396 KvpFrame *cm_kvp;
00397
00398 gnc_numeric cm_numeric, (*numeric_getter) (QofEntity*, QofParam*);
00399 double cm_double, (*double_getter) (QofEntity*, QofParam*);
00400 gboolean cm_boolean, (*boolean_getter) (QofEntity*, QofParam*);
00401 gint32 cm_i32, (*int32_getter) (QofEntity*, QofParam*);
00402 gint64 cm_i64, (*int64_getter) (QofEntity*, QofParam*);
00403 Timespec cm_date, (*date_getter) (QofEntity*, QofParam*);
00404
00405 void (*string_setter) (QofEntity*, const char*);
00406 void (*date_setter) (QofEntity*, Timespec);
00407 void (*numeric_setter) (QofEntity*, gnc_numeric);
00408 void (*guid_setter) (QofEntity*, const GUID*);
00409 void (*double_setter) (QofEntity*, double);
00410 void (*boolean_setter) (QofEntity*, gboolean);
00411 void (*i32_setter) (QofEntity*, gint32);
00412 void (*i64_setter) (QofEntity*, gint64);
00413 void (*char_setter) (QofEntity*, char*);
00414 void (*kvp_frame_setter) (QofEntity*, KvpFrame*);
00415
00416 g_return_if_fail(user_data != NULL);
00417 context = (QofEntityCopyData*) user_data;
00418 cm_date.tv_nsec = 0;
00419 cm_date.tv_sec = 0;
00420 importEnt = context->from;
00421 targetEnt = context->to;
00422 registered_type = FALSE;
00423 cm_param = (QofParam*) data;
00424 g_return_if_fail(cm_param != NULL);
00425 if(safe_strcmp(cm_param->param_type, QOF_TYPE_STRING) == 0) {
00426 cm_string = g_strdup((gchar*)cm_param->param_getfcn(importEnt, cm_param));
00427 string_setter = (void(*)(QofEntity*, const char*))cm_param->param_setfcn;
00428 if(string_setter != NULL) { string_setter(targetEnt, cm_string); }
00429 registered_type = TRUE;
00430 }
00431 if(safe_strcmp(cm_param->param_type, QOF_TYPE_DATE) == 0) {
00432 date_getter = (Timespec (*)(QofEntity*, QofParam*))cm_param->param_getfcn;
00433 cm_date = date_getter(importEnt, cm_param);
00434 date_setter = (void(*)(QofEntity*, Timespec))cm_param->param_setfcn;
00435 if(date_setter != NULL) { date_setter(targetEnt, cm_date); }
00436 registered_type = TRUE;
00437 }
00438 if((safe_strcmp(cm_param->param_type, QOF_TYPE_NUMERIC) == 0) ||
00439 (safe_strcmp(cm_param->param_type, QOF_TYPE_DEBCRED) == 0)) {
00440 numeric_getter = (gnc_numeric (*)(QofEntity*, QofParam*))cm_param->param_getfcn;
00441 cm_numeric = numeric_getter(importEnt, cm_param);
00442 numeric_setter = (void(*)(QofEntity*, gnc_numeric))cm_param->param_setfcn;
00443 if(numeric_setter != NULL) { numeric_setter(targetEnt, cm_numeric); }
00444 registered_type = TRUE;
00445 }
00446 if(safe_strcmp(cm_param->param_type, QOF_TYPE_GUID) == 0) {
00447 cm_guid = (const GUID*)cm_param->param_getfcn(importEnt, cm_param);
00448 guid_setter = (void(*)(QofEntity*, const GUID*))cm_param->param_setfcn;
00449 if(guid_setter != NULL) { guid_setter(targetEnt, cm_guid); }
00450 registered_type = TRUE;
00451 }
00452 if(safe_strcmp(cm_param->param_type, QOF_TYPE_INT32) == 0) {
00453 int32_getter = (gint32 (*)(QofEntity*, QofParam*)) cm_param->param_getfcn;
00454 cm_i32 = int32_getter(importEnt, cm_param);
00455 i32_setter = (void(*)(QofEntity*, gint32))cm_param->param_setfcn;
00456 if(i32_setter != NULL) { i32_setter(targetEnt, cm_i32); }
00457 registered_type = TRUE;
00458 }
00459 if(safe_strcmp(cm_param->param_type, QOF_TYPE_INT64) == 0) {
00460 int64_getter = (gint64 (*)(QofEntity*, QofParam*)) cm_param->param_getfcn;
00461 cm_i64 = int64_getter(importEnt, cm_param);
00462 i64_setter = (void(*)(QofEntity*, gint64))cm_param->param_setfcn;
00463 if(i64_setter != NULL) { i64_setter(targetEnt, cm_i64); }
00464 registered_type = TRUE;
00465 }
00466 if(safe_strcmp(cm_param->param_type, QOF_TYPE_DOUBLE) == 0) {
00467 double_getter = (double (*)(QofEntity*, QofParam*)) cm_param->param_getfcn;
00468 cm_double = double_getter(importEnt, cm_param);
00469 double_setter = (void(*)(QofEntity*, double))cm_param->param_setfcn;
00470 if(double_setter != NULL) { double_setter(targetEnt, cm_double); }
00471 registered_type = TRUE;
00472 }
00473 if(safe_strcmp(cm_param->param_type, QOF_TYPE_BOOLEAN) == 0){
00474 boolean_getter = (gboolean (*)(QofEntity*, QofParam*)) cm_param->param_getfcn;
00475 cm_boolean = boolean_getter(importEnt, cm_param);
00476 boolean_setter = (void(*)(QofEntity*, gboolean))cm_param->param_setfcn;
00477 if(boolean_setter != NULL) { boolean_setter(targetEnt, cm_boolean); }
00478 registered_type = TRUE;
00479 }
00480 if(safe_strcmp(cm_param->param_type, QOF_TYPE_KVP) == 0) {
00481 cm_kvp = kvp_frame_copy((KvpFrame*)cm_param->param_getfcn(importEnt,cm_param));
00482 kvp_frame_setter = (void(*)(QofEntity*, KvpFrame*))cm_param->param_setfcn;
00483 if(kvp_frame_setter != NULL) { kvp_frame_setter(targetEnt, cm_kvp); }
00484 registered_type = TRUE;
00485 }
00486 if(safe_strcmp(cm_param->param_type, QOF_TYPE_CHAR) == 0) {
00487 cm_char = (gchar*)cm_param->param_getfcn(importEnt,cm_param);
00488 char_setter = (void(*)(QofEntity*, char*))cm_param->param_setfcn;
00489 if(char_setter != NULL) { char_setter(targetEnt, cm_char); }
00490 registered_type = TRUE;
00491 }
00492 if(registered_type == FALSE) {
00493 referenceEnt = (QofEntity*)cm_param->param_getfcn(importEnt, cm_param);
00494 if(!referenceEnt || !referenceEnt->e_type) { return; }
00495 reference = qof_entity_get_reference_from(importEnt, cm_param);
00496 if(reference) {
00497 qof_session_update_reference_list(context->new_session, reference);
00498 }
00499 }
00500 }
00501
00502 static gboolean
00503 qof_entity_guid_match(QofSession *new_session, QofEntity *original)
00504 {
00505 QofEntity *copy;
00506 const GUID *g;
00507 QofIdTypeConst type;
00508 QofBook *targetBook;
00509 QofCollection *coll;
00510
00511 copy = NULL;
00512 g_return_val_if_fail(original != NULL, FALSE);
00513 targetBook = qof_session_get_book(new_session);
00514 g_return_val_if_fail(targetBook != NULL, FALSE);
00515 g = qof_entity_get_guid(original);
00516 type = g_strdup(original->e_type);
00517 coll = qof_book_get_collection(targetBook, type);
00518 copy = qof_collection_lookup_entity(coll, g);
00519 if(copy) { return TRUE; }
00520 return FALSE;
00521 }
00522
00523 static void
00524 qof_entity_list_foreach(gpointer data, gpointer user_data)
00525 {
00526 QofEntityCopyData *qecd;
00527 QofEntity *original;
00528 QofInstance *inst;
00529 QofBook *book;
00530 const GUID *g;
00531
00532 g_return_if_fail(data != NULL);
00533 original = (QofEntity*)data;
00534 g_return_if_fail(user_data != NULL);
00535 qecd = (QofEntityCopyData*)user_data;
00536 if(qof_entity_guid_match(qecd->new_session, original)) { return; }
00537 qecd->from = original;
00538 book = qof_session_get_book(qecd->new_session);
00539 inst = (QofInstance*)qof_object_new_instance(original->e_type, book);
00540 qecd->to = &inst->entity;
00541 g = qof_entity_get_guid(original);
00542 qof_entity_set_guid(qecd->to, g);
00543 if(qecd->param_list != NULL) {
00544 g_slist_free(qecd->param_list);
00545 qecd->param_list = NULL;
00546 }
00547 qof_class_param_foreach(original->e_type, qof_entity_param_cb, qecd);
00548 qof_begin_edit(inst);
00549 g_slist_foreach(qecd->param_list, qof_entity_foreach_copy, qecd);
00550 qof_commit_edit(inst);
00551 }
00552
00553 static void
00554 qof_entity_coll_foreach(QofEntity *original, gpointer user_data)
00555 {
00556 QofEntityCopyData *qecd;
00557 const GUID *g;
00558 QofBook *targetBook;
00559 QofCollection *coll;
00560 QofEntity *copy;
00561
00562 g_return_if_fail(user_data != NULL);
00563 copy = NULL;
00564 qecd = (QofEntityCopyData*)user_data;
00565 targetBook = qof_session_get_book(qecd->new_session);
00566 g = qof_entity_get_guid(original);
00567 coll = qof_book_get_collection(targetBook, original->e_type);
00568 copy = qof_collection_lookup_entity(coll, g);
00569 if(copy) { qecd->error = TRUE; }
00570 }
00571
00572 static void
00573 qof_entity_coll_copy(QofEntity *original, gpointer user_data)
00574 {
00575 QofEntityCopyData *qecd;
00576 QofBook *book;
00577 QofInstance *inst;
00578 const GUID *g;
00579
00580 g_return_if_fail(user_data != NULL);
00581 qecd = (QofEntityCopyData*)user_data;
00582 book = qof_session_get_book(qecd->new_session);
00583 inst = (QofInstance*)qof_object_new_instance(original->e_type, book);
00584 qecd->to = &inst->entity;
00585 qecd->from = original;
00586 g = qof_entity_get_guid(original);
00587 qof_entity_set_guid(qecd->to, g);
00588 qof_begin_edit(inst);
00589 g_slist_foreach(qecd->param_list, qof_entity_foreach_copy, qecd);
00590 qof_commit_edit(inst);
00591 }
00592
00593 gboolean qof_entity_copy_to_session(QofSession* new_session, QofEntity* original)
00594 {
00595 QofEntityCopyData qecd;
00596 QofInstance *inst;
00597 QofBook *book;
00598
00599 if(!new_session || !original) { return FALSE; }
00600 if(qof_entity_guid_match(new_session, original)) { return FALSE; }
00601 gnc_engine_suspend_events();
00602 qecd.param_list = NULL;
00603 book = qof_session_get_book(new_session);
00604 qecd.new_session = new_session;
00605 qof_book_set_partial(book);
00606 inst = (QofInstance*)qof_object_new_instance(original->e_type, book);
00607 qecd.to = &inst->entity;
00608 qecd.from = original;
00609 qof_entity_set_guid(qecd.to, qof_entity_get_guid(original));
00610 qof_begin_edit(inst);
00611 qof_class_param_foreach(original->e_type, qof_entity_param_cb, &qecd);
00612 qof_commit_edit(inst);
00613 if(g_slist_length(qecd.param_list) == 0) { return FALSE; }
00614 g_slist_foreach(qecd.param_list, qof_entity_foreach_copy, &qecd);
00615 g_slist_free(qecd.param_list);
00616 gnc_engine_resume_events();
00617 return TRUE;
00618 }
00619
00620 gboolean qof_entity_copy_list(QofSession *new_session, GList *entity_list)
00621 {
00622 QofEntityCopyData *qecd;
00623
00624 if(!new_session || !entity_list) { return FALSE; }
00625 ENTER (" list=%d", g_list_length(entity_list));
00626 qecd = g_new0(QofEntityCopyData, 1);
00627 gnc_engine_suspend_events();
00628 qecd->param_list = NULL;
00629 qecd->new_session = new_session;
00630 qof_book_set_partial(qof_session_get_book(new_session));
00631 g_list_foreach(entity_list, qof_entity_list_foreach, qecd);
00632 gnc_engine_resume_events();
00633 g_free(qecd);
00634 LEAVE (" ");
00635 return TRUE;
00636 }
00637
00638 gboolean qof_entity_copy_coll(QofSession *new_session, QofCollection *entity_coll)
00639 {
00640 QofEntityCopyData qecd;
00641
00642 gnc_engine_suspend_events();
00643 qecd.param_list = NULL;
00644 qecd.new_session = new_session;
00645 qof_book_set_partial(qof_session_get_book(qecd.new_session));
00646 qof_collection_foreach(entity_coll, qof_entity_coll_foreach, &qecd);
00647 qof_class_param_foreach(qof_collection_get_type(entity_coll), qof_entity_param_cb, &qecd);
00648 qof_collection_foreach(entity_coll, qof_entity_coll_copy, &qecd);
00649 if(qecd.param_list != NULL) { g_slist_free(qecd.param_list); }
00650 gnc_engine_resume_events();
00651 return TRUE;
00652 }
00653
00654 struct recurse_s
00655 {
00656 QofSession *session;
00657 gboolean success;
00658 GList *ref_list;
00659 GList *ent_list;
00660 };
00661
00662 static void
00663 recurse_collection_cb (QofEntity *ent, gpointer user_data)
00664 {
00665 struct recurse_s *store;
00666
00667 if(user_data == NULL) { return; }
00668 store = (struct recurse_s*)user_data;
00669 if(!ent || !store) { return; }
00670 store->success = qof_entity_copy_to_session(store->session, ent);
00671 if(store->success) {
00672 store->ent_list = g_list_append(store->ent_list, ent);
00673 }
00674 }
00675
00676 static void
00677 recurse_ent_cb(QofEntity *ent, gpointer user_data)
00678 {
00679 GList *ref_list, *i, *j, *ent_list, *child_list;
00680 QofParam *ref_param;
00681 QofEntity *ref_ent, *child_ent;
00682 QofSession *session;
00683 struct recurse_s *store;
00684 gboolean success;
00685
00686 if(user_data == NULL) { return; }
00687 store = (struct recurse_s*)user_data;
00688 session = store->session;
00689 success = store->success;
00690 ref_list = NULL;
00691 child_ent = NULL;
00692 ref_list = g_list_copy(store->ref_list);
00693 if((!session)||(!ent)) { return; }
00694 ent_list = NULL;
00695 child_list = NULL;
00696 i = NULL;
00697 j = NULL;
00698 for(i = ref_list; i != NULL; i=i->next)
00699 {
00700 if(i->data == NULL) { continue; }
00701 ref_param = (QofParam*)i->data;
00702 if(ref_param->param_name == NULL) { continue; }
00703 if(ref_param->param_type == QOF_TYPE_COLLECT) {
00704 QofCollection *col;
00705 col = ref_param->param_getfcn(ent, ref_param);
00706 qof_collection_foreach(col, recurse_collection_cb, store);
00707 continue;
00708 }
00709 ref_ent = (QofEntity*)ref_param->param_getfcn(ent, ref_param);
00710 if((ref_ent)&&(ref_ent->e_type))
00711 {
00712 store->success = qof_entity_copy_to_session(session, ref_ent);
00713 if(store->success) { ent_list = g_list_append(ent_list, ref_ent); }
00714 }
00715 }
00716 for(i = ent_list; i != NULL; i = i->next)
00717 {
00718 if(i->data == NULL) { continue; }
00719 child_ent = (QofEntity*)i->data;
00720 if(child_ent == NULL) { continue; }
00721 ref_list = qof_class_get_referenceList(child_ent->e_type);
00722 for(j = ref_list; j != NULL; j = j->next)
00723 {
00724 if(j->data == NULL) { continue; }
00725 ref_param = (QofParam*)j->data;
00726 ref_ent = ref_param->param_getfcn(child_ent, ref_param);
00727 if(ref_ent != NULL)
00728 {
00729 success = qof_entity_copy_to_session(session, ref_ent);
00730 if(success) { child_list = g_list_append(child_list, ref_ent); }
00731 }
00732 }
00733 }
00734 for(i = child_list; i != NULL; i = i->next)
00735 {
00736 if(i->data == NULL) { continue; }
00737 ref_ent = (QofEntity*)i->data;
00738 if(ref_ent == NULL) { continue; }
00739 ref_list = qof_class_get_referenceList(ref_ent->e_type);
00740 for(j = ref_list; j != NULL; j = j->next)
00741 {
00742 if(j->data == NULL) { continue; }
00743 ref_param = (QofParam*)j->data;
00744 child_ent = ref_param->param_getfcn(ref_ent, ref_param);
00745 if(child_ent != NULL)
00746 {
00747 qof_entity_copy_to_session(session, child_ent);
00748 }
00749 }
00750 }
00751 }
00752
00753 gboolean
00754 qof_entity_copy_coll_r(QofSession *new_session, QofCollection *coll)
00755 {
00756 struct recurse_s store;
00757 gboolean success;
00758
00759 if((!new_session)||(!coll)) { return FALSE; }
00760 store.session = new_session;
00761 success = TRUE;
00762 store.success = success;
00763 store.ent_list = NULL;
00764 store.ref_list = qof_class_get_referenceList(qof_collection_get_type(coll));
00765 success = qof_entity_copy_coll(new_session, coll);
00766 if(success){ qof_collection_foreach(coll, recurse_ent_cb, &store); }
00767 return success;
00768 }
00769
00770 gboolean qof_entity_copy_one_r(QofSession *new_session, QofEntity *ent)
00771 {
00772 struct recurse_s store;
00773 QofCollection *coll;
00774 gboolean success;
00775
00776 if((!new_session)||(!ent)) { return FALSE; }
00777 store.session = new_session;
00778 success = TRUE;
00779 store.success = success;
00780 store.ref_list = qof_class_get_referenceList(ent->e_type);
00781 success = qof_entity_copy_to_session(new_session, ent);
00782 if(success == TRUE) {
00783 coll = qof_book_get_collection(qof_session_get_book(new_session), ent->e_type);
00784 qof_collection_foreach(coll, recurse_ent_cb, &store);
00785 }
00786 return success;
00787 }
00788
00789
00790
00791
00792
00793
00794
00795 struct backend_providers
00796 {
00797 const char *libdir;
00798 const char *filename;
00799 const char *init_fcn;
00800 };
00801
00802
00803
00804
00805
00806 struct backend_providers backend_list[] = {
00807 { QOF_LIB_DIR, "libqof-backend-qsf.la", "qsf_provider_init" },
00808 #ifdef HAVE_DWI
00809 { QOF_LIB_DIR, "libqof_backend_dwi.la", "dwiend_provider_init" },
00810 #endif
00811 { NULL, NULL, NULL }
00812 };
00813
00814 static void
00815 qof_session_load_backend(QofSession * session, char * access_method)
00816 {
00817 GSList *p;
00818 GList *node;
00819 QofBackendProvider *prov;
00820 QofBook *book;
00821 char *msg;
00822 gint num;
00823 gboolean prov_type;
00824 gboolean (*type_check) (const char*);
00825
00826 ENTER (" list=%d", g_slist_length(provider_list));
00827 prov_type = FALSE;
00828 if (NULL == provider_list)
00829 {
00830 for (num = 0; backend_list[num].filename != NULL; num++) {
00831 if(!qof_load_backend_library(backend_list[num].libdir,
00832 backend_list[num].filename, backend_list[num].init_fcn))
00833 {
00834 PWARN (" failed to load %s from %s using %s",
00835 backend_list[num].filename, backend_list[num].libdir,
00836 backend_list[num].init_fcn);
00837 }
00838 }
00839 }
00840 p = g_slist_copy(provider_list);
00841 while(p != NULL)
00842 {
00843 prov = p->data;
00844
00845 if (0 == strcasecmp (access_method, prov->access_method))
00846 {
00847
00848
00849 type_check = (gboolean (*)(const char*)) prov->check_data_type;
00850 prov_type = (type_check)(session->book_id);
00851 if(!prov_type)
00852 {
00853 PINFO(" %s not usable", prov->provider_name);
00854 p = p->next;
00855 continue;
00856 }
00857 PINFO (" selected %s", prov->provider_name);
00858 if (NULL == prov->backend_new)
00859 {
00860 p = p->next;
00861 continue;
00862 }
00863
00864 session->backend = (*(prov->backend_new))();
00865 session->backend->provider = prov;
00866
00867 for (node=session->books; node; node=node->next)
00868 {
00869 book = node->data;
00870 qof_book_set_backend (book, session->backend);
00871 }
00872 LEAVE (" ");
00873 return;
00874 }
00875 p = p->next;
00876 }
00877 msg = g_strdup_printf("failed to load '%s' using access_method", access_method);
00878 qof_session_push_error (session, ERR_BACKEND_NO_HANDLER, msg);
00879 LEAVE (" ");
00880 }
00881
00882
00883
00884 static void
00885 qof_session_destroy_backend (QofSession *session)
00886 {
00887 g_return_if_fail (session);
00888
00889 if (session->backend)
00890 {
00891
00892 char * msg = qof_backend_get_message (session->backend);
00893 g_free (msg);
00894
00895
00896 if (session->backend->destroy_backend)
00897 {
00898 session->backend->destroy_backend(session->backend);
00899 }
00900 else
00901 {
00902 g_free(session->backend);
00903 }
00904 }
00905
00906 session->backend = NULL;
00907 }
00908
00909 void
00910 qof_session_begin (QofSession *session, const char * book_id,
00911 gboolean ignore_lock, gboolean create_if_nonexistent)
00912 {
00913 char *p, *access_method, *msg;
00914 int err;
00915
00916 if (!session) return;
00917
00918 ENTER (" sess=%p ignore_lock=%d, book-id=%s",
00919 session, ignore_lock,
00920 book_id ? book_id : "(null)");
00921
00922
00923 qof_session_clear_error (session);
00924
00925
00926 if (session->book_id)
00927 {
00928 qof_session_push_error (session, ERR_BACKEND_LOCKED, NULL);
00929 LEAVE("push error book is already open ");
00930 return;
00931 }
00932
00933
00934 if (!book_id)
00935 {
00936 qof_session_push_error (session, ERR_BACKEND_BAD_URL, NULL);
00937 LEAVE("push error missing book_id");
00938 return;
00939 }
00940
00941
00942 session->book_id = g_strdup (book_id);
00943
00944
00945 qof_session_destroy_backend(session);
00946
00947
00948
00949
00950
00951 p = strchr (book_id, ':');
00952 if (p)
00953 {
00954 access_method = g_strdup (book_id);
00955 p = strchr (access_method, ':');
00956 *p = 0;
00957 qof_session_load_backend(session, access_method);
00958 g_free (access_method);
00959 }
00960 else
00961 {
00962
00963 qof_session_load_backend(session, "file");
00964 }
00965
00966
00967 if (NULL == session->backend)
00968 {
00969 qof_session_push_error (session, ERR_BACKEND_BAD_URL, NULL);
00970 LEAVE (" BAD: no backend: sess=%p book-id=%s",
00971 session, book_id ? book_id : "(null)");
00972 return;
00973 }
00974
00975
00976 if (session->backend->session_begin)
00977 {
00978
00979 (session->backend->session_begin)(session->backend, session,
00980 session->book_id, ignore_lock,
00981 create_if_nonexistent);
00982 PINFO("Done running session_begin on backend");
00983 err = qof_backend_get_error(session->backend);
00984 msg = qof_backend_get_message(session->backend);
00985 if (err != ERR_BACKEND_NO_ERR)
00986 {
00987 g_free(session->book_id);
00988 session->book_id = NULL;
00989 qof_session_push_error (session, err, msg);
00990 LEAVE(" backend error %d %s", err, msg);
00991 return;
00992 }
00993 if (msg != NULL)
00994 {
00995 PWARN("%s", msg);
00996 g_free(msg);
00997 }
00998 }
00999
01000 LEAVE (" sess=%p book-id=%s",
01001 session, book_id ? book_id : "(null)");
01002 }
01003
01004
01005
01006 void
01007 qof_session_load (QofSession *session,
01008 QofPercentageFunc percentage_func)
01009 {
01010 QofBook *newbook, *ob;
01011 QofBookList *oldbooks, *node;
01012 QofBackend *be;
01013 QofBackendError err;
01014
01015 if (!session) return;
01016 if (!session->book_id) return;
01017
01018 ENTER ("sess=%p book_id=%s", session, session->book_id
01019 ? session->book_id : "(null)");
01020
01021
01022
01023
01024 oldbooks = session->books;
01025
01026
01027
01028
01029
01030 newbook = qof_book_new();
01031 session->books = g_list_append (NULL, newbook);
01032 PINFO ("new book=%p", newbook);
01033
01034 qof_session_clear_error (session);
01035
01036
01037
01038
01039
01040
01041
01042
01043 be = session->backend;
01044 qof_book_set_backend(newbook, be);
01045
01046
01047
01048
01049
01050 if (be)
01051 {
01052 be->percentage = percentage_func;
01053
01054 if (be->load)
01055 {
01056 be->load (be, newbook);
01057 qof_session_push_error (session, qof_backend_get_error(be), NULL);
01058 }
01059 }
01060
01061
01062
01063
01064
01065
01066 err = qof_session_get_error(session);
01067 if ((err != ERR_BACKEND_NO_ERR) &&
01068 (err != ERR_FILEIO_FILE_TOO_OLD) &&
01069 (err != ERR_SQL_DB_TOO_OLD))
01070 {
01071
01072 qof_book_set_backend (newbook, NULL);
01073 qof_book_destroy (newbook);
01074 g_list_free (session->books);
01075 session->books = oldbooks;
01076 LEAVE("error from backend %d", qof_session_get_error(session));
01077 return;
01078 }
01079
01080 for (node=oldbooks; node; node=node->next)
01081 {
01082 ob = node->data;
01083 qof_book_set_backend (ob, NULL);
01084 qof_book_destroy (ob);
01085 }
01086
01087
01088 LEAVE ("sess = %p, book_id=%s", session, session->book_id
01089 ? session->book_id : "(null)");
01090 }
01091
01092
01093
01094 gboolean
01095 qof_session_save_may_clobber_data (QofSession *session)
01096 {
01097 if (!session) return FALSE;
01098 if (!session->backend) return FALSE;
01099 if (!session->backend->save_may_clobber_data) return FALSE;
01100
01101 return (*(session->backend->save_may_clobber_data)) (session->backend);
01102 }
01103
01104 static gboolean
01105 save_error_handler(QofBackend *be, QofSession *session)
01106 {
01107 int err;
01108 err = qof_backend_get_error(be);
01109
01110 if (ERR_BACKEND_NO_ERR != err)
01111 {
01112 qof_session_push_error (session, err, NULL);
01113 return TRUE;
01114 }
01115 return FALSE;
01116 }
01117
01118 void
01119 qof_session_save (QofSession *session,
01120 QofPercentageFunc percentage_func)
01121 {
01122 GList *node;
01123 QofBackend *be;
01124 gboolean partial, change_backend;
01125 QofBackendProvider *prov;
01126 GSList *p;
01127 QofBook *book, *abook;
01128 int err;
01129 gint num;
01130 char *msg, *book_id;
01131
01132 if (!session) return;
01133 ENTER ("sess=%p book_id=%s",
01134 session, session->book_id ? session->book_id : "(null)");
01135
01136 book = qof_session_get_book(session);
01137 partial = (gboolean)GPOINTER_TO_INT(qof_book_get_data(book, PARTIAL_QOFBOOK));
01138 change_backend = FALSE;
01139 msg = g_strdup_printf(" ");
01140 book_id = g_strdup(session->book_id);
01141 if(partial == TRUE)
01142 {
01143 if(session->backend && session->backend->provider) {
01144 prov = session->backend->provider;
01145 if(TRUE == prov->partial_book_supported)
01146 {
01147
01148 change_backend = FALSE;
01149 }
01150 else { change_backend = TRUE; }
01151 }
01152
01153 else { change_backend = TRUE; }
01154 }
01155 if(change_backend == TRUE)
01156 {
01157 qof_session_destroy_backend(session);
01158 if (NULL == provider_list)
01159 {
01160 for (num = 0; backend_list[num].filename != NULL; num++) {
01161 qof_load_backend_library(backend_list[num].libdir,
01162 backend_list[num].filename, backend_list[num].init_fcn);
01163 }
01164 }
01165 p = g_slist_copy(provider_list);
01166 while(p != NULL)
01167 {
01168 prov = p->data;
01169 if(TRUE == prov->partial_book_supported)
01170 {
01172
01173
01174
01175 if (NULL == prov->backend_new) continue;
01176
01177 session->backend = (*(prov->backend_new))();
01178 session->backend->provider = prov;
01179 if (session->backend->session_begin)
01180 {
01181
01182
01183
01184 g_free(session->book_id);
01185 session->book_id = NULL;
01186 (session->backend->session_begin)(session->backend, session,
01187 book_id, TRUE, TRUE);
01188 PINFO("Done running session_begin on changed backend");
01189 err = qof_backend_get_error(session->backend);
01190 msg = qof_backend_get_message(session->backend);
01191 if (err != ERR_BACKEND_NO_ERR)
01192 {
01193 g_free(session->book_id);
01194 session->book_id = NULL;
01195 qof_session_push_error (session, err, msg);
01196 LEAVE("changed backend error %d", err);
01197 return;
01198 }
01199 if (msg != NULL)
01200 {
01201 PWARN("%s", msg);
01202 g_free(msg);
01203 }
01204 }
01205
01206 for (node=session->books; node; node=node->next)
01207 {
01208 book = node->data;
01209 qof_book_set_backend (book, session->backend);
01210 }
01211 p = NULL;
01212 }
01213 if(p) {
01214 p = p->next;
01215 }
01216 }
01217 if(!session->backend)
01218 {
01219 msg = g_strdup_printf("failed to load backend");
01220 qof_session_push_error(session, ERR_BACKEND_NO_HANDLER, msg);
01221 return;
01222 }
01223 }
01224
01225
01226
01227
01228
01229
01230
01231
01232
01233 be = session->backend;
01234 if (be)
01235 {
01236 for (node = session->books; node; node=node->next)
01237 {
01238 abook = node->data;
01239
01240 qof_book_set_backend (abook, be);
01241 be->percentage = percentage_func;
01242 if (be->sync)
01243 {
01244 (be->sync)(be, abook);
01245 if (save_error_handler(be, session)) return;
01246 }
01247 }
01248
01249
01250
01251 qof_session_clear_error (session);
01252 LEAVE("Success");
01253 return;
01254 }
01255 else
01256 {
01257 msg = g_strdup_printf("failed to load backend");
01258 qof_session_push_error(session, ERR_BACKEND_NO_HANDLER, msg);
01259 }
01260 LEAVE("error -- No backend!");
01261 }
01262
01263
01264
01265 void
01266 qof_session_end (QofSession *session)
01267 {
01268 if (!session) return;
01269
01270 ENTER ("sess=%p book_id=%s", session, session->book_id
01271 ? session->book_id : "(null)");
01272
01273
01274 if (session->backend && session->backend->session_end)
01275 {
01276 (session->backend->session_end)(session->backend);
01277 }
01278
01279 qof_session_clear_error (session);
01280
01281 g_free (session->book_id);
01282 session->book_id = NULL;
01283
01284 LEAVE ("sess=%p book_id=%s", session, session->book_id
01285 ? session->book_id : "(null)");
01286 }
01287
01288 void
01289 qof_session_destroy (QofSession *session)
01290 {
01291 GList *node;
01292 if (!session) return;
01293
01294 ENTER ("sess=%p book_id=%s", session, session->book_id
01295 ? session->book_id : "(null)");
01296
01297 qof_session_end (session);
01298
01299
01300 qof_session_destroy_backend(session);
01301
01302 for (node = session->books; node; node = node->next)
01303 {
01304 QofBook *book = node->data;
01305 qof_book_set_backend (book, NULL);
01306 qof_book_destroy (book);
01307 }
01308
01309 session->books = NULL;
01310 if (session == current_session)
01311 current_session = NULL;
01312
01313 g_free (session);
01314
01315 LEAVE ("sess=%p", session);
01316 }
01317
01318
01319
01320
01321 void
01322 qof_session_swap_data (QofSession *session_1, QofSession *session_2)
01323 {
01324 GList *books_1, *books_2, *node;
01325
01326 if (session_1 == session_2) return;
01327 if (!session_1 || !session_2) return;
01328
01329 ENTER ("sess1=%p sess2=%p", session_1, session_2);
01330
01331 books_1 = session_1->books;
01332 books_2 = session_2->books;
01333
01334 session_1->books = books_2;
01335 session_2->books = books_1;
01336
01337 for (node=books_1; node; node=node->next)
01338 {
01339 QofBook *book_1 = node->data;
01340 qof_book_set_backend (book_1, session_2->backend);
01341 }
01342 for (node=books_2; node; node=node->next)
01343 {
01344 QofBook *book_2 = node->data;
01345 qof_book_set_backend (book_2, session_1->backend);
01346 }
01347
01348 LEAVE (" ");
01349 }
01350
01351
01352
01353 gboolean
01354 qof_session_events_pending (QofSession *session)
01355 {
01356 if (!session) return FALSE;
01357 if (!session->backend) return FALSE;
01358 if (!session->backend->events_pending) return FALSE;
01359
01360 return session->backend->events_pending (session->backend);
01361 }
01362
01363 gboolean
01364 qof_session_process_events (QofSession *session)
01365 {
01366 if (!session) return FALSE;
01367 if (!session->backend) return FALSE;
01368 if (!session->backend->process_events) return FALSE;
01369
01370 return session->backend->process_events (session->backend);
01371 }
01372
01373