]> git.ipfire.org Git - thirdparty/dbus.git/commitdiff
Add a stub .Debug.Stats interface if --enable-stats
authorSimon McVittie <simon.mcvittie@collabora.co.uk>
Tue, 8 Feb 2011 15:33:35 +0000 (15:33 +0000)
committerSimon McVittie <simon.mcvittie@collabora.co.uk>
Fri, 24 Jun 2011 15:00:49 +0000 (16:00 +0100)
There are no actual statistics yet, just a count of how many times the
method has been called, and (for the per-connection stats) the unique name.

Reviewed-by: Cosimo Alfarano <cosimo.alfarano@collabora.co.uk>
Bug: https://bugs.freedesktop.org/show_bug.cgi?id=34040

bus/Makefile.am
bus/driver.c
bus/stats.c [new file with mode: 0644]
bus/stats.h [new file with mode: 0644]

index 9761c27c7d4d05dd7233b235eaf8b37933e167f6..df48667fa17a2d9a4e41e213aa4fa5c12057c2b6 100644 (file)
@@ -73,6 +73,8 @@ BUS_SOURCES=                                  \
        services.h                              \
        signals.c                               \
        signals.h                               \
+       stats.c                                 \
+       stats.h                                 \
        test.c                                  \
        test.h                                  \
        utils.c                                 \
index 425a3d5ab2d1ee92f7b5ad7a4cded03682323311..9ecfd55ff7dc8cad93e0b398636aa955cbd86e6c 100644 (file)
@@ -30,6 +30,7 @@
 #include "services.h"
 #include "selinux.h"
 #include "signals.h"
+#include "stats.h"
 #include "utils.h"
 #include <dbus/dbus-string.h>
 #include <dbus/dbus-internals.h>
@@ -1743,6 +1744,14 @@ static const MessageHandler introspectable_message_handlers[] = {
   { NULL, NULL, NULL, NULL }
 };
 
+#ifdef DBUS_ENABLE_STATS
+static const MessageHandler stats_message_handlers[] = {
+  { "GetStats", "", "a{sv}", bus_stats_handle_get_stats },
+  { "GetConnectionStats", "s", "a{sv}", bus_stats_handle_get_connection_stats },
+  { NULL, NULL, NULL, NULL }
+};
+#endif
+
 typedef struct {
   const char *name;
   const MessageHandler *message_handlers;
@@ -1765,6 +1774,9 @@ static InterfaceHandler interface_handlers[] = {
     "      <arg type=\"s\"/>\n"
     "    </signal>\n" },
   { DBUS_INTERFACE_INTROSPECTABLE, introspectable_message_handlers, NULL },
+#ifdef DBUS_ENABLE_STATS
+  { BUS_INTERFACE_STATS, stats_message_handlers, NULL },
+#endif
   { NULL, NULL, NULL }
 };
 
