Backends are used to save and restore Entities in a Book.
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 | qof-be-utils.h |
| QOF Backend Utilities. | |
| file | qofbackend.h |
| API for data storage Backend. | |
| file | qofsession.h |
| Encapsulates a connection to a backend (persistent store). | |
Modules | |
| QOF Serialisation Format | |
Data Structures | |
| struct | QofBackendOption_s |
| struct | qof_entity_reference |
| External references in a partial QofBook. More... | |
Using a partial QofBook. | |
| Part of the handling for partial books requires a storage mechanism for references to entities that are not within reach of the partial book. This requires a GList in the book data to contain the reference QofIdType and GUID so that when the book is written out, the reference can be included. See qof_book_get_data. When the file is imported back in, the list needs to be rebuilt. The QSF backend rebuilds the references by linking to real entities. Other backends can process the hash table in similar ways. The list stores the QofEntityReference to the referenced entity - a struct that contains the GUID and the QofIdType of the referenced entity as well as the parameter used to obtain the reference.
Partial books need to be differentiated in the backend, the flag in the book data is used by qof_session_save to prevent a partial book being saved using a backend that requires a full book. | |
| #define | ENTITYREFERENCE "QofEntityReference" |
| #define | PARTIAL_QOFBOOK "PartialQofBook" |
| Flag indicating a partial QofBook. | |
| typedef qof_entity_reference | QofEntityReference |
| External references in a partial QofBook. | |
| QofEntityReference * | qof_entity_get_reference_from (QofEntity *ent, const QofParam *param) |
| Get a reference from this entity to another entity. | |
| void | qof_session_update_reference_list (QofSession *session, QofEntityReference *reference) |
| Adds a new reference to the partial book data hash. | |
Backend Configuration using KVP | |
| The backend uses qof_backend_get_config to pass back a KvpFrame of QofBackendOption that includes the translated strings that serve as description and tooltip for that option. i.e. backends need to run gettext in the init function. qof_backend_prepare_frame, qof_backend_prepare_option and qof_backend_complete_frame are intended to be used by the backend itself to create the options.
qof_backend_get_config, qof_backend_option_foreach and qof_backend_load_config are intended for either the backend or the frontend to retrieve the option data from the frame or set new data. | |
| typedef QofBackendOption_s | QofBackendOption |
| typedef void(* | QofBackendOptionCB )(QofBackendOption *, gpointer data) |
| void | qof_backend_prepare_frame (QofBackend *be) |
| void | qof_backend_prepare_option (QofBackend *be, QofBackendOption *option) |
| KvpFrame * | qof_backend_complete_frame (QofBackend *be) |
| void | qof_backend_option_foreach (KvpFrame *config, QofBackendOptionCB cb, gpointer data) |
| void | qof_backend_load_config (QofBackend *be, KvpFrame *config) |
| Load configuration options specific to this backend. | |
| KvpFrame * | qof_backend_get_config (QofBackend *be) |
| Get the available configuration options. | |
Allow access to the begin routine for this backend. | |
| QOF_BEGIN_EDIT and QOF_COMMIT_EDIT_PART1 and part2 rely on calling QofBackend *be->begin and be->commit. This means the QofBackend struct becomes part of the public API. These function replaces those calls to allow the macros to be used when QOF is built as a library. | |
| void | qof_backend_run_begin (QofBackend *be, QofInstance *inst) |
| gboolean | qof_backend_begin_exists (QofBackend *be) |
| void | qof_backend_run_commit (QofBackend *be, QofInstance *inst) |
| gboolean | qof_backend_commit_exists (QofBackend *be) |
Session Errors | |
| QofBackendError | qof_session_get_error (QofSession *session) |
| const char * | 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. 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 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_BEGIN_EDIT(inst) |
| #define | QOF_COMMIT_EDIT_PART1(inst) |
| #define | QOF_COMMIT_EDIT_PART2(inst, on_error, on_done, on_free) |
| #define | QOF_MOD_BACKEND "qof-backend" |
| #define | QOF_MOD_SESSION "qof-session" |
| #define | QOF_STDOUT "file:" |
| Allow session data to be printed to stdout. | |
Typedefs | |
| typedef QofBackendProvider_s | QofBackendProvider |
| typedef QofBackend_s | QofBackend |
| Pseudo-object providing an interface between the engine and a persistant data store (e.g. a server, a database, or a file). | |
| typedef void(* | QofBePercentageFunc )(const char *message, double percent) |
| DOCUMENT ME! | |
| typedef _QofSession | QofSession |
| typedef void(* | QofPercentageFunc )(const char *message, double percent) |
Enumerations | |
| enum | QofBackendError { ERR_BACKEND_NO_ERR = 0, ERR_BACKEND_NO_HANDLER, ERR_BACKEND_NO_BACKEND, ERR_BACKEND_BAD_URL, ERR_BACKEND_NO_SUCH_DB, ERR_BACKEND_CANT_CONNECT, ERR_BACKEND_CONN_LOST, ERR_BACKEND_LOCKED, ERR_BACKEND_READONLY, ERR_BACKEND_TOO_NEW, ERR_BACKEND_DATA_CORRUPT, ERR_BACKEND_SERVER_ERR, ERR_BACKEND_ALLOC, ERR_BACKEND_PERM, ERR_BACKEND_MODIFIED, ERR_BACKEND_MOD_DESTROY, ERR_BACKEND_MISC, ERR_QSF_INVALID_OBJ, ERR_QSF_INVALID_MAP, ERR_QSF_BAD_OBJ_GUID, ERR_QSF_BAD_QOF_VERSION, ERR_QSF_BAD_MAP, ERR_QSF_NO_MAP, ERR_QSF_WRONG_MAP, ERR_QSF_MAP_NOT_OBJ, ERR_QSF_OVERFLOW, ERR_QSF_OPEN_NOT_MERGE, ERR_FILEIO_FILE_BAD_READ = 1000, ERR_FILEIO_FILE_EMPTY, ERR_FILEIO_FILE_LOCKERR, ERR_FILEIO_FILE_NOT_FOUND, ERR_FILEIO_FILE_TOO_OLD, ERR_FILEIO_UNKNOWN_FILE_TYPE, ERR_FILEIO_PARSE_ERROR, ERR_FILEIO_BACKUP_ERROR, ERR_FILEIO_WRITE_ERROR, ERR_NETIO_SHORT_READ = 2000, ERR_NETIO_WRONG_CONTENT_TYPE, ERR_NETIO_NOT_GNCXML, ERR_SQL_MISSING_DATA = 3000, ERR_SQL_DB_TOO_OLD, ERR_SQL_DB_BUSY, ERR_RPC_HOST_UNK = 4000, ERR_RPC_CANT_BIND, ERR_RPC_CANT_ACCEPT, ERR_RPC_NO_CONNECTION, ERR_RPC_BAD_VERSION, ERR_RPC_FAILED, ERR_RPC_NOT_ADDED } |
| The errors that can be reported to the GUI & other front-end users. More... | |
Functions | |
| gboolean | qof_begin_edit (QofInstance *inst) |
| function version of QOF_BEGIN_EDIT | |
| gboolean | qof_commit_edit (QofInstance *inst) |
| function version of QOF_COMMIT_EDIT_PART1 | |
| gboolean | qof_load_backend_library (const char *directory, const char *filename, const char *init_fcn) |
| Load a QOF-compatible backend shared library. | |
| QofBackend * | qof_book_get_backend (QofBook *book) |
| Retrieve the backend used by this book. | |
| void | qof_book_set_backend (QofBook *book, QofBackend *) |
| QofSession * | qof_session_new (void) |
| void | qof_session_destroy (QofSession *session) |
| QofSession * | qof_session_get_current_session (void) |
| void | qof_session_set_current_session (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) |
| QofBook * | qof_session_get_book (QofSession *session) |
| const char * | qof_session_get_file_path (QofSession *session) |
| const char * | 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) |
|
|
Used as the key value for the QofBook data hash. Retrieved later by QSF (or any other suitable backend) to rebuild the references from the QofEntityReference struct that contains the QofIdType and GUID of the referenced entity of the original QofBook as well as the parameter data and the GUID of the original entity. Definition at line 473 of file qofsession.h. |
|
|
Flag indicating a partial QofBook. When set in the book data with a gboolean value of TRUE, the flag denotes that only a backend that supports partial books can be used to save this session. Definition at line 482 of file qofsession.h. |
|
|
Value: QofBackend * be; \ if (!(inst)) return; \ \ (inst)->editlevel++; \ if (1 < (inst)->editlevel) return; \ \ if (0 >= (inst)->editlevel) \ { \ PERR ("unbalanced call - resetting (was %d)", (inst)->editlevel); \ (inst)->editlevel = 1; \ } \ ENTER ("(inst=%p)", (inst)); \ \ /* See if there's a backend. If there is, invoke it. */ \ be = qof_book_get_backend ((inst)->book); \ if (be && qof_backend_begin_exists((be))) { \ qof_backend_run_begin((be), (inst)); \ } else { \ /* We tried and failed to start transaction! */ \ (inst)->dirty = TRUE; \ } \ LEAVE (" ");
Uses newly created functions to allow the macro to be used when QOF is linked as a library. qofbackend-p.h is a private header. Definition at line 54 of file qof-be-utils.h. |
|
|
Value: { \
if (!(inst)) return; \
\
(inst)->editlevel--; \
if (0 < (inst)->editlevel) return; \
\
/* The pricedb sufffers from delayed update... */ \
/* This may be setting a bad precedent for other types, I fear. */ \
/* Other types probably really should handle begin like this. */ \
if ((-1 == (inst)->editlevel) && (inst)->dirty) \
{ \
QofBackend * be; \
be = qof_book_get_backend ((inst)->book); \
if (be && qof_backend_begin_exists((be))) { \
qof_backend_run_begin((be), (inst)); \
} \
(inst)->editlevel = 0; \
} \
if (0 > (inst)->editlevel) \
{ \
PERR ("unbalanced call - resetting (was %d)", (inst)->editlevel); \
(inst)->editlevel = 0; \
} \
ENTER ("(inst=%p) dirty=%d do-free=%d", \
(inst), (inst)->dirty, (inst)->do_free); \
}
Definition at line 99 of file qof-be-utils.h. |
|
|
part2 -- deal with the backend
Definition at line 146 of file qof-be-utils.h. |
|
|
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 502 of file qofsession.h. |
|
|
Pseudo-object providing an interface between the engine and a persistant data store (e.g. a server, a database, or a file). There are no backend functions that are 'public' to users of the engine. The backend can, however, report errors to the GUI & other front-end users. Definition at line 152 of file qofbackend.h. |
|
|
A single Backend Configuration Option. |
|
|
Backend configuration option foreach callback prototype. Definition at line 210 of file qofbackend.h. |
|
|
A structure that declares backend services that can be gotten. The Provider specifies a URL access method, and specifies the function to create a backend that can handle that URL access function. Definition at line 142 of file qofbackend.h. |
|
|
External references in a partial QofBook. For use by any session that deals with partial QofBooks. It is used by the entity copy functions and by the QSF backend. Creates a GList stored in the Book hashtable to contain repeated references for a single entity. |
|
|
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. |
|
|
The errors that can be reported to the GUI & other front-end users.
Definition at line 52 of file qofbackend.h. 00052 { 00053 ERR_BACKEND_NO_ERR = 0, 00054 ERR_BACKEND_NO_HANDLER, 00055 ERR_BACKEND_NO_BACKEND, 00056 ERR_BACKEND_BAD_URL, 00057 ERR_BACKEND_NO_SUCH_DB, 00058 ERR_BACKEND_CANT_CONNECT, 00059 ERR_BACKEND_CONN_LOST, 00060 ERR_BACKEND_LOCKED, 00061 ERR_BACKEND_READONLY, 00062 ERR_BACKEND_TOO_NEW, 00063 ERR_BACKEND_DATA_CORRUPT, 00064 ERR_BACKEND_SERVER_ERR, 00065 ERR_BACKEND_ALLOC, 00066 ERR_BACKEND_PERM, 00068 ERR_BACKEND_MODIFIED, 00070 ERR_BACKEND_MOD_DESTROY, 00072 ERR_BACKEND_MISC, 00074 /* QSF add-ons */ 00075 ERR_QSF_INVALID_OBJ, 00076 ERR_QSF_INVALID_MAP, 00077 ERR_QSF_BAD_OBJ_GUID, 00078 ERR_QSF_BAD_QOF_VERSION, 00079 ERR_QSF_BAD_MAP, 00084 ERR_QSF_NO_MAP, 00088 ERR_QSF_WRONG_MAP, 00093 ERR_QSF_MAP_NOT_OBJ, 00094 ERR_QSF_OVERFLOW, 00100 ERR_QSF_OPEN_NOT_MERGE, 00105 /* fileio errors */ 00106 ERR_FILEIO_FILE_BAD_READ = 1000, 00107 ERR_FILEIO_FILE_EMPTY, 00108 ERR_FILEIO_FILE_LOCKERR, 00109 ERR_FILEIO_FILE_NOT_FOUND, 00110 ERR_FILEIO_FILE_TOO_OLD, 00111 ERR_FILEIO_UNKNOWN_FILE_TYPE, 00112 ERR_FILEIO_PARSE_ERROR, 00113 ERR_FILEIO_BACKUP_ERROR, 00114 ERR_FILEIO_WRITE_ERROR, 00116 /* network errors */ 00117 ERR_NETIO_SHORT_READ = 2000, 00118 ERR_NETIO_WRONG_CONTENT_TYPE, 00119 ERR_NETIO_NOT_GNCXML, 00121 /* database errors */ 00122 ERR_SQL_MISSING_DATA = 3000, 00123 ERR_SQL_DB_TOO_OLD, 00124 ERR_SQL_DB_BUSY, 00126 /* RPC errors */ 00127 ERR_RPC_HOST_UNK = 4000, 00128 ERR_RPC_CANT_BIND, 00129 ERR_RPC_CANT_ACCEPT, 00130 ERR_RPC_NO_CONNECTION, 00131 ERR_RPC_BAD_VERSION, 00132 ERR_RPC_FAILED, 00133 ERR_RPC_NOT_ADDED, 00134 } QofBackendError;
|
|
|
Complete the backend_configuration and return the frame. Definition at line 244 of file qofbackend.c. 00245 { 00246 g_return_val_if_fail(be, NULL); 00247 be->config_count = 0; 00248 return be->backend_configuration; 00249 }
|
|
|
Get the available configuration options. To retrieve the options from the returned KvpFrame, the caller needs to parse the XML file that documents the option names and data types. The XML file itself is part of the backend and is installed in a directory determined by the backend. Therefore, loading a new backend requires two paths: the path to the .la file and the path to the xml. Both paths are available by including a generated header file, e.g. gncla-dir.h defines GNC_LIB_DIR for the location of the .la file and GNC_XML_DIR for the xml.
Definition at line 343 of file qofbackend.c. 00344 { 00345 if(!be) { return NULL; } 00346 if(!be->get_config) { return NULL; } 00347 return (be->get_config) (be); 00348 }
|
|
||||||||||||
|
Load configuration options specific to this backend.
Definition at line 335 of file qofbackend.c. 00336 { 00337 if(!be || !config) { return; } 00338 if(!be->load_config) { return; } 00339 (be->load_config) (be, config); 00340 }
|
|
||||||||||||||||
|
Iterate over the frame and process each option. Definition at line 320 of file qofbackend.c. 00321 { 00322 struct config_iterate helper; 00323 00324 if(!config || !cb) { return; } 00325 ENTER (" "); 00326 helper.fcn = cb; 00327 helper.count = 1; 00328 helper.data = data; 00329 helper.recursive = config; 00330 kvp_frame_for_each_slot(config, config_foreach_cb, &helper); 00331 LEAVE (" "); 00332 }
|
|
|
Initialise the backend_configuration Definition at line 175 of file qofbackend.c. 00176 { 00177 g_return_if_fail(be); 00178 if(!kvp_frame_is_empty(be->backend_configuration)) { 00179 kvp_frame_delete(be->backend_configuration); 00180 be->backend_configuration = kvp_frame_new(); 00181 } 00182 be->config_count = 0; 00183 }
|
|
||||||||||||
|
Add an option to the backend_configuration. Repeat for more. Definition at line 185 of file qofbackend.c. 00186 { 00187 KvpValue *value; 00188 gchar *temp; 00189 gint count; 00190 00191 g_return_if_fail(be || option); 00192 count = be->config_count; 00193 count++; 00194 value = NULL; 00195 ENTER (" %d", count); 00196 switch (option->type) 00197 { 00198 case KVP_TYPE_GINT64 : { 00199 value = kvp_value_new_gint64(*(gint64*)option->value); 00200 break; 00201 } 00202 case KVP_TYPE_DOUBLE : { 00203 value = kvp_value_new_double(*(double*)option->value); 00204 break; 00205 } 00206 case KVP_TYPE_NUMERIC : { 00207 value = kvp_value_new_numeric(*(gnc_numeric*)option->value); 00208 break; 00209 } 00210 case KVP_TYPE_STRING : { 00211 value = kvp_value_new_string((const char*)option->value); 00212 break; 00213 } 00214 case KVP_TYPE_GUID : { break; } /* unsupported */ 00215 case KVP_TYPE_TIMESPEC : { 00216 value = kvp_value_new_timespec(*(Timespec*)option->value); 00217 break; 00218 } 00219 case KVP_TYPE_BINARY : { break; } /* unsupported */ 00220 case KVP_TYPE_GLIST : { break; } /* unsupported */ 00221 case KVP_TYPE_FRAME : { break; } /* unsupported */ 00222 } 00223 if(value) { 00224 temp = g_strdup_printf("/%s", option->option_name); 00225 kvp_frame_set_value(be->backend_configuration, temp, value); 00226 PINFO (" setting value at %s", temp); 00227 g_free(temp); 00228 temp = g_strdup_printf("/%s/%s", QOF_CONFIG_DESC, option->option_name); 00229 PINFO (" setting description %s at %s", option->description, temp); 00230 kvp_frame_set_string(be->backend_configuration, temp, option->description); 00231 PINFO (" check= %s", kvp_frame_get_string(be->backend_configuration, temp)); 00232 g_free(temp); 00233 temp = g_strdup_printf("/%s/%s", QOF_CONFIG_TIP, option->option_name); 00234 PINFO (" setting tooltip %s at %s", option->tooltip, temp); 00235 kvp_frame_set_string(be->backend_configuration, temp, option->tooltip); 00236 PINFO (" check= %s", kvp_frame_get_string(be->backend_configuration, temp)); 00237 g_free(temp); 00238 /* only increment the counter if successful */ 00239 be->config_count = count; 00240 } 00241 LEAVE (" "); 00242 }
|
|
|
function version of QOF_BEGIN_EDIT The macro cannot be used in a function that returns a value, this function can be used instead. Definition at line 359 of file qofbackend.c. 00360 { 00361 QofBackend * be; 00362 00363 if (!inst) { return FALSE; } 00364 (inst->editlevel)++; 00365 if (1 < inst->editlevel) { return FALSE; } 00366 if (0 >= inst->editlevel) { inst->editlevel = 1; } 00367 be = qof_book_get_backend (inst->book); 00368 if (be && qof_backend_begin_exists(be)) { 00369 qof_backend_run_begin(be, inst); 00370 } else { inst->dirty = TRUE; } 00371 return TRUE; 00372 }
|
|
|
function version of QOF_COMMIT_EDIT_PART1 The macro cannot be used in a function that returns a value, this function can be used instead. Only Part1 is implemented. Definition at line 374 of file qofbackend.c. 00375 { 00376 QofBackend * be; 00377 00378 if (!inst) { return FALSE; } 00379 (inst->editlevel)--; 00380 if (0 < inst->editlevel) { return FALSE; } 00381 if ((-1 == inst->editlevel) && inst->dirty) 00382 { 00383 be = qof_book_get_backend ((inst)->book); 00384 if (be && qof_backend_begin_exists(be)) { 00385 qof_backend_run_begin(be, inst); 00386 } 00387 inst->editlevel = 0; 00388 } 00389 if (0 > inst->editlevel) { inst->editlevel = 0; } 00390 return TRUE; 00391 }
|
|
||||||||||||
|
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 Merging QofBook structures
Definition at line 638 of file qofsession.c. 00639 { 00640 QofEntityCopyData qecd; 00641 00642 gnc_engine_suspend_events(); 00643 qecd.param_list = NULL; 00644 qecd.new_session = new_session; 00645 qof_book_set_partial(qof_session_get_book(qecd.new_session)); 00646 qof_collection_foreach(entity_coll, qof_entity_coll_foreach, &qecd); 00647 qof_class_param_foreach(qof_collection_get_type(entity_coll), qof_entity_param_cb, &qecd); 00648 qof_collection_foreach(entity_coll, qof_entity_coll_copy, &qecd); 00649 if(qecd.param_list != NULL) { g_slist_free(qecd.param_list); } 00650 gnc_engine_resume_events(); 00651 return TRUE; 00652 }
|
|
||||||||||||
|
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.
Definition at line 754 of file qofsession.c. 00755 { 00756 struct recurse_s store; 00757 gboolean success; 00758 00759 if((!new_session)||(!coll)) { return FALSE; } 00760 store.session = new_session; 00761 success = TRUE; 00762 store.success = success; 00763 store.ent_list = NULL; 00764 store.ref_list = qof_class_get_referenceList(qof_collection_get_type(coll)); 00765 success = qof_entity_copy_coll(new_session, coll); 00766 if(success){ qof_collection_foreach(coll, recurse_ent_cb, &store); } 00767 return success; 00768 }
|
|
||||||||||||
|
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 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.
Definition at line 620 of file qofsession.c. 00621 { 00622 QofEntityCopyData *qecd; 00623 00624 if(!new_session || !entity_list) { return FALSE; } 00625 ENTER (" list=%d", g_list_length(entity_list)); 00626 qecd = g_new0(QofEntityCopyData, 1); 00627 gnc_engine_suspend_events(); 00628 qecd->param_list = NULL; 00629 qecd->new_session = new_session; 00630 qof_book_set_partial(qof_session_get_book(new_session)); 00631 g_list_foreach(entity_list, qof_entity_list_foreach, qecd); 00632 gnc_engine_resume_events(); 00633 g_free(qecd); 00634 LEAVE (" "); 00635 return TRUE; 00636 }
|
|
||||||||||||
|
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.
Definition at line 770 of file qofsession.c. 00771 { 00772 struct recurse_s store; 00773 QofCollection *coll; 00774 gboolean success; 00775 00776 if((!new_session)||(!ent)) { return FALSE; } 00777 store.session = new_session; 00778 success = TRUE; 00779 store.success = success; 00780 store.ref_list = qof_class_get_referenceList(ent->e_type); 00781 success = qof_entity_copy_to_session(new_session, ent); 00782 if(success == TRUE) { 00783 coll = qof_book_get_collection(qof_session_get_book(new_session), ent->e_type); 00784 qof_collection_foreach(coll, recurse_ent_cb, &store); 00785 } 00786 return success; 00787 }
|
|
||||||||||||
|
Copy a single QofEntity to another session. Checks first that no entity in the session book contains the GUID of the source entity.
Definition at line 593 of file qofsession.c. 00594 { 00595 QofEntityCopyData qecd; 00596 QofInstance *inst; 00597 QofBook *book; 00598 00599 if(!new_session || !original) { return FALSE; } 00600 if(qof_entity_guid_match(new_session, original)) { return FALSE; } 00601 gnc_engine_suspend_events(); 00602 qecd.param_list = NULL; 00603 book = qof_session_get_book(new_session); 00604 qecd.new_session = new_session; 00605 qof_book_set_partial(book); 00606 inst = (QofInstance*)qof_object_new_instance(original->e_type, book); 00607 qecd.to = &inst->entity; 00608 qecd.from = original; 00609 qof_entity_set_guid(qecd.to, qof_entity_get_guid(original)); 00610 qof_begin_edit(inst); 00611 qof_class_param_foreach(original->e_type, qof_entity_param_cb, &qecd); 00612 qof_commit_edit(inst); 00613 if(g_slist_length(qecd.param_list) == 0) { return FALSE; } 00614 g_slist_foreach(qecd.param_list, qof_entity_foreach_copy, &qecd); 00615 g_slist_free(qecd.param_list); 00616 gnc_engine_resume_events(); 00617 return TRUE; 00618 }
|
|
||||||||||||
|
Get a reference from this entity to another entity. Used in the preparation of a partial QofBook when the known entity (the one currently being copied into the partial book) refers to any other entity, usually as a parent or child. The routine calls the param_getfcn of the supplied parameter, which must return an object (QofEntity*), not a known QOF data type, to retrieve the referenced entity and therefore the GUID. The GUID of both entities are stored in the reference which then needs to be added to the reference list which is added to the partial book data hash. The reference itself is used by the backend to preserve the relationship between entities within and outside the partial book. See also qof_class_get_referenceList to obtain the list of parameters that provide references to the known entity whilst excluding parameters that return known QOF data types. Note that even if the referenced entity exists in the partial book (or will exist later), a reference must still be obtained and added to the reference list for the book itself. This maintains the integrity of the partial book during sequential copy operations.
Definition at line 359 of file qofsession.c. 00360 { 00361 QofEntityReference *reference; 00362 QofEntity *ref_ent; 00363 const GUID *cm_guid; 00364 char cm_sa[GUID_ENCODING_LENGTH + 1]; 00365 gchar *cm_string; 00366 00367 g_return_val_if_fail(param, NULL); 00368 ref_ent = (QofEntity*)param->param_getfcn(ent, param); 00369 if(ref_ent != NULL) { 00370 reference = g_new0(QofEntityReference, 1); 00371 reference->type = ent->e_type; 00372 reference->ref_guid = g_new(GUID, 1); 00373 reference->ent_guid = &ent->guid; 00374 reference->param = qof_class_get_parameter(ent->e_type, param->param_name); 00375 cm_guid = qof_entity_get_guid(ref_ent); 00376 guid_to_string_buff(cm_guid, cm_sa); 00377 cm_string = g_strdup(cm_sa); 00378 if(TRUE == string_to_guid(cm_string, reference->ref_guid)) { 00379 return reference; 00380 } 00381 } 00382 return NULL; 00383 }
|
|
||||||||||||||||
|
Load a QOF-compatible backend shared library.
Definition at line 394 of file qofbackend.c. 00396 { 00397 struct stat sbuf; 00398 gchar *fullpath; 00399 typedef void (* backend_init) (void); 00400 GModule *backend; 00401 backend_init gmod_init; 00402 gpointer g; 00403 00404 g_return_val_if_fail(g_module_supported(), FALSE); 00405 fullpath = g_module_build_path(directory, filename); 00406 PINFO (" fullpath=%s", fullpath); 00407 g_return_val_if_fail((stat(fullpath, &sbuf) == 0), FALSE); 00408 backend = g_module_open(fullpath, G_MODULE_BIND_LAZY); 00409 if(!backend) { 00410 g_message ("%s: %s\n", PACKAGE, g_module_error ()); 00411 return FALSE; 00412 } 00413 g = &gmod_init; 00414 if (!g_module_symbol (backend, init_fcn, g)) 00415 { 00416 g_message ("%s: %s\n", PACKAGE, g_module_error ()); 00417 return FALSE; 00418 } 00419 g_module_make_resident(backend); 00420 gmod_init(); 00421 return TRUE; 00422 }
|
|
||||||||||||
|
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 254 of file qofsession.c. 00255 { 00256 GList *node; 00257 if (!session) return; 00258 00259 ENTER (" sess=%p book=%p", session, addbook); 00260 00261 /* See if this book is already there ... */ 00262 for (node=session->books; node; node=node->next) 00263 { 00264 QofBook *book = node->data; 00265 if (addbook == book) return; 00266 } 00267 00268 if ('y' == addbook->book_open) 00269 { 00270 /* hack alert -- someone should free all the books in the list, 00271 * but it should probably not be us ... since the books backends 00272 * should be shutdown first, etc */ 00273 /* XXX this should probably be an error XXX */ 00274 g_list_free (session->books); 00275 session->books = g_list_append (NULL, addbook); 00276 } 00277 else 00278 { 00279 /* XXX Need to tell the backend to add a book as well */ 00280 session->books = g_list_append (session->books, addbook); 00281 } 00282 00283 qof_book_set_backend (addbook, session->backend); 00284 LEAVE (" "); 00285 }
|
|
||||||||||||
|
Register a function to be called just before a session is closed.
Definition at line 75 of file qofsession.c. 00076 { 00077 GHook *hook; 00078 00079 if (session_closed_hooks == NULL) { 00080 session_closed_hooks = malloc(sizeof(GHookList)); /* LEAKED */ 00081 g_hook_list_init (session_closed_hooks, sizeof(GHook)); 00082 } 00083 00084 hook = g_hook_alloc(session_closed_hooks); 00085 if (!hook) 00086 return; 00087 00088 hook->func = (GHookFunc)fn; 00089 hook->data = data; 00090 g_hook_append(session_closed_hooks, hook); 00091 }
|
|
||||||||||||||||||||
|
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 910 of file qofsession.c. 00912 { 00913 char *p, *access_method, *msg; 00914 int err; 00915 00916 if (!session) return; 00917 00918 ENTER (" sess=%p ignore_lock=%d, book-id=%s", 00919 session, ignore_lock, 00920 book_id ? book_id : "(null)"); 00921 00922 /* Clear the error condition of previous errors */ 00923 qof_session_clear_error (session); 00924 00925 /* Check to see if this session is already open */ 00926 if (session->book_id) 00927 { 00928 qof_session_push_error (session, ERR_BACKEND_LOCKED, NULL); 00929 LEAVE("push error book is already open "); 00930 return; 00931 } 00932 00933 /* seriously invalid */ 00934 if (!book_id) 00935 { 00936 qof_session_push_error (session, ERR_BACKEND_BAD_URL, NULL); 00937 LEAVE("push error missing book_id"); 00938 return; 00939 } 00940 00941 /* Store the session URL */ 00942 session->book_id = g_strdup (book_id); 00943 00944 /* destroy the old backend */ 00945 qof_session_destroy_backend(session); 00946 00947 /* Look for something of the form of "file:/", "http://" or 00948 * "postgres://". Everything before the colon is the access 00949 * method. Load the first backend found for that access method. 00950 */ 00951 p = strchr (book_id, ':'); 00952 if (p) 00953 { 00954 access_method = g_strdup (book_id); 00955 p = strchr (access_method, ':'); 00956 *p = 0; 00957 qof_session_load_backend(session, access_method); 00958 g_free (access_method); 00959 } 00960 else 00961 { 00962 /* If no colon found, assume it must be a file-path */ 00963 qof_session_load_backend(session, "file"); 00964 } 00965 00966 /* No backend was found. That's bad. */ 00967 if (NULL == session->backend) 00968 { 00969 qof_session_push_error (session, ERR_BACKEND_BAD_URL, NULL); 00970 LEAVE (" BAD: no backend: sess=%p book-id=%s", 00971 session, book_id ? book_id : "(null)"); 00972 return; 00973 } 00974 00975 /* If there's a begin method, call that. */ 00976 if (session->backend->session_begin) 00977 { 00978 00979 (session->backend->session_begin)(session->backend, session, 00980 session->book_id, ignore_lock, 00981 create_if_nonexistent); 00982 PINFO("Done running session_begin on backend"); 00983 err = qof_backend_get_error(session->backend); 00984 msg = qof_backend_get_message(session->backend); 00985 if (err != ERR_BACKEND_NO_ERR) 00986 { 00987 g_free(session->book_id); 00988 session->book_id = NULL; 00989 qof_session_push_error (session, err, msg); 00990 LEAVE(" backend error %d %s", err, msg); 00991 return; 00992 } 00993 if (msg != NULL) 00994 { 00995 PWARN("%s", msg); 00996 g_free(msg); 00997 } 00998 } 00999 01000 LEAVE (" sess=%p book-id=%s", 01001 session, book_id ? book_id : "(null)"); 01002 }
|
|
|
Call all registered session close hooks, informing them that the specified session is about to be closed.
Definition at line 94 of file qofsession.c. 00095 { 00096 GHook *hook; 00097 GFunc fn; 00098 00099 if (session_closed_hooks == NULL) 00100 return; 00101 00102 hook = g_hook_first_valid (session_closed_hooks, FALSE); 00103 while (hook) { 00104 fn = (GFunc)hook->func; 00105 fn(session, hook->data); 00106 hook = g_hook_next_valid (session_closed_hooks, hook, FALSE); 00107 } 00108 }
|
|
|
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 1266 of file qofsession.c. 01267 { 01268 if (!session) return; 01269 01270 ENTER ("sess=%p book_id=%s", session, session->book_id 01271 ? session->book_id : "(null)"); 01272 01273 /* close down the backend first */ 01274 if (session->backend && session->backend->session_end) 01275 { 01276 (session->backend->session_end)(session->backend); 01277 } 01278 01279 qof_session_clear_error (session); 01280 01281 g_free (session->book_id); 01282 session->book_id = NULL; 01283 01284 LEAVE ("sess=%p book_id=%s", session, session->book_id 01285 ? session->book_id : "(null)"); 01286 }
|
|
|
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 1354 of file qofsession.c. 01355 { 01356 if (!session) return FALSE; 01357 if (!session->backend) return FALSE; 01358 if (!session->backend->events_pending) return FALSE; 01359 01360 return session->backend->events_pending (session->backend); 01361 }
|
|
|
Definition at line 219 of file qofsession.c. 00220 { 00221 if (!current_session) 00222 { 00223 gnc_engine_suspend_events (); 00224 current_session = qof_session_new (); 00225 gnc_engine_resume_events (); 00226 } 00227 00228 return current_session; 00229 }
|
|
|
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 145 of file qofsession.c. 00146 { 00147 QofBackendError err; 00148 00149 if (!session) return ERR_BACKEND_NO_BACKEND; 00150 00151 /* if we have a local error, return that. */ 00152 if (ERR_BACKEND_NO_ERR != session->last_err) 00153 { 00154 return session->last_err; 00155 } 00156 00157 /* maybe we should return a no-backend error ??? */ 00158 if (! session->backend) return ERR_BACKEND_NO_ERR; 00159 00160 err = qof_backend_get_error (session->backend); 00161 session->last_err = err; 00162 return err; 00163 }
|
|
|
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 295 of file qofsession.c. 00296 { 00297 if (!session) return NULL; 00298 if (!session->backend) return NULL; 00299 return session->backend->fullpath; 00300 }
|
|
|
The qof_session_not_saved() subroutine will return TRUE if any data in the session hasn't been saved to long-term storage. |
|
|
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 181 of file qofsession.c. 00182 { 00183 QofBackendError err; 00184 00185 if (!session) return ERR_BACKEND_NO_BACKEND; 00186 00187 err = qof_session_get_error(session); 00188 qof_session_clear_error(session); 00189 00190 return err; 00191 }
|
|
|
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 1364 of file qofsession.c. 01365 { 01366 if (!session) return FALSE; 01367 if (!session->backend) return FALSE; 01368 if (!session->backend->process_events) return FALSE; 01369 01370 return session->backend->process_events (session->backend); 01371 }
|
|
||||||||||||
|
Definition at line 1119 of file qofsession.c. 01121 { 01122 GList *node; 01123 QofBackend *be; 01124 gboolean partial, change_backend; 01125 QofBackendProvider *prov; 01126 GSList *p; 01127 QofBook *book, *abook; 01128 int err; 01129 gint num; 01130 char *msg, *book_id; 01131 01132 if (!session) return; 01133 ENTER ("sess=%p book_id=%s", 01134 session, session->book_id ? session->book_id : "(null)"); 01135 /* Partial book handling. */ 01136 book = qof_session_get_book(session); 01137 partial = (gboolean)GPOINTER_TO_INT(qof_book_get_data(book, PARTIAL_QOFBOOK)); 01138 change_backend = FALSE; 01139 msg = g_strdup_printf(" "); 01140 book_id = g_strdup(session->book_id); 01141 if(partial == TRUE) 01142 { 01143 if(session->backend && session->backend->provider) { 01144 prov = session->backend->provider; 01145 if(TRUE == prov->partial_book_supported) 01146 { 01147 /* if current backend supports partial, leave alone. */ 01148 change_backend = FALSE; 01149 } 01150 else { change_backend = TRUE; } 01151 } 01152 /* If provider is undefined, assume partial not supported. */ 01153 else { change_backend = TRUE; } 01154 } 01155 if(change_backend == TRUE) 01156 { 01157 qof_session_destroy_backend(session); 01158 if (NULL == provider_list) 01159 { 01160 for (num = 0; backend_list[num].filename != NULL; num++) { 01161 qof_load_backend_library(backend_list[num].libdir, 01162 backend_list[num].filename, backend_list[num].init_fcn); 01163 } 01164 } 01165 p = g_slist_copy(provider_list); 01166 while(p != NULL) 01167 { 01168 prov = p->data; 01169 if(TRUE == prov->partial_book_supported) 01170 { 01172 /* if((TRUE == prov->partial_book_supported) && 01173 (0 == strcasecmp (access_method, prov->access_method))) 01174 {*/ 01175 if (NULL == prov->backend_new) continue; 01176 /* Use the providers creation callback */ 01177 session->backend = (*(prov->backend_new))(); 01178 session->backend->provider = prov; 01179 if (session->backend->session_begin) 01180 { 01181 /* Call begin - backend has been changed, 01182 so make sure a file can be written, 01183 use ignore_lock and create_if_nonexistent */ 01184 g_free(session->book_id); 01185 session->book_id = NULL; 01186 (session->backend->session_begin)(session->backend, session, 01187 book_id, TRUE, TRUE); 01188 PINFO("Done running session_begin on changed backend"); 01189 err = qof_backend_get_error(session->backend); 01190 msg = qof_backend_get_message(session->backend); 01191 if (err != ERR_BACKEND_NO_ERR) 01192 { 01193 g_free(session->book_id); 01194 session->book_id = NULL; 01195 qof_session_push_error (session, err, msg); 01196 LEAVE("changed backend error %d", err); 01197 return; 01198 } 01199 if (msg != NULL) 01200 { 01201 PWARN("%s", msg); 01202 g_free(msg); 01203 } 01204 } 01205 /* Tell the books about the backend that they'll be using. */ 01206 for (node=session->books; node; node=node->next) 01207 { 01208 book = node->data; 01209 qof_book_set_backend (book, session->backend); 01210 } 01211 p = NULL; 01212 } 01213 if(p) { 01214 p = p->next; 01215 } 01216 } 01217 if(!session->backend) 01218 { 01219 msg = g_strdup_printf("failed to load backend"); 01220 qof_session_push_error(session, ERR_BACKEND_NO_HANDLER, msg); 01221 return; 01222 } 01223 } 01224 /* If there is a backend, and the backend is reachable 01225 * (i.e. we can communicate with it), then synchronize with 01226 * the backend. If we cannot contact the backend (e.g. 01227 * because we've gone offline, the network has crashed, etc.) 01228 * then give the user the option to save to the local disk. 01229 * 01230 * hack alert -- FIXME -- XXX the code below no longer 01231 * does what the words above say. This needs fixing. 01232 */ 01233 be = session->backend; 01234 if (be) 01235 { 01236 for (node = session->books; node; node=node->next) 01237 { 01238 abook = node->data; 01239 /* if invoked as SaveAs(), then backend not yet set */ 01240 qof_book_set_backend (abook, be); 01241 be->percentage = percentage_func; 01242 if (be->sync) 01243 { 01244 (be->sync)(be, abook); 01245 if (save_error_handler(be, session)) return; 01246 } 01247 } 01248 /* If we got to here, then the backend saved everything 01249 * just fine, and we are done. So return. */ 01250 /* Return the book_id to previous value. */ 01251 qof_session_clear_error (session); 01252 LEAVE("Success"); 01253 return; 01254 } 01255 else 01256 { 01257 msg = g_strdup_printf("failed to load backend"); 01258 qof_session_push_error(session, ERR_BACKEND_NO_HANDLER, msg); 01259 } 01260 LEAVE("error -- No backend!"); 01261 }
|
|
|
FIXME: This isn't as thorough as we might want it to be... Definition at line 1095 of file qofsession.c. 01096 { 01097 if (!session) return FALSE; 01098 if (!session->backend) return FALSE; 01099 if (!session->backend->save_may_clobber_data) return FALSE; 01100 01101 return (*(session->backend->save_may_clobber_data)) (session->backend); 01102 }
|
|
|
Definition at line 234 of file qofsession.c. 00235 { 00236 current_session = session; 00237 }
|
|
||||||||||||
|
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 1322 of file qofsession.c. 01323 { 01324 GList *books_1, *books_2, *node; 01325 01326 if (session_1 == session_2) return; 01327 if (!session_1 || !session_2) return; 01328 01329 ENTER ("sess1=%p sess2=%p", session_1, session_2); 01330 01331 books_1 = session_1->books; 01332 books_2 = session_2->books; 01333 01334 session_1->books = books_2; 01335 session_2->books = books_1; 01336 01337 for (node=books_1; node; node=node->next) 01338 { 01339 QofBook *book_1 = node->data; 01340 qof_book_set_backend (book_1, session_2->backend); 01341 } 01342 for (node=books_2; node; node=node->next) 01343 { 01344 QofBook *book_2 = node->data; 01345 qof_book_set_backend (book_2, session_1->backend); 01346 } 01347 01348 LEAVE (" "); 01349 }
|
|
||||||||||||
|
Adds a new reference to the partial book data hash. Retrieves any existing reference list and appends the new reference. If the book is not already marked as partial, it will be marked as partial. Definition at line 333 of file qofsession.c. 00334 { 00335 QofBook *book; 00336 GList *book_ref_list; 00337 00338 book = qof_session_get_book(session); 00339 book_ref_list = (GList*)qof_book_get_data(book, ENTITYREFERENCE); 00340 book_ref_list = g_list_append(book_ref_list, reference); 00341 qof_book_set_data(book, ENTITYREFERENCE, book_ref_list); 00342 qof_book_set_partial(book); 00343 }
|
1.4.5