Implement GetAllMatchRules on the Stats interface
authorAlban Crequy <alban.crequy@collabora.co.uk>
Mon, 30 Jun 2014 12:44:58 +0000 (13:44 +0100)
committerSimon McVittie <simon.mcvittie@collabora.co.uk>
Thu, 25 Sep 2014 11:59:50 +0000 (12:59 +0100)
Usage:

$ dbus-send --print-reply --dest=org.freedesktop.DBus /org/freedesktop/DBus \
      org.freedesktop.DBus.Debug.Stats.GetAllMatchRules
method return sender=org.freedesktop.DBus -> dest=:1.13 reply_serial=2
   array [
      dict entry(
         string ":1.4"
         array [
         ]
      )
      dict entry(
         string ":1.9"
         array [
            string "type='signal',interface='org.freedesktop.DBus',member='NameOwnerChanged'"
         ]
      )
      dict entry(
         string ":1.11"
         array [
            string "eavesdrop='true'"
         ]
      )
   ]

Bug: https://bugs.freedesktop.org/show_bug.cgi?id=24307
Reviewed-by: Simon McVittie <simon.mcvittie@collabora.co.uk>
bus/driver.c
bus/signals.c
bus/signals.h
bus/stats.c
bus/stats.h

index e95a79d..777b2f8 100644 (file)
@@ -1789,6 +1789,7 @@ static const MessageHandler introspectable_message_handlers[] = {
 static const MessageHandler stats_message_handlers[] = {
   { "GetStats", "", "a{sv}", bus_stats_handle_get_stats },
   { "GetConnectionStats", "s", "a{sv}", bus_stats_handle_get_connection_stats },
+  { "GetAllMatchRules", "", "a{sas}", bus_stats_handle_get_all_match_rules },
   { NULL, NULL, NULL, NULL }
 };
 #endif
index 4c500c6..d81bf2c 100644 (file)
@@ -118,7 +118,7 @@ bus_match_rule_unref (BusMatchRule *rule)
     }
 }
 
-#ifdef DBUS_ENABLE_VERBOSE_MODE
+#if defined(DBUS_ENABLE_VERBOSE_MODE) || defined(DBUS_ENABLE_STATS)
 /* Note this function does not do escaping, so it's only
  * good for debug spew at the moment
  */
@@ -279,7 +279,7 @@ match_rule_to_string (BusMatchRule *rule)
     return s;
   }
 }
-#endif /* DBUS_ENABLE_VERBOSE_MODE */
+#endif /* defined(DBUS_ENABLE_VERBOSE_MODE) || defined(DBUS_ENABLE_STATS) */
 
 dbus_bool_t
 bus_match_rule_set_message_type (BusMatchRule *rule,
@@ -1141,6 +1141,74 @@ struct BusMatchmaker
   RulePool rules_by_type[DBUS_NUM_MESSAGE_TYPES];
 };
 
+#ifdef DBUS_ENABLE_STATS
+dbus_bool_t
+bus_match_rule_dump (BusMatchmaker *matchmaker,
+                     DBusConnection *conn_filter,
+                     DBusMessageIter *arr_iter)
+{
+  int i;
+
+  for (i = 0 ; i < DBUS_NUM_MESSAGE_TYPES ; i++)
+    {
+      DBusHashIter iter;
+      DBusList **list;
+      DBusList *link;
+
+      _dbus_hash_iter_init (matchmaker->rules_by_type[i].rules_by_iface, &iter);
+      while (_dbus_hash_iter_next (&iter))
+        {
+          list =  _dbus_hash_iter_get_value (&iter);
+          for (link = _dbus_list_get_first_link (list);
+               link != NULL;
+               link = _dbus_list_get_next_link (list, link))
+            {
+              BusMatchRule *rule = link->data;
+
+              if (rule->matches_go_to == conn_filter)
+                {
+                  char *s = match_rule_to_string (rule);
+
+                  if (s == NULL)
+                    return FALSE;
+
+                  if (!dbus_message_iter_append_basic (arr_iter, DBUS_TYPE_STRING, &s))
+                    {
+                      dbus_free (s);
+                      return FALSE;
+                    }
+                  dbus_free (s);
+                }
+            }
+        }
+      list = &matchmaker->rules_by_type[i].rules_without_iface;
+      for (link = _dbus_list_get_first_link (list);
+           link != NULL;
+           link = _dbus_list_get_next_link (list, link))
+        {
+          BusMatchRule *rule = link->data;
+
+          if (rule->matches_go_to == conn_filter)
+            {
+              char *s = match_rule_to_string (rule);
+
+              if (s == NULL)
+                return FALSE;
+
+              if (!dbus_message_iter_append_basic (arr_iter, DBUS_TYPE_STRING, &s))
+                {
+                  dbus_free (s);
+                  return FALSE;
+                }
+              dbus_free (s);
+            }
+        }
+    }
+
+  return TRUE;
+}
+#endif
+
 static void
 rule_list_free (DBusList **rules)
 {
index a71d2e4..d19fc7c 100644 (file)
@@ -77,6 +77,12 @@ BusMatchRule* bus_match_rule_parse (DBusConnection   *matches_go_to,
                                     const DBusString *rule_text,
                                     DBusError        *error);
 
+#ifdef DBUS_ENABLE_STATS
+dbus_bool_t bus_match_rule_dump (BusMatchmaker *matchmaker,
+                                 DBusConnection *conn_filter,
+                                 DBusMessageIter *arr_iter);
+#endif
+
 BusMatchmaker* bus_matchmaker_new   (void);
 BusMatchmaker* bus_matchmaker_ref   (BusMatchmaker *matchmaker);
 void           bus_matchmaker_unref (BusMatchmaker *matchmaker);
index 24308eb..859c6a5 100644 (file)
@@ -30,6 +30,7 @@
 
 #include "connection.h"
 #include "services.h"
+#include "signals.h"
 #include "utils.h"
 
 #ifdef DBUS_ENABLE_STATS
@@ -217,4 +218,120 @@ oom:
   return FALSE;
 }
 
