From 565ae5fd90e63be835b35e9980bd33150a8e60f6 Mon Sep 17 00:00:00 2001 From: Linas Vepstas Date: Sun, 14 May 2000 20:56:36 +0000 Subject: [PATCH] new, improved debug printing macros some SQL backend prototyping work. git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@2309 57a11ea4-9604-0410-9ed3-97b8803252fd --- src/engine/Backend.c | 95 ++++++++++++++++++++++++++++++++++++++++ src/engine/BackendP.h | 55 +++++++++++++++++++++++ src/engine/Group.c | 25 +++++++---- src/engine/GroupP.h | 6 ++- src/engine/Makefile.in | 2 +- src/engine/Session.c | 54 ++++++++++++++++++++--- src/engine/Transaction.c | 44 +++++++++++-------- 7 files changed, 245 insertions(+), 36 deletions(-) create mode 100644 src/engine/Backend.c create mode 100644 src/engine/BackendP.h diff --git a/src/engine/Backend.c b/src/engine/Backend.c new file mode 100644 index 0000000000..a43c721f80 --- /dev/null +++ b/src/engine/Backend.c @@ -0,0 +1,95 @@ +/********************************************************************\ + * Backend.c -- utility routines for dealing with the data backend * + * Copyright (C) 2000 Linas Vepstas * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License as * + * published by the Free Software Foundation; either version 2 of * + * the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License* + * along with this program; if not, contact: * + * * + * Free Software Foundation Voice: +1-617-542-5942 * + * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 * + * Boston, MA 02111-1307, USA gnu@gnu.org * + * * +\********************************************************************/ + +#include "Account.h" +#include "AccountP.h" +#include "BackendP.h" +#include "Group.h" +#include "GroupP.h" +#include "TransactionP.h" +#include "util.h" + +/* static short module = MOD_ENGINE; */ + + +/********************************************************************\ + * Fetch the backend * +\********************************************************************/ + +Backend * +xaccAccountGetBackend (Account * acc) +{ + Account *parent_acc; + AccountGroup * grp; + + if (!acc) return NULL; + + /* find the first account group that has a backend */ + grp = (AccountGroup *) acc->parent; + while (grp) { + if (grp->backend) return (grp->backend); + parent_acc = grp -> parent; + grp = NULL; + if (parent_acc) { + grp = (AccountGroup *) parent_acc->parent; + } + } + return NULL; +} + +/********************************************************************\ + * Fetch the backend * +\********************************************************************/ + +Backend * +xaccTransactionGetBackend (Transaction *trans) +{ + Backend *be; + Split *s; + if (!trans) return NULL; + + /* find an account */ + s = trans->splits[0]; + if (!s) return NULL; + + /* I suppose it would be more 'technically correct' to make sure that + * all splits share teh same backend, and flag an error if they + * don't. However, at this point, it seems quite unlikely, so we'll + * just use teh first backend we find. + */ + be = xaccAccountGetBackend (s->acc); + return be; +} + +/********************************************************************\ + * Set the backend * +\********************************************************************/ + +void +xaccGroupSetBackend (AccountGroup *grp, Backend *be) +{ + if (!grp) return; + grp->backend = be; +} + +/************************* END OF FILE ********************************/ diff --git a/src/engine/BackendP.h b/src/engine/BackendP.h new file mode 100644 index 0000000000..669feca281 --- /dev/null +++ b/src/engine/BackendP.h @@ -0,0 +1,55 @@ +/* + * BackendP.h + * + * Pseudo-object defining how the engine can interact with different + * back-ends (which will probably be sql databases). + * + * The callbacks will be called at the appropriate times during + * a session to allow the backend to store the data as needed. + * + */ + +#ifndef __XACC_BACKEND_P_H__ +#define __XACC_BACKEND_P_H__ + +#include "config.h" +#include "Account.h" +#include "Group.h" +#include "Session.h" +#include "Transaction.h" + +typedef struct _backend Backend; + +struct _backend +{ + AccountGroup * (*session_begin) (Session *, const char * sessionid); + int (*session_end) (Session *); + int (*account_begin_edit) (Backend *, Account *, int defer); + int (*account_commit_edit) (Backend *, Account *); + int (*trans_begin_edit) (Backend *, Transaction *, int defer); + int (*trans_commit_edit) (Backend *, Transaction *); + int (*trans_rollback_edit) (Backend *, Transaction *); +}; + +/* + * The xaccGetAccountBackend() subroutine will find the + * persistent-data storage backend associated with this account. + * This routine traverses up the account heirarchy until it + * finds and account-group node that has a backend associated with + * it. The assumption is that all accounts in that account-group + * share a common back-end. + * + * The xaccGetTransactionBackend() subroutine does the same, for a given + * transaction. + */ + +Backend * xaccAccountGetBackend (Account *); +Backend * xaccTransactionGetBackend (Transaction *); + +/* + * The xaccGroupSetBackend() associates a backend to a group + */ +void xaccGroupSetBackend (AccountGroup *, Backend *); + + +#endif /* __XACC_BACKEND_P_H__ */ diff --git a/src/engine/Group.c b/src/engine/Group.c index d629f60a4b..52eebadb0e 100644 --- a/src/engine/Group.c +++ b/src/engine/Group.c @@ -1,7 +1,7 @@ /********************************************************************\ * Group.c -- the main data structure of the program * * Copyright (C) 1997 Robin D. Clark * - * Copyright (C) 1997-2000 Linas Vepstas * + * Copyright (C) 1997-2000 Linas Vepstas * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * @@ -29,12 +29,13 @@ #include "Account.h" #include "AccountP.h" +#include "BackendP.h" +#include "GNCIdP.h" #include "Group.h" #include "GroupP.h" #include "TransactionP.h" -#include "GNCIdP.h" -#include "util.h" #include "gnc-common.h" +#include "util.h" /* static short module = MOD_ENGINE; */ @@ -47,6 +48,7 @@ /********************************************************************\ \********************************************************************/ + void xaccInitializeAccountGroup (AccountGroup *grp) { @@ -58,10 +60,17 @@ xaccInitializeAccountGroup (AccountGroup *grp) grp->account[0] = NULL; /* null-terminated array */ grp->balance = 0.0; + + xaccGUIDNew(&grp->guid); + xaccStoreEntity(grp, &grp->guid, GNC_ID_GROUP); + + grp->backend = NULL; + } /********************************************************************\ \********************************************************************/ + AccountGroup * xaccMallocAccountGroup( void ) { @@ -69,15 +78,12 @@ xaccMallocAccountGroup( void ) xaccInitializeAccountGroup (grp); - xaccGUIDNew(&grp->guid); - - xaccStoreEntity(grp, &grp->guid, GNC_ID_GROUP); - return grp; } /********************************************************************\ \********************************************************************/ + void xaccFreeAccountGroup( AccountGroup *grp ) { @@ -104,6 +110,7 @@ xaccFreeAccountGroup( AccountGroup *grp ) /********************************************************************\ \********************************************************************/ + void xaccAccountGroupMarkSaved (AccountGroup *grp) { @@ -119,6 +126,7 @@ xaccAccountGroupMarkSaved (AccountGroup *grp) /********************************************************************\ \********************************************************************/ + void xaccAccountGroupMarkNotSaved (AccountGroup *grp) { @@ -170,6 +178,7 @@ void xaccGroupSetGUID (AccountGroup *group, GUID *guid) /********************************************************************\ \********************************************************************/ + AccountGroup * xaccGroupLookup (const GUID *guid) { @@ -1111,4 +1120,4 @@ xaccGroupStagedTransactionTraversal(AccountGroup *grp, return 0; } -/****************** END OF FILE *************************************/ +/************************* END OF FILE ********************************/ diff --git a/src/engine/GroupP.h b/src/engine/GroupP.h index 396feab340..ac4958ed5d 100644 --- a/src/engine/GroupP.h +++ b/src/engine/GroupP.h @@ -37,8 +37,9 @@ #define __XACC_ACCOUNT_GROUP_P_H__ #include "config.h" -#include "Transaction.h" +#include "BackendP.h" #include "GNCId.h" +#include "Transaction.h" /** STRUCTS *********************************************************/ @@ -54,6 +55,8 @@ struct _account_group { GUID guid; /* globally unique id */ + Backend *backend; /* persistant storage backend */ + /* cached parameters */ double balance; }; @@ -64,5 +67,4 @@ struct _account_group { * call this on an existing group! */ void xaccGroupSetGUID (AccountGroup *group, GUID *guid); - #endif /* __XACC_ACCOUNT_GROUP_P_H__ */ diff --git a/src/engine/Makefile.in b/src/engine/Makefile.in index 4d02f2be0d..32dc25e6a6 100644 --- a/src/engine/Makefile.in +++ b/src/engine/Makefile.in @@ -34,7 +34,7 @@ LIBS = @LIBS@ ${GLIB_LIBS} ###################################################################### # See Makefile.common for information about these variables. -INDEP_SRCS := AccInfo.c Account.c DateUtils.c FileIO.c Group.c \ +INDEP_SRCS := AccInfo.c Account.c Backend.c DateUtils.c FileIO.c Group.c \ LedgerUtils.c QIFIO.c Query.c Queue.c Scrub.c Session.c \ Transaction.c TransLog.c date.c util.c GNCId.c \ guid/md5.c guid/guid.c diff --git a/src/engine/Session.c b/src/engine/Session.c index 96a14c90cb..e8bea77a3e 100644 --- a/src/engine/Session.c +++ b/src/engine/Session.c @@ -38,6 +38,7 @@ #include #include +#include "BackendP.h" #include "FileIO.h" #include "FileIOP.h" #include "Group.h" @@ -48,10 +49,18 @@ struct _session { AccountGroup *topgroup; /* the requested session id, in the form or a URI, such as - * file:/some/where + * file:/some/where, or sql:server.host.com:555 */ char *sessionid; + /* if session failed, this records the failure reason + * (file not found, etc). + * the standard errno values are used. + */ + int errtype; + + /* ---------------------------------------------------- */ + /* teh following struct members apply only for file-io */ /* the fully-resolved path to the file */ char *fullpath; @@ -60,11 +69,10 @@ struct _session { char * linkfile; int lockfd; - /* if session failed, this records the failure reason - * (file not found, etc). - * the standard errno values are used. - */ - int errtype; + /* ---------------------------------------------------- */ + /* this struct member applies only for SQL i/o */ + Backend *backend; + }; /* ============================================================== */ @@ -90,6 +98,7 @@ xaccInitSession (Session *sess) sess->lockfile = NULL; sess->linkfile = NULL; sess->lockfd = -1; + sess->backend = NULL; }; /* ============================================================== */ @@ -166,6 +175,33 @@ xaccSessionBegin (Session *sess, const char * sid) return retval; } +/* ============================================================== */ + +AccountGroup * +xaccSessionBeginSQL (Session *sess, const char * dbname) +{ + Backend *be = NULL; + AccountGroup *grp = NULL; + + if (!sess) return NULL; + +{ +/* for testing the sql, just a hack, remove later ... */ +Backend * pgendNew (void); +be = pgendNew (); +} + sess->backend = be; + + if (be && be->session_begin) { + grp = (be->session_begin) (sess, dbname); + } + // comment out until testing done, else clobber file ... + // sess->topgroup = grp; + xaccGroupSetBackend (sess->topgroup, be); +} + +/* ============================================================== */ + AccountGroup * xaccSessionBeginFile (Session *sess, const char * filefrag) { @@ -290,6 +326,12 @@ xaccSessionBeginFile (Session *sess, const char * filefrag) sess->topgroup = xaccReadAccountGroupFile (sess->fullpath); } +#ifdef SQLHACK +/* for testing the sql, just a hack, remove later ... */ +/* this should never ever appear here ... */ +xaccSessionBeginSQL (sess, "gnc_bogus"); +#endif + return (sess->topgroup); } diff --git a/src/engine/Transaction.c b/src/engine/Transaction.c index 55d0b7277e..421e62f36f 100644 --- a/src/engine/Transaction.c +++ b/src/engine/Transaction.c @@ -1,7 +1,7 @@ /********************************************************************\ * Transaction.c -- the transaction data structure * * Copyright (C) 1997 Robin D. Clark * - * Copyright (C) 1997, 1998, 1999, 2000 Linas Vepstas * + * Copyright (C) 1997-2000 Linas Vepstas * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * @@ -32,11 +32,12 @@ #include "Account.h" #include "AccountP.h" +#include "BackendP.h" +#include "GNCIdP.h" #include "Group.h" #include "Transaction.h" #include "TransactionP.h" #include "TransLog.h" -#include "GNCIdP.h" #include "util.h" #include "date.h" @@ -463,7 +464,7 @@ xaccFreeTransaction( Transaction *trans ) if (!trans) return; - ENTER ("xaccFreeTransaction(): addr=%p\n", trans); + ENTER ("addr=%p\n", trans); /* free up the destination splits */ if (trans->splits) { @@ -503,7 +504,7 @@ xaccFreeTransaction( Transaction *trans ) _free(trans); - LEAVE ("xaccFreeTransaction(): addr=%p\n", trans); + LEAVE ("addr=%p\n", trans); } /********************************************************************\ @@ -575,8 +576,7 @@ xaccSplitSetBaseValue (Split *s, double value, const char * base_currency) s -> damount = (value / (s->share_price)); } else { - PERR ("xaccSplitSetBaseValue(): " - " inappropriate base currency %s " + PERR (" inappropriate base currency %s " " given split currency=%s and security=%s\n", base_currency, s->acc->currency, s->acc->security); return; @@ -617,8 +617,7 @@ xaccSplitGetBaseValue (Split *s, char * base_currency) value = s->damount * s->share_price; } else { - PERR ("xaccSplitGetBaseValue(): " - " inappropriate base currency %s " + PERR (" inappropriate base currency %s " " given split currency=%s and security=%s\n", base_currency, s->acc->currency, s->acc->security); return 0.0; @@ -665,7 +664,7 @@ ComputeValue (Split **sarray, Split * skip_me, const char * base_currency) if (!safe_strcmp(s->acc->security, base_currency)) { value += s->damount; } else { - PERR ("Internal Error: ComputeValue(): " + PERR ("Internal Error: " " inconsistent currencies \n"); assert (0); } @@ -851,7 +850,7 @@ xaccSplitRebalance (Split *split) base_currency = FindCommonCurrency (trans->splits, ra, rb); if (!base_currency) { - PERR ("Internal Error: SplitRebalance(): no common split currencies \n"); + PERR ("Internal Error: no common split currencies \n"); s = trans->splits[0]; while (s) { if (s->acc) { @@ -978,9 +977,10 @@ xaccTransCommitEdit (Transaction *trans) int i; Split *split; Account *acc; + Backend *be; if (!trans) return; - ENTER ("xaccTransCommitEdit(): trans addr=%p\n", trans); + ENTER ("trans addr=%p\n", trans); CHECK_OPEN (trans); /* At this point, we check to see if we have a valid transaction. @@ -991,7 +991,7 @@ xaccTransCommitEdit (Transaction *trans) split = trans->splits[0]; if (!split) { - PINFO ("xaccTransCommitEdit(): delete trans at addr=%p\n", trans); + PINFO ("delete trans at addr=%p\n", trans); /* Make a log in the journal before destruction. */ xaccTransWriteLog (trans, 'D'); xaccRemoveEntity(&trans->guid); @@ -1062,7 +1062,13 @@ xaccTransCommitEdit (Transaction *trans) xaccFreeTransaction (trans->orig); trans->orig = NULL; - LEAVE ("xaccTransCommitEdit(): trans addr=%p\n", trans); + /* see if there's a backend. If there is, invoke it */ + be = xaccTransactionGetBackend (trans); + if (be) { + (be->trans_commit_edit) (be, trans); + } + + LEAVE ("trans addr=%p\n", trans); } void @@ -1077,7 +1083,7 @@ xaccTransRollbackEdit (Transaction *trans) CHECK_OPEN (trans); - ENTER ("xaccTransRollbackEdit(): trans addr=%p\n", trans); + ENTER ("trans addr=%p\n", trans); /* copy the original values back in. */ orig = trans->orig; @@ -1179,7 +1185,7 @@ xaccTransRollbackEdit (Transaction *trans) trans->orig = NULL; trans->open = 0; - LEAVE ("xaccTransRollbackEdit(): trans addr=%p\n", trans); + LEAVE ("trans addr=%p\n", trans); } gncBoolean @@ -1645,7 +1651,7 @@ xaccTransSetDateSecs (Transaction *trans, time_t secs) { if (!trans) return; CHECK_OPEN (trans); - PINFO ("xaccTransSetDateSecs(): addr=%p set date to %lu %s \n", + PINFO ("addr=%p set date to %lu %s \n", trans, secs, ctime (&secs)); trans->date_posted.tv_sec = secs; @@ -1667,7 +1673,7 @@ xaccTransSetDateSecsL (Transaction *trans, long long secs) CHECK_OPEN (trans); DEBUGCMD ({ time_t sicko = secs; - PINFO ("xaccTransSetDateSecsL(): addr=%p set date to %Lu %s \n", + PINFO ("addr=%p set date to %Lu %s \n", trans, secs, ctime (&sicko)); }) @@ -1692,7 +1698,7 @@ xaccTransSetDateTS (Transaction *trans, const Timespec *ts) CHECK_OPEN (trans); DEBUGCMD ({ time_t sicko = ts->tv_sec; - PINFO ("xaccTransSetDateTS(): addr=%p set date to %Lu %s \n", + PINFO ("addr=%p set date to %Lu %s \n", trans, ts->tv_sec, ctime (&sicko)); }) @@ -1769,7 +1775,7 @@ xaccTransSetDateToday (Transaction *trans) trans->date_posted.tv_sec = tv.tv_sec; trans->date_posted.tv_nsec = 1000 * tv.tv_usec; - PINFO ("xaccTransSetDateToday(): addr=%p set date to %lu %s \n", + PINFO ("addr=%p set date to %lu %s \n", trans, tv.tv_sec, ctime ((time_t *)&tv.tv_sec)); }