QOF  0.8.7
Files | Macros | Typedefs | Functions

Files

file  qofsession.h
 Encapsulates a connection to a backend (persistent store)
 

Macros

#define QOF_MOD_SESSION   "qof-session"
 
#define QOF_STDOUT   "file:"
 Allow session data to be printed to stdout. More...
 

Typedefs

typedef struct _QofSession QofSession
 
typedef void(* QofPercentageFunc) (const gchar *message, gdouble percent)
 

Functions

QofSessionqof_session_new (void)
 
void qof_session_destroy (QofSession *session)
 
void qof_session_swap_data (QofSession *session_1, QofSession *session_2)
 
void qof_session_begin (QofSession *session, const gchar *book_id, gboolean ignore_lock, gboolean create_if_nonexistent)
 
void qof_session_load (QofSession *session, QofPercentageFunc percentage_func)
 
void qof_session_add_book (QofSession *session, QofBook *book)
 
QofBookqof_session_get_book (QofSession *session)
 
const gchar * qof_session_get_file_path (QofSession *session)
 
const gchar * qof_session_get_url (QofSession *session)
 
gboolean qof_session_not_saved (QofSession *session)
 
gboolean qof_session_save_may_clobber_data (QofSession *session)
 
void qof_session_save (QofSession *session, QofPercentageFunc percentage_func)
 
void qof_session_end (QofSession *session)
 
void qof_session_add_close_hook (GFunc fn, gpointer data)
 
void qof_session_call_close_hooks (QofSession *session)
 

Copying entities between sessions.

Only certain backends can cope with selective copying of entities and only fully defined QOF entities can be copied between sessions - see the QOF Serialisation Format (QSF) documentation (::qsf_write_file) for more information.

The recommended backend for the new session is QSF or a future SQL backend. Using any of these entity copy functions sets a flag in the backend that this is now a partial QofBook. See Reference: Referring to entities outside a partial book.. When you save a session containing a partial QofBook, the session will check that the backend is able to handle the partial book. If not, the backend will be replaced by one that can handle partial books, preferably one using the same ::access_method. Currently, this means that a book using the GnuCash XML v2 file backend will be switched to QSF.

Copied entities are identical to the source entity, all parameters defined with QofAccessFunc and QofSetterFunc in QOF are copied and the ::GUID of the original QofEntity is set in the new entity. Sessions containing copied entities are intended for use as mechanisms for data export.

It is acceptable to add entities to new_session in batches. Note that any of these calls will fail if an entity already exists in new_session with the same GUID as any entity to be copied.

To merge a whole QofBook or where there is any possibility of collisions or requirement for user intervention, see Merge: Merging QofBook structures

gboolean qof_entity_copy_to_session (QofSession *new_session, QofEntity *original)
 Copy a single QofEntity to another session. More...
 
gboolean qof_entity_copy_list (QofSession *new_session, GList *entity_list)
 Copy a GList of entities to another session. More...
 
gboolean qof_entity_copy_coll (QofSession *new_session, QofCollection *entity_coll)
 Copy a QofCollection of entities. More...
 
gboolean qof_entity_copy_coll_r (QofSession *new_session, QofCollection *coll)
 Recursively copy a collection of entities to a session. More...
 
gboolean qof_entity_copy_one_r (QofSession *new_session, QofEntity *ent)
 Recursively copy a single entity to a new session. More...
 

Event Handling

gboolean qof_session_events_pending (QofSession *session)
 
gboolean qof_session_process_events (QofSession *session)
 

Detailed Description

The QOF Session encapsulates a connection to a storage backend. That is, it manages the connection to a persistant data store; whereas the backend is the thing that performs the actual datastore access.

This class provides several important services:

1) It resolves and loads the appropriate backend, based on the URL.

2) It reports backend errors (e.g. network errors, storage corruption errors) through a single, backend-independent API.

3) It reports non-error events received from the backend.

4) It helps manage global dataset locks. For example, for the file backend, the lock prevents multiple users from editing the same file at the same time, thus avoiding lost data due to race conditions. Thus, an open session implies that the associated file is locked.

