Backend
[Object: Dynamic Object Class Framework]


Detailed Description

The QOF Backend is a pseudo-object providing an interface between the engine and a persistant data store (e.g. a server, a database, or a file). Backends are not meant to be used directly by an application; instead the Session should be used to make a connection with some particular backend. 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. This file defines these errors.

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  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

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.

Backends are loaded using QofBackendProvider via the function specified in prov->backend_new. Before backend_new returns, you should ensure that your backend is fully configured and ready for use.

typedef QofBackendOption_s QofBackendOption
typedef void(*) QofBackendOptionCB (QofBackendOption *, gpointer data)
void qof_backend_prepare_frame (QofBackend *be)
void qof_backend_prepare_option (QofBackend *be, const QofBackendOption *option)
KvpFrameqof_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.
KvpFrameqof_backend_get_config (QofBackend *be)
 Get the available configuration options.

Allow access to the begin routine for this backend.



void qof_backend_run_begin (QofBackend *be, QofInstance *inst)
gboolean qof_backend_begin_exists (const QofBackend *be)
void qof_backend_run_commit (QofBackend *be, QofInstance *inst)
gboolean qof_backend_commit_exists (const QofBackend *be)

Session Errors

QofBackendError qof_session_get_error (QofSession *session)
const char * qof_session_get_error_message (const 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 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 QofInstance 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_instance_copy_to_session (QofSession *new_session, QofInstance *original)
 Copy a single QofInstance to another session.
gboolean qof_instance_copy_list (QofSession *new_session, GList *entity_list)
 Copy a GList of entities to another session.
gboolean qof_instance_copy_coll (QofSession *new_session, QofCollection *entity_coll)
 Copy a QofCollection of entities.
gboolean qof_instance_copy_coll_r (QofSession *new_session, QofCollection *coll)
 Recursively copy a collection of entities to a session.
gboolean qof_instance_copy_one_r (QofSession *new_session, QofInstance *ent)
 Recursively copy a single entity to a new session.

Event Handling

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

Defines

#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_FILEIO_READ_ERROR, ERR_FILEIO_NO_ENCODING, ERR_FILEIO_FILE_EACCES, 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

void qof_backend_set_error (QofBackend *be, QofBackendError err)
QofBackendError qof_backend_get_error (QofBackend *be)
gboolean qof_load_backend_library (const gchar *directory, const gchar *module_name)
 Load a QOF-compatible backend shared library.
QofBackendqof_book_get_backend (const QofBook *book)
 Retrieve the backend used by this book.
void qof_book_set_backend (QofBook *book, QofBackend *)
QofSessionqof_session_new (void)
void qof_session_destroy (QofSession *session)
QofSessionqof_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)
QofBookqof_session_get_book (const QofSession *session)
const char * qof_session_get_file_path (const QofSession *session)
const char * qof_session_get_url (const QofSession *session)
gboolean qof_session_not_saved (QofSession *session)
gboolean qof_session_save_in_progress (QofSession *session)
gboolean qof_session_save_may_clobber_data (const 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)
gboolean qof_session_export (QofSession *tmp_session, QofSession *real_session, QofPercentageFunc percentage_func)


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 struct 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).

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 158 of file qofbackend.h.

typedef struct QofBackendOption_s QofBackendOption

A single Backend Configuration Option.

typedef void(*) QofBackendOptionCB(QofBackendOption *, gpointer data)

Backend configuration option foreach callback prototype.

Definition at line 223 of file qofbackend.h.

typedef struct QofBackendProvider_s QofBackendProvider

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 148 of file qofbackend.h.

