[folks] Allow printing out status information at runtime
- From: Philip Withnall <pwithnall src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [folks] Allow printing out status information at runtime
- Date: Mon, 2 May 2011 20:27:45 +0000 (UTC)
commit 4292b07504c13e70fba6c1b23b1a043cb2120fa3
Author: Philip Withnall <philip tecnocode co uk>
Date: Sat Apr 23 01:14:20 2011 +0100
Allow printing out status information at runtime
When Folks.Debug.print-status is emitted, BackendStore, IndividualAggregator
and Tpf.PersonaStore will now print out their status, including a list
of all the loaded backends, persona stores, aggregated individuals and their
personas.
Folks.Debug.print-status could be emitted as a result of the client process
receiving SIGUSR2, for example.
Helps: bgo#648533
backends/telepathy/lib/tpf-persona-store.vala | 220 +++++++++++++++++++++++++
folks/backend-store.vala | 69 ++++++++
folks/debug.vala | 50 ++++++
folks/individual-aggregator.vala | 85 ++++++++++
4 files changed, 424 insertions(+), 0 deletions(-)
---
diff --git a/backends/telepathy/lib/tpf-persona-store.vala b/backends/telepathy/lib/tpf-persona-store.vala
index 5adca55..893698a 100644
--- a/backends/telepathy/lib/tpf-persona-store.vala
+++ b/backends/telepathy/lib/tpf-persona-store.vala
@@ -24,6 +24,7 @@ using Gee;
using TelepathyGLib;
using Folks;
+extern const string G_LOG_DOMAIN;
extern const string BACKEND_NAME;
/**
@@ -87,6 +88,7 @@ public class Tpf.PersonaStore : Folks.PersonaStore
private MaybeBool _can_group_personas = MaybeBool.UNSET;
private MaybeBool _can_remove_personas = MaybeBool.UNSET;
private bool _is_prepared = false;
+ private Debug _debug;
internal signal void group_members_changed (string group,
GLib.List<Persona>? added, GLib.List<Persona>? removed);
@@ -190,9 +192,227 @@ public class Tpf.PersonaStore : Folks.PersonaStore
display_name: account.display_name,
id: account.get_object_path ());
+ this._debug = Debug.dup ();
+ this._debug.print_status.connect (this._debug_print_status);
+
this._reset ();
}
+ ~PersonaStore ()
+ {
+ this._debug.print_status.disconnect (this._debug_print_status);
+ this._debug = null;
+ }
+
+ private string _format_maybe_bool (MaybeBool input)
+ {
+ switch (input)
+ {
+ case MaybeBool.UNSET:
+ return "unset";
+ case MaybeBool.TRUE:
+ return "true";
+ case MaybeBool.FALSE:
+ return "false";
+ default:
+ assert_not_reached ();
+ }
+ }
+
+ private void _debug_print_status (Debug debug)
+ {
+ const string domain = Debug.STATUS_LOG_DOMAIN;
+ const LogLevelFlags level = LogLevelFlags.LEVEL_INFO;
+
+ debug.print_heading (domain, level, "Tpf.PersonaStore (%p)", this);
+ debug.print_key_value_pairs (domain, level,
+ "ID", this.id,
+ "Prepared?", this._is_prepared ? "yes" : "no",
+ "Publish TpChannel", "%p".printf (this._publish),
+ "Stored TpChannel", "%p".printf (this._stored),
+ "Subscribe TpChannel", "%p".printf (this._subscribe),
+ "TpConnection", "%p".printf (this._conn),
+ "TpAccountManager", "%p".printf (this._account_manager),
+ "Self-TpContact", "%p".printf (this._self_contact),
+ "Can add personas?", this._format_maybe_bool (this._can_add_personas),
+ "Can alias personas?",
+ this._format_maybe_bool (this._can_alias_personas),
+ "Can group personas?",
+ this._format_maybe_bool (this._can_group_personas),
+ "Can remove personas?",
+ this._format_maybe_bool (this._can_remove_personas)
+ );
+
+ debug.print_line (domain, level, "%u Personas:", this._persona_set.size);
+ debug.indent ();
+
+ foreach (var persona in this._persona_set)
+ {
+ debug.print_heading (domain, level, "Persona (%p)", persona);
+ debug.print_key_value_pairs (domain, level,
+ "UID", persona.uid,
+ "IID", persona.iid,
+ "Display ID", persona.display_id,
+ "User?", persona.is_user ? "yes" : "no",
+ "In contact list?", persona.is_in_contact_list ? "yes" : "no",
+ "TpContact", "%p".printf (persona.contact)
+ );
+ }
+
+ debug.unindent ();
+
+ debug.print_line (domain, level, "%u handleâ??Persona mappings:",
+ this._handle_persona_map.size);
+ debug.indent ();
+
+ var iter1 = this._handle_persona_map.map_iterator ();
+ while (iter1.next () == true)
+ {
+ debug.print_line (domain, level,
+ "%u â?? %p", iter1.get_key (), iter1.get_value ());
+ }
+
+ debug.unindent ();
+
+ debug.print_line (domain, level, "%u channel group Persona sets:",
+ this._channel_group_personas_map.size);
+ debug.indent ();
+
+ var iter2 = this._channel_group_personas_map.map_iterator ();
+ while (iter2.next () == true)
+ {
+ debug.print_heading (domain, level,
+ "Channel (%p):", iter2.get_key ());
+
+ debug.indent ();
+
+ foreach (var persona in iter2.get_value ())
+ {
+ debug.print_line (domain, level, "%p", persona);
+ }
+
+ debug.unindent ();
+ }
+
+ debug.unindent ();
+
+ debug.print_line (domain, level, "%u channel group incoming handle sets:",
+ this._channel_group_incoming_adds.size);
+ debug.indent ();
+
+ var iter3 = this._channel_group_incoming_adds.map_iterator ();
+ while (iter3.next () == true)
+ {
+ debug.print_heading (domain, level,
+ "Channel (%p):", iter3.get_key ());
+
+ debug.indent ();
+
+ foreach (var handle in iter3.get_value ())
+ {
+ debug.print_line (domain, level, "%u", handle);
+ }
+
+ debug.unindent ();
+ }
+
+ debug.unindent ();
+
+ debug.print_line (domain, level, "%u group outgoing add sets:",
+ this._group_outgoing_adds.size);
+ debug.indent ();
+
+ var iter4 = this._group_outgoing_adds.map_iterator ();
+ while (iter4.next () == true)
+ {
+ debug.print_heading (domain, level, "Group (%s):", iter4.get_key ());
+
+ debug.indent ();
+
+ foreach (var persona in iter4.get_value ())
+ {
+ debug.print_line (domain, level, "%p", persona);
+ }
+
+ debug.unindent ();
+ }
+
+ debug.unindent ();
+
+ debug.print_line (domain, level, "%u group outgoing remove sets:",
+ this._group_outgoing_removes.size);
+ debug.indent ();
+
+ var iter5 = this._group_outgoing_removes.map_iterator ();
+ while (iter5.next () == true)
+ {
+ debug.print_heading (domain, level, "Group (%s):", iter5.get_key ());
+
+ debug.indent ();
+
+ foreach (var persona in iter5.get_value ())
+ {
+ debug.print_line (domain, level, "%p", persona);
+ }
+
+ debug.unindent ();
+ }
+
+ debug.unindent ();
+
+ debug.print_line (domain, level, "%u unready standard channels:",
+ this._standard_channels_unready.size);
+ debug.indent ();
+
+ var iter6 = this._standard_channels_unready.map_iterator ();
+ while (iter6.next () == true)
+ {
+ debug.print_line (domain, level,
+ "%s â?? %p", iter6.get_key (), iter6.get_value ());
+ }
+
+ debug.unindent ();
+
+ debug.print_line (domain, level, "%u unready group channels:",
+ this._group_channels_unready.size);
+ debug.indent ();
+
+ var iter7 = this._group_channels_unready.map_iterator ();
+ while (iter7.next () == true)
+ {
+ debug.print_line (domain, level,
+ "%s â?? %p", iter7.get_key (), iter7.get_value ());
+ }
+
+ debug.unindent ();
+
+ debug.print_line (domain, level, "%u ready group channels:",
+ this._groups.size);
+ debug.indent ();
+
+ var iter8 = this._groups.map_iterator ();
+ while (iter8.next () == true)
+ {
+ debug.print_line (domain, level,
+ "%s â?? %p", iter8.get_key (), iter8.get_value ());
+ }
+
+ debug.unindent ();
+
+ debug.print_line (domain, level, "%u favourite handles:",
+ this._favourite_handles.size);
+ debug.indent ();
+
+ foreach (var handle in this._favourite_handles)
+ {
+ debug.print_line (domain, level, "%u", handle);
+ }
+
+ debug.unindent ();
+
+ debug.print_line (domain, level, "");
+ }
+
private void _reset ()
{
/* We do not trust local-xmpp or IRC at all, since Persona UIDs can be
diff --git a/folks/backend-store.vala b/folks/backend-store.vala
index 18ee698..d8c21d8 100644
--- a/folks/backend-store.vala
+++ b/folks/backend-store.vala
@@ -139,6 +139,8 @@ public class Folks.BackendStore : Object {
/* register the core debug messages */
this._debug._register_domain (G_LOG_DOMAIN);
+ this._debug.print_status.connect (this._debug_print_status);
+
this._modules = new HashMap<string,unowned Module> (str_hash, str_equal);
this._backend_hash = new HashMap<string,Backend> (str_hash, str_equal);
this._prepared_backends = new HashMap<string,Backend> (str_hash,
@@ -159,10 +161,77 @@ public class Folks.BackendStore : Object {
}
}
+ /* Disconnect from the debug handler */
+ this._debug.print_status.disconnect (this._debug_print_status);
+ this._debug = null;
+
/* manually clear the singleton instance */
_instance = null;
}
+ private void _debug_print_status (Debug debug)
+ {
+ const string domain = Debug.STATUS_LOG_DOMAIN;
+ const LogLevelFlags level = LogLevelFlags.LEVEL_INFO;
+
+ debug.print_heading (domain, level, "BackendStore (%p)", this);
+ debug.print_line (domain, level, "%u Backends:",
+ this._backend_hash.size);
+
+ debug.indent ();
+
+ foreach (var backend in this._backend_hash.values)
+ {
+ debug.print_heading (domain, level, "Backend (%p)", backend);
+ debug.print_key_value_pairs (domain, level,
+ "Ref. count", this.ref_count.to_string (),
+ "Name", backend.name,
+ "Prepared?", backend.is_prepared ? "yes" : "no"
+ );
+ debug.print_line (domain, level, "%u PersonaStores:",
+ backend.persona_stores.size);
+
+ debug.indent ();
+
+ foreach (var persona_store in backend.persona_stores.values)
+ {
+ string trust_level = null;
+
+ switch (persona_store.trust_level)
+ {
+ case PersonaStoreTrust.NONE:
+ trust_level = "none";
+ break;
+ case PersonaStoreTrust.PARTIAL:
+ trust_level = "partial";
+ break;
+ case PersonaStoreTrust.FULL:
+ trust_level = "full";
+ break;
+ default:
+ assert_not_reached ();
+ }
+
+ debug.print_heading (domain, level, "PersonaStore (%p)",
+ persona_store);
+ debug.print_key_value_pairs (domain, level,
+ "Ref. count", this.ref_count.to_string (),
+ "ID", persona_store.id,
+ "Prepared?", persona_store.is_prepared ? "yes" : "no",
+ "Writeable?", persona_store.is_writeable ? "yes" : "no",
+ "Trust level", trust_level,
+ "Persona count", persona_store.personas.size.to_string ()
+ );
+ }
+
+ debug.unindent ();
+ }
+
+ debug.unindent ();
+
+ debug.print_line (domain, level, "");
+ }
+
/**
* Prepare the BackendStore for use.
*
diff --git a/folks/debug.vala b/folks/debug.vala
index 5bade93..6acad1d 100644
--- a/folks/debug.vala
+++ b/folks/debug.vala
@@ -114,6 +114,38 @@ public class Folks.Debug : Object
}
}
+ /**
+ * Signal emitted in the main thread whenever objects should print their
+ * current status. All significant objects in the library should connect
+ * to this and print their current status in some suitable format when it's
+ * emitted.
+ *
+ * Client processes should emit this signal by calling
+ * { link Debug.emit_print_status}.
+ *
+ * @since UNRELEASED
+ */
+ public signal void print_status ();
+
+ /**
+ * Log domain for the status messages logged as a result of calling
+ * { link Debug.emit_print_status().
+ *
+ * This could be used in conjunction with a log handler to redirect the
+ * status information to a debug window or log file, for example.
+ *
+ * @since UNRELEASED
+ */
+ public const string STATUS_LOG_DOMAIN = "folks-status";
+
+ private void _print_status_log_handler_cb (string? log_domain,
+ LogLevelFlags log_levels,
+ string message)
+ {
+ /* Print directly to stdout without any adornments */
+ GLib.stdout.printf ("%s\n", message);
+ }
+
private void _log_handler_cb (string? log_domain,
LogLevelFlags log_levels,
string message)
@@ -222,6 +254,11 @@ public class Folks.Debug : Object
private Debug ()
{
/* Private constructor for singleton */
+
+ /* Install a log handler for log messages emitted as a result of
+ * Debug.print-status being emitted. */
+ Log.set_handler (Debug.STATUS_LOG_DOMAIN, LogLevelFlags.LEVEL_MASK,
+ this._print_status_log_handler_cb);
}
~Debug ()
@@ -234,6 +271,19 @@ public class Folks.Debug : Object
}
/**
+ * Causes all significant objects in the library to print their current
+ * status to standard output, obeying the options set on this
+ * { link Debug} instance for colouring and other formatting.
+ *
+ * @since UNRELEASED
+ */
+ public void emit_print_status ()
+ {
+ print ("Dumping status informationâ?¦\n");
+ this.print_status ();
+ }
+
+ /**
* Increment the indentation level used when printing output through the
* object.
*
diff --git a/folks/individual-aggregator.vala b/folks/individual-aggregator.vala
index be208e7..ddaf293 100644
--- a/folks/individual-aggregator.vala
+++ b/folks/individual-aggregator.vala
@@ -63,6 +63,7 @@ public class Folks.IndividualAggregator : Object
private HashTable<string, Individual> _link_map;
private bool _linking_enabled = true;
private bool _is_prepared = false;
+ private Debug _debug;
private string _configured_writeable_store_type_id;
private static const string _FOLKS_CONFIG_KEY =
"/system/folks/backends/primary_store";
@@ -176,6 +177,8 @@ public class Folks.IndividualAggregator : Object
this._link_map = new HashTable<string, Individual> (str_hash, str_equal);
this._backends = new HashSet<Backend> ();
+ this._debug = Debug.dup ();
+ this._debug.print_status.connect (this._debug_print_status);
/* Check out the configured writeable store */
var store_type_id = Environment.get_variable ("FOLKS_WRITEABLE_STORE");
@@ -215,6 +218,88 @@ public class Folks.IndividualAggregator : Object
this._backend_store.backend_available.disconnect (
this._backend_available_cb);
this._backend_store = null;
+
+ this._debug.print_status.disconnect (this._debug_print_status);
+ }
+
+ private void _debug_print_status (Debug debug)
+ {
+ const string domain = Debug.STATUS_LOG_DOMAIN;
+ const LogLevelFlags level = LogLevelFlags.LEVEL_INFO;
+
+ debug.print_heading (domain, level, "IndividualAggregator (%p)", this);
+ debug.print_key_value_pairs (domain, level,
+ "Ref. count", this.ref_count.to_string (),
+ "Writeable store", "%p".printf (this._writeable_store),
+ "Linking enabled?", this._linking_enabled ? "yes" : "no",
+ "Prepared?", this._is_prepared ? "yes" : "no"
+ );
+
+ debug.print_line (domain, level,
+ "%u Individuals:", this.individuals.size);
+ debug.indent ();
+
+ foreach (var individual in this.individuals.values)
+ {
+ string trust_level = null;
+
+ switch (individual.trust_level)
+ {
+ case TrustLevel.NONE:
+ trust_level = "none";
+ break;
+ case TrustLevel.PERSONAS:
+ trust_level = "personas";
+ break;
+ default:
+ assert_not_reached ();
+ }
+
+ debug.print_heading (domain, level, "Individual (%p)", individual);
+ debug.print_key_value_pairs (domain, level,
+ "Ref. count", individual.ref_count.to_string (),
+ "ID", individual.id,
+ "User?", individual.is_user ? "yes" : "no",
+ "Trust level", trust_level
+ );
+ debug.print_line (domain, level, "%u Personas:",
+ individual.personas.size);
+
+ debug.indent ();
+
+ foreach (var persona in individual.personas)
+ {
+ debug.print_heading (domain, level, "Persona (%p)", persona);
+ debug.print_key_value_pairs (domain, level,
+ "Ref. count", persona.ref_count.to_string (),
+ "UID", persona.uid,
+ "IID", persona.iid,
+ "Display ID", persona.display_id,
+ "User?", persona.is_user ? "yes" : "no"
+ );
+ }
+
+ debug.unindent ();
+ }
+
+ debug.unindent ();
+
+ debug.print_line (domain, level, "%u entries in the link map:",
+ this._link_map.size ());
+ debug.indent ();
+
+ var iter = HashTableIter<string, Individual> (this._link_map);
+ string link_key;
+ Individual individual;
+ while (iter.next (out link_key, out individual) == true)
+ {
+ debug.print_line (domain, level,
+ "%s â?? %p", link_key, individual);
+ }
+
+ debug.unindent ();
+
+ debug.print_line (domain, level, "");
}
/**
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]