-
Notifications
You must be signed in to change notification settings - Fork 4.9k
/
Copy pathmanager_impl.cc
103 lines (86 loc) · 3.77 KB
/
manager_impl.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#include "common/init/manager_impl.h"
#include <functional>
#include "common/common/assert.h"
#include "common/init/watcher_impl.h"
namespace Envoy {
namespace Init {
ManagerImpl::ManagerImpl(absl::string_view name)
: name_(fmt::format("init manager {}", name)), state_(State::Uninitialized), count_(0),
watcher_(name_, [this](absl::string_view target_name) { onTargetReady(target_name); }) {}
Manager::State ManagerImpl::state() const { return state_; }
void ManagerImpl::add(const Target& target) {
++count_;
TargetHandlePtr target_handle(target.createHandle(name_));
++target_names_count_[target.name()];
switch (state_) {
case State::Uninitialized:
// If the manager isn't initialized yet, save the target handle to be initialized later.
ENVOY_LOG(debug, "added {} to {}", target.name(), name_);
target_handles_.push_back(std::move(target_handle));
return;
case State::Initializing:
// If the manager is already initializing, initialize the new target immediately. Note that
// it's important in this case that count_ was incremented above before calling the target,
// because if the target calls the init manager back immediately, count_ will be decremented
// here (see the definition of watcher_ above).
target_handle->initialize(watcher_);
return;
case State::Initialized:
// If the manager has already completed initialization, consider this a programming error.
ASSERT(false, fmt::format("attempted to add {} to initialized {}", target.name(), name_));
}
}
void ManagerImpl::initialize(const Watcher& watcher) {
// If the manager is already initializing or initialized, consider this a programming error.
ASSERT(state_ == State::Uninitialized, fmt::format("attempted to initialize {} twice", name_));
// Create a handle to notify when initialization is complete.
watcher_handle_ = watcher.createHandle(name_);
if (count_ == 0) {
// If we have no targets, initialization trivially completes. This can happen, and is fine.
ENVOY_LOG(debug, "{} contains no targets", name_);
ready();
} else {
// If we have some targets, start initialization...
ENVOY_LOG(debug, "{} initializing", name_);
state_ = State::Initializing;
// Attempt to initialize each target. If a target is unavailable, treat it as though it
// completed immediately.
for (const auto& target_handle : target_handles_) {
if (!target_handle->initialize(watcher_)) {
onTargetReady(target_handle->name());
}
}
}
}
const absl::flat_hash_map<std::string, uint32_t>& ManagerImpl::unreadyTargets() const {
return target_names_count_;
}
void ManagerImpl::dumpUnreadyTargets(envoy::admin::v3::UnreadyTargetsDumps& unready_targets_dumps) {
auto& message = *unready_targets_dumps.mutable_unready_targets_dumps()->Add();
message.set_name(name_);
for (const auto& [target_name, count] : target_names_count_) {
UNREFERENCED_PARAMETER(count);
message.add_target_names(target_name);
}
}
void ManagerImpl::onTargetReady(absl::string_view target_name) {
// If there are no remaining targets and one mysteriously calls us back, this manager is haunted.
ASSERT(count_ != 0,
fmt::format("{} called back by target after initialization complete", target_name));
// Decrease target_name count by 1.
ASSERT(target_names_count_.find(target_name) != target_names_count_.end());
if (--target_names_count_[target_name] == 0) {
target_names_count_.erase(target_name);
}
// If there are no uninitialized targets remaining when called back by a target, that means it was
// the last. Signal `ready` to the handle we saved in `initialize`.
if (--count_ == 0) {
ready();
}
}
void ManagerImpl::ready() {
state_ = State::Initialized;
watcher_handle_->ready();
}
} // namespace Init
} // namespace Envoy