5) Misc utilities, such as a search path for the file to be edited, and/or other URL resolution utilities. This should simplify install & maintenance problems for naive users who may not have a good grasp on what a file system is, or where they want to keep their data files.

6) In the future, this class is probably a good place to manage a portion of the user authentication process, and hold user credentials/cookies/keys/tokens. This is because at the coarsest level, authorization can happen at the datastore level: i.e. does this user even have the authority to connect to and open this datastore?

A brief note about books & sessions: A book encapsulates the datasets manipulated by QOF. A book holds the actual data. By contrast, the session mediates the connection between a book (the thing that lives in virtual memory in the local process) and the datastore (the place where book data lives permanently, e.g., file, database).

In the current design, a session may hold multiple books. For now, exactly what this means is somewhat vague, and code in various places makes some implicit assumptions: first, only one book is 'current' and open for editing. Next, its assumed that all of the books in a session are related in some way. i.e. that they are all earlier accounting periods of the currently open book. In particular, the backends probably make that assumption, in order to store the different accounting periods in a clump so that one can be found, given another.

If you want multiple books that are unrelated to each other, use multiple sessions.

The session now calls QofBackendProvider->check_data_type to check that the incoming path contains data that the backend provider can open. The backend provider should also check if it can contact it's storage media (disk, network, server, etc.) and abort if it can't. Malformed file URL's would be handled the same way.

Macro Definition Documentation

#define QOF_STDOUT   "file:"

Allow session data to be printed to stdout.

book_id can't be NULL and we do need to have an access_method, so use one to solve the other.

To print a session to stdout, use qof_session_begin. Example:

qof_session_begin(session,QOF_STDOUT,TRUE,FALSE);

When you call qof_session_save(session, NULL), the output will appear on stdout and can be piped or redirected to other processes.

Currently, only the QSF backend supports writing to stdout, other backends may return a ::QofBackendError.

Definition at line 385 of file qofsession.h.

Typedef Documentation

typedef void(* QofPercentageFunc) (const gchar *message, gdouble percent)

The qof_session_load() method causes the QofBook to be made ready to to use with this URL/datastore. When the URL points at a file, then this routine would load the data from the file. With remote backends, e.g. network or SQL, this would load only enough data to make the book actually usable; it would not cause all of the data to be loaded.

XXX the current design tries to accomodate multiple calls to 'load' for each session, each time wiping out the old books; this seems wrong to me, and should be restricted to allow only one load per session.

Definition at line 168 of file qofsession.h.

Function Documentation

gboolean qof_entity_copy_coll ( QofSession new_session,
QofCollection entity_coll 
)

Copy a QofCollection of entities.

The QofBook in the new_session must not contain any entities with the same GUID as any entities in the collection - there is no support for handling collisions - instead, use Merge: Merging QofBook structures

Parameters
new_session- the target session
entity_coll- a QofCollection of any QofIdType.
Returns
FALSE, without copying, if new_session contains any entities with the same GUID. Otherwise TRUE.

Definition at line 685 of file qofsession.c.

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 }
void qof_class_param_foreach(QofIdTypeConst obj_name, QofParamForeachCB cb, gpointer user_data)
Definition: qofclass.c:268
void qof_collection_foreach(QofCollection *col, QofEntityForeachCB cb_func, gpointer user_data)
Definition: qofid.c:392
QofIdType qof_collection_get_type(QofCollection *col)
Definition: qofid.c:146
void qof_event_suspend(void)
Suspend all engine events.
Definition: qofevent.c:145
void qof_event_resume(void)
Definition: qofevent.c:156
gboolean qof_entity_copy_coll_r ( QofSession new_session,
QofCollection coll 
)

Recursively copy a collection of entities to a session.

Note
This function creates a partial QofBook. See qof_entity_copy_to_session for more information.

The QofBook in the new_session must not contain any entities with the same GUID as any entities to be copied - there is no support for handling collisions - instead, use Merge: Merging QofBook structures

