AUDIT: r17087 - gnucash/trunk/src/engine - Add a risk-reduction measure to xaccAccountStagedTransactionTraversal() in case
Charles Day
cedayiv at cvs.gnucash.org
Wed Apr 16 14:00:54 EDT 2008
Author: cedayiv
Date: 2008-04-16 14:00:53 -0400 (Wed, 16 Apr 2008)
New Revision: 17087
Trac: http://svn.gnucash.org/trac/changeset/17087
Modified:
gnucash/trunk/src/engine/Account.c
gnucash/trunk/src/engine/Account.h
Log:
Add a risk-reduction measure to xaccAccountStagedTransactionTraversal() in case
of a naughty thunk. Add warnings to doxygen documentation for all Account.h
functions with TransactionCallback parameters.
BP
Modified: gnucash/trunk/src/engine/Account.c
===================================================================
--- gnucash/trunk/src/engine/Account.c 2008-04-14 17:09:04 UTC (rev 17086)
+++ gnucash/trunk/src/engine/Account.c 2008-04-16 18:00:53 UTC (rev 17087)
@@ -4378,6 +4378,7 @@
{
AccountPrivate *priv;
GList *split_p;
+ GList *next;
Transaction *trans;
Split *s;
int retval;
@@ -4385,7 +4386,13 @@
if (!acc) return 0;
priv = GET_PRIVATE(acc);
- for(split_p = priv->splits; split_p; split_p = g_list_next(split_p)) {
+ for(split_p = priv->splits; split_p; split_p = next) {
+ /* Get the next element in the split list now, just in case some
+ * naughty thunk destroys the one we're using. This reduces, but
+ * does not eliminate, the possibility of undefined results if
+ * a thunk removes splits from this account. */
+ next = g_list_next(split_p);
+
s = split_p->data;
trans = s->parent;
if (trans && (trans->marker < stage)) {
Modified: gnucash/trunk/src/engine/Account.h
===================================================================
--- gnucash/trunk/src/engine/Account.h 2008-04-14 17:09:04 UTC (rev 17086)
+++ gnucash/trunk/src/engine/Account.h 2008-04-16 18:00:53 UTC (rev 17087)
@@ -978,29 +978,33 @@
void xaccAccountMoveAllSplits (Account *accfrom, Account *accto);
/** The xaccAccountForEachTransaction() routine will traverse all of
- the transactions in the given 'account' and call the callback
- function 'proc' on each transaction. Processing will continue
- if-and-only-if 'proc' returns 0. The user data pointer
- 'data' will be passed on to the callback function 'proc'.
-
- This function does not descend recursively to traverse transactions
- in child accounts.
-
- 'proc' will be called exactly once for each transaction that is
- pointed to by at least one split in the given account.
-
- The result of this function will be 0 if-and-only-if
- every relevant transaction was traversed exactly once.
- Else the return value is the last non-zero value returned by proc.
-
- Note that the traversal occurs only over the transactions that
- are locally cached in the local gnucash engine. If the gnucash
- engine is attached to a remote database, the database may contain
- (many) transactions that are not mirrored in the local cache.
- This routine will not cause an SQL database query to be performed;
- it will not traverse transactions present only in the remote
- database.
-*/
+ * the transactions in @a account and call the callback
+ * function @a proc on each transaction. Processing will continue
+ * if-and-only-if @a proc returns 0. The user data pointer
+ * @a data will be passed on to the callback function @a proc.
+ *
+ * This function does not descend recursively to traverse transactions
+ * in child accounts.
+ *
+ * @a proc will be called exactly once for each transaction that is
+ * pointed to by at least one split in the given account.
+ *
+ * The result of this function will be 0 <em>if and only if</em>
+ * every relevant transaction was traversed exactly once.
+ * Else the return value is the last non-zero value returned by proc.
+ *
+ * \warning For performance reasons, the transaction callback @a proc
+ * must never destroy any of the transaction's splits, nor assign any
+ * of them to a different account. <b>To do so risks a crash.</b>
+ *
+ * \warning The traversal occurs only over the transactions that
+ * are locally cached in the local gnucash engine. If the gnucash
+ * engine is attached to a remote database, the database may contain
+ * (many) transactions that are not mirrored in the local cache.
+ * This routine will not cause an SQL database query to be performed;
+ * it will not traverse transactions present only in the remote
+ * database.
+ */
gint xaccAccountForEachTransaction(const Account *account,
TransactionCallback proc,
void *data);
@@ -1278,16 +1282,17 @@
*/
gboolean xaccSplitTransactionTraverse(Split *split, int stage);
-/** xaccAccountStagedTransactionTraversal() calls thunk on each
- * transaction in the account whose current marker is less than the
- * given `stage' and updates each transaction's marker to be `stage'.
- * The traversal will stop if thunk() returns a non-zero value.
+/** xaccAccountStagedTransactionTraversal() calls @a thunk on each
+ * transaction in account @a a whose current marker is less than the
+ * given @a stage and updates each transaction's marker to be @a stage.
+ * The traversal will stop if @a thunk returns a non-zero value.
* xaccAccountStagedTransactionTraversal() function will return zero
- * or the non-zero value returned by thunk().
+ * or the non-zero value returned by @a thunk.
* This API does not handle handle recursive traversals.
*
- * Currently the result of adding or removing transactions during
- * a traversal is undefined, so don't do that.
+ * \warning For performance reasons, the transaction callback @a thunk
+ * must never destroy any of the transaction's splits, nor assign any
+ * of them to a different account. <b>To do so risks a crash.</b>
*/
int xaccAccountStagedTransactionTraversal(const Account *a,
@@ -1295,16 +1300,17 @@
TransactionCallback thunk,
void *data);
-/** gnc_account_tree_staged_transaction_traversal() calls thunk on each
+/** gnc_account_tree_staged_transaction_traversal() calls @a thunk on each
* transaction in the group whose current marker is less than the
- * given `stage' and updates each transaction's marker to be `stage'.
- * The traversal will stop if thunk() returns a non-zero value.
- * gnc_account_tree_staged_transaction_traversal() function will return zero
- * or the non-zero value returned by thunk(). This
+ * given @a stage and updates each transaction's marker to be @a stage.
+ * The traversal will stop if @a thunk returns a non-zero value.
+ * gnc_account_tree_staged_transaction_traversal() function will return zero
+ * or the non-zero value returned by @a thunk. This
* API does not handle handle recursive traversals.
*
- * Currently the result of adding or removing transactions during
- * a traversal is undefined, so don't do that.
+ * \warning For performance reasons, the transaction callback @a thunk
+ * must never destroy any of the transaction's splits, nor assign any
+ * of them to a different account. <b>To do so risks a crash.</b>
*/
int gnc_account_tree_staged_transaction_traversal(const Account *account,
@@ -1313,30 +1319,34 @@
void *data);
/** Traverse all of the transactions in the given account group.
- Continue processing IFF proc returns 0. This function
- will descend recursively to traverse transactions in the
- children of the accounts in the group.
-
- Proc will be called exactly once for each transaction that is
- pointed to by at least one split in any account in the hierarchy
- topped by the root Account acc.
-
- The result of this function will be 0 IFF every relevant
- transaction was traversed exactly once; otherwise, the return
- value is the last non-zero value returned by the callback.
-
- Note that the traversal occurs only over the transactions that
- are locally cached in the local gnucash engine. If the gnucash
- engine is attached to a remote database, the database may contain
- (many) transactions that are not mirrored in the local cache.
- This routine will not cause an SQL database query to be performed;
- it will not traverse transactions present only in the remote
- database.
-
- Note that this routine is just a trivial wrapper for
-
- gnc_account_tree_begin_staged_transaction_traversals(g);
- gnc_account_tree_staged_transaction_traversal(g, 42, proc, data);
+ * Continue processing IFF @a proc returns 0. This function
+ * will descend recursively to traverse transactions in the
+ * children of the accounts in the group.
+ *
+ * @a Proc will be called exactly once for each transaction that is
+ * pointed to by at least one split in any account in the hierarchy
+ * topped by the root Account @a acc.
+ *
+ * The result of this function will be 0 IFF every relevant
+ * transaction was traversed exactly once; otherwise, the return
+ * value is the last non-zero value returned by the callback.
+ *
+ * \warning For performance reasons, the transaction callback @a proc
+ * must never destroy any of the transaction's splits, nor assign any
+ * of them to a different account. <b>To do so risks a crash.</b>
+ *
+ * \warning The traversal occurs only over the transactions that
+ * are locally cached in the local gnucash engine. If the gnucash
+ * engine is attached to a remote database, the database may contain
+ * (many) transactions that are not mirrored in the local cache.
+ * This routine will not cause an SQL database query to be performed;
+ * it will not traverse transactions present only in the remote
+ * database.
+ *
+ * Note that this routine is just a trivial wrapper for
+ *
+ * gnc_account_tree_begin_staged_transaction_traversals(g);
+ * gnc_account_tree_staged_transaction_traversal(g, 42, proc, data);
*/
int xaccAccountTreeForEachTransaction(Account *acc,
More information about the gnucash-changes
mailing list