typedef void(*) QofPercentageFunc(const char *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.


Enumeration Type Documentation

enum QofBackendError

The errors that can be reported to the GUI & other front-end users.

Warning:
(GnuCash) If you modify QofBackendError, please update src/engine/gw-engine-spec.scm
Enumerator:
ERR_BACKEND_NO_ERR 
ERR_BACKEND_NO_HANDLER  no backend handler found for this access method (ENOSYS)
ERR_BACKEND_NO_BACKEND  Backend * pointer was unexpectedly null
ERR_BACKEND_BAD_URL  Can't parse url
ERR_BACKEND_NO_SUCH_DB  the named database doesn't exist
ERR_BACKEND_CANT_CONNECT  bad dbname/login/passwd or network failure
ERR_BACKEND_CONN_LOST  Lost connection to server
ERR_BACKEND_LOCKED  in use by another user (ETXTBSY)
ERR_BACKEND_READONLY  cannot write to file/directory
ERR_BACKEND_TOO_NEW  file/db version newer than what we can read
ERR_BACKEND_DATA_CORRUPT  data in db is corrupt
ERR_BACKEND_SERVER_ERR  error in response from server
ERR_BACKEND_ALLOC  internal memory allocation failure
ERR_BACKEND_PERM  user login successful, but no permissions to access the desired object
ERR_BACKEND_MODIFIED  commit of object update failed because another user has modified the object
ERR_BACKEND_MOD_DESTROY  commit of object update failed because another user has deleted the object
ERR_BACKEND_MISC  undetermined error
ERR_QSF_INVALID_OBJ  The QSF object failed to validate against the QSF object schema
ERR_QSF_INVALID_MAP  The QSF map failed to validate against the QSF map schema
ERR_QSF_BAD_OBJ_GUID  The QSF object contains one or more invalid GUIDs.
ERR_QSF_BAD_QOF_VERSION  QSF map or object doesn't match the current QOF_OBJECT_VERSION.
ERR_QSF_BAD_MAP  The selected map validates but is unusable.

This is usually because not all the required parameters for the defined objects have calculations described in the map.

ERR_QSF_NO_MAP  The QSF object file was loaded without a map

The QSF Object file requires a map but it was not provided.

ERR_QSF_WRONG_MAP  The selected map validates but is for different objects.

The list of objects defined in this map does not include all the objects described in the current QSF object file.

ERR_QSF_MAP_NOT_OBJ  Selected file is a QSF map and cannot be opened as a QSF object
ERR_QSF_OVERFLOW  EOVERFLOW - generated by strtol or strtoll.

When converting XML strings into numbers, an overflow has been detected. The XML file contains invalid data in a field that is meant to hold a signed long integer or signed long long integer.

ERR_QSF_OPEN_NOT_MERGE 
ERR_FILEIO_FILE_BAD_READ  QSF files cannot be opened alone. The data must be merged.

This error is more of a warning that can be ignored by any routine that uses qof_book_merge on the new session. read failed or file prematurely truncated

ERR_FILEIO_FILE_EMPTY  file exists, is readable, but is empty
ERR_FILEIO_FILE_LOCKERR  mangled locks (unspecified error)
ERR_FILEIO_FILE_NOT_FOUND  not found / no such file
ERR_FILEIO_FILE_TOO_OLD  file version so old we can't read it
ERR_FILEIO_UNKNOWN_FILE_TYPE  didn't recognize the file type
ERR_FILEIO_PARSE_ERROR  couldn't parse the data in the file
ERR_FILEIO_BACKUP_ERROR  couldn't make a backup of the file
ERR_FILEIO_WRITE_ERROR  couldn't write to the file
ERR_FILEIO_READ_ERROR  Could not open the file for reading.
ERR_FILEIO_NO_ENCODING  file does not specify encoding
ERR_FILEIO_FILE_EACCES  No read access permission for the given file
ERR_NETIO_SHORT_READ  not enough bytes received
ERR_NETIO_WRONG_CONTENT_TYPE  wrong kind of server, wrong data served
ERR_NETIO_NOT_GNCXML  whatever it is, we can't parse it.
ERR_SQL_MISSING_DATA  database doesn't contain expected data
ERR_SQL_DB_TOO_OLD  database is old and needs upgrading
ERR_SQL_DB_BUSY  database is busy, cannot upgrade version
ERR_RPC_HOST_UNK  Host unknown
ERR_RPC_CANT_BIND  can't bind to address
ERR_RPC_CANT_ACCEPT  can't accept connection
ERR_RPC_NO_CONNECTION  no connection to server
ERR_RPC_BAD_VERSION  RPC Version Mismatch
ERR_RPC_FAILED  Operation failed
ERR_RPC_NOT_ADDED  object not added

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,    
00120   ERR_FILEIO_FILE_EACCES,    
00122   /* network errors */
00123   ERR_NETIO_SHORT_READ = 2000,  
00124   ERR_NETIO_WRONG_CONTENT_TYPE, 
00125   ERR_NETIO_NOT_GNCXML,         
00127   /* database errors */
00128   ERR_SQL_MISSING_DATA = 3000,  
00129   ERR_SQL_DB_TOO_OLD,           
00130   ERR_SQL_DB_BUSY,              
00132   /* RPC errors */
00133   ERR_RPC_HOST_UNK = 4000,      
00134   ERR_RPC_CANT_BIND,            
00135   ERR_RPC_CANT_ACCEPT,          
00136   ERR_RPC_NO_CONNECTION,        
00137   ERR_RPC_BAD_VERSION,          
00138   ERR_RPC_FAILED,               
00139   ERR_RPC_NOT_ADDED,            
00140 } QofBackendError;


