blob: 418ce07c0cb2bd1c7484167dba20af0f5b2c2ad7 [file] [log] [blame]
Gary Morainf80ef062012-05-16 14:57:04 -07001// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "shill/hook_table.h"
6
7#include <string>
8
9#include <base/bind.h>
10#include <base/callback.h>
Gary Moraina9fb3252012-05-31 12:05:31 -070011#include <base/cancelable_callback.h>
Gary Morainf80ef062012-05-16 14:57:04 -070012
13#include "shill/error.h"
14#include "shill/event_dispatcher.h"
mukesh agrawalb1136662013-10-14 16:39:38 -070015#include "shill/logging.h"
Gary Morainf80ef062012-05-16 14:57:04 -070016
17using base::Bind;
Gary Moraina9fb3252012-05-31 12:05:31 -070018using base::Callback;
Gary Morainf80ef062012-05-16 14:57:04 -070019using base::Closure;
20using base::ConstRef;
21using base::Unretained;
22using std::string;
23
24namespace shill {
25
Gary Morainf80ef062012-05-16 14:57:04 -070026HookTable::HookTable(EventDispatcher *event_dispatcher)
Gary Moraina9fb3252012-05-31 12:05:31 -070027 : event_dispatcher_(event_dispatcher) {}
Gary Morainf80ef062012-05-16 14:57:04 -070028
Gary Moraina9fb3252012-05-31 12:05:31 -070029void HookTable::Add(const string &name, const base::Closure &start) {
30 Remove(name);
Gary Morainf80ef062012-05-16 14:57:04 -070031 hook_table_.insert(
Gary Moraina9fb3252012-05-31 12:05:31 -070032 HookTableMap::value_type(name, HookAction(start)));
Gary Morainf80ef062012-05-16 14:57:04 -070033}
34
Gary Moraina9fb3252012-05-31 12:05:31 -070035HookTable::~HookTable() {
36 timeout_cb_.Cancel();
37}
38
39void HookTable::Remove(const std::string &name) {
40 HookTableMap::iterator it = hook_table_.find(name);
41 if (it != hook_table_.end()) {
42 hook_table_.erase(it);
Gary Morainf80ef062012-05-16 14:57:04 -070043 }
Gary Morainf80ef062012-05-16 14:57:04 -070044}
45
Gary Moraina9fb3252012-05-31 12:05:31 -070046void HookTable::ActionComplete(const std::string &name) {
mukesh agrawalb1136662013-10-14 16:39:38 -070047 SLOG(Manager, 2) << __func__ << ": " << name;
Gary Moraina9fb3252012-05-31 12:05:31 -070048 HookTableMap::iterator it = hook_table_.find(name);
49 if (it != hook_table_.end()) {
50 HookAction *action = &it->second;
51 if (action->started && !action->completed) {
52 action->completed = true;
Gary Morainf80ef062012-05-16 14:57:04 -070053 }
54 }
Gary Moraina9fb3252012-05-31 12:05:31 -070055 if (AllActionsComplete() && !done_cb_.is_null()) {
56 timeout_cb_.Cancel();
57 done_cb_.Run(Error(Error::kSuccess));
58 done_cb_.Reset();
59 }
60}
Gary Morainf80ef062012-05-16 14:57:04 -070061
Gary Moraina9fb3252012-05-31 12:05:31 -070062void HookTable::Run(int timeout_ms,
63 const Callback<void(const Error &)> &done) {
mukesh agrawalb1136662013-10-14 16:39:38 -070064 SLOG(Manager, 2) << __func__;
Gary Moraina9fb3252012-05-31 12:05:31 -070065 if (hook_table_.empty()) {
Gary Morainf80ef062012-05-16 14:57:04 -070066 done.Run(Error(Error::kSuccess));
67 return;
68 }
Gary Moraina9fb3252012-05-31 12:05:31 -070069 done_cb_ = done;
70 timeout_cb_.Reset(Bind(&HookTable::ActionsTimedOut, Unretained(this)));
71 event_dispatcher_->PostDelayedTask(timeout_cb_.callback(), timeout_ms);
Gary Morainf80ef062012-05-16 14:57:04 -070072
Gary Moraina9fb3252012-05-31 12:05:31 -070073 // Mark all actions as having started before we execute any actions.
74 // Otherwise, if the first action completes inline, its call to
75 // ActionComplete() will cause the |done| callback to be invoked before the
76 // rest of the actions get started.
Paul Stewart6db7b242014-05-02 15:34:21 -070077 for (auto &hook_entry : hook_table_) {
78 HookAction *action = &hook_entry.second;
Gary Moraina9fb3252012-05-31 12:05:31 -070079 action->started = true;
80 action->completed = false;
Gary Morainf80ef062012-05-16 14:57:04 -070081 }
Gary Moraina9fb3252012-05-31 12:05:31 -070082 // Now start the actions.
Paul Stewart6db7b242014-05-02 15:34:21 -070083 for (auto &hook_entry : hook_table_) {
84 hook_entry.second.start.Run();
Gary Moraina9fb3252012-05-31 12:05:31 -070085 }
86}
Gary Morainf80ef062012-05-16 14:57:04 -070087
Gary Moraina9fb3252012-05-31 12:05:31 -070088bool HookTable::AllActionsComplete() {
mukesh agrawalb1136662013-10-14 16:39:38 -070089 SLOG(Manager, 2) << __func__;
Gary Moraina9fb3252012-05-31 12:05:31 -070090 for (HookTableMap::const_iterator it = hook_table_.begin();
91 it != hook_table_.end(); ++it) {
92 const HookAction &action = it->second;
93 if (action.started && !action.completed) {
94 return false;
95 }
96 }
97 return true;
98}
99
100void HookTable::ActionsTimedOut() {
101 done_cb_.Run(Error(Error::kOperationTimeout));
Darin Petkov3ec55342012-09-28 14:04:44 +0200102 done_cb_.Reset();
Gary Morainf80ef062012-05-16 14:57:04 -0700103}
104
105} // namespace shill