[PATCH] sort when saving

Jim Radford radford at blackbean.org
Sat May 2 15:18:25 EDT 2009


The attached patches sort the slots, lots, book accounts, bill terms,
customers, employees, entries, invoices, jobs, orders, tax tables and
vendors before saving them to the gnucash XML file.

This is an attempt to make saves more idempotent thereby facilitating
the use of a revision control system on the gnucash XML files.

With these patches most of the needless and seemingly random churn is
gone.  I can now for example add or remove a transaction and expect
there to be no other changes to the gnucash file.

I'm curious to see if these patches affect save performance noticeably
for anyone.  They don't for me, but I don't have a very large file.

A change I'm also considering is removing the counts of accounts,
transactions, jobs, etc. that appear at the top of the file as well
since they always cause merge conflicts.  The information seems
redundant and gnucash seems to be able to regenerate it when asked to.
Are these counts a performance optimization?  Are they needed for
another reason?

-Jim
-------------- next part --------------
--- gnucash-2.2.8/lib/libqof/qof/qofobject.h.orig	2009-04-23 21:33:54.000000000 -0700
+++ gnucash-2.2.8/lib/libqof/qof/qofobject.h	2009-04-23 21:33:17.000000000 -0700
@@ -162,6 +162,10 @@
 void qof_object_foreach (QofIdTypeConst type_name, QofBook *book, 
                          QofInstanceForeachCB cb, gpointer user_data);
 
+/** Invoke callback 'cb' on each instance in guid orted order */
+void qof_object_foreach_sorted (QofIdTypeConst type_name, QofBook *book,
+                                QofInstanceForeachCB cb, gpointer user_data);
+
 /** Register and lookup backend-specific data for this particular object */
 gboolean qof_object_register_backend (QofIdTypeConst type_name,
                                       const char *backend_name,
--- gnucash-2.2.8/lib/libqof/qof/qofobject.c.orig	2009-04-23 21:28:13.000000000 -0700
+++ gnucash-2.2.8/lib/libqof/qof/qofobject.c	2009-04-23 21:30:42.000000000 -0700
@@ -137,6 +137,29 @@
   }
 }
 
