[Scrub.c] refactor xaccAccountTreeScrubImbalance

The scrubbing routines are transaction oriented. Instead of
xaccAccountTreeScrubImbalance calling xaccAccountScrubImbalance for
each descendant, refactor so that the transaction list is generated
only once. The scrubbing is faster and progress bar is more accurate.
pull/1651/head
Christopher Lam 3 years ago
parent d214b2f05d
commit 8628ca8715

@ -43,6 +43,7 @@
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include "Account.h"
#include "AccountP.h"
@ -52,6 +53,8 @@
#include "gnc-commodity.h"
#include "qofinstance-p.h"
#include "gnc-session.h"
#include "qofquery.h"
#include "Query.h"
#undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "gnc.engine.scrub"
@ -88,6 +91,22 @@ gnc_get_ongoing_scrub (void)
/* ================================================================ */
static GList*
get_all_transactions (Account *account, bool descendants)
{
GList *accounts = descendants ? gnc_account_get_descendants (account) : NULL;
accounts = g_list_prepend (accounts, account);
QofQuery *q = qof_query_create_for (GNC_ID_TRANS);
QofBook *book = qof_session_get_book (gnc_get_current_session ());
qof_query_set_book (q, book);
xaccQueryAddAccountMatch (q, accounts, QOF_GUID_MATCH_ANY, QOF_QUERY_AND);
GList *transactions = g_list_copy (qof_query_run (q));
qof_query_destroy (q);
return transactions;
}
/* ================================================================ */
void
xaccAccountTreeScrubOrphans (Account *acc, QofPercentageFunc percentagefunc)
{
@ -331,78 +350,59 @@ xaccSplitScrub (Split *split)
/* ================================================================ */
void
xaccAccountTreeScrubImbalance (Account *acc, QofPercentageFunc percentagefunc)
{
if (!acc) return;
if (abort_now)
(percentagefunc)(NULL, -1.0);
scrub_depth++;
xaccAccountScrubImbalance (acc, percentagefunc);
gnc_account_foreach_descendant(acc,
(AccountCb)xaccAccountScrubImbalance, percentagefunc);
scrub_depth--;
}
void
xaccAccountScrubImbalance (Account *acc, QofPercentageFunc percentagefunc)
static void
AccountScrubImbalance (Account *acc, bool descendants,
QofPercentageFunc percentagefunc)
{
GList *node, *splits;
const char *str;
const char *message = _( "Looking for imbalances in account %s: %u of %u");
gint split_count = 0, curr_split_no = 0;
const char *message = _( "Looking for imbalances in transaction date %s: %u of %u");
if (!acc) return;
/* If it's a trading account and an imbalanced transaction is
* found the trading splits will be replaced, invalidating the
* split list in mid-traversal, see
* https://bugs.gnucash.org/show_bug.cgi?id=798346. Also the
* transactions will get scrubbed at least twice from their "real"
* accounts anyway so doing so from the trading accounts is wasted
* effort.
*/
if (xaccAccountGetType(acc) == ACCT_TYPE_TRADING)
return;
scrub_depth++;
str = xaccAccountGetName(acc);
str = str ? str : "(null)";
PINFO ("Looking for imbalances in account %s\n", str);
QofBook *book = qof_session_get_book (gnc_get_current_session ());
Account *root = gnc_book_get_root_account (book);
GList *transactions = get_all_transactions (acc, descendants);
guint count = g_list_length (transactions), curr_trans = 0;
splits = xaccAccountGetSplitList(acc);
split_count = g_list_length (splits);
for (node = splits; node; node = node->next)
scrub_depth++;
for (GList *node = transactions; node; node = node->next, curr_trans++)
{
Split *split = node->data;
Transaction *trans = xaccSplitGetParent(split);
Transaction *trans = node->data;
if (abort_now) break;
PINFO("Start processing split %d of %d",
curr_split_no + 1, split_count);
PINFO("Start processing transaction %d of %d", curr_trans + 1, count);
if (curr_split_no % 10 == 0)
if (curr_trans % 10 == 0)
{
char *progress_msg = g_strdup_printf (message, str, curr_split_no, split_count);
(percentagefunc)(progress_msg, (100 * curr_split_no) / split_count);
char *date = qof_print_date (xaccTransGetDate (trans));
char *progress_msg = g_strdup_printf (message, date, curr_trans, count);
(percentagefunc)(progress_msg, (100 * curr_trans) / count);
g_free (progress_msg);
g_free (date);
}
TransScrubOrphansFast (xaccSplitGetParent (split),
gnc_account_get_root (acc));
TransScrubOrphansFast (trans, root);
xaccTransScrubCurrency(trans);
xaccTransScrubImbalance (trans, root, NULL);
xaccTransScrubImbalance (trans, gnc_account_get_root (acc), NULL);
PINFO("Finished processing split %d of %d",
curr_split_no + 1, split_count);
curr_split_no++;
PINFO("Finished processing transaction %d of %d", curr_trans + 1, count);
}
(percentagefunc)(NULL, -1.0);
scrub_depth--;
g_list_free (transactions);
}
void
xaccAccountTreeScrubImbalance (Account *acc, QofPercentageFunc percentagefunc)
{
AccountScrubImbalance (acc, true, percentagefunc);
}
void
xaccAccountScrubImbalance (Account *acc, QofPercentageFunc percentagefunc)
{
AccountScrubImbalance (acc, false, percentagefunc);
}
static Split *

Loading…
Cancel
Save