Objects can be defined solely in terms of QOF data types or as a mix of data types and other objects, which may in turn include other objects. These references can be copied recursively down to the third level. See QofEntityReference.

Note
This is a deep recursive copy - every referenced entity is copied to the new session, including all parameters. The starting point is all entities in the top level collection. It can take some time.
Parameters
collA QofCollection of entities that may or may not have references.
new_sessionThe QofSession to receive the copied entities.
Returns
TRUE on success; if any individual copy fails, returns FALSE. Note : Some entities may have been copied successfully even if one of the references fails to copy.

Definition at line 859 of file qofsession.c.

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 }
gboolean qof_entity_copy_coll(QofSession *new_session, QofCollection *entity_coll)
Copy a QofCollection of entities.
Definition: qofsession.c:685
void qof_collection_foreach(QofCollection *col, QofEntityForeachCB cb_func, gpointer user_data)
Definition: qofid.c:392
GList * qof_class_get_referenceList(QofIdTypeConst type)
List of the parameters that could be references.
Definition: qofclass.c:329
QofIdType qof_collection_get_type(QofCollection *col)
Definition: qofid.c:146
gboolean qof_entity_copy_list ( QofSession new_session,
GList *  entity_list 
)

Copy a GList of entities to another session.

The QofBook in the new_session must not contain any entities with the same GUID as any of the source entities - there is no support for handling collisions, instead use Merge: Merging QofBook structures

Note that the GList (e.g. from qof_sql_query_run) can contain QofEntity pointers of any QofIdType, in any sequence. As long as all members of the list are QofEntity*, and all GUID's are unique, the list can be copied.

Parameters
new_session- the target session
entity_list- a GList of QofEntity pointers of any type(s).
Returns
FALSE, without copying, if new_session contains any entities with the same GUID. Otherwise TRUE.

Definition at line 663 of file qofsession.c.

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 }
#define LEAVE(format, args...)
Definition: qoflog.h:227
#define PWARN(format, args...)
Definition: qoflog.h:191
void qof_event_suspend(void)
Suspend all engine events.
Definition: qofevent.c:145
void qof_event_resume(void)
Definition: qofevent.c:156
#define ENTER(format, args...)
Definition: qoflog.h:217
gboolean qof_entity_copy_one_r ( QofSession new_session,
QofEntity ent 
)

Recursively copy a single entity to a new session.

Copy the single entity and all referenced entities to the second level.

Only entities that are directly referenced by the top level entity are copied.

This is a deep copy - all parameters of all referenced entities are copied. If the top level entity has no references, this is identical to qof_entity_copy_to_session.

Parameters
entA single entity that may or may not have references.
new_sessionThe QofSession to receive the copied entities.
Returns
TRUE on success; if any individual copy fails, returns FALSE. Note : Some entities may have been copied successfully even if one of the references fails to copy.

Definition at line 883 of file qofsession.c.

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 }
QofCollection * qof_book_get_collection(QofBook *book, QofIdType entity_type)
Definition: qofbook.c:220
struct QofCollection_s QofCollection
Definition: qofid.h:138
void qof_collection_foreach(QofCollection *col, QofEntityForeachCB cb_func, gpointer user_data)
Definition: qofid.c:392
gboolean qof_entity_copy_to_session(QofSession *new_session, QofEntity *original)
Copy a single QofEntity to another session.
Definition: qofsession.c:631
GList * qof_class_get_referenceList(QofIdTypeConst type)
List of the parameters that could be references.
Definition: qofclass.c:329
gboolean qof_entity_copy_to_session ( QofSession new_session,
QofEntity original 
)

Copy a single QofEntity to another session.

Checks first that no entity in the session book contains the GUID of the source entity.

Parameters
new_session- the target session
original- the QofEntity* to copy
Returns
FALSE without copying if the session contains an entity with the same GUID already, otherwise TRUE.

