From 8674898c8857269b73f98ac219c22cbd171f8b0f Mon Sep 17 00:00:00 2001 From: Linas Vepstas Date: Sun, 10 Jun 2001 22:53:28 +0000 Subject: [PATCH] restructure event handling git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@4594 57a11ea4-9604-0410-9ed3-97b8803252fd --- src/engine/gnc-engine-util.c | 1 + src/engine/gnc-engine-util.h | 3 +- src/engine/sql/README | 2 +- src/engine/sql/events.c | 155 ++++++++++++++++++++--------------- src/engine/sql/txn.c | 2 +- 5 files changed, 96 insertions(+), 67 deletions(-) diff --git a/src/engine/gnc-engine-util.c b/src/engine/gnc-engine-util.c index 426d36693c..f57f04eaa8 100644 --- a/src/engine/gnc-engine-util.c +++ b/src/engine/gnc-engine-util.c @@ -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 */ }; diff --git a/src/engine/gnc-engine-util.h b/src/engine/gnc-engine-util.h index 84cc14731e..a5f8f2f91b 100644 --- a/src/engine/gnc-engine-util.h +++ b/src/engine/gnc-engine-util.h @@ -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 diff --git a/src/engine/sql/README b/src/engine/sql/README index 8db0160ce7..e2f350099e 100644 --- a/src/engine/sql/README +++ b/src/engine/sql/README @@ -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 ... diff --git a/src/engine/sql/events.c b/src/engine/sql/events.c index 1df7fdfe7e..74e5634213 100644 --- a/src/engine/sql/events.c +++ b/src/engine/sql/events.c @@ -1,5 +1,6 @@ /********************************************************************\ * events.c -- implements event handling for postgres backend * + * Copyright (c) 2001 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 * @@ -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); - - /* 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); - } + PINFO ("event %c for %s", change, guid_str); - /* get event timestamp */ - ts = gnc_iso8601_to_timespec_local (DB_GET_VAL("date_changed",j)); - if (0 < timespec_cmp(&ts, latest)) *latest = ts; + ev = g_new (Event, 1); - /* 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;"; diff --git a/src/engine/sql/txn.c b/src/engine/sql/txn.c index 4a54f128b3..69dbc163f3 100644 --- a/src/engine/sql/txn.c +++ b/src/engine/sql/txn.c @@ -49,7 +49,7 @@ #include "putil.h" -static short module = MOD_BACKEND; +static short module = MOD_TXN; /* ============================================================= */ /* ============================================================= */