343 lines
11 KiB
C
343 lines
11 KiB
C
/* stats.c - statistics from the bus driver
|
|
*
|
|
* Copyright © 2011-2012 Nokia Corporation
|
|
* Copyright © 2012-2013 Collabora Ltd.
|
|
*
|
|
* SPDX-License-Identifier: AFL-2.1 OR GPL-2.0-or-later
|
|
*
|
|
* 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-asv-util.h>
|
|
#include <dbus/dbus-internals.h>
|
|
#include <dbus/dbus-connection-internal.h>
|
|
|
|
#include "connection.h"
|
|
#include "driver.h"
|
|
#include "services.h"
|
|
#include "signals.h"
|
|
#include "utils.h"
|
|
|
|
#ifdef DBUS_ENABLE_STATS
|
|
|
|
dbus_bool_t
|
|
bus_stats_handle_get_stats (DBusConnection *connection,
|
|
BusTransaction *transaction,
|
|
DBusMessage *message,
|
|
DBusError *error)
|
|
{
|
|
BusContext *context;
|
|
BusConnections *connections;
|
|
DBusMessage *reply = NULL;
|
|
DBusMessageIter iter, arr_iter;
|
|
static dbus_uint32_t stats_serial = 0;
|
|
dbus_uint32_t in_use, in_free_list, allocated;
|
|
|
|
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
|
|
|
|
context = bus_transaction_get_context (transaction);
|
|
connections = bus_context_get_connections (context);
|
|
|
|
reply = _dbus_asv_new_method_return (message, &iter, &arr_iter);
|
|
|
|
if (reply == NULL)
|
|
goto oom;
|
|
|
|
/* Globals */
|
|
|
|
_dbus_list_get_stats (&in_use, &in_free_list, &allocated);
|
|
|
|
if (!_dbus_asv_add_uint32 (&arr_iter, "Serial", stats_serial++) ||
|
|
!_dbus_asv_add_uint32 (&arr_iter, "ListMemPoolUsedBytes", in_use) ||
|
|
!_dbus_asv_add_uint32 (&arr_iter, "ListMemPoolCachedBytes", in_free_list) ||
|
|
!_dbus_asv_add_uint32 (&arr_iter, "ListMemPoolAllocatedBytes", allocated))
|
|
{
|
|
_dbus_asv_abandon (&iter, &arr_iter);
|
|
goto oom;
|
|
}
|
|
|
|
/* Connections */
|
|
|
|
if (!_dbus_asv_add_uint32 (&arr_iter, "ActiveConnections",
|
|
bus_connections_get_n_active (connections)) ||
|
|
!_dbus_asv_add_uint32 (&arr_iter, "IncompleteConnections",
|
|
bus_connections_get_n_incomplete (connections)) ||
|
|
!_dbus_asv_add_uint32 (&arr_iter, "MatchRules",
|
|
bus_connections_get_total_match_rules (connections)) ||
|
|
!_dbus_asv_add_uint32 (&arr_iter, "PeakMatchRules",
|
|
bus_connections_get_peak_match_rules (connections)) ||
|
|
!_dbus_asv_add_uint32 (&arr_iter, "PeakMatchRulesPerConnection",
|
|
bus_connections_get_peak_match_rules_per_conn (connections)) ||
|
|
!_dbus_asv_add_uint32 (&arr_iter, "BusNames",
|
|
bus_connections_get_total_bus_names (connections)) ||
|
|
!_dbus_asv_add_uint32 (&arr_iter, "PeakBusNames",
|
|
bus_connections_get_peak_bus_names (connections)) ||
|
|
!_dbus_asv_add_uint32 (&arr_iter, "PeakBusNamesPerConnection",
|
|
bus_connections_get_peak_bus_names_per_conn (connections)))
|
|
{
|
|
_dbus_asv_abandon (&iter, &arr_iter);
|
|
goto oom;
|
|
}
|
|
|
|
/* end */
|
|
|
|
if (!_dbus_asv_close (&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)
|
|
{
|
|
BusDriverFound found;
|
|
DBusMessage *reply = NULL;
|
|
DBusMessageIter iter, arr_iter;
|
|
static dbus_uint32_t stats_serial = 0;
|
|
dbus_uint32_t in_messages, in_bytes, in_fds, in_peak_bytes, in_peak_fds;
|
|
dbus_uint32_t out_messages, out_bytes, out_fds, out_peak_bytes, out_peak_fds;
|
|
DBusConnection *stats_connection;
|
|
|
|
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
|
|
|
|
found = bus_driver_get_conn_helper (caller_connection, message,
|
|
"statistics", NULL, &stats_connection,
|
|
error);
|
|
|
|
switch (found)
|
|
{
|
|
case BUS_DRIVER_FOUND_SELF:
|
|
dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
|
|
"GetConnectionStats is not meaningful for the "
|
|
"message bus \"%s\" itself", DBUS_SERVICE_DBUS);
|
|
goto failed;
|
|
|
|
case BUS_DRIVER_FOUND_PEER:
|
|
break;
|
|
|
|
case BUS_DRIVER_FOUND_ERROR:
|
|
/* fall through */
|
|
default:
|
|
goto failed;
|
|
}
|
|
|
|
_dbus_assert (stats_connection != NULL);
|
|
|
|
reply = _dbus_asv_new_method_return (message, &iter, &arr_iter);
|
|
|
|
if (reply == NULL)
|
|
goto oom;
|
|
|
|
/* Bus daemon per-connection stats */
|
|
|
|
if (!_dbus_asv_add_uint32 (&arr_iter, "Serial", stats_serial++) ||
|
|
!_dbus_asv_add_uint32 (&arr_iter, "MatchRules",
|
|
bus_connection_get_n_match_rules (stats_connection)) ||
|
|
!_dbus_asv_add_uint32 (&arr_iter, "PeakMatchRules",
|
|
bus_connection_get_peak_match_rules (stats_connection)) ||
|
|
!_dbus_asv_add_uint32 (&arr_iter, "BusNames",
|
|
bus_connection_get_n_services_owned (stats_connection)) ||
|
|
!_dbus_asv_add_uint32 (&arr_iter, "PeakBusNames",
|
|
bus_connection_get_peak_bus_names (stats_connection)) ||
|
|
!_dbus_asv_add_string (&arr_iter, "UniqueName",
|
|
bus_connection_get_name (stats_connection)))
|
|
{
|
|
_dbus_asv_abandon (&iter, &arr_iter);
|
|
goto oom;
|
|
}
|
|
|
|
/* DBusConnection per-connection stats */
|
|
|
|
_dbus_connection_get_stats (stats_connection,
|
|
&in_messages, &in_bytes, &in_fds,
|
|
&in_peak_bytes, &in_peak_fds,
|
|
&out_messages, &out_bytes, &out_fds,
|
|
&out_peak_bytes, &out_peak_fds);
|
|
|
|
if (!_dbus_asv_add_uint32 (&arr_iter, "IncomingMessages", in_messages) ||
|
|
!_dbus_asv_add_uint32 (&arr_iter, "IncomingBytes", in_bytes) ||
|
|
!_dbus_asv_add_uint32 (&arr_iter, "IncomingFDs", in_fds) ||
|
|
!_dbus_asv_add_uint32 (&arr_iter, "PeakIncomingBytes", in_peak_bytes) ||
|
|
!_dbus_asv_add_uint32 (&arr_iter, "PeakIncomingFDs", in_peak_fds) ||
|
|
!_dbus_asv_add_uint32 (&arr_iter, "OutgoingMessages", out_messages) ||
|
|
!_dbus_asv_add_uint32 (&arr_iter, "OutgoingBytes", out_bytes) ||
|
|
!_dbus_asv_add_uint32 (&arr_iter, "OutgoingFDs", out_fds) ||
|
|
!_dbus_asv_add_uint32 (&arr_iter, "PeakOutgoingBytes", out_peak_bytes) ||
|
|
!_dbus_asv_add_uint32 (&arr_iter, "PeakOutgoingFDs", out_peak_fds))
|
|
{
|
|
_dbus_asv_abandon (&iter, &arr_iter);
|
|
goto oom;
|
|
}
|
|
|
|
/* end */
|
|
|
|
if (!_dbus_asv_close (&iter, &arr_iter))
|
|
goto oom;
|
|
|
|
if (!bus_transaction_send_from_driver (transaction, caller_connection,
|
|
reply))
|
|
goto oom;
|
|
|
|
dbus_message_unref (reply);
|
|
return TRUE;
|
|
|
|
oom:
|
|
BUS_SET_OOM (error);
|
|
/* fall through */
|
|
failed:
|
|
if (reply != NULL)
|
|
dbus_message_unref (reply);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
dbus_bool_t
|
|
bus_stats_handle_get_all_match_rules (DBusConnection *caller_connection,
|
|
BusTransaction *transaction,
|
|
DBusMessage *message,
|
|
DBusError *error)
|
|
{
|
|
BusContext *context;
|
|
DBusString bus_name_str;
|
|
DBusMessage *reply = NULL;
|
|
DBusMessageIter iter, hash_iter, entry_iter, arr_iter;
|
|
BusRegistry *registry;
|
|
char **services = NULL;
|
|
int services_len;
|
|
DBusConnection *conn_filter = NULL;
|
|
BusMatchmaker *matchmaker;
|
|
int i;
|
|
|
|
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
|
|
|
|
registry = bus_connection_get_registry (caller_connection);
|
|
context = bus_transaction_get_context (transaction);
|
|
matchmaker = bus_context_get_matchmaker (context);
|
|
|
|
if (!bus_registry_list_services (registry, &services, &services_len))
|
|
return FALSE;
|
|
|
|
reply = dbus_message_new_method_return (message);
|
|
if (reply == NULL)
|
|
goto oom;
|
|
|
|
dbus_message_iter_init_append (reply, &iter);
|
|
|
|
if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "{sas}",
|
|
&hash_iter))
|
|
goto oom;
|
|
|
|
for (i = 0 ; i < services_len ; i++)
|
|
{
|
|
BusService *service;
|
|
|
|
/* To avoid duplicate entries, only look for unique names */
|
|
if (services[i][0] != ':')
|
|
continue;
|
|
|
|
_dbus_string_init_const (&bus_name_str, services[i]);
|
|
service = bus_registry_lookup (registry, &bus_name_str);
|
|
_dbus_assert (service != NULL);
|
|
|
|
conn_filter = bus_service_get_primary_owners_connection (service);
|
|
_dbus_assert (conn_filter != NULL);
|
|
|
|
if (!dbus_message_iter_open_container (&hash_iter, DBUS_TYPE_DICT_ENTRY, NULL,
|
|
&entry_iter))
|
|
{
|
|
dbus_message_iter_abandon_container (&iter, &hash_iter);
|
|
goto oom;
|
|
}
|
|
|
|
if (!dbus_message_iter_append_basic (&entry_iter, DBUS_TYPE_STRING, &services[i]))
|
|
{
|
|
dbus_message_iter_abandon_container (&hash_iter, &entry_iter);
|
|
dbus_message_iter_abandon_container (&iter, &hash_iter);
|
|
goto oom;
|
|
}
|
|
|
|
if (!dbus_message_iter_open_container (&entry_iter, DBUS_TYPE_ARRAY, "s",
|
|
&arr_iter))
|
|
{
|
|
dbus_message_iter_abandon_container (&hash_iter, &entry_iter);
|
|
dbus_message_iter_abandon_container (&iter, &hash_iter);
|
|
goto oom;
|
|
}
|
|
|
|
if (!bus_match_rule_dump (matchmaker, conn_filter, &arr_iter))
|
|
{
|
|
dbus_message_iter_abandon_container (&entry_iter, &arr_iter);
|
|
dbus_message_iter_abandon_container (&hash_iter, &entry_iter);
|
|
dbus_message_iter_abandon_container (&iter, &hash_iter);
|
|
goto oom;
|
|
}
|
|
|
|
if (!dbus_message_iter_close_container (&entry_iter, &arr_iter))
|
|
{
|
|
dbus_message_iter_abandon_container (&hash_iter, &entry_iter);
|
|
dbus_message_iter_abandon_container (&iter, &hash_iter);
|
|
goto oom;
|
|
}
|
|
if (!dbus_message_iter_close_container (&hash_iter, &entry_iter))
|
|
{
|
|
dbus_message_iter_abandon_container (&iter, &hash_iter);
|
|
goto oom;
|
|
}
|
|
}
|
|
|
|
if (!dbus_message_iter_close_container (&iter, &hash_iter))
|
|
goto oom;
|
|
|
|
if (!bus_transaction_send_from_driver (transaction, caller_connection,
|
|
reply))
|
|
goto oom;
|
|
|
|
dbus_message_unref (reply);
|
|
dbus_free_string_array (services);
|
|
return TRUE;
|
|
|
|
oom:
|
|
if (reply != NULL)
|
|
dbus_message_unref (reply);
|
|
|
|
dbus_free_string_array (services);
|
|
|
|
BUS_SET_OOM (error);
|
|
return FALSE;
|
|
}
|
|
|
|
#endif
|