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