[dconf: 1/7] Service: filter changesets when performing writes such that changed events are only emitted if new v



commit 5974d2d08b2d4dffffd348d240aba8afb9dfeb35
Author: Daniel Playfair Cal <daniel playfair cal gmail com>
Date:   Mon Dec 11 17:11:14 2017 +1100

    Service: filter changesets when performing writes such that changed events are only emitted if new values 
differ from existing values

 common/dconf-changeset.c | 70 +++++++++++++++++++++++++++++++++++++-----------
 common/dconf-changeset.h |  3 +++
 service/dconf-writer.c   | 24 ++++++++++-------
 3 files changed, 72 insertions(+), 25 deletions(-)
---
diff --git a/common/dconf-changeset.c b/common/dconf-changeset.c
index c80c88c..705fec9 100644
--- a/common/dconf-changeset.c
+++ b/common/dconf-changeset.c
@@ -771,6 +771,57 @@ dconf_changeset_change (DConfChangeset *changeset,
     }
 }
 
+/**
+ * dconf_changeset_filter_changes:
+ * @base: a database mode changeset
+ * @changes: a changeset
+ *
+ * Produces a changeset that contains all the changes in @changes that
+ * are not already present in @base
+ *
+ * If there are no such changes, %NULL is returned
+ *
+ * Applying the result to @base will yield the same result as applying
+ * @changes to @base
+ *
+ * Returns: (transfer full) (nullable): the minimal changes, or %NULL
+ *
+ * Since: 0.35.1
+ */
+DConfChangeset *
+dconf_changeset_filter_changes (DConfChangeset *base,
+                                DConfChangeset *changes)
+{
+  DConfChangeset *result = NULL;
+  GHashTableIter iter;
+  gpointer key, val;
+
+  g_return_val_if_fail (base->is_database, NULL);
+
+  /* We create the list of changes by iterating the 'changes' changeset
+   * and noting any keys that are not in the 'base' changeset or do not
+   * have the same value in the 'base' changeset
+   *
+   * Note: because 'base' is a database changeset we don't have to
+   * worry about it containing NULL values (dir resets).
+   */
+  g_hash_table_iter_init (&iter, changes->table);
+  while (g_hash_table_iter_next (&iter, &key, &val))
+    {
+      GVariant *base_val = g_hash_table_lookup (base->table, key);
+
+      if (base_val == NULL || !g_variant_equal (val, base_val))
+        {
+          if (!result)
+            result = dconf_changeset_new ();
+
+          dconf_changeset_set (result, key, val);
+        }
+    }
+
+  return result;
+}
+
 /**
  * dconf_changeset_diff:
  * @from: a database mode changeset
@@ -793,7 +844,7 @@ DConfChangeset *
 dconf_changeset_diff (DConfChangeset *from,
                       DConfChangeset *to)
 {
-  DConfChangeset *changeset = NULL;
+  DConfChangeset *changeset;
   GHashTableIter iter;
   gpointer key, val;
 
@@ -806,8 +857,8 @@ dconf_changeset_diff (DConfChangeset *from,
    *
    * We create our list of changes in two steps:
    *
-   *   - iterate the 'to' changeset and note any keys that do not have
-   *     the same value in the 'from' changeset
+   *   - call dconf_changeset_filter_changes to find values from 'to'
+   *     which are not present in 'from' or hold different values to 'to'
    *
    *   - iterate the 'from' changeset and note any keys not present in
    *     the 'to' changeset, recording resets for them
@@ -817,19 +868,8 @@ dconf_changeset_diff (DConfChangeset *from,
    * Note: because 'from' and 'to' are database changesets we don't have
    * to worry about seeing NULL values or dirs.
    */
-  g_hash_table_iter_init (&iter, to->table);
-  while (g_hash_table_iter_next (&iter, &key, &val))
-    {
-      GVariant *from_val = g_hash_table_lookup (from->table, key);
 
-      if (from_val == NULL || !g_variant_equal (val, from_val))
-        {
-          if (!changeset)
-            changeset = dconf_changeset_new ();
-
-          dconf_changeset_set (changeset, key, val);
-        }
-    }
+  changeset = dconf_changeset_filter_changes (from, to);
 
   g_hash_table_iter_init (&iter, from->table);
   while (g_hash_table_iter_next (&iter, &key, &val))
diff --git a/common/dconf-changeset.h b/common/dconf-changeset.h
index b0ce450..6fe60f2 100644
--- a/common/dconf-changeset.h
+++ b/common/dconf-changeset.h
@@ -65,6 +65,9 @@ DConfChangeset *        dconf_changeset_deserialise                     (GVarian
 void                    dconf_changeset_change                          (DConfChangeset           *changeset,
                                                                          DConfChangeset           *changes);
 
+DConfChangeset *        dconf_changeset_filter_changes                  (DConfChangeset           *from,
+                                                                         DConfChangeset           *changes);
+
 DConfChangeset *        dconf_changeset_diff                            (DConfChangeset           *from,
                                                                          DConfChangeset           *to);
 
diff --git a/service/dconf-writer.c b/service/dconf-writer.c
index 26f66dd..8b59019 100644
--- a/service/dconf-writer.c
+++ b/service/dconf-writer.c
@@ -130,21 +130,25 @@ dconf_writer_real_change (DConfWriter    *writer,
                           const gchar    *tag)
 {
   g_return_if_fail (writer->priv->uncommited_values != NULL);
+  DConfChangeset *effective_changeset = dconf_changeset_filter_changes (writer->priv->uncommited_values,
+                                                                        changeset);
 
-  dconf_changeset_change (writer->priv->uncommited_values, changeset);
-
-  if (tag)
+  if (effective_changeset)
     {
-      TaggedChange *change;
+      dconf_changeset_change (writer->priv->uncommited_values, effective_changeset);
+      if (tag)
+        {
+          TaggedChange *change;
 
-      change = g_slice_new (TaggedChange);
-      change->changeset = dconf_changeset_ref (changeset);
-      change->tag = g_strdup (tag);
+          change = g_slice_new (TaggedChange);
+          change->changeset = dconf_changeset_ref (effective_changeset);
+          change->tag = g_strdup (tag);
 
-      g_queue_push_tail (&writer->priv->uncommited_changes, change);
-    }
+          g_queue_push_tail (&writer->priv->uncommited_changes, change);
+        }
 
-  writer->priv->need_write = TRUE;
+      writer->priv->need_write = TRUE;
+    }
 }
 
 static gboolean


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]