r18527 - gnucash/trunk/src/engine - Free accounts/lots/splits/transactions when closing a book

Phil Longstaff plongstaff at code.gnucash.org
Fri Dec 18 14:45:58 EST 2009


Author: plongstaff
Date: 2009-12-18 14:45:57 -0500 (Fri, 18 Dec 2009)
New Revision: 18527
Trac: http://svn.gnucash.org/trac/changeset/18527

Modified:
   gnucash/trunk/src/engine/Account.c
   gnucash/trunk/src/engine/Split.c
   gnucash/trunk/src/engine/Transaction.c
   gnucash/trunk/src/engine/gnc-lot.c
Log:
Free accounts/lots/splits/transactions when closing a book


Modified: gnucash/trunk/src/engine/Account.c
===================================================================
--- gnucash/trunk/src/engine/Account.c	2009-12-18 12:39:15 UTC (rev 18526)
+++ gnucash/trunk/src/engine/Account.c	2009-12-18 19:45:57 UTC (rev 18527)
@@ -997,6 +997,7 @@
 {
   AccountPrivate *priv;
   GList *lp;
+  gboolean shutting_down = qof_book_shutting_down(qof_instance_get_book(acc));
 
   g_return_if_fail(GNC_IS_ACCOUNT(acc));
 
@@ -1015,13 +1016,16 @@
   /* remove lots -- although these should be gone by now. */
   if (priv->lots)
   {
-    PERR (" instead of calling xaccFreeAccount(), please call \n"
-          " xaccAccountBeginEdit(); xaccAccountDestroy(); \n");
+	/* If shutting down, just drop lots - don't worry about nicities. */
+    if (!shutting_down) {
+        PERR (" instead of calling xaccFreeAccount(), please call \n"
+              " xaccAccountBeginEdit(); xaccAccountDestroy(); \n");
   
-    for (lp=priv->lots; lp; lp=lp->next)
-    {
-      GNCLot *lot = lp->data;
-      gnc_lot_destroy (lot);
+        for (lp=priv->lots; lp; lp=lp->next)
+        {
+          GNCLot *lot = lp->data;
+          gnc_lot_destroy (lot);
+        }
     }
     g_list_free (priv->lots);
     priv->lots = NULL;
@@ -1033,20 +1037,34 @@
    * check once we know the warning isn't occurring any more. */
   if (priv->splits) 
   {
-    GList *slist;
-    PERR (" instead of calling xaccFreeAccount(), please call \n"
-          " xaccAccountBeginEdit(); xaccAccountDestroy(); \n");
+    GList *slist = priv->splits;
+
+	/* If shutting down, just drop lots - don't worry about nicities. */
+	if (!shutting_down) {
+        PERR (" instead of calling xaccFreeAccount(), please call \n"
+              " xaccAccountBeginEdit(); xaccAccountDestroy(); \n");
   
-    qof_instance_reset_editlevel(acc);
+        qof_instance_reset_editlevel(acc);
 
-    slist = g_list_copy(priv->splits);
-    for (lp = slist; lp; lp = lp->next) {
-      Split *s = (Split *) lp->data;
-      g_assert(xaccSplitGetAccount(s) == acc);
-      xaccSplitDestroy (s);
+        slist = g_list_copy(priv->splits);
+        for (lp = slist; lp; lp = lp->next) {
+          Split *s = (Split *) lp->data;
+          g_assert(xaccSplitGetAccount(s) == acc);
+          xaccSplitDestroy (s);
+        }
+    } else {
+	    /* The book is being shut down.  Just break the link from the split
+		  to this account. */
+        for (lp = priv->splits; lp; lp = lp->next) {
+          Split *s = (Split *) lp->data;
+		  s->acc = NULL;
+		  s->orig_acc = NULL;
+		}
+	}
+    g_list_free(slist);
+    if (!shutting_down && priv->splits != NULL) {
+	    PERR("priv->splits != NULL\n");
     }
-    g_list_free(slist);
-    g_assert(priv->splits == NULL);
   }
 
   CACHE_REPLACE(priv->accountName, NULL);
@@ -1135,8 +1153,11 @@
   {
     GList *lp, *slist;
     QofCollection *col;
+	gboolean shutting_down;
  
     qof_instance_increase_editlevel(acc);
+    book = qof_instance_get_book(acc);
+	shutting_down = qof_book_shutting_down(book);
 
     /* First, recursively free children */
     xaccFreeAccountChildren(acc);
@@ -1145,10 +1166,12 @@
            acc, priv->accountName ? priv->accountName : "(null)");
 
     slist = g_list_copy(priv->splits);
-    for (lp = slist; lp; lp = lp->next)
-    {
-      Split *s = lp->data;
-      xaccSplitDestroy (s);
+	if (!shutting_down) {
+        for (lp = slist; lp; lp = lp->next)
+        {
+          Split *s = lp->data;
+          xaccSplitDestroy (s);
+		}
     }
     g_list_free(slist); 
     /* It turns out there's a case where this assertion does not hold:
@@ -1159,8 +1182,7 @@
        g_assert(priv->splits == NULL || qof_book_shutting_down(acc->inst.book));
     */
 
-    book = qof_instance_get_book(acc);
-    if (!qof_book_shutting_down(book)) {
+    if (!shutting_down) {
       col = qof_book_get_collection(book, GNC_ID_TRANS);
       qof_collection_foreach(col, destroy_pending_splits_for_account, acc);
     }
@@ -1566,8 +1588,10 @@
     // And send the account-based event, too
     qof_event_gen(&acc->inst, GNC_EVENT_ITEM_REMOVED, s);
 
-    priv->balance_dirty = TRUE;
-    xaccAccountRecomputeBalance(acc);
+	if (!qof_book_shutting_down(qof_instance_get_book(acc))) {
+        priv->balance_dirty = TRUE;
+        xaccAccountRecomputeBalance(acc);
+	}
     return TRUE;
 }
 
@@ -4608,6 +4632,22 @@
   return xaccAccountStagedTransactionTraversal(acc, 42, proc, data);
 }
 
+static void
+account_book_end(QofBook* book)
+{
+  QofCollection *col;
+  Account *root;
+
+  col = qof_book_get_collection (book, GNC_ID_ROOT_ACCOUNT);
+  root = gnc_coll_get_root_account (col);
+  if (root != NULL) {
+      xaccAccountBeginEdit(root);
+      xaccAccountDestroy(root);
+  }
+  col = qof_book_get_collection (book, GNC_ID_ACCOUNT);
+  printf("Accounts left: %d\n", qof_collection_count(col));
+}
+
 /* ================================================================ */
 /* QofObject function implementation and registration */
 
@@ -4617,7 +4657,7 @@
   .type_label        = "Account",
   .create            = (gpointer)xaccMallocAccount,
   .book_begin        = NULL,
-  .book_end          = NULL,
+  .book_end          = account_book_end,
   .is_dirty          = qof_collection_is_dirty,
   .mark_clean        = qof_collection_mark_clean,
   .foreach           = qof_collection_foreach,

Modified: gnucash/trunk/src/engine/Split.c
===================================================================
--- gnucash/trunk/src/engine/Split.c	2009-12-18 12:39:15 UTC (rev 18526)
+++ gnucash/trunk/src/engine/Split.c	2009-12-18 19:45:57 UTC (rev 18527)
@@ -514,27 +514,30 @@
 xaccSplitCommitEdit(Split *s)
 {
     Account *acc, *orig_acc;
+	gboolean shutting_down = qof_book_shutting_down(qof_instance_get_book(s));
 
     g_return_if_fail(s);
-    if (!qof_instance_is_dirty(QOF_INSTANCE(s)))
+    if (!qof_instance_is_dirty(QOF_INSTANCE(s)) && !shutting_down) {
         return;
+    }
 
     orig_acc = s->orig_acc;
     acc = s->acc;
     /* Remove from lot (but only if it hasn't been moved to
        new lot already) */
-    if (s->lot && (s->lot->account != acc || qof_instance_get_destroying(s)))
+    if (s->lot && (s->lot->account != acc || qof_instance_get_destroying(s))) {
         gnc_lot_remove_split (s->lot, s);
+    }
 
     /* Possibly remove the split from the original account... */
     if (orig_acc && (orig_acc != acc || qof_instance_get_destroying(s))) {
         if (!gnc_account_remove_split(orig_acc, s)) {
           PERR("Account lost track of moved or deleted split.");
         }
-    }
+	}
 
     /* ... and insert it into the new account if needed */
-    if (acc && (orig_acc != acc) && !qof_instance_get_destroying(s)) {
+    if (acc && (orig_acc != acc) && !qof_instance_get_destroying(s) && !shutting_down) {
         if (gnc_account_insert_split(acc, s)) {
             /* If the split's lot belonged to some other account, we
                leave it so. */
@@ -565,7 +568,7 @@
     qof_commit_edit_part2(QOF_INSTANCE(s), commit_err, NULL, 
                           (void (*) (QofInstance *)) xaccFreeSplit);
 
-    if (acc) {
+    if (acc && !shutting_down) {
         g_object_set(acc, "sort-dirty", TRUE, "balance-dirty", TRUE, NULL);
         xaccAccountRecomputeBalance(acc);
     }
@@ -1116,8 +1119,10 @@
    acc = split->acc;
    trans = split->parent;
    if (acc && !qof_instance_get_destroying(acc)
-       && xaccTransGetReadOnly(trans))
+       && xaccTransGetReadOnly(trans)
+	   && !qof_book_shutting_down(qof_instance_get_book(split))) {
        return FALSE;
+   }
 
    xaccTransBeginEdit(trans);
    ed.node = split;

Modified: gnucash/trunk/src/engine/Transaction.c
===================================================================
--- gnucash/trunk/src/engine/Transaction.c	2009-12-18 12:39:15 UTC (rev 18526)
+++ gnucash/trunk/src/engine/Transaction.c	2009-12-18 19:45:57 UTC (rev 18527)
@@ -334,6 +334,11 @@
   GList *node, *new_list = NULL;
   Split *split;
 
+  /* Don't bother if shutting down */
+  if (qof_book_shutting_down(qof_instance_get_book(trans))) {
+      return;
+  }
+
   /* first debits */
   for (node = trans->splits; node; node = node->next) {
     split = node->data;
@@ -451,6 +456,8 @@
 {
   GList *node;
 
+  if (qof_book_shutting_down(qof_instance_get_book(trans)))
+      PINFO("xaccFreeTransaction(%p)\n", trans);
   if (!trans) return;
 
   ENTER ("(addr=%p)", trans);
@@ -957,10 +964,14 @@
 {
   if (!trans) return;
 
+  if (qof_book_shutting_down(qof_instance_get_book(trans)))
+      PINFO("xaccTransDestroy(%p)\n", trans);
   if (!xaccTransGetReadOnly (trans) || 
       qof_book_shutting_down(qof_instance_get_book(trans))) {
       xaccTransBeginEdit(trans);
       qof_instance_set_destroying(trans, TRUE);
+      if (qof_book_shutting_down(qof_instance_get_book(trans)))
+          PINFO("xaccTransDestroy(%p): set destroying\n", trans);
       xaccTransCommitEdit(trans);
   }
 }
@@ -991,6 +1002,9 @@
   SplitList *node;
   gboolean shutting_down = qof_book_shutting_down(qof_instance_get_book(trans));
 
+  if (shutting_down)
+      PINFO("do_destroy(%p)\n", trans);
+
   /* If there are capital-gains transactions associated with this, 
    * they need to be destroyed too.  */
   destroy_gains (trans);
@@ -1002,13 +1016,24 @@
   qof_event_gen (&trans->inst, QOF_EVENT_DESTROY, NULL);
 
   /* We only own the splits that still think they belong to us. */
-  trans->splits = g_list_copy(trans->splits);
-  for (node = trans->splits; node; node = node->next) {
-      Split *s = node->data;
-      if (s->parent == trans) {
-          xaccSplitDestroy(s);
-          xaccSplitCommitEdit(s);
+  if (shutting_down) {
+      while (trans->splits != NULL) {
+	    Split* s;
+        node = g_list_first(trans->splits);
+	    s = node->data;
+	    trans->splits = g_list_remove_link(trans->splits, node);
+	    xaccSplitDestroy(s);
+	    xaccSplitCommitEdit(s);
       }
+  } else {
+  //  trans->splits = g_list_copy(trans->splits);
+    for (node = trans->splits; node; node = node->next) {
+        Split *s = node->data;
+        if (s->parent == trans) {
+            xaccSplitDestroy(s);
+            xaccSplitCommitEdit(s);
+	    }
+    }
   }
   g_list_free (trans->splits);
   trans->splits = NULL;
@@ -1018,7 +1043,7 @@
 /********************************************************************\
 \********************************************************************/
 
-/* Temporary hack for data consitency */
+/* Temporary hack for data consistency */
 static int scrub_data = 1;
 void xaccEnableDataScrubbing(void) { scrub_data = 1; }
 void xaccDisableDataScrubbing(void) { scrub_data = 0; }
@@ -1126,7 +1151,7 @@
     * change the number of splits in this transaction, and the 
     * transaction itself might be deleted.  This is also why
     * we can't really enforce these constraints elsewhere: they
-    * can cause pointers to splits and transactions to disapear out
+    * can cause pointers to splits and transactions to disappear out
     * from under the holder.
     */
    if (!qof_instance_get_destroying(trans) && scrub_data && 
@@ -2013,6 +2038,42 @@
     return NULL;
 }
 
+static void
+trans_destroy(Transaction* trans)
+{
+	ENTER("trans=%p", trans);
+    xaccTransDestroy(trans);
+	LEAVE("trans=%p", trans);
+}
+
+static void
+trans_xy(Transaction* trans)
+{
+    xaccTransDestroy(trans);
+}
+
+static void
+trans_book_end(QofBook* book)
+{
+	guint old_count = 0;
+	guint count;
+
+    QofCollection *col;
+    col = qof_book_get_collection (book, GNC_ID_TRANS);
+	count = qof_collection_count(col);
+	if( count == 0 ) return;
+
+	printf( "Transactions left: %d\n", count);
+	qof_collection_foreach(col, (QofInstanceForeachCB)trans_destroy, NULL);
+	printf( "Transactions left: %d\n", count);
+	while( old_count != count ) {
+	    old_count = count;
+	    qof_collection_foreach(col, (QofInstanceForeachCB)trans_destroy, NULL);
+	    count = qof_collection_count(col);
+	    printf( "Transactions left: %d\n", count);
+    }
+}
+
 /********************************************************************\
 \********************************************************************/
 /* QofObject function implementation */
@@ -2024,7 +2085,7 @@
   .type_label        = "Transaction",
   .create            = (gpointer)xaccMallocTransaction,
   .book_begin        = NULL,
-  .book_end          = NULL,
+  .book_end          = trans_book_end,
   .is_dirty          = qof_collection_is_dirty,
   .mark_clean        = qof_collection_mark_clean,
   .foreach           = qof_collection_foreach,

Modified: gnucash/trunk/src/engine/gnc-lot.c
===================================================================
--- gnucash/trunk/src/engine/gnc-lot.c	2009-12-18 12:39:15 UTC (rev 18526)
+++ gnucash/trunk/src/engine/gnc-lot.c	2009-12-18 19:45:57 UTC (rev 18527)
@@ -450,8 +450,16 @@
 lot_book_end(QofBook* book)
 {
   QofCollection *col;
+  guint count;
+
   col = qof_book_get_collection (book, GNC_ID_LOT);
-  qof_collection_foreach(col, (QofInstanceForeachCB)lot_destroy_book_end, NULL);
+  count = qof_collection_count(col);
+  printf( "Book end: Lots left: %d\n", count);
+  while(count > 0) {
+      qof_collection_foreach(col, (QofInstanceForeachCB)lot_destroy_book_end, NULL);
+      count = qof_collection_count(col);
+      printf( "Lots left: %d\n", count);
+  }
 }
 
 /* ============================================================= */



More information about the gnucash-changes mailing list