Function Documentation

KvpFrame* qof_backend_complete_frame ( QofBackend be  ) 

Complete the backend_configuration and return the frame.

Definition at line 243 of file qofbackend.c.

00244 {
00245         g_return_val_if_fail(be, NULL);
00246         be->config_count = 0;
00247         return be->backend_configuration;
00248 }

KvpFrame* qof_backend_get_config ( QofBackend be  ) 

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.

Parameters:
be The QofBackend to be configured.
Returns:
A new KvpFrame containing the available options or NULL on failure.

Definition at line 380 of file qofbackend.c.

00381 {
00382         if(!be) { return NULL; }
00383         if(!be->get_config) { return NULL; }
00384         return (be->get_config) (be);
00385 }

QofBackendError qof_backend_get_error ( QofBackend be  ) 

The qof_backend_get_error() routine pops an error code off the error stack.

Definition at line 56 of file qofbackend.c.

00057 {
00058    QofBackendError err;
00059    if (!be) return ERR_BACKEND_NO_BACKEND;
00060 
00061    /* use 'stack-pop' semantics */
00062    err = be->last_err;
00063    be->last_err = ERR_BACKEND_NO_ERR;
00064    return err;
00065 }

void qof_backend_load_config ( QofBackend be,
KvpFrame config 
)

Load configuration options specific to this backend.

Parameters:
be The backend to configure.
config A KvpFrame of QofBackendOptions that this backend will recognise. Each backend needs to document their own config types and acceptable values.

Definition at line 372 of file qofbackend.c.

00373 {
00374         if(!be || !config) { return; }
00375         if(!be->load_config) { return; }
00376         (be->load_config) (be, config);
00377 }

void qof_backend_option_foreach ( KvpFrame config,
QofBackendOptionCB  cb,
gpointer  data 
)

Iterate over the frame and process each option.

Definition at line 357 of file qofbackend.c.

00358 {
00359         struct config_iterate helper;
00360 
00361         if(!config || !cb) { return; }
00362         ENTER (" ");
00363         helper.fcn = cb;
00364         helper.count = 1;
00365         helper.data = data;
00366         helper.recursive = config;
00367         kvp_frame_for_each_slot(config, config_foreach_cb, &helper);
00368         LEAVE (" ");
00369 }

void qof_backend_prepare_frame ( QofBackend be  ) 

Initialise the backend_configuration

Definition at line 181 of file qofbackend.c.

00182 {
00183         g_return_if_fail(be);
00184         if(!kvp_frame_is_empty(be->backend_configuration)) {
00185                 kvp_frame_delete(be->backend_configuration);
00186                 be->backend_configuration = kvp_frame_new();
00187         }
00188         be->config_count = 0;
00189 }

void qof_backend_prepare_option ( QofBackend be,
const QofBackendOption option 
)

Add an option to the backend_configuration. Repeat for more.

Definition at line 191 of file qofbackend.c.