diff --git a/bus/stats.c b/bus/stats.c
new file mode 100644 (file)
index 0000000..0cd36ca
--- /dev/null
@@ -0,0 +1,287 @@
+/* stats.c - statistics from the bus driver
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include <config.h>
+#include "stats.h"
+
+#include <dbus/dbus-internals.h>
+#include <dbus/dbus-connection-internal.h>
+
+#include "connection.h"
+#include "services.h"
+#include "utils.h"
+
+#ifdef DBUS_ENABLE_STATS
+
+static DBusMessage *
+new_asv_reply (DBusMessage      *message,
+               DBusMessageIter  *iter,
+               DBusMessageIter  *arr_iter)
+{
+  DBusMessage *reply = dbus_message_new_method_return (message);
+
+  if (reply == NULL)
+    return NULL;
+
+  dbus_message_iter_init_append (reply, iter);
+
+  if (!dbus_message_iter_open_container (iter, DBUS_TYPE_ARRAY, "{sv}",
+                                         arr_iter))
+    {
+      dbus_message_unref (reply);
+      return NULL;
+    }
+
+  return reply;
+}
+
+static dbus_bool_t
+open_asv_entry (DBusMessageIter *arr_iter,
+                DBusMessageIter *entry_iter,
+                const char      *key,
+                const char      *type,
+                DBusMessageIter *var_iter)
+{
+  if (!dbus_message_iter_open_container (arr_iter, DBUS_TYPE_DICT_ENTRY,
+                                         NULL, entry_iter))
+    return FALSE;
+
+  if (!dbus_message_iter_append_basic (entry_iter, DBUS_TYPE_STRING, &key))
+    {
+      dbus_message_iter_abandon_container (arr_iter, entry_iter);
+      return FALSE;
+    }
+
+  if (!dbus_message_iter_open_container (entry_iter, DBUS_TYPE_VARIANT,
+                                         type, var_iter))
+    {
+      dbus_message_iter_abandon_container (arr_iter, entry_iter);
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
+static dbus_bool_t
+close_asv_entry (DBusMessageIter *arr_iter,
+                 DBusMessageIter *entry_iter,
+                 DBusMessageIter *var_iter)
+{
+  if (!dbus_message_iter_close_container (entry_iter, var_iter))
+    {
+      dbus_message_iter_abandon_container (arr_iter, entry_iter);
+      return FALSE;
+    }
+
+  if (!dbus_message_iter_close_container (arr_iter, entry_iter))
+    return FALSE;
+
+  return TRUE;
+}
+
+static dbus_bool_t
+close_asv_reply (DBusMessageIter *iter,
+                 DBusMessageIter *arr_iter)
+{
+  return dbus_message_iter_close_container (iter, arr_iter);
+}
+
+static void
+abandon_asv_entry (DBusMessageIter *arr_iter,
+                   DBusMessageIter *entry_iter,
+                   DBusMessageIter *var_iter)
+{
+  dbus_message_iter_abandon_container (entry_iter, var_iter);
+  dbus_message_iter_abandon_container (arr_iter, entry_iter);
+}
+
+static void
+abandon_asv_reply (DBusMessageIter *iter,
+                 DBusMessageIter *arr_iter)
+{
+  dbus_message_iter_abandon_container (iter, arr_iter);
+}
+
+static dbus_bool_t
+asv_add_uint32 (DBusMessageIter *iter,
+                DBusMessageIter *arr_iter,
+                const char *key,
+                dbus_uint32_t value)
+{
+  DBusMessageIter entry_iter, var_iter;
+
+  if (!open_asv_entry (arr_iter, &entry_iter, key, DBUS_TYPE_UINT32_AS_STRING,
+                       &var_iter))
+    goto oom;
+
+  if (!dbus_message_iter_append_basic (&var_iter, DBUS_TYPE_UINT32,
+                                       &value))
+    {
+      abandon_asv_entry (arr_iter, &entry_iter, &var_iter);
+      goto oom;
+    }
+
+  if (!close_asv_entry (arr_iter, &entry_iter, &var_iter))
+    goto oom;
+
+  return TRUE;
+
+oom:
+  abandon_asv_reply (iter, arr_iter);
+  return FALSE;
+}
+
+static dbus_bool_t
+asv_add_string (DBusMessageIter *iter,
+                DBusMessageIter *arr_iter,
+                const char *key,
+                const char *value)
+{
+  DBusMessageIter entry_iter, var_iter;
+
+  if (!open_asv_entry (arr_iter, &entry_iter, key, DBUS_TYPE_STRING_AS_STRING,
+                       &var_iter))
+    goto oom;
+
+  if (!dbus_message_iter_append_basic (&var_iter, DBUS_TYPE_STRING,
+                                       &value))
+    {
+      abandon_asv_entry (arr_iter, &entry_iter, &var_iter);
+      goto oom;
+    }
+
+  if (!close_asv_entry (arr_iter, &entry_iter, &var_iter))
+    goto oom;
+
+  return TRUE;
+
+oom:
+  abandon_asv_reply (iter, arr_iter);
+  return FALSE;
+}
+
+dbus_bool_t
+bus_stats_handle_get_stats (DBusConnection *connection,
+                            BusTransaction *transaction,
+                            DBusMessage    *message,
+                            DBusError      *error)
+{
+  BusConnections *connections;
+  DBusMessage *reply = NULL;
+  DBusMessageIter iter, arr_iter;
+  static dbus_uint32_t stats_serial = 0;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  connections = bus_transaction_get_connections (transaction);
+
+  reply = new_asv_reply (message, &iter, &arr_iter);
+
+  if (reply == NULL)
+    goto oom;
+
+  if (!asv_add_uint32 (&iter, &arr_iter, "Serial", stats_serial++))
+    goto oom;
+
+  if (!close_asv_reply (&iter, &arr_iter))
+    goto oom;
+
+  if (!bus_transaction_send_from_driver (transaction, connection, reply))
+    goto oom;
+
+  dbus_message_unref (reply);
+  return TRUE;
+
+oom:
+  if (reply != NULL)
+    dbus_message_unref (reply);
+
+  BUS_SET_OOM (error);
+  return FALSE;
+}
+
+dbus_bool_t
+bus_stats_handle_get_connection_stats (DBusConnection *caller_connection,
+                                       BusTransaction *transaction,
+                                       DBusMessage    *message,
+                                       DBusError      *error)
+{
+  const char *bus_name = NULL;
+  DBusString bus_name_str;
+  DBusMessage *reply = NULL;
+  DBusMessageIter iter, arr_iter;
+  static dbus_uint32_t stats_serial = 0;
+  dbus_uint32_t in_messages, in_bytes, in_fds;
+  dbus_uint32_t out_messages, out_bytes, out_fds;
+  BusRegistry *registry;
+  BusService *service;
+  DBusConnection *stats_connection;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  registry = bus_connection_get_registry (caller_connection);
+
+  if (! dbus_message_get_args (message, error,
+                               DBUS_TYPE_STRING, &bus_name,
+                               DBUS_TYPE_INVALID))
+      return FALSE;
+
+  _dbus_string_init_const (&bus_name_str, bus_name);
+  service = bus_registry_lookup (registry, &bus_name_str);
+
+  if (service == NULL)
+    {
+      dbus_set_error (error, DBUS_ERROR_NAME_HAS_NO_OWNER,
+                      "Bus name '%s' has no owner", bus_name);
+      return FALSE;
+    }
+
+  stats_connection = bus_service_get_primary_owners_connection (service);
+  _dbus_assert (stats_connection != NULL);
+
+  reply = new_asv_reply (message, &iter, &arr_iter);
+
+  if (reply == NULL)
+    goto oom;
+
+  if (!asv_add_uint32 (&iter, &arr_iter, "Serial", stats_serial++) ||
+      !asv_add_string (&iter, &arr_iter, "UniqueName",
+        bus_connection_get_name (stats_connection)))
+    goto oom;
+
+  if (!close_asv_reply (&iter, &arr_iter))
+    goto oom;
+
+  if (!bus_transaction_send_from_driver (transaction, caller_connection,
+                                         reply))
+    goto oom;
+
+  dbus_message_unref (reply);
+  return TRUE;
+
+oom:
+  if (reply != NULL)
+    dbus_message_unref (reply);
+
+  BUS_SET_OOM (error);
+  return FALSE;
+}
+
+#endif
diff --git a/bus/stats.h b/bus/stats.h
new file mode 100644 (file)
index 0000000..0f843db
--- /dev/null
@@ -0,0 +1,38 @@
+/* stats.h - statistics from the bus driver
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#ifndef BUS_STATS_H
+#define BUS_STATS_H
+
+#include "bus.h"
+
+#define BUS_INTERFACE_STATS "org.freedesktop.DBus.Debug.Stats"
+
+dbus_bool_t bus_stats_handle_get_stats (DBusConnection *connection,
+                                        BusTransaction *transaction,
+                                        DBusMessage    *message,
+                                        DBusError      *error);
+
+dbus_bool_t bus_stats_handle_get_connection_stats (DBusConnection *connection,
+                                                   BusTransaction *transaction,
+                                                   DBusMessage    *message,
+                                                   DBusError      *error);
+
+#endif /* multiple-inclusion guard */