Definition at line 631 of file qofsession.c.

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 }
gpointer qof_object_new_instance(QofIdTypeConst type_name, QofBook *book)
Definition: qofobject.c:42
void qof_class_param_foreach(QofIdTypeConst obj_name, QofParamForeachCB cb, gpointer user_data)
Definition: qofclass.c:268
gboolean qof_object_compliance(QofIdTypeConst type_name, gboolean warn)
check an object can be created and supports iteration
Definition: qofobject.c:155
QofEntity entity
Definition: qofinstance-p.h:39
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
void qof_event_resume(void)
Definition: qofevent.c:156
void qof_entity_set_guid(QofEntity *ent, const GUID *guid)
Definition: qofid.c:92
void qof_session_add_book ( QofSession session,
QofBook book 
)

The qof_session_add_book() allows additional books to be added to a session. XXX Under construction, clarify the following when done: XXX There must already be an open book in the session already!? XXX Only one open book at a time per session is allowed!? XXX each book gets its own unique backend ???

Definition at line 145 of file qofsession.c.

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 }
#define LEAVE(format, args...)
Definition: qoflog.h:227
void qof_book_set_backend(QofBook *book, QofBackend *)
Set the backend used by this book.
Definition: qofbook.c:170
#define ENTER(format, args...)
Definition: qoflog.h:217
void qof_session_add_close_hook ( GFunc  fn,
gpointer  data 
)

Register a function to be called just before a session is closed.

Parameters
fnThe function to be called. The function definition must be func(gpointer session, gpointer user_data);
dataThe data to be passed to the function.

Definition at line 69 of file qofsession.c.

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 }
void qof_session_begin ( QofSession session,
const gchar *  book_id,
gboolean  ignore_lock,
gboolean  create_if_nonexistent 
)

The qof_session_begin () method begins a new session. It takes as an argument the book id. The book id must be a string in the form of a URI/URL. The access method specified depends on the loaded backends. In the absence of a customised backend, only QSF XML would be accepted). Paths may be relative or absolute. If the path is relative; that is, if the argument is "file:somefile.xml" then the current working directory is assumed. Customised backends can choose to search other, application-specific, directories as well.

The 'ignore_lock' argument, if set to TRUE, will cause this routine to ignore any global-datastore locks (e.g. file locks) that it finds. If set to FALSE, then file/database-global locks will be tested and obeyed.

If the datastore exists, can be reached (e.g over the net), connected to, opened and read, and a lock can be obtained then a lock will be obtained. Note that multi-user datastores (e.g. the SQL backend) typically will not need to get a global lock, and thus, the user will not be locked out. That's the whole point of 'multi-user'.

If the file/database doesn't exist, and the create_if_nonexistent flag is set to TRUE, then the database is created.

If an error occurs, it will be pushed onto the session error stack, and that is where it should be examined.

Definition at line 1032 of file qofsession.c.

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 }
QofErrorId qof_error_register(const gchar *err_message, gboolean use_file)
Generate and register a new error.
Definition: qoferror.c:73
#define PINFO(format, args...)
Definition: qoflog.h:199
QofErrorId qof_error_check(QofSession *session)
Definition: qoferror.c:197
#define LEAVE(format, args...)
Definition: qoflog.h:227
void qof_error_set(QofSession *session, QofErrorId error)
Add an error to the stack for this session.
Definition: qoferror.c:112
#define QOF_SUCCESS
Definition: qoferror.h:124
#define DEBUG(format, args...)
Definition: qoflog.h:208
void qof_error_clear(QofSession *session)
clear the error stack for the session.
Definition: qoferror.c:182
#define ENTER(format, args...)
Definition: qoflog.h:217
void qof_session_call_close_hooks ( QofSession session)

Call all registered session close hooks, informing them that the specified session is about to be closed.

Parameters
sessionA pointer to the session being closed.

Definition at line 89 of file qofsession.c.

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 }
void qof_session_end ( QofSession session)

The qof_session_end() method will release the session lock. For the file backend, it will not save the data to a file. Thus, this method acts as an "abort" or "rollback" primitive. However, for other backends, such as the sql backend, the data would have been written out before this, and so this routines wouldn't roll-back anything; it would just shut the connection.

