From 8c7ea23e0b3ab2bb9c3282a8b272d8437a78fe85 Mon Sep 17 00:00:00 2001 From: Alban Crequy Date: Tue, 22 Feb 2011 18:07:14 +0000 Subject: [PATCH] Include global peaks for message sizes, recipients counts and per interfaces Bug: https://bugs.freedesktop.org/show_bug.cgi?id=34040 --- bus/connection.c | 179 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ bus/connection.h | 10 +++ bus/dispatch.c | 4 + bus/stats.c | 89 ++++++++++++++++++++++++++- 4 files changed, 281 insertions(+), 1 deletions(-) diff --git a/bus/connection.c b/bus/connection.c index 139bc2c..bd58063 100644 --- a/bus/connection.c +++ b/bus/connection.c @@ -30,6 +30,7 @@ #include "signals.h" #include "expirelist.h" #include "selinux.h" +#include #include #include #include @@ -71,6 +72,19 @@ struct BusConnections int total_bus_names; int peak_bus_names; int peak_bus_names_per_conn; + + int peak_message_recipients; + int peak_message_size; + int peak_size_x_recipients; + int messages_count; + /* a{sa{sv}} + * Iface.Member -> { + * PeakMessageSize:u, + * PeakMessageRecipients:u, + * PeakMessageSizeXRecipients:u} + * MessagesCount:u} + */ + DBusHashTable *many_recipient_messages; #endif }; @@ -481,9 +495,18 @@ bus_connections_new (BusContext *context) connections->refcount = 1; connections->context = context; + + connections->many_recipient_messages = + _dbus_hash_table_new (DBUS_HASH_STRING, NULL, NULL); + + if (connections->many_recipient_messages == NULL) + goto failed_6; return connections; + failed_6: + _dbus_loop_remove_timeout (bus_context_get_loop (context), + connections->expire_timeout, call_timeout_callback, NULL); failed_5: bus_expire_list_free (connections->pending_replies); failed_4: @@ -2409,6 +2432,162 @@ bus_connections_get_peak_bus_names_per_conn (BusConnections *connections) } int +bus_connections_get_peak_message_recipients (BusConnections *connections) +{ + return connections->peak_message_recipients; +} + +int +bus_connections_get_peak_message_size (BusConnections *connections) +{ + return connections->peak_message_size; +} + +int +bus_connections_get_peak_size_x_recipients (BusConnections *connections) +{ + return connections->peak_size_x_recipients; +} + +int +bus_connections_get_messages_count (BusConnections *connections) +{ + return connections->messages_count; +} + +DBusHashTable * +bus_connections_get_many_recipient_messages (BusConnections *connections) +{ + return connections->many_recipient_messages; +} + +void +bus_connections_stats_add_message (BusConnections *connections, + DBusMessage *message, + DBusList *recipients) +{ + const char *destination; + const char *interface; + const char *member; + int type; + char *buffer; + int size = 0; + int recipients_count = 0; + int ret; + DBusList *link; + DBusString iface_member; + DBusHashTable *inner; + dbus_uint32_t *inner_peak_size; + dbus_uint32_t *inner_peak_size_x_recipients; + dbus_uint32_t *inner_peak_recipients; + dbus_uint32_t *inner_messages_count; + + type = dbus_message_get_type (message); + destination = dbus_message_get_destination (message); + interface = dbus_message_get_interface (message); + if (type == DBUS_MESSAGE_TYPE_ERROR) + member = dbus_message_get_error_name (message); + else + member = dbus_message_get_member (message); + + /* Just get the size and discard the buffer */ + ret = dbus_message_marshal (message, &buffer, &size); + if (ret) + free (buffer); + + /* Count the recipients */ + link = _dbus_list_get_first_link (&recipients); + while (link != NULL) + { + recipients_count++; + link = _dbus_list_get_next_link (&recipients, link); + } + if (destination) + recipients_count++; + + update_peak (&connections->peak_message_recipients, recipients_count); + update_peak (&connections->peak_message_size, size); + update_peak (&connections->peak_size_x_recipients, size * recipients_count); + connections->messages_count++; + + if (!_dbus_string_init (&iface_member)) + return; + + if (interface && member) + { + if (!_dbus_string_append_printf (&iface_member, "%s %s.%s", + dbus_message_type_to_string (type), interface, member)) + goto free_string; + } + else + { + if (!_dbus_string_append_printf (&iface_member, "%s", + dbus_message_type_to_string (type))) + goto free_string; + } + + inner = _dbus_hash_table_lookup_string ( + connections->many_recipient_messages, + _dbus_string_get_const_data (&iface_member)); + if (!inner) + { + char *key = NULL; + ret = _dbus_string_copy_data (&iface_member, &key); + if (!ret) + goto free_string; + inner = _dbus_hash_table_new (DBUS_HASH_STRING, NULL, + (DBusFreeFunction)dbus_free); + if (!inner) + { + dbus_free (key); + goto free_string; + } + inner_peak_size = dbus_malloc0 (sizeof (dbus_uint32_t)); + inner_peak_recipients = dbus_malloc0 (sizeof (dbus_uint32_t)); + inner_peak_size_x_recipients = dbus_malloc0 (sizeof (dbus_uint32_t)); + inner_messages_count = dbus_malloc0 (sizeof (dbus_uint32_t)); + + if (inner_peak_size == NULL || inner_peak_recipients == NULL || + inner_peak_size_x_recipients == NULL || inner_messages_count == NULL) + { + _dbus_hash_table_unref (inner); + dbus_free (key); + dbus_free (inner_peak_size); + dbus_free (inner_peak_recipients); + dbus_free (inner_peak_size_x_recipients); + dbus_free (inner_messages_count); + goto free_string; + } + + _dbus_hash_table_insert_string (inner, "PeakMessageSize", inner_peak_size); + _dbus_hash_table_insert_string (inner, "PeakMessageRecipients", + inner_peak_recipients); + _dbus_hash_table_insert_string (inner, "PeakMessageSizeXRecipients", + inner_peak_size_x_recipients); + _dbus_hash_table_insert_string (inner, "MessagesCount", + inner_messages_count); + _dbus_hash_table_insert_string ( + connections->many_recipient_messages, key, inner); + } + + inner_peak_size = _dbus_hash_table_lookup_string (inner, "PeakMessageSize"); + inner_peak_recipients = _dbus_hash_table_lookup_string (inner, + "PeakMessageRecipients"); + inner_peak_size_x_recipients = _dbus_hash_table_lookup_string (inner, + "PeakMessageSizeXRecipients"); + inner_messages_count = _dbus_hash_table_lookup_string (inner, + "MessagesCount"); + + update_peak (inner_peak_recipients, recipients_count); + update_peak (inner_peak_size, size); + update_peak (inner_peak_size_x_recipients, size * recipients_count); + *inner_messages_count += 1; + +free_string: + _dbus_string_free (&iface_member); +} + +int bus_connection_get_peak_match_rules (DBusConnection *connection) { BusConnectionData *d; diff --git a/bus/connection.h b/bus/connection.h index c936021..b5c3519 100644 --- a/bus/connection.h +++ b/bus/connection.h @@ -26,6 +26,7 @@ #include #include +#include #include "bus.h" typedef dbus_bool_t (* BusConnectionForeachFunction) (DBusConnection *connection, @@ -147,6 +148,15 @@ int bus_connections_get_peak_match_rules_per_conn (BusConnections *connections); int bus_connections_get_total_bus_names (BusConnections *connections); int bus_connections_get_peak_bus_names (BusConnections *connections); int bus_connections_get_peak_bus_names_per_conn (BusConnections *connections); +int bus_connections_get_peak_message_recipients (BusConnections *connections); +int bus_connections_get_peak_message_size (BusConnections *connections); +int bus_connections_get_peak_size_x_recipients (BusConnections *connections); +int bus_connections_get_messages_count (BusConnections *connections); +DBusHashTable * bus_connections_get_many_recipient_messages (BusConnections *connections); + +void bus_connections_stats_add_message (BusConnections *connections, + DBusMessage *message, + DBusList *recipients); int bus_connection_get_peak_match_rules (DBusConnection *connection); int bus_connection_get_peak_bus_names (DBusConnection *connection); diff --git a/bus/dispatch.c b/bus/dispatch.c index a80476c..8595de6 100644 --- a/bus/dispatch.c +++ b/bus/dispatch.c @@ -152,6 +152,10 @@ bus_dispatch_matches (BusTransaction *transaction, return FALSE; } +#ifdef DBUS_ENABLE_STATS + bus_connections_stats_add_message (connections, message, recipients); +#endif + link = _dbus_list_get_first_link (&recipients); while (link != NULL) { diff --git a/bus/stats.c b/bus/stats.c index 4e72885..c1cd73e 100644 --- a/bus/stats.c +++ b/bus/stats.c @@ -23,6 +23,7 @@ #include #include +#include #include "connection.h" #include "services.h" @@ -177,6 +178,82 @@ oom: return FALSE; } +static dbus_bool_t +asv_add_asasvu (DBusMessageIter *iter, + DBusMessageIter *arr_iter, + const char *key, + DBusHashTable *value) +{ + DBusMessageIter entry_iter, var_iter; + DBusMessageIter inner_arr_iter, inner_entry_iter, inner_var_iter; + DBusHashIter hash_iter; + + if (!open_asv_entry (arr_iter, &entry_iter, key, "a{sv}", + &var_iter)) + goto oom; + + if (!dbus_message_iter_open_container (&var_iter, DBUS_TYPE_ARRAY, "{sv}", + &inner_arr_iter)) + { + abandon_asv_entry (arr_iter, &entry_iter, &var_iter); + goto oom; + } + + _dbus_hash_iter_init (value, &hash_iter); + while (_dbus_hash_iter_next (&hash_iter)) + { + const char *k = _dbus_hash_iter_get_string_key (&hash_iter); + DBusHashTable *v = _dbus_hash_iter_get_value (&hash_iter); + DBusMessageIter inner2_arr_iter, inner2_entry_iter, inner2_var_iter; + DBusHashIter hash_iter2; + + if (!open_asv_entry (&inner_arr_iter, &inner_entry_iter, k, + "a{sv}", &inner_var_iter)) + goto oom; + + if (!dbus_message_iter_open_container (&inner_var_iter, DBUS_TYPE_ARRAY, "{sv}", + &inner2_arr_iter)) + goto oom; + + _dbus_hash_iter_init (v, &hash_iter2); + while (_dbus_hash_iter_next (&hash_iter2)) + { + const char *k2 = _dbus_hash_iter_get_string_key (&hash_iter2); + dbus_uint32_t *v2 = _dbus_hash_iter_get_value (&hash_iter2); + + + if (!open_asv_entry (&inner2_arr_iter, &inner2_entry_iter, k2, + DBUS_TYPE_UINT32_AS_STRING, &inner2_var_iter)) + goto oom; + + if (!dbus_message_iter_append_basic (&inner2_var_iter, DBUS_TYPE_UINT32, + v2)) + goto oom; + + if (!close_asv_entry (&inner2_arr_iter, &inner2_entry_iter, &inner2_var_iter)) + goto oom; + + + } + if (!dbus_message_iter_close_container (&inner_var_iter, &inner2_arr_iter)) + goto oom; + + if (!close_asv_entry (&inner_arr_iter, &inner_entry_iter, &inner_var_iter)) + goto oom; + } + + if (!dbus_message_iter_close_container (&var_iter, &inner_arr_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, @@ -228,7 +305,17 @@ bus_stats_handle_get_stats (DBusConnection *connection, !asv_add_uint32 (&iter, &arr_iter, "PeakBusNames", bus_connections_get_peak_bus_names (connections)) || !asv_add_uint32 (&iter, &arr_iter, "PeakBusNamesPerConnection", - bus_connections_get_peak_bus_names_per_conn (connections))) + bus_connections_get_peak_bus_names_per_conn (connections)) || + !asv_add_uint32 (&iter, &arr_iter, "PeakMessageRecipients", + bus_connections_get_peak_message_recipients (connections)) || + !asv_add_uint32 (&iter, &arr_iter, "PeakMessageSize", + bus_connections_get_peak_message_size (connections)) || + !asv_add_uint32 (&iter, &arr_iter, "PeakSizeXRecipients", + bus_connections_get_peak_size_x_recipients (connections)) || + !asv_add_uint32 (&iter, &arr_iter, "MessagesCount", + bus_connections_get_messages_count (connections)) || + !asv_add_asasvu (&iter, &arr_iter, "ManyRecipientMessages", + bus_connections_get_many_recipient_messages (connections))) goto oom; /* end */ -- 1.7.1