QOF  0.8.7
qofsession.c
Go to the documentation of this file.
1 /********************************************************************\
2  * qofsesssion.c -- session access (connection to backend) *
3  * *
4  * This program is free software; you can redistribute it and/or *
5  * modify it under the terms of the GNU General Public License as *
6  * published by the Free Software Foundation; either version 2 of *
7  * the License, or (at your option) any later version. *
8  * *
9  * This program is distributed in the hope that it will be useful, *
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12  * GNU General Public License for more details. *
13  * *
14  * You should have received a copy of the GNU General Public License*
15  * along with this program; if not, contact: *
16  * *
17  * Free Software Foundation Voice: +1-617-542-5942 *
18  * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
19  * Boston, MA 02110-1301, USA gnu@gnu.org *
20 \********************************************************************/
21 
34 #include "config.h"
35 
36 #include <stdlib.h>
37 #include <string.h>
38 #include <sys/types.h>
39 #include <sys/stat.h>
40 #include <unistd.h>
41 #include <glib.h>
42 #include <libintl.h>
43 #include "qof.h"
44 #include "qoferror-p.h"
45 #include "qofbackend-p.h"
46 #include "qofbook-p.h"
47 #include "qofsession-p.h"
48 #include "qofobject-p.h"
49 
50 #define _(String) dgettext (GETTEXT_PACKAGE, String)
51 
52 static GHookList *session_closed_hooks = NULL;
53 static QofLogModule log_module = QOF_MOD_SESSION;
54 static GSList *provider_list = NULL;
55 
56 /* ============================================================= */
57 
58 void
60 {
61  provider_list = g_slist_prepend (provider_list, prov);
62 }
63 
64 /* =========================================================== */
65 
66 /* hook routines */
67 
68 void
69 qof_session_add_close_hook (GFunc fn, gpointer data)
70 {
71  GHook *hook;
72 
73  if (session_closed_hooks == NULL)
74  {
75  session_closed_hooks = malloc (sizeof (GHookList)); /* LEAKED */
76  g_hook_list_init (session_closed_hooks, sizeof (GHook));
77  }
78 
79  hook = g_hook_alloc (session_closed_hooks);
80  if (!hook)
81  return;
82 
83  hook->func = (GHookFunc) fn;
84  hook->data = data;
85  g_hook_append (session_closed_hooks, hook);
86 }
87 
88 void
90 {
91  GHook *hook;
92  GFunc fn;
93 
94  if (session_closed_hooks == NULL)
95  return;
96 
97  hook = g_hook_first_valid (session_closed_hooks, FALSE);
98  while (hook)
99  {
100  fn = (GFunc) hook->func;
101  fn (session, hook->data);
102  hook = g_hook_next_valid (session_closed_hooks, hook, FALSE);
103  }
104 }
105 
106 /* =============================================================== */
107 
108 static void
109 qof_session_init (QofSession * session)
110 {
111  if (!session)
112  return;
113 
114  session->books = g_list_append (NULL, qof_book_new ());
115  session->book_id = NULL;
116  session->backend = NULL;
117  qof_error_init ();
118 }
119 
120 QofSession *
121 qof_session_new (void)
122 {
123  QofSession *session = g_new0 (QofSession, 1);
124  qof_session_init (session);
125  return session;
126 }
127 
128 QofBook *
129 qof_session_get_book (QofSession * session)
130 {
131  GList *node;
132  if (!session)
133  return NULL;
134 
135  for (node = session->books; node; node = node->next)
136  {
137  QofBook *book = node->data;
138  if ('y' == book->book_open)
139  return book;
140  }
141  return NULL;
142 }
143 
144 void
146 {
147  GList *node;
148  if (!session)
149  return;
150 
151  ENTER (" sess=%p book=%p", session, addbook);
152 
153  /* See if this book is already there ... */
154  for (node = session->books; node; node = node->next)
155  {
156  QofBook *book = node->data;
157  if (addbook == book)
158  return;
159  }
160 
161  if ('y' == addbook->book_open)
162  {
163  /* hack alert -- someone should free all the books in the list,
164  * but it should probably not be us ... since the books backends
165  * should be shutdown first, etc */
166 /* XXX this should probably be an error XXX */
167  g_list_free (session->books);
168  session->books = g_list_append (NULL, addbook);
169  }
170  else
171  {
172 /* XXX Need to tell the backend to add a book as well */
173  session->books = g_list_append (session->books, addbook);
174  }
175 
176  qof_book_set_backend (addbook, session->backend);
177  LEAVE (" ");
178 }
179 
180 QofBackend *
181 qof_session_get_backend (QofSession * session)
182 {
183  if (!session)
184  return NULL;
185  return session->backend;
186 }
187 
188 const gchar *
190 {
191  if (!session)
192  return NULL;
193  if (!session->backend)
194  return NULL;
195  return session->backend->fullpath;
196 }
197 
198 const gchar *
199 qof_session_get_url (QofSession * session)
200 {
201  if (!session)
202  return NULL;
203  return session->book_id;
204 }
205 
206 /* =============================================================== */
207 
208 typedef struct qof_entity_copy_data
209 {
210  QofEntity *from;
211  QofEntity *to;
212  QofParam *param;
213  GList *referenceList;
214  GSList *param_list;
215  QofSession *new_session;
216  gboolean error;
217 } QofEntityCopyData;
218 
219 static void
220 qof_book_set_partial (QofBook * book)
221 {
222  gboolean partial;
223 
224  partial =
225  (gboolean)
226  GPOINTER_TO_INT (qof_book_get_data (book, PARTIAL_QOFBOOK));
227  if (!partial)
228  {
229  qof_book_set_data (book, PARTIAL_QOFBOOK, GINT_TO_POINTER (TRUE));
230  }
231 }
232 
233 void
235  QofEntityReference * reference)
236 {
237  QofBook *book;
238  GList *book_ref_list;
239 
240  book = qof_session_get_book (session);
241  book_ref_list = (GList *) qof_book_get_data (book, ENTITYREFERENCE);
242  book_ref_list = g_list_append (book_ref_list, reference);
243  qof_book_set_data (book, ENTITYREFERENCE, book_ref_list);
244  qof_book_set_partial (book);
245 }
246 
247 static void
248 qof_entity_param_cb (QofParam * param, gpointer data)
249 {
250  QofEntityCopyData *qecd;
251 
252  g_return_if_fail (data != NULL);
253  qecd = (QofEntityCopyData *) data;
254  g_return_if_fail (param != NULL);
255  /* KVP doesn't need a set routine to be copied. */
256  if (0 == safe_strcmp (param->param_type, QOF_TYPE_KVP))
257  {
258  qecd->param_list = g_slist_prepend (qecd->param_list, param);
259  return;
260  }
261  if ((param->param_getfcn != NULL) && (param->param_setfcn != NULL))
262  {
263  qecd->param_list = g_slist_prepend (qecd->param_list, param);
264  }
265 }
266 
267 static void
268 col_ref_cb (QofEntity * ref_ent, gpointer user_data)
269 {
270  QofEntityReference *ref;
271  QofEntityCopyData *qecd;
272  QofEntity *ent;
273  const GUID *cm_guid;
274  gchar cm_sa[GUID_ENCODING_LENGTH + 1];
275  gchar *cm_string;
276 
277  qecd = (QofEntityCopyData *) user_data;
278  ent = qecd->from;
279  ref = g_new0 (QofEntityReference, 1);
280  ref->type = ent->e_type;
281  ref->ref_guid = g_new (GUID, 1);
282  ref->ent_guid = &ent->guid;
283  ref->param = qof_class_get_parameter (ent->e_type,
284  qecd->param->param_name);
285  cm_guid = qof_entity_get_guid (ref_ent);
286  guid_to_string_buff (cm_guid, cm_sa);
287  cm_string = g_strdup (cm_sa);
288  if (TRUE == string_to_guid (cm_string, ref->ref_guid))
289  {
290  g_free (cm_string);
291  qof_session_update_reference_list (qecd->new_session, ref);
292  }
293 }
294 
295 static void
296 qof_entity_foreach_copy (gpointer data, gpointer user_data)
297 {
298  QofEntity *importEnt, *targetEnt /*, *referenceEnt */ ;
299  QofEntityCopyData *context;
300  QofEntityReference *reference;
301  gboolean registered_type;
302  /* cm_ prefix used for variables that hold the data to commit */
303  QofParam *cm_param;
304  gchar *cm_string, *cm_char;
305  const GUID *cm_guid;
306  KvpFrame *cm_kvp;
307  QofCollection *cm_col;
308  /* function pointers and variables for parameter getters that don't use pointers normally */
309  QofNumeric cm_numeric, (*numeric_getter) (QofEntity *, QofParam *);
310  gdouble cm_double, (*double_getter) (QofEntity *, QofParam *);
311  gboolean cm_boolean, (*boolean_getter) (QofEntity *, QofParam *);
312  gint32 cm_i32, (*int32_getter) (QofEntity *, QofParam *);
313  gint64 cm_i64, (*int64_getter) (QofEntity *, QofParam *);
314  /* function pointers to the parameter setters */
315  void (*string_setter) (QofEntity *, const gchar *);
316  void (*numeric_setter) (QofEntity *, QofNumeric);
317  void (*guid_setter) (QofEntity *, const GUID *);
318  void (*double_setter) (QofEntity *, gdouble);
319  void (*boolean_setter) (QofEntity *, gboolean);
320  void (*i32_setter) (QofEntity *, gint32);
321  void (*i64_setter) (QofEntity *, gint64);
322  void (*char_setter) (QofEntity *, gchar *);
323  void (*kvp_frame_setter) (QofEntity *, KvpFrame *);
324 
325  g_return_if_fail (user_data != NULL);
326  context = (QofEntityCopyData *) user_data;
327  importEnt = context->from;
328  targetEnt = context->to;
329  registered_type = FALSE;
330  cm_param = (QofParam *) data;
331  g_return_if_fail (cm_param != NULL);
332  context->param = cm_param;
333  if (safe_strcmp (cm_param->param_type, QOF_TYPE_STRING) == 0)
334  {
335  cm_string = (gchar *) cm_param->param_getfcn (importEnt, cm_param);
336  if (cm_string)
337  {
338  string_setter =
339  (void (*)(QofEntity *,
340  const char *)) cm_param->param_setfcn;
341  if (string_setter != NULL)
342  {
343  qof_util_param_edit ((QofInstance *) targetEnt, cm_param);
344  string_setter (targetEnt, cm_string);
345  qof_util_param_commit ((QofInstance *) targetEnt, cm_param);
346  }
347  }
348  registered_type = TRUE;
349  }
350  if (safe_strcmp (cm_param->param_type, QOF_TYPE_TIME) == 0)
351  {
352  QofTime *qt;
353  void (*time_setter) (QofEntity *, QofTime *);
354 
355  qt = cm_param->param_getfcn (importEnt, cm_param);
356  time_setter =
357  (void (*)(QofEntity *, QofTime*))cm_param->param_setfcn;
358  if (time_setter != NULL)
359  {
360  qof_util_param_edit ((QofInstance *) targetEnt, cm_param);
361  time_setter (targetEnt, qt);
362  qof_util_param_commit ((QofInstance *) targetEnt, cm_param);
363  }
364  registered_type = TRUE;
365  }
366  if ((safe_strcmp (cm_param->param_type, QOF_TYPE_NUMERIC) == 0) ||
367  (safe_strcmp (cm_param->param_type, QOF_TYPE_DEBCRED) == 0))
368  {
369  numeric_getter =
370  (QofNumeric (*)(QofEntity *,
371  QofParam *)) cm_param->param_getfcn;
372  cm_numeric = numeric_getter (importEnt, cm_param);
373  numeric_setter =
374  (void (*)(QofEntity *, QofNumeric)) cm_param->param_setfcn;
375  if (numeric_setter != NULL)
376  {
377  qof_util_param_edit ((QofInstance *) targetEnt, cm_param);
378  numeric_setter (targetEnt, cm_numeric);
379  qof_util_param_commit ((QofInstance *) targetEnt, cm_param);
380  }
381  registered_type = TRUE;
382  }
383  if (safe_strcmp (cm_param->param_type, QOF_TYPE_GUID) == 0)
384  {
385  cm_guid =
386  (const GUID *) cm_param->param_getfcn (importEnt, cm_param);
387  guid_setter =
388  (void (*)(QofEntity *, const GUID *)) cm_param->param_setfcn;
389  if (guid_setter != NULL)
390  {
391  qof_util_param_edit ((QofInstance *) targetEnt, cm_param);
392  guid_setter (targetEnt, cm_guid);
393  qof_util_param_commit ((QofInstance *) targetEnt, cm_param);
394  }
395  registered_type = TRUE;
396  }
397  if (safe_strcmp (cm_param->param_type, QOF_TYPE_INT32) == 0)
398  {
399  int32_getter =
400  (gint32 (*)(QofEntity *, QofParam *)) cm_param->param_getfcn;
401  cm_i32 = int32_getter (importEnt, cm_param);
402  i32_setter =
403  (void (*)(QofEntity *, gint32)) cm_param->param_setfcn;
404  if (i32_setter != NULL)
405  {
406  qof_util_param_edit ((QofInstance *) targetEnt, cm_param);
407  i32_setter (targetEnt, cm_i32);
408  qof_util_param_commit ((QofInstance *) targetEnt, cm_param);
409  }
410  registered_type = TRUE;
411  }
412  if (safe_strcmp (cm_param->param_type, QOF_TYPE_INT64) == 0)
413  {
414  int64_getter =
415  (gint64 (*)(QofEntity *, QofParam *)) cm_param->param_getfcn;
416  cm_i64 = int64_getter (importEnt, cm_param);
417  i64_setter =
418  (void (*)(QofEntity *, gint64)) cm_param->param_setfcn;
419  if (i64_setter != NULL)
420  {
421  qof_util_param_edit ((QofInstance *) targetEnt, cm_param);
422  i64_setter (targetEnt, cm_i64);
423  qof_util_param_commit ((QofInstance *) targetEnt, cm_param);
424  }
425  registered_type = TRUE;
426  }
427  if (safe_strcmp (cm_param->param_type, QOF_TYPE_DOUBLE) == 0)
428  {
429  double_getter =
430  (gdouble (*)(QofEntity *, QofParam *)) cm_param->param_getfcn;
431  cm_double = double_getter (importEnt, cm_param);
432  double_setter =
433  (void (*)(QofEntity *, gdouble)) cm_param->param_setfcn;
434  if (double_setter != NULL)
435  {
436  qof_util_param_edit ((QofInstance *) targetEnt, cm_param);
437  double_setter (targetEnt, cm_double);
438  qof_util_param_commit ((QofInstance *) targetEnt, cm_param);
439  }
440  registered_type = TRUE;
441  }
442  if (safe_strcmp (cm_param->param_type, QOF_TYPE_BOOLEAN) == 0)
443  {
444  boolean_getter =
445  (gboolean (*)(QofEntity *, QofParam *)) cm_param->param_getfcn;
446  cm_boolean = boolean_getter (importEnt, cm_param);
447  boolean_setter =
448  (void (*)(QofEntity *, gboolean)) cm_param->param_setfcn;
449  if (boolean_setter != NULL)
450  {
451  qof_util_param_edit ((QofInstance *) targetEnt, cm_param);
452  boolean_setter (targetEnt, cm_boolean);
453  qof_util_param_commit ((QofInstance *) targetEnt, cm_param);
454  }
455  registered_type = TRUE;
456  }
457  if (safe_strcmp (cm_param->param_type, QOF_TYPE_KVP) == 0)
458  {
459  cm_kvp = (KvpFrame *) cm_param->param_getfcn (importEnt, cm_param);
460  kvp_frame_setter =
461  (void (*)(QofEntity *, KvpFrame *)) cm_param->param_setfcn;
462  if (kvp_frame_setter != NULL)
463  {
464  qof_util_param_edit ((QofInstance *) targetEnt, cm_param);
465  kvp_frame_setter (targetEnt, cm_kvp);
466  qof_util_param_commit ((QofInstance *) targetEnt, cm_param);
467  }
468  else
469  {
470  QofInstance *target_inst;
471 
472  target_inst = (QofInstance *) targetEnt;
473  kvp_frame_delete (target_inst->kvp_data);
474  target_inst->kvp_data = kvp_frame_copy (cm_kvp);
475  }
476  registered_type = TRUE;
477  }
478  if (safe_strcmp (cm_param->param_type, QOF_TYPE_CHAR) == 0)
479  {
480  cm_char = (gchar *) cm_param->param_getfcn (importEnt, cm_param);
481  char_setter =
482  (void (*)(QofEntity *, char *)) cm_param->param_setfcn;
483  if (char_setter != NULL)
484  {
485  qof_util_param_edit ((QofInstance *) targetEnt, cm_param);
486  char_setter (targetEnt, cm_char);
487  qof_util_param_commit ((QofInstance *) targetEnt, cm_param);
488  }
489  registered_type = TRUE;
490  }
491  if (safe_strcmp (cm_param->param_type, QOF_TYPE_COLLECT) == 0)
492  {
493  cm_col =
494  (QofCollection *) cm_param->param_getfcn (importEnt, cm_param);
495  if (cm_col)
496  {
497  /* create one reference for each member of the collection. */
498  qof_collection_foreach (cm_col, col_ref_cb, context);
499  }
500  registered_type = TRUE;
501  }
502  if (registered_type == FALSE)
503  {
504 /* referenceEnt = (QofEntity*)cm_param->param_getfcn(importEnt, cm_param);
505  if(!referenceEnt) { return; }
506  if(!referenceEnt->e_type) { return; }*/
507  reference = qof_entity_get_reference_from (importEnt, cm_param);
508  if (reference)
509  {
510  qof_session_update_reference_list (context->new_session,
511  reference);
512  }
513  }
514 }
515 
516 static gboolean
517 qof_entity_guid_match (QofSession * new_session, QofEntity * original)
518 {
519  QofEntity *copy;
520  const GUID *g;
521  QofIdTypeConst type;
522  QofBook *targetBook;
523  QofCollection *coll;
524 
525  copy = NULL;
526  g_return_val_if_fail (original != NULL, FALSE);
527  targetBook = qof_session_get_book (new_session);
528  g_return_val_if_fail (targetBook != NULL, FALSE);
529  g = qof_entity_get_guid (original);
530  type = g_strdup (original->e_type);
531  coll = qof_book_get_collection (targetBook, type);
532  copy = qof_collection_lookup_entity (coll, g);
533  if (copy)
534  {
535  return TRUE;
536  }
537  return FALSE;
538 }
539 
540 static void
541 qof_entity_list_foreach (gpointer data, gpointer user_data)
542 {
543  QofEntityCopyData *qecd;
544  QofEntity *original;
545  QofInstance *inst;
546  QofBook *book;
547  const GUID *g;
548 
549  g_return_if_fail (data != NULL);
550  original = (QofEntity *) data;
551  g_return_if_fail (user_data != NULL);
552  qecd = (QofEntityCopyData *) user_data;
553  if (qof_entity_guid_match (qecd->new_session, original))
554  {
555  return;
556  }
557  qecd->from = original;
558  if (!qof_object_compliance (original->e_type, FALSE))
559  {
560  qecd->error = TRUE;
561  return;
562  }
563  book = qof_session_get_book (qecd->new_session);
564  inst =
565  (QofInstance *) qof_object_new_instance (original->e_type, book);
566  if (!inst)
567  {
568  PERR (" failed to create new entity type=%s.", original->e_type);
569  qecd->error = TRUE;
570  return;
571  }
572  qecd->to = &inst->entity;
573  g = qof_entity_get_guid (original);
574  qof_entity_set_guid (qecd->to, g);
575  if (qecd->param_list != NULL)
576  {
577  g_slist_free (qecd->param_list);
578  qecd->param_list = NULL;
579  }
580  qof_class_param_foreach (original->e_type, qof_entity_param_cb, qecd);
581  g_slist_foreach (qecd->param_list, qof_entity_foreach_copy, qecd);
582 }
583 
584 static void
585 qof_entity_coll_foreach (QofEntity * original, gpointer user_data)
586 {
587  QofEntityCopyData *qecd;
588  const GUID *g;
589  QofBook *targetBook;
590  QofCollection *coll;
591  QofEntity *copy;
592 
593  g_return_if_fail (user_data != NULL);
594  copy = NULL;
595  qecd = (QofEntityCopyData *) user_data;
596  targetBook = qof_session_get_book (qecd->new_session);
597  g = qof_entity_get_guid (original);
598  coll = qof_book_get_collection (targetBook, original->e_type);
599  copy = qof_collection_lookup_entity (coll, g);
600  if (copy)
601  {
602  qecd->error = TRUE;
603  }
604 }
605 
606 static void
607 qof_entity_coll_copy (QofEntity * original, gpointer user_data)
608 {
609  QofEntityCopyData *qecd;
610  QofBook *book;
611  QofInstance *inst;
612  const GUID *g;
613 
614  g_return_if_fail (user_data != NULL);
615  qecd = (QofEntityCopyData *) user_data;
616  book = qof_session_get_book (qecd->new_session);
617  if (!qof_object_compliance (original->e_type, TRUE))
618  {
619  return;
620  }
621  inst =
622  (QofInstance *) qof_object_new_instance (original->e_type, book);
623  qecd->to = &inst->entity;
624  qecd->from = original;
625  g = qof_entity_get_guid (original);
626  qof_entity_set_guid (qecd->to, g);
627  g_slist_foreach (qecd->param_list, qof_entity_foreach_copy, qecd);
628 }
629 
630 gboolean
632 {
633  QofEntityCopyData qecd;
634  QofInstance *inst;
635  QofBook *book;
636 
637  if (!new_session || !original)
638  return FALSE;
639  if (qof_entity_guid_match (new_session, original))
640  return FALSE;
641  if (!qof_object_compliance (original->e_type, TRUE))
642  return FALSE;
644  qecd.param_list = NULL;
645  book = qof_session_get_book (new_session);
646  qecd.new_session = new_session;
647  qof_book_set_partial (book);
648  inst =
649  (QofInstance *) qof_object_new_instance (original->e_type, book);
650  qecd.to = &inst->entity;
651  qecd.from = original;
652  qof_entity_set_guid (qecd.to, qof_entity_get_guid (original));
653  qof_class_param_foreach (original->e_type, qof_entity_param_cb, &qecd);
654  if (g_slist_length (qecd.param_list) == 0)
655  return FALSE;
656  g_slist_foreach (qecd.param_list, qof_entity_foreach_copy, &qecd);
657  g_slist_free (qecd.param_list);
658  qof_event_resume ();
659  return TRUE;
660 }
661 
662 gboolean
663 qof_entity_copy_list (QofSession * new_session, GList * entity_list)
664 {
665  QofEntityCopyData *qecd;
666 
667  if (!new_session || !entity_list)
668  return FALSE;
669  ENTER (" list=%d", g_list_length (entity_list));
670  qecd = g_new0 (QofEntityCopyData, 1);
672  qecd->param_list = NULL;
673  qecd->new_session = new_session;
674  qof_book_set_partial (qof_session_get_book (new_session));
675  g_list_foreach (entity_list, qof_entity_list_foreach, qecd);
676  qof_event_resume ();
677  if (qecd->error)
678  PWARN (" some/all entities in the list could not be copied.");
679  g_free (qecd);
680  LEAVE (" ");
681  return TRUE;
682 }
683 
684 gboolean
686  QofCollection * entity_coll)
687 {
688  QofEntityCopyData qecd;
689 
690  g_return_val_if_fail (new_session, FALSE);
691  if (!entity_coll)
692  {
693  return FALSE;
694  }
696  qecd.param_list = NULL;
697  qecd.new_session = new_session;
698  qof_book_set_partial (qof_session_get_book (qecd.new_session));
699  qof_collection_foreach (entity_coll, qof_entity_coll_foreach, &qecd);
701  qof_entity_param_cb, &qecd);
702  qof_collection_foreach (entity_coll, qof_entity_coll_copy, &qecd);
703  if (qecd.param_list != NULL)
704  {
705  g_slist_free (qecd.param_list);
706  }
707  qof_event_resume ();
708  return TRUE;
709 }
710 
711 struct recurse_s
712 {
713  QofSession *session;
714  gboolean success;
715  GList *ref_list;
716  GList *ent_list;
717 };
718 
719 static void
720 recurse_collection_cb (QofEntity * ent, gpointer user_data)
721 {
722  struct recurse_s *store;
723 
724  if (user_data == NULL)
725  {
726  return;
727  }
728  store = (struct recurse_s *) user_data;
729  if (!ent || !store)
730  {
731  return;
732  }
733  store->success = qof_entity_copy_to_session (store->session, ent);
734  if (store->success)
735  {
736  store->ent_list = g_list_append (store->ent_list, ent);
737  }
738 }
739 
740 static void
741 recurse_ent_cb (QofEntity * ent, gpointer user_data)
742 {
743  GList *ref_list, *i, *j, *ent_list, *child_list;
744  QofParam *ref_param;
745  QofEntity *ref_ent, *child_ent;
746  QofSession *session;
747  struct recurse_s *store;
748  gboolean success;
749 
750  if (user_data == NULL)
751  {
752  return;
753  }
754  store = (struct recurse_s *) user_data;
755  session = store->session;
756  success = store->success;
757  ref_list = NULL;
758  child_ent = NULL;
759  ref_list = g_list_copy (store->ref_list);
760  if ((!session) || (!ent))
761  {
762  return;
763  }
764  ent_list = NULL;
765  child_list = NULL;
766  i = NULL;
767  j = NULL;
768  for (i = ref_list; i != NULL; i = i->next)
769  {
770  if (i->data == NULL)
771  {
772  continue;
773  }
774  ref_param = (QofParam *) i->data;
775  if (ref_param->param_name == NULL)
776  {
777  continue;
778  }
779  if (0 == safe_strcmp (ref_param->param_type, QOF_TYPE_COLLECT))
780  {
781  QofCollection *col;
782 
783  col = ref_param->param_getfcn (ent, ref_param);
784  if (col)
785  {
786  qof_collection_foreach (col, recurse_collection_cb, store);
787  }
788  continue;
789  }
790  ref_ent = (QofEntity *) ref_param->param_getfcn (ent, ref_param);
791  if ((ref_ent) && (ref_ent->e_type))
792  {
793  store->success = qof_entity_copy_to_session (session, ref_ent);
794  if (store->success)
795  {
796  ent_list = g_list_append (ent_list, ref_ent);
797  }
798  }
799  }
800  for (i = ent_list; i != NULL; i = i->next)
801  {
802  if (i->data == NULL)
803  {
804  continue;
805  }
806  child_ent = (QofEntity *) i->data;
807  if (child_ent == NULL)
808  {
809  continue;
810  }
811  ref_list = qof_class_get_referenceList (child_ent->e_type);
812  for (j = ref_list; j != NULL; j = j->next)
813  {
814  if (j->data == NULL)
815  {
816  continue;
817  }
818  ref_param = (QofParam *) j->data;
819  ref_ent = ref_param->param_getfcn (child_ent, ref_param);
820  if (ref_ent != NULL)
821  {
822  success = qof_entity_copy_to_session (session, ref_ent);
823  if (success)
824  {
825  child_list = g_list_append (child_list, ref_ent);
826  }
827  }
828  }
829  }
830  for (i = child_list; i != NULL; i = i->next)
831  {
832  if (i->data == NULL)
833  {
834  continue;
835  }
836  ref_ent = (QofEntity *) i->data;
837  if (ref_ent == NULL)
838  {
839  continue;
840  }
841  ref_list = qof_class_get_referenceList (ref_ent->e_type);
842  for (j = ref_list; j != NULL; j = j->next)
843  {
844  if (j->data == NULL)
845  {
846  continue;
847  }
848  ref_param = (QofParam *) j->data;
849  child_ent = ref_param->param_getfcn (ref_ent, ref_param);
850  if (child_ent != NULL)
851  {
852  qof_entity_copy_to_session (session, child_ent);
853  }
854  }
855  }
856 }
857 
858 gboolean
860 {
861  struct recurse_s store;
862  gboolean success;
863 
864  if ((!new_session) || (!coll))
865  {
866  return FALSE;
867  }
868  store.session = new_session;
869  success = TRUE;
870  store.success = success;
871  store.ent_list = NULL;
872  store.ref_list =
874  success = qof_entity_copy_coll (new_session, coll);
875  if (success)
876  {
877  qof_collection_foreach (coll, recurse_ent_cb, &store);
878  }
879  return success;
880 }
881 
882 gboolean
884 {
885  struct recurse_s store;
886  QofCollection *coll;
887  gboolean success;
888 
889  if ((!new_session) || (!ent))
890  {
891  return FALSE;
892  }
893  store.session = new_session;
894  success = TRUE;
895  store.success = success;
896  store.ref_list = qof_class_get_referenceList (ent->e_type);
897  success = qof_entity_copy_to_session (new_session, ent);
898  if (success == TRUE)
899  {
900  coll =
901  qof_book_get_collection (qof_session_get_book (new_session),
902  ent->e_type);
903  if (coll)
904  {
905  qof_collection_foreach (coll, recurse_ent_cb, &store);
906  }
907  }
908  return success;
909 }
910 
911 
912 /* ============================================================== */
913 
917 struct backend_providers
918 {
919  const gchar *libdir;
920  const gchar *filename;
921  const gchar *init_fcn;
922 };
923 
924 /* All available QOF backends need to be described here
925 and the last entry must be three NULL's.
926 Remember: Use the libdir from the current build environment
927 and use JUST the module name without .so - .so is not portable! */
928 struct backend_providers backend_list[] = {
929  {QOF_LIB_DIR, QSF_BACKEND_LIB, QSF_MODULE_INIT},
930  {QOF_LIB_DIR, "libqof-backend-sqlite", "qof_sqlite_provider_init"},
931 #ifdef HAVE_GDA
932  {QOF_LIB_DIR, "libqof-backend-gda", "qof_gda_provider_init"},
933 #endif
934 #ifdef HAVE_ESTRON
935  {QOF_LIB_DIR, "libqof_backend_estron", "dwiend_provider_init"},
936 #endif
937  {NULL, NULL, NULL}
938 };
939 
940 static void
941 qof_session_load_backend (QofSession * session, gchar *access_method)
942 {
943  GSList *p;
944  GList *node;
945  QofBackendProvider *prov;
946  QofBook *book;
947  gint num;
948  gboolean prov_type;
949  gboolean (*type_check) (const gchar *);
950 
951  ENTER (" list=%d", g_slist_length (provider_list));
952  prov_type = FALSE;
953  if (NULL == provider_list)
954  {
955  for (num = 0; backend_list[num].filename != NULL; num++)
956  {
957  if (!qof_load_backend_library (backend_list[num].libdir,
958  backend_list[num].filename,
959  backend_list[num].init_fcn))
960  {
961  PWARN (" failed to load %s from %s using %s",
962  backend_list[num].filename, backend_list[num].libdir,
963  backend_list[num].init_fcn);
964  }
965  }
966  }
967  p = g_slist_copy (provider_list);
968  while (p != NULL)
969  {
970  prov = p->data;
971  /* Does this provider handle the desired access method? */
972  if (0 == strcasecmp (access_method, prov->access_method))
973  {
974  /* More than one backend could provide this
975  access method, check file type compatibility. */
976  type_check =
977  (gboolean (*)(const gchar *)) prov->check_data_type;
978  prov_type = (type_check) (session->book_id);
979  if (!prov_type)
980  {
981  PINFO (" %s not usable", prov->provider_name);
982  p = p->next;
983  continue;
984  }
985  PINFO (" selected %s", prov->provider_name);
986  if (NULL == prov->backend_new)
987  {
988  p = p->next;
989  continue;
990  }
991  /* Use the providers creation callback */
992  session->backend = (*(prov->backend_new)) ();
993  session->backend->provider = prov;
994  /* Tell the books about the backend that they'll be using. */
995  for (node = session->books; node; node = node->next)
996  {
997  book = node->data;
998  qof_book_set_backend (book, session->backend);
999  }
1000  LEAVE (" ");
1001  return;
1002  }
1003  p = p->next;
1004  }
1005  LEAVE (" ");
1006 }
1007 
1008 /* =============================================================== */
1009 
1010 static void
1011 qof_session_destroy_backend (QofSession * session)
1012 {
1013  g_return_if_fail (session);
1014 
1015  if (session->backend)
1016  {
1017  /* Then destroy the backend */
1018  if (session->backend->destroy_backend)
1019  {
1020  session->backend->destroy_backend (session->backend);
1021  }
1022  else
1023  {
1024  g_free (session->backend);
1025  }
1026  }
1027 
1028  session->backend = NULL;
1029 }
1030 
1031 void
1032 qof_session_begin (QofSession * session, const gchar *book_id,
1033  gboolean ignore_lock, gboolean create_if_nonexistent)
1034 {
1035  gchar *p, *access_method;
1036 
1037  if (!session)
1038  return;
1039 
1040  ENTER (" sess=%p ignore_lock=%d, book-id=%s",
1041  session, ignore_lock, book_id ? book_id : "(null)");
1042 
1043  /* Clear the error condition of previous errors */
1044  qof_error_clear (session);
1045 
1046  /* Check to see if this session is already open */
1047  if (session->book_id)
1048  {
1050  (_("This book appears to be open already."), FALSE));
1051  LEAVE (" push error book is already open ");
1052  return;
1053  }
1054 
1055  if (!book_id)
1056  {
1057  LEAVE (" using stdout");
1058  return;
1059  }
1060 
1061  /* Store the session URL */
1062  session->book_id = g_strdup (book_id);
1063 
1064  /* destroy the old backend */
1065  qof_session_destroy_backend (session);
1066 
1067  /* Look for something of the form of "file:/", "http://" or
1068  * "postgres://". Everything before the colon is the access
1069  * method. Load the first backend found for that access method.
1070  */
1071  p = strchr (book_id, ':');
1072  if (p)
1073  {
1074  access_method = g_strdup (book_id);
1075  p = strchr (access_method, ':');
1076  *p = 0;
1077  qof_session_load_backend (session, access_method);
1078  g_free (access_method);
1079  }
1080  else
1081  {
1082  /* If no colon found, assume it must be a file-path */
1083  qof_session_load_backend (session, "file");
1084  }
1085 
1086  /* No backend was found. That's bad. */
1087  if (NULL == session->backend)
1088  {
1089  gchar * msg;
1090 
1091  msg = g_strdup_printf (_("Unable to locate a "
1092  "suitable backend for '%s' - please check "
1093  "you have specified an access method "
1094  "like file: or sqlite:"), book_id);
1096  (msg, FALSE));
1097  DEBUG (" msg=%s", msg);
1098  LEAVE (" BAD: no backend: sess=%p book-id=%s",
1099  session, book_id ? book_id : "(null)");
1100  g_free (msg);
1101  return;
1102  }
1103 
1104  /* If there's a begin method, call that. */
1105  if (session->backend->session_begin)
1106  {
1107  (session->backend->session_begin) (session->backend, session,
1108  session->book_id, ignore_lock, create_if_nonexistent);
1109  PINFO (" Done running session_begin on backend");
1110  if (qof_error_check(session) != QOF_SUCCESS)
1111  {
1112  g_free (session->book_id);
1113  session->book_id = NULL;
1114  LEAVE (" backend error ");
1115  return;
1116  }
1117  }
1118  qof_error_clear (session);
1119  LEAVE (" sess=%p book-id=%s", session, book_id ? book_id : "(null)");
1120 }
1121 
1122 /* ============================================================== */
1123 
1124 void
1125 qof_session_load (QofSession * session, QofPercentageFunc percentage_func)
1126 {
1127  QofBook *newbook, *ob;
1128  QofBookList *oldbooks, *node;
1129  QofBackend *be;
1130 
1131  if (!session)
1132  return;
1133  if ((!session->book_id) ||
1134  (0 == safe_strcasecmp(session->book_id, QOF_STDOUT)))
1135  return;
1136 
1137  ENTER (" sess=%p book_id=%s", session, session->book_id
1138  ? session->book_id : "(null)");
1139 
1140  /* At this point, we should are supposed to have a valid book
1141  * id and a lock on the file. */
1142 
1143  oldbooks = session->books;
1144 
1145  /* XXX why are we creating a book here? I think the books
1146  * need to be handled by the backend ... especially since
1147  * the backend may need to load multiple books ... XXX. FIXME.
1148  */
1149  newbook = qof_book_new ();
1150  session->books = g_list_append (NULL, newbook);
1151  PINFO (" new book=%p", newbook);
1152 
1153  qof_error_clear (session);
1154 
1155  /* This code should be sufficient to initialize *any* backend,
1156  * whether http, postgres, or anything else that might come along.
1157  * Basically, the idea is that by now, a backend has already been
1158  * created & set up. At this point, we only need to get the
1159  * top-level account group out of the backend, and that is a
1160  * generic, backend-independent operation.
1161  */
1162  be = session->backend;
1163  qof_book_set_backend (newbook, be);
1164 
1165  /* Starting the session should result in a bunch of accounts
1166  * and currencies being downloaded, but probably no transactions;
1167  * The GUI will need to do a query for that.
1168  */
1169  if (be)
1170  {
1171  be->percentage = percentage_func;
1172 
1173  if (be->load)
1174  {
1175  be->load (be, newbook);
1176  }
1177  }
1178 
1179  if (qof_error_check(session) != QOF_SUCCESS)
1180  {
1181  /* Something broke, put back the old stuff */
1182  qof_book_set_backend (newbook, NULL);
1183  qof_book_destroy (newbook);
1184  g_list_free (session->books);
1185  session->books = oldbooks;
1186  g_free (session->book_id);
1187  session->book_id = NULL;
1188  LEAVE (" error from backend ");
1189  return;
1190  }
1191 
1192  for (node = oldbooks; node; node = node->next)
1193  {
1194  ob = node->data;
1195  qof_book_set_backend (ob, NULL);
1196  qof_book_destroy (ob);
1197  }
1198  g_list_free (oldbooks);
1199 
1200  LEAVE (" sess = %p, book_id=%s", session, session->book_id
1201  ? session->book_id : "(null)");
1202 }
1203 
1204 /* ============================================================= */
1205 
1206 gboolean
1208 {
1209  if (!session)
1210  return FALSE;
1211  if (!session->backend)
1212  return FALSE;
1213  if (!session->backend->save_may_clobber_data)
1214  return FALSE;
1215 
1216  return (*(session->backend->save_may_clobber_data)) (session->backend);
1217 }
1218 
1219 void
1221  QofPercentageFunc percentage_func)
1222 {
1223  GList *node;
1224  QofBackend *be;
1225  gboolean partial, change_backend;
1226  QofBackendProvider *prov;
1227  GSList *p;
1228  QofBook *book, *abook;
1229  gint num;
1230  gchar * G_GNUC_UNUSED msg, *book_id;
1231 
1232  if (!session)
1233  return;
1234  ENTER (" sess=%p book_id=%s",
1235  session, session->book_id ? session->book_id : "(null)");
1236  /* Partial book handling. */
1237  book = qof_session_get_book (session);
1238  partial =
1239  (gboolean)
1240  GPOINTER_TO_INT (qof_book_get_data (book, PARTIAL_QOFBOOK));
1241  change_backend = FALSE;
1242  msg = g_strdup_printf (" ");
1243  book_id = g_strdup (session->book_id);
1244  if (partial == TRUE)
1245  {
1246  if (session->backend && session->backend->provider)
1247  {
1248  prov = session->backend->provider;
1249  if (TRUE == prov->partial_book_supported)
1250  {
1251  /* if current backend supports partial, leave alone. */
1252  change_backend = FALSE;
1253  }
1254  else
1255  {
1256  change_backend = TRUE;
1257  }
1258  }
1259  /* If provider is undefined, assume partial not supported. */
1260  else
1261  {
1262  change_backend = TRUE;
1263  }
1264  }
1265  if (change_backend == TRUE)
1266  {
1267  qof_session_destroy_backend (session);
1268  if (NULL == provider_list)
1269  {
1270  for (num = 0; backend_list[num].filename != NULL; num++)
1271  {
1272  qof_load_backend_library (backend_list[num].libdir,
1273  backend_list[num].filename,
1274  backend_list[num].init_fcn);
1275  }
1276  }
1277  p = g_slist_copy (provider_list);
1278  while (p != NULL)
1279  {
1280  prov = p->data;
1281  if (TRUE == prov->partial_book_supported)
1282  {
1284  /* if((TRUE == prov->partial_book_supported) &&
1285  (0 == strcasecmp (access_method, prov->access_method)))
1286  { */
1287  if (NULL == prov->backend_new)
1288  continue;
1289  /* Use the providers creation callback */
1290  session->backend = (*(prov->backend_new)) ();
1291  session->backend->provider = prov;
1292  if (session->backend->session_begin)
1293  {
1294  /* Call begin - backend has been changed,
1295  so make sure a file can be written,
1296  use ignore_lock and create_if_nonexistent */
1297  g_free (session->book_id);
1298  session->book_id = NULL;
1299  (session->backend->session_begin) (session->backend,
1300  session, book_id, TRUE, TRUE);
1301  PINFO
1302  (" Done running session_begin on changed backend");
1303  if (qof_error_check (session) != QOF_SUCCESS)
1304  {
1305  g_free (session->book_id);
1306  session->book_id = NULL;
1307  LEAVE (" changed backend error");
1308  return;
1309  }
1310  }
1311  /* Tell the books about the backend that they'll be using. */
1312  for (node = session->books; node; node = node->next)
1313  {
1314  book = node->data;
1315  qof_book_set_backend (book, session->backend);
1316  }
1317  p = NULL;
1318  }
1319  if (p)
1320  {
1321  p = p->next;
1322  }
1323  }
1324  if (!session->backend)
1325  {
1326  msg = g_strdup_printf (" failed to load backend");
1328  (_("Failed to load backend, no suitable handler."),
1329  FALSE));
1330  return;
1331  }
1332  }
1333  /* If there is a backend, and the backend is reachable
1334  * (i.e. we can communicate with it), then synchronize with
1335  * the backend. If we cannot contact the backend (e.g.
1336  * because we've gone offline, the network has crashed, etc.)
1337  * then give the user the option to save to the local disk.
1338  *
1339  * hack alert -- FIXME -- XXX the code below no longer
1340  * does what the words above say. This needs fixing.
1341  */
1342  be = session->backend;
1343  if (be)
1344  {
1345  for (node = session->books; node; node = node->next)
1346  {
1347  abook = node->data;
1348  /* if invoked as SaveAs(), then backend not yet set */
1349  qof_book_set_backend (abook, be);
1350  be->percentage = percentage_func;
1351  if (be->sync)
1352  (be->sync) (be, abook);
1353  }
1354  /* If we got to here, then the backend saved everything
1355  * just fine, and we are done. So return. */
1356  /* Return the book_id to previous value. */
1357  qof_error_clear (session);
1358  LEAVE (" Success");
1359  return;
1360  }
1361  else
1362  {
1363  msg = g_strdup_printf (" failed to load backend");
1365  (_("Failed to load backend, no suitable handler."),
1366  FALSE));
1367  }
1368  LEAVE (" error -- No backend!");
1369 }
1370 
1371 /* ============================================================= */
1372 
1373 void
1375 {
1376  if (!session)
1377  return;
1378 
1379  ENTER (" sess=%p book_id=%s", session, session->book_id
1380  ? session->book_id : "(null)");
1381 
1382  /* close down the backend first */
1383  if (session->backend && session->backend->session_end)
1384  {
1385  (session->backend->session_end) (session->backend);
1386  }
1387 
1388  qof_error_clear (session);
1389 
1390  g_free (session->book_id);
1391  session->book_id = NULL;
1392 
1393  LEAVE (" sess=%p book_id=%s", session, session->book_id
1394  ? session->book_id : "(null)");
1395 }
1396 
1397 void
1398 qof_session_destroy (QofSession * session)
1399 {
1400  GList *node;
1401  if (!session)
1402  return;
1403 
1404  ENTER (" sess=%p book_id=%s", session, session->book_id
1405  ? session->book_id : "(null)");
1406 
1407  qof_session_end (session);
1408 
1409  /* destroy the backend */
1410  qof_session_destroy_backend (session);
1411 
1412  for (node = session->books; node; node = node->next)
1413  {
1414  QofBook *book = node->data;
1415  qof_book_set_backend (book, NULL);
1416  qof_book_destroy (book);
1417  }
1418 
1419  session->books = NULL;
1420  g_free (session);
1421  qof_error_close ();
1422 
1423  LEAVE (" sess=%p", session);
1424 }
1425 
1426 /* ============================================================= */
1427 
1428 void
1429 qof_session_swap_data (QofSession * session_1, QofSession * session_2)
1430 {
1431  GList *books_1, *books_2, *node;
1432 
1433  if (session_1 == session_2)
1434  return;
1435  if (!session_1 || !session_2)
1436  return;
1437 
1438  ENTER (" sess1=%p sess2=%p", session_1, session_2);
1439 
1440  books_1 = session_1->books;
1441  books_2 = session_2->books;
1442 
1443  session_1->books = books_2;
1444  session_2->books = books_1;
1445 
1446  for (node = books_1; node; node = node->next)
1447  {
1448  QofBook *book_1 = node->data;
1449  qof_book_set_backend (book_1, session_2->backend);
1450  }
1451  for (node = books_2; node; node = node->next)
1452  {
1453  QofBook *book_2 = node->data;
1454  qof_book_set_backend (book_2, session_1->backend);
1455  }
1456 
1457  LEAVE (" ");
1458 }
1459 
1460 /* ============================================================= */
1461 
1462 gboolean
1464 {
1465  if (!session)
1466  return FALSE;
1467  if (!session->backend)
1468  return FALSE;
1469  if (!session->backend->events_pending)
1470  return FALSE;
1471 
1472  return session->backend->events_pending (session->backend);
1473 }
1474 
1475 gboolean
1477 {
1478  if (!session)
1479  return FALSE;
1480  if (!session->backend)
1481  return FALSE;
1482  if (!session->backend->process_events)
1483  return FALSE;
1484 
1485  return session->backend->process_events (session->backend);
1486 }
1487 
1488 /* ============== END OF FILE ========================== */
void qof_session_call_close_hooks(QofSession *session)
Definition: qofsession.c:89
QofErrorId qof_error_register(const gchar *err_message, gboolean use_file)
Generate and register a new error.
Definition: qoferror.c:73
gchar * fullpath
Definition: qofbackend-p.h:332
gboolean(* save_may_clobber_data)(QofBackend *)
Definition: qofbackend-p.h:320
#define PERR(format, args...)
Definition: qoflog.h:183
gpointer qof_object_new_instance(QofIdTypeConst type_name, QofBook *book)
Definition: qofobject.c:42
const GUID * ent_guid
Definition: qofreference.h:115
gboolean qof_entity_copy_coll(QofSession *new_session, QofCollection *entity_coll)
Copy a QofCollection of entities.
Definition: qofsession.c:685
#define QOF_TYPE_COLLECT
secondary collections are used for one-to-many references between entities and are implemented using ...
Definition: qofclass.h:121
#define PINFO(format, args...)
Definition: qoflog.h:199
QofCollection * qof_book_get_collection(QofBook *book, QofIdType entity_type)
Definition: qofbook.c:220
struct _QofNumeric QofNumeric
A rational-number type.
Definition: qofnumeric.h:61
void qof_class_param_foreach(QofIdTypeConst obj_name, QofParamForeachCB cb, gpointer user_data)
Definition: qofclass.c:268
void qof_backend_register_provider(QofBackendProvider *prov)
Definition: qofsession.c:59
gboolean qof_entity_copy_one_r(QofSession *new_session, QofEntity *ent)
Recursively copy a single entity to a new session.
Definition: qofsession.c:883
gboolean qof_session_events_pending(QofSession *session)
Definition: qofsession.c:1463
gboolean qof_object_compliance(QofIdTypeConst type_name, gboolean warn)
check an object can be created and supports iteration
Definition: qofobject.c:155
void qof_session_add_book(QofSession *session, QofBook *addbook)
Definition: qofsession.c:145
gboolean qof_session_process_events(QofSession *session)
Definition: qofsession.c:1476
QofErrorId qof_error_check(QofSession *session)
Definition: qoferror.c:197
gboolean string_to_guid(const gchar *string, GUID *guid)
gpointer qof_book_get_data(QofBook *book, const gchar *key)
Definition: qofbook.c:212
gchar book_open
Definition: qofbook-p.h:70
gboolean partial_book_supported
Partial QofBook handler.
Definition: qofbackend-p.h:254
KvpFrame * kvp_frame_copy(const KvpFrame *frame)
Definition: kvpframe.c:153
struct _KvpFrame KvpFrame
Definition: kvpframe.h:74
QofBook * qof_book_new(void)
Definition: qofbook.c:75
gint safe_strcasecmp(const gchar *da, const gchar *db)
Definition: qofutil.c:95
gboolean qof_load_backend_library(const gchar *directory, const gchar *filename, const gchar *init_fcn)
Load a QOF-compatible backend shared library.
Definition: qofbackend.c:397
KvpFrame * kvp_data
Definition: qofinstance-p.h:48
#define LEAVE(format, args...)
Definition: qoflog.h:227
#define GUID_ENCODING_LENGTH
Definition: guid.h:64
Private QofBook interface.
void kvp_frame_delete(KvpFrame *frame)
Definition: kvpframe.c:115
the Core Object Registration/Lookup Private Interface
void qof_session_swap_data(QofSession *session_1, QofSession *session_2)
Definition: qofsession.c:1429
void(* QofPercentageFunc)(const gchar *message, gdouble percent)
Definition: qofsession.h:168
struct QofCollection_s QofCollection
Definition: qofid.h:138
const QofParam * qof_class_get_parameter(QofIdTypeConst obj_name, const gchar *parameter)
Definition: qofclass.c:147
gboolean qof_util_param_edit(QofInstance *inst, const QofParam *param)
Prepare to edit a parameter.
Definition: qofutil.c:281
gboolean qof_entity_copy_coll_r(QofSession *new_session, QofCollection *coll)
Recursively copy a collection of entities to a session.
Definition: qofsession.c:859
gboolean qof_session_save_may_clobber_data(QofSession *session)
Definition: qofsession.c:1207
void qof_error_set(QofSession *session, QofErrorId error)
Add an error to the stack for this session.
Definition: qoferror.c:112
void qof_session_begin(QofSession *session, const gchar *book_id, gboolean ignore_lock, gboolean create_if_nonexistent)
Definition: qofsession.c:1032
void qof_book_set_backend(QofBook *book, QofBackend *)
Set the backend used by this book.
Definition: qofbook.c:170
QofEntity * qof_collection_lookup_entity(QofCollection *col, const GUID *guid)
Definition: qofid.c:292
QofEntityReference * qof_entity_get_reference_from(QofEntity *ent, const QofParam *param)
Get a reference from this entity to another entity.
Definition: qofreference.c:167
void qof_collection_foreach(QofCollection *col, QofEntityForeachCB cb_func, gpointer user_data)
Definition: qofid.c:392
#define QOF_SUCCESS
Definition: qoferror.h:124
#define DEBUG(format, args...)
Definition: qoflog.h:208
QofBackend *(* backend_new)(void)
Definition: qofbackend-p.h:260
gboolean qof_entity_copy_list(QofSession *new_session, GList *entity_list)
Copy a GList of entities to another session.
Definition: qofsession.c:663
gchar * guid_to_string_buff(const GUID *guid, gchar *buff)
const gchar * qof_session_get_file_path(QofSession *session)
Definition: qofsession.c:189
gboolean qof_util_param_commit(QofInstance *inst, const QofParam *param)
Commit this parameter change, with undo support.
Definition: qofutil.c:309
void qof_book_set_data(QofBook *book, const gchar *key, gpointer data)
Definition: qofbook.c:191
QofEntity entity
Definition: qofinstance-p.h:39
gboolean qof_entity_copy_to_session(QofSession *new_session, QofEntity *original)
Copy a single QofEntity to another session.
Definition: qofsession.c:631
const QofParam * param
Definition: qofreference.h:113
GList * qof_class_get_referenceList(QofIdTypeConst type)
List of the parameters that could be references.
Definition: qofclass.c:329
const gchar * access_method
Definition: qofbackend-p.h:247
#define ENTITYREFERENCE
Definition: qofreference.h:137
QofIdType qof_collection_get_type(QofCollection *col)
Definition: qofid.c:146
Definition: guid.h:53
void qof_session_add_close_hook(GFunc fn, gpointer data)
Definition: qofsession.c:69
gboolean(* check_data_type)(const gchar *)
Distinguish two providers with same access method.
Definition: qofbackend-p.h:277
#define QOF_STDOUT
Allow session data to be printed to stdout.
Definition: qofsession.h:385
private api for data storage backend
const gchar * QofIdTypeConst
Definition: qofid.h:83
#define PWARN(format, args...)
Definition: qoflog.h:191
struct QofTime64 QofTime
Use a 64-bit signed int QofTime.
Definition: qoftime.h:112
void qof_event_suspend(void)
Suspend all engine events.
Definition: qofevent.c:145
const GUID * qof_entity_get_guid(QofEntity *ent)
Definition: qofid.c:105
External references in a partial QofBook.
Definition: qofreference.h:105
void qof_event_resume(void)
Definition: qofevent.c:156
void qof_session_save(QofSession *session, QofPercentageFunc percentage_func)
Definition: qofsession.c:1220
GList QofBookList
Definition: qofbook.h:64
void qof_session_end(QofSession *session)
Definition: qofsession.c:1374
void qof_error_clear(QofSession *session)
clear the error stack for the session.
Definition: qoferror.c:182
void qof_entity_set_guid(QofEntity *ent, const GUID *guid)
Definition: qofid.c:92
gint safe_strcmp(const gchar *da, const gchar *db)
Definition: qofutil.c:75
const gchar * provider_name
Definition: qofbackend-p.h:241
void qof_session_update_reference_list(QofSession *session, QofEntityReference *reference)
Adds a new reference to the partial book data hash.
Definition: qofsession.c:234
#define ENTER(format, args...)
Definition: qoflog.h:217
const gchar * QofLogModule
Definition: qofid.h:85
#define PARTIAL_QOFBOOK
Flag indicating a partial QofBook.
Definition: qofreference.h:146
void qof_book_destroy(QofBook *book)
Definition: qofbook.c:99