00192 {
00193         KvpValue *value;
00194         gchar *temp;
00195         gint count;
00196 
00197         g_return_if_fail(be || option);
00198         count = be->config_count;
00199         count++;
00200         value = NULL;
00201         switch (option->type)
00202         {
00203                 case KVP_TYPE_GINT64   : {
00204                         value = kvp_value_new_gint64(*(gint64*)option->value);
00205                         break; 
00206                 }
00207                 case KVP_TYPE_DOUBLE   : { 
00208                         value = kvp_value_new_double(*(double*)option->value);
00209                         break; 
00210                 }
00211                 case KVP_TYPE_NUMERIC  : {
00212                         value = kvp_value_new_numeric(*(gnc_numeric*)option->value);
00213                         break; 
00214                 }
00215                 case KVP_TYPE_STRING   : {
00216                         value = kvp_value_new_string((const char*)option->value);
00217                         break;
00218                 }
00219                 case KVP_TYPE_GUID     : { break; } /* unsupported */
00220                 case KVP_TYPE_TIMESPEC : {
00221                         value = kvp_value_new_timespec(*(Timespec*)option->value);
00222                         break;
00223                 }
00224                 case KVP_TYPE_BINARY   : { break; } /* unsupported */
00225                 case KVP_TYPE_GLIST    : { break; } /* unsupported */
00226                 case KVP_TYPE_FRAME    : { break; } /* unsupported */
00227         }
00228         if(value) {
00229                 temp = g_strdup_printf("/%s", option->option_name);
00230                 kvp_frame_set_value(be->backend_configuration, temp, value);
00231                 g_free(temp);
00232                 temp = g_strdup_printf("/%s/%s", QOF_CONFIG_DESC, option->option_name);
00233                 kvp_frame_set_string(be->backend_configuration, temp, option->description);
00234                 g_free(temp);
00235                 temp = g_strdup_printf("/%s/%s", QOF_CONFIG_TIP, option->option_name);
00236                 kvp_frame_set_string(be->backend_configuration, temp, option->tooltip);
00237                 g_free(temp);
00238                 /* only increment the counter if successful */
00239                 be->config_count = count;
00240         }
00241 }

void qof_backend_set_error ( QofBackend be,
QofBackendError  err 
)

The qof_backend_set_error() routine pushes an error code onto the error stack. (FIXME: the stack is 1 deep in current implementation).

Definition at line 46 of file qofbackend.c.

00047 {
00048    if (!be) return;
00049 
00050    /* use stack-push semantics. Only the earliest error counts */
00051    if (ERR_BACKEND_NO_ERR != be->last_err) return;
00052    be->last_err = err;
00053 }

gboolean qof_instance_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 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 686 of file qofsession.c.

00687 {
00688         QofInstanceCopyData qecd;
00689 
00690         g_return_val_if_fail(new_session, FALSE);
00691         if(!entity_coll) { return FALSE; }
00692         qof_event_suspend();
00693         qecd.param_list = NULL;
00694         qecd.new_session = new_session;
00695         qof_book_set_partial(qof_session_get_book(qecd.new_session));
00696         qof_collection_foreach(entity_coll, qof_instance_coll_foreach, &qecd);
00697         qof_class_param_foreach(qof_collection_get_type(entity_coll), 
00698                 qof_instance_param_cb, &qecd);
00699         qof_collection_foreach(entity_coll, qof_instance_coll_copy, &qecd);
00700         if(qecd.param_list != NULL) { g_slist_free(qecd.param_list); }
00701         qof_event_resume();
00702         return TRUE;
00703 }

gboolean qof_instance_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_instance_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 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 QofInstanceReference.

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

00809 {
00810         struct recurse_s store;
00811         gboolean success;
00812 
00813         if((!new_session)||(!coll)) { return FALSE; }
00814         store.session = new_session;
00815         success = TRUE;
00816         store.success = success;
00817         store.ent_list = NULL;
00818         store.ref_list = qof_class_get_referenceList(qof_collection_get_type(coll));
00819         success = qof_instance_copy_coll(new_session, coll);
00820         if(success){ qof_collection_foreach(coll, recurse_ent_cb, &store); }
00821         return success;
00822 }

