HISTORY: Created by Linas Vepstas December 1998
Copyright (c) 2000 Dave Peticolas
Copyright (c) 2005 Neil Williams <linux@codehelp.co.uk>
Definition in file qofsession.c.
#include "config.h"
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <glib.h>
#include "qof.h"
#include "qofbackend-p.h"
#include "qofbook-p.h"
#include "qofsession-p.h"
#include "qofobject-p.h"
Go to the source code of this file.
Data Structures | |
struct | qof_entity_copy_data |
struct | recurse_s |
struct | backend_providers |
Typedefs | |
typedef qof_entity_copy_data | QofEntityCopyData |
Functions | |
void | qof_backend_register_provider (QofBackendProvider *prov) |
void | qof_session_add_close_hook (GFunc fn, gpointer data) |
void | qof_session_call_close_hooks (QofSession *session) |
static void | qof_session_clear_error (QofSession *session) |
void | qof_session_push_error (QofSession *session, QofBackendError err, const char *message) |
QofBackendError | qof_session_get_error (QofSession *session) |
static const char * | get_default_error_message (QofBackendError err) |
const char * | qof_session_get_error_message (QofSession *session) |
QofBackendError | qof_session_pop_error (QofSession *session) |
static void | qof_session_init (QofSession *session) |
QofSession * | qof_session_new (void) |
QofSession * | qof_session_get_current_session (void) |
void | qof_session_set_current_session (QofSession *session) |
QofBook * | qof_session_get_book (QofSession *session) |
void | qof_session_add_book (QofSession *session, QofBook *addbook) |
QofBackend * | qof_session_get_backend (QofSession *session) |
const char * | qof_session_get_file_path (QofSession *session) |
const char * | qof_session_get_url (QofSession *session) |
static void | qof_book_set_partial (QofBook *book) |
void | qof_session_update_reference_list (QofSession *session, QofEntityReference *reference) |
Adds a new reference to the partial book data hash. | |
static void | qof_entity_param_cb (QofParam *param, gpointer data) |
static void | col_ref_cb (QofEntity *ref_ent, gpointer user_data) |
static void | qof_entity_foreach_copy (gpointer data, gpointer user_data) |
static gboolean | qof_entity_guid_match (QofSession *new_session, QofEntity *original) |
static void | qof_entity_list_foreach (gpointer data, gpointer user_data) |
static void | qof_entity_coll_foreach (QofEntity *original, gpointer user_data) |
static void | qof_entity_coll_copy (QofEntity *original, gpointer user_data) |
gboolean | qof_entity_copy_to_session (QofSession *new_session, QofEntity *original) |
Copy a single QofEntity to another session. | |
gboolean | qof_entity_copy_list (QofSession *new_session, GList *entity_list) |
Copy a GList of entities to another session. | |
gboolean | qof_entity_copy_coll (QofSession *new_session, QofCollection *entity_coll) |
Copy a QofCollection of entities. | |
static void | recurse_collection_cb (QofEntity *ent, gpointer user_data) |
static void | recurse_ent_cb (QofEntity *ent, gpointer user_data) |
gboolean | qof_entity_copy_coll_r (QofSession *new_session, QofCollection *coll) |
Recursively copy a collection of entities to a session. | |
gboolean | qof_entity_copy_one_r (QofSession *new_session, QofEntity *ent) |
Recursively copy a single entity to a new session. | |
static void | qof_session_load_backend (QofSession *session, char *access_method) |
static void | qof_session_destroy_backend (QofSession *session) |
void | qof_session_begin (QofSession *session, const char *book_id, gboolean ignore_lock, gboolean create_if_nonexistent) |
void | qof_session_load (QofSession *session, QofPercentageFunc percentage_func) |
gboolean | qof_session_save_may_clobber_data (QofSession *session) |
static gboolean | save_error_handler (QofBackend *be, QofSession *session) |
void | qof_session_save (QofSession *session, QofPercentageFunc percentage_func) |
void | qof_session_end (QofSession *session) |
void | qof_session_destroy (QofSession *session) |
void | qof_session_swap_data (QofSession *session_1, QofSession *session_2) |
gboolean | qof_session_events_pending (QofSession *session) |
gboolean | qof_session_process_events (QofSession *session) |
Variables | |
static QofSession * | current_session = NULL |
static GHookList * | session_closed_hooks = NULL |
static QofLogModule | log_module = "qof-session" |
static GSList * | provider_list = NULL |
backend_providers | backend_list [] |
|
Copy a QofCollection of entities. The QofBook in the new_session must not contain any entities with the same GUID as any entities in the collection - there is no support for handling collisions - instead, use Merging QofBook structures
Definition at line 706 of file qofsession.c. 00708 { 00709 struct recurse_s *store; 00710 00711 if(user_data == NULL) { return; } 00712 store = (struct recurse_s*)user_data; 00713 if(!ent || !store) { return; } 00714 store->success = qof_entity_copy_to_session(store->session, ent); 00715 if(store->success) { 00716 store->ent_list = g_list_append(store->ent_list, ent); 00717 } 00718 } 00719 00720 static void 00721 recurse_ent_cb(QofEntity *ent, gpointer user_data) 00722 { 00723 GList *ref_list, *i, *j, *ent_list, *child_list;
|
|
Recursively copy a collection of entities to a session.
Objects can be defined solely in terms of QOF data types or as a mix of data types and other objects, which may in turn include other objects. These references can be copied recursively down to the third level. See QofEntityReference.
Definition at line 855 of file qofsession.c. 00856 { QOF_LIB_DIR, "libqof_backend_dwi", "dwiend_provider_init" }, 00857 #endif 00858 { NULL, NULL, NULL } 00859 }; 00860 00861 static void 00862 qof_session_load_backend(QofSession * session, char * access_method) 00863 { 00864 GSList *p; 00865 GList *node; 00866 QofBackendProvider *prov; 00867 QofBook *book; 00868 char *msg; 00869 gint num;
|
|
Copy a GList of entities to another session. The QofBook in the new_session must not contain any entities with the same GUID as any of the source entities - there is no support for handling collisions, instead use Merging QofBook structures Note that the GList (e.g. from qof_sql_query_run) can contain QofEntity pointers of any QofIdType, in any sequence. As long as all members of the list are QofEntity*, and all GUID's are unique, the list can be copied.
Definition at line 683 of file qofsession.c. 00684 { return FALSE; } 00685 qof_event_suspend(); 00686 qecd.param_list = NULL; 00687 qecd.new_session = new_session; 00688 qof_book_set_partial(qof_session_get_book(qecd.new_session)); 00689 qof_collection_foreach(entity_coll, qof_entity_coll_foreach, &qecd); 00690 qof_class_param_foreach(qof_collection_get_type(entity_coll), 00691 qof_entity_param_cb, &qecd); 00692 qof_collection_foreach(entity_coll, qof_entity_coll_copy, &qecd); 00693 if(qecd.param_list != NULL) { g_slist_free(qecd.param_list); } 00694 qof_event_resume(); 00695 return TRUE; 00696 } 00697 00698 struct recurse_s 00699 { 00700 QofSession *session; 00701 gboolean success; 00702 GList *ref_list; 00703 GList *ent_list;
|
|
Recursively copy a single entity to a new session. Copy the single entity and all referenced entities to the second level. Only entities that are directly referenced by the top level entity are copied. This is a deep copy - all parameters of all referenced entities are copied. If the top level entity has no references, this is identical to qof_entity_copy_to_session.
Definition at line 871 of file qofsession.c. 00876 { 00877 for (num = 0; backend_list[num].filename != NULL; num++) { 00878 if(!qof_load_backend_library(backend_list[num].libdir, 00879 backend_list[num].filename, backend_list[num].init_fcn)) 00880 { 00881 PWARN (" failed to load %s from %s using %s", 00882 backend_list[num].filename, backend_list[num].libdir, 00883 backend_list[num].init_fcn); 00884 } 00885 } 00886 } 00887 p = g_slist_copy(provider_list); 00888 while(p != NULL)
|
|
Copy a single QofEntity to another session. Checks first that no entity in the session book contains the GUID of the source entity.
Definition at line 655 of file qofsession.c. 00657 { 00658 QofEntityCopyData *qecd; 00659 00660 if(!new_session || !entity_list) { return FALSE; } 00661 ENTER (" list=%d", g_list_length(entity_list)); 00662 qecd = g_new0(QofEntityCopyData, 1); 00663 qof_event_suspend(); 00664 qecd->param_list = NULL; 00665 qecd->new_session = new_session; 00666 qof_book_set_partial(qof_session_get_book(new_session)); 00667 g_list_foreach(entity_list, qof_entity_list_foreach, qecd); 00668 qof_event_resume(); 00669 if(qecd->error) 00670 { 00671 PWARN (" some/all entities in the list could not be copied."); 00672 } 00673 g_free(qecd); 00674 LEAVE (" "); 00675 return TRUE; 00676 } 00677 00678 gboolean 00679 qof_entity_copy_coll(QofSession *new_session, QofCollection *entity_coll) 00680 { 00681 QofEntityCopyData qecd;
|
|
< secondary collections are used for one-to-many references between entities and are implemented using QofCollection. These are NOT the same as the main collections in the QofBook.
QOF_TYPE_COLLECT has two functions, both related to one-to-many links:
If the set function can handle it, it could also be used for true one-to-many links: one object linked to many entities of many types. n.b. Always subject to each collection holding only one type at runtime. (otherwise use books). Definition at line 386 of file qofsession.c. 00387 { 00388 QofEntity *importEnt, *targetEnt/*, *referenceEnt*/; 00389 QofEntityCopyData *context; 00390 QofEntityReference *reference; 00391 gboolean registered_type; 00392 /* cm_ prefix used for variables that hold the data to commit */ 00393 QofParam *cm_param; 00394 gchar *cm_string, *cm_char; 00395 const GUID *cm_guid; 00396 KvpFrame *cm_kvp; 00397 QofCollection *cm_col; 00398 /* function pointers and variables for parameter getters that don't use pointers normally */ 00399 gnc_numeric cm_numeric, (*numeric_getter) (QofEntity*, QofParam*); 00400 double cm_double, (*double_getter) (QofEntity*, QofParam*); 00401 gboolean cm_boolean, (*boolean_getter) (QofEntity*, QofParam*); 00402 gint32 cm_i32, (*int32_getter) (QofEntity*, QofParam*); 00403 gint64 cm_i64, (*int64_getter) (QofEntity*, QofParam*); 00404 Timespec cm_date, (*date_getter) (QofEntity*, QofParam*); 00405 /* function pointers to the parameter setters */ 00406 void (*string_setter) (QofEntity*, const char*); 00407 void (*date_setter) (QofEntity*, Timespec); 00408 void (*numeric_setter) (QofEntity*, gnc_numeric); 00409 void (*guid_setter) (QofEntity*, const GUID*); 00410 void (*double_setter) (QofEntity*, double); 00411 void (*boolean_setter) (QofEntity*, gboolean); 00412 void (*i32_setter) (QofEntity*, gint32); 00413 void (*i64_setter) (QofEntity*, gint64); 00414 void (*char_setter) (QofEntity*, char*); 00415 void (*kvp_frame_setter) (QofEntity*, KvpFrame*); 00416 00417 g_return_if_fail(user_data != NULL); 00418 context = (QofEntityCopyData*) user_data; 00419 cm_date.tv_nsec = 0; 00420 cm_date.tv_sec = 0; 00421 importEnt = context->from; 00422 targetEnt = context->to; 00423 registered_type = FALSE; 00424 cm_param = (QofParam*) data; 00425 g_return_if_fail(cm_param != NULL); 00426 context->param = cm_param; 00427 if(safe_strcmp(cm_param->param_type, QOF_TYPE_STRING) == 0) { 00428 cm_string = (gchar*)cm_param->param_getfcn(importEnt, cm_param); 00429 if(cm_string) { 00430 string_setter = (void(*)(QofEntity*, const char*))cm_param->param_setfcn; 00431 if(string_setter != NULL) { string_setter(targetEnt, cm_string); } 00432 } 00433 registered_type = TRUE; 00434 } 00435 if(safe_strcmp(cm_param->param_type, QOF_TYPE_DATE) == 0) { 00436 date_getter = (Timespec (*)(QofEntity*, QofParam*))cm_param->param_getfcn; 00437 cm_date = date_getter(importEnt, cm_param); 00438 date_setter = (void(*)(QofEntity*, Timespec))cm_param->param_setfcn; 00439 if(date_setter != NULL) { date_setter(targetEnt, cm_date); } 00440 registered_type = TRUE; 00441 } 00442 if((safe_strcmp(cm_param->param_type, QOF_TYPE_NUMERIC) == 0) || 00443 (safe_strcmp(cm_param->param_type, QOF_TYPE_DEBCRED) == 0)) { 00444 numeric_getter = (gnc_numeric (*)(QofEntity*, QofParam*))cm_param->param_getfcn; 00445 cm_numeric = numeric_getter(importEnt, cm_param); 00446 numeric_setter = (void(*)(QofEntity*, gnc_numeric))cm_param->param_setfcn; 00447 if(numeric_setter != NULL) { numeric_setter(targetEnt, cm_numeric); } 00448 registered_type = TRUE; 00449 } 00450 if(safe_strcmp(cm_param->param_type, QOF_TYPE_GUID) == 0) { 00451 cm_guid = (const GUID*)cm_param->param_getfcn(importEnt, cm_param); 00452 guid_setter = (void(*)(QofEntity*, const GUID*))cm_param->param_setfcn; 00453 if(guid_setter != NULL) { guid_setter(targetEnt, cm_guid); } 00454 registered_type = TRUE; 00455 } 00456 if(safe_strcmp(cm_param->param_type, QOF_TYPE_INT32) == 0) { 00457 int32_getter = (gint32 (*)(QofEntity*, QofParam*)) cm_param->param_getfcn; 00458 cm_i32 = int32_getter(importEnt, cm_param); 00459 i32_setter = (void(*)(QofEntity*, gint32))cm_param->param_setfcn; 00460 if(i32_setter != NULL) { i32_setter(targetEnt, cm_i32); } 00461 registered_type = TRUE; 00462 } 00463 if(safe_strcmp(cm_param->param_type, QOF_TYPE_INT64) == 0) { 00464 int64_getter = (gint64 (*)(QofEntity*, QofParam*)) cm_param->param_getfcn; 00465 cm_i64 = int64_getter(importEnt, cm_param); 00466 i64_setter = (void(*)(QofEntity*, gint64))cm_param->param_setfcn; 00467 if(i64_setter != NULL) { i64_setter(targetEnt, cm_i64); } 00468 registered_type = TRUE; 00469 } 00470 if(safe_strcmp(cm_param->param_type, QOF_TYPE_DOUBLE) == 0) { 00471 double_getter = (double (*)(QofEntity*, QofParam*)) cm_param->param_getfcn; 00472 cm_double = double_getter(importEnt, cm_param); 00473 double_setter = (void(*)(QofEntity*, double))cm_param->param_setfcn; 00474 if(double_setter != NULL) { double_setter(targetEnt, cm_double); } 00475 registered_type = TRUE; 00476 } 00477 if(safe_strcmp(cm_param->param_type, QOF_TYPE_BOOLEAN) == 0){ 00478 boolean_getter = (gboolean (*)(QofEntity*, QofParam*)) cm_param->param_getfcn; 00479 cm_boolean = boolean_getter(importEnt, cm_param); 00480 boolean_setter = (void(*)(QofEntity*, gboolean))cm_param->param_setfcn; 00481 if(boolean_setter != NULL) { boolean_setter(targetEnt, cm_boolean); } 00482 registered_type = TRUE; 00483 } 00484 if(safe_strcmp(cm_param->param_type, QOF_TYPE_KVP) == 0) { 00485 cm_kvp = (KvpFrame*)cm_param->param_getfcn(importEnt,cm_param); 00486 kvp_frame_setter = (void(*)(QofEntity*, KvpFrame*))cm_param->param_setfcn; 00487 if(kvp_frame_setter != NULL) { kvp_frame_setter(targetEnt, cm_kvp); } 00488 else 00489 { 00490 QofInstance *target_inst; 00491 00492 target_inst = (QofInstance*)targetEnt; 00493 kvp_frame_delete(target_inst->kvp_data); 00494 target_inst->kvp_data = kvp_frame_copy(cm_kvp); 00495 } 00496 registered_type = TRUE; 00497 } 00498 if(safe_strcmp(cm_param->param_type, QOF_TYPE_CHAR) == 0) { 00499 cm_char = (gchar*)cm_param->param_getfcn(importEnt,cm_param); 00500 char_setter = (void(*)(QofEntity*, char*))cm_param->param_setfcn; 00501 if(char_setter != NULL) { char_setter(targetEnt, cm_char); } 00502 registered_type = TRUE; 00503 } 00504 if(safe_strcmp(cm_param->param_type, QOF_TYPE_COLLECT) == 0) { 00505 cm_col = (QofCollection*)cm_param->param_getfcn(importEnt, cm_param); 00506 if(cm_col) 00507 { 00508 /* create one reference for each member of the collection. */ 00509 qof_collection_foreach(cm_col, col_ref_cb, context); 00510 } 00511 registered_type = TRUE; 00512 } 00513 if(registered_type == FALSE) { 00514 /* referenceEnt = (QofEntity*)cm_param->param_getfcn(importEnt, cm_param); 00515 if(!referenceEnt) { return; } 00516 if(!referenceEnt->e_type) { return; }*/ 00517 reference = qof_entity_get_reference_from(importEnt, cm_param); 00518 if(reference) { 00519 qof_session_update_reference_list(context->new_session, reference); 00520 } 00521 } 00522 } 00523 00524 static gboolean 00525 qof_entity_guid_match(QofSession *new_session, QofEntity *original) 00526 { 00527 QofEntity *copy; 00528 const GUID *g; 00529 QofIdTypeConst type; 00530 QofBook *targetBook; 00531 QofCollection *coll; 00532 00533 copy = NULL; 00534 g_return_val_if_fail(original != NULL, FALSE); 00535 targetBook = qof_session_get_book(new_session); 00536 g_return_val_if_fail(targetBook != NULL, FALSE); 00537 g = qof_entity_get_guid(original); 00538 type = g_strdup(original->e_type); 00539 coll = qof_book_get_collection(targetBook, type); 00540 copy = qof_collection_lookup_entity(coll, g); 00541 if(copy) { return TRUE; } 00542 return FALSE; 00543 } 00544 00545 static void 00546 qof_entity_list_foreach(gpointer data, gpointer user_data) 00547 { 00548 QofEntityCopyData *qecd; 00549 QofEntity *original;
|
|
The qof_session_add_book() allows additional books to be added to a session. XXX Under construction, clarify the following when done: XXX There must already be an open book in the session already!? XXX Only one open book at a time per session is allowed!? XXX each book gets its own unique backend ??? Definition at line 248 of file qofsession.c. 00249 { 00250 GList *node; 00251 if (!session) return; 00252 00253 ENTER (" sess=%p book=%p", session, addbook); 00254 00255 /* See if this book is already there ... */ 00256 for (node=session->books; node; node=node->next) 00257 { 00258 QofBook *book = node->data; 00259 if (addbook == book) return; 00260 } 00261 00262 if ('y' == addbook->book_open) 00263 { 00264 /* hack alert -- someone should free all the books in the list, 00265 * but it should probably not be us ... since the books backends 00266 * should be shutdown first, etc */ 00267 /* XXX this should probably be an error XXX */ 00268 g_list_free (session->books); 00269 session->books = g_list_append (NULL, addbook); 00270 } 00271 else 00272 { 00273 /* XXX Need to tell the backend to add a book as well */ 00274 session->books = g_list_append (session->books, addbook); 00275 } 00276 00277 qof_book_set_backend (addbook, session->backend); 00278 LEAVE (" "); 00279 }
|
|
Register a function to be called just before a session is closed.
Definition at line 69 of file qofsession.c. 00070 { 00071 GHook *hook; 00072 00073 if (session_closed_hooks == NULL) { 00074 session_closed_hooks = malloc(sizeof(GHookList)); /* LEAKED */ 00075 g_hook_list_init (session_closed_hooks, sizeof(GHook)); 00076 } 00077 00078 hook = g_hook_alloc(session_closed_hooks); 00079 if (!hook) 00080 return; 00081 00082 hook->func = (GHookFunc)fn; 00083 hook->data = data; 00084 g_hook_append(session_closed_hooks, hook); 00085 }
|
|
Call all registered session close hooks, informing them that the specified session is about to be closed.
Definition at line 88 of file qofsession.c. 00089 { 00090 GHook *hook; 00091 GFunc fn; 00092 00093 if (session_closed_hooks == NULL) 00094 return; 00095 00096 hook = g_hook_first_valid (session_closed_hooks, FALSE); 00097 while (hook) { 00098 fn = (GFunc)hook->func; 00099 fn(session, hook->data); 00100 hook = g_hook_next_valid (session_closed_hooks, hook, FALSE); 00101 } 00102 }
|
|
The qof_session_end() method will release the session lock. For the file backend, it will *not* save the data to a file. Thus, this method acts as an "abort" or "rollback" primitive. However, for other backends, such as the sql backend, the data would have been written out before this, and so this routines wouldn't roll-back anything; it would just shut the connection. Definition at line 1368 of file qofsession.c. 01371 { 01372 GList *books_1, *books_2, *node; 01373 01374 if (session_1 == session_2) return; 01375 if (!session_1 || !session_2) return; 01376 01377 ENTER ("sess1=%p sess2=%p", session_1, session_2); 01378 01379 books_1 = session_1->books; 01380 books_2 = session_2->books; 01381 01382 session_1->books = books_2; 01383 session_2->books = books_1; 01384 01385 for (node=books_1; node; node=node->next) 01386 { 01387 QofBook *book_1 = node->data; 01388 qof_book_set_backend (book_1, session_2->backend);
|
|
The qof_session_events_pending() method will return TRUE if the backend has pending events which must be processed to bring the engine up to date with the backend. Definition at line 1456 of file qofsession.c. |
|
The qof_session_get_error() routine can be used to obtain the reason for any failure. Calling this routine returns the current error. Definition at line 139 of file qofsession.c. 00140 { 00141 QofBackendError err; 00142 00143 if (!session) return ERR_BACKEND_NO_BACKEND; 00144 00145 /* if we have a local error, return that. */ 00146 if (ERR_BACKEND_NO_ERR != session->last_err) 00147 { 00148 return session->last_err; 00149 } 00150 00151 /* maybe we should return a no-backend error ??? */ 00152 if (! session->backend) return ERR_BACKEND_NO_ERR; 00153 00154 err = qof_backend_get_error (session->backend); 00155 session->last_err = err; 00156 return err; 00157 }
|
|
The qof_session_get_file_path() routine returns the fully-qualified file path for the session. That is, if a relative or partial filename was for the session, then it had to have been fully resolved to open the session. This routine returns the result of this resolution. The path is always guaranteed to reside in the local file system, even if the session itself was opened as a URL. (currently, the filepath is derived from the url by substituting commas for slashes). The qof_session_get_url() routine returns the url that was opened. URL's for local files take the form of file:/some/where/some/file.gml Definition at line 289 of file qofsession.c. 00290 { 00291 if (!session) return NULL; 00292 if (!session->backend) return NULL; 00293 return session->backend->fullpath; 00294 }
|
|
The qof_session_pop_error() routine can be used to obtain the reason for any failure. Calling this routine resets the error value. This routine allows an implementation of multiple error values, e.g. in a stack, where this routine pops the top value. The current implementation has a stack that is one-deep. See qofbackend.h for a listing of returned errors. Definition at line 175 of file qofsession.c. 00176 { 00177 QofBackendError err; 00178 00179 if (!session) return ERR_BACKEND_NO_BACKEND; 00180 00181 err = qof_session_get_error(session); 00182 qof_session_clear_error(session); 00183 00184 return err; 00185 }
|
|
The qof_session_process_events() method will process any events indicated by the qof_session_events_pending() method. It returns TRUE if the engine was modified while engine events were suspended. Definition at line 1466 of file qofsession.c. |
|
Definition at line 1221 of file qofsession.c. 01222 {*/ 01223 if (NULL == prov->backend_new) continue; 01224 /* Use the providers creation callback */ 01225 session->backend = (*(prov->backend_new))(); 01226 session->backend->provider = prov; 01227 if (session->backend->session_begin) 01228 { 01229 /* Call begin - backend has been changed, 01230 so make sure a file can be written, 01231 use ignore_lock and create_if_nonexistent */ 01232 g_free(session->book_id); 01233 session->book_id = NULL; 01234 (session->backend->session_begin)(session->backend, session, 01235 book_id, TRUE, TRUE); 01236 PINFO("Done running session_begin on changed backend"); 01237 err = qof_backend_get_error(session->backend); 01238 msg = qof_backend_get_message(session->backend); 01239 if (err != ERR_BACKEND_NO_ERR) 01240 { 01241 g_free(session->book_id); 01242 session->book_id = NULL; 01243 qof_session_push_error (session, err, msg); 01244 LEAVE("changed backend error %d", err); 01245 return; 01246 } 01247 if (msg != NULL) 01248 { 01249 PWARN("%s", msg); 01250 g_free(msg); 01251 } 01252 } 01253 /* Tell the books about the backend that they'll be using. */ 01254 for (node=session->books; node; node=node->next) 01255 { 01256 book = node->data; 01257 qof_book_set_backend (book, session->backend); 01258 } 01259 p = NULL; 01260 } 01261 if(p) { 01262 p = p->next; 01263 } 01264 } 01265 if(!session->backend) 01266 { 01267 msg = g_strdup_printf("failed to load backend"); 01268 qof_session_push_error(session, ERR_BACKEND_NO_HANDLER, msg); 01269 return; 01270 } 01271 } 01272 /* If there is a backend, and the backend is reachable 01273 * (i.e. we can communicate with it), then synchronize with 01274 * the backend. If we cannot contact the backend (e.g. 01275 * because we've gone offline, the network has crashed, etc.) 01276 * then give the user the option to save to the local disk. 01277 * 01278 * hack alert -- FIXME -- XXX the code below no longer 01279 * does what the words above say. This needs fixing. 01280 */ 01281 be = session->backend; 01282 if (be) 01283 { 01284 for (node = session->books; node; node=node->next) 01285 { 01286 abook = node->data; 01287 /* if invoked as SaveAs(), then backend not yet set */ 01288 qof_book_set_backend (abook, be); 01289 be->percentage = percentage_func; 01290 if (be->sync) 01291 { 01292 (be->sync)(be, abook); 01293 if (save_error_handler(be, session)) return; 01294 } 01295 } 01296 /* If we got to here, then the backend saved everything 01297 * just fine, and we are done. So return. */ 01298 /* Return the book_id to previous value. */ 01299 qof_session_clear_error (session); 01300 LEAVE("Success"); 01301 return; 01302 } 01303 else 01304 { 01305 msg = g_strdup_printf("failed to load backend"); 01306 qof_session_push_error(session, ERR_BACKEND_NO_HANDLER, msg); 01307 } 01308 LEAVE("error -- No backend!"); 01309 } 01310 01311 /* ====================================================================== */ 01312 01313 void 01314 qof_session_end (QofSession *session) 01315 { 01316 if (!session) return; 01317 01318 ENTER ("sess=%p book_id=%s", session, session->book_id 01319 ? session->book_id : "(null)"); 01320 01321 /* close down the backend first */ 01322 if (session->backend && session->backend->session_end) 01323 { 01324 (session->backend->session_end)(session->backend); 01325 } 01326 01327 qof_session_clear_error (session); 01328 01329 g_free (session->book_id); 01330 session->book_id = NULL; 01331 01332 LEAVE ("sess=%p book_id=%s", session, session->book_id 01333 ? session->book_id : "(null)"); 01334 } 01335 01336 void 01337 qof_session_destroy (QofSession *session) 01338 { 01339 GList *node; 01340 if (!session) return; 01341 01342 ENTER ("sess=%p book_id=%s", session, session->book_id 01343 ? session->book_id : "(null)"); 01344 01345 qof_session_end (session); 01346 01347 /* destroy the backend */ 01348 qof_session_destroy_backend(session); 01349 01350 for (node = session->books; node; node = node->next) 01351 { 01352 QofBook *book = node->data; 01353 qof_book_set_backend (book, NULL); 01354 qof_book_destroy (book); 01355 } 01356 01357 session->books = NULL; 01358 if (session == current_session) 01359 current_session = NULL; 01360 01361 g_free (session); 01362 01363 LEAVE ("sess=%p", session);
|
|
Allows the backend to warn the user if a dataset already exists. Definition at line 1197 of file qofsession.c. 01198 { change_backend = TRUE; } 01199 } 01200 /* If provider is undefined, assume partial not supported. */ 01201 else { change_backend = TRUE; } 01202 } 01203 if(change_backend == TRUE) 01204 {
|
|
Adds a new reference to the partial book data hash. Retrieves any existing reference list and appends the new reference. If the book is not already marked as partial, it will be marked as partial. Definition at line 328 of file qofsession.c. 00329 { 00330 QofBook *book; 00331 GList *book_ref_list; 00332 00333 book = qof_session_get_book(session); 00334 book_ref_list = (GList*)qof_book_get_data(book, ENTITYREFERENCE); 00335 book_ref_list = g_list_append(book_ref_list, reference); 00336 qof_book_set_data(book, ENTITYREFERENCE, book_ref_list); 00337 qof_book_set_partial(book); 00338 }
|
|
< secondary collections are used for one-to-many references between entities and are implemented using QofCollection. These are NOT the same as the main collections in the QofBook.
QOF_TYPE_COLLECT has two functions, both related to one-to-many links:
If the set function can handle it, it could also be used for true one-to-many links: one object linked to many entities of many types. n.b. Always subject to each collection holding only one type at runtime. (otherwise use books). Definition at line 748 of file qofsession.c. 00751 { 00752 qof_collection_foreach(col, recurse_collection_cb, store); 00753 } 00754 continue; 00755 } 00756 ref_ent = (QofEntity*)ref_param->param_getfcn(ent, ref_param); 00757 if((ref_ent)&&(ref_ent->e_type)) 00758 { 00759 store->success = qof_entity_copy_to_session(session, ref_ent); 00760 if(store->success) { ent_list = g_list_append(ent_list, ref_ent); } 00761 } 00762 } 00763 for(i = ent_list; i != NULL; i = i->next) 00764 { 00765 if(i->data == NULL) { continue; } 00766 child_ent = (QofEntity*)i->data; 00767 if(child_ent == NULL) { continue; } 00768 ref_list = qof_class_get_referenceList(child_ent->e_type); 00769 for(j = ref_list; j != NULL; j = j->next) 00770 { 00771 if(j->data == NULL) { continue; } 00772 ref_param = (QofParam*)j->data; 00773 ref_ent = ref_param->param_getfcn(child_ent, ref_param); 00774 if(ref_ent != NULL) 00775 { 00776 success = qof_entity_copy_to_session(session, ref_ent); 00777 if(success) { child_list = g_list_append(child_list, ref_ent); } 00778 } 00779 } 00780 } 00781 for(i = child_list; i != NULL; i = i->next) 00782 { 00783 if(i->data == NULL) { continue; } 00784 ref_ent = (QofEntity*)i->data; 00785 if(ref_ent == NULL) { continue; } 00786 ref_list = qof_class_get_referenceList(ref_ent->e_type); 00787 for(j = ref_list; j != NULL; j = j->next) 00788 { 00789 if(j->data == NULL) { continue; } 00790 ref_param = (QofParam*)j->data; 00791 child_ent = ref_param->param_getfcn(ref_ent, ref_param); 00792 if(child_ent != NULL) 00793 { 00794 qof_entity_copy_to_session(session, child_ent); 00795 } 00796 } 00797 } 00798 } 00799 00800 gboolean 00801 qof_entity_copy_coll_r(QofSession *new_session, QofCollection *coll) 00802 { 00803 struct recurse_s store; 00804 gboolean success; 00805 00806 if((!new_session)||(!coll)) { return FALSE; } 00807 store.session = new_session; 00808 success = TRUE; 00809 store.success = success; 00810 store.ent_list = NULL; 00811 store.ref_list = qof_class_get_referenceList(qof_collection_get_type(coll)); 00812 success = qof_entity_copy_coll(new_session, coll); 00813 if(success){ qof_collection_foreach(coll, recurse_ent_cb, &store); } 00814 return success; 00815 } 00816 00817 gboolean qof_entity_copy_one_r(QofSession *new_session, QofEntity *ent) 00818 { 00819 struct recurse_s store; 00820 QofCollection *coll; 00821 gboolean success; 00822 00823 if((!new_session)||(!ent)) { return FALSE; } 00824 store.session = new_session; 00825 success = TRUE; 00826 store.success = success; 00827 store.ref_list = qof_class_get_referenceList(ent->e_type); 00828 success = qof_entity_copy_to_session(new_session, ent); 00829 if(success == TRUE) { 00830 coll = qof_book_get_collection(qof_session_get_book(new_session), ent->e_type); 00831 if(coll) { qof_collection_foreach(coll, recurse_ent_cb, &store); } 00832 } 00833 return success; 00834 } 00835 00836 00837 /* ====================================================================== */ 00838 00842 struct backend_providers 00843 { 00844 const char *libdir; 00845 const char *filename; 00846 const char *init_fcn; 00847 }; 00848 00849 /* All available QOF backends need to be described here 00850 and the last entry must be three NULL's. 00851 Remember: Use the libdir from the current build environment 00852 and use JUST the module name without .so - .so is not portable! */
|
|
Initial value: { { "/usr/lib" , "libqof-backend-qsf" , "qsf_provider_init" }, { NULL, NULL, NULL } } Definition at line 907 of file qofsession.c. |
|
Definition at line 50 of file qofsession.c. |