Definition at line 1374 of file qofsession.c.

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 }
#define LEAVE(format, args...)
Definition: qoflog.h:227
void qof_error_clear(QofSession *session)
clear the error stack for the session.
Definition: qoferror.c:182
#define ENTER(format, args...)
Definition: qoflog.h:217
gboolean qof_session_events_pending ( QofSession session)

The qof_session_events_pending() method will return TRUE if the backend has pending events which must be processed to bring the engine up to date with the backend.

Definition at line 1463 of file qofsession.c.

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 }
const gchar* qof_session_get_file_path ( QofSession session)

The qof_session_get_file_path() routine returns the fully-qualified file path for the session. That is, if a relative or partial filename was for the session, then it had to have been fully resolved to open the session. This routine returns the result of this resolution. The path is always guaranteed to reside in the local file system, even if the session itself was opened as a URL. (currently, the filepath is derived from the url by substituting commas for slashes).

The qof_session_get_url() routine returns the url that was opened. URL's for local files take the form of file:/some/where/some/file.gml

Definition at line 189 of file qofsession.c.

190 {
191  if (!session)
192  return NULL;
193  if (!session->backend)
194  return NULL;
195  return session->backend->fullpath;
196 }
gchar * fullpath
Definition: qofbackend-p.h:332
gboolean qof_session_not_saved ( QofSession session)

The qof_session_not_saved() subroutine will return TRUE if any data in the session hasn't been saved to long-term storage.

gboolean qof_session_process_events ( QofSession session)

The qof_session_process_events() method will process any events indicated by the qof_session_events_pending() method. It returns TRUE if the engine was modified while engine events were suspended.

Definition at line 1476 of file qofsession.c.

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 }
void qof_session_save ( QofSession session,
QofPercentageFunc  percentage_func 
)

The qof_session_save() method will commit all changes that have been made to the session. For the file backend, this is nothing more than a write to the file of the current AccountGroup & etc. For the SQL backend, this is typically a no-op (since all data has already been written out to the database.

Todo:
check the access_method too, not in scope here, yet.

Definition at line 1220 of file qofsession.c.

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 }
QofErrorId qof_error_register(const gchar *err_message, gboolean use_file)
Generate and register a new error.
Definition: qoferror.c:73
#define PINFO(format, args...)
Definition: qoflog.h:199
QofErrorId qof_error_check(QofSession *session)
Definition: qoferror.c:197
gpointer qof_book_get_data(QofBook *book, const gchar *key)
Definition: qofbook.c:212
gboolean partial_book_supported
Partial QofBook handler.
Definition: qofbackend-p.h:254
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
#define LEAVE(format, args...)
Definition: qoflog.h:227
void qof_error_set(QofSession *session, QofErrorId error)
Add an error to the stack for this session.
Definition: qoferror.c:112
void qof_book_set_backend(QofBook *book, QofBackend *)
Set the backend used by this book.
Definition: qofbook.c:170
#define QOF_SUCCESS
Definition: qoferror.h:124
QofBackend *(* backend_new)(void)
Definition: qofbackend-p.h:260
void qof_error_clear(QofSession *session)
clear the error stack for the session.
Definition: qoferror.c:182
#define ENTER(format, args...)
Definition: qoflog.h:217
#define PARTIAL_QOFBOOK
Flag indicating a partial QofBook.
Definition: qofreference.h:146
gboolean qof_session_save_may_clobber_data ( QofSession session)

Allows the backend to warn the user if a dataset already exists.

Definition at line 1207 of file qofsession.c.

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 }
gboolean(* save_may_clobber_data)(QofBackend *)
Definition: qofbackend-p.h:320
void qof_session_swap_data ( QofSession session_1,
QofSession session_2 
)

The qof_session_swap_data () method swaps the book of the two given sessions. It is useful for 'Save As' type functionality.

Definition at line 1429 of file qofsession.c.

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 }
#define LEAVE(format, args...)
Definition: qoflog.h:227
void qof_book_set_backend(QofBook *book, QofBackend *)
Set the backend used by this book.
Definition: qofbook.c:170
#define ENTER(format, args...)
Definition: qoflog.h:217