restructure event handling

git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@4594 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
Linas Vepstas 2001-06-10 22:53:28 +00:00
parent 9de71e4d8d
commit 8674898c88
5 changed files with 96 additions and 67 deletions

View File

@ -60,6 +60,7 @@ static gncLogLevel loglevel[MOD_LAST + 1] =
GNC_LOG_WARNING, /* QUERY */
GNC_LOG_WARNING, /* PRICE */
GNC_LOG_WARNING, /* EVENT */
GNC_LOG_WARNING, /* TXN */
};

View File

@ -59,7 +59,8 @@ typedef enum
MOD_QUERY = 11,
MOD_PRICE = 12,
MOD_EVENT = 13,
MOD_LAST = 13
MOD_TXN = 14,
MOD_LAST = 14
} gncModuleType;
typedef enum

View File

@ -294,7 +294,7 @@ operation is probably OK.
They're not needed until there are a lot of transactions in the
system. Need to recompute checkpoints on some periodic basis.
-- get notify timestamp from trail. (to avoid clock skew)
-- put marks on transactions during FillOut
-- NOTIFY is not updating main window balances ...

View File

@ -1,5 +1,6 @@
/********************************************************************\
* events.c -- implements event handling for postgres backend *
* Copyright (c) 2001 Linas Vepstas <linas@linas.org> *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
@ -20,18 +21,6 @@
\********************************************************************/
/*
* FILE:
* events.c
*
* FUNCTION:
* Implements the event-handling callbacks for the Postgres backend.
*
* HISTORY:
* Copyright (c) 2000, 2001 Linas Vepstas
*
*/
#define _GNU_SOURCE
#include "config.h"
@ -49,8 +38,8 @@
#include "GNCIdP.h"
#include "PostgresBackend.h"
#include "putil.h"
#include "txn.h"
static short module = MOD_EVENT;
@ -139,69 +128,53 @@ pgendEventsPending (Backend *bend)
return FALSE;
}
/* ============================================================= */
typedef struct _event {
Timespec stamp;
GNCEngineEventType type;
GUID guid;
} Event;
static gpointer
get_event_cb (PGBackend *be, PGresult *result, int j, gpointer data)
{
GNCEngineEventType type;
char * guid_str;
GUID guid;
GNCIdType obj_type;
Timespec ts;
Timespec *latest = (Timespec *) data;
GList *list = (GList *) data;
char *guid_str;
Event *ev;
char change = (DB_GET_VAL("change",j))[0];
guid_str = DB_GET_VAL("guid",j);
string_to_guid (guid_str, &guid);
PINFO ("event %c for %s", change, guid_str);
/* lets see if the local cache has this item in it */
obj_type = xaccGUIDType (&guid);
switch (obj_type)
{
case GNC_ID_NONE:
case GNC_ID_NULL:
PINFO ("unknown object for guid=%s", guid_str);
break;
case GNC_ID_ACCOUNT:
break;
case GNC_ID_TRANS:
// pgendCopyTransactionToEngine (be, &guid);
break;
case GNC_ID_SPLIT:
break;
case GNC_ID_PRICE:
break;
default:
PERR ("unknown guid type %d for guid=%s", obj_type, guid_str);
}
ev = g_new (Event, 1);
/* get event timestamp */
ts = gnc_iso8601_to_timespec_local (DB_GET_VAL("date_changed",j));
if (0 < timespec_cmp(&ts, latest)) *latest = ts;
/* send out the event to listeners */
/* convert from SQL type to engine type */
switch (change)
{
case 'a': type = GNC_EVENT_CREATE; break;
case 'm': type = GNC_EVENT_MODIFY; break;
case 'd': type = GNC_EVENT_DESTROY; break;
case 'a': ev->type = GNC_EVENT_CREATE; break;
case 'm': ev->type = GNC_EVENT_MODIFY; break;
case 'd': ev->type = GNC_EVENT_DESTROY; break;
default:
PERR ("unknown change type %c", change);
PERR ("unknown change type %c for guid=%s", change, guid_str);
g_free (ev);
return data;
}
string_to_guid (guid_str, &(ev->guid));
PINFO ("event %c for %s", change, guid_str);
gnc_engine_generate_event (&guid, type);
/* get event timestamp */
ev->stamp = gnc_iso8601_to_timespec_local (DB_GET_VAL("date_changed",j));
return data;
/* add it to our list */
list = g_list_prepend (list, ev);
return (gpointer) list;
}
#define GET_EVENTS(guid_name,table,timestamp) \
#define GET_EVENTS(guid_name,table, timestamp) \
{ \
Timespec latest; \
char *p; \
latest.tv_sec = -2; \
latest.tv_nsec = 0; \
\
p = be->buff; *p = 0; \
p = stpcpy (p, "SELECT change, date_changed, " #guid_name \
" AS guid FROM " #table \
@ -212,24 +185,20 @@ get_event_cb (PGBackend *be, PGresult *result, int j, gpointer data)
p = stpcpy (p, "';"); \
\
SEND_QUERY (be, be->buff, FALSE); \
pgendGetResults (be, get_event_cb, &latest); \
\
if (0 < timespec_cmp(&latest, &(timestamp))) \
{ \
(timestamp) = latest; \
} \
pending = (GList *) pgendGetResults (be, get_event_cb, pending); \
}
gboolean
pgendProcessEvents (Backend *bend)
{
PGBackend *be = (PGBackend *) bend;
GList *node, *pending = NULL;
if (!be) return FALSE;
ENTER (" ");
/* handle each event type */
/* get all recent events from teh SQL db. */
if (be->do_account)
{
GET_EVENTS (accountGuid, gncAccountTrail, be->last_account);
@ -246,6 +215,43 @@ pgendProcessEvents (Backend *bend)
// GET_EVENTS (entryGuid, gncEntryTrail, be->last_transaction);
}
/* Loop over each item, updating the engine, and dispatching events */
for (node = pending; node; node = node->next)
{
Event *ev = (Event *) node->data;
GNCIdType obj_type;
/* lets see if the local cache has this item in it */
obj_type = xaccGUIDType (&(ev->guid));
switch (obj_type)
{
case GNC_ID_NONE:
case GNC_ID_NULL:
PINFO ("object not present in local cache");
break;
case GNC_ID_ACCOUNT:
if (0 < timespec_cmp(&(ev->stamp), &(be->last_account))) be->last_account = ev->stamp;
break;
case GNC_ID_TRANS:
if (0 < timespec_cmp(&(ev->stamp), &(be->last_transaction))) be->last_transaction = ev->stamp;
// pgendCopyTransactionToEngine (be, &(ev->guid));
break;
case GNC_ID_SPLIT:
if (0 < timespec_cmp(&(ev->stamp), &(be->last_transaction))) be->last_transaction = ev->stamp;
break;
case GNC_ID_PRICE:
if (0 < timespec_cmp(&(ev->stamp), &(be->last_price))) be->last_price = ev->stamp;
break;
default:
PERR ("unknown guid type %d", obj_type);
}
gnc_engine_generate_event (&(ev->guid), ev->type);
g_free (ev);
}
g_list_free (pending);
be->do_account = 0;
be->do_checkpoint = 0;
be->do_price = 0;
@ -289,11 +295,32 @@ pgendSessionGetPid (PGBackend *be)
/* ============================================================= */
static gpointer
get_latest_cb (PGBackend *be, PGresult *result, int j, gpointer data)
{
Timespec latest;
/* get event timestamp */
latest = gnc_iso8601_to_timespec_local (DB_GET_VAL("date_changed",j));
be->last_account = latest;
be->last_price = latest;
be->last_transaction = latest;
return data;
}
void
pgendSessionSetupNotifies (PGBackend *be)
{
char *p;
/* get latest times from the database; this to avoid clock
* skew between database and this local process */
p = "SELECT date_changed FROM gncAuditTrail* ORDER BY date_changed DESC LIMIT 1;";
SEND_QUERY (be, p, );
pgendGetResults (be, get_latest_cb, NULL);
p = "LISTEN gncSession;\nLISTEN gncAccount;\n"
"LISTEN gncPrice;\nLISTEN gncTransaction;\n"
"LISTEN gncCheckpoint;";

View File

@ -49,7 +49,7 @@
#include "putil.h"
static short module = MOD_BACKEND;
static short module = MOD_TXN;
/* ============================================================= */
/* ============================================================= */