qofsession.c

Go to the documentation of this file.
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 ========================== */

Generated on Thu Jan 31 22:50:26 2008 for QOF by  doxygen 1.5.4