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

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.
QofBackendqof_book_get_backend (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 (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)


Define Documentation

#define ENTITYREFERENCE   "QofEntityReference"
 

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.

#define PARTIAL_QOFBOOK   "PartialQofBook"
 

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.

#define QOF_BEGIN_EDIT inst   ) 
 

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 (" ");
begin_edit helper

Parameters:
inst,: an instance of QofInstance
The caller should use this macro first and then perform any other operations.

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.

#define QOF_COMMIT_EDIT_PART1 inst   ) 
 

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);             \
}
part1 -- deal with the editlevel

Parameters:
inst,: an instance of QofInstance

Definition at line 99 of file qof-be-utils.h.

#define QOF_COMMIT_EDIT_PART2 inst,
on_error,
on_done,
on_free   ) 
 

part2 -- deal with the backend

Parameters:
inst,: an instance of QofInstance
on_error,: a function called if there is a backend error. void (*on_error)(inst, QofBackendError)
on_done,: a function called after the commit is complete but before the instect is freed. Perform any other operations after the commit. void (*on_done)(inst)
on_free,: a function called if inst->do_free is TRUE. void (*on_free)(inst)

Definition at line 146 of file qof-be-utils.h.

#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 502 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 152 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 210 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 142 of file qofbackend.h.

typedef struct qof_entity_reference QofEntityReference
 

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.

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


Function Documentation

KvpFrame* qof_backend_complete_frame QofBackend be  ) 
 

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 }

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

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 335 of file qofbackend.c.

00336 {
00337         if(!be || !config) { return; }
00338         if(!be->load_config) { return; }
00339         (be->load_config) (be, config);
00340 }

void qof_backend_option_foreach KvpFrame config,
QofBackendOptionCB  cb,
gpointer  data
 

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 }

void qof_backend_prepare_frame QofBackend be  ) 
 

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 }

void qof_backend_prepare_option QofBackend be,
QofBackendOption option
 

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 }

gboolean qof_begin_edit QofInstance inst  ) 
 

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 }

gboolean qof_commit_edit QofInstance inst  ) 
 

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 }

gboolean qof_entity_copy_coll QofSession new_session,
QofCollection entity_coll
 

Copy a QofCollection of entities.

The QofBook in the new_session must not contain any entities with the same GUID as any entities in the collection - there is no support for handling collisions - instead, use 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 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 }

gboolean qof_entity_copy_coll_r QofSession new_session,
QofCollection coll
 

Recursively copy a collection of entities to a session.

Note:
This function creates a partial QofBook. See qof_entity_copy_to_session for more information.
The QofBook in the new_session must not contain any entities with the same GUID as any entities to be copied - there is no support for handling collisions - instead, use Merging QofBook structures

Objects can be defined solely in terms of QOF data types or as a mix of data types and other objects, which may in turn include other objects. These references can be copied recursively down to the third level. See QofEntityReference.

Note:
This is a deep recursive copy - every referenced entity is copied to the new session, including all parameters. The starting point is all entities in the top level collection. It can take some time.
Parameters:
coll A QofCollection of entities that may or may not have references.
new_session The QofSession to receive the copied entities.
Returns:
TRUE on success; if any individual copy fails, returns FALSE. Note : Some entities may have been copied successfully even if one of the references fails to copy.

Definition at line 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 }

gboolean qof_entity_copy_list QofSession new_session,
GList *  entity_list
 

Copy a GList of entities to another session.

The QofBook in the new_session must not contain any entities with the same GUID as any of the source entities - there is no support for handling collisions, instead use Merging QofBook structures

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

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

Definition at line 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 }

gboolean qof_entity_copy_one_r QofSession new_session,
QofEntity ent
 

Recursively copy a single entity to a new session.

Copy the single entity and all referenced entities to the second level.

Only entities that are directly referenced by the top level entity are copied.

This is a deep copy - all parameters of all referenced entities are copied. If the top level entity has no references, this is identical to qof_entity_copy_to_session.

Parameters:
ent A single entity that may or may not have references.
new_session The QofSession to receive the copied entities.
Returns:
TRUE on success; if any individual copy fails, returns FALSE. Note : Some entities may have been copied successfully even if one of the references fails to copy.

Definition at line 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 }

gboolean qof_entity_copy_to_session QofSession new_session,
QofEntity original
 

Copy a single QofEntity to another session.

Checks first that no entity in the session book contains the GUID of the source entity.

Parameters:
new_session - the target session
original - the QofEntity* to copy
Returns:
FALSE without copying if the session contains an entity with the same GUID already, otherwise TRUE.

Definition at line 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 }

QofEntityReference* qof_entity_get_reference_from QofEntity ent,
const QofParam param
 

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.

