From 15631cf55381b0fe8652914caacc5d6710c49258 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Tue, 8 Feb 2011 15:33:35 +0000 Subject: [PATCH 03/10] 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 --- bus/Makefile.am | 2 + bus/driver.c | 12 +++ bus/stats.c | 287 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ bus/stats.h | 38 +++++++ 4 files changed, 339 insertions(+), 0 deletions(-) create mode 100644 bus/stats.c create mode 100644 bus/stats.h diff --git a/bus/Makefile.am b/bus/Makefile.am index efa8ab5..d04a5ee 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 1e9573e..ce6acc0 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 #include @@ -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[] = { " \n" " \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 0000000..0cd36ca --- /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 +#include "stats.h" + +#include +#include + +#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 0000000..0f843db --- /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 */ -- 1.7.2.3