13ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley// Copyright 2014 The Chromium OS Authors. All rights reserved. 23ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley// Use of this source code is governed by a BSD-style license that can be 33ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley// found in the LICENSE file. 43ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley 59ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko#include <brillo/dbus/async_event_sequencer.h> 63ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley 79ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenkonamespace brillo { 83ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley 93ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wileynamespace dbus_utils { 103ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley 1105d29044d14a60775ed6c51c75a414eb0cb50347Alex VakulenkoAsyncEventSequencer::AsyncEventSequencer() { 1205d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko} 1305d29044d14a60775ed6c51c75a414eb0cb50347Alex VakulenkoAsyncEventSequencer::~AsyncEventSequencer() { 1405d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko} 153ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley 163ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher WileyAsyncEventSequencer::Handler AsyncEventSequencer::GetHandler( 1705d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko const std::string& descriptive_message, 1805d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko bool failure_is_fatal) { 193ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley CHECK(!started_) << "Cannot create handlers after OnAllTasksCompletedCall()"; 203ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley int unique_registration_id = ++registration_counter_; 213ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley outstanding_registrations_.insert(unique_registration_id); 2205d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko return base::Bind(&AsyncEventSequencer::HandleFinish, 2305d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko this, 2405d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko unique_registration_id, 2505d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko descriptive_message, 263ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley failure_is_fatal); 273ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley} 283ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley 293ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher WileyAsyncEventSequencer::ExportHandler AsyncEventSequencer::GetExportHandler( 3005d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko const std::string& interface_name, 3105d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko const std::string& method_name, 3205d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko const std::string& descriptive_message, 3305d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko bool failure_is_fatal) { 343ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley auto finish_handler = GetHandler(descriptive_message, failure_is_fatal); 3505d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko return base::Bind(&AsyncEventSequencer::HandleDBusMethodExported, 3605d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko this, 373ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley finish_handler, 383ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley interface_name, 393ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley method_name); 403ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley} 413ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley 423ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wileyvoid AsyncEventSequencer::OnAllTasksCompletedCall( 433ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley std::vector<CompletionAction> actions) { 443ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley CHECK(!started_) << "OnAllTasksCompletedCall called twice!"; 453ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley started_ = true; 463ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley completion_actions_.assign(actions.begin(), actions.end()); 473ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley // All of our callbacks might have been called already. 483ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley PossiblyRunCompletionActions(); 493ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley} 503ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley 513ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wileynamespace { 523ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wileyvoid IgnoreSuccess(const AsyncEventSequencer::CompletionTask& task, 5305d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko bool /*success*/) { 5405d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko task.Run(); 5505d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko} 562fd46ba1458275cd16b0949675bff70cc8abcdadChristopher Wileyvoid DoNothing(bool /* success */) { 5705d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko} 583ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley} // namespace 593ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley 603ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher WileyAsyncEventSequencer::CompletionAction AsyncEventSequencer::WrapCompletionTask( 613ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley const CompletionTask& task) { 623ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley return base::Bind(&IgnoreSuccess, task); 633ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley} 643ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley 6590e4ffc22f8eaeb8284b30e22474d77aa1ba1557Alex VakulenkoAsyncEventSequencer::CompletionAction 6605d29044d14a60775ed6c51c75a414eb0cb50347Alex VakulenkoAsyncEventSequencer::GetDefaultCompletionAction() { 6790e4ffc22f8eaeb8284b30e22474d77aa1ba1557Alex Vakulenko return base::Bind(&DoNothing); 6890e4ffc22f8eaeb8284b30e22474d77aa1ba1557Alex Vakulenko} 6990e4ffc22f8eaeb8284b30e22474d77aa1ba1557Alex Vakulenko 703ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wileyvoid AsyncEventSequencer::HandleFinish(int registration_number, 713ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley const std::string& error_message, 7205d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko bool failure_is_fatal, 7305d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko bool success) { 743ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley RetireRegistration(registration_number); 753ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley CheckForFailure(failure_is_fatal, success, error_message); 763ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley PossiblyRunCompletionActions(); 773ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley} 783ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley 793ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wileyvoid AsyncEventSequencer::HandleDBusMethodExported( 803ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley const AsyncEventSequencer::Handler& finish_handler, 813ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley const std::string& expected_interface_name, 823ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley const std::string& expected_method_name, 833ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley const std::string& actual_interface_name, 8405d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko const std::string& actual_method_name, 8505d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko bool success) { 863ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley CHECK_EQ(expected_method_name, actual_method_name) 873ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley << "Exported DBus method '" << actual_method_name << "' " 883ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley << "but expected '" << expected_method_name << "'"; 893ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley CHECK_EQ(expected_interface_name, actual_interface_name) 903ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley << "Exported method DBus interface '" << actual_interface_name << "' " 913ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley << "but expected '" << expected_interface_name << "'"; 923ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley finish_handler.Run(success); 933ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley} 943ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley 953ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wileyvoid AsyncEventSequencer::RetireRegistration(int registration_number) { 9605d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko const size_t handlers_retired = 9705d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko outstanding_registrations_.erase(registration_number); 9805d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko CHECK_EQ(1U, handlers_retired) << "Tried to retire invalid handler " 9905d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko << registration_number << ")"; 1003ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley} 1013ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley 10205d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenkovoid AsyncEventSequencer::CheckForFailure(bool failure_is_fatal, 10305d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko bool success, 1043ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley const std::string& error_message) { 1053ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley if (failure_is_fatal) { 1063ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley CHECK(success) << error_message; 1073ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley } 1083ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley if (!success) { 1093ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley LOG(ERROR) << error_message; 1103ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley had_failures_ = true; 1113ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley } 1123ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley} 1133ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley 1143ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wileyvoid AsyncEventSequencer::PossiblyRunCompletionActions() { 1153ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley if (!started_ || !outstanding_registrations_.empty()) { 1163ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley // Don't run completion actions if we have any outstanding 1173ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley // Handlers outstanding or if any more handlers might 1183ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley // be scheduled in the future. 1193ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley return; 1203ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley } 1213ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley for (const auto& completion_action : completion_actions_) { 1223ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley // Should this be put on the message loop or run directly? 1233ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley completion_action.Run(!had_failures_); 1243ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley } 1253ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley // Discard our references to those actions. 1263ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley completion_actions_.clear(); 1273ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley} 1283ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley 1293ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley} // namespace dbus_utils 1303ed0af9644cac24bc40bee6cf4b3dd7b063b5b8eChristopher Wiley 1319ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko} // namespace brillo 132