stats.c 7.47 KB
Newer Older
1
/* stats.c - statistics from the bus driver
2 3 4
 *
 * Copyright © 2011-2012 Nokia Corporation
 * Copyright © 2012-2013 Collabora Ltd.
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
 *
 * 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"

27
#include <dbus/dbus-asv-util.h>
28 29 30 31
#include <dbus/dbus-internals.h>
#include <dbus/dbus-connection-internal.h>

#include "connection.h"
32
#include "driver.h"
33 34 35 36 37 38 39 40 41 42 43
#include "services.h"
#include "utils.h"

#ifdef DBUS_ENABLE_STATS

dbus_bool_t
bus_stats_handle_get_stats (DBusConnection *connection,
                            BusTransaction *transaction,
                            DBusMessage    *message,
                            DBusError      *error)
{
44
  BusContext *context;
45 46 47 48
  BusConnections *connections;
  DBusMessage *reply = NULL;
  DBusMessageIter iter, arr_iter;
  static dbus_uint32_t stats_serial = 0;
49
  dbus_uint32_t in_use, in_free_list, allocated;
50 51 52

  _DBUS_ASSERT_ERROR_IS_CLEAR (error);

53 54 55
  if (!bus_driver_check_message_is_for_us (message, error))
    return FALSE;

56 57
  context = bus_transaction_get_context (transaction);
  connections = bus_context_get_connections (context);
58

59
  reply = _dbus_asv_new_method_return (message, &iter, &arr_iter);
60 61 62 63

  if (reply == NULL)
    goto oom;

64 65
  /* Globals */

66 67
  _dbus_list_get_stats (&in_use, &in_free_list, &allocated);

68 69 70 71 72 73 74 75
  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;
    }
76 77 78

  /* Connections */

79
  if (!_dbus_asv_add_uint32 (&arr_iter, "ActiveConnections",
80
        bus_connections_get_n_active (connections)) ||
81
      !_dbus_asv_add_uint32 (&arr_iter, "IncompleteConnections",
82
        bus_connections_get_n_incomplete (connections)) ||
83
      !_dbus_asv_add_uint32 (&arr_iter, "MatchRules",
84
        bus_connections_get_total_match_rules (connections)) ||
85
      !_dbus_asv_add_uint32 (&arr_iter, "PeakMatchRules",
86
        bus_connections_get_peak_match_rules (connections)) ||
87
      !_dbus_asv_add_uint32 (&arr_iter, "PeakMatchRulesPerConnection",
88
        bus_connections_get_peak_match_rules_per_conn (connections)) ||
89
      !_dbus_asv_add_uint32 (&arr_iter, "BusNames",
90
        bus_connections_get_total_bus_names (connections)) ||
91
      !_dbus_asv_add_uint32 (&arr_iter, "PeakBusNames",
92
        bus_connections_get_peak_bus_names (connections)) ||
93
      !_dbus_asv_add_uint32 (&arr_iter, "PeakBusNamesPerConnection",
94
        bus_connections_get_peak_bus_names_per_conn (connections)))
95 96 97 98
    {
      _dbus_asv_abandon (&iter, &arr_iter);
      goto oom;
    }
99 100 101

  /* end */

102
  if (!_dbus_asv_close (&iter, &arr_iter))
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
    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;
130 131
  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;
132 133 134 135 136 137
  BusRegistry *registry;
  BusService *service;
  DBusConnection *stats_connection;

  _DBUS_ASSERT_ERROR_IS_CLEAR (error);

138 139 140
  if (!bus_driver_check_message_is_for_us (message, error))
    return FALSE;

141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
  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);

161
  reply = _dbus_asv_new_method_return (message, &iter, &arr_iter);
162 163 164 165

  if (reply == NULL)
    goto oom;

166 167
  /* Bus daemon per-connection stats */

168 169
  if (!_dbus_asv_add_uint32 (&arr_iter, "Serial", stats_serial++) ||
      !_dbus_asv_add_uint32 (&arr_iter, "MatchRules",
170
        bus_connection_get_n_match_rules (stats_connection)) ||
171
      !_dbus_asv_add_uint32 (&arr_iter, "PeakMatchRules",
172
        bus_connection_get_peak_match_rules (stats_connection)) ||
173
      !_dbus_asv_add_uint32 (&arr_iter, "BusNames",
174
        bus_connection_get_n_services_owned (stats_connection)) ||
175
      !_dbus_asv_add_uint32 (&arr_iter, "PeakBusNames",
176
        bus_connection_get_peak_bus_names (stats_connection)) ||
177
      !_dbus_asv_add_string (&arr_iter, "UniqueName",
178
        bus_connection_get_name (stats_connection)))
179 180 181 182
    {
      _dbus_asv_abandon (&iter, &arr_iter);
      goto oom;
    }
183

184 185 186 187
  /* DBusConnection per-connection stats */

  _dbus_connection_get_stats (stats_connection,
                              &in_messages, &in_bytes, &in_fds,
188 189
                              &in_peak_bytes, &in_peak_fds,
                              &out_messages, &out_bytes, &out_fds,
190
                              &out_peak_bytes, &out_peak_fds);
191

192 193 194 195 196 197 198 199 200 201 202 203 204 205
  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;
    }
206 207 208

  /* end */

209
  if (!_dbus_asv_close (&iter, &arr_iter))
210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227
    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