Fix memory leaks and rollback semantics for kvp_frames.

git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@3195 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
Dave Peticolas 2000-11-27 21:59:49 +00:00
parent 10dc08e3db
commit 41b8f66407
2 changed files with 79 additions and 40 deletions

View File

@ -133,24 +133,26 @@ xaccMallocSplit(void)
static Split *
xaccCloneSplit (Split *s)
{
Split *split = g_new(Split, 1);
split->acc = s->acc;
split->parent = s->parent;
split->action = g_cache_insert(gnc_string_cache, s->action);
split->memo = g_cache_insert(gnc_string_cache, s->memo);
split->reconciled = s->reconciled;
split->damount = s->damount;
split->value = s->value;
split->date_reconciled.tv_sec = s->date_reconciled.tv_sec;
split->date_reconciled.tv_nsec = s->date_reconciled.tv_nsec;
Split *split = g_new0 (Split, 1);
/* copy(!) the guid. The cloned split is *not* unique,
* is a sick twisted clone that holds 'undo' information. */
split->guid = s->guid;
split->acc = s->acc;
split->parent = s->parent;
split->memo = g_cache_insert (gnc_string_cache, s->memo);
split->action = g_cache_insert (gnc_string_cache, s->action);
split->kvp_data = kvp_frame_copy (s->kvp_data);
split->reconciled = s->reconciled;
split->date_reconciled = s->date_reconciled;
split->value = s->value;
split->damount = s->damount;
/* no need to futz with the balances; these get wiped each time ...
* split->balance = s->balance;
* split->cleared_balance = s->cleared_balance;
@ -160,7 +162,7 @@ xaccCloneSplit (Split *s)
* split->share_reconciled_balance = s->share_reconciled_balance;
*/
return (split);
return split;
}
/********************************************************************\
@ -171,12 +173,15 @@ xaccFreeSplit (Split *split)
{
if (!split) return;
kvp_frame_delete (split->kvp_data);
g_cache_remove(gnc_string_cache, split->memo);
g_cache_remove(gnc_string_cache, split->action);
/* just in case someone looks up freed memory ... */
split->memo = NULL;
split->action = NULL;
split->kvp_data = NULL;
split->reconciled = NREC;
split->damount = gnc_numeric_zero();
split->value = gnc_numeric_zero();
@ -205,7 +210,7 @@ xaccSplitEqual(const Split *sa, const Split *sb,
if(!guid_equal(&(sa->guid), &(sb->guid))) return FALSE;
}
/* Since these strings are cached we can just use pointer equality */
/* Since these strings are cached we can just use pointer equality */
if(sa->memo != sb->memo) return FALSE;
if(sa->action != sb->action) return FALSE;
@ -599,10 +604,12 @@ xaccCloneTransaction (Transaction *t)
Transaction *trans;
GList *node;
trans = g_new(Transaction, 1);
trans = g_new0 (Transaction, 1);
trans->num = g_cache_insert(gnc_string_cache, t->num);
trans->description = g_cache_insert(gnc_string_cache, t->description);
trans->num = g_cache_insert (gnc_string_cache, t->num);
trans->description = g_cache_insert (gnc_string_cache, t->description);
trans->kvp_data = kvp_frame_copy (t->kvp_data);
trans->splits = g_list_copy (t->splits);
for (node = trans->splits; node; node = node->next)
@ -621,7 +628,7 @@ xaccCloneTransaction (Transaction *t)
* is a sick twisted clone that holds 'undo' information. */
trans->guid = t->guid;
return (trans);
return trans;
}
@ -647,10 +654,14 @@ xaccFreeTransaction (Transaction *trans)
g_cache_remove(gnc_string_cache, trans->num);
g_cache_remove(gnc_string_cache, trans->description);
kvp_frame_delete (trans->kvp_data);
/* just in case someone looks up freed memory ... */
trans->num = NULL;
trans->description = NULL;
trans->kvp_data = NULL;
trans->date_entered.tv_sec = 0;
trans->date_entered.tv_nsec = 0;
@ -659,7 +670,8 @@ xaccFreeTransaction (Transaction *trans)
trans->open = 0;
if (trans->orig) {
if (trans->orig)
{
xaccFreeTransaction (trans->orig);
trans->orig = NULL;
}
@ -1396,6 +1408,12 @@ xaccTransRollbackEdit (Transaction *trans)
trans->description = orig->description;
orig->description = g_cache_insert(gnc_string_cache, "");
kvp_frame_delete (trans->kvp_data);
trans->kvp_data = orig->kvp_data;
if (!trans->kvp_data)
trans->kvp_data = kvp_frame_new ();
orig->kvp_data = kvp_frame_new ();
trans->date_entered.tv_sec = orig->date_entered.tv_sec;
trans->date_entered.tv_nsec = orig->date_entered.tv_nsec;
@ -1410,11 +1428,13 @@ xaccTransRollbackEdit (Transaction *trans)
* CheckDateOrder routine could be cpu-cyle brutal, so it maybe
* it could use some tuning.
*/
if (trans->open & BEING_DESTROYED) {
if (trans->open & BEING_DESTROYED)
{
force_it = 1;
mismatch = 0;
}
else {
else
{
GList *node;
GList *node_orig;
Split *s, *so;
@ -1423,11 +1443,17 @@ xaccTransRollbackEdit (Transaction *trans)
for (i = 0, node = trans->splits, node_orig = orig->splits ;
node && node_orig ;
i++, node = node->next, node_orig = node_orig->next) {
i++, node = node->next, node_orig = node_orig->next)
{
s = node->data;
so = node_orig->data;
if (so->acc != s->acc) { force_it = 1; mismatch=i; break; }
if (so->acc != s->acc)
{
force_it = 1;
mismatch = i;
break;
}
g_cache_remove (gnc_string_cache, s->action);
s->action = so->action;
@ -1437,6 +1463,12 @@ xaccTransRollbackEdit (Transaction *trans)
s->memo = so->memo;
so->memo = g_cache_insert(gnc_string_cache, "");
kvp_frame_delete (s->kvp_data);
s->kvp_data = so->kvp_data;
if (!s->kvp_data)
s->kvp_data = kvp_frame_new ();
so->kvp_data = kvp_frame_new ();
s->reconciled = so->reconciled;
s->damount = so->damount;
s->value = so->value;
@ -1451,19 +1483,25 @@ xaccTransRollbackEdit (Transaction *trans)
xaccAccountRecomputeBalance (s->acc);
}
if (so != s) { force_it = 1; mismatch=i; }
if (so != s)
{
force_it = 1;
mismatch = i;
}
}
/* OK, if force_it got set, we'll have to tough it out and brute-force
* the rest of the way. Clobber all the edited splits, add all new splits.
* Unfortunately, this can suck up CPU cycles in the Remove/Insert routines.
*/
if (force_it) {
if (force_it)
{
GList *node;
for (i = 0, node = trans->splits ;
node && i < mismatch ;
i++, node = node->next) {
i++, node = node->next)
{
Split *s = node->data;
GList *node_orig;
@ -1473,7 +1511,8 @@ xaccTransRollbackEdit (Transaction *trans)
}
for (node = g_list_nth (trans->splits, mismatch) ;
node ; node = node->next) {
node ; node = node->next)
{
Split *s = node->data;
MARK_SPLIT (s);
@ -1489,7 +1528,8 @@ xaccTransRollbackEdit (Transaction *trans)
orig->splits = NULL;
for (node = g_list_nth (trans->splits, mismatch) ;
node ; node = node->next) {
node ; node = node->next)
{
Split *s = node->data;
MARK_SPLIT (s);
@ -1529,7 +1569,8 @@ xaccTransDestroy (Transaction *trans)
trans->open |= BEING_DESTROYED;
xaccTransWriteLog (trans, 'D');
for (node = trans->splits; node; node = node->next) {
for (node = trans->splits; node; node = node->next)
{
Split *split = node->data;
MARK_SPLIT (split);
@ -1573,7 +1614,6 @@ xaccSplitDestroy (Split *split)
{
Transaction *trans;
gboolean ismember = FALSE;
GList *node;
if (!split) return;
@ -1584,15 +1624,7 @@ xaccSplitDestroy (Split *split)
xaccRemoveEntity(&split->guid);
for (node = trans->splits; node; node = node->next)
{
Split *s = node->data;
MARK_SPLIT(s); /* why??? */
if (s == split)
ismember = TRUE;
}
ismember = (g_list_find (trans->splits, split) != NULL);
assert (ismember);

View File

@ -94,6 +94,9 @@ kvp_frame_delete_worker(gpointer key, gpointer value, gpointer user_data) {
void
kvp_frame_delete(kvp_frame * frame) {
if (!frame)
return;
if(frame->hash) {
/* free any allocated resource for frame or its children */
g_hash_table_foreach(frame->hash, & kvp_frame_delete_worker,
@ -119,6 +122,10 @@ kvp_frame_copy_worker(gpointer key, gpointer value, gpointer user_data) {
kvp_frame *
kvp_frame_copy(const kvp_frame * frame) {
kvp_frame * retval = kvp_frame_new();
if (!frame)
return retval;
if(frame->hash) {
if(!init_frame_body_if_needed(retval)) return(NULL);
g_hash_table_foreach(frame->hash,