[Gnucash-changes] Backend configuration support and new method for
dlopen()
Neil Williams
codehelp at cvs.gnucash.org
Mon Aug 22 16:00:44 EDT 2005
Log Message:
-----------
Backend configuration support and new method for dlopen()
Tags:
----
gnucash-gnome2-dev
Modified Files:
--------------
gnucash/src/engine:
qofbackend-p.h
qofbackend.c
qofbackend.h
Revision Data
-------------
Index: qofbackend.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/qofbackend.c,v
retrieving revision 1.2.4.3
retrieving revision 1.2.4.4
diff -Lsrc/engine/qofbackend.c -Lsrc/engine/qofbackend.c -u -r1.2.4.3 -r1.2.4.4
--- src/engine/qofbackend.c
+++ src/engine/qofbackend.c
@@ -21,11 +21,16 @@
* *
\********************************************************************/
+#define _GNU_SOURCE
#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
#include <stdarg.h>
+#include <regex.h>
#include <glib.h>
-
-#include "qofbackend.h"
+#include <dlfcn.h>
+#include <sys/stat.h>
+#include <errno.h>
#include "qofbackend-p.h"
/* static short module = MOD_BACKEND; */
@@ -121,6 +126,7 @@
be->run_query = NULL;
be->sync = NULL;
+ be->load_config = NULL;
be->events_pending = NULL;
be->process_events = NULL;
@@ -129,6 +135,7 @@
if (be->error_msg) g_free (be->error_msg);
be->error_msg = NULL;
be->percentage = NULL;
+ be->backend_configuration = kvp_frame_new();
#ifdef GNUCASH_MAJOR_VERSION
/* XXX remove these */
@@ -141,6 +148,8 @@
void
qof_backend_run_begin(QofBackend *be, QofInstance *inst)
{
+ if(!be | !inst) { return; }
+ if(!be->begin) { return; }
(be->begin) (be, inst);
}
@@ -154,16 +163,43 @@
void
qof_backend_run_commit(QofBackend *be, QofInstance *inst)
{
+ if(!be | !inst) { return; }
+ if(!be->commit) { return; }
(be->commit) (be, inst);
}
+void
+qof_backend_load_config(QofBackend *be, KvpFrame *config)
+{
+ if(!be | !config) { return; }
+ if(!be->load_config) { return; }
+ (be->load_config) (be, config);
+}
+
+KvpFrame*
+qof_backend_get_config(QofBackend *be)
+{
+ if(!be) { return NULL; }
+ if(!be->get_config) { return NULL; }
+ return (be->get_config) (be);
+}
+
gboolean
qof_backend_commit_exists(QofBackend *be)
{
+ if(!be) { return FALSE; }
if(be->commit) { return TRUE; }
else { return FALSE; }
}
+gboolean
+qof_backend_check_type (QofBackend *be, const char *path)
+{
+ if(!be) { return FALSE; }
+ if(!be->check_data_type) { return FALSE; }
+ return (gboolean)(be->check_data_type) (be, path);
+}
+
void
qof_begin_edit(QofInstance *inst)
{
@@ -197,5 +233,96 @@
if (0 > inst->editlevel) { inst->editlevel = 0; }
}
+#define STR_DLNAME "dlname="
+#define STR_LIBDIR "libdir="
+
+gboolean
+qof_load_backend_library (const char* filename, const char* init_fcn)
+{
+ FILE *filehandle;
+ void (*initfn) (void);
+ void *dl_hand = NULL;
+#ifndef HAVE_GETLINE
+ char lineptr[1024];
+#else
+ char *lineptr;
+#endif
+ const char * err_str;
+ gchar *dlname, *libdirpath, *tempstr;
+ int errors;
+ guint n, end;
+ struct stat sbuf;
+
+ errors = 0;
+ dlname = NULL;
+ tempstr = NULL;
+ libdirpath = NULL;
+ g_return_val_if_fail((filename || init_fcn), FALSE);
+ g_return_val_if_fail(g_str_has_suffix (filename, ".la"), FALSE);
+ /* now we have a filename ending in .la, see if we can open it. */
+ n = (guint)strlen(STR_DLNAME);
+ g_return_val_if_fail((stat(filename, &sbuf) <0), FALSE);
+ filehandle = fopen(filename, "r");
+ g_return_val_if_fail((filehandle), FALSE);
+#ifndef HAVE_GETLINE
+ while (NULL != (fgets(lineptr, sizeof(lineptr), filehandle)))
+#else
+ lineptr = NULL;
+ while (0 < getline(&lineptr, &n, filehandle))
+#endif
+ {
+ if (strncmp (lineptr, STR_DLNAME, n - 1) == 0)
+ {
+ /* obtain substring from dlname='.*'\n
+ where .* matches the library .so|.dylib name
+ allowing for single quotes, if used. */
+ tempstr = g_strdup(lineptr + n);
+ if(tempstr[0] == '\'') { tempstr++; }
+ dlname = g_strndup(tempstr, strlen(tempstr) - 1);
+ end = strlen(dlname);
+ if(dlname[end-1] == '\'')
+ {
+ tempstr = g_strndup(dlname, end - 1);
+ dlname = tempstr;
+ }
+ }
+ /* now get the path, just in case */
+ n = (guint)strlen(STR_LIBDIR);
+ if (strncmp (lineptr, STR_LIBDIR, n - 1) == 0)
+ {
+ tempstr = g_strdup(lineptr + n);
+ if(tempstr[0] == '\'') { tempstr++; }
+ libdirpath = g_strndup(tempstr, strlen(tempstr) - 1);
+ end = strlen(libdirpath);
+ if(libdirpath[end-1] == '\'')
+ {
+ tempstr = g_strndup(libdirpath, end - 1);
+ libdirpath = tempstr;
+ }
+ break;
+ }
+ }
+ fclose(filehandle);
+ tempstr = g_strconcat(libdirpath, "/", dlname, NULL);
+ dlname = tempstr;
+ g_free(libdirpath);
+ dl_hand = dlopen (dlname, RTLD_LAZY);
+ if (NULL == dl_hand)
+ {
+ err_str = dlerror();
+ g_message ("Can't load backend, %s\n", err_str);
+ return FALSE;
+ }
+ initfn = dlsym (dl_hand, init_fcn);
+ if (initfn) { (*initfn)(); }
+ else
+ {
+ err_str = dlerror();
+ g_message("Can't find %s:%s, %s\n", dlname, init_fcn, err_str);
+ return FALSE;
+ }
+ g_free(dlname);
+ return TRUE;
+}
/************************* END OF FILE ********************************/
Index: qofbackend-p.h
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/qofbackend-p.h,v
retrieving revision 1.2.4.4
retrieving revision 1.2.4.5
diff -Lsrc/engine/qofbackend-p.h -Lsrc/engine/qofbackend-p.h -u -r1.2.4.4 -r1.2.4.5
--- src/engine/qofbackend-p.h
+++ src/engine/qofbackend-p.h
@@ -27,8 +27,7 @@
/** @name Backend_Private
Pseudo-object defining how the engine can interact with different
back-ends (which may be SQL databases, or network interfaces to
- remote GnuCash servers. In theory, file-io should be a type of
- backend).
+ remote GnuCash servers. File-io is just one type of backend).
The callbacks will be called at the appropriate times during
a book session to allow the backend to store the data as needed.
@@ -36,6 +35,7 @@
@file qofbackend-p.h
@brief private api for data storage backend
@author Copyright (c) 2000,2001,2004 Linas Vepstas <linas at linas.org>
+ @author Copyright (c) 2005 Neil Williams <linux at codehelp.co.uk>
@{ */
#ifndef QOF_BACKEND_P_H
@@ -231,6 +231,16 @@
* a mass transfer of transactions between books without having
* to actually move much (or any) data to the engine.
*
+ *
+ * To support configuration options from the frontend, the backend
+ * can be passed a GHashTable - according to the allowed options
+ * for that backend, using load_config(). Configuration can be
+ * updated at any point - it is up to the frontend to load the
+ * data in time for whatever the backend needs to do. e.g. an
+ * option to save a new book in a compressed format need not be
+ * loaded until the backend is about to save. If the configuration
+ * is updated by the user, the frontend should call load_config
+ * again to update the backend.
*/
struct QofBackendProvider_s
@@ -254,6 +264,21 @@
/** Return a new, initialized backend backend. */
QofBackend * (*backend_new) (void);
+ /** \brief Name of the QofBackendProvider XML Configuration file
+
+ This is to be generated from a Perl script to utilise gettext
+ translations and includes translated strings that describe
+ what each configuration option achieves.
+
+ The file itself can be located in the QSF_SCHEMA_DIR or
+ in any directory accessible to the frontend program.
+
+ The filename should include the name of the backend as
+ specified in provider_name and the version of the backend
+ that can use the file: myname-backend-v1.xml
+ */
+ const char* provider_config;
+
/** Free this structure, unregister this backend handler. */
void (*provider_free) (QofBackendProvider *);
};
@@ -279,7 +304,8 @@
void (*run_query) (QofBackend *, gpointer);
void (*sync) (QofBackend *, QofBook *);
-
+ void (*load_config) (QofBackend *, KvpFrame *);
+ KvpFrame* (*get_config) (QofBackend *);
gint64 (*counter) (QofBackend *, const char *counter_name);
gboolean (*events_pending) (QofBackend *);
@@ -295,12 +321,27 @@
QofBackendError last_err;
char * error_msg;
- /** XXX the file backend resolves the if to a fully-qualified file
- * path. This holds the filepath and communicates it to the GUI.
- * This is temprary scaffolding and should be removed. Deprecated.
+ KvpFrame* backend_configuration;
+ /** Each backend resolves a fully-qualified file path.
+ * This holds the filepath and communicates it to the frontends.
*/
char * fullpath;
+ /** \brief Distinguish two providers with same access method.
+
+ When more than 1 backend is registered under the same access_method,
+ each one is passed the path to the data (usually a file) and
+ should return TRUE only if the backend recognises the type
+ as one that it can load and write.
+
+ \note If the backend can cope with more than one type, the backend
+ should not try to store or cache the sub-type for this data.
+ It is sufficient only to return TRUE if any ONE of the supported
+ types match the incoming data. The backend should not assume that
+ returning TRUE will mean that the data will naturally follow.
+ */
+ gboolean (*check_data_type) (QofBackend *, const char*);
+
#ifdef GNUCASH_MAJOR_VERSION
/** XXX price_lookup should be removed during the redesign
* of the SQL backend... prices can now be queried using
Index: qofbackend.h
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/qofbackend.h,v
retrieving revision 1.3.4.7
retrieving revision 1.3.4.8
diff -Lsrc/engine/qofbackend.h -Lsrc/engine/qofbackend.h -u -r1.3.4.7 -r1.3.4.8
--- src/engine/qofbackend.h
+++ src/engine/qofbackend.h
@@ -161,6 +161,21 @@
used when QOF is built as a library.
@{
*/
+
+/** \brief Load configuration options specific to this backend.
+
+ at param be The backend to configure.
+ at param config A hash table with specific keys that this backend
+will recognise. Each backend needs to document their own config
+keys and acceptable values.
+
+The hash table remains the property of the caller and should
+be freed / destroyed once loaded in the backend.
+*/
+void qof_backend_load_config (QofBackend *be, KvpFrame *config);
+
+KvpFrame* qof_backend_get_config(QofBackend *be);
+
void qof_backend_run_begin(QofBackend *be, QofInstance *inst);
gboolean qof_backend_begin_exists(QofBackend *be);
@@ -169,6 +184,9 @@
gboolean qof_backend_commit_exists(QofBackend *be);
+gboolean
+qof_load_backend_library (const char* filename, const char* init_fcn);
+
/** @} */
/** \brief Retrieve the backend used by this book */
QofBackend* qof_book_get_backend (QofBook *book);
More information about the gnucash-changes
mailing list