Session: Backend connections.
[Backends: Permanent storage for QOF entities.]


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.


Files

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

Session Errors

QofBackendError qof_session_get_error (QofSession *session)
const gchar * qof_session_get_error_message (QofSession *session)
QofBackendError qof_session_pop_error (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.
gboolean qof_entity_copy_list (QofSession *new_session, GList *entity_list)
 Copy a GList of entities to another session.
gboolean qof_entity_copy_coll (QofSession *new_session, QofCollection *entity_coll)
 Copy a QofCollection of entities.
gboolean qof_entity_copy_coll_r (QofSession *new_session, QofCollection *coll)
 Recursively copy a collection of entities to a session.
gboolean qof_entity_copy_one_r (QofSession *new_session, QofEntity *ent)
 Recursively copy a single entity to a new session.

Event Handling

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

Defines

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

Typedefs

typedef _QofSession QofSession
typedef void(*) QofPercentageFunc (const gchar *message, double 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 char *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)


Define 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 403 of file qofsession.h.


Typedef Documentation

typedef void(*) QofPercentageFunc(const gchar *message, double 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 166 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 826 of file qofsession.c.

00826 {
00827     QofSession *session;
00828     gboolean success;
00829     GList *ref_list;
00830     GList *ent_list;
00831 };
00832 
00833 static void
00834 recurse_collection_cb (QofEntity * ent, gpointer user_data)
00835 {
00836     struct recurse_s *store;
00837 
00838     if (user_data == NULL)
00839     {
00840         return;
00841     }
00842     store = (struct recurse_s *) user_data;
00843     if (!ent || !store)
00844     {
00845         return;
00846     }
00847     store->success = qof_entity_copy_to_session (store->session, ent);
00848     if (store->success)
00849     {
00850         store->ent_list = g_list_append (store->ent_list, ent);

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:
coll A QofCollection of entities that may or may not have references.
new_session The 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 1027 of file qofsession.c.

01032 {
01033     const gchar *libdir;
01034     const gchar *filename;
01035     const gchar *init_fcn;
01036 };
01037 
01038 /* All available QOF backends need to be described here
01039 and the last entry must be three NULL's.
01040 Remember: Use the libdir from the current build environment
01041 and use JUST the module name without .so - .so is not portable! */
01042 struct backend_providers backend_list[] = {
01043     {QOF_LIB_DIR, QSF_BACKEND_LIB, QSF_MODULE_INIT},
01044     {QOF_LIB_DIR, "libqof-backend-sqlite", "qof_sqlite_provider_init"},
01045 #ifdef HAVE_DWI
01046     {QOF_LIB_DIR, "libqof_backend_dwi", "dwiend_provider_init"},
01047 #endif
01048     {NULL, NULL, NULL}

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 800 of file qofsession.c.

00801 {
00802     QofEntityCopyData qecd;
00803 
00804     g_return_val_if_fail (new_session, FALSE);
00805     if (!entity_coll)
00806     {
00807         return FALSE;
00808     }
00809     qof_event_suspend ();
00810     qecd.param_list = NULL;
00811     qecd.new_session = new_session;
00812     qof_book_set_partial (qof_session_get_book (qecd.new_session));
00813     qof_collection_foreach (entity_coll, qof_entity_coll_foreach, &qecd);
00814     qof_class_param_foreach (qof_collection_get_type (entity_coll),
00815         qof_entity_param_cb, &qecd);
00816     qof_collection_foreach (entity_coll, qof_entity_coll_copy, &qecd);
00817     if (qecd.param_list != NULL)
00818     {
00819         g_slist_free (qecd.param_list);
00820     }
00821     qof_event_resume ();
00822     return TRUE;
00823 }

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:
ent A single entity that may or may not have references.
new_session The 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 1051 of file qofsession.c.

01053 {
01054     GSList *p;
01055     GList *node;
01056     QofBackendProvider *prov;
01057     QofBook *book;
01058     gchar *msg;
01059     gint num;
01060     gboolean prov_type;
01061     gboolean (*type_check) (const char *);
01062 
01063     ENTER (" list=%d", g_slist_length (provider_list));
01064     prov_type = FALSE;
01065     if (NULL == provider_list)
01066     {
01067         for (num = 0; backend_list[num].filename != NULL; num++)
01068         {
01069             if (!qof_load_backend_library (backend_list[num].libdir,
01070                     backend_list[num].filename,
01071                     backend_list[num].init_fcn))
01072             {
01073                 PWARN (" failed to load %s from %s using %s",
01074                     backend_list[num].filename, backend_list[num].libdir,
01075                     backend_list[num].init_fcn);
01076             }
01077         }

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 768 of file qofsession.c.

00774 {
00775     QofEntityCopyData *qecd;
00776 
00777     if (!new_session || !entity_list)
00778     {
00779         return FALSE;
00780     }
00781     ENTER (" list=%d", g_list_length (entity_list));
00782     qecd = g_new0 (QofEntityCopyData, 1);
00783     qof_event_suspend ();
00784     qecd->param_list = NULL;
00785     qecd->new_session = new_session;
00786     qof_book_set_partial (qof_session_get_book (new_session));
00787     g_list_foreach (entity_list, qof_entity_list_foreach, qecd);
00788     qof_event_resume ();
00789     if (qecd->error)
00790     {
00791         PWARN (" some/all entities in the list could not be copied.");
00792     }
00793     g_free (qecd);
00794     LEAVE (" ");
00795     return TRUE;
00796 }
00797 

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 233 of file qofsession.c.

00234 {
00235     GList *node;
00236     if (!session)
00237         return;
00238 
00239     ENTER (" sess=%p book=%p", session, addbook);
00240 
00241     /* See if this book is already there ... */
00242     for (node = session->books; node; node = node->next)
00243     {
00244         QofBook *book = node->data;
00245         if (addbook == book)
00246             return;
00247     }
00248 
00249     if ('y' == addbook->book_open)
00250     {
00251         /* hack alert -- someone should free all the books in the list,
00252          * but it should probably not be us ... since the books backends
00253          * should be shutdown first, etc */
00254 /* XXX this should probably be an error XXX */
00255         g_list_free (session->books);
00256         session->books = g_list_append (NULL, addbook);
00257     }
00258     else
00259     {
00260 /* XXX Need to tell the backend to add a book as well */
00261         session->books = g_list_append (session->books, addbook);
00262     }
00263 
00264     qof_book_set_backend (addbook, session->backend);
00265     LEAVE (" ");
00266 }

void qof_session_add_close_hook ( GFunc  fn,
gpointer  data 
)

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

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

Definition at line 65 of file qofsession.c.

00066 {
00067     GHook *hook;
00068 
00069     if (session_closed_hooks == NULL)
00070     {
00071         session_closed_hooks = malloc (sizeof (GHookList)); /* LEAKED */
00072         g_hook_list_init (session_closed_hooks, sizeof (GHook));
00073     }
00074 
00075     hook = g_hook_alloc (session_closed_hooks);
00076     if (!hook)
00077         return;
00078 
00079     hook->func = (GHookFunc) fn;
00080     hook->data = data;
00081     g_hook_append (session_closed_hooks, hook);
00082 }

void qof_session_begin ( QofSession session,
const char *  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.

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:
session A pointer to the session being closed.

Definition at line 85 of file qofsession.c.

00086 {
00087     GHook *hook;
00088     GFunc fn;
00089 
00090     if (session_closed_hooks == NULL)
00091         return;
00092 
00093     hook = g_hook_first_valid (session_closed_hooks, FALSE);
00094     while (hook)
00095     {
00096         fn = (GFunc) hook->func;
00097         fn (session, hook->data);
00098         hook = g_hook_next_valid (session_closed_hooks, hook, FALSE);
00099     }
00100 }

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 1581 of file qofsession.c.

01586 {
01587     GList *books_1, *books_2, *node;
01588 
01589     if (session_1 == session_2)
01590         return;
01591     if (!session_1 || !session_2)
01592         return;
01593 
01594     ENTER (" sess1=%p sess2=%p", session_1, session_2);
01595 
01596     books_1 = session_1->books;
01597     books_2 = session_2->books;
01598 
01599     session_1->books = books_2;
01600     session_2->books = books_1;
01601 
01602     for (node = books_1; node; node = node->next)

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 1673 of file qofsession.c.

QofBackendError qof_session_get_error ( QofSession session  ) 

The qof_session_get_error() routine can be used to obtain the reason for any failure. Calling this routine returns the current error.

Definition at line 139 of file qofsession.c.

00140 {
00141     QofBackendError err;
00142 
00143     if (!session)
00144         return ERR_BACKEND_NO_BACKEND;
00145 
00146     /* if we have a local error, return that. */
00147     if (ERR_BACKEND_NO_ERR != session->last_err)
00148     {
00149         return session->last_err;
00150     }
00151 
00152     /* maybe we should return a no-backend error ??? */
00153     if (!session->backend)
00154         return ERR_BACKEND_NO_ERR;
00155 
00156     err = qof_backend_get_error (session->backend);
00157     session->last_err = err;
00158     return err;
00159 }

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 277 of file qofsession.c.

00278 {
00279     if (!session)
00280         return NULL;
00281     if (!session->backend)
00282         return NULL;
00283     return session->backend->fullpath;
00284 }

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.

QofBackendError qof_session_pop_error ( QofSession session  ) 

The qof_session_pop_error() routine can be used to obtain the reason for any failure. Calling this routine resets the error value.

This routine allows an implementation of multiple error values, e.g. in a stack, where this routine pops the top value. The current implementation has a stack that is one-deep.

See qofbackend.h for a listing of returned errors.

Definition at line 179 of file qofsession.c.

00180 {
00181     QofBackendError err;
00182 
00183     if (!session)
00184         return ERR_BACKEND_NO_BACKEND;
00185 
00186     err = qof_session_get_error (session);
00187     qof_session_clear_error (session);
00188 
00189     return err;
00190 }

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 1686 of file qofsession.c.

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 1418 of file qofsession.c.

01424         {
01425             prov = p->data;
01426             if (TRUE == prov->partial_book_supported)
01427             {
01429                 /*  if((TRUE == prov->partial_book_supported) && 
01430                    (0 == strcasecmp (access_method, prov->access_method)))
01431                    { */
01432                 if (NULL == prov->backend_new)
01433                     continue;
01434                 /* Use the providers creation callback */
01435                 session->backend = (*(prov->backend_new)) ();
01436                 session->backend->provider = prov;
01437                 if (session->backend->session_begin)
01438                 {
01439                     /* Call begin - backend has been changed,
01440                        so make sure a file can be written,
01441                        use ignore_lock and create_if_nonexistent */
01442                     g_free (session->book_id);
01443                     session->book_id = NULL;
01444                     (session->backend->session_begin) (session->backend,
01445                         session, book_id, TRUE, TRUE);
01446                     PINFO
01447                         (" Done running session_begin on changed backend");
01448                     err = qof_backend_get_error (session->backend);
01449                     msg = qof_backend_get_message (session->backend);
01450                     if (err != ERR_BACKEND_NO_ERR)
01451                     {
01452                         g_free (session->book_id);
01453                         session->book_id = NULL;
01454                         qof_session_push_error (session, err, msg);
01455                         LEAVE (" changed backend error %d", err);
01456                         return;
01457                     }
01458                     if (msg != NULL)
01459                     {
01460                         PWARN ("%s", msg);
01461                         g_free (msg);
01462                     }
01463                 }
01464                 /* Tell the books about the backend that they'll be using. */
01465                 for (node = session->books; node; node = node->next)
01466                 {
01467                     book = node->data;
01468                     qof_book_set_backend (book, session->backend);
01469                 }
01470                 p = NULL;
01471             }
01472             if (p)
01473             {
01474                 p = p->next;
01475             }
01476         }
01477         if (!session->backend)
01478         {
01479             msg = g_strdup_printf (" failed to load backend");
01480             qof_session_push_error (session, ERR_BACKEND_NO_HANDLER, msg);
01481             return;
01482         }
01483     }
01484     /* If there is a backend, and the backend is reachable
01485      * (i.e. we can communicate with it), then synchronize with 
01486      * the backend.  If we cannot contact the backend (e.g.
01487      * because we've gone offline, the network has crashed, etc.)
01488      * then give the user the option to save to the local disk. 
01489      *
01490      * hack alert -- FIXME -- XXX the code below no longer
01491      * does what the words above say.  This needs fixing.
01492      */
01493     be = session->backend;
01494     if (be)
01495     {
01496         for (node = session->books; node; node = node->next)
01497         {
01498             abook = node->data;
01499             /* if invoked as SaveAs(), then backend not yet set */
01500             qof_book_set_backend (abook, be);
01501             be->percentage = percentage_func;
01502             if (be->sync)
01503             {
01504                 (be->sync) (be, abook);
01505                 if (save_error_handler (be, session))
01506                     return;
01507             }
01508         }
01509         /* If we got to here, then the backend saved everything 
01510          * just fine, and we are done. So return. */
01511         /* Return the book_id to previous value. */
01512         qof_session_clear_error (session);
01513         LEAVE (" Success");
01514         return;
01515     }
01516     else
01517     {
01518         msg = g_strdup_printf (" failed to load backend");
01519         qof_session_push_error (session, ERR_BACKEND_NO_HANDLER, msg);
01520     }
01521     LEAVE (" error -- No backend!");
01522 }
01523 
01524 /* ============================================================= */
01525 
01526 void
01527 qof_session_end (QofSession * session)
01528 {
01529     if (!session)
01530         return;
01531 
01532     ENTER (" sess=%p book_id=%s", session, session->book_id
01533         ? session->book_id : "(null)");
01534 
01535     /* close down the backend first */
01536     if (session->backend && session->backend->session_end)
01537     {
01538         (session->backend->session_end) (session->backend);
01539     }
01540 
01541     qof_session_clear_error (session);
01542 
01543     g_free (session->book_id);
01544     session->book_id = NULL;
01545 
01546     LEAVE (" sess=%p book_id=%s", session, session->book_id
01547         ? session->book_id : "(null)");
01548 }
01549 
01550 void
01551 qof_session_destroy (QofSession * session)
01552 {
01553     GList *node;
01554     if (!session)
01555         return;
01556 
01557     ENTER (" sess=%p book_id=%s", session, session->book_id
01558         ? session->book_id : "(null)");
01559 
01560     qof_session_end (session);
01561 
01562     /* destroy the backend */
01563     qof_session_destroy_backend (session);
01564 
01565     for (node = session->books; node; node = node->next)
01566     {
01567         QofBook *book = node->data;
01568         qof_book_set_backend (book, NULL);
01569         qof_book_destroy (book);
01570     }
01571 
01572     session->books = NULL;
01573 #ifndef QOF_DISABLE_DEPRECATED
01574     if (session == qof_session_get_current_session())
01575         qof_session_clear_current_session();
01576 #endif

gboolean qof_session_save_may_clobber_data ( QofSession session  ) 

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

Definition at line 1391 of file qofsession.c.

01392         {
01393             prov = session->backend->provider;
01394             if (TRUE == prov->partial_book_supported)
01395             {
01396                 /* if current backend supports partial, leave alone. */
01397                 change_backend = FALSE;
01398             }
01399             else
01400             {
01401                 change_backend = TRUE;

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 1639 of file qofsession.c.


Generated on Fri Sep 15 14:24:58 2006 for QOF by  doxygen 1.4.7