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