+
+dbus_bool_t
+bus_stats_handle_get_all_match_rules (DBusConnection *caller_connection,
+                                      BusTransaction *transaction,
+                                      DBusMessage    *message,
+                                      DBusError      *error)
+{
+  BusContext *context;
+  DBusString bus_name_str;
+  DBusMessage *reply = NULL;
+  DBusMessageIter iter, hash_iter, entry_iter, arr_iter;
+  BusRegistry *registry;
+  char **services = NULL;
+  int services_len;
+  DBusConnection *conn_filter = NULL;
+  BusMatchmaker *matchmaker;
+  int i;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  registry = bus_connection_get_registry (caller_connection);
+  context = bus_transaction_get_context (transaction);
+  matchmaker = bus_context_get_matchmaker (context);
+
+  if (!bus_registry_list_services (registry, &services, &services_len))
+    return FALSE;
+
+  reply = dbus_message_new_method_return (message);
+  if (reply == NULL)
+    goto oom;
+
+  dbus_message_iter_init_append (reply, &iter);
+
+  if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "{sas}",
+                                         &hash_iter))
+    goto oom;
+
+  for (i = 0 ; i < services_len ; i++)
+    {
+      BusService *service;
+
+      /* To avoid duplicate entries, only look for unique names */
+      if (services[i][0] != ':')
+        continue;
+
+      _dbus_string_init_const (&bus_name_str, services[i]);
+      service = bus_registry_lookup (registry, &bus_name_str);
+      _dbus_assert (service != NULL);
+
+      conn_filter = bus_service_get_primary_owners_connection (service);
+      _dbus_assert (conn_filter != NULL);
+
+      if (!dbus_message_iter_open_container (&hash_iter, DBUS_TYPE_DICT_ENTRY, NULL,
+                                             &entry_iter))
+        {
+          dbus_message_iter_abandon_container (&iter, &hash_iter);
+          goto oom;
+        }
+
+      if (!dbus_message_iter_append_basic (&entry_iter, DBUS_TYPE_STRING, &services[i]))
+        {
+          dbus_message_iter_abandon_container (&hash_iter, &entry_iter);
+          dbus_message_iter_abandon_container (&iter, &hash_iter);
+          goto oom;
+        }
+
+      if (!dbus_message_iter_open_container (&entry_iter, DBUS_TYPE_ARRAY, "s",
+                                             &arr_iter))
+        {
+          dbus_message_iter_abandon_container (&hash_iter, &entry_iter);
+          dbus_message_iter_abandon_container (&iter, &hash_iter);
+          goto oom;
+        }
+
+      if (!bus_match_rule_dump (matchmaker, conn_filter, &arr_iter))
+        {
+          dbus_message_iter_abandon_container (&entry_iter, &arr_iter);
+          dbus_message_iter_abandon_container (&hash_iter, &entry_iter);
+          dbus_message_iter_abandon_container (&iter, &hash_iter);
+          goto oom;
+        }
+
+      if (!dbus_message_iter_close_container (&entry_iter, &arr_iter))
+        {
+          dbus_message_iter_abandon_container (&hash_iter, &entry_iter);
+          dbus_message_iter_abandon_container (&iter, &hash_iter);
+          goto oom;
+        }
+      if (!dbus_message_iter_close_container (&hash_iter, &entry_iter))
+        {
+          dbus_message_iter_abandon_container (&iter, &hash_iter);
+          goto oom;
+        }
+    }
+
+  if (!dbus_message_iter_close_container (&iter, &hash_iter))
+    goto oom;
+
+  if (!bus_transaction_send_from_driver (transaction, caller_connection,
+                                         reply))
+    goto oom;
+
+  dbus_message_unref (reply);
+  dbus_free_string_array (services);
+  return TRUE;
+
+oom:
+  if (reply != NULL)
+    dbus_message_unref (reply);
+
+  dbus_free_string_array (services);
+
+  BUS_SET_OOM (error);
+  return FALSE;
+}
+
 #endif
index 0f843db..dcb022c 100644 (file)
@@ -35,4 +35,9 @@ dbus_bool_t bus_stats_handle_get_connection_stats (DBusConnection *connection,
                                                    DBusMessage    *message,
                                                    DBusError      *error);
 
+dbus_bool_t bus_stats_handle_get_all_match_rules (DBusConnection *caller_connection,
+                                                  BusTransaction *transaction,
+                                                  DBusMessage    *message,
+                                                  DBusError      *error);
+
 #endif /* multiple-inclusion guard */