allow begin-end edit's to be nested;

check more strictly that transaction is open for editing.
(if you see any 'transaction %p not open for editing', let me know --linas)


git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@3633 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
Linas Vepstas 2001-02-11 04:46:39 +00:00
parent edc699a651
commit c8a5ead533
3 changed files with 80 additions and 54 deletions

View File

@ -248,7 +248,7 @@ xaccAccountBeginEdit (Account *acc)
if (0 >= acc->editlevel) if (0 >= acc->editlevel)
{ {
PERR ("unbalanced call - resetting (was %d)", acc->editlevel); PERR ("unbalanced call - resetting (was %d)", acc->editlevel);
acc->editlevel = 0; acc->editlevel = 1;
} }
acc->core_dirty = FALSE; acc->core_dirty = FALSE;

View File

@ -72,6 +72,18 @@ int force_double_entry = 0;
static short module = MOD_ENGINE; static short module = MOD_ENGINE;
G_INLINE_FUNC void check_open (Transaction *trans);
G_INLINE_FUNC void
check_open (Transaction *trans)
{
if (trans && 0 >= trans->editlevel)
{
PERR ("transaction %p not open for editing\n", trans);
// assert (trans->editlevel);
PERR ("\t%s:%d \n", __FILE__, __LINE__);
}
}
/********************************************************************\ /********************************************************************\
* xaccInitSplit * xaccInitSplit
* Initialize a Split structure * Initialize a Split structure
@ -254,6 +266,7 @@ void
xaccSplitSetGUID (Split *split, GUID *guid) xaccSplitSetGUID (Split *split, GUID *guid)
{ {
if (!split || !guid) return; if (!split || !guid) return;
check_open (split->parent);
xaccRemoveEntity(&split->guid); xaccRemoveEntity(&split->guid);
split->guid = *guid; split->guid = *guid;
xaccStoreEntity(split, &split->guid, GNC_ID_SPLIT); xaccStoreEntity(split, &split->guid, GNC_ID_SPLIT);
@ -373,6 +386,7 @@ xaccSplitSetSharePriceAndAmount (Split *s, gnc_numeric price,
gnc_numeric amt) gnc_numeric amt)
{ {
if (!s) return; if (!s) return;
check_open (s->parent);
s->damount = gnc_numeric_convert(amt, get_security_denom(s), GNC_RND_ROUND);; s->damount = gnc_numeric_convert(amt, get_security_denom(s), GNC_RND_ROUND);;
s->value = gnc_numeric_mul(s->damount, price, s->value = gnc_numeric_mul(s->damount, price,
@ -382,14 +396,17 @@ xaccSplitSetSharePriceAndAmount (Split *s, gnc_numeric price,
} }
void void
DxaccSplitSetSharePrice (Split *s, double amt) { DxaccSplitSetSharePrice (Split *s, double amt)
{
xaccSplitSetSharePrice xaccSplitSetSharePrice
(s, double_to_gnc_numeric(amt, PRICE_DENOM, GNC_RND_ROUND)); (s, double_to_gnc_numeric(amt, PRICE_DENOM, GNC_RND_ROUND));
} }
void void
xaccSplitSetSharePrice (Split *s, gnc_numeric price) { xaccSplitSetSharePrice (Split *s, gnc_numeric price)
{
if (!s) return; if (!s) return;
check_open (s->parent);
s->value = gnc_numeric_mul(s->damount, price, get_currency_denom(s), s->value = gnc_numeric_mul(s->damount, price, get_currency_denom(s),
GNC_RND_ROUND); GNC_RND_ROUND);
@ -398,11 +415,13 @@ xaccSplitSetSharePrice (Split *s, gnc_numeric price) {
} }
void void
DxaccSplitSetShareAmount (Split *s, double damt) { DxaccSplitSetShareAmount (Split *s, double damt)
{
gnc_numeric old_price; gnc_numeric old_price;
gnc_numeric amt = double_to_gnc_numeric(damt, get_security_denom(s), gnc_numeric amt = double_to_gnc_numeric(damt, get_security_denom(s),
GNC_RND_ROUND); GNC_RND_ROUND);
if (!s) return; if (!s) return;
check_open (s->parent);
if(!gnc_numeric_zero_p(s->damount)) { if(!gnc_numeric_zero_p(s->damount)) {
old_price = gnc_numeric_div(s->value, s->damount, GNC_DENOM_AUTO, old_price = gnc_numeric_div(s->value, s->damount, GNC_DENOM_AUTO,
@ -421,8 +440,10 @@ DxaccSplitSetShareAmount (Split *s, double damt) {
} }
void void
xaccSplitSetShareAmount (Split *s, gnc_numeric amt) { xaccSplitSetShareAmount (Split *s, gnc_numeric amt)
{
if(!s) return; if(!s) return;
check_open (s->parent);
s->damount = gnc_numeric_convert(amt, get_security_denom(s), GNC_RND_ROUND); s->damount = gnc_numeric_convert(amt, get_security_denom(s), GNC_RND_ROUND);
@ -430,12 +451,14 @@ xaccSplitSetShareAmount (Split *s, gnc_numeric amt) {
} }
void void
DxaccSplitSetValue (Split *s, double damt) { DxaccSplitSetValue (Split *s, double damt)
{
gnc_numeric amt = double_to_gnc_numeric(damt, gnc_numeric amt = double_to_gnc_numeric(damt,
get_currency_denom(s), get_currency_denom(s),
GNC_RND_ROUND); GNC_RND_ROUND);
gnc_numeric old_price; gnc_numeric old_price;
if (!s) return; if (!s) return;
check_open (s->parent);
if(!gnc_numeric_zero_p(s->damount)) { if(!gnc_numeric_zero_p(s->damount)) {
old_price = gnc_numeric_div(s->value, s->damount, GNC_DENOM_AUTO, old_price = gnc_numeric_div(s->value, s->damount, GNC_DENOM_AUTO,
@ -457,8 +480,10 @@ DxaccSplitSetValue (Split *s, double damt) {
} }
void void
xaccSplitSetValue (Split *s, gnc_numeric amt) { xaccSplitSetValue (Split *s, gnc_numeric amt)
{
if(!s) return; if(!s) return;
check_open (s->parent);
s->value = gnc_numeric_convert(amt, get_currency_denom(s), GNC_RND_ROUND); s->value = gnc_numeric_convert(amt, get_currency_denom(s), GNC_RND_ROUND);
@ -558,7 +583,8 @@ xaccInitTransaction (Transaction * trans)
trans->date_posted.tv_nsec = 0; trans->date_posted.tv_nsec = 0;
trans->marker = 0; trans->marker = 0;
trans->open = 0; trans->editlevel = 0;
trans->do_free = FALSE;
trans->orig = NULL; trans->orig = NULL;
trans->kvp_data = kvp_frame_new(); trans->kvp_data = kvp_frame_new();
@ -613,7 +639,8 @@ xaccCloneTransaction (Transaction *t)
trans->date_posted.tv_sec = t->date_posted.tv_sec; trans->date_posted.tv_sec = t->date_posted.tv_sec;
trans->date_posted.tv_nsec = t->date_posted.tv_nsec; trans->date_posted.tv_nsec = t->date_posted.tv_nsec;
trans->open = 0; trans->editlevel = 0;
trans->do_free = FALSE;
trans->orig = NULL; trans->orig = NULL;
/* copy(!) the guid. The cloned transaction is *not* unique, /* copy(!) the guid. The cloned transaction is *not* unique,
@ -660,7 +687,8 @@ xaccFreeTransaction (Transaction *trans)
trans->date_posted.tv_sec = 0; trans->date_posted.tv_sec = 0;
trans->date_posted.tv_nsec = 0; trans->date_posted.tv_nsec = 0;
trans->open = 0; trans->editlevel = 0;
trans->do_free = FALSE;
if (trans->orig) if (trans->orig)
{ {
@ -793,6 +821,7 @@ xaccSplitSetBaseValue (Split *s, gnc_numeric value,
const gnc_commodity *security; const gnc_commodity *security;
if (!s) return; if (!s) return;
check_open (s->parent);
/* Novice/casual users may not want or use the double entry /* Novice/casual users may not want or use the double entry
* features of this engine. So, in particular, there may be the * features of this engine. So, in particular, there may be the
@ -1205,29 +1234,20 @@ xaccTransSetCurrency (Transaction *trans, const gnc_commodity *curr)
/********************************************************************\ /********************************************************************\
\********************************************************************/ \********************************************************************/
G_INLINE_FUNC void check_open (Transaction *trans);
G_INLINE_FUNC void
check_open (Transaction *trans)
{
if (!trans->open)
{
PERR ("transaction %p not open for editing\n", trans);
/* assert (trans->open); */
PERR ("\t%s:%d \n", __FILE__, __LINE__);
}
}
void void
xaccTransBeginEdit (Transaction *trans) xaccTransBeginEdit (Transaction *trans)
{ {
char open;
Backend *be; Backend *be;
if (!trans) return; if (!trans) return;
open = trans->open;
trans->open = BEGIN_EDIT;
if (open & BEGIN_EDIT) return; trans->editlevel ++;
if (1 < trans->editlevel) return;
if (0 >= trans->editlevel)
{
PERR ("unbalanced call - resetting (was %d)", trans->editlevel);
trans->editlevel = 1;
}
/* See if there's a backend. If there is, invoke it. */ /* See if there's a backend. If there is, invoke it. */
be = xaccTransactionGetBackend (trans); be = xaccTransactionGetBackend (trans);
@ -1252,7 +1272,15 @@ xaccTransCommitEdit (Transaction *trans)
if (!trans) return; if (!trans) return;
ENTER ("trans addr=%p", trans); ENTER ("trans addr=%p", trans);
check_open (trans);
trans->editlevel--;
if (0 < trans->editlevel) return;
if (0 > trans->editlevel)
{
PERR ("unbalanced call - resetting (was %d)", trans->editlevel);
trans->editlevel = 0;
}
/* At this point, we check to see if we have a valid transaction. /* At this point, we check to see if we have a valid transaction.
* There are two possiblities: * There are two possiblities:
@ -1261,7 +1289,7 @@ xaccTransCommitEdit (Transaction *trans)
* We handle 1) immediately, and we call the backend before * We handle 1) immediately, and we call the backend before
* we go through with 2). * we go through with 2).
*/ */
if (trans->splits && !(trans->open & BEING_DESTROYED)) if (trans->splits && !(trans->do_free))
{ {
split = trans->splits->data; split = trans->splits->data;
@ -1325,7 +1353,7 @@ xaccTransCommitEdit (Transaction *trans)
} }
/* ------------------------------------------------- */ /* ------------------------------------------------- */
if (!trans->splits || (trans->open & BEING_DESTROYED)) if (!trans->splits || trans->do_free)
{ {
PINFO ("delete trans at addr=%p", trans); PINFO ("delete trans at addr=%p", trans);
/* Make a log in the journal before destruction. */ /* Make a log in the journal before destruction. */
@ -1349,7 +1377,7 @@ xaccTransCommitEdit (Transaction *trans)
xaccAccountRecomputeBalance (split->acc); xaccAccountRecomputeBalance (split->acc);
} }
trans->open = 0; trans->do_free = FALSE;
xaccTransWriteLog (trans, 'C'); xaccTransWriteLog (trans, 'C');
/* Get rid of the copy we made. We won't be rolling back, /* Get rid of the copy we made. We won't be rolling back,
@ -1366,12 +1394,17 @@ xaccTransRollbackEdit (Transaction *trans)
Transaction *orig; Transaction *orig;
int force_it=0, mismatch=0; int force_it=0, mismatch=0;
int i; int i;
ENTER ("trans addr=%p\n", trans);
if (!trans) return; if (!trans) return;
trans->editlevel--;
if (0 < trans->editlevel) return;
check_open (trans); if (0 > trans->editlevel)
{
ENTER ("trans addr=%p\n", trans); PERR ("unbalanced call - resetting (was %d)", trans->editlevel);
trans->editlevel = 0;
}
/* copy the original values back in. */ /* copy the original values back in. */
orig = trans->orig; orig = trans->orig;
@ -1408,7 +1441,7 @@ xaccTransRollbackEdit (Transaction *trans)
* CheckDateOrder routine could be cpu-cyle brutal, so it maybe * CheckDateOrder routine could be cpu-cyle brutal, so it maybe
* it could use some tuning. * it could use some tuning.
*/ */
if (trans->open & BEING_DESTROYED) if (trans->do_free)
{ {
force_it = 1; force_it = 1;
mismatch = 0; mismatch = 0;
@ -1526,7 +1559,7 @@ xaccTransRollbackEdit (Transaction *trans)
xaccFreeTransaction (trans->orig); xaccFreeTransaction (trans->orig);
trans->orig = NULL; trans->orig = NULL;
trans->open = 0; trans->do_free = FALSE;
LEAVE ("trans addr=%p\n", trans); LEAVE ("trans addr=%p\n", trans);
} }
@ -1535,7 +1568,7 @@ gboolean
xaccTransIsOpen (Transaction *trans) xaccTransIsOpen (Transaction *trans)
{ {
if (!trans) return FALSE; if (!trans) return FALSE;
return (0 != (trans->open & BEGIN_EDIT)); return (0 < trans->editlevel);
} }
/********************************************************************\ /********************************************************************\
@ -1548,7 +1581,7 @@ xaccTransDestroy (Transaction *trans)
if (!trans) return; if (!trans) return;
check_open (trans); check_open (trans);
trans->open |= BEING_DESTROYED; trans->do_free = TRUE;
xaccTransWriteLog (trans, 'D'); xaccTransWriteLog (trans, 'D');
gnc_engine_generate_event (&trans->guid, GNC_EVENT_DESTROY); gnc_engine_generate_event (&trans->guid, GNC_EVENT_DESTROY);
@ -1601,10 +1634,7 @@ xaccSplitDestroy (Split *split)
if (!split) return; if (!split) return;
trans = split->parent; trans = split->parent;
if (trans) check_open (trans);
{
check_open (trans);
}
mark_split (split); mark_split (split);
xaccRemoveEntity (&split->guid); xaccRemoveEntity (&split->guid);
@ -1631,7 +1661,6 @@ xaccTransAppendSplit (Transaction *trans, Split *split)
Transaction *oldtrans; Transaction *oldtrans;
if (!trans || !split) return; if (!trans || !split) return;
check_open (trans); check_open (trans);
/* first, make sure that the split isn't already inserted /* first, make sure that the split isn't already inserted
@ -1891,7 +1920,6 @@ xaccTransSetNotes (Transaction *trans, const char *notes)
kvp_value *new_value; kvp_value *new_value;
if (!trans || !notes) return; if (!trans || !notes) return;
check_open (trans); check_open (trans);
new_value = kvp_value_new_string (notes); new_value = kvp_value_new_string (notes);
@ -2017,6 +2045,7 @@ xaccSplitSetMemo (Split *split, const char *memo)
{ {
char * tmp; char * tmp;
if (!split || !memo) return; if (!split || !memo) return;
check_open (split->parent);
tmp = g_cache_insert(gnc_string_cache, (gpointer) memo); tmp = g_cache_insert(gnc_string_cache, (gpointer) memo);
g_cache_remove(gnc_string_cache, split->memo); g_cache_remove(gnc_string_cache, split->memo);
@ -2029,6 +2058,7 @@ xaccSplitSetAction (Split *split, const char *actn)
{ {
char * tmp; char * tmp;
if (!split || !actn) return; if (!split || !actn) return;
check_open (split->parent);
tmp = g_cache_insert(gnc_string_cache, (gpointer) actn); tmp = g_cache_insert(gnc_string_cache, (gpointer) actn);
g_cache_remove(gnc_string_cache, split->action); g_cache_remove(gnc_string_cache, split->action);
@ -2040,6 +2070,7 @@ void
xaccSplitSetReconcile (Split *split, char recn) xaccSplitSetReconcile (Split *split, char recn)
{ {
if (!split) return; if (!split) return;
check_open (split->parent);
switch (recn) switch (recn)
{ {
@ -2063,6 +2094,7 @@ void
xaccSplitSetDateReconciledSecs (Split *split, time_t secs) xaccSplitSetDateReconciledSecs (Split *split, time_t secs)
{ {
if (!split) return; if (!split) return;
check_open (split->parent);
split->date_reconciled.tv_sec = secs; split->date_reconciled.tv_sec = secs;
split->date_reconciled.tv_nsec = 0; split->date_reconciled.tv_nsec = 0;
@ -2073,6 +2105,7 @@ void
xaccSplitSetDateReconciledTS (Split *split, Timespec *ts) xaccSplitSetDateReconciledTS (Split *split, Timespec *ts)
{ {
if (!split || !ts) return; if (!split || !ts) return;
check_open (split->parent);
split->date_reconciled = *ts; split->date_reconciled = *ts;
mark_split (split); mark_split (split);
@ -2194,6 +2227,7 @@ void
xaccSplitMakeStockSplit(Split *s) xaccSplitMakeStockSplit(Split *s)
{ {
kvp_frame *frame = xaccSplitGetSlots(s); kvp_frame *frame = xaccSplitGetSlots(s);
check_open (s->parent);
xaccSplitSetValue(s, gnc_numeric_zero()); xaccSplitSetValue(s, gnc_numeric_zero());
kvp_frame_set_slot(frame, kvp_frame_set_slot(frame,

View File

@ -54,13 +54,6 @@
#include "Transaction.h" /* for typedefs */ #include "Transaction.h" /* for typedefs */
#include "GNCId.h" #include "GNCId.h"
/* bit-field flags for controlling transaction commits */
typedef enum
{
BEGIN_EDIT = 1 << 0,
BEING_DESTROYED = 1 << 1,
} TransFlags;
/** STRUCTS *********************************************************/ /** STRUCTS *********************************************************/
/* /*
@ -184,9 +177,8 @@ struct _transaction
* corresponding to the current traversal. */ * corresponding to the current traversal. */
unsigned char marker; unsigned char marker;
/* the "open" flag indicates if the transaction has been gint32 editlevel; /* nestcount of begin/end edit calls */
* opened for editing. */ gboolean do_free; /* transaction in process of being destroyed */
char open;
/* the orig pointer points at a copy of the original transaction, /* the orig pointer points at a copy of the original transaction,
* before editing was started. This orig copy is used to rollback * before editing was started. This orig copy is used to rollback