1ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat// Use of this source code is governed by a BSD-style license that can be
3ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat// found in the LICENSE file.
4ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat
5ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat#include "dbus/dbus_statistics.h"
6ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat
794ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez#include <memory>
8ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat#include <set>
9ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat
10ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat#include "base/logging.h"
110d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko#include "base/macros.h"
12ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat#include "base/stl_util.h"
13ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat#include "base/strings/stringprintf.h"
14ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat#include "base/threading/platform_thread.h"
15ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat#include "base/time/time.h"
16ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat
17ae6a045d2239408e25198ad17e2413bdde105788Daniel Eratnamespace dbus {
18ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat
19ae6a045d2239408e25198ad17e2413bdde105788Daniel Eratnamespace {
20ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat
21ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat// Used to store dbus statistics sorted alphabetically by service, interface,
22ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat// then method (using std::string <).
23ae6a045d2239408e25198ad17e2413bdde105788Daniel Eratstruct Stat {
24ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat  Stat(const std::string& service,
25ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat       const std::string& interface,
26ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat       const std::string& method)
27ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat      : service(service),
28ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat        interface(interface),
29ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat        method(method),
30ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat        sent_method_calls(0),
31ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat        received_signals(0),
32ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat        sent_blocking_method_calls(0) {
33ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat  }
34ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat  std::string service;
35ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat  std::string interface;
36ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat  std::string method;
37ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat  int sent_method_calls;
38ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat  int received_signals;
39ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat  int sent_blocking_method_calls;
40ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat
41ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat  bool Compare(const Stat& other) const {
42ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat    if (service != other.service)
43ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat      return service < other.service;
44ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat    if (interface != other.interface)
45ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat      return interface < other.interface;
46ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat    return method < other.method;
47ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat  }
48ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat
49ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat  struct PtrCompare {
50ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat    bool operator()(Stat* lhs, Stat* rhs) const {
51ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat      DCHECK(lhs && rhs);
52ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat      return lhs->Compare(*rhs);
53ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat    }
54ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat  };
55ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat};
56ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat
57ae6a045d2239408e25198ad17e2413bdde105788Daniel Erattypedef std::set<Stat*, Stat::PtrCompare> StatSet;
58ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat
59ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat//------------------------------------------------------------------------------
60ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat// DBusStatistics
61ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat
62ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat// Simple class for gathering DBus usage statistics.
63ae6a045d2239408e25198ad17e2413bdde105788Daniel Eratclass DBusStatistics {
64ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat public:
65ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat  DBusStatistics()
66ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat      : start_time_(base::Time::Now()),
67ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat        origin_thread_id_(base::PlatformThread::CurrentId()) {
68ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat  }
69ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat
70ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat  ~DBusStatistics() {
71ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat    DCHECK_EQ(origin_thread_id_, base::PlatformThread::CurrentId());
72ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat    STLDeleteContainerPointers(stats_.begin(), stats_.end());
73ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat  }
74ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat
75ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat  // Enum to specify which field in Stat to increment in AddStat
76ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat  enum StatType {
77ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat    TYPE_SENT_METHOD_CALLS,
78ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat    TYPE_RECEIVED_SIGNALS,
79ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat    TYPE_SENT_BLOCKING_METHOD_CALLS
80ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat  };
81ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat
82ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat  // Add a call to |method| for |interface|. See also MethodCall in message.h.
83ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat  void AddStat(const std::string& service,
84ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat               const std::string& interface,
85ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat               const std::string& method,
86ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat               StatType type) {
87ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat    if (base::PlatformThread::CurrentId() != origin_thread_id_) {
88ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat      DVLOG(1) << "Ignoring DBusStatistics::AddStat call from thread: "
89ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat               << base::PlatformThread::CurrentId();
90ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat      return;
91ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat    }
92ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat    Stat* stat = GetStat(service, interface, method, true);
93ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat    DCHECK(stat);
94ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat    if (type == TYPE_SENT_METHOD_CALLS)
95ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat      ++stat->sent_method_calls;
96ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat    else if (type == TYPE_RECEIVED_SIGNALS)
97ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat      ++stat->received_signals;
98ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat    else if (type == TYPE_SENT_BLOCKING_METHOD_CALLS)
99ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat      ++stat->sent_blocking_method_calls;
100ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat    else
101ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat      NOTREACHED();
102ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat  }
103ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat
104ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat  // Look up the Stat entry in |stats_|. If |add_stat| is true, add a new entry
105ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat  // if one does not already exist.
106ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat  Stat* GetStat(const std::string& service,
107ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat                const std::string& interface,
108ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat                const std::string& method,
109ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat                bool add_stat) {
110ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat    DCHECK_EQ(origin_thread_id_, base::PlatformThread::CurrentId());
11194ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez    std::unique_ptr<Stat> stat(new Stat(service, interface, method));
112ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat    StatSet::iterator found = stats_.find(stat.get());
113ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat    if (found != stats_.end())
114ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat      return *found;
115ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat    if (!add_stat)
116ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat      return NULL;
117ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat    found = stats_.insert(stat.release()).first;
118ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat    return *found;
119ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat  }
120ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat
121ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat  StatSet& stats() { return stats_; }
122ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat  base::Time start_time() { return start_time_; }
123ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat
124ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat private:
125ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat  StatSet stats_;
126ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat  base::Time start_time_;
127ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat  base::PlatformThreadId origin_thread_id_;
128ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat
129ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat  DISALLOW_COPY_AND_ASSIGN(DBusStatistics);
130ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat};
131ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat
132ae6a045d2239408e25198ad17e2413bdde105788Daniel EratDBusStatistics* g_dbus_statistics = NULL;
133ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat
134ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat}  // namespace
135ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat
136ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat//------------------------------------------------------------------------------
137ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat
138ae6a045d2239408e25198ad17e2413bdde105788Daniel Eratnamespace statistics {
139ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat
140ae6a045d2239408e25198ad17e2413bdde105788Daniel Eratvoid Initialize() {
141ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat  if (g_dbus_statistics)
142ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat    delete g_dbus_statistics;  // reset statistics
143ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat  g_dbus_statistics = new DBusStatistics();
144ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat}
145ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat
146ae6a045d2239408e25198ad17e2413bdde105788Daniel Eratvoid Shutdown() {
147ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat  delete g_dbus_statistics;
148ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat  g_dbus_statistics = NULL;
149ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat}
150ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat
151ae6a045d2239408e25198ad17e2413bdde105788Daniel Eratvoid AddSentMethodCall(const std::string& service,
152ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat                       const std::string& interface,
153ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat                       const std::string& method) {
154ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat  if (!g_dbus_statistics)
155ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat    return;
156ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat  g_dbus_statistics->AddStat(
157ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat      service, interface, method, DBusStatistics::TYPE_SENT_METHOD_CALLS);
158ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat}
159ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat
160ae6a045d2239408e25198ad17e2413bdde105788Daniel Eratvoid AddReceivedSignal(const std::string& service,
161ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat                       const std::string& interface,
162ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat                       const std::string& method) {
163ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat  if (!g_dbus_statistics)
164ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat    return;
165ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat  g_dbus_statistics->AddStat(
166ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat      service, interface, method, DBusStatistics::TYPE_RECEIVED_SIGNALS);
167ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat}
168ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat
169ae6a045d2239408e25198ad17e2413bdde105788Daniel Eratvoid AddBlockingSentMethodCall(const std::string& service,
170ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat                               const std::string& interface,
171ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat                               const std::string& method) {
172ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat  if (!g_dbus_statistics)
173ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat    return;
174ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat  g_dbus_statistics->AddStat(
175ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat      service, interface, method,
176ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat      DBusStatistics::TYPE_SENT_BLOCKING_METHOD_CALLS);
177ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat}
178ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat
179ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat// NOTE: If the output format is changed, be certain to change the test
180ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat// expectations as well.
181ae6a045d2239408e25198ad17e2413bdde105788Daniel Eratstd::string GetAsString(ShowInString show, FormatString format) {
182ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat  if (!g_dbus_statistics)
183ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat    return "DBusStatistics not initialized.";
184ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat
185ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat  const StatSet& stats = g_dbus_statistics->stats();
186ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat  if (stats.empty())
187ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat    return "No DBus calls.";
188ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat
189ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat  base::TimeDelta dtime = base::Time::Now() - g_dbus_statistics->start_time();
190ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat  int dminutes = dtime.InMinutes();
191ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat  dminutes = std::max(dminutes, 1);
192ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat
193ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat  std::string result;
194ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat  int sent = 0, received = 0, sent_blocking = 0;
195ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat  // Stats are stored in order by service, then interface, then method.
196ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat  for (StatSet::const_iterator iter = stats.begin(); iter != stats.end(); ) {
197ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat    StatSet::const_iterator cur_iter = iter;
198ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat    StatSet::const_iterator next_iter = ++iter;
199ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat    const Stat* stat = *cur_iter;
200ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat    sent += stat->sent_method_calls;
201ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat    received += stat->received_signals;
202ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat    sent_blocking += stat->sent_blocking_method_calls;
203ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat    // If this is not the last stat, and if the next stat matches the current
204ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat    // stat, continue.
205ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat    if (next_iter != stats.end() &&
206ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat        (*next_iter)->service == stat->service &&
207ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat        (show < SHOW_INTERFACE || (*next_iter)->interface == stat->interface) &&
208ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat        (show < SHOW_METHOD || (*next_iter)->method == stat->method))
209ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat      continue;
210ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat
211ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat    if (!sent && !received && !sent_blocking)
212ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat        continue;  // No stats collected for this line, skip it and continue.
213ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat
214ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat    // Add a line to the result and clear the counts.
215ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat    std::string line;
216ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat    if (show == SHOW_SERVICE) {
217ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat      line += stat->service;
218ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat    } else {
219ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat      // The interface usually includes the service so don't show both.
220ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat      line += stat->interface;
221ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat      if (show >= SHOW_METHOD)
222ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat        line += "." + stat->method;
223ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat    }
224ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat    line += base::StringPrintf(":");
225ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat    if (sent_blocking) {
226ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat      line += base::StringPrintf(" Sent (BLOCKING):");
227ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat      if (format == FORMAT_TOTALS)
228ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat        line += base::StringPrintf(" %d", sent_blocking);
229ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat      else if (format == FORMAT_PER_MINUTE)
230ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat        line += base::StringPrintf(" %d/min", sent_blocking / dminutes);
231ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat      else if (format == FORMAT_ALL)
232ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat        line += base::StringPrintf(" %d (%d/min)",
233ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat                                   sent_blocking, sent_blocking / dminutes);
234ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat    }
235ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat    if (sent) {
236ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat      line += base::StringPrintf(" Sent:");
237ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat      if (format == FORMAT_TOTALS)
238ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat        line += base::StringPrintf(" %d", sent);
239ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat      else if (format == FORMAT_PER_MINUTE)
240ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat        line += base::StringPrintf(" %d/min", sent / dminutes);
241ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat      else if (format == FORMAT_ALL)
242ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat        line += base::StringPrintf(" %d (%d/min)", sent, sent / dminutes);
243ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat    }
244ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat    if (received) {
245ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat      line += base::StringPrintf(" Received:");
246ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat      if (format == FORMAT_TOTALS)
247ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat        line += base::StringPrintf(" %d", received);
248ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat      else if (format == FORMAT_PER_MINUTE)
249ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat        line += base::StringPrintf(" %d/min", received / dminutes);
250ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat      else if (format == FORMAT_ALL)
251ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat        line += base::StringPrintf(
252ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat            " %d (%d/min)", received, received / dminutes);
253ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat    }
254ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat    result += line + "\n";
255ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat    sent = 0;
256ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat    sent_blocking = 0;
257ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat    received = 0;
258ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat  }
259ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat  return result;
260ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat}
261ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat
262ae6a045d2239408e25198ad17e2413bdde105788Daniel Eratnamespace testing {
263ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat
264ae6a045d2239408e25198ad17e2413bdde105788Daniel Eratbool GetCalls(const std::string& service,
265ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat              const std::string& interface,
266ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat              const std::string& method,
267ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat              int* sent,
268ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat              int* received,
269ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat              int* blocking) {
270ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat  if (!g_dbus_statistics)
271ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat    return false;
272ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat  Stat* stat = g_dbus_statistics->GetStat(service, interface, method, false);
273ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat  if (!stat)
274ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat    return false;
275ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat  *sent = stat->sent_method_calls;
276ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat  *received = stat->received_signals;
277ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat  *blocking = stat->sent_blocking_method_calls;
278ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat  return true;
279ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat}
280ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat
281ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat}  // namespace testing
282ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat
283ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat}  // namespace statistics
284ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat}  // namespace dbus
285