mirror of
https://github.com/Gnucash/gnucash.git
synced 2026-10-13 01:41:59 -05:00
rough in event notification framework
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@4570 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
1 parent
5693de8531
commit
d25f757053
3 files changed
+223
-15
No files matched your search
@@ -233,6 +233,137 @@ static const char *table_drop_str =
|
||||
#include "table-drop.c"
|
||||
;
|
||||
|
||||
/* ============================================================= */
|
||||
/* ============================================================= */
|
||||
/* EVENT NOTIFICATION HANDLER */
|
||||
/* ============================================================= */
|
||||
/* ============================================================= */
|
||||
|
||||
#define NOTIFY_ACCOUNT(be,x) { \
|
||||
if ((MODE_POLL == be->session_mode) || \
|
||||
(MODE_EVENT == be->session_mode)) \
|
||||
{ \
|
||||
SEND_QUERY (be,"NOTIFY gncAccount;", x); \
|
||||
FINISH_QUERY(be->connection); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define NOTIFY_CHECKPOINT(be,x) { \
|
||||
if ((MODE_POLL == be->session_mode) || \
|
||||
(MODE_EVENT == be->session_mode)) \
|
||||
{ \
|
||||
SEND_QUERY (be,"NOTIFY gncCheckpoint;", x);\
|
||||
FINISH_QUERY(be->connection); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define NOTIFY_PRICE(be,x) { \
|
||||
if ((MODE_POLL == be->session_mode) || \
|
||||
(MODE_EVENT == be->session_mode)) \
|
||||
{ \
|
||||
SEND_QUERY (be,"NOTIFY gncPrice;", x); \
|
||||
FINISH_QUERY(be->connection); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define NOTIFY_TRANSACTION(be,x) { \
|
||||
if ((MODE_POLL == be->session_mode) || \
|
||||
(MODE_EVENT == be->session_mode)) \
|
||||
{ \
|
||||
SEND_QUERY (be,"NOTIFY gncTransaction;", x);\
|
||||
FINISH_QUERY(be->connection); \
|
||||
} \
|
||||
}
|
||||
|
||||
static void
|
||||
pgendHandleEvents (PGBackend *be)
|
||||
{
|
||||
PGnotify *note;
|
||||
char *p;
|
||||
int do_account=0, do_checkpoint=0, do_price=0;
|
||||
int do_session=0, do_transaction=0;
|
||||
|
||||
/* no need to handle events in single-modes, since
|
||||
* they shouldn't be generated nor received. */
|
||||
if ((MODE_SINGLE_UPDATE == be->session_mode) ||
|
||||
(MODE_SINGLE_FILE == be->session_mode))
|
||||
{
|
||||
note = PQnotifies (be->connection);
|
||||
while (note)
|
||||
{
|
||||
note = PQnotifies (be->connection);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* consolidate multiple event notifications */
|
||||
note = PQnotifies (be->connection);
|
||||
while (note)
|
||||
{
|
||||
/* ignore notifies from myself */
|
||||
if (note->be_pid == be->my_pid)
|
||||
{
|
||||
note = PQnotifies (be->connection);
|
||||
continue;
|
||||
}
|
||||
|
||||
PINFO ("%s", note->relname);
|
||||
|
||||
if (0 == strcasecmp ("gncTransaction", note->relname))
|
||||
{
|
||||
do_transaction ++;
|
||||
}
|
||||
else
|
||||
if (0 == strcasecmp ("gncCheckpoint", note->relname))
|
||||
{
|
||||
do_checkpoint ++;
|
||||
}
|
||||
else
|
||||
if (0 == strcasecmp ("gncPrice", note->relname))
|
||||
{
|
||||
do_price ++;
|
||||
}
|
||||
else
|
||||
if (0 == strcasecmp ("gncAccount", note->relname))
|
||||
{
|
||||
do_account ++;
|
||||
}
|
||||
else
|
||||
if (0 == strcasecmp ("gncSession", note->relname))
|
||||
{
|
||||
do_session ++;
|
||||
}
|
||||
else
|
||||
{
|
||||
PERR ("unexpected notify %s", note->relname)
|
||||
}
|
||||
|
||||
/* get the next one */
|
||||
note = PQnotifies (be->connection);
|
||||
}
|
||||
|
||||
/* handle each event type */
|
||||
if (do_account)
|
||||
{
|
||||
}
|
||||
|
||||
if (do_checkpoint)
|
||||
{
|
||||
}
|
||||
|
||||
if (do_price)
|
||||
{
|
||||
}
|
||||
|
||||
if (do_session)
|
||||
{
|
||||
}
|
||||
|
||||
if (do_transaction)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/* ============================================================= */
|
||||
/* ============================================================= */
|
||||
/* ACCOUNT AND GROUP STUFF */
|
||||
@@ -370,7 +501,8 @@ pgendStoreGroup (PGBackend *be, AccountGroup *grp)
|
||||
/* reset the write flags again */
|
||||
xaccClearMarkDownGr (grp, 0);
|
||||
|
||||
p = "COMMIT;";
|
||||
p = "COMMIT;\n"
|
||||
"NOTIFY gncAccount;";
|
||||
SEND_QUERY (be,p, );
|
||||
FINISH_QUERY(be->connection);
|
||||
LEAVE(" ");
|
||||
@@ -792,7 +924,8 @@ pgendStoreTransaction (PGBackend *be, Transaction *trans)
|
||||
|
||||
pgendStoreTransactionNoLock (be, trans, TRUE);
|
||||
|
||||
bufp = "COMMIT;";
|
||||
bufp = "COMMIT;\n"
|
||||
"NOTIFY gncTransaction;";
|
||||
SEND_QUERY (be,bufp, );
|
||||
FINISH_QUERY(be->connection);
|
||||
|
||||
@@ -847,7 +980,8 @@ pgendStoreAllTransactions (PGBackend *be, AccountGroup *grp)
|
||||
xaccGroupBeginStagedTransactionTraversals(grp);
|
||||
xaccGroupStagedTransactionTraversal (grp, 1, trans_traverse_cb, be);
|
||||
|
||||
p = "COMMIT;";
|
||||
p = "COMMIT;\n"
|
||||
"NOTIFY gncTransaction;";
|
||||
SEND_QUERY (be,p, );
|
||||
FINISH_QUERY(be->connection);
|
||||
|
||||
@@ -947,6 +1081,7 @@ pgendCopyTransactionToEngine (PGBackend *be, const GUID *trans_guid)
|
||||
guid_to_string (trans_guid));
|
||||
if (jrows != nrows) xaccTransCommitEdit (trans);
|
||||
xaccBackendSetError (&be->be, ERR_BACKEND_DATA_CORRUPT);
|
||||
pgendHandleEvents(be);
|
||||
pgendEnable(be);
|
||||
gnc_engine_resume_events();
|
||||
return 0;
|
||||
@@ -1012,6 +1147,7 @@ pgendCopyTransactionToEngine (PGBackend *be, const GUID *trans_guid)
|
||||
* punt for now ... */
|
||||
PERR ("no such transaction in the database. This is unexpected ...\n");
|
||||
xaccBackendSetError (&be->be, ERR_SQL_MISSING_DATA);
|
||||
pgendHandleEvents(be);
|
||||
pgendEnable(be);
|
||||
gnc_engine_resume_events();
|
||||
return 0;
|
||||
@@ -1020,6 +1156,7 @@ pgendCopyTransactionToEngine (PGBackend *be, const GUID *trans_guid)
|
||||
/* if engine data was newer, we are done */
|
||||
if (0 <= engine_data_is_newer)
|
||||
{
|
||||
pgendHandleEvents(be);
|
||||
pgendEnable(be);
|
||||
gnc_engine_resume_events();
|
||||
return engine_data_is_newer;
|
||||
@@ -1180,6 +1317,7 @@ pgendCopyTransactionToEngine (PGBackend *be, const GUID *trans_guid)
|
||||
xaccTransCommitEdit (trans);
|
||||
|
||||
/* re-enable events to the backend and GUI */
|
||||
pgendHandleEvents(be);
|
||||
pgendEnable(be);
|
||||
gnc_engine_resume_events();
|
||||
|
||||
@@ -1245,6 +1383,7 @@ pgendSyncTransaction (PGBackend *be, GUID *trans_guid)
|
||||
}
|
||||
|
||||
/* re-enable events to the backend and GUI */
|
||||
pgendHandleEvents(be);
|
||||
pgendEnable(be);
|
||||
gnc_engine_resume_events();
|
||||
|
||||
@@ -1475,6 +1614,7 @@ pgendRunQuery (Backend *bend, Query *q)
|
||||
* mark it all as having been saved. */
|
||||
xaccGroupMarkSaved (be->topgroup);
|
||||
|
||||
pgendHandleEvents(be);
|
||||
pgendEnable(be);
|
||||
gnc_engine_resume_events();
|
||||
|
||||
@@ -1511,6 +1651,7 @@ pgendGetAllTransactions (PGBackend *be, AccountGroup *grp)
|
||||
}
|
||||
g_list_free(xaction_list);
|
||||
|
||||
pgendHandleEvents(be);
|
||||
pgendEnable(be);
|
||||
gnc_engine_resume_events();
|
||||
}
|
||||
@@ -1618,7 +1759,8 @@ pgendStorePriceDB (PGBackend *be, GNCPriceDB *prdb)
|
||||
|
||||
pgendStorePriceDBNoLock (be, prdb);
|
||||
|
||||
p = "COMMIT;";
|
||||
p = "COMMIT;\n"
|
||||
"NOTIFY gncPrice;";
|
||||
SEND_QUERY (be,p, );
|
||||
FINISH_QUERY(be->connection);
|
||||
LEAVE(" ");
|
||||
@@ -1802,6 +1944,7 @@ pgendPriceLookup (Backend *bend, GNCPriceLookup *look)
|
||||
gnc_pricedb_mark_clean (look->prdb);
|
||||
|
||||
/* re-enable events */
|
||||
pgendHandleEvents(be);
|
||||
pgendEnable(be);
|
||||
gnc_engine_resume_events();
|
||||
|
||||
@@ -1878,7 +2021,8 @@ pgend_account_commit_edit (Backend * bend,
|
||||
pgendStoreAccountNoLock (be, acct, FALSE, FALSE);
|
||||
}
|
||||
|
||||
p = "COMMIT;";
|
||||
p = "COMMIT;\n"
|
||||
"NOTIFY gncAccount;";
|
||||
SEND_QUERY (be,p,336);
|
||||
FINISH_QUERY(be->connection);
|
||||
|
||||
@@ -2003,7 +2147,8 @@ pgend_trans_commit_edit (Backend * bend,
|
||||
/* if we are here, we are good to go */
|
||||
pgendStoreTransactionNoLock (be, trans, FALSE);
|
||||
|
||||
bufp = "COMMIT;";
|
||||
bufp = "COMMIT;\n"
|
||||
"NOTIFY gncTransaction;";
|
||||
SEND_QUERY (be,bufp,334);
|
||||
FINISH_QUERY(be->connection);
|
||||
|
||||
@@ -2143,7 +2288,8 @@ pgend_price_commit_edit (Backend * bend, GNCPrice *pr)
|
||||
pgendStorePriceNoLock (be, pr, FALSE);
|
||||
}
|
||||
|
||||
bufp = "COMMIT;";
|
||||
bufp = "COMMIT;\n"
|
||||
"NOTIFY gncPrice;";
|
||||
SEND_QUERY (be,bufp,335);
|
||||
FINISH_QUERY(be->connection);
|
||||
|
||||
@@ -2223,6 +2369,7 @@ pgendSync (Backend *bend, AccountGroup *grp)
|
||||
}
|
||||
|
||||
/* re-enable events */
|
||||
pgendHandleEvents(be);
|
||||
pgendEnable(be);
|
||||
gnc_engine_resume_events();
|
||||
|
||||
@@ -2301,6 +2448,7 @@ pgendSyncPriceDB (Backend *bend, GNCPriceDB *prdb)
|
||||
pgendGetAllPrices (be, prdb);
|
||||
|
||||
/* re-enable events */
|
||||
pgendHandleEvents(be);
|
||||
pgendEnable(be);
|
||||
gnc_engine_resume_events();
|
||||
|
||||
@@ -2347,6 +2495,52 @@ pgendSyncPriceDBSingleFile (Backend *bend, GNCPriceDB *prdb)
|
||||
LEAVE(" ");
|
||||
}
|
||||
|
||||
/* ============================================================= */
|
||||
/* find the backend pid */
|
||||
|
||||
static void
|
||||
pgendSessionGetPid (PGBackend *be)
|
||||
{
|
||||
PGnotify *note;
|
||||
char *p;
|
||||
long int r;
|
||||
|
||||
r = random ();
|
||||
|
||||
p = be->buff; *p=0;
|
||||
sprintf (p, "LISTEN \"%ld\";\n NOTIFY \"%ld\";", r, r);
|
||||
SEND_QUERY (be, be->buff, );
|
||||
FINISH_QUERY(be->connection);
|
||||
note = PQnotifies (be->connection);
|
||||
if (!note)
|
||||
{
|
||||
PERR ("didn't receive notification");
|
||||
return;
|
||||
}
|
||||
|
||||
be->my_pid = note->be_pid;
|
||||
PINFO ("postgres backend pid =%d", be->my_pid);
|
||||
|
||||
p = be->buff; *p=0;
|
||||
sprintf (p, "UNLISTEN \"%ld\";", r);
|
||||
SEND_QUERY (be, be->buff, );
|
||||
FINISH_QUERY(be->connection);
|
||||
}
|
||||
|
||||
/* ============================================================= */
|
||||
|
||||
static void
|
||||
pgendSessionSetupNotifies (PGBackend *be)
|
||||
{
|
||||
char *p;
|
||||
|
||||
p = "LISTEN gncSession;\nLISTEN gncAccount;\n"
|
||||
"LISTEN gncPrice;\nLISTEN gncTransaction;\n"
|
||||
"LISTEN gncCheckpoint;";
|
||||
SEND_QUERY (be, p, );
|
||||
FINISH_QUERY(be->connection);
|
||||
}
|
||||
|
||||
/* ============================================================= */
|
||||
|
||||
static const char *
|
||||
@@ -2536,7 +2730,8 @@ pgendSessionValidate (PGBackend *be, int break_lock)
|
||||
retval = TRUE;
|
||||
}
|
||||
|
||||
p = "COMMIT;";
|
||||
p = "COMMIT;\n"
|
||||
"NOTIFY gncSession;";
|
||||
SEND_QUERY (be,p, FALSE);
|
||||
FINISH_QUERY(be->connection);
|
||||
|
||||
@@ -2560,7 +2755,8 @@ pgendSessionEnd (PGBackend *be)
|
||||
p = stpcpy (p, "UPDATE gncSession SET time_off='NOW' "
|
||||
"WHERE sessionGuid='");
|
||||
p = guid_to_string_buff (be->sessionGuid, p);
|
||||
p = stpcpy (p, "';");
|
||||
p = stpcpy (p, "';\n"
|
||||
"NOTIFY gncSession;");
|
||||
|
||||
SEND_QUERY (be,be->buff, );
|
||||
FINISH_QUERY(be->connection);
|
||||
@@ -2664,6 +2860,7 @@ pgend_book_load_poll (Backend *bend)
|
||||
pgendGroupGetAllBalances (be, grp, ts);
|
||||
|
||||
/* re-enable events */
|
||||
pgendHandleEvents(be);
|
||||
pgendEnable(be);
|
||||
gnc_engine_resume_events();
|
||||
|
||||
@@ -3174,6 +3371,10 @@ pgend_session_begin (GNCBook *sess, const char * sessionid,
|
||||
|
||||
case MODE_POLL:
|
||||
pgendEnable(be);
|
||||
|
||||
pgendSessionGetPid (be);
|
||||
pgendSessionSetupNotifies (be);
|
||||
|
||||
be->be.book_load = pgend_book_load_poll;
|
||||
be->be.price_load = pgend_price_load_poll;
|
||||
be->be.account_begin_edit = NULL;
|
||||
@@ -3188,9 +3389,9 @@ pgend_session_begin (GNCBook *sess, const char * sessionid,
|
||||
// be->be.sync = pgendSync;
|
||||
be->be.sync = NULL;
|
||||
be->be.sync_price = pgendSyncPriceDB;
|
||||
PWARN ("MODE_POLL is alpha -- \n"
|
||||
"there are a few unfixed bugs, but maybe this mode is usable.\n"
|
||||
"It might still corrupt your data, we're not sure yet.\n");
|
||||
PWARN ("MODE_POLL is beta -- \n"
|
||||
"we've fixed all known bugs but that doesn't mean\n"
|
||||
"there aren't any! If something seems weird, let us know.\n");
|
||||
break;
|
||||
|
||||
case MODE_EVENT:
|
||||
@@ -3322,6 +3523,8 @@ pgendInit (PGBackend *be)
|
||||
be->username = NULL;
|
||||
be->connection = NULL;
|
||||
|
||||
be->my_pid = 0;
|
||||
|
||||
be->builder = sqlBuilder_new();
|
||||
|
||||
be->buff = g_malloc (QBUFSIZE);
|
||||
|
||||
@@ -75,6 +75,8 @@ struct _pgend {
|
||||
/* callback hooks are saved in snr during disables */
|
||||
Backend snr;
|
||||
|
||||
/* my postgres backend pid, used for telling apart notifies */
|
||||
int my_pid;
|
||||
|
||||
/* scratch space for constructing queries */
|
||||
int bufflen;
|
||||
|
||||
@@ -212,7 +212,8 @@ done:
|
||||
" WHERE accountGuid='");
|
||||
p = stpcpy (p, guid_string);
|
||||
p = stpcpy (p, "';\n");
|
||||
p = stpcpy (p, "COMMIT WORK;\n");
|
||||
p = stpcpy (p, "COMMIT WORK;\n"
|
||||
"NOTIFY gncCheckpoint;\n");
|
||||
SEND_QUERY (be,be->buff, );
|
||||
FINISH_QUERY(be->connection);
|
||||
|
||||
@@ -262,7 +263,8 @@ pgendAccountRecomputeOneCheckpoint (PGBackend *be, Account *acc, Timespec ts)
|
||||
p = stpcpy (p, dbuf);
|
||||
p = stpcpy (p, "';\n");
|
||||
|
||||
p = stpcpy (p, "COMMIT WORK;\n");
|
||||
p = stpcpy (p, "COMMIT WORK;\n"
|
||||
"NOTIFY gncCheckpoint;\n");
|
||||
SEND_QUERY (be,be->buff, );
|
||||
FINISH_QUERY(be->connection);
|
||||
}
|
||||
@@ -290,7 +292,8 @@ pgendTransactionRecomputeCheckpoints (PGBackend *be, Transaction *trans)
|
||||
" AND gncCheckpoint.accountGuid = gncEntry.accountGuid "
|
||||
" AND date_start <= gncTransaction.date_posted "
|
||||
" AND date_end > gncTransaction.date_posted;\n"
|
||||
"COMMIT WORK;\n");
|
||||
"COMMIT WORK;\n"
|
||||
"NOTIFY gncCheckpoint;\n");
|
||||
SEND_QUERY (be,be->buff, );
|
||||
FINISH_QUERY(be->connection);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user