changes to defer date sorting until the commit phase. Also, changes to make

re-ordering due to a date change a tad more efficient.


git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@1247 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
Linas Vepstas 1998-09-30 15:15:46 +00:00
parent 565e304965
commit 49ab81302d
2 changed files with 100 additions and 70 deletions

View File

@ -222,6 +222,7 @@ xaccAccountInsertSplit ( Account *acc, Split *split )
{ {
int i,j; int i,j;
Split **oldsplits; Split **oldsplits;
Account *oldacc;
if (!acc) return; if (!acc) return;
if (!split) return; if (!split) return;
@ -254,39 +255,73 @@ disable for now till we figure out what the right thing is.
* there first. We don't want to ever leave the system * there first. We don't want to ever leave the system
* in an inconsistent state. * in an inconsistent state.
*/ */
oldacc = split->acc;
if (split->acc) xaccAccountRemoveSplit (split->acc, split); if (split->acc) xaccAccountRemoveSplit (split->acc, split);
split->acc = acc; split->acc = acc;
oldsplits = acc->splits; /* enlarge the size of the split array to accomadate the new split,
acc->numSplits ++; * and copy all the splits over to the new array.
acc->splits = (Split **)_malloc(((acc->numSplits) + 1) * sizeof(Split *)); * If the old and new accounts are the same account, then we
* are just shuffling around the split, resumably due to a
* date reordering. In this case, most of the malloc/copy/free bit
* can be avoided.
*/
if (oldacc != acc) {
oldsplits = acc->splits;
acc->numSplits ++;
/* Find the insertion point */ acc->splits = (Split **)_malloc(((acc->numSplits) + 1) * sizeof(Split *));
/* to get realy fancy, could use binary search. */
for(i = 0; i < (acc->numSplits - 1);) { /* Find the insertion point */
if(xaccSplitOrder(&(oldsplits[i]), &split) > 0) { /* to get realy fancy, could use binary search. */
break; for(i = 0; i < (acc->numSplits - 1);) {
} else { if(xaccSplitOrder(&(oldsplits[i]), &split) > 0) {
acc->splits[i] = oldsplits[i]; break;
} } else {
i++; /* Don't put this in the loop guard! It'll go too far. */ acc->splits[i] = oldsplits[i];
}
i++; /* Don't put this in the loop guard! It'll go too far. */
}
/* Insertion point is now i */
//fprintf(stderr, "Insertion position is: %d\n", i);
/* Move all the other splits down (this could be done faster with memmove)*/
for( j = acc->numSplits; j > i; j--) {
acc->splits[j] = oldsplits[j - 1];
}
/* Now insert the new split */
acc->splits[i] = split;
/* make sure the array is NULL terminated */
acc->splits[acc->numSplits] = NULL;
_free(oldsplits);
} else {
acc->numSplits ++;
/* Find the insertion point */
/* to get realy fancy, could use binary search. */
for(i = 0; i < (acc->numSplits - 1);) {
if(xaccSplitOrder(&(acc->splits[i]), &split) > 0) {
break;
}
i++; /* Don't put this in the loop guard! It'll go too far. */
}
/* Insertion point is now i */
/* Move all the other splits down (this could be done faster with memmove)*/
for( j = acc->numSplits; j > i; j--) {
acc->splits[j] = acc->splits[j - 1];
}
/* Now insert the new split */
acc->splits[i] = split;
/* make sure the array is NULL terminated */
acc->splits[acc->numSplits] = NULL;
} }
/* Insertion point is now i */
//fprintf(stderr, "Insertion position is: %d\n", i);
/* Move all the other splits down (this could be done faster with memmove)*/
for( j = acc->numSplits; j > i; j--) {
acc->splits[j] = oldsplits[j - 1];
}
/* Now insert the new split */
acc->splits[i] = split;
/* make sure the array is NULL terminated */
acc->splits[acc->numSplits] = NULL;
_free(oldsplits);
xaccAccountRecomputeBalance (acc); xaccAccountRecomputeBalance (acc);
} }
@ -485,7 +520,6 @@ xaccCheckDateOrder (Account * acc, Split *split )
/* take care of re-ordering, if necessary */ /* take care of re-ordering, if necessary */
if( outOfOrder ) { if( outOfOrder ) {
xaccAccountRemoveSplit( acc, split );
xaccAccountInsertSplit( acc, split ); xaccAccountInsertSplit( acc, split );
return 1; return 1;
} }

