summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon McVittie <simon.mcvittie@collabora.co.uk>2011-02-08 15:33:35 +0000
committerSimon McVittie <simon.mcvittie@collabora.co.uk>2011-03-01 15:14:07 +0000
commite4951a1acaf7833033bea129bd2a30bfae639b7d (patch)
tree4fc3dca550a14eb5fecf96eb5c49a21e1d95f238
parent65a4a47eb9eae61f27a6ce0f164faeb6fd28ea25 (diff)
Add a stub .Debug.Stats interface if --enable-stats
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. Bug: https://bugs.freedesktop.org/show_bug.cgi?id=34040
-rw-r--r--bus/Makefile.am2
-rw-r--r--bus/driver.c12
-rw-r--r--bus/stats.c287
-rw-r--r--bus/stats.h38
4 files changed, 339 insertions, 0 deletions
diff --git a/bus/Makefile.am b/bus/Makefile.am
index efa8ab5b..d04a5eee 100644
--- a/bus/Makefile.am
+++ b/bus/Makefile.am
@@ -72,6 +72,8 @@ BUS_SOURCES= \
services.h \
signals.c \
signals.h \
+ stats.c \
+ stats.h \
test.c \
test.h \
utils.c \
diff --git a/bus/driver.c b/bus/driver.c
index 1e9573ee..ce6acc05 100644
--- a/bus/driver.c
+++ b/bus/driver.c
@@ -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
index 00000000..0cd36ca0
--- /dev/null
+++ b/bus/stats.c
@@ -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
index 00000000..0f843db5
--- /dev/null
+++ b/bus/stats.h
@@ -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 */