12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "dbus/dbus_statistics.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <set>
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/logging.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/memory/scoped_ptr.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/stl_util.h"
12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/threading/platform_thread.h"
14eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace dbus {
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Used to store dbus statistics sorted alphabetically by service, interface,
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// then method (using std::string <).
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct Stat {
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Stat(const std::string& service,
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       const std::string& interface,
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       const std::string& method)
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      : service(service),
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        interface(interface),
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        method(method),
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        sent_method_calls(0),
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        received_signals(0),
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        sent_blocking_method_calls(0) {
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string service;
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string interface;
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string method;
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int sent_method_calls;
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int received_signals;
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int sent_blocking_method_calls;
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool Compare(const Stat& other) const {
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (service != other.service)
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return service < other.service;
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (interface != other.interface)
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return interface < other.interface;
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return method < other.method;
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  struct PtrCompare {
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool operator()(Stat* lhs, Stat* rhs) const {
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      DCHECK(lhs && rhs);
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return lhs->Compare(*rhs);
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)typedef std::set<Stat*, Stat::PtrCompare> StatSet;
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//------------------------------------------------------------------------------
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// DBusStatistics
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Simple class for gathering DBus usage statistics.
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class DBusStatistics {
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DBusStatistics()
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      : start_time_(base::Time::Now()),
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        origin_thread_id_(base::PlatformThread::CurrentId()) {
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ~DBusStatistics() {
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK_EQ(origin_thread_id_, base::PlatformThread::CurrentId());
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    STLDeleteContainerPointers(stats_.begin(), stats_.end());
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Enum to specify which field in Stat to increment in AddStat
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  enum StatType {
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TYPE_SENT_METHOD_CALLS,
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TYPE_RECEIVED_SIGNALS,
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TYPE_SENT_BLOCKING_METHOD_CALLS
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Add a call to |method| for |interface|. See also MethodCall in message.h.
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void AddStat(const std::string& service,
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               const std::string& interface,
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               const std::string& method,
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               StatType type) {
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (base::PlatformThread::CurrentId() != origin_thread_id_) {
877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      DVLOG(1) << "Ignoring DBusStatistics::AddStat call from thread: "
887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch               << base::PlatformThread::CurrentId();
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Stat* stat = GetStat(service, interface, method, true);
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(stat);
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (type == TYPE_SENT_METHOD_CALLS)
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ++stat->sent_method_calls;
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    else if (type == TYPE_RECEIVED_SIGNALS)
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ++stat->received_signals;
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    else if (type == TYPE_SENT_BLOCKING_METHOD_CALLS)
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ++stat->sent_blocking_method_calls;
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    else
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      NOTREACHED();
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Look up the Stat entry in |stats_|. If |add_stat| is true, add a new entry
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // if one does not already exist.
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Stat* GetStat(const std::string& service,
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                const std::string& interface,
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                const std::string& method,
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                bool add_stat) {
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK_EQ(origin_thread_id_, base::PlatformThread::CurrentId());
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<Stat> stat(new Stat(service, interface, method));
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    StatSet::iterator found = stats_.find(stat.get());
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (found != stats_.end())
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return *found;
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!add_stat)
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return NULL;
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    found = stats_.insert(stat.release()).first;
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return *found;
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  StatSet& stats() { return stats_; }
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::Time start_time() { return start_time_; }
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  StatSet stats_;
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::Time start_time_;
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::PlatformThreadId origin_thread_id_;
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(DBusStatistics);
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DBusStatistics* g_dbus_statistics = NULL;
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//------------------------------------------------------------------------------
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace statistics {
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Initialize() {
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (g_dbus_statistics)
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    delete g_dbus_statistics;  // reset statistics
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  g_dbus_statistics = new DBusStatistics();
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Shutdown() {
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  delete g_dbus_statistics;
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  g_dbus_statistics = NULL;
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AddSentMethodCall(const std::string& service,
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       const std::string& interface,
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       const std::string& method) {
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!g_dbus_statistics)
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  g_dbus_statistics->AddStat(
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      service, interface, method, DBusStatistics::TYPE_SENT_METHOD_CALLS);
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AddReceivedSignal(const std::string& service,
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       const std::string& interface,
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       const std::string& method) {
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!g_dbus_statistics)
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  g_dbus_statistics->AddStat(
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      service, interface, method, DBusStatistics::TYPE_RECEIVED_SIGNALS);
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AddBlockingSentMethodCall(const std::string& service,
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               const std::string& interface,
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               const std::string& method) {
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!g_dbus_statistics)
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  g_dbus_statistics->AddStat(
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      service, interface, method,
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      DBusStatistics::TYPE_SENT_BLOCKING_METHOD_CALLS);
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// NOTE: If the output format is changed, be certain to change the test
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// expectations as well.
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)std::string GetAsString(ShowInString show, FormatString format) {
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!g_dbus_statistics)
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return "DBusStatistics not initialized.";
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const StatSet& stats = g_dbus_statistics->stats();
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (stats.empty())
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return "No DBus calls.";
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::TimeDelta dtime = base::Time::Now() - g_dbus_statistics->start_time();
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int dminutes = dtime.InMinutes();
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  dminutes = std::max(dminutes, 1);
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string result;
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int sent = 0, received = 0, sent_blocking = 0;
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Stats are stored in order by service, then interface, then method.
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (StatSet::const_iterator iter = stats.begin(); iter != stats.end(); ) {
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    StatSet::const_iterator cur_iter = iter;
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    StatSet::const_iterator next_iter = ++iter;
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const Stat* stat = *cur_iter;
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sent += stat->sent_method_calls;
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    received += stat->received_signals;
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sent_blocking += stat->sent_blocking_method_calls;
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // If this is not the last stat, and if the next stat matches the current
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // stat, continue.
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (next_iter != stats.end() &&
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        (*next_iter)->service == stat->service &&
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        (show < SHOW_INTERFACE || (*next_iter)->interface == stat->interface) &&
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        (show < SHOW_METHOD || (*next_iter)->method == stat->method))
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      continue;
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!sent && !received && !sent_blocking)
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        continue;  // No stats collected for this line, skip it and continue.
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Add a line to the result and clear the counts.
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string line;
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (show == SHOW_SERVICE) {
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      line += stat->service;
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // The interface usually includes the service so don't show both.
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      line += stat->interface;
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (show >= SHOW_METHOD)
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        line += "." + stat->method;
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    line += base::StringPrintf(":");
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (sent_blocking) {
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      line += base::StringPrintf(" Sent (BLOCKING):");
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (format == FORMAT_TOTALS)
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        line += base::StringPrintf(" %d", sent_blocking);
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      else if (format == FORMAT_PER_MINUTE)
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        line += base::StringPrintf(" %d/min", sent_blocking / dminutes);
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      else if (format == FORMAT_ALL)
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        line += base::StringPrintf(" %d (%d/min)",
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   sent_blocking, sent_blocking / dminutes);
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (sent) {
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      line += base::StringPrintf(" Sent:");
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (format == FORMAT_TOTALS)
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        line += base::StringPrintf(" %d", sent);
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      else if (format == FORMAT_PER_MINUTE)
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        line += base::StringPrintf(" %d/min", sent / dminutes);
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      else if (format == FORMAT_ALL)
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        line += base::StringPrintf(" %d (%d/min)", sent, sent / dminutes);
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (received) {
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      line += base::StringPrintf(" Received:");
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (format == FORMAT_TOTALS)
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        line += base::StringPrintf(" %d", received);
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      else if (format == FORMAT_PER_MINUTE)
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        line += base::StringPrintf(" %d/min", received / dminutes);
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      else if (format == FORMAT_ALL)
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        line += base::StringPrintf(
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            " %d (%d/min)", received, received / dminutes);
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    result += line + "\n";
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sent = 0;
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sent_blocking = 0;
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    received = 0;
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return result;
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace testing {
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool GetCalls(const std::string& service,
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              const std::string& interface,
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              const std::string& method,
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              int* sent,
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              int* received,
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              int* blocking) {
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!g_dbus_statistics)
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Stat* stat = g_dbus_statistics->GetStat(service, interface, method, false);
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!stat)
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *sent = stat->sent_method_calls;
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *received = stat->received_signals;
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *blocking = stat->sent_blocking_method_calls;
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace testing
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace statistics
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace dbus
284