1*1a96fba6SXin Li // Copyright 2014 The Chromium OS Authors. All rights reserved.
2*1a96fba6SXin Li // Use of this source code is governed by a BSD-style license that can be
3*1a96fba6SXin Li // found in the LICENSE file.
4*1a96fba6SXin Li
5*1a96fba6SXin Li #include <brillo/dbus/async_event_sequencer.h>
6*1a96fba6SXin Li
7*1a96fba6SXin Li #include <base/bind.h>
8*1a96fba6SXin Li #include <base/callback.h>
9*1a96fba6SXin Li
10*1a96fba6SXin Li namespace brillo {
11*1a96fba6SXin Li
12*1a96fba6SXin Li namespace dbus_utils {
13*1a96fba6SXin Li
AsyncEventSequencer()14*1a96fba6SXin Li AsyncEventSequencer::AsyncEventSequencer() {
15*1a96fba6SXin Li }
~AsyncEventSequencer()16*1a96fba6SXin Li AsyncEventSequencer::~AsyncEventSequencer() {
17*1a96fba6SXin Li }
18*1a96fba6SXin Li
GetHandler(const std::string & descriptive_message,bool failure_is_fatal)19*1a96fba6SXin Li AsyncEventSequencer::Handler AsyncEventSequencer::GetHandler(
20*1a96fba6SXin Li const std::string& descriptive_message,
21*1a96fba6SXin Li bool failure_is_fatal) {
22*1a96fba6SXin Li CHECK(!started_) << "Cannot create handlers after OnAllTasksCompletedCall()";
23*1a96fba6SXin Li int unique_registration_id = ++registration_counter_;
24*1a96fba6SXin Li outstanding_registrations_.insert(unique_registration_id);
25*1a96fba6SXin Li return base::Bind(&AsyncEventSequencer::HandleFinish,
26*1a96fba6SXin Li this,
27*1a96fba6SXin Li unique_registration_id,
28*1a96fba6SXin Li descriptive_message,
29*1a96fba6SXin Li failure_is_fatal);
30*1a96fba6SXin Li }
31*1a96fba6SXin Li
GetExportHandler(const std::string & interface_name,const std::string & method_name,const std::string & descriptive_message,bool failure_is_fatal)32*1a96fba6SXin Li AsyncEventSequencer::ExportHandler AsyncEventSequencer::GetExportHandler(
33*1a96fba6SXin Li const std::string& interface_name,
34*1a96fba6SXin Li const std::string& method_name,
35*1a96fba6SXin Li const std::string& descriptive_message,
36*1a96fba6SXin Li bool failure_is_fatal) {
37*1a96fba6SXin Li auto finish_handler = GetHandler(descriptive_message, failure_is_fatal);
38*1a96fba6SXin Li return base::Bind(&AsyncEventSequencer::HandleDBusMethodExported,
39*1a96fba6SXin Li this,
40*1a96fba6SXin Li finish_handler,
41*1a96fba6SXin Li interface_name,
42*1a96fba6SXin Li method_name);
43*1a96fba6SXin Li }
44*1a96fba6SXin Li
OnAllTasksCompletedCall(std::vector<CompletionAction> actions)45*1a96fba6SXin Li void AsyncEventSequencer::OnAllTasksCompletedCall(
46*1a96fba6SXin Li std::vector<CompletionAction> actions) {
47*1a96fba6SXin Li CHECK(!started_) << "OnAllTasksCompletedCall called twice!";
48*1a96fba6SXin Li started_ = true;
49*1a96fba6SXin Li completion_actions_.assign(actions.begin(), actions.end());
50*1a96fba6SXin Li // All of our callbacks might have been called already.
51*1a96fba6SXin Li PossiblyRunCompletionActions();
52*1a96fba6SXin Li }
53*1a96fba6SXin Li
54*1a96fba6SXin Li namespace {
IgnoreSuccess(const AsyncEventSequencer::CompletionTask & task,bool)55*1a96fba6SXin Li void IgnoreSuccess(const AsyncEventSequencer::CompletionTask& task,
56*1a96fba6SXin Li bool /*success*/) {
57*1a96fba6SXin Li task.Run();
58*1a96fba6SXin Li }
DoNothing(bool)59*1a96fba6SXin Li void DoNothing(bool /* success */) {
60*1a96fba6SXin Li }
61*1a96fba6SXin Li } // namespace
62*1a96fba6SXin Li
WrapCompletionTask(const CompletionTask & task)63*1a96fba6SXin Li AsyncEventSequencer::CompletionAction AsyncEventSequencer::WrapCompletionTask(
64*1a96fba6SXin Li const CompletionTask& task) {
65*1a96fba6SXin Li return base::Bind(&IgnoreSuccess, task);
66*1a96fba6SXin Li }
67*1a96fba6SXin Li
68*1a96fba6SXin Li AsyncEventSequencer::CompletionAction
GetDefaultCompletionAction()69*1a96fba6SXin Li AsyncEventSequencer::GetDefaultCompletionAction() {
70*1a96fba6SXin Li return base::Bind(&DoNothing);
71*1a96fba6SXin Li }
72*1a96fba6SXin Li
HandleFinish(int registration_number,const std::string & error_message,bool failure_is_fatal,bool success)73*1a96fba6SXin Li void AsyncEventSequencer::HandleFinish(int registration_number,
74*1a96fba6SXin Li const std::string& error_message,
75*1a96fba6SXin Li bool failure_is_fatal,
76*1a96fba6SXin Li bool success) {
77*1a96fba6SXin Li RetireRegistration(registration_number);
78*1a96fba6SXin Li CheckForFailure(failure_is_fatal, success, error_message);
79*1a96fba6SXin Li PossiblyRunCompletionActions();
80*1a96fba6SXin Li }
81*1a96fba6SXin Li
HandleDBusMethodExported(const AsyncEventSequencer::Handler & finish_handler,const std::string & expected_interface_name,const std::string & expected_method_name,const std::string & actual_interface_name,const std::string & actual_method_name,bool success)82*1a96fba6SXin Li void AsyncEventSequencer::HandleDBusMethodExported(
83*1a96fba6SXin Li const AsyncEventSequencer::Handler& finish_handler,
84*1a96fba6SXin Li const std::string& expected_interface_name,
85*1a96fba6SXin Li const std::string& expected_method_name,
86*1a96fba6SXin Li const std::string& actual_interface_name,
87*1a96fba6SXin Li const std::string& actual_method_name,
88*1a96fba6SXin Li bool success) {
89*1a96fba6SXin Li CHECK_EQ(expected_method_name, actual_method_name)
90*1a96fba6SXin Li << "Exported DBus method '" << actual_method_name << "' "
91*1a96fba6SXin Li << "but expected '" << expected_method_name << "'";
92*1a96fba6SXin Li CHECK_EQ(expected_interface_name, actual_interface_name)
93*1a96fba6SXin Li << "Exported method DBus interface '" << actual_interface_name << "' "
94*1a96fba6SXin Li << "but expected '" << expected_interface_name << "'";
95*1a96fba6SXin Li finish_handler.Run(success);
96*1a96fba6SXin Li }
97*1a96fba6SXin Li
RetireRegistration(int registration_number)98*1a96fba6SXin Li void AsyncEventSequencer::RetireRegistration(int registration_number) {
99*1a96fba6SXin Li const size_t handlers_retired =
100*1a96fba6SXin Li outstanding_registrations_.erase(registration_number);
101*1a96fba6SXin Li CHECK_EQ(1U, handlers_retired) << "Tried to retire invalid handler "
102*1a96fba6SXin Li << registration_number << ")";
103*1a96fba6SXin Li }
104*1a96fba6SXin Li
CheckForFailure(bool failure_is_fatal,bool success,const std::string & error_message)105*1a96fba6SXin Li void AsyncEventSequencer::CheckForFailure(bool failure_is_fatal,
106*1a96fba6SXin Li bool success,
107*1a96fba6SXin Li const std::string& error_message) {
108*1a96fba6SXin Li if (failure_is_fatal) {
109*1a96fba6SXin Li CHECK(success) << error_message;
110*1a96fba6SXin Li }
111*1a96fba6SXin Li if (!success) {
112*1a96fba6SXin Li LOG(ERROR) << error_message;
113*1a96fba6SXin Li had_failures_ = true;
114*1a96fba6SXin Li }
115*1a96fba6SXin Li }
116*1a96fba6SXin Li
PossiblyRunCompletionActions()117*1a96fba6SXin Li void AsyncEventSequencer::PossiblyRunCompletionActions() {
118*1a96fba6SXin Li if (!started_ || !outstanding_registrations_.empty()) {
119*1a96fba6SXin Li // Don't run completion actions if we have any outstanding
120*1a96fba6SXin Li // Handlers outstanding or if any more handlers might
121*1a96fba6SXin Li // be scheduled in the future.
122*1a96fba6SXin Li return;
123*1a96fba6SXin Li }
124*1a96fba6SXin Li for (const auto& completion_action : completion_actions_) {
125*1a96fba6SXin Li // Should this be put on the message loop or run directly?
126*1a96fba6SXin Li completion_action.Run(!had_failures_);
127*1a96fba6SXin Li }
128*1a96fba6SXin Li // Discard our references to those actions.
129*1a96fba6SXin Li completion_actions_.clear();
130*1a96fba6SXin Li }
131*1a96fba6SXin Li
132*1a96fba6SXin Li } // namespace dbus_utils
133*1a96fba6SXin Li
134*1a96fba6SXin Li } // namespace brillo
135