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
23654
    : handle_name_(handle_name), name_(name), fn_(std::move(fn)) {}
9

            
10
23488
bool TargetHandleImpl::initialize(const Watcher& watcher) const {
11
23488
  auto locked_fn(fn_.lock());
12
23488
  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
23475
    ENVOY_LOG(debug, "{} initializing {}", handle_name_, name_);
16
23475
    (*locked_fn)(watcher.createHandle(name_));
17
23475
    return true;
18
23475
  } 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
23488
}
24

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

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

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

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

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

            
44
35104
bool TargetImpl::ready() {
45
35104
  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
22379
    auto local_watcher_handle = std::move(watcher_handle_);
52
22379
    return local_watcher_handle->ready();
53
22379
  }
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
12725
  fn_.reset();
59
12725
  return false;
60
35104
}
61

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

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

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

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

            
83
1457
bool SharedTargetImpl::ready() {
84
1457
  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
1457
  auto local_watcher_handles = std::move(watcher_handles_);
89
1457
  bool all_notified = !local_watcher_handles.empty();
90
1479
  for (auto& watcher_handle : local_watcher_handles) {
91
884
    all_notified = watcher_handle->ready() && all_notified;
92
884
  }
93
1457
  return all_notified;
94
1457
}
95

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