XML-RPC interface (was: Will GnuCash ever work for me?)

Linas Vepstas linas@linas.org
Tue, 25 Sep 2001 22:00:38 -0500


On Tue, Sep 25, 2001 at 01:15:00PM -0700, Jeb Bateman was heard to remark:
> On Tue, Sep 25, 2001 at 02:02:58PM -0500, Linas Vepstas wrote:
> > The traditional gnucash 'theory' is that the 'correct' programming
> > interface/API is the 'engine' programming interface.  Part of this
> > theory is that there are supposed to be 'engine backends' that know how
> > to communicate with persistent-storage backends.
> 
> And from a client-side programming perspective, you shouldn't have to
> worry about which data-store is being used by the backend, right?

Right.  Yuo just nead to know the URI to connect to. The rest is handled
automagically.

> > There are currently four backends:
> > -- the file format backend, can save/restore from file.  This is a 
> >    single-user, local-storage backend.
> > -- the sql backend, can connect to local or remote database, supports
> >    multiple simultaneous users.  Beta.  Works for me; might have
> >    scalability or performance problems.
> > -- the 'rpc' backend.  Uses rpc to talk to remote gnucash server.
> >    Code exists, but its broken, not currently operational.
> > -- the 'http' backend.  Uses http to manage connections.  Uses a
> >    an enhanced version of the XML file format as the actual data
> >    protocol.  Currently broken by recent file format changes, but it
> >    used to kinda-work.  (The idea was that http would provide SSL,
> >    authentication, socket management, state management, permissions,
> >    etc ... all that communnications-level stuff that apache provides).
> 
> It sounds like the last two could be combined into an XML-RPC backend,
> since it inherently runs over HTTP.  

Hmmm. Well, that might be the right thing to do then.  I always thought
that our xml code should have been autogenerated from some kind of 
idl description, instead of being hand-weinered.  However, there's 
no (open source) idl compiler that would do this. 

But maybe indeed it would be easier to use xml-rpc than to whack our xml
code back into having a stream interface. 

> > Right.  You could put an XML-RPC interface in front of the engine.
> > But I think it would suffer serious performance problems.  It would be 
> > nasty to make an rpc call to set the payee, a second one to set the
> > date, a third one to set the amount... etc. 
> 
> You don't have to make an rpc call for each piece of data.  The client
> program collects data from the user, and then submits it all at once
> to the XML-RPC server for processing...

Well, right.  That's what the gnucash 'backend' is (or is supposed to
be).   You make a bunch of gnucash engine api calls to assemble a transaction.
There's one very special engine api call called 'xaccTransCommitEdit()'.
This call invokes the backend 'commit_edit()' routine that is supposed
to 'marshall' all the data and ship it off to the server.

> > Note also that one of the things that the 'engine' provides
> > is a 'local cache' of the account data.  
> 
> You mean there is an "engine" for the client side too?  

'too' is the wrong word.

Yes.  What we call the 'engine' is supposed to sit in the client.  
Its 'libgnc_engine.so', and its supposed to be linked by the client.

There's not really any clearly-defined gnucash server, and whether or
not it would use any pre-existing gnucash code is 'implementation
dependent'.   For example the 'gnucash sql server' is one and the 
same as the postgres sql server.  Its 100% pure postgres. There
is 0% gnucash code in there.   None-the-less, its a 'real server',
allowing multiple connections etc. 

In the case of the unfinished rpc and http gnucash servers, we
were planning on linking to libgnc_engine.so as well, but that's
an 'implementation issue'.

> What language
> is it written in?  

100% pure C.

> Is it easy for any language to use this local data
> cache?  

Sort-of. I've used swig to generate perl bindings, and swig should be
do python bindings as well.  Rob developed g-wrap to provide scheme
bindings.   Since the engine has an OO-style interface, it should be
straightforward to wrapper it in java.

> > Note that the 'cache' is not a theory: it actually works with the sql
> > backend. As far as I know, there are are no bugs or problems with 
> > the cache getting out of sync.
> 
> Cool.  If it's written and working, that's great; but I suspect it's
> limited to a single language implementation, which is okay.  (People
> writing sophisticated clients might want to choose that language to
> save the work of implementing a cache themselves...)

Well, there are some swig issues, such as converting glib linked lists
into perl arrays.  But this is a solvable problem.   If you just want to 
open a gnucash data-store and poke around, it works. 

#!/usr/bin/perl -w

# gnucash perl demo:
#
# This file demonstrates how to open a gnucash file/url and print 
# the names and balances of the top-level accounts in the file.
# Its a pretty basic demo.
#
# use lib '/usr/lib/gnucash/';
use lib '..';
use gnucash;                                           
package gnucash;

die "Usage: $0 <gnucash filename or url>" if $#ARGV < 0;
print "Will load $ARGV[0]\n";

gnucash::gnc_engine_init(0, $ARGV);
$session = gnucash::gnc_book_new ();

$rc = gnucash::gnc_book_begin ($session, $ARGV[0], 1, 0);
if ($rc != 1) 
{
   $err = gnucash::gnc_book_get_error ($session);
   print "Could not find $ARGV[0], errrocode=$err\n";
}

$rc = gnucash::gnc_book_load ($session);
die "Could not load $ARGV[0]\n" if $rc != 1;

$grp = gnucash::gnc_book_get_group ($session);
$numacc = gnucash::xaccGroupGetNumAccounts ($grp);
print "Loaded $numacc accounts\n\n";

for ($i=0; $i<$numacc; $i++) {
   $acct = gnucash::xaccGroupGetAccount ($grp, $i);
   $acctname = gnucash::xaccAccountGetName ($acct);
   $numeric_baln = gnucash::xaccAccountGetBalance ($acct);
   $baln = gnucash::gnc_numeric_to_double ($numeric_baln);
   print "\tAccount: $acctname \tBalance: $baln\n";
}

gnucash::gnc_book_end ($session);

> > I was hopping that you were going to tell me that you had some
> > explicit plans ....
> 
> No time at the moment, but I might start taking a look at the backend
> code and interfaces sometime later, especially after Bill has checked
> in his initial XML-RPC implementation...

Well, 

What I keep trying to say is that most people should *not* look at the
backends at all.  Its clear that we still need to implement one or two
more, so that we can really have a generic server.   But ordinary
'users' should be coding to the engine api.  The backends are supposed
to be off-limits, and have a kind-of special relationship with the
engine.

--linas


-- 
pub  1024D/01045933 2001-02-01 Linas Vepstas (Labas!) <linas@linas.org>
     Key fingerprint = 8305 2521 6000 0B5E 8984  3F54 64A9 9A82 0104 5933