+static void
+do_append (QofInstance *qof_p, gpointer list_p)
+{
+  GList **list = list_p;
+  *list = g_list_append(*list, qof_p);
+}
+
+void
+qof_object_foreach_sorted (QofIdTypeConst type_name, QofBook *book, QofInstanceForeachCB cb, gpointer user_data)
+{
+  GList *list = NULL, *n, *l;
+
+  qof_object_foreach(type_name, book, do_append, &list);
+
+  list = g_list_sort(list, qof_instance_guid_compare);
+
+  for (l = list; l; l = l->next)
+    cb(l->data, user_data);
+
+  g_list_free(list);
+}
+
+
 gboolean 
 qof_object_compliance (QofIdTypeConst type_name, gboolean warn)
 {
-------------- next part --------------
--- gnucash-2.2.8/src/business/business-core/file/gnc-bill-term-xml-v2.c.orig	2009-04-23 21:44:09.000000000 -0700
+++ gnucash-2.2.8/src/business/business-core/file/gnc-bill-term-xml-v2.c	2009-04-23 21:44:18.000000000 -0700
@@ -512,7 +512,7 @@
 static void
 billterm_write (FILE *out, QofBook *book)
 {
-  qof_object_foreach (_GNC_MOD_NAME, book, xml_add_billterm, (gpointer) out);
+  qof_object_foreach_sorted (_GNC_MOD_NAME, book, xml_add_billterm, (gpointer) out);
 }
 
 static gboolean
--- gnucash-2.2.8/src/business/business-core/file/gnc-customer-xml-v2.c.orig	2009-04-23 21:40:51.000000000 -0700
+++ gnucash-2.2.8/src/business/business-core/file/gnc-customer-xml-v2.c	2009-04-23 21:41:00.000000000 -0700
@@ -504,7 +504,7 @@
 static void
 customer_write (FILE *out, QofBook *book)
 {
-  qof_object_foreach (_GNC_MOD_NAME, book, xml_add_customer, (gpointer) out);
+  qof_object_foreach_sorted (_GNC_MOD_NAME, book, xml_add_customer, (gpointer) out);
 }
 
 static void
--- gnucash-2.2.8/src/business/business-core/file/gnc-employee-xml-v2.c.orig	2009-04-23 21:41:20.000000000 -0700
+++ gnucash-2.2.8/src/business/business-core/file/gnc-employee-xml-v2.c	2009-04-23 21:41:30.000000000 -0700
@@ -423,7 +423,7 @@
 static void
 employee_write (FILE *out, QofBook *book)
 {
-  qof_object_foreach (_GNC_MOD_NAME, book, xml_add_employee, (gpointer) out);
+  qof_object_foreach_sorted (_GNC_MOD_NAME, book, xml_add_employee, (gpointer) out);
 }
 
 static void
--- gnucash-2.2.8/src/business/business-core/file/gnc-entry-xml-v2.c.orig	2008-01-07 17:05:59.000000000 -0800
+++ gnucash-2.2.8/src/business/business-core/file/gnc-entry-xml-v2.c	2009-04-23 21:42:06.000000000 -0700
@@ -816,7 +816,7 @@
 static void
 entry_write (FILE *out, QofBook *book)
 {
-  qof_object_foreach (_GNC_MOD_NAME, book, xml_add_entry, (gpointer) out);
+  qof_object_foreach_sorted (_GNC_MOD_NAME, book, xml_add_entry, (gpointer) out);
 }
 
 static void
--- gnucash-2.2.8/src/business/business-core/file/gnc-invoice-xml-v2.c.orig	2009-04-23 21:36:01.000000000 -0700
+++ gnucash-2.2.8/src/business/business-core/file/gnc-invoice-xml-v2.c	2009-04-23 21:36:33.000000000 -0700
@@ -535,7 +535,7 @@
 static void
 invoice_write (FILE *out, QofBook *book)
 {
-  qof_object_foreach (_GNC_MOD_NAME, book, xml_add_invoice, (gpointer) out);
+  qof_object_foreach_sorted (_GNC_MOD_NAME, book, xml_add_invoice, (gpointer) out);
 }
 
 static void
--- gnucash-2.2.8/src/business/business-core/file/gnc-job-xml-v2.c.orig	2009-04-23 21:42:29.000000000 -0700
+++ gnucash-2.2.8/src/business/business-core/file/gnc-job-xml-v2.c	2009-04-23 21:42:40.000000000 -0700
@@ -322,7 +322,7 @@
 static void
 job_write (FILE *out, QofBook *book)
 {
-  qof_object_foreach (_GNC_MOD_NAME, book, xml_add_job, (gpointer) out);
+  qof_object_foreach_sorted (_GNC_MOD_NAME, book, xml_add_job, (gpointer) out);
 }
 
 static void
--- gnucash-2.2.8/src/business/business-core/file/gnc-order-xml-v2.c.orig	2009-04-23 21:42:56.000000000 -0700
+++ gnucash-2.2.8/src/business/business-core/file/gnc-order-xml-v2.c	2009-04-23 21:43:02.000000000 -0700
@@ -365,7 +365,7 @@
 static void
 order_write (FILE *out, QofBook *book)
 {
-  qof_object_foreach (_GNC_MOD_NAME, book, xml_add_order, (gpointer) out);
+  qof_object_foreach_sorted (_GNC_MOD_NAME, book, xml_add_order, (gpointer) out);
 }
 
 static void
--- gnucash-2.2.8/src/business/business-core/file/gnc-tax-table-xml-v2.c.orig	2009-04-23 21:43:17.000000000 -0700
+++ gnucash-2.2.8/src/business/business-core/file/gnc-tax-table-xml-v2.c	2009-04-23 21:43:24.000000000 -0700
@@ -475,7 +475,7 @@
 static void
 taxtable_write (FILE *out, QofBook *book)
 {
-  qof_object_foreach (_GNC_MOD_NAME, book, xml_add_taxtable, (gpointer) out);
+  qof_object_foreach_sorted (_GNC_MOD_NAME, book, xml_add_taxtable, (gpointer) out);
 }
 
 
--- gnucash-2.2.8/src/business/business-core/file/gnc-vendor-xml-v2.c.orig	2009-04-23 21:43:45.000000000 -0700
+++ gnucash-2.2.8/src/business/business-core/file/gnc-vendor-xml-v2.c	2009-04-23 21:43:50.000000000 -0700
@@ -441,7 +441,7 @@
 static void
 vendor_write (FILE *out, QofBook *book)
 {
-  qof_object_foreach (_GNC_MOD_NAME, book, xml_add_vendor, (gpointer) out);
+  qof_object_foreach_sorted (_GNC_MOD_NAME, book, xml_add_vendor, (gpointer) out);
 }
 
 static void
-------------- next part --------------
diff -u gnucash-2.2.4/src/backend/file/gnc-account-xml-v2.c gnucash-2.2.4-sorted/src/backend/file/gnc-account-xml-v2.c
--- gnucash-2.2.4/src/backend/file/gnc-account-xml-v2.c	2008-03-02 05:24:27.000000000 -0800
+++ gnucash-2.2.4-sorted/src/backend/file/gnc-account-xml-v2.c	2008-04-23 15:06:13.000000000 -0700
@@ -139,6 +139,8 @@
     {
        xmlNodePtr toaddto = xmlNewChild(ret, NULL, BAD_CAST act_lots_string, NULL);
 
+       lots = g_list_sort(lots, qof_instance_guid_compare);
+
        for (n = lots; n; n=n->next)
        {
           GNCLot * lot = n->data;
-------------- next part --------------
--- gnucash-2.2.8/src/backend/file/sixtp-dom-generators.c.orig	2009-05-01 16:41:27.000000000 -0700
+++ gnucash-2.2.8/src/backend/file/sixtp-dom-generators.c	2009-05-01 16:56:16.000000000 -0700
@@ -357,6 +357,15 @@
 
     add_kvp_value_node(slot_node, "slot:value", (kvp_value*)value);
 }
+
+static void
+g_hash_table_foreach_sorted(GHashTable *hash_table, GHFunc func, gpointer user_data, GCompareFunc compare_func)
+{
+    GList *i, *keys = g_list_sort(g_hash_table_get_keys(hash_table), compare_func);
+    for (i = keys; i; i = i->next)
+        func(i->data, g_hash_table_lookup(hash_table, i->data), user_data);
+    g_list_free(keys);
+}
     
 xmlNodePtr
 kvp_frame_to_dom_tree(const char *tag, const kvp_frame *frame)
@@ -380,7 +389,7 @@
     
     ret = xmlNewNode(NULL, BAD_CAST tag);
     
-    g_hash_table_foreach(kvp_frame_get_hash(frame), add_kvp_slot, ret);
+    g_hash_table_foreach_sorted(kvp_frame_get_hash(frame), add_kvp_slot, ret, strcmp);
     
     return ret;
 }
-------------- next part --------------
--- gnucash-2.2.8/src/backend/file/gnc-book-xml-v2.c~	2008-01-07 17:05:37.000000000 -0800
+++ gnucash-2.2.8/src/backend/file/gnc-book-xml-v2.c	2009-04-13 14:40:28.000000000 -0700
@@ -69,6 +69,7 @@
     GList *children, *node;
 
     children = gnc_account_get_children(account);
+    children = g_list_sort(children, qof_instance_guid_compare);
     for (node = children; node; node = node->next) 
     {
         xmlNodePtr accnode;


More information about the gnucash-devel mailing list