mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
fix multi-user transaction rollback
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@4556 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user