QOF 0.7.5
|
00001 /********************************************************************\ 00002 * qofsesssion.c -- session access (connection to backend) * 00003 * * 00004 * This program is free software; you can redistribute it and/or * 00005 * modify it under the terms of the GNU General Public License as * 00006 * published by the Free Software Foundation; either version 2 of * 00007 * the License, or (at your option) any later version. * 00008 * * 00009 * This program is distributed in the hope that it will be useful, * 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00012 * GNU General Public License for more details. * 00013 * * 00014 * You should have received a copy of the GNU General Public License* 00015 * along with this program; if not, contact: * 00016 * * 00017 * Free Software Foundation Voice: +1-617-542-5942 * 00018 * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 * 00019 * Boston, MA 02110-1301, USA gnu@gnu.org * 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 #include <glib.h> 00042 #include <libintl.h> 00043 #include "qof.h" 00044 #include "qoferror-p.h" 00045 #include "qofbackend-p.h" 00046 #include "qofbook-p.h" 00047 #include "qofsession-p.h" 00048 #include "qofobject-p.h" 00049 00050 #define _(String) dgettext (GETTEXT_PACKAGE, String) 00051 00052 static GHookList *session_closed_hooks = NULL; 00053 static QofLogModule log_module = QOF_MOD_SESSION; 00054 static GSList *provider_list = NULL; 00055 00056 /* ============================================================= */ 00057 00058 void 00059 qof_backend_register_provider (QofBackendProvider * prov) 00060 { 00061 provider_list = g_slist_prepend (provider_list, prov); 00062 } 00063 00064 /* =========================================================== */ 00065 00066 /* hook routines */ 00067 00068 void 00069 qof_session_add_close_hook (GFunc fn, gpointer data) 00070 { 00071 GHook *hook; 00072 00073 if (session_closed_hooks == NULL) 00074 { 00075 session_closed_hooks = malloc (sizeof (GHookList)); /* LEAKED */ 00076 g_hook_list_init (session_closed_hooks, sizeof (GHook)); 00077 } 00078 00079 hook = g_hook_alloc (session_closed_hooks); 00080 if (!hook) 00081 return; 00082 00083 hook->func = (GHookFunc) fn; 00084 hook->data = data; 00085 g_hook_append (session_closed_hooks, hook); 00086 } 00087 00088 void 00089 qof_session_call_close_hooks (QofSession * session) 00090 { 00091 GHook *hook; 00092 GFunc fn; 00093 00094 if (session_closed_hooks == NULL) 00095 return; 00096 00097 hook = g_hook_first_valid (session_closed_hooks, FALSE); 00098 while (hook) 00099 { 00100 fn = (GFunc) hook->func; 00101 fn (session, hook->data); 00102 hook = g_hook_next_valid (session_closed_hooks, hook, FALSE); 00103 } 00104 } 00105 00106 /* =============================================================== */ 00107 00108 static void 00109 qof_session_init (QofSession * session) 00110 { 00111 if (!session) 00112 return; 00113 00114 #ifndef QOF_DISABLE_DEPRECATED 00115 session->entity.e_type = QOF_ID_SESSION; 00116 #endif 00117 session->books = g_list_append (NULL, qof_book_new ()); 00118 session->book_id = NULL; 00119 session->backend = NULL; 00120 qof_error_init (); 00121 } 00122 00123 QofSession * 00124 qof_session_new (void) 00125 { 00126 QofSession *session = g_new0 (QofSession, 1); 00127 qof_session_init (session); 00128 return session; 00129 } 00130 00131 QofBook * 00132 qof_session_get_book (QofSession * session) 00133 { 00134 GList *node; 00135 if (!session) 00136 return NULL; 00137 00138 for (node = session->books; node; node = node->next) 00139 { 00140 QofBook *book = node->data; 00141 if ('y' == book->book_open) 00142 return book; 00143 } 00144 return NULL; 00145 } 00146 00147 void 00148 qof_session_add_book (QofSession * session, QofBook * addbook) 00149 { 00150 GList *node; 00151 if (!session) 00152 return; 00153 00154 ENTER (" sess=%p book=%p", session, addbook); 00155 00156 /* See if this book is already there ... */ 00157 for (node = session->books; node; node = node->next) 00158 { 00159 QofBook *book = node->data; 00160 if (addbook == book) 00161 return; 00162 } 00163 00164 if ('y' == addbook->book_open) 00165 { 00166 /* hack alert -- someone should free all the books in the list, 00167 * but it should probably not be us ... since the books backends 00168 * should be shutdown first, etc */ 00169 /* XXX this should probably be an error XXX */ 00170 g_list_free (session->books); 00171 session->books = g_list_append (NULL, addbook); 00172 } 00173 else 00174 { 00175 /* XXX Need to tell the backend to add a book as well */ 00176 session->books = g_list_append (session->books, addbook); 00177 } 00178 00179 qof_book_set_backend (addbook, session->backend); 00180 LEAVE (" "); 00181 } 00182 00183 QofBackend * 00184 qof_session_get_backend (QofSession * session) 00185 { 00186 if (!session) 00187 return NULL; 00188 return session->backend; 00189 } 00190 00191 const gchar * 00192 qof_session_get_file_path (QofSession * session) 00193 { 00194 if (!session) 00195 return NULL; 00196 if (!session->backend) 00197 return NULL; 00198 return session->backend->fullpath; 00199 } 00200 00201 const gchar * 00202 qof_session_get_url (QofSession * session) 00203 { 00204 if (!session) 00205 return NULL; 00206 return session->book_id; 00207 } 00208 00209 /* =============================================================== */ 00210 00211 typedef struct qof_entity_copy_data 00212 { 00213 QofEntity *from; 00214 QofEntity *to; 00215 QofParam *param; 00216 GList *referenceList; 00217 GSList *param_list; 00218 QofSession *new_session; 00219 gboolean error; 00220 } QofEntityCopyData; 00221 00222 static void 00223 qof_book_set_partial (QofBook * book) 00224 { 00225 gboolean partial; 00226 00227 partial = 00228 (gboolean) 00229 GPOINTER_TO_INT (qof_book_get_data (book, PARTIAL_QOFBOOK)); 00230 if (!partial) 00231 { 00232 qof_book_set_data (book, PARTIAL_QOFBOOK, GINT_TO_POINTER (TRUE)); 00233 } 00234 } 00235 00236 void 00237 qof_session_update_reference_list (QofSession * session, 00238 QofEntityReference * reference) 00239 { 00240 QofBook *book; 00241 GList *book_ref_list; 00242 00243 book = qof_session_get_book (session); 00244 book_ref_list = (GList *) qof_book_get_data (book, ENTITYREFERENCE); 00245 book_ref_list = g_list_append (book_ref_list, reference); 00246 qof_book_set_data (book, ENTITYREFERENCE, book_ref_list); 00247 qof_book_set_partial (book); 00248 } 00249 00250 static void 00251 qof_entity_param_cb (QofParam * param, gpointer data) 00252 { 00253 QofEntityCopyData *qecd; 00254 00255 g_return_if_fail (data != NULL); 00256 qecd = (QofEntityCopyData *) data; 00257 g_return_if_fail (param != NULL); 00258 /* KVP doesn't need a set routine to be copied. */ 00259 if (0 == safe_strcmp (param->param_type, QOF_TYPE_KVP)) 00260 { 00261 qecd->param_list = g_slist_prepend (qecd->param_list, param); 00262 return; 00263 } 00264 if ((param->param_getfcn != NULL) && (param->param_setfcn != NULL)) 00265 { 00266 qecd->param_list = g_slist_prepend (qecd->param_list, param); 00267 } 00268 } 00269 00270 static void 00271 col_ref_cb (QofEntity * ref_ent, gpointer user_data) 00272 { 00273 QofEntityReference *ref; 00274 QofEntityCopyData *qecd; 00275 QofEntity *ent; 00276 const GUID *cm_guid; 00277 gchar cm_sa[GUID_ENCODING_LENGTH + 1]; 00278 gchar *cm_string; 00279 00280 qecd = (QofEntityCopyData *) user_data; 00281 ent = qecd->from; 00282 ref = g_new0 (QofEntityReference, 1); 00283 ref->type = ent->e_type; 00284 ref->ref_guid = g_new (GUID, 1); 00285 ref->ent_guid = &ent->guid; 00286 ref->param = qof_class_get_parameter (ent->e_type, 00287 qecd->param->param_name); 00288 cm_guid = qof_entity_get_guid (ref_ent); 00289 guid_to_string_buff (cm_guid, cm_sa); 00290 cm_string = g_strdup (cm_sa); 00291 if (TRUE == string_to_guid (cm_string, ref->ref_guid)) 00292 { 00293 g_free (cm_string); 00294 qof_session_update_reference_list (qecd->new_session, ref); 00295 } 00296 } 00297 00298 static void 00299 qof_entity_foreach_copy (gpointer data, gpointer user_data) 00300 { 00301 QofEntity *importEnt, *targetEnt /*, *referenceEnt */ ; 00302 QofEntityCopyData *context; 00303 QofEntityReference *reference; 00304 gboolean registered_type; 00305 /* cm_ prefix used for variables that hold the data to commit */ 00306 QofParam *cm_param; 00307 gchar *cm_string, *cm_char; 00308 const GUID *cm_guid; 00309 KvpFrame *cm_kvp; 00310 QofCollection *cm_col; 00311 /* function pointers and variables for parameter getters that don't use pointers normally */ 00312 QofNumeric cm_numeric, (*numeric_getter) (QofEntity *, QofParam *); 00313 gdouble cm_double, (*double_getter) (QofEntity *, QofParam *); 00314 gboolean cm_boolean, (*boolean_getter) (QofEntity *, QofParam *); 00315 gint32 cm_i32, (*int32_getter) (QofEntity *, QofParam *); 00316 gint64 cm_i64, (*int64_getter) (QofEntity *, QofParam *); 00317 /* function pointers to the parameter setters */ 00318 void (*string_setter) (QofEntity *, const gchar *); 00319 void (*numeric_setter) (QofEntity *, QofNumeric); 00320 void (*guid_setter) (QofEntity *, const GUID *); 00321 void (*double_setter) (QofEntity *, gdouble); 00322 void (*boolean_setter) (QofEntity *, gboolean); 00323 void (*i32_setter) (QofEntity *, gint32); 00324 void (*i64_setter) (QofEntity *, gint64); 00325 void (*char_setter) (QofEntity *, gchar *); 00326 void (*kvp_frame_setter) (QofEntity *, KvpFrame *); 00327 00328 g_return_if_fail (user_data != NULL); 00329 context = (QofEntityCopyData *) user_data; 00330 importEnt = context->from; 00331 targetEnt = context->to; 00332 registered_type = FALSE; 00333 cm_param = (QofParam *) data; 00334 g_return_if_fail (cm_param != NULL); 00335 context->param = cm_param; 00336 if (safe_strcmp (cm_param->param_type, QOF_TYPE_STRING) == 0) 00337 { 00338 cm_string = (gchar *) cm_param->param_getfcn (importEnt, cm_param); 00339 if (cm_string) 00340 { 00341 string_setter = 00342 (void (*)(QofEntity *, 00343 const char *)) cm_param->param_setfcn; 00344 if (string_setter != NULL) 00345 { 00346 qof_util_param_edit ((QofInstance *) targetEnt, cm_param); 00347 string_setter (targetEnt, cm_string); 00348 qof_util_param_commit ((QofInstance *) targetEnt, cm_param); 00349 } 00350 } 00351 registered_type = TRUE; 00352 } 00353 if (safe_strcmp (cm_param->param_type, QOF_TYPE_TIME) == 0) 00354 { 00355 QofTime *qt; 00356 void (*time_setter) (QofEntity *, QofTime *); 00357 00358 qt = cm_param->param_getfcn (importEnt, cm_param); 00359 time_setter = 00360 (void (*)(QofEntity *, QofTime*))cm_param->param_setfcn; 00361 if (time_setter != NULL) 00362 { 00363 qof_util_param_edit ((QofInstance *) targetEnt, cm_param); 00364 time_setter (targetEnt, qt); 00365 qof_util_param_commit ((QofInstance *) targetEnt, cm_param); 00366 } 00367 registered_type = TRUE; 00368 } 00369 #ifndef QOF_DISABLE_DEPRECATED 00370 if (safe_strcmp (cm_param->param_type, QOF_TYPE_DATE) == 0) 00371 { 00372 Timespec cm_date, (*date_getter) (QofEntity *, QofParam *); 00373 void (*date_setter) (QofEntity *, Timespec); 00374 00375 cm_date.tv_nsec = 0; 00376 cm_date.tv_sec = 0; 00377 date_getter = 00378 (Timespec (*)(QofEntity *, QofParam *)) cm_param->param_getfcn; 00379 cm_date = date_getter (importEnt, cm_param); 00380 date_setter = 00381 (void (*)(QofEntity *, Timespec)) cm_param->param_setfcn; 00382 if (date_setter != NULL) 00383 { 00384 qof_util_param_edit ((QofInstance *) targetEnt, cm_param); 00385 date_setter (targetEnt, cm_date); 00386 qof_util_param_commit ((QofInstance *) targetEnt, cm_param); 00387 } 00388 registered_type = TRUE; 00389 } 00390 #endif 00391 if ((safe_strcmp (cm_param->param_type, QOF_TYPE_NUMERIC) == 0) || 00392 (safe_strcmp (cm_param->param_type, QOF_TYPE_DEBCRED) == 0)) 00393 { 00394 numeric_getter = 00395 (QofNumeric (*)(QofEntity *, 00396 QofParam *)) cm_param->param_getfcn; 00397 cm_numeric = numeric_getter (importEnt, cm_param); 00398 numeric_setter = 00399 (void (*)(QofEntity *, QofNumeric)) cm_param->param_setfcn; 00400 if (numeric_setter != NULL) 00401 { 00402 qof_util_param_edit ((QofInstance *) targetEnt, cm_param); 00403 numeric_setter (targetEnt, cm_numeric); 00404 qof_util_param_commit ((QofInstance *) targetEnt, cm_param); 00405 } 00406 registered_type = TRUE; 00407 } 00408 if (safe_strcmp (cm_param->param_type, QOF_TYPE_GUID) == 0) 00409 { 00410 cm_guid = 00411 (const GUID *) cm_param->param_getfcn (importEnt, cm_param); 00412 guid_setter = 00413 (void (*)(QofEntity *, const GUID *)) cm_param->param_setfcn; 00414 if (guid_setter != NULL) 00415 { 00416 qof_util_param_edit ((QofInstance *) targetEnt, cm_param); 00417 guid_setter (targetEnt, cm_guid); 00418 qof_util_param_commit ((QofInstance *) targetEnt, cm_param); 00419 } 00420 registered_type = TRUE; 00421 } 00422 if (safe_strcmp (cm_param->param_type, QOF_TYPE_INT32) == 0) 00423 { 00424 int32_getter = 00425 (gint32 (*)(QofEntity *, QofParam *)) cm_param->param_getfcn; 00426 cm_i32 = int32_getter (importEnt, cm_param); 00427 i32_setter = 00428 (void (*)(QofEntity *, gint32)) cm_param->param_setfcn; 00429 if (i32_setter != NULL) 00430 { 00431 qof_util_param_edit ((QofInstance *) targetEnt, cm_param); 00432 i32_setter (targetEnt, cm_i32); 00433 qof_util_param_commit ((QofInstance *) targetEnt, cm_param); 00434 } 00435 registered_type = TRUE; 00436 } 00437 if (safe_strcmp (cm_param->param_type, QOF_TYPE_INT64) == 0) 00438 { 00439 int64_getter = 00440 (gint64 (*)(QofEntity *, QofParam *)) cm_param->param_getfcn; 00441 cm_i64 = int64_getter (importEnt, cm_param); 00442 i64_setter = 00443 (void (*)(QofEntity *, gint64)) cm_param->param_setfcn; 00444 if (i64_setter != NULL) 00445 { 00446 qof_util_param_edit ((QofInstance *) targetEnt, cm_param); 00447 i64_setter (targetEnt, cm_i64); 00448 qof_util_param_commit ((QofInstance *) targetEnt, cm_param); 00449 } 00450 registered_type = TRUE; 00451 } 00452 if (safe_strcmp (cm_param->param_type, QOF_TYPE_DOUBLE) == 0) 00453 { 00454 double_getter = 00455 (gdouble (*)(QofEntity *, QofParam *)) cm_param->param_getfcn; 00456 cm_double = double_getter (importEnt, cm_param); 00457 double_setter = 00458 (void (*)(QofEntity *, gdouble)) cm_param->param_setfcn; 00459 if (double_setter != NULL) 00460 { 00461 qof_util_param_edit ((QofInstance *) targetEnt, cm_param); 00462 double_setter (targetEnt, cm_double); 00463 qof_util_param_commit ((QofInstance *) targetEnt, cm_param); 00464 } 00465 registered_type = TRUE; 00466 } 00467 if (safe_strcmp (cm_param->param_type, QOF_TYPE_BOOLEAN) == 0) 00468 { 00469 boolean_getter = 00470 (gboolean (*)(QofEntity *, QofParam *)) cm_param->param_getfcn; 00471 cm_boolean = boolean_getter (importEnt, cm_param); 00472 boolean_setter = 00473 (void (*)(QofEntity *, gboolean)) cm_param->param_setfcn; 00474 if (boolean_setter != NULL) 00475 { 00476 qof_util_param_edit ((QofInstance *) targetEnt, cm_param); 00477 boolean_setter (targetEnt, cm_boolean); 00478 qof_util_param_commit ((QofInstance *) targetEnt, cm_param); 00479 } 00480 registered_type = TRUE; 00481 } 00482 if (safe_strcmp (cm_param->param_type, QOF_TYPE_KVP) == 0) 00483 { 00484 cm_kvp = (KvpFrame *) cm_param->param_getfcn (importEnt, cm_param); 00485 kvp_frame_setter = 00486 (void (*)(QofEntity *, KvpFrame *)) cm_param->param_setfcn; 00487 if (kvp_frame_setter != NULL) 00488 { 00489 qof_util_param_edit ((QofInstance *) targetEnt, cm_param); 00490 kvp_frame_setter (targetEnt, cm_kvp); 00491 qof_util_param_commit ((QofInstance *) targetEnt, cm_param); 00492 } 00493 else 00494 { 00495 QofInstance *target_inst; 00496 00497 target_inst = (QofInstance *) targetEnt; 00498 kvp_frame_delete (target_inst->kvp_data); 00499 target_inst->kvp_data = kvp_frame_copy (cm_kvp); 00500 } 00501 registered_type = TRUE; 00502 } 00503 if (safe_strcmp (cm_param->param_type, QOF_TYPE_CHAR) == 0) 00504 { 00505 cm_char = (gchar *) cm_param->param_getfcn (importEnt, cm_param); 00506 char_setter = 00507 (void (*)(QofEntity *, char *)) cm_param->param_setfcn; 00508 if (char_setter != NULL) 00509 { 00510 qof_util_param_edit ((QofInstance *) targetEnt, cm_param); 00511 char_setter (targetEnt, cm_char); 00512 qof_util_param_commit ((QofInstance *) targetEnt, cm_param); 00513 } 00514 registered_type = TRUE; 00515 } 00516 if (safe_strcmp (cm_param->param_type, QOF_TYPE_COLLECT) == 0) 00517 { 00518 cm_col = 00519 (QofCollection *) cm_param->param_getfcn (importEnt, cm_param); 00520 if (cm_col) 00521 { 00522 /* create one reference for each member of the collection. */ 00523 qof_collection_foreach (cm_col, col_ref_cb, context); 00524 } 00525 registered_type = TRUE; 00526 } 00527 if (registered_type == FALSE) 00528 { 00529 /* referenceEnt = (QofEntity*)cm_param->param_getfcn(importEnt, cm_param); 00530 if(!referenceEnt) { return; } 00531 if(!referenceEnt->e_type) { return; }*/ 00532 reference = qof_entity_get_reference_from (importEnt, cm_param); 00533 if (reference) 00534 { 00535 qof_session_update_reference_list (context->new_session, 00536 reference); 00537 } 00538 } 00539 } 00540 00541 static gboolean 00542 qof_entity_guid_match (QofSession * new_session, QofEntity * original) 00543 { 00544 QofEntity *copy; 00545 const GUID *g; 00546 QofIdTypeConst type; 00547 QofBook *targetBook; 00548 QofCollection *coll; 00549 00550 copy = NULL; 00551 g_return_val_if_fail (original != NULL, FALSE); 00552 targetBook = qof_session_get_book (new_session); 00553 g_return_val_if_fail (targetBook != NULL, FALSE); 00554 g = qof_entity_get_guid (original); 00555 type = g_strdup (original->e_type); 00556 coll = qof_book_get_collection (targetBook, type); 00557 copy = qof_collection_lookup_entity (coll, g); 00558 if (copy) 00559 { 00560 return TRUE; 00561 } 00562 return FALSE; 00563 } 00564 00565 static void 00566 qof_entity_list_foreach (gpointer data, gpointer user_data) 00567 { 00568 QofEntityCopyData *qecd; 00569 QofEntity *original; 00570 QofInstance *inst; 00571 QofBook *book; 00572 const GUID *g; 00573 00574 g_return_if_fail (data != NULL); 00575 original = (QofEntity *) data; 00576 g_return_if_fail (user_data != NULL); 00577 qecd = (QofEntityCopyData *) user_data; 00578 if (qof_entity_guid_match (qecd->new_session, original)) 00579 { 00580 return; 00581 } 00582 qecd->from = original; 00583 if (!qof_object_compliance (original->e_type, FALSE)) 00584 { 00585 qecd->error = TRUE; 00586 return; 00587 } 00588 book = qof_session_get_book (qecd->new_session); 00589 inst = 00590 (QofInstance *) qof_object_new_instance (original->e_type, book); 00591 if (!inst) 00592 { 00593 PERR (" failed to create new entity type=%s.", original->e_type); 00594 qecd->error = TRUE; 00595 return; 00596 } 00597 qecd->to = &inst->entity; 00598 g = qof_entity_get_guid (original); 00599 qof_entity_set_guid (qecd->to, g); 00600 if (qecd->param_list != NULL) 00601 { 00602 g_slist_free (qecd->param_list); 00603 qecd->param_list = NULL; 00604 } 00605 qof_class_param_foreach (original->e_type, qof_entity_param_cb, qecd); 00606 g_slist_foreach (qecd->param_list, qof_entity_foreach_copy, qecd); 00607 } 00608 00609 static void 00610 qof_entity_coll_foreach (QofEntity * original, gpointer user_data) 00611 { 00612 QofEntityCopyData *qecd; 00613 const GUID *g; 00614 QofBook *targetBook; 00615 QofCollection *coll; 00616 QofEntity *copy; 00617 00618 g_return_if_fail (user_data != NULL); 00619 copy = NULL; 00620 qecd = (QofEntityCopyData *) user_data; 00621 targetBook = qof_session_get_book (qecd->new_session); 00622 g = qof_entity_get_guid (original); 00623 coll = qof_book_get_collection (targetBook, original->e_type); 00624 copy = qof_collection_lookup_entity (coll, g); 00625 if (copy) 00626 { 00627 qecd->error = TRUE; 00628 } 00629 } 00630 00631 static void 00632 qof_entity_coll_copy (QofEntity * original, gpointer user_data) 00633 { 00634 QofEntityCopyData *qecd; 00635 QofBook *book; 00636 QofInstance *inst; 00637 const GUID *g; 00638 00639 g_return_if_fail (user_data != NULL); 00640 qecd = (QofEntityCopyData *) user_data; 00641 book = qof_session_get_book (qecd->new_session); 00642 if (!qof_object_compliance (original->e_type, TRUE)) 00643 { 00644 return; 00645 } 00646 inst = 00647 (QofInstance *) qof_object_new_instance (original->e_type, book); 00648 qecd->to = &inst->entity; 00649 qecd->from = original; 00650 g = qof_entity_get_guid (original); 00651 qof_entity_set_guid (qecd->to, g); 00652 g_slist_foreach (qecd->param_list, qof_entity_foreach_copy, qecd); 00653 } 00654 00655 gboolean 00656 qof_entity_copy_to_session (QofSession * new_session, QofEntity * original) 00657 { 00658 QofEntityCopyData qecd; 00659 QofInstance *inst; 00660 QofBook *book; 00661 00662 if (!new_session || !original) 00663 return FALSE; 00664 if (qof_entity_guid_match (new_session, original)) 00665 return FALSE; 00666 if (!qof_object_compliance (original->e_type, TRUE)) 00667 return FALSE; 00668 qof_event_suspend (); 00669 qecd.param_list = NULL; 00670 book = qof_session_get_book (new_session); 00671 qecd.new_session = new_session; 00672 qof_book_set_partial (book); 00673 inst = 00674 (QofInstance *) qof_object_new_instance (original->e_type, book); 00675 qecd.to = &inst->entity; 00676 qecd.from = original; 00677 qof_entity_set_guid (qecd.to, qof_entity_get_guid (original)); 00678 qof_class_param_foreach (original->e_type, qof_entity_param_cb, &qecd); 00679 if (g_slist_length (qecd.param_list) == 0) 00680 return FALSE; 00681 g_slist_foreach (qecd.param_list, qof_entity_foreach_copy, &qecd); 00682 g_slist_free (qecd.param_list); 00683 qof_event_resume (); 00684 return TRUE; 00685 } 00686 00687 gboolean 00688 qof_entity_copy_list (QofSession * new_session, GList * entity_list) 00689 { 00690 QofEntityCopyData *qecd; 00691 00692 if (!new_session || !entity_list) 00693 return FALSE; 00694 ENTER (" list=%d", g_list_length (entity_list)); 00695 qecd = g_new0 (QofEntityCopyData, 1); 00696 qof_event_suspend (); 00697 qecd->param_list = NULL; 00698 qecd->new_session = new_session; 00699 qof_book_set_partial (qof_session_get_book (new_session)); 00700 g_list_foreach (entity_list, qof_entity_list_foreach, qecd); 00701 qof_event_resume (); 00702 if (qecd->error) 00703 PWARN (" some/all entities in the list could not be copied."); 00704 g_free (qecd); 00705 LEAVE (" "); 00706 return TRUE; 00707 } 00708 00709 gboolean 00710 qof_entity_copy_coll (QofSession * new_session, 00711 QofCollection * entity_coll) 00712 { 00713 QofEntityCopyData qecd; 00714 00715 g_return_val_if_fail (new_session, FALSE); 00716 if (!entity_coll) 00717 { 00718 return FALSE; 00719 } 00720 qof_event_suspend (); 00721 qecd.param_list = NULL; 00722 qecd.new_session = new_session; 00723 qof_book_set_partial (qof_session_get_book (qecd.new_session)); 00724 qof_collection_foreach (entity_coll, qof_entity_coll_foreach, &qecd); 00725 qof_class_param_foreach (qof_collection_get_type (entity_coll), 00726 qof_entity_param_cb, &qecd); 00727 qof_collection_foreach (entity_coll, qof_entity_coll_copy, &qecd); 00728 if (qecd.param_list != NULL) 00729 { 00730 g_slist_free (qecd.param_list); 00731 } 00732 qof_event_resume (); 00733 return TRUE; 00734 } 00735 00736 struct recurse_s 00737 { 00738 QofSession *session; 00739 gboolean success; 00740 GList *ref_list; 00741 GList *ent_list; 00742 }; 00743 00744 static void 00745 recurse_collection_cb (QofEntity * ent, gpointer user_data) 00746 { 00747 struct recurse_s *store; 00748 00749 if (user_data == NULL) 00750 { 00751 return; 00752 } 00753 store = (struct recurse_s *) user_data; 00754 if (!ent || !store) 00755 { 00756 return; 00757 } 00758 store->success = qof_entity_copy_to_session (store->session, ent); 00759 if (store->success) 00760 { 00761 store->ent_list = g_list_append (store->ent_list, ent); 00762 } 00763 } 00764 00765 static void 00766 recurse_ent_cb (QofEntity * ent, gpointer user_data) 00767 { 00768 GList *ref_list, *i, *j, *ent_list, *child_list; 00769 QofParam *ref_param; 00770 QofEntity *ref_ent, *child_ent; 00771 QofSession *session; 00772 struct recurse_s *store; 00773 gboolean success; 00774 00775 if (user_data == NULL) 00776 { 00777 return; 00778 } 00779 store = (struct recurse_s *) user_data; 00780 session = store->session; 00781 success = store->success; 00782 ref_list = NULL; 00783 child_ent = NULL; 00784 ref_list = g_list_copy (store->ref_list); 00785 if ((!session) || (!ent)) 00786 { 00787 return; 00788 } 00789 ent_list = NULL; 00790 child_list = NULL; 00791 i = NULL; 00792 j = NULL; 00793 for (i = ref_list; i != NULL; i = i->next) 00794 { 00795 if (i->data == NULL) 00796 { 00797 continue; 00798 } 00799 ref_param = (QofParam *) i->data; 00800 if (ref_param->param_name == NULL) 00801 { 00802 continue; 00803 } 00804 if (0 == safe_strcmp (ref_param->param_type, QOF_TYPE_COLLECT)) 00805 { 00806 QofCollection *col; 00807 00808 col = ref_param->param_getfcn (ent, ref_param); 00809 if (col) 00810 { 00811 qof_collection_foreach (col, recurse_collection_cb, store); 00812 } 00813 continue; 00814 } 00815 ref_ent = (QofEntity *) ref_param->param_getfcn (ent, ref_param); 00816 if ((ref_ent) && (ref_ent->e_type)) 00817 { 00818 store->success = qof_entity_copy_to_session (session, ref_ent); 00819 if (store->success) 00820 { 00821 ent_list = g_list_append (ent_list, ref_ent); 00822 } 00823 } 00824 } 00825 for (i = ent_list; i != NULL; i = i->next) 00826 { 00827 if (i->data == NULL) 00828 { 00829 continue; 00830 } 00831 child_ent = (QofEntity *) i->data; 00832 if (child_ent == NULL) 00833 { 00834 continue; 00835 } 00836 ref_list = qof_class_get_referenceList (child_ent->e_type); 00837 for (j = ref_list; j != NULL; j = j->next) 00838 { 00839 if (j->data == NULL) 00840 { 00841 continue; 00842 } 00843 ref_param = (QofParam *) j->data; 00844 ref_ent = ref_param->param_getfcn (child_ent, ref_param); 00845 if (ref_ent != NULL) 00846 { 00847 success = qof_entity_copy_to_session (session, ref_ent); 00848 if (success) 00849 { 00850 child_list = g_list_append (child_list, ref_ent); 00851 } 00852 } 00853 } 00854 } 00855 for (i = child_list; i != NULL; i = i->next) 00856 { 00857 if (i->data == NULL) 00858 { 00859 continue; 00860 } 00861 ref_ent = (QofEntity *) i->data; 00862 if (ref_ent == NULL) 00863 { 00864 continue; 00865 } 00866 ref_list = qof_class_get_referenceList (ref_ent->e_type); 00867 for (j = ref_list; j != NULL; j = j->next) 00868 { 00869 if (j->data == NULL) 00870 { 00871 continue; 00872 } 00873 ref_param = (QofParam *) j->data; 00874 child_ent = ref_param->param_getfcn (ref_ent, ref_param); 00875 if (child_ent != NULL) 00876 { 00877 qof_entity_copy_to_session (session, child_ent); 00878 } 00879 } 00880 } 00881 } 00882 00883 gboolean 00884 qof_entity_copy_coll_r (QofSession * new_session, QofCollection * coll) 00885 { 00886 struct recurse_s store; 00887 gboolean success; 00888 00889 if ((!new_session) || (!coll)) 00890 { 00891 return FALSE; 00892 } 00893 store.session = new_session; 00894 success = TRUE; 00895 store.success = success; 00896 store.ent_list = NULL; 00897 store.ref_list = 00898 qof_class_get_referenceList (qof_collection_get_type (coll)); 00899 success = qof_entity_copy_coll (new_session, coll); 00900 if (success) 00901 { 00902 qof_collection_foreach (coll, recurse_ent_cb, &store); 00903 } 00904 return success; 00905 } 00906 00907 gboolean 00908 qof_entity_copy_one_r (QofSession * new_session, QofEntity * ent) 00909 { 00910 struct recurse_s store; 00911 QofCollection *coll; 00912 gboolean success; 00913 00914 if ((!new_session) || (!ent)) 00915 { 00916 return FALSE; 00917 } 00918 store.session = new_session; 00919 success = TRUE; 00920 store.success = success; 00921 store.ref_list = qof_class_get_referenceList (ent->e_type); 00922 success = qof_entity_copy_to_session (new_session, ent); 00923 if (success == TRUE) 00924 { 00925 coll = 00926 qof_book_get_collection (qof_session_get_book (new_session), 00927 ent->e_type); 00928 if (coll) 00929 { 00930 qof_collection_foreach (coll, recurse_ent_cb, &store); 00931 } 00932 } 00933 return success; 00934 } 00935 00936 00937 /* ============================================================== */ 00938 00942 struct backend_providers 00943 { 00944 const gchar *libdir; 00945 const gchar *filename; 00946 const gchar *init_fcn; 00947 }; 00948 00949 /* All available QOF backends need to be described here 00950 and the last entry must be three NULL's. 00951 Remember: Use the libdir from the current build environment 00952 and use JUST the module name without .so - .so is not portable! */ 00953 struct backend_providers backend_list[] = { 00954 {QOF_LIB_DIR, QSF_BACKEND_LIB, QSF_MODULE_INIT}, 00955 {QOF_LIB_DIR, "libqof-backend-sqlite", "qof_sqlite_provider_init"}, 00956 #ifdef HAVE_GDA 00957 {QOF_LIB_DIR, "libqof-backend-gda", "qof_gda_provider_init"}, 00958 #endif 00959 #ifdef HAVE_DWI 00960 {QOF_LIB_DIR, "libqof_backend_dwi", "dwiend_provider_init"}, 00961 #endif 00962 {NULL, NULL, NULL} 00963 }; 00964 00965 static void 00966 qof_session_load_backend (QofSession * session, gchar *access_method) 00967 { 00968 GSList *p; 00969 GList *node; 00970 QofBackendProvider *prov; 00971 QofBook *book; 00972 gint num; 00973 gboolean prov_type; 00974 gboolean (*type_check) (const gchar *); 00975 00976 ENTER (" list=%d", g_slist_length (provider_list)); 00977 prov_type = FALSE; 00978 if (NULL == provider_list) 00979 { 00980 for (num = 0; backend_list[num].filename != NULL; num++) 00981 { 00982 if (!qof_load_backend_library (backend_list[num].libdir, 00983 backend_list[num].filename, 00984 backend_list[num].init_fcn)) 00985 { 00986 PWARN (" failed to load %s from %s using %s", 00987 backend_list[num].filename, backend_list[num].libdir, 00988 backend_list[num].init_fcn); 00989 } 00990 } 00991 } 00992 p = g_slist_copy (provider_list); 00993 while (p != NULL) 00994 { 00995 prov = p->data; 00996 /* Does this provider handle the desired access method? */ 00997 if (0 == strcasecmp (access_method, prov->access_method)) 00998 { 00999 /* More than one backend could provide this 01000 access method, check file type compatibility. */ 01001 type_check = 01002 (gboolean (*)(const gchar *)) prov->check_data_type; 01003 prov_type = (type_check) (session->book_id); 01004 if (!prov_type) 01005 { 01006 PINFO (" %s not usable", prov->provider_name); 01007 p = p->next; 01008 continue; 01009 } 01010 PINFO (" selected %s", prov->provider_name); 01011 if (NULL == prov->backend_new) 01012 { 01013 p = p->next; 01014 continue; 01015 } 01016 /* Use the providers creation callback */ 01017 session->backend = (*(prov->backend_new)) (); 01018 session->backend->provider = prov; 01019 /* Tell the books about the backend that they'll be using. */ 01020 for (node = session->books; node; node = node->next) 01021 { 01022 book = node->data; 01023 qof_book_set_backend (book, session->backend); 01024 } 01025 LEAVE (" "); 01026 return; 01027 } 01028 p = p->next; 01029 } 01030 LEAVE (" "); 01031 } 01032 01033 /* =============================================================== */ 01034 01035 static void 01036 qof_session_destroy_backend (QofSession * session) 01037 { 01038 g_return_if_fail (session); 01039 01040 if (session->backend) 01041 { 01042 /* Then destroy the backend */ 01043 if (session->backend->destroy_backend) 01044 { 01045 session->backend->destroy_backend (session->backend); 01046 } 01047 else 01048 { 01049 g_free (session->backend); 01050 } 01051 } 01052 01053 session->backend = NULL; 01054 } 01055 01056 void 01057 qof_session_begin (QofSession * session, const gchar *book_id, 01058 gboolean ignore_lock, gboolean create_if_nonexistent) 01059 { 01060 gchar *p, *access_method; 01061 01062 if (!session) 01063 return; 01064 01065 ENTER (" sess=%p ignore_lock=%d, book-id=%s", 01066 session, ignore_lock, book_id ? book_id : "(null)"); 01067 01068 /* Clear the error condition of previous errors */ 01069 qof_error_clear (session); 01070 01071 /* Check to see if this session is already open */ 01072 if (session->book_id) 01073 { 01074 qof_error_set (session, qof_error_register 01075 (_("This book appears to be open already."), FALSE)); 01076 LEAVE (" push error book is already open "); 01077 return; 01078 } 01079 01080 if (!book_id) 01081 { 01082 LEAVE (" using stdout"); 01083 return; 01084 } 01085 01086 /* Store the session URL */ 01087 session->book_id = g_strdup (book_id); 01088 01089 /* destroy the old backend */ 01090 qof_session_destroy_backend (session); 01091 01092 /* Look for something of the form of "file:/", "http://" or 01093 * "postgres://". Everything before the colon is the access 01094 * method. Load the first backend found for that access method. 01095 */ 01096 p = strchr (book_id, ':'); 01097 if (p) 01098 { 01099 access_method = g_strdup (book_id); 01100 p = strchr (access_method, ':'); 01101 *p = 0; 01102 qof_session_load_backend (session, access_method); 01103 g_free (access_method); 01104 } 01105 else 01106 { 01107 /* If no colon found, assume it must be a file-path */ 01108 qof_session_load_backend (session, "file"); 01109 } 01110 01111 /* No backend was found. That's bad. */ 01112 if (NULL == session->backend) 01113 { 01114 gchar * msg; 01115 01116 msg = g_strdup_printf (_("Unable to locate a " 01117 "suitable backend for '%s' - please check " 01118 "you have specified an access method " 01119 "like file: or sqlite:"), book_id); 01120 qof_error_set (session, qof_error_register 01121 (msg, FALSE)); 01122 DEBUG (" msg=%s", msg); 01123 LEAVE (" BAD: no backend: sess=%p book-id=%s", 01124 session, book_id ? book_id : "(null)"); 01125 g_free (msg); 01126 return; 01127 } 01128 01129 /* If there's a begin method, call that. */ 01130 if (session->backend->session_begin) 01131 { 01132 (session->backend->session_begin) (session->backend, session, 01133 session->book_id, ignore_lock, create_if_nonexistent); 01134 PINFO (" Done running session_begin on backend"); 01135 if (qof_error_check(session) != QOF_SUCCESS) 01136 { 01137 g_free (session->book_id); 01138 session->book_id = NULL; 01139 LEAVE (" backend error "); 01140 return; 01141 } 01142 } 01143 qof_error_clear (session); 01144 LEAVE (" sess=%p book-id=%s", session, book_id ? book_id : "(null)"); 01145 } 01146 01147 /* ============================================================== */ 01148 01149 void 01150 qof_session_load (QofSession * session, QofPercentageFunc percentage_func) 01151 { 01152 QofBook *newbook, *ob; 01153 QofBookList *oldbooks, *node; 01154 QofBackend *be; 01155 01156 if (!session) 01157 return; 01158 if ((!session->book_id) || 01159 (0 == safe_strcasecmp(session->book_id, QOF_STDOUT))) 01160 return; 01161 01162 ENTER (" sess=%p book_id=%s", session, session->book_id 01163 ? session->book_id : "(null)"); 01164 01165 /* At this point, we should are supposed to have a valid book 01166 * id and a lock on the file. */ 01167 01168 oldbooks = session->books; 01169 01170 /* XXX why are we creating a book here? I think the books 01171 * need to be handled by the backend ... especially since 01172 * the backend may need to load multiple books ... XXX. FIXME. 01173 */ 01174 newbook = qof_book_new (); 01175 session->books = g_list_append (NULL, newbook); 01176 PINFO (" new book=%p", newbook); 01177 01178 qof_error_clear (session); 01179 01180 /* This code should be sufficient to initialize *any* backend, 01181 * whether http, postgres, or anything else that might come along. 01182 * Basically, the idea is that by now, a backend has already been 01183 * created & set up. At this point, we only need to get the 01184 * top-level account group out of the backend, and that is a 01185 * generic, backend-independent operation. 01186 */ 01187 be = session->backend; 01188 qof_book_set_backend (newbook, be); 01189 01190 /* Starting the session should result in a bunch of accounts 01191 * and currencies being downloaded, but probably no transactions; 01192 * The GUI will need to do a query for that. 01193 */ 01194 if (be) 01195 { 01196 be->percentage = percentage_func; 01197 01198 if (be->load) 01199 { 01200 be->load (be, newbook); 01201 } 01202 } 01203 01204 if (qof_error_check(session) != QOF_SUCCESS) 01205 { 01206 /* Something broke, put back the old stuff */ 01207 qof_book_set_backend (newbook, NULL); 01208 qof_book_destroy (newbook); 01209 g_list_free (session->books); 01210 session->books = oldbooks; 01211 g_free (session->book_id); 01212 session->book_id = NULL; 01213 LEAVE (" error from backend "); 01214 return; 01215 } 01216 01217 for (node = oldbooks; node; node = node->next) 01218 { 01219 ob = node->data; 01220 qof_book_set_backend (ob, NULL); 01221 qof_book_destroy (ob); 01222 } 01223 g_list_free (oldbooks); 01224 01225 LEAVE (" sess = %p, book_id=%s", session, session->book_id 01226 ? session->book_id : "(null)"); 01227 } 01228 01229 /* ============================================================= */ 01230 01231 gboolean 01232 qof_session_save_may_clobber_data (QofSession * session) 01233 { 01234 if (!session) 01235 return FALSE; 01236 if (!session->backend) 01237 return FALSE; 01238 if (!session->backend->save_may_clobber_data) 01239 return FALSE; 01240 01241 return (*(session->backend->save_may_clobber_data)) (session->backend); 01242 } 01243 01244 void 01245 qof_session_save (QofSession * session, 01246 QofPercentageFunc percentage_func) 01247 { 01248 GList *node; 01249 QofBackend *be; 01250 gboolean partial, change_backend; 01251 QofBackendProvider *prov; 01252 GSList *p; 01253 QofBook *book, *abook; 01254 gint num; 01255 gchar *msg, *book_id; 01256 01257 if (!session) 01258 return; 01259 ENTER (" sess=%p book_id=%s", 01260 session, session->book_id ? session->book_id : "(null)"); 01261 /* Partial book handling. */ 01262 book = qof_session_get_book (session); 01263 partial = 01264 (gboolean) 01265 GPOINTER_TO_INT (qof_book_get_data (book, PARTIAL_QOFBOOK)); 01266 change_backend = FALSE; 01267 msg = g_strdup_printf (" "); 01268 book_id = g_strdup (session->book_id); 01269 if (partial == TRUE) 01270 { 01271 if (session->backend && session->backend->provider) 01272 { 01273 prov = session->backend->provider; 01274 if (TRUE == prov->partial_book_supported) 01275 { 01276 /* if current backend supports partial, leave alone. */ 01277 change_backend = FALSE; 01278 } 01279 else 01280 { 01281 change_backend = TRUE; 01282 } 01283 } 01284 /* If provider is undefined, assume partial not supported. */ 01285 else 01286 { 01287 change_backend = TRUE; 01288 } 01289 } 01290 if (change_backend == TRUE) 01291 { 01292 qof_session_destroy_backend (session); 01293 if (NULL == provider_list) 01294 { 01295 for (num = 0; backend_list[num].filename != NULL; num++) 01296 { 01297 qof_load_backend_library (backend_list[num].libdir, 01298 backend_list[num].filename, 01299 backend_list[num].init_fcn); 01300 } 01301 } 01302 p = g_slist_copy (provider_list); 01303 while (p != NULL) 01304 { 01305 prov = p->data; 01306 if (TRUE == prov->partial_book_supported) 01307 { 01309 /* if((TRUE == prov->partial_book_supported) && 01310 (0 == strcasecmp (access_method, prov->access_method))) 01311 { */ 01312 if (NULL == prov->backend_new) 01313 continue; 01314 /* Use the providers creation callback */ 01315 session->backend = (*(prov->backend_new)) (); 01316 session->backend->provider = prov; 01317 if (session->backend->session_begin) 01318 { 01319 /* Call begin - backend has been changed, 01320 so make sure a file can be written, 01321 use ignore_lock and create_if_nonexistent */ 01322 g_free (session->book_id); 01323 session->book_id = NULL; 01324 (session->backend->session_begin) (session->backend, 01325 session, book_id, TRUE, TRUE); 01326 PINFO 01327 (" Done running session_begin on changed backend"); 01328 if (qof_error_check (session) != QOF_SUCCESS) 01329 { 01330 g_free (session->book_id); 01331 session->book_id = NULL; 01332 LEAVE (" changed backend error"); 01333 return; 01334 } 01335 } 01336 /* Tell the books about the backend that they'll be using. */ 01337 for (node = session->books; node; node = node->next) 01338 { 01339 book = node->data; 01340 qof_book_set_backend (book, session->backend); 01341 } 01342 p = NULL; 01343 } 01344 if (p) 01345 { 01346 p = p->next; 01347 } 01348 } 01349 if (!session->backend) 01350 { 01351 msg = g_strdup_printf (" failed to load backend"); 01352 qof_error_set (session, qof_error_register 01353 (_("Failed to load backend, no suitable handler."), 01354 FALSE)); 01355 return; 01356 } 01357 } 01358 /* If there is a backend, and the backend is reachable 01359 * (i.e. we can communicate with it), then synchronize with 01360 * the backend. If we cannot contact the backend (e.g. 01361 * because we've gone offline, the network has crashed, etc.) 01362 * then give the user the option to save to the local disk. 01363 * 01364 * hack alert -- FIXME -- XXX the code below no longer 01365 * does what the words above say. This needs fixing. 01366 */ 01367 be = session->backend; 01368 if (be) 01369 { 01370 for (node = session->books; node; node = node->next) 01371 { 01372 abook = node->data; 01373 /* if invoked as SaveAs(), then backend not yet set */ 01374 qof_book_set_backend (abook, be); 01375 be->percentage = percentage_func; 01376 if (be->sync) 01377 (be->sync) (be, abook); 01378 } 01379 /* If we got to here, then the backend saved everything 01380 * just fine, and we are done. So return. */ 01381 /* Return the book_id to previous value. */ 01382 qof_error_clear (session); 01383 LEAVE (" Success"); 01384 return; 01385 } 01386 else 01387 { 01388 msg = g_strdup_printf (" failed to load backend"); 01389 qof_error_set (session, qof_error_register 01390 (_("Failed to load backend, no suitable handler."), 01391 FALSE)); 01392 } 01393 LEAVE (" error -- No backend!"); 01394 } 01395 01396 /* ============================================================= */ 01397 01398 void 01399 qof_session_end (QofSession * session) 01400 { 01401 if (!session) 01402 return; 01403 01404 ENTER (" sess=%p book_id=%s", session, session->book_id 01405 ? session->book_id : "(null)"); 01406 01407 /* close down the backend first */ 01408 if (session->backend && session->backend->session_end) 01409 { 01410 (session->backend->session_end) (session->backend); 01411 } 01412 01413 qof_error_clear (session); 01414 01415 g_free (session->book_id); 01416 session->book_id = NULL; 01417 01418 LEAVE (" sess=%p book_id=%s", session, session->book_id 01419 ? session->book_id : "(null)"); 01420 } 01421 01422 void 01423 qof_session_destroy (QofSession * session) 01424 { 01425 GList *node; 01426 if (!session) 01427 return; 01428 01429 ENTER (" sess=%p book_id=%s", session, session->book_id 01430 ? session->book_id : "(null)"); 01431 01432 qof_session_end (session); 01433 01434 /* destroy the backend */ 01435 qof_session_destroy_backend (session); 01436 01437 for (node = session->books; node; node = node->next) 01438 { 01439 QofBook *book = node->data; 01440 qof_book_set_backend (book, NULL); 01441 qof_book_destroy (book); 01442 } 01443 01444 session->books = NULL; 01445 #ifndef QOF_DISABLE_DEPRECATED 01446 if (session == qof_session_get_current_session()) 01447 qof_session_clear_current_session(); 01448 #endif 01449 g_free (session); 01450 qof_error_close (); 01451 01452 LEAVE (" sess=%p", session); 01453 } 01454 01455 /* ============================================================= */ 01456 01457 void 01458 qof_session_swap_data (QofSession * session_1, QofSession * session_2) 01459 { 01460 GList *books_1, *books_2, *node; 01461 01462 if (session_1 == session_2) 01463 return; 01464 if (!session_1 || !session_2) 01465 return; 01466 01467 ENTER (" sess1=%p sess2=%p", session_1, session_2); 01468 01469 books_1 = session_1->books; 01470 books_2 = session_2->books; 01471 01472 session_1->books = books_2; 01473 session_2->books = books_1; 01474 01475 for (node = books_1; node; node = node->next) 01476 { 01477 QofBook *book_1 = node->data; 01478 qof_book_set_backend (book_1, session_2->backend); 01479 } 01480 for (node = books_2; node; node = node->next) 01481 { 01482 QofBook *book_2 = node->data; 01483 qof_book_set_backend (book_2, session_1->backend); 01484 } 01485 01486 LEAVE (" "); 01487 } 01488 01489 /* ============================================================= */ 01490 01491 gboolean 01492 qof_session_events_pending (QofSession * session) 01493 { 01494 if (!session) 01495 return FALSE; 01496 if (!session->backend) 01497 return FALSE; 01498 if (!session->backend->events_pending) 01499 return FALSE; 01500 01501 return session->backend->events_pending (session->backend); 01502 } 01503 01504 gboolean 01505 qof_session_process_events (QofSession * session) 01506 { 01507 if (!session) 01508 return FALSE; 01509 if (!session->backend) 01510 return FALSE; 01511 if (!session->backend->process_events) 01512 return FALSE; 01513 01514 return session->backend->process_events (session->backend); 01515 } 01516 01517 /* ============== END OF FILE ========================== */