summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Hughes <richard@hughsie.com>2016-11-17 19:39:21 +0000
committerRichard Hughes <richard@hughsie.com>2016-11-18 20:22:31 +0000
commit9372be022bb7534063ee8ba541abb880e06980c5 (patch)
treea41f8d70a027438cb87bf6515666a467fba6b682
parent9d8cec9a4a4e955f4267acd1a016801fbdff2f80 (diff)
downloadappstream-glib-9372be022bb7534063ee8ba541abb880e06980c5.tar.gz
trivial: Add as_ref_string_debug()
This allows us to debug the reference counted string functionality.
-rw-r--r--client/as-util.c7
-rw-r--r--libappstream-glib/as-ref-string.c95
-rw-r--r--libappstream-glib/as-ref-string.h17
3 files changed, 119 insertions, 0 deletions
diff --git a/client/as-util.c b/client/as-util.c
index f3f6a2c..87bd77f 100644
--- a/client/as-util.c
+++ b/client/as-util.c
@@ -1362,6 +1362,13 @@ as_util_search (AsUtilPrivate *priv, gchar **values, GError **error)
g_print ("%s\n", xml->str);
}
+ /* dump refcounted string debug data */
+ if (g_getenv ("AS_REF_STR_DEBUG") != NULL) {
+ g_autofree gchar *tmp = as_ref_string_debug (AS_REF_STRING_DEBUG_DEDUPED |
+ AS_REF_STRING_DEBUG_DUPES);
+ g_print ("%s", tmp);
+ }
+
return TRUE;
}
diff --git a/libappstream-glib/as-ref-string.c b/libappstream-glib/as-ref-string.c
index 1ee6376..a1ba129 100644
--- a/libappstream-glib/as-ref-string.c
+++ b/libappstream-glib/as-ref-string.c
@@ -261,3 +261,98 @@ as_ref_string_assign_safe (AsRefString **rstr_ptr, const gchar *str)
if (str != NULL)
*rstr_ptr = as_ref_string_new (str);
}
+
+static gint
+as_ref_string_sort_by_refcnt_cb (gconstpointer a, gconstpointer b)
+{
+ AsRefStringHeader *hdr1 = AS_REFPTR_TO_HEADER (a);
+ AsRefStringHeader *hdr2 = AS_REFPTR_TO_HEADER (b);
+ if (hdr1->refcnt > hdr2->refcnt)
+ return -1;
+ if (hdr1->refcnt < hdr2->refcnt)
+ return 1;
+ return 0;
+}
+
+/**
+ * as_ref_string_debug:
+ * @flags: some #AsRefStringDebugFlags, e.g. %AS_REF_STRING_DEBUG_DUPES
+ *
+ * This function outputs some debugging information to a string.
+ *
+ * Returns: a string describing the current state of the dedupe hash.
+ *
+ * Since: 0.6.6
+ */
+gchar *
+as_ref_string_debug (AsRefStringDebugFlags flags)
+{
+ GHashTable *hash = as_ref_string_get_hash ();
+ GString *tmp = g_string_new (NULL);
+
+ /* overview */
+ g_string_append_printf (tmp, "Size of hash table: %u\n",
+ g_hash_table_size (hash));
+
+ /* success: deduped */
+ if (flags & AS_REF_STRING_DEBUG_DEDUPED) {
+ GList *l;
+ g_autoptr(GList) keys = g_hash_table_get_keys (hash);
+
+ /* split up sections */
+ if (tmp->len > 0)
+ g_string_append (tmp, "\n\n");
+
+ /* sort by refcount number */
+ keys = g_list_sort (keys, as_ref_string_sort_by_refcnt_cb);
+ g_string_append (tmp, "Deduplicated strings:\n");
+ for (l = keys; l != NULL; l = l->next) {
+ const gchar *str = l->data;
+ AsRefStringHeader *hdr = AS_REFPTR_TO_HEADER (str);
+ if (hdr->refcnt <= 1)
+ continue;
+ g_string_append_printf (tmp, "%i\t%s\n", hdr->refcnt, str);
+ }
+ }
+
+ /* failed: duplicate */
+ if (flags & AS_REF_STRING_DEBUG_DUPES) {
+ GList *l;
+ GList *l2;
+ g_autoptr(GHashTable) dupes = g_hash_table_new (g_direct_hash, g_direct_equal);
+ g_autoptr(GList) keys = g_hash_table_get_keys (hash);
+
+ /* split up sections */
+ if (tmp->len > 0)
+ g_string_append (tmp, "\n\n");
+
+ g_string_append (tmp, "Duplicated strings:\n");
+ for (l = keys; l != NULL; l = l->next) {
+ const gchar *str = l->data;
+ AsRefStringHeader *hdr = AS_REFPTR_TO_HEADER (str);
+ guint dupe_cnt = 0;
+
+ if (g_hash_table_contains (dupes, hdr))
+ continue;
+ g_hash_table_add (dupes, (gpointer) hdr);
+
+ for (l2 = l; l2 != NULL; l2 = l2->next) {
+ const gchar *str2 = l2->data;
+ AsRefStringHeader *hdr2 = AS_REFPTR_TO_HEADER (str2);
+ if (g_hash_table_contains (dupes, hdr2))
+ continue;
+ if (l == l2)
+ continue;
+ if (g_strcmp0 (str, str2) != 0)
+ continue;
+ g_hash_table_add (dupes, (gpointer) hdr2);
+ dupe_cnt += 1;
+ }
+ if (dupe_cnt > 0) {
+ g_string_append_printf (tmp, "%u\t%s\n",
+ dupe_cnt, str);
+ }
+ }
+ }
+ return g_string_free (tmp, FALSE);
+}
diff --git a/libappstream-glib/as-ref-string.h b/libappstream-glib/as-ref-string.h
index 2da3b08..79f26d9 100644
--- a/libappstream-glib/as-ref-string.h
+++ b/libappstream-glib/as-ref-string.h
@@ -32,6 +32,22 @@ G_BEGIN_DECLS
typedef gchar AsRefString;
+/**
+ * AsRefStringDebugFlags:
+ * @AS_REF_STRING_DEBUG_NONE: No detailed debugging
+ * @AS_REF_STRING_DEBUG_DEDUPED: Show detailed dedupe stats
+ * @AS_REF_STRING_DEBUG_DUPES: Show detailed duplication stats
+ *
+ * The debug type flags.
+ **/
+typedef enum {
+ AS_REF_STRING_DEBUG_NONE = 0, /* Since: 0.6.16 */
+ AS_REF_STRING_DEBUG_DEDUPED = 1 << 0, /* Since: 0.6.16 */
+ AS_REF_STRING_DEBUG_DUPES = 1 << 1, /* Since: 0.6.16 */
+ /*< private >*/
+ AS_REF_STRING_DEBUG_LAST
+} AsRefStringDebugFlags;
+
AsRefString *as_ref_string_new (const gchar *str);
AsRefString *as_ref_string_new_with_length (const gchar *str,
gsize len);
@@ -44,6 +60,7 @@ void as_ref_string_assign (AsRefString **rstr_ptr,
AsRefString *rstr);
void as_ref_string_assign_safe (AsRefString **rstr_ptr,
const gchar *str);
+gchar *as_ref_string_debug (AsRefStringDebugFlags flags);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(AsRefString, as_ref_string_unref)