1
#include "source/common/init/target_impl.h"
2

            
3
namespace Envoy {
4
namespace Init {
5

            
6
TargetHandleImpl::TargetHandleImpl(absl::string_view handle_name, absl::string_view name,
7
                                   std::weak_ptr<InternalInitializeFn> fn)
8
23637
    : handle_name_(handle_name), name_(name), fn_(std::move(fn)) {}
9

            
10
23472
bool TargetHandleImpl::initialize(const Watcher& watcher) const {
11
23472
  auto locked_fn(fn_.lock());
12
23472
  if (locked_fn) {
13
    // If we can "lock" a shared pointer to the target's callback function, call it
14
    // with a new handle to the ManagerImpl's watcher that was passed in.
15
23459
    ENVOY_LOG(debug, "{} initializing {}", handle_name_, name_);
16
23459
    (*locked_fn)(watcher.createHandle(name_));
17
23459
    return true;
18
23459
  } else {
19
    // If not, the target was already destroyed.
20
13
    ENVOY_LOG(debug, "{} can't initialize {} (unavailable)", handle_name_, name_);
21
13
    return false;
22
13
  }
23
23472
}
24

            
25
10
absl::string_view TargetHandleImpl::name() const { return name_; }
26

            
27
TargetImpl::TargetImpl(absl::string_view name, InitializeFn fn)
28
23741
    : name_(fmt::format("target {}", name)),
29
23741
      fn_(std::make_shared<InternalInitializeFn>([this, fn](WatcherHandlePtr watcher_handle) {
30
22481
        watcher_handle_ = std::move(watcher_handle);
31
22481
        fn();
32
23741
      })) {}
33

            
34
23741
TargetImpl::~TargetImpl() { ENVOY_LOG(debug, "{} destroyed", name_); }
35

            
36
22633
absl::string_view TargetImpl::name() const { return name_; }
37

            
38
22618
TargetHandlePtr TargetImpl::createHandle(absl::string_view handle_name) const {
39
  // Note: can't use std::make_unique here because TargetHandleImpl ctor is private.
40
22618
  return TargetHandlePtr(
41
22618
      new TargetHandleImpl(handle_name, name_, std::weak_ptr<InternalInitializeFn>(fn_)));
42
22618
}
43

            
44
35021
bool TargetImpl::ready() {
45
35021
  if (watcher_handle_) {
46
    // If we have a handle for the ManagerImpl's watcher, signal it and then reset so it can't be
47
    // accidentally signaled again.
48
    // NOTE: We must move watcher_handle_ to a local to avoid the scenario in which as a result of
49
    // calling ready() this target is destroyed. This is possible in practice, for example when
50
    // a listener is deleted as a result of a failure in the context of the ready() call.
51
22374
    auto local_watcher_handle = std::move(watcher_handle_);
52
22374
    return local_watcher_handle->ready();
53
22374
  }
54

            
55
  // If the watcher handle is not initialized, it means that the manager did not initialize its
56
  // targets yet. Disposing the callback here so when the manager initializes it will not hang
57
  // waiting for this target since it is already marked as ready.
58
12647
  fn_.reset();
59
12647
  return false;
60
35021
}
61

            
62
SharedTargetImpl::SharedTargetImpl(absl::string_view name, InitializeFn fn)
63
1040
    : name_(fmt::format("shared target {}", name)),
64
1164
      fn_(std::make_shared<InternalInitializeFn>([this, fn](WatcherHandlePtr watcher_handle) {
65
978
        if (initialized_) {
66
103
          watcher_handle->ready();
67
901
        } else {
68
875
          watcher_handles_.push_back(std::move(watcher_handle));
69
875
          std::call_once(once_flag_, fn);
70
875
        }
71
1164
      })) {}
72

            
73
1040
SharedTargetImpl::~SharedTargetImpl() { ENVOY_LOG(debug, "{} destroyed", name_); }
74

            
75
831
absl::string_view SharedTargetImpl::name() const { return name_; }
76

            
77
1019
TargetHandlePtr SharedTargetImpl::createHandle(absl::string_view handle_name) const {
78
  // Note: can't use std::make_unique here because TargetHandleImpl ctor is private.
79
1019
  return TargetHandlePtr(
80
1019
      new TargetHandleImpl(handle_name, name_, std::weak_ptr<InternalInitializeFn>(fn_)));
81
1019
}
82

            
83
1447
bool SharedTargetImpl::ready() {
84
1447
  initialized_ = true;
85
  // NOTE: We must move watcher_handles_ to a local to avoid the scenario in which as a result of
86
  // calling ready() this target is destroyed. This is possible in practice, for example when
87
  // a listener is deleted as a result of a failure in the context of the ready() call.
88
1447
  auto local_watcher_handles = std::move(watcher_handles_);
89
1447
  bool all_notified = !local_watcher_handles.empty();
90
1469
  for (auto& watcher_handle : local_watcher_handles) {
91
867
    all_notified = watcher_handle->ready() && all_notified;
92
867
  }
93
1447
  return all_notified;
94
1447
}
95

            
96
} // namespace Init
97
} // namespace Envoy