summaryrefslogtreecommitdiff
path: root/folks
diff options
context:
space:
mode:
authorPhilip Withnall <philip@tecnocode.co.uk>2011-04-23 01:14:20 +0100
committerPhilip Withnall <philip@tecnocode.co.uk>2011-05-02 21:23:58 +0100
commit4292b07504c13e70fba6c1b23b1a043cb2120fa3 (patch)
treecf5a93d5d4e9ef50850ce7454e6d5879e38db8a1 /folks
parent26ea12bdcfbca8ba00b859a59db357a9608e5b39 (diff)
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
Diffstat (limited to 'folks')
-rw-r--r--folks/backend-store.vala69
-rw-r--r--folks/debug.vala50
-rw-r--r--folks/individual-aggregator.vala85
3 files changed, 204 insertions, 0 deletions
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, "");
}
/**