View File

@ -414,6 +414,11 @@ xaccFreeTransaction( Transaction *trans )
trans->open = 0; trans->open = 0;
if (trans->orig) {
xaccFreeTransaction (trans->orig);
trans->orig = NULL;
}
_free(trans); _free(trans);
} }
@ -767,12 +772,6 @@ xaccTransCommitEdit (Transaction *trans)
if (!trans) return; if (!trans) return;
CHECK_OPEN (trans); CHECK_OPEN (trans);
/* get rid of the copy we made. We won't be rolling back,
* so we don't need i any more.
*/
xaccFreeTransaction (trans->orig);
trans->orig = NULL;
/* 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.
* As a result of editing, we could end up with a transaction that * As a result of editing, we could end up with a transaction that
* has no splits in it, in which case we delete the transaction and * has no splits in it, in which case we delete the transaction and
@ -807,17 +806,26 @@ xaccTransCommitEdit (Transaction *trans)
trans->open &= ~DEFER_REBALANCE; trans->open &= ~DEFER_REBALANCE;
xaccTransRebalance (trans); xaccTransRebalance (trans);
/* um, theoritically, it is impossible for splits /* check to see if the date has changed. We use the date as the sort key. */
* to get inserted out of order. But we'll get paranoid, if ((trans->orig->date_entered.tv_sec != trans->date_entered.tv_sec) ||
* and check anyway, at the loss of some performance. (trans->orig->date_posted.tv_sec != trans->date_posted.tv_sec))
*/ {
i=0;
split = trans->splits[i]; /* since the date has changed, we need to be careful to
while (split) { * make sure all associated splits are in proper order
acc = split ->acc; * in thier accounts. The easiest way of ensuring this
xaccCheckDateOrder(acc, trans->splits[i]); * is to remove and reinsert every split. The reinsertion
i++; * process will place the split in the correct date-sorted
* order.
*/
i=0;
split = trans->splits[i]; split = trans->splits[i];
while (split) {
acc = split ->acc;
xaccCheckDateOrder(acc, trans->splits[i]);
i++;
split = trans->splits[i];
}
} }
i=0; i=0;
@ -831,6 +839,12 @@ xaccTransCommitEdit (Transaction *trans)
trans->open = 0; trans->open = 0;
xaccTransWriteLog (trans, 'C'); xaccTransWriteLog (trans, 'C');
/* get rid of the copy we made. We won't be rolling back,
* so we don't need it any more. */
xaccFreeTransaction (trans->orig);
trans->orig = NULL;
} }
void void
@ -1203,40 +1217,22 @@ xaccCountTransactions (Transaction **tarray)
void void
xaccTransSetDateSecs (Transaction *trans, time_t secs) xaccTransSetDateSecs (Transaction *trans, time_t secs)
{ {
Split *split;
Account *acc;
int i=0;
if (!trans) return; if (!trans) return;
CHECK_OPEN (trans); CHECK_OPEN (trans);
/* hack alert -- for right now, keep the posted and the entered /* hack alert -- for right now, keep the posted and the entered
* dates in sync. Later, we'll have to split these up. */ * dates in sync. Later, we'll have to split these up. */
trans->date_entered.tv_sec = secs; trans->date_entered.tv_sec = secs;
trans->date_posted.tv_sec = secs; trans->date_posted.tv_sec = secs;
/* since the date has changed, we need to be careful to /* Because the date has changed, we need to make sure that each of the
* make sure all associated splits are in proper order * splits is properly ordered in each of thier accounts. We could do that
* in thier accounts. The easiest way of ensuring this * here, simply by reinserting each split into its account. However, in
* is to remove and reinsert every split. The reinsertion * some ways this is bad behaviour, and it seems much better/nicer to defer
* process will place the split in the correct date-sorted * that until the commit phase, i.e. until the user has called the
* order. * xaccTransCommitEdit() routine. So, for now, we are done.
*/ */
assert (trans->splits);
i=0;
split = trans->splits[i];
while (split) {
acc = split->acc;
xaccAccountRemoveSplit (acc, split);
xaccAccountInsertSplit (acc, split);
i++;
split = trans->splits[i];
}
} }
void void