1 /* stats.c - statistics from the bus driver
3 * Copyright © 2011-2012 Nokia Corporation
4 * Copyright © 2012-2013 Collabora Ltd.
6 * Licensed under the Academic Free License version 2.1
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
27 #include <dbus/dbus-asv-util.h>
28 #include <dbus/dbus-internals.h>
29 #include <dbus/dbus-connection-internal.h>
31 #include "connection.h"
37 #ifdef DBUS_ENABLE_STATS
40 bus_stats_handle_get_stats (DBusConnection *connection,
41 BusTransaction *transaction,
46 BusConnections *connections;
47 DBusMessage *reply = NULL;
48 DBusMessageIter iter, arr_iter;
49 static dbus_uint32_t stats_serial = 0;
50 dbus_uint32_t in_use, in_free_list, allocated;
52 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
54 if (!bus_driver_check_message_is_for_us (message, error))
57 context = bus_transaction_get_context (transaction);
58 connections = bus_context_get_connections (context);
60 reply = _dbus_asv_new_method_return (message, &iter, &arr_iter);
67 _dbus_list_get_stats (&in_use, &in_free_list, &allocated);
69 if (!_dbus_asv_add_uint32 (&arr_iter, "Serial", stats_serial++) ||
70 !_dbus_asv_add_uint32 (&arr_iter, "ListMemPoolUsedBytes", in_use) ||
71 !_dbus_asv_add_uint32 (&arr_iter, "ListMemPoolCachedBytes", in_free_list) ||
72 !_dbus_asv_add_uint32 (&arr_iter, "ListMemPoolAllocatedBytes", allocated))
74 _dbus_asv_abandon (&iter, &arr_iter);
80 if (!_dbus_asv_add_uint32 (&arr_iter, "ActiveConnections",
81 bus_connections_get_n_active (connections)) ||
82 !_dbus_asv_add_uint32 (&arr_iter, "IncompleteConnections",
83 bus_connections_get_n_incomplete (connections)) ||
84 !_dbus_asv_add_uint32 (&arr_iter, "MatchRules",
85 bus_connections_get_total_match_rules (connections)) ||
86 !_dbus_asv_add_uint32 (&arr_iter, "PeakMatchRules",
87 bus_connections_get_peak_match_rules (connections)) ||
88 !_dbus_asv_add_uint32 (&arr_iter, "PeakMatchRulesPerConnection",
89 bus_connections_get_peak_match_rules_per_conn (connections)) ||
90 !_dbus_asv_add_uint32 (&arr_iter, "BusNames",
91 bus_connections_get_total_bus_names (connections)) ||
92 !_dbus_asv_add_uint32 (&arr_iter, "PeakBusNames",
93 bus_connections_get_peak_bus_names (connections)) ||
94 !_dbus_asv_add_uint32 (&arr_iter, "PeakBusNamesPerConnection",
95 bus_connections_get_peak_bus_names_per_conn (connections)))
97 _dbus_asv_abandon (&iter, &arr_iter);
103 if (!_dbus_asv_close (&iter, &arr_iter))
106 if (!bus_transaction_send_from_driver (transaction, connection, reply))
109 dbus_message_unref (reply);
110 return BUS_RESULT_TRUE;
114 dbus_message_unref (reply);
117 return BUS_RESULT_FALSE;
121 bus_stats_handle_get_connection_stats (DBusConnection *caller_connection,
122 BusTransaction *transaction,
123 DBusMessage *message,
126 const char *bus_name = NULL;
127 DBusString bus_name_str;
128 DBusMessage *reply = NULL;
129 DBusMessageIter iter, arr_iter;
130 static dbus_uint32_t stats_serial = 0;
131 dbus_uint32_t in_messages, in_bytes, in_fds, in_peak_bytes, in_peak_fds;
132 dbus_uint32_t out_messages, out_bytes, out_fds, out_peak_bytes, out_peak_fds;
133 BusRegistry *registry;
135 DBusConnection *stats_connection;
137 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
139 if (!bus_driver_check_message_is_for_us (message, error))
142 registry = bus_connection_get_registry (caller_connection);
144 if (! dbus_message_get_args (message, error,
145 DBUS_TYPE_STRING, &bus_name,
147 return BUS_RESULT_FALSE;
149 _dbus_string_init_const (&bus_name_str, bus_name);
150 service = bus_registry_lookup (registry, &bus_name_str);
154 dbus_set_error (error, DBUS_ERROR_NAME_HAS_NO_OWNER,
155 "Bus name '%s' has no owner", bus_name);
156 return BUS_RESULT_FALSE;
159 stats_connection = bus_service_get_primary_owners_connection (service);
160 _dbus_assert (stats_connection != NULL);
162 reply = _dbus_asv_new_method_return (message, &iter, &arr_iter);
167 /* Bus daemon per-connection stats */
169 if (!_dbus_asv_add_uint32 (&arr_iter, "Serial", stats_serial++) ||
170 !_dbus_asv_add_uint32 (&arr_iter, "MatchRules",
171 bus_connection_get_n_match_rules (stats_connection)) ||
172 !_dbus_asv_add_uint32 (&arr_iter, "PeakMatchRules",
173 bus_connection_get_peak_match_rules (stats_connection)) ||
174 !_dbus_asv_add_uint32 (&arr_iter, "BusNames",
175 bus_connection_get_n_services_owned (stats_connection)) ||
176 !_dbus_asv_add_uint32 (&arr_iter, "PeakBusNames",
177 bus_connection_get_peak_bus_names (stats_connection)) ||
178 !_dbus_asv_add_string (&arr_iter, "UniqueName",
179 bus_connection_get_name (stats_connection)))
181 _dbus_asv_abandon (&iter, &arr_iter);
185 /* DBusConnection per-connection stats */
187 _dbus_connection_get_stats (stats_connection,
188 &in_messages, &in_bytes, &in_fds,
189 &in_peak_bytes, &in_peak_fds,
190 &out_messages, &out_bytes, &out_fds,
191 &out_peak_bytes, &out_peak_fds);
193 if (!_dbus_asv_add_uint32 (&arr_iter, "IncomingMessages", in_messages) ||
194 !_dbus_asv_add_uint32 (&arr_iter, "IncomingBytes", in_bytes) ||
195 !_dbus_asv_add_uint32 (&arr_iter, "IncomingFDs", in_fds) ||
196 !_dbus_asv_add_uint32 (&arr_iter, "PeakIncomingBytes", in_peak_bytes) ||
197 !_dbus_asv_add_uint32 (&arr_iter, "PeakIncomingFDs", in_peak_fds) ||
198 !_dbus_asv_add_uint32 (&arr_iter, "OutgoingMessages", out_messages) ||
199 !_dbus_asv_add_uint32 (&arr_iter, "OutgoingBytes", out_bytes) ||
200 !_dbus_asv_add_uint32 (&arr_iter, "OutgoingFDs", out_fds) ||
201 !_dbus_asv_add_uint32 (&arr_iter, "PeakOutgoingBytes", out_peak_bytes) ||
202 !_dbus_asv_add_uint32 (&arr_iter, "PeakOutgoingFDs", out_peak_fds))
204 _dbus_asv_abandon (&iter, &arr_iter);
210 if (!_dbus_asv_close (&iter, &arr_iter))
213 if (!bus_transaction_send_from_driver (transaction, caller_connection,
217 dbus_message_unref (reply);
218 return BUS_RESULT_TRUE;
222 dbus_message_unref (reply);
225 return BUS_RESULT_FALSE;
230 bus_stats_handle_get_all_match_rules (DBusConnection *caller_connection,
231 BusTransaction *transaction,
232 DBusMessage *message,
236 DBusString bus_name_str;
237 DBusMessage *reply = NULL;
238 DBusMessageIter iter, hash_iter, entry_iter, arr_iter;
239 BusRegistry *registry;
240 char **services = NULL;
242 DBusConnection *conn_filter = NULL;
243 BusMatchmaker *matchmaker;
246 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
248 registry = bus_connection_get_registry (caller_connection);
249 context = bus_transaction_get_context (transaction);
250 matchmaker = bus_context_get_matchmaker (context);
252 if (!bus_registry_list_services (registry, &services, &services_len))
255 reply = dbus_message_new_method_return (message);
259 dbus_message_iter_init_append (reply, &iter);
261 if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "{sas}",
265 for (i = 0 ; i < services_len ; i++)
269 /* To avoid duplicate entries, only look for unique names */
270 if (services[i][0] != ':')
273 _dbus_string_init_const (&bus_name_str, services[i]);
274 service = bus_registry_lookup (registry, &bus_name_str);
275 _dbus_assert (service != NULL);
277 conn_filter = bus_service_get_primary_owners_connection (service);
278 _dbus_assert (conn_filter != NULL);
280 if (!dbus_message_iter_open_container (&hash_iter, DBUS_TYPE_DICT_ENTRY, NULL,
283 dbus_message_iter_abandon_container (&iter, &hash_iter);
287 if (!dbus_message_iter_append_basic (&entry_iter, DBUS_TYPE_STRING, &services[i]))
289 dbus_message_iter_abandon_container (&hash_iter, &entry_iter);
290 dbus_message_iter_abandon_container (&iter, &hash_iter);
294 if (!dbus_message_iter_open_container (&entry_iter, DBUS_TYPE_ARRAY, "s",
297 dbus_message_iter_abandon_container (&hash_iter, &entry_iter);
298 dbus_message_iter_abandon_container (&iter, &hash_iter);
302 if (!bus_match_rule_dump (matchmaker, conn_filter, &arr_iter))
304 dbus_message_iter_abandon_container (&entry_iter, &arr_iter);
305 dbus_message_iter_abandon_container (&hash_iter, &entry_iter);
306 dbus_message_iter_abandon_container (&iter, &hash_iter);
310 if (!dbus_message_iter_close_container (&entry_iter, &arr_iter))
312 dbus_message_iter_abandon_container (&hash_iter, &entry_iter);
313 dbus_message_iter_abandon_container (&iter, &hash_iter);
316 if (!dbus_message_iter_close_container (&hash_iter, &entry_iter))
318 dbus_message_iter_abandon_container (&iter, &hash_iter);
323 if (!dbus_message_iter_close_container (&iter, &hash_iter))
326 if (!bus_transaction_send_from_driver (transaction, caller_connection,
330 dbus_message_unref (reply);
331 dbus_free_string_array (services);
336 dbus_message_unref (reply);
338 dbus_free_string_array (services);