From e94e681a482bfbdeb89ff127ed1c3c2f85e51dad Mon Sep 17 00:00:00 2001 From: Linas Vepstas Date: Sat, 9 Jun 2001 04:16:40 +0000 Subject: [PATCH] fix multi-user transaction rollback git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@4556 57a11ea4-9604-0410-9ed3-97b8803252fd --- src/engine/sql/PostgresBackend.c | 45 +++++++++++++++++++++++++++----- src/engine/sql/README | 24 +++++++---------- 2 files changed, 49 insertions(+), 20 deletions(-) diff --git a/src/engine/sql/PostgresBackend.c b/src/engine/sql/PostgresBackend.c index af8ea8b5c9..70fcd276da 100644 --- a/src/engine/sql/PostgresBackend.c +++ b/src/engine/sql/PostgresBackend.c @@ -1264,7 +1264,7 @@ pgendSyncTransaction (PGBackend *be, GUID *trans_guid) * The problem that this routine is trying to solve is the need to * to run a query *and* maintain consistent balance checkpoints * within the engine data. As a by-product, it can pull in a vast - * amount of sql data into the engine. The steps of teh algorithm + * amount of sql data into the engine. The steps of the algorithm * are: * * 1) convert the engine style query to an SQL query string. @@ -1954,11 +1954,18 @@ pgend_trans_commit_edit (Backend * bend, if (rollback) { bufp = "ROLLBACK;"; - SEND_QUERY (be,bufp,444); + SEND_QUERY (be,bufp,444); /* hack alert hard coded literal */ FINISH_QUERY(be->connection); PINFO ("old tranasction didn't match DB, edit rolled back)\n"); - return 666; /* hack alert */ + + /* What happens here: We return to the engine with an + * error code. This causes the engine to call + * xaccTransRollback(), with then invokes our backend rollback + * routine. Our rollback routine updates from the latest in + * the sql database, and voila! we are good to go. + */ + return 666; /* hack alert- hard coded literal */ } } @@ -2005,6 +2012,32 @@ pgend_trans_commit_edit (Backend * bend, return 0; } +/* ============================================================= */ +/* transaction rollback routine. This routine can be invoked + * in one of two ways: if the user canceled an edited transaction + * by hand, from the gui, or automatically, due to a multi-user + * edit conflict. In this latter case, the commit_edit routine + * above failed, and returned to the engine. Then the engine + * xaccTransRollback routine got invoked, which called us. + * What we do here is to copy the transaction out of the dataabse + * and into the engine. This will bring the local engine up + * to sync from the changes that other users had made. + */ + +static int +pgend_trans_rollback_edit (Backend * bend, + Transaction * trans) +{ + PGBackend *be = (PGBackend *)bend; + GUID * trans_guid; + + if (!be || !trans) return 0; + + trans_guid = xaccTransGetGUID (trans); + pgendCopyTransactionToEngine (be, trans_guid); + return 0; +} + /* ============================================================= */ static int @@ -2923,7 +2956,7 @@ pgend_session_begin (GNCBook *sess, const char * sessionid, * postgres. (Porblem: we don't really know why there was a fatal * error, there may be many reasons. This is the fundamental * problem with this approach.) If the connect failed, then we - * create teh database, and try again. + * create the database, and try again. */ be->connection = PQsetdbLogin (be->hostname, be->portno, @@ -3082,7 +3115,7 @@ pgend_session_begin (GNCBook *sess, const char * sessionid, be->be.account_commit_edit = pgend_account_commit_edit; be->be.trans_begin_edit = NULL; be->be.trans_commit_edit = pgend_trans_commit_edit; - be->be.trans_rollback_edit = NULL; + be->be.trans_rollback_edit = NULL; /* no-op for single user */ be->be.price_begin_edit = pgend_price_begin_edit; be->be.price_commit_edit = pgend_price_commit_edit; be->be.run_query = NULL; @@ -3102,7 +3135,7 @@ pgend_session_begin (GNCBook *sess, const char * sessionid, be->be.account_commit_edit = pgend_account_commit_edit; be->be.trans_begin_edit = NULL; be->be.trans_commit_edit = pgend_trans_commit_edit; - be->be.trans_rollback_edit = NULL; + be->be.trans_rollback_edit = pgend_trans_rollback_edit; be->be.price_begin_edit = pgend_price_begin_edit; be->be.price_commit_edit = pgend_price_commit_edit; be->be.run_query = pgendRunQuery; diff --git a/src/engine/sql/README b/src/engine/sql/README index 37ac2ee236..9706975859 100644 --- a/src/engine/sql/README +++ b/src/engine/sql/README @@ -226,6 +226,12 @@ access). In some cases, we have PERR without setting a backend error... grep for all PERR's that don't set backend error. +-- note that transaction commit errors may in fact be i/o errors. + If an i/o error occured during commit, there would be some + abberant rollback behaviour. Ouch. + +-- the transaction rollback code needs to be a gui popup... + -- fix the annoying postgres:,,localhost,asdf file syntax: needs mods to gnc-book to keep it happy about lock files & such. (coord with rlb on gnc-book redesign) @@ -266,11 +272,11 @@ This list only affects the multi-user and advanced/optional features. Most of the items on this list are 'critical' in the sense that multi-user mode is fundamentally broken unless they are fixed. --- before going beta: turn down debugging. Set min-checkpoint-count - to 30 not 3. +-- before going beta: turn down debugging. --- possible bug ??: if always in multi-mode, then initial checkpoints - not set up ?? should crete checkpoints during account creation... +-- if always in multi-mode, then initial checkpoints not set up. + They're not needed until there are a lot of transactions in the + system. Need to recompute checkpoints on some periodic basis. -- bug: if another user deletes a transaction, or an account, we need to look at the audit trail to see if the thing has been deleted. @@ -291,16 +297,6 @@ multi-user mode is fundamentally broken unless they are fixed. account, we need to do something to merge their work into ours...) ditto for prices ... --- transaction rollback is 'incorrect'; sort of ?? since we should - roll back to what's in the db, and not the old stored transaction ... - (Currently, the register uses xaccTransRollback() to implement - a single level of undo; it performs the 'undo' from what it has - cached, rather than from the contents in the DB. This is OK, - as long as some other user hasn't modified the DB in the meanwhile.) - This may not be a problem, as practically speaking, its highly - unlikely that one user is modifying data while the other is undoing - the same transaction. - -- fix caching in the face of lost contact to the backend. If the backend can't contact its server, then we should just save up caches, and then when contact with backend re-established, we should spit