Parameters:
ent The known entity.
param The parameter to use to get the referenced entity.
Returns:
FALSE on error, otherwise a pointer to the QofEntityReference.

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 }

gboolean qof_load_backend_library const char *  directory,
const char *  filename,
const char *  init_fcn
 

Load a QOF-compatible backend shared library.

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

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 }

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

void qof_session_add_close_hook GFunc  fn,
gpointer  data
 

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

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

Definition at line 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 }

void qof_session_begin QofSession session,
const char *  book_id,
gboolean  ignore_lock,
gboolean  create_if_nonexistent
 

The qof_session_begin () method begins a new session. It takes as an argument the book id. The book id must be a string in the form of a URI/URL. The access method specified depends on the loaded backends. In the absence of a customised backend, only QSF XML would be accepted). Paths may be relative or absolute. If the path is relative; that is, if the argument is "file:somefile.xml" then the current working directory is assumed. Customised backends can choose to search other, application-specific, directories as well.

The 'ignore_lock' argument, if set to TRUE, will cause this routine to ignore any global-datastore locks (e.g. file locks) that it finds. If set to FALSE, then file/database-global locks will be tested and obeyed.

If the datastore exists, can be reached (e.g over the net), connected to, opened and read, and a lock can be obtained then a lock will be obtained. Note that multi-user datastores (e.g. the SQL backend) typically will not need to get a global lock, and thus, the user will not be locked out. That's the whole point of 'multi-user'.

If the file/database doesn't exist, and the create_if_nonexistent flag is set to TRUE, then the database is created.

If an error occurs, it will be pushed onto the session error stack, and that is where it should be examined.

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 }

void qof_session_call_close_hooks QofSession session  ) 
 

Call all registered session close hooks, informing them that the specified session is about to be closed.

Parameters:
session A pointer to the session being closed.

Definition at line 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 }

void qof_session_end QofSession session  ) 
 

The qof_session_end() method will release the session lock. For the file backend, it will *not* save the data to a file. Thus, this method acts as an "abort" or "rollback" primitive. However, for other backends, such as the sql backend, the data would have been written out before this, and so this routines wouldn't roll-back anything; it would just shut the connection.

Definition at line 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 }

gboolean qof_session_events_pending QofSession session  ) 
 

The qof_session_events_pending() method will return TRUE if the backend has pending events which must be processed to bring the engine up to date with the backend.

Definition at line 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 }

QofSession* qof_session_get_current_session void   ) 
 

Deprecated:
Each application should keep their own session context.

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 }

QofBackendError qof_session_get_error QofSession session  ) 
 

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

Definition at line 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 }

const char* qof_session_get_file_path QofSession session  ) 
 

The qof_session_get_file_path() routine returns the fully-qualified file path for the session. That is, if a relative or partial filename was for the session, then it had to have been fully resolved to open the session. This routine returns the result of this resolution. The path is always guaranteed to reside in the local file system, even if the session itself was opened as a URL. (currently, the filepath is derived from the url by substituting commas for slashes).

The qof_session_get_url() routine returns the url that was opened. URL's for local files take the form of file:/some/where/some/file.gml

Definition at line 295 of file qofsession.c.

00296 {
00297    if (!session) return NULL;
00298    if (!session->backend) return NULL;
00299    return session->backend->fullpath;
00300 }

gboolean qof_session_not_saved QofSession session  ) 
 

The qof_session_not_saved() subroutine will return TRUE if any data in the session hasn't been saved to long-term storage.

QofBackendError qof_session_pop_error QofSession session  ) 
 

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

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

See qofbackend.h for a listing of returned errors.

Definition at line 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 }

gboolean qof_session_process_events QofSession session  ) 
 

The qof_session_process_events() method will process any events indicated by the qof_session_events_pending() method. It returns TRUE if the engine was modified while engine events were suspended.

Definition at line 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 }

void qof_session_save QofSession session,
QofPercentageFunc  percentage_func
 

Todo:
check the access_method too, not in scope here, yet.

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 }

gboolean qof_session_save_may_clobber_data QofSession session  ) 
 

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 }

void qof_session_set_current_session QofSession session  ) 
 

Deprecated:
Each application should keep their own session context.

Definition at line 234 of file qofsession.c.

00235 {
00236   current_session = session;
00237 }

void qof_session_swap_data QofSession session_1,
QofSession session_2
 

The qof_session_swap_data () method swaps the book of the two given sessions. It is useful for 'Save As' type functionality.

Definition at line 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 }

void qof_session_update_reference_list QofSession session,
QofEntityReference reference
 

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 }


Generated on Fri Oct 21 15:49:59 2005 for QOF by  doxygen 1.4.5