Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2010 The Chromium OS Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium OS 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 "src/service.h" | 5 #include "src/service.h" |
| 6 | 6 |
| 7 #include <glog/logging.h> | 7 #include <glog/logging.h> |
| 8 | 8 |
| 9 #include "src/data_plan_provider.h" | 9 #include "src/data_plan_provider.h" |
| 10 #include "src/device.h" | 10 #include "src/device.h" |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 76 Service::Service(ServiceManager * const parent, | 76 Service::Service(ServiceManager * const parent, |
| 77 DBus::Connection& connection, // NOLINT | 77 DBus::Connection& connection, // NOLINT |
| 78 const DBus::Path& path) | 78 const DBus::Path& path) |
| 79 : DBus::ObjectProxy(connection, path, kFlimflamServiceName), | 79 : DBus::ObjectProxy(connection, path, kFlimflamServiceName), |
| 80 parent_(CHECK_NOTNULL(parent)), connection_(connection), path_(path), | 80 parent_(CHECK_NOTNULL(parent)), connection_(connection), path_(path), |
| 81 state_(kStateUnknown), type_(kTypeUnknown), device_(NULL), | 81 state_(kStateUnknown), type_(kTypeUnknown), device_(NULL), |
| 82 provider_(NULL), request_in_progress_(false), | 82 provider_(NULL), request_in_progress_(false), |
| 83 update_timeout_source_(NULL), policy_(NULL), | 83 update_timeout_source_(NULL), policy_(NULL), |
| 84 is_default_service_(false), get_properties_source_id_(0), | 84 is_default_service_(false), get_properties_source_id_(0), |
| 85 retrying_get_properties_(false), | 85 retrying_get_properties_(false), |
| 86 connectivity_state_(kConnectivityStateUnknown) { | 86 connectivity_state_(kConnectivityStateUnknown), |
| 87 deferred_device_deletion_source_id_(0) { | |
| 87 // schedule a GetProperties() call to our Flimflam service path to init state | 88 // schedule a GetProperties() call to our Flimflam service path to init state |
| 88 // we'll keep trying periodically until we succeed | 89 // we'll keep trying periodically until we succeed |
| 89 // we'll subsequently update this state by monitoring PropertyChanged signals | 90 // we'll subsequently update this state by monitoring PropertyChanged signals |
| 90 get_properties_source_id_ = | 91 get_properties_source_id_ = |
| 91 g_idle_add(StaticGetServicePropertiesCallback, this); | 92 g_idle_add(StaticGetServicePropertiesCallback, this); |
| 92 if (get_properties_source_id_ == 0) { | 93 if (get_properties_source_id_ == 0) { |
| 93 LOG(ERROR) << path_ << ": ctor: g_idle_add failed"; | 94 LOG(ERROR) << path_ << ": ctor: g_idle_add failed"; |
| 94 } | 95 } |
| 95 } | 96 } |
| 96 | 97 |
| 97 Service::~Service() { | 98 Service::~Service() { |
| 98 DeleteCarrierState(); | 99 DeleteCarrierState(); |
| 99 DeleteDataPlans(&data_plans_); | 100 DeleteDataPlans(&data_plans_); |
| 101 // ServiceManager ensures that this dtor is not being called from within a | |
| 102 // D-Bus callback, so it's ok to delete |device_| and any members of | |
| 103 // |devices_pending_deletion_| directly. | |
| 100 if (device_ != NULL) { | 104 if (device_ != NULL) { |
| 101 DLOG(INFO) << path_ << ": deleting device " << device_->GetPath(); | 105 DLOG(INFO) << path_ << ": dtor: deleting device " << device_->GetPath(); |
| 102 delete device_; | 106 delete device_; |
| 103 device_ = NULL; | 107 device_ = NULL; |
| 104 } | 108 } |
| 109 DeletePendingDevices(); | |
| 105 if (get_properties_source_id_ != 0 && | 110 if (get_properties_source_id_ != 0 && |
| 106 !g_source_remove(get_properties_source_id_)) { | 111 !g_source_remove(get_properties_source_id_)) { |
| 107 DLOG(WARNING) << path_ << ": dtor: g_source_remove failed"; | 112 DLOG(WARNING) << path_ << ": dtor: g_source_remove failed for source id " |
| 113 << get_properties_source_id_; | |
| 114 } | |
| 115 if (deferred_device_deletion_source_id_ != 0 && | |
| 116 !g_source_remove(deferred_device_deletion_source_id_)) { | |
| 117 DLOG(WARNING) << path_ << ": dtor: g_source_remove failed for source id " | |
| 118 << deferred_device_deletion_source_id_; | |
| 108 } | 119 } |
| 109 } | 120 } |
| 110 | 121 |
| 111 const DBus::Path& Service::GetPath() const { | 122 const DBus::Path& Service::GetPath() const { |
| 112 return path_; | 123 return path_; |
| 113 } | 124 } |
| 114 | 125 |
| 115 Service::State Service::GetState() const { | 126 Service::State Service::GetState() const { |
| 116 return state_; | 127 return state_; |
| 117 } | 128 } |
| (...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 443 } | 454 } |
| 444 | 455 |
| 445 bool Service::RetryingGetProperties() const { | 456 bool Service::RetryingGetProperties() const { |
| 446 return retrying_get_properties_; | 457 return retrying_get_properties_; |
| 447 } | 458 } |
| 448 | 459 |
| 449 void Service::OnRetryingGetProperties(bool retrying) { | 460 void Service::OnRetryingGetProperties(bool retrying) { |
| 450 retrying_get_properties_ = retrying; | 461 retrying_get_properties_ = retrying; |
| 451 } | 462 } |
| 452 | 463 |
| 464 guint Service::GetDeferredDeviceDeletionSourceId() const { | |
| 465 return deferred_device_deletion_source_id_; | |
| 466 } | |
| 467 | |
| 468 void Service::SetDeferredDeviceDeletionSourceId(guint source_id) { | |
| 469 deferred_device_deletion_source_id_ = source_id; | |
| 470 } | |
| 471 | |
| 453 // Private methods | 472 // Private methods |
| 454 | 473 |
| 474 void Service::DeletePendingDevices() { | |
| 475 while (!devices_pending_deletion_.empty()) { | |
| 476 Device *device = *(devices_pending_deletion_.begin()); | |
| 477 DCHECK(device != NULL); | |
| 478 DLOG(INFO) << path_ << ": DeletePendingDevices: deleting device: " | |
|
Daniel Kurtz
2010/11/24 02:33:47
Can you use __func__ or __FUNCTION__ instead of ty
Vince Laviano
2010/11/24 04:48:34
I'll look at doing this cashew-wide in the future.
| |
| 479 << device->GetPath(); | |
| 480 DCHECK(device != device_); | |
| 481 delete device; | |
| 482 devices_pending_deletion_.erase(devices_pending_deletion_.begin()); | |
| 483 } | |
| 484 } | |
| 485 | |
| 486 void Service::ScheduleDeviceForLaterDeletion(Device *device) { | |
| 487 DCHECK(device != NULL); | |
| 488 DCHECK(device != device_); | |
| 489 // We might be inside of a D-Bus callback. We add the device to our | |
| 490 // |devices_pending_deletion_| list and schedule a glib callback to | |
| 491 // delete these devices from the main loop if one is not already | |
| 492 // scheduled. | |
| 493 DLOG(INFO) << path_ << ": ScheduleDeviceForLaterDeletion: " | |
| 494 << device->GetPath(); | |
| 495 devices_pending_deletion_.push_back(device); | |
| 496 if (deferred_device_deletion_source_id_ != 0) { | |
| 497 DLOG(INFO) << path_ << ": ScheduleDeviceForLaterDeletion: " | |
| 498 << "deferred device deletion callback already scheduled"; | |
| 499 return; | |
| 500 } | |
| 501 deferred_device_deletion_source_id_ = | |
| 502 g_idle_add(StaticDeletePendingDevicesCallback, this); | |
| 503 if (deferred_device_deletion_source_id_ == 0) { | |
| 504 LOG(ERROR) << path_ | |
| 505 << ": ScheduleDeviceForLaterDeletion: g_idle_add failed"; | |
| 506 return; | |
| 507 } | |
| 508 DLOG(INFO) << path_ << ": ScheduleDeviceForLaterDeletion: " | |
| 509 << "scheduled deferred device deletion callback"; | |
| 510 } | |
| 511 | |
| 512 // static | |
| 513 gboolean Service::StaticDeletePendingDevicesCallback(gpointer data) { | |
| 514 Service *service = reinterpret_cast<Service*>(data); | |
| 515 CHECK_NOTNULL(service); | |
|
Daniel Kurtz
2010/11/24 02:33:47
DCHECK(service != NULL); ??
Vince Laviano
2010/11/24 04:48:34
Done.
| |
| 516 DCHECK_NE(service->GetDeferredDeviceDeletionSourceId(), 0); | |
| 517 service->DeletePendingDevices(); | |
| 518 // we don't want to be run again automatically | |
| 519 // ScheduleDeviceForLaterDeletion will schedule us as needed | |
| 520 service->SetDeferredDeviceDeletionSourceId(0); | |
| 521 return FALSE; | |
| 522 } | |
| 523 | |
| 455 // static | 524 // static |
| 456 Service::ConnectivityState Service::ConnectivityStateFromString( | 525 Service::ConnectivityState Service::ConnectivityStateFromString( |
| 457 const std::string& connectivity_state) { | 526 const std::string& connectivity_state) { |
| 458 if (connectivity_state == kFlimflamServiceConnectivityStateUnknown) { | 527 if (connectivity_state == kFlimflamServiceConnectivityStateUnknown) { |
| 459 return kConnectivityStateUnknown; | 528 return kConnectivityStateUnknown; |
| 460 } | 529 } |
| 461 if (connectivity_state == kFlimflamServiceConnectivityStateRestricted) { | 530 if (connectivity_state == kFlimflamServiceConnectivityStateRestricted) { |
| 462 return kConnectivityStateRestricted; | 531 return kConnectivityStateRestricted; |
| 463 } | 532 } |
| 464 if (connectivity_state == kFlimflamServiceConnectivityStateUnrestricted) { | 533 if (connectivity_state == kFlimflamServiceConnectivityStateUnrestricted) { |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 500 } | 569 } |
| 501 | 570 |
| 502 void Service::OnDeviceUpdate(const DBus::Path& device_path) { | 571 void Service::OnDeviceUpdate(const DBus::Path& device_path) { |
| 503 DLOG(INFO) << path_ << ": OnDeviceUpdate: device_path = " << device_path; | 572 DLOG(INFO) << path_ << ": OnDeviceUpdate: device_path = " << device_path; |
| 504 | 573 |
| 505 // if there's an existing device with a non-matching path: destroy it and | 574 // if there's an existing device with a non-matching path: destroy it and |
| 506 // fall through to make a new one below. | 575 // fall through to make a new one below. |
| 507 if (device_ != NULL && device_->GetPath() != device_path) { | 576 if (device_ != NULL && device_->GetPath() != device_path) { |
| 508 LOG(WARNING) << path_ << ": OnDeviceUpdate: device path changed from " | 577 LOG(WARNING) << path_ << ": OnDeviceUpdate: device path changed from " |
| 509 << device_->GetPath() << " to " << device_path; | 578 << device_->GetPath() << " to " << device_path; |
| 510 delete device_; | 579 // We might be in a D-Bus callback, so schedule device for later deletion |
| 580 // to avoid possible deadlock. See the comments in service_manager.h and | |
| 581 // service_manager.cc for more on this issue. | |
| 582 ScheduleDeviceForLaterDeletion(device_); | |
|
Daniel Kurtz
2010/11/24 02:33:47
save a ref to device_, then NULL device_, then Sch
Vince Laviano
2010/11/24 04:48:34
Done.
| |
| 511 device_ = NULL; | 583 device_ = NULL; |
| 512 } | 584 } |
| 513 | 585 |
| 514 // if there's an existing device with matching path: all is well | 586 // if there's an existing device with matching path: all is well |
| 515 if (device_ != NULL) { | 587 if (device_ != NULL) { |
| 516 return; | 588 return; |
| 517 } | 589 } |
| 518 | 590 |
| 519 // if there's no existing device: make one | 591 // if there's no existing device: make one |
| 520 device_ = new(std::nothrow) Device(this, connection_, device_path); | 592 device_ = new(std::nothrow) Device(this, connection_, device_path); |
| (...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 915 DCHECK(policy_ != NULL); | 987 DCHECK(policy_ != NULL); |
| 916 if (policy_->ShouldEmitDataPlansUpdate(data_plans_)) { | 988 if (policy_->ShouldEmitDataPlansUpdate(data_plans_)) { |
| 917 DLOG(INFO) << path_ << ": MaybeEmitDataPlansUpdate: sending update"; | 989 DLOG(INFO) << path_ << ": MaybeEmitDataPlansUpdate: sending update"; |
| 918 parent_->EmitDataPlansUpdate(*this); | 990 parent_->EmitDataPlansUpdate(*this); |
| 919 } else { | 991 } else { |
| 920 DLOG(INFO) << path_ << ": MaybeEmitDataPlansUpdate: not sending update"; | 992 DLOG(INFO) << path_ << ": MaybeEmitDataPlansUpdate: not sending update"; |
| 921 } | 993 } |
| 922 } | 994 } |
| 923 | 995 |
| 924 } // namespace cashew | 996 } // namespace cashew |
| OLD | NEW |