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.
|
compression level Type: gint (KVP_TYPE_GINT64) Use GINT_TO_POINTER() to set a integer value between 0 and 9. Definition at line 177 of file qof-backend-qsf.h. |
|
Encoding string. Defaults of UTF-8. Definition at line 199 of file qof-backend-qsf.h. |
|
selected QSF maps Type: GList* (KVP_TYPE_GLIST) of const char* (QOF_TYPE_STRING) values. Defaults to the pre-installed QSF map(s) but may be overridden by the application to pass full path(s) of user selected QSF map file(s). If you override the list, it is advisable to only specify the single map file for this QSF object to reduce the amount of error checking required within the backend. Simply reset the QofBackendOption before another file is to be opened. It is up to the application to decide how to offer multiple map selections to the user. Definition at line 194 of file qof-backend-qsf.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 157 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 147 of file qofbackend.h. |
|
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 55 of file qofbackend.h. 00055 { 00056 ERR_BACKEND_NO_ERR = 0, 00057 ERR_BACKEND_NO_HANDLER, 00058 ERR_BACKEND_NO_BACKEND, 00059 ERR_BACKEND_BAD_URL, 00060 ERR_BACKEND_NO_SUCH_DB, 00061 ERR_BACKEND_CANT_CONNECT, 00062 ERR_BACKEND_CONN_LOST, 00063 ERR_BACKEND_LOCKED, 00064 ERR_BACKEND_READONLY, 00065 ERR_BACKEND_TOO_NEW, 00066 ERR_BACKEND_DATA_CORRUPT, 00067 ERR_BACKEND_SERVER_ERR, 00068 ERR_BACKEND_ALLOC, 00069 ERR_BACKEND_PERM, 00071 ERR_BACKEND_MODIFIED, 00073 ERR_BACKEND_MOD_DESTROY, 00075 ERR_BACKEND_MISC, 00077 /* QSF add-ons */ 00078 ERR_QSF_INVALID_OBJ, 00079 ERR_QSF_INVALID_MAP, 00080 ERR_QSF_BAD_OBJ_GUID, 00081 ERR_QSF_BAD_QOF_VERSION, 00082 ERR_QSF_BAD_MAP, 00087 ERR_QSF_NO_MAP, 00091 ERR_QSF_WRONG_MAP, 00096 ERR_QSF_MAP_NOT_OBJ, 00097 ERR_QSF_OVERFLOW, 00103 ERR_QSF_OPEN_NOT_MERGE, 00108 /* fileio errors */ 00109 ERR_FILEIO_FILE_BAD_READ = 1000, 00110 ERR_FILEIO_FILE_EMPTY, 00111 ERR_FILEIO_FILE_LOCKERR, 00112 ERR_FILEIO_FILE_NOT_FOUND, 00113 ERR_FILEIO_FILE_TOO_OLD, 00114 ERR_FILEIO_UNKNOWN_FILE_TYPE, 00115 ERR_FILEIO_PARSE_ERROR, 00116 ERR_FILEIO_BACKUP_ERROR, 00117 ERR_FILEIO_WRITE_ERROR, 00118 ERR_FILEIO_READ_ERROR, 00119 ERR_FILEIO_NO_ENCODING, 00121 /* network errors */ 00122 ERR_NETIO_SHORT_READ = 2000, 00123 ERR_NETIO_WRONG_CONTENT_TYPE, 00124 ERR_NETIO_NOT_GNCXML, 00126 /* database errors */ 00127 ERR_SQL_MISSING_DATA = 3000, 00128 ERR_SQL_DB_TOO_OLD, 00129 ERR_SQL_DB_BUSY, 00131 /* RPC errors */ 00132 ERR_RPC_HOST_UNK = 4000, 00133 ERR_RPC_CANT_BIND, 00134 ERR_RPC_CANT_ACCEPT, 00135 ERR_RPC_NO_CONNECTION, 00136 ERR_RPC_BAD_VERSION, 00137 ERR_RPC_FAILED, 00138 ERR_RPC_NOT_ADDED, 00139 } QofBackendError;
|
|
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 1011 of file qofsession.c. 01015 { 01016 qof_session_push_error (session, ERR_BACKEND_BAD_URL, NULL); 01017 LEAVE (" BAD: no backend: sess=%p book-id=%s", 01018 session, book_id ? book_id : "(null)"); 01019 return; 01020 } 01021 01022 /* If there's a begin method, call that. */ 01023 if (session->backend->session_begin) 01024 { 01025 01026 (session->backend->session_begin)(session->backend, session, 01027 session->book_id, ignore_lock, 01028 create_if_nonexistent); 01029 PINFO("Done running session_begin on backend"); 01030 err = qof_backend_get_error(session->backend); 01031 msg = qof_backend_get_message(session->backend); 01032 if (err != ERR_BACKEND_NO_ERR) 01033 { 01034 g_free(session->book_id); 01035 session->book_id = NULL; 01036 qof_session_push_error (session, err, msg); 01037 LEAVE(" backend error %d %s", err, msg); 01038 return; 01039 } 01040 if (msg != NULL) 01041 { 01042 PWARN("%s", msg); 01043 g_free(msg); 01044 } 01045 } 01046 01047 LEAVE (" sess=%p book-id=%s", 01048 session, book_id ? book_id : "(null)"); 01049 } 01050 01051 /* ====================================================================== */ 01052 01053 void 01054 qof_session_load (QofSession *session, 01055 QofPercentageFunc percentage_func) 01056 { 01057 QofBook *newbook, *ob; 01058 QofBookList *oldbooks, *node; 01059 QofBackend *be; 01060 QofBackendError err; 01061 01062 if (!session) return; 01063 if (!session->book_id) return; 01064 01065 ENTER ("sess=%p book_id=%s", session, session->book_id 01066 ? session->book_id : "(null)"); 01067 01068 /* At this point, we should are supposed to have a valid book 01069 * id and a lock on the file. */ 01070 01071 oldbooks = session->books; 01072 01073 /* XXX why are we creating a book here? I think the books 01074 * need to be handled by the backend ... especially since 01075 * the backend may need to load multiple books ... XXX. FIXME. 01076 */ 01077 newbook = qof_book_new(); 01078 session->books = g_list_append (NULL, newbook); 01079 PINFO ("new book=%p", newbook); 01080 01081 qof_session_clear_error (session); 01082 01083 /* This code should be sufficient to initialize *any* backend, 01084 * whether http, postgres, or anything else that might come along. 01085 * Basically, the idea is that by now, a backend has already been 01086 * created & set up. At this point, we only need to get the 01087 * top-level account group out of the backend, and that is a 01088 * generic, backend-independent operation. 01089 */ 01090 be = session->backend; 01091 qof_book_set_backend(newbook, be); 01092 01093 /* Starting the session should result in a bunch of accounts 01094 * and currencies being downloaded, but probably no transactions; 01095 * The GUI will need to do a query for that. 01096 */ 01097 if (be) 01098 { 01099 be->percentage = percentage_func; 01100 01101 if (be->load) 01102 { 01103 be->load (be, newbook);
|
|
Definition at line 213 of file qofsession.c. 00214 { 00215 if (!current_session) 00216 { 00217 qof_event_suspend (); 00218 current_session = qof_session_new (); 00219 qof_event_resume (); 00220 } 00221 00222 return current_session; 00223 }
|
|
Definition at line 228 of file qofsession.c. 00229 { 00230 current_session = session; 00231 }
|
|
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 1424 of file qofsession.c. |