Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(61)

Side by Side Diff: dbus/object_proxy.cc

Issue 7824054: Add some histograms to the D-Bus library: (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rate->ratio Created 9 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « dbus/object_proxy.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "dbus/bus.h" 5 #include "dbus/bus.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/logging.h" 8 #include "base/logging.h"
9 #include "base/message_loop.h" 9 #include "base/message_loop.h"
10 #include "base/metrics/histogram.h"
10 #include "base/stringprintf.h" 11 #include "base/stringprintf.h"
11 #include "base/threading/thread.h" 12 #include "base/threading/thread.h"
12 #include "base/threading/thread_restrictions.h" 13 #include "base/threading/thread_restrictions.h"
13 #include "dbus/message.h" 14 #include "dbus/message.h"
14 #include "dbus/object_proxy.h" 15 #include "dbus/object_proxy.h"
15 #include "dbus/scoped_dbus_error.h" 16 #include "dbus/scoped_dbus_error.h"
16 17
17 namespace { 18 namespace {
18 19
20 // Used for success ratio histograms. 1 for success, 0 for failure.
21 const int kSuccessRatioHistogramMaxValue = 2;
22
19 // Gets the absolute signal name by concatenating the interface name and 23 // Gets the absolute signal name by concatenating the interface name and
20 // the signal name. Used for building keys for method_table_ in 24 // the signal name. Used for building keys for method_table_ in
21 // ObjectProxy. 25 // ObjectProxy.
22 std::string GetAbsoluteSignalName( 26 std::string GetAbsoluteSignalName(
23 const std::string& interface_name, 27 const std::string& interface_name,
24 const std::string& signal_name) { 28 const std::string& signal_name) {
25 return interface_name + "." + signal_name; 29 return interface_name + "." + signal_name;
26 } 30 }
27 31
28 } // namespace 32 } // namespace
(...skipping 22 matching lines...) Expand all
51 if (!bus_->Connect()) 55 if (!bus_->Connect())
52 return NULL; 56 return NULL;
53 57
54 method_call->SetDestination(service_name_); 58 method_call->SetDestination(service_name_);
55 method_call->SetPath(object_path_); 59 method_call->SetPath(object_path_);
56 DBusMessage* request_message = method_call->raw_message(); 60 DBusMessage* request_message = method_call->raw_message();
57 61
58 ScopedDBusError error; 62 ScopedDBusError error;
59 63
60 // Send the message synchronously. 64 // Send the message synchronously.
65 const base::TimeTicks start_time = base::TimeTicks::Now();
61 DBusMessage* response_message = 66 DBusMessage* response_message =
62 bus_->SendWithReplyAndBlock(request_message, timeout_ms, error.get()); 67 bus_->SendWithReplyAndBlock(request_message, timeout_ms, error.get());
68 // Record if the method call is successful, or not. 1 if successful.
69 UMA_HISTOGRAM_ENUMERATION("DBus.SyncMethodCallSuccess",
70 response_message ? 1 : 0,
71 kSuccessRatioHistogramMaxValue);
63 72
64 if (!response_message) { 73 if (!response_message) {
65 LOG(ERROR) << "Failed to call method: " 74 LOG(ERROR) << "Failed to call method: "
66 << (error.is_set() ? error.message() : ""); 75 << (error.is_set() ? error.message() : "");
67 return NULL; 76 return NULL;
68 } 77 }
78 // Record time spent for the method call. Don't include failures.
79 UMA_HISTOGRAM_TIMES("DBus.SyncMethodCallTime",
80 base::TimeTicks::Now() - start_time);
69 81
70 return Response::FromRawMessage(response_message); 82 return Response::FromRawMessage(response_message);
71 } 83 }
72 84
73 void ObjectProxy::CallMethod(MethodCall* method_call, 85 void ObjectProxy::CallMethod(MethodCall* method_call,
74 int timeout_ms, 86 int timeout_ms,
75 ResponseCallback callback) { 87 ResponseCallback callback) {
76 bus_->AssertOnOriginThread(); 88 bus_->AssertOnOriginThread();
77 89
78 method_call->SetDestination(service_name_); 90 method_call->SetDestination(service_name_);
79 method_call->SetPath(object_path_); 91 method_call->SetPath(object_path_);
80 // Increment the reference count so we can safely reference the 92 // Increment the reference count so we can safely reference the
81 // underlying request message until the method call is complete. This 93 // underlying request message until the method call is complete. This
82 // will be unref'ed in StartAsyncMethodCall(). 94 // will be unref'ed in StartAsyncMethodCall().
83 DBusMessage* request_message = method_call->raw_message(); 95 DBusMessage* request_message = method_call->raw_message();
84 dbus_message_ref(request_message); 96 dbus_message_ref(request_message);
85 97
86 // Bind() won't compile if we pass request_message as-is since 98 // Bind() won't compile if we pass request_message as-is since
87 // DBusMessage is an opaque struct which Bind() cannot handle. 99 // DBusMessage is an opaque struct which Bind() cannot handle.
88 // Hence we cast it to void* to workaround the issue. 100 // Hence we cast it to void* to workaround the issue.
101 const base::TimeTicks start_time = base::TimeTicks::Now();
89 base::Closure task = base::Bind(&ObjectProxy::StartAsyncMethodCall, 102 base::Closure task = base::Bind(&ObjectProxy::StartAsyncMethodCall,
90 this, 103 this,
91 timeout_ms, 104 timeout_ms,
92 static_cast<void*>(request_message), 105 static_cast<void*>(request_message),
93 callback); 106 callback,
107 start_time);
94 // Wait for the response in the D-Bus thread. 108 // Wait for the response in the D-Bus thread.
95 bus_->PostTaskToDBusThread(FROM_HERE, task); 109 bus_->PostTaskToDBusThread(FROM_HERE, task);
96 } 110 }
97 111
98 void ObjectProxy::ConnectToSignal(const std::string& interface_name, 112 void ObjectProxy::ConnectToSignal(const std::string& interface_name,
99 const std::string& signal_name, 113 const std::string& signal_name,
100 SignalCallback signal_callback, 114 SignalCallback signal_callback,
101 OnConnectedCallback on_connected_callback) { 115 OnConnectedCallback on_connected_callback) {
102 bus_->AssertOnOriginThread(); 116 bus_->AssertOnOriginThread();
103 117
(...skipping 17 matching lines...) Expand all
121 bus_->RemoveMatch(match_rules_[i], error.get()); 135 bus_->RemoveMatch(match_rules_[i], error.get());
122 if (error.is_set()) { 136 if (error.is_set()) {
123 // There is nothing we can do to recover, so just print the error. 137 // There is nothing we can do to recover, so just print the error.
124 LOG(ERROR) << "Failed to remove match rule: " << match_rules_[i]; 138 LOG(ERROR) << "Failed to remove match rule: " << match_rules_[i];
125 } 139 }
126 } 140 }
127 } 141 }
128 142
129 ObjectProxy::OnPendingCallIsCompleteData::OnPendingCallIsCompleteData( 143 ObjectProxy::OnPendingCallIsCompleteData::OnPendingCallIsCompleteData(
130 ObjectProxy* in_object_proxy, 144 ObjectProxy* in_object_proxy,
131 ResponseCallback in_response_callback) 145 ResponseCallback in_response_callback,
146 base::TimeTicks in_start_time)
132 : object_proxy(in_object_proxy), 147 : object_proxy(in_object_proxy),
133 response_callback(in_response_callback) { 148 response_callback(in_response_callback),
149 start_time(in_start_time) {
134 } 150 }
135 151
136 ObjectProxy::OnPendingCallIsCompleteData::~OnPendingCallIsCompleteData() { 152 ObjectProxy::OnPendingCallIsCompleteData::~OnPendingCallIsCompleteData() {
137 } 153 }
138 154
139 void ObjectProxy::StartAsyncMethodCall(int timeout_ms, 155 void ObjectProxy::StartAsyncMethodCall(int timeout_ms,
140 void* in_request_message, 156 void* in_request_message,
141 ResponseCallback response_callback) { 157 ResponseCallback response_callback,
158 base::TimeTicks start_time) {
142 bus_->AssertOnDBusThread(); 159 bus_->AssertOnDBusThread();
143 160
144 if (!bus_->Connect() || !bus_->SetUpAsyncOperations()) { 161 if (!bus_->Connect() || !bus_->SetUpAsyncOperations()) {
145 // In case of a failure, run the callback with NULL response, that 162 // In case of a failure, run the callback with NULL response, that
146 // indicates a failure. 163 // indicates a failure.
147 Response* response = NULL; 164 Response* response = NULL;
148 base::Closure task = base::Bind(&ObjectProxy::RunResponseCallback, 165 base::Closure task = base::Bind(&ObjectProxy::RunResponseCallback,
149 this, 166 this,
150 response_callback, 167 response_callback,
168 start_time,
151 response); 169 response);
152 bus_->PostTaskToOriginThread(FROM_HERE, task); 170 bus_->PostTaskToOriginThread(FROM_HERE, task);
153 return; 171 return;
154 } 172 }
155 173
156 DBusMessage* request_message = 174 DBusMessage* request_message =
157 static_cast<DBusMessage*>(in_request_message); 175 static_cast<DBusMessage*>(in_request_message);
158 DBusPendingCall* pending_call = NULL; 176 DBusPendingCall* pending_call = NULL;
159 177
160 bus_->SendWithReply(request_message, &pending_call, timeout_ms); 178 bus_->SendWithReply(request_message, &pending_call, timeout_ms);
161 179
162 // Prepare the data we'll be passing to OnPendingCallIsCompleteThunk(). 180 // Prepare the data we'll be passing to OnPendingCallIsCompleteThunk().
163 // The data will be deleted in OnPendingCallIsCompleteThunk(). 181 // The data will be deleted in OnPendingCallIsCompleteThunk().
164 OnPendingCallIsCompleteData* data = 182 OnPendingCallIsCompleteData* data =
165 new OnPendingCallIsCompleteData(this, response_callback); 183 new OnPendingCallIsCompleteData(this, response_callback, start_time);
166 184
167 // This returns false only when unable to allocate memory. 185 // This returns false only when unable to allocate memory.
168 const bool success = dbus_pending_call_set_notify( 186 const bool success = dbus_pending_call_set_notify(
169 pending_call, 187 pending_call,
170 &ObjectProxy::OnPendingCallIsCompleteThunk, 188 &ObjectProxy::OnPendingCallIsCompleteThunk,
171 data, 189 data,
172 NULL); 190 NULL);
173 CHECK(success) << "Unable to allocate memory"; 191 CHECK(success) << "Unable to allocate memory";
174 dbus_pending_call_unref(pending_call); 192 dbus_pending_call_unref(pending_call);
175 193
176 // It's now safe to unref the request message. 194 // It's now safe to unref the request message.
177 dbus_message_unref(request_message); 195 dbus_message_unref(request_message);
178 } 196 }
179 197
180 void ObjectProxy::OnPendingCallIsComplete(DBusPendingCall* pending_call, 198 void ObjectProxy::OnPendingCallIsComplete(DBusPendingCall* pending_call,
181 ResponseCallback response_callback) { 199 ResponseCallback response_callback,
200 base::TimeTicks start_time) {
182 bus_->AssertOnDBusThread(); 201 bus_->AssertOnDBusThread();
183 202
184 DBusMessage* response_message = dbus_pending_call_steal_reply(pending_call); 203 DBusMessage* response_message = dbus_pending_call_steal_reply(pending_call);
185 // |response_message| will be unref'ed in RunResponseCallback(). 204 // |response_message| will be unref'ed in RunResponseCallback().
186 // Bind() won't compile if we pass response_message as-is. 205 // Bind() won't compile if we pass response_message as-is.
187 // See CallMethod() for details. 206 // See CallMethod() for details.
188 base::Closure task = base::Bind(&ObjectProxy::RunResponseCallback, 207 base::Closure task = base::Bind(&ObjectProxy::RunResponseCallback,
189 this, 208 this,
190 response_callback, 209 response_callback,
210 start_time,
191 static_cast<void*>(response_message)); 211 static_cast<void*>(response_message));
192 bus_->PostTaskToOriginThread(FROM_HERE, task); 212 bus_->PostTaskToOriginThread(FROM_HERE, task);
193 } 213 }
194 214
195 void ObjectProxy::RunResponseCallback(ResponseCallback response_callback, 215 void ObjectProxy::RunResponseCallback(ResponseCallback response_callback,
216 base::TimeTicks start_time,
196 void* in_response_message) { 217 void* in_response_message) {
197 bus_->AssertOnOriginThread(); 218 bus_->AssertOnOriginThread();
198 DBusMessage* response_message = 219 DBusMessage* response_message =
199 static_cast<DBusMessage*>(in_response_message); 220 static_cast<DBusMessage*>(in_response_message);
200 221
222 bool response_callback_called = false;
201 if (!response_message) { 223 if (!response_message) {
202 // The response is not received. 224 // The response is not received.
203 response_callback.Run(NULL); 225 response_callback.Run(NULL);
204 } else if (dbus_message_get_type(response_message) == 226 } else if (dbus_message_get_type(response_message) ==
205 DBUS_MESSAGE_TYPE_ERROR) { 227 DBUS_MESSAGE_TYPE_ERROR) {
206 // This will take |response_message| and release (unref) it. 228 // This will take |response_message| and release (unref) it.
207 scoped_ptr<dbus::ErrorResponse> error_response( 229 scoped_ptr<dbus::ErrorResponse> error_response(
208 dbus::ErrorResponse::FromRawMessage(response_message)); 230 dbus::ErrorResponse::FromRawMessage(response_message));
209 // Error message may contain the error message as string. 231 // Error message may contain the error message as string.
210 dbus::MessageReader reader(error_response.get()); 232 dbus::MessageReader reader(error_response.get());
211 std::string error_message; 233 std::string error_message;
212 reader.PopString(&error_message); 234 reader.PopString(&error_message);
213 LOG(ERROR) << "Failed to call method: " << error_response->GetErrorName() 235 LOG(ERROR) << "Failed to call method: " << error_response->GetErrorName()
214 << ": " << error_message; 236 << ": " << error_message;
215 // We don't give the error message to the callback. 237 // We don't give the error message to the callback.
216 response_callback.Run(NULL); 238 response_callback.Run(NULL);
217 } else { 239 } else {
218 // This will take |response_message| and release (unref) it. 240 // This will take |response_message| and release (unref) it.
219 scoped_ptr<dbus::Response> response( 241 scoped_ptr<dbus::Response> response(
220 dbus::Response::FromRawMessage(response_message)); 242 dbus::Response::FromRawMessage(response_message));
221 // The response is successfully received. 243 // The response is successfully received.
222 response_callback.Run(response.get()); 244 response_callback.Run(response.get());
245 response_callback_called = true;
246 // Record time spent for the method call. Don't include failures.
247 UMA_HISTOGRAM_TIMES("DBus.AsyncMethodCallTime",
248 base::TimeTicks::Now() - start_time);
223 } 249 }
250 // Record if the method call is successful, or not. 1 if successful.
251 UMA_HISTOGRAM_ENUMERATION("DBus.AsyncMethodCallSuccess",
252 response_callback_called,
253 kSuccessRatioHistogramMaxValue);
224 } 254 }
225 255
226 void ObjectProxy::OnPendingCallIsCompleteThunk(DBusPendingCall* pending_call, 256 void ObjectProxy::OnPendingCallIsCompleteThunk(DBusPendingCall* pending_call,
227 void* user_data) { 257 void* user_data) {
228 OnPendingCallIsCompleteData* data = 258 OnPendingCallIsCompleteData* data =
229 reinterpret_cast<OnPendingCallIsCompleteData*>(user_data); 259 reinterpret_cast<OnPendingCallIsCompleteData*>(user_data);
230 ObjectProxy* self = data->object_proxy; 260 ObjectProxy* self = data->object_proxy;
231 self->OnPendingCallIsComplete(pending_call, 261 self->OnPendingCallIsComplete(pending_call,
232 data->response_callback); 262 data->response_callback,
263 data->start_time);
233 delete data; 264 delete data;
234 } 265 }
235 266
236 void ObjectProxy::ConnectToSignalInternal( 267 void ObjectProxy::ConnectToSignalInternal(
237 const std::string& interface_name, 268 const std::string& interface_name,
238 const std::string& signal_name, 269 const std::string& signal_name,
239 SignalCallback signal_callback, 270 SignalCallback signal_callback,
240 OnConnectedCallback on_connected_callback) { 271 OnConnectedCallback on_connected_callback) {
241 bus_->AssertOnDBusThread(); 272 bus_->AssertOnDBusThread();
242 273
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
310 scoped_ptr<Signal> signal( 341 scoped_ptr<Signal> signal(
311 Signal::FromRawMessage(raw_message)); 342 Signal::FromRawMessage(raw_message));
312 343
313 // The signal is not coming from the remote object we are attaching to. 344 // The signal is not coming from the remote object we are attaching to.
314 if (signal->GetPath() != object_path_) 345 if (signal->GetPath() != object_path_)
315 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 346 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
316 347
317 const std::string interface = signal->GetInterface(); 348 const std::string interface = signal->GetInterface();
318 const std::string member = signal->GetMember(); 349 const std::string member = signal->GetMember();
319 350
320 // Check if we know about the method. 351 // Check if we know about the signal.
321 const std::string absolute_signal_name = GetAbsoluteSignalName( 352 const std::string absolute_signal_name = GetAbsoluteSignalName(
322 interface, member); 353 interface, member);
323 MethodTable::const_iterator iter = method_table_.find(absolute_signal_name); 354 MethodTable::const_iterator iter = method_table_.find(absolute_signal_name);
324 if (iter == method_table_.end()) { 355 if (iter == method_table_.end()) {
325 // Don't know about the method. 356 // Don't know about the signal.
326 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 357 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
327 } 358 }
328 359
360 const base::TimeTicks start_time = base::TimeTicks::Now();
329 if (bus_->HasDBusThread()) { 361 if (bus_->HasDBusThread()) {
330 // Post a task to run the method in the origin thread. 362 // Post a task to run the method in the origin thread.
331 // Transfer the ownership of |signal| to RunMethod(). 363 // Transfer the ownership of |signal| to RunMethod().
332 // |released_signal| will be deleted in RunMethod(). 364 // |released_signal| will be deleted in RunMethod().
333 Signal* released_signal = signal.release(); 365 Signal* released_signal = signal.release();
334 bus_->PostTaskToOriginThread(FROM_HERE, 366 bus_->PostTaskToOriginThread(FROM_HERE,
335 base::Bind(&ObjectProxy::RunMethod, 367 base::Bind(&ObjectProxy::RunMethod,
336 this, 368 this,
369 start_time,
337 iter->second, 370 iter->second,
338 released_signal)); 371 released_signal));
339 } else { 372 } else {
340 // If the D-Bus thread is not used, just call the method directly. We 373 const base::TimeTicks start_time = base::TimeTicks::Now();
341 // don't need the complicated logic to wait for the method call to be 374 // If the D-Bus thread is not used, just call the callback on the
342 // complete. 375 // current thread. Transfer the ownership of |signal| to RunMethod().
343 iter->second.Run(signal.get()); 376 Signal* released_signal = signal.release();
377 RunMethod(start_time, iter->second, released_signal);
344 } 378 }
345 379
346 return DBUS_HANDLER_RESULT_HANDLED; 380 return DBUS_HANDLER_RESULT_HANDLED;
347 } 381 }
348 382
349 void ObjectProxy::RunMethod(SignalCallback signal_callback, 383 void ObjectProxy::RunMethod(base::TimeTicks start_time,
384 SignalCallback signal_callback,
350 Signal* signal) { 385 Signal* signal) {
351 bus_->AssertOnOriginThread(); 386 bus_->AssertOnOriginThread();
352 387
353 signal_callback.Run(signal); 388 signal_callback.Run(signal);
354 delete signal; 389 delete signal;
390 // Record time spent for handling the signal.
391 UMA_HISTOGRAM_TIMES("DBus.SignalHandleTime",
392 base::TimeTicks::Now() - start_time);
355 } 393 }
356 394
357 DBusHandlerResult ObjectProxy::HandleMessageThunk( 395 DBusHandlerResult ObjectProxy::HandleMessageThunk(
358 DBusConnection* connection, 396 DBusConnection* connection,
359 DBusMessage* raw_message, 397 DBusMessage* raw_message,
360 void* user_data) { 398 void* user_data) {
361 ObjectProxy* self = reinterpret_cast<ObjectProxy*>(user_data); 399 ObjectProxy* self = reinterpret_cast<ObjectProxy*>(user_data);
362 return self->HandleMessage(connection, raw_message); 400 return self->HandleMessage(connection, raw_message);
363 } 401 }
364 402
365 } // namespace dbus 403 } // namespace dbus
OLDNEW
« no previous file with comments | « dbus/object_proxy.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698