gboolean qof_instance_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 Merging QofBook structures

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

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

Definition at line 663 of file qofsession.c.

00664 {
00665         QofInstanceCopyData *qecd;
00666 
00667         if(!new_session || !entity_list) { return FALSE; }
00668         ENTER (" list=%d", g_list_length(entity_list));
00669         qecd = g_new0(QofInstanceCopyData, 1);
00670         qof_event_suspend();
00671         qecd->param_list = NULL;
00672         qecd->new_session = new_session;
00673         qof_book_set_partial(qof_session_get_book(new_session));
00674         g_list_foreach(entity_list, qof_instance_list_foreach, qecd);
00675         qof_event_resume();
00676         if(qecd->error) 
00677         { 
00678                 PWARN (" some/all entities in the list could not be copied.");
00679         }
00680         g_free(qecd);
00681         LEAVE (" ");
00682         return TRUE;
00683 }

gboolean qof_instance_copy_one_r ( QofSession new_session,
QofInstance 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_instance_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 824 of file qofsession.c.

00825 {
00826         struct recurse_s store;
00827         QofCollection *coll;
00828         gboolean success;
00829 
00830         if((!new_session)||(!ent)) { return FALSE; }
00831         store.session = new_session;
00832         success = TRUE;
00833         store.success = success;
00834         store.ref_list = qof_class_get_referenceList(ent->e_type);
00835         success = qof_instance_copy_to_session(new_session, ent);
00836         if(success == TRUE) {
00837                 coll = qof_book_get_collection(qof_session_get_book(new_session), ent->e_type);
00838                 if(coll) { qof_collection_foreach(coll, recurse_ent_cb, &store); }
00839         }
00840         return success;
00841 }

gboolean qof_instance_copy_to_session ( QofSession new_session,
QofInstance original 
)

Copy a single QofInstance 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 QofInstance* to copy
Returns:
FALSE without copying if the session contains an entity with the same GUID already, otherwise TRUE.

Definition at line 635 of file qofsession.c.

00636 {
00637         QofInstanceCopyData qecd;
00638         QofInstance *inst;
00639         QofBook *book;
00640 
00641         if(!new_session || !original) { return FALSE; }
00642         if(qof_instance_guid_match(new_session, original)) { return FALSE; }
00643         if(!qof_object_compliance(original->e_type, TRUE)) { return FALSE; }
00644         qof_event_suspend();
00645         qecd.param_list = NULL;
00646         book = qof_session_get_book(new_session);
00647         qecd.new_session = new_session;
00648         qof_book_set_partial(book);
00649         inst = (QofInstance*)qof_object_new_instance(original->e_type, book);
00650         qecd.to = inst;
00651         qecd.from = original;
00652         qof_instance_set_guid(qecd.to, qof_instance_get_guid(original));
00653         qof_begin_edit(inst);
00654         qof_class_param_foreach(original->e_type, qof_instance_param_cb, &qecd);
00655         qof_commit_edit(inst);
00656         if(g_slist_length(qecd.param_list) == 0) { return FALSE; }
00657         g_slist_foreach(qecd.param_list, qof_instance_foreach_copy, &qecd);
00658         g_slist_free(qecd.param_list);
00659         qof_event_resume();
00660         return TRUE;
00661 }

gboolean qof_load_backend_library ( const gchar *  directory,
const gchar *  module_name 
)

Load a QOF-compatible backend shared library.

Parameters:
directory Can be NULL if filename is a complete path.
module_name Name of the .la file that describes the shared library. This provides platform independence, courtesy of libtool.
Returns:
FALSE in case or error, otherwise TRUE.

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

00252 {
00253   GList *node;
00254   if (!session) return;
00255 
00256   ENTER (" sess=%p book=%p", session, addbook);
00257 
00258   /* See if this book is already there ... */
00259   for (node=session->books; node; node=node->next)
00260   {
00261      QofBook *book = node->data;
00262      if (addbook == book) return;
00263   }
00264 
00265   if ('y' == addbook->book_open)
00266   {
00267     /* hack alert -- someone should free all the books in the list,
00268      *