diff options
author | Richard Hughes <richard@hughsie.com> | 2016-11-17 19:39:21 +0000 |
---|---|---|
committer | Richard Hughes <richard@hughsie.com> | 2016-11-21 15:19:55 +0000 |
commit | da6750f328fd099fdd1d8cde59f88c07af692514 (patch) | |
tree | ed05ce353b54144ad38e535ed090c32b3fda13b1 | |
parent | c8c76fb8c85b2fbdf65652b85156682f37568ed8 (diff) | |
download | appstream-glib-da6750f328fd099fdd1d8cde59f88c07af692514.tar.gz |
trivial: Add as_ref_string_debug()
This allows us to debug the reference counted string functionality.
-rw-r--r-- | client/as-util.c | 7 | ||||
-rw-r--r-- | libappstream-glib/as-ref-string.c | 95 | ||||
-rw-r--r-- | libappstream-glib/as-ref-string.h | 17 |
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 27e6621..e902713 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) |