Files | |
file | qofsession.h |
Encapsulates a connection to a backend (persistent store). | |
Defines | |
#define | QOF_MOD_SESSION "qof-session" |
#define | QOF_STDOUT "file:" |
Allow session data to be printed to stdout. | |
Typedefs | |
typedef struct _QofSession | QofSession |
typedef void(* | QofPercentageFunc )(const gchar *message, gdouble percent) |
Functions | |
QofSession * | qof_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) |
QofBook * | qof_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. | |
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) |
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.
#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 386 of file qofsession.h.
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.
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
new_session | - the target session | |
entity_coll | - a QofCollection of any QofIdType. |
Definition at line 685 of file qofsession.c.
00687 { 00688 QofEntityCopyData qecd; 00689 00690 g_return_val_if_fail (new_session, FALSE); 00691 if (!entity_coll) 00692 { 00693 return FALSE; 00694 } 00695 qof_event_suspend (); 00696 qecd.param_list = NULL; 00697 qecd.new_session = new_session; 00698 qof_book_set_partial (qof_session_get_book (qecd.new_session)); 00699 qof_collection_foreach (entity_coll, qof_entity_coll_foreach, &qecd); 00700 qof_class_param_foreach (qof_collection_get_type (entity_coll), 00701 qof_entity_param_cb, &qecd); 00702 qof_collection_foreach (entity_coll, qof_entity_coll_copy, &qecd); 00703 if (qecd.param_list != NULL) 00704 { 00705 g_slist_free (qecd.param_list); 00706 } 00707 qof_event_resume (); 00708 return TRUE; 00709 }
gboolean qof_entity_copy_coll_r | ( | QofSession * | new_session, | |
QofCollection * | coll | |||
) |
Recursively copy a collection of entities to a session.
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.
coll | A QofCollection of entities that may or may not have references. | |
new_session | The QofSession to receive the copied entities. |
Definition at line 859 of file qofsession.c.
00860 { 00861 struct recurse_s store; 00862 gboolean success; 00863 00864 if ((!new_session) || (!coll)) 00865 { 00866 return FALSE; 00867 } 00868 store.session = new_session; 00869 success = TRUE; 00870 store.success = success; 00871 store.ent_list = NULL; 00872 store.ref_list = 00873 qof_class_get_referenceList (qof_collection_get_type (coll)); 00874 success = qof_entity_copy_coll (new_session, coll); 00875 if (success) 00876 { 00877 qof_collection_foreach (coll, recurse_ent_cb, &store); 00878 } 00879 return success; 00880 }
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.
new_session | - the target session | |
entity_list | - a GList of QofEntity pointers of any type(s). |
Definition at line 663 of file qofsession.c.
00664 { 00665 QofEntityCopyData *qecd; 00666 00667 if (!new_session || !entity_list) 00668 return FALSE; 00669 ENTER (" list=%d", g_list_length (entity_list)); 00670 qecd = g_new0 (QofEntityCopyData, 1); 00671 qof_event_suspend (); 00672 qecd->param_list = NULL; 00673 qecd->new_session = new_session; 00674 qof_book_set_partial (qof_session_get_book (new_session)); 00675 g_list_foreach (entity_list, qof_entity_list_foreach, qecd); 00676 qof_event_resume (); 00677 if (qecd->error) 00678 PWARN (" some/all entities in the list could not be copied."); 00679 g_free (qecd); 00680 LEAVE (" "); 00681 return TRUE; 00682 }
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.
ent | A single entity that may or may not have references. | |
new_session | The QofSession to receive the copied entities. |
Definition at line 883 of file qofsession.c.
00884 { 00885 struct recurse_s store; 00886 QofCollection *coll; 00887 gboolean success; 00888 00889 if ((!new_session) || (!ent)) 00890 { 00891 return FALSE; 00892 } 00893 store.session = new_session; 00894 success = TRUE; 00895 store.success = success; 00896 store.ref_list = qof_class_get_referenceList (ent->e_type); 00897 success = qof_entity_copy_to_session (new_session, ent); 00898 if (success == TRUE) 00899 { 00900 coll = 00901 qof_book_get_collection (qof_session_get_book (new_session), 00902 ent->e_type); 00903 if (coll) 00904 { 00905 qof_collection_foreach (coll, recurse_ent_cb, &store); 00906 } 00907 } 00908 return success; 00909 }
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.
new_session | - the target session | |
original | - the QofEntity* to copy |
Definition at line 631 of file qofsession.c.
00632 { 00633 QofEntityCopyData qecd; 00634 QofInstance *inst; 00635 QofBook *book; 00636 00637 if (!new_session || !original) 00638 return FALSE; 00639 if (qof_entity_guid_match (new_session, original)) 00640 return FALSE; 00641 if (!qof_object_compliance (original->e_type, TRUE)) 00642 return FALSE; 00643 qof_event_suspend (); 00644 qecd.param_list = NULL; 00645 book = qof_session_get_book (new_session); 00646 qecd.new_session = new_session; 00647 qof_book_set_partial (book); 00648 inst = 00649 (QofInstance *) qof_object_new_instance (original->e_type, book); 00650 qecd.to = &inst->entity; 00651 qecd.from = original; 00652 qof_entity_set_guid (qecd.to, qof_entity_get_guid (original)); 00653 qof_class_param_foreach (original->e_type, qof_entity_param_cb, &qecd); 00654 if (g_slist_length (qecd.param_list) == 0) 00655 return FALSE; 00656 g_slist_foreach (qecd.param_list, qof_entity_foreach_copy, &qecd); 00657 g_slist_free (qecd.param_list); 00658 qof_event_resume (); 00659 return TRUE; 00660 }
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.
00146 { 00147 GList *node; 00148 if (!session) 00149 return; 00150 00151 ENTER (" sess=%p book=%p", session, addbook); 00152 00153 /* See if this book is already there ... */ 00154 for (node = session->books; node; node = node->next) 00155 { 00156 QofBook *book = node->data; 00157 if (addbook == book) 00158 return; 00159 } 00160 00161 if ('y' == addbook->book_open) 00162 { 00163 /* hack alert -- someone should free all the books in the list, 00164 * but it should probably not be us ... since the books backends 00165 * should be shutdown first, etc */ 00166 /* XXX this should probably be an error XXX */ 00167 g_list_free (session->books); 00168 session->books = g_list_append (NULL, addbook); 00169 } 00170 else 00171 { 00172 /* XXX Need to tell the backend to add a book as well */ 00173 session->books = g_list_append (session->books, addbook); 00174 } 00175 00176 qof_book_set_backend (addbook, session->backend); 00177 LEAVE (" "); 00178 }
void qof_session_add_close_hook | ( | GFunc | fn, | |
gpointer | data | |||
) |
Register a function to be called just before a session is closed.
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 69 of file qofsession.c.
00070 { 00071 GHook *hook; 00072 00073 if (session_closed_hooks == NULL) 00074 { 00075 session_closed_hooks = malloc (sizeof (GHookList)); /* LEAKED */ 00076 g_hook_list_init (session_closed_hooks, sizeof (GHook)); 00077 } 00078 00079 hook = g_hook_alloc (session_closed_hooks); 00080 if (!hook) 00081 return; 00082 00083 hook->func = (GHookFunc) fn; 00084 hook->data = data; 00085 g_hook_append (session_closed_hooks, hook); 00086 }
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.
01034 { 01035 gchar *p, *access_method; 01036 01037 if (!session) 01038 return; 01039 01040 ENTER (" sess=%p ignore_lock=%d, book-id=%s", 01041 session, ignore_lock, book_id ? book_id : "(null)"); 01042 01043 /* Clear the error condition of previous errors */ 01044 qof_error_clear (session); 01045 01046 /* Check to see if this session is already open */ 01047 if (session->book_id) 01048 { 01049 qof_error_set (session, qof_error_register 01050 (_("This book appears to be open already."), FALSE)); 01051 LEAVE (" push error book is already open "); 01052 return; 01053 } 01054 01055 if (!book_id) 01056 { 01057 LEAVE (" using stdout"); 01058 return; 01059 } 01060 01061 /* Store the session URL */ 01062 session->book_id = g_strdup (book_id); 01063 01064 /* destroy the old backend */ 01065 qof_session_destroy_backend (session); 01066 01067 /* Look for something of the form of "file:/", "http://" or 01068 * "postgres://". Everything before the colon is the access 01069 * method. Load the first backend found for that access method. 01070 */ 01071 p = strchr (book_id, ':'); 01072 if (p) 01073 { 01074 access_method = g_strdup (book_id); 01075 p = strchr (access_method, ':'); 01076 *p = 0; 01077 qof_session_load_backend (session, access_method); 01078 g_free (access_method); 01079 } 01080 else 01081 { 01082 /* If no colon found, assume it must be a file-path */ 01083 qof_session_load_backend (session, "file"); 01084 } 01085 01086 /* No backend was found. That's bad. */ 01087 if (NULL == session->backend) 01088 { 01089 gchar * msg; 01090 01091 msg = g_strdup_printf (_("Unable to locate a " 01092 "suitable backend for '%s' - please check " 01093 "you have specified an access method " 01094 "like file: or sqlite:"), book_id); 01095 qof_error_set (session, qof_error_register 01096 (msg, FALSE)); 01097 DEBUG (" msg=%s", msg); 01098 LEAVE (" BAD: no backend: sess=%p book-id=%s", 01099 session, book_id ? book_id : "(null)"); 01100 g_free (msg); 01101 return; 01102 } 01103 01104 /* If there's a begin method, call that. */ 01105 if (session->backend->session_begin) 01106 { 01107 (session->backend->session_begin) (session->backend, session, 01108 session->book_id, ignore_lock, create_if_nonexistent); 01109 PINFO (" Done running session_begin on backend"); 01110 if (qof_error_check(session) != QOF_SUCCESS) 01111 { 01112 g_free (session->book_id); 01113 session->book_id = NULL; 01114 LEAVE (" backend error "); 01115 return; 01116 } 01117 } 01118 qof_error_clear (session); 01119 LEAVE (" sess=%p book-id=%s", session, book_id ? book_id : "(null)"); 01120 }
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.
session | A pointer to the session being closed. |
Definition at line 89 of file qofsession.c.
00090 { 00091 GHook *hook; 00092 GFunc fn; 00093 00094 if (session_closed_hooks == NULL) 00095 return; 00096 00097 hook = g_hook_first_valid (session_closed_hooks, FALSE); 00098 while (hook) 00099 { 00100 fn = (GFunc) hook->func; 00101 fn (session, hook->data); 00102 hook = g_hook_next_valid (session_closed_hooks, hook, FALSE); 00103 } 00104 }
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.
01375 { 01376 if (!session) 01377 return; 01378 01379 ENTER (" sess=%p book_id=%s", session, session->book_id 01380 ? session->book_id : "(null)"); 01381 01382 /* close down the backend first */ 01383 if (session->backend && session->backend->session_end) 01384 { 01385 (session->backend->session_end) (session->backend); 01386 } 01387 01388 qof_error_clear (session); 01389 01390 g_free (session->book_id); 01391 session->book_id = NULL; 01392 01393 LEAVE (" sess=%p book_id=%s", session, session->book_id 01394 ? session->book_id : "(null)"); 01395 }
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.
01464 { 01465 if (!session) 01466 return FALSE; 01467 if (!session->backend) 01468 return FALSE; 01469 if (!session->backend->events_pending) 01470 return FALSE; 01471 01472 return session->backend->events_pending (session->backend); 01473 }
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.
00190 { 00191 if (!session) 00192 return NULL; 00193 if (!session->backend) 00194 return NULL; 00195 return session->backend->fullpath; 00196 }
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.
01477 { 01478 if (!session) 01479 return FALSE; 01480 if (!session->backend) 01481 return FALSE; 01482 if (!session->backend->process_events) 01483 return FALSE; 01484 01485 return session->backend->process_events (session->backend); 01486 }
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.
Definition at line 1220 of file qofsession.c.
01222 { 01223 GList *node; 01224 QofBackend *be; 01225 gboolean partial, change_backend; 01226 QofBackendProvider *prov; 01227 GSList *p; 01228 QofBook *book, *abook; 01229 gint num; 01230 gchar *msg, *book_id; 01231 01232 if (!session) 01233 return; 01234 ENTER (" sess=%p book_id=%s", 01235 session, session->book_id ? session->book_id : "(null)"); 01236 /* Partial book handling. */ 01237 book = qof_session_get_book (session); 01238 partial = 01239 (gboolean) 01240 GPOINTER_TO_INT (qof_book_get_data (book, PARTIAL_QOFBOOK)); 01241 change_backend = FALSE; 01242 msg = g_strdup_printf (" "); 01243 book_id = g_strdup (session->book_id); 01244 if (partial == TRUE) 01245 { 01246 if (session->backend && session->backend->provider) 01247 { 01248 prov = session->backend->provider; 01249 if (TRUE == prov->partial_book_supported) 01250 { 01251 /* if current backend supports partial, leave alone. */ 01252 change_backend = FALSE; 01253 } 01254 else 01255 { 01256 change_backend = TRUE; 01257 } 01258 } 01259 /* If provider is undefined, assume partial not supported. */ 01260 else 01261 { 01262 change_backend = TRUE; 01263 } 01264 } 01265 if (change_backend == TRUE) 01266 { 01267 qof_session_destroy_backend (session); 01268 if (NULL == provider_list) 01269 { 01270 for (num = 0; backend_list[num].filename != NULL; num++) 01271 { 01272 qof_load_backend_library (backend_list[num].libdir, 01273 backend_list[num].filename, 01274 backend_list[num].init_fcn); 01275 } 01276 } 01277 p = g_slist_copy (provider_list); 01278 while (p != NULL) 01279 { 01280 prov = p->data; 01281 if (TRUE == prov->partial_book_supported) 01282 { 01284 /* if((TRUE == prov->partial_book_supported) && 01285 (0 == strcasecmp (access_method, prov->access_method))) 01286 { */ 01287 if (NULL == prov->backend_new) 01288 continue; 01289 /* Use the providers creation callback */ 01290 session->backend = (*(prov->backend_new)) (); 01291 session->backend->provider = prov; 01292 if (session->backend->session_begin) 01293 { 01294 /* Call begin - backend has been changed, 01295 so make sure a file can be written, 01296 use ignore_lock and create_if_nonexistent */ 01297 g_free (session->book_id); 01298 session->book_id = NULL; 01299 (session->backend->session_begin) (session->backend, 01300 session, book_id, TRUE, TRUE); 01301 PINFO 01302 (" Done running session_begin on changed backend"); 01303 if (qof_error_check (session) != QOF_SUCCESS) 01304 { 01305 g_free (session->book_id); 01306 session->book_id = NULL; 01307 LEAVE (" changed backend error"); 01308 return; 01309 } 01310 } 01311 /* Tell the books about the backend that they'll be using. */ 01312 for (node = session->books; node; node = node->next) 01313 { 01314 book = node->data; 01315 qof_book_set_backend (book, session->backend); 01316 } 01317 p = NULL; 01318 } 01319 if (p) 01320 { 01321 p = p->next; 01322 } 01323 } 01324 if (!session->backend) 01325 { 01326 msg = g_strdup_printf (" failed to load backend"); 01327 qof_error_set (session, qof_error_register 01328 (_("Failed to load backend, no suitable handler."), 01329 FALSE)); 01330 return; 01331 } 01332 } 01333 /* If there is a backend, and the backend is reachable 01334 * (i.e. we can communicate with it), then synchronize with 01335 * the backend. If we cannot contact the backend (e.g. 01336 * because we've gone offline, the network has crashed, etc.) 01337 * then give the user the option to save to the local disk. 01338 * 01339 * hack alert -- FIXME -- XXX the code below no longer 01340 * does what the words above say. This needs fixing. 01341 */ 01342 be = session->backend; 01343 if (be) 01344 { 01345 for (node = session->books; node; node = node->next) 01346 { 01347 abook = node->data; 01348 /* if invoked as SaveAs(), then backend not yet set */ 01349 qof_book_set_backend (abook, be); 01350 be->percentage = percentage_func; 01351 if (be->sync) 01352 (be->sync) (be, abook); 01353 } 01354 /* If we got to here, then the backend saved everything 01355 * just fine, and we are done. So return. */ 01356 /* Return the book_id to previous value. */ 01357 qof_error_clear (session); 01358 LEAVE (" Success"); 01359 return; 01360 } 01361 else 01362 { 01363 msg = g_strdup_printf (" failed to load backend"); 01364 qof_error_set (session, qof_error_register 01365 (_("Failed to load backend, no suitable handler."), 01366 FALSE)); 01367 } 01368 LEAVE (" error -- No backend!"); 01369 }
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.
01208 { 01209 if (!session) 01210 return FALSE; 01211 if (!session->backend) 01212 return FALSE; 01213 if (!session->backend->save_may_clobber_data) 01214 return FALSE; 01215 01216 return (*(session->backend->save_may_clobber_data)) (session->backend); 01217 }
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.
01430 { 01431 GList *books_1, *books_2, *node; 01432 01433 if (session_1 == session_2) 01434 return; 01435 if (!session_1 || !session_2) 01436 return; 01437 01438 ENTER (" sess1=%p sess2=%p", session_1, session_2); 01439 01440 books_1 = session_1->books; 01441 books_2 = session_2->books; 01442 01443 session_1->books = books_2; 01444 session_2->books = books_1; 01445 01446 for (node = books_1; node; node = node->next) 01447 { 01448 QofBook *book_1 = node->data; 01449 qof_book_set_backend (book_1, session_2->backend); 01450 } 01451 for (node = books_2; node; node = node->next) 01452 { 01453 QofBook *book_2 = node->data; 01454 qof_book_set_backend (book_2, session_1->backend); 01455 } 01456 01457 LEAVE (" "); 01458 }