1
#pragma once
2

            
3
#include "envoy/admin/v3/init_dump.pb.h"
4
#include "envoy/common/pure.h"
5
#include "envoy/init/target.h"
6
#include "envoy/init/watcher.h"
7

            
8
#include "absl/container/flat_hash_map.h"
9

            
10
namespace Envoy {
11
namespace Init {
12

            
13
/**
14
 * Init::Manager coordinates initialization of one or more "targets." A typical flow would be:
15
 *
16
 *   - One or more initialization targets are registered with a manager using `add`.
17
 *   - The manager is told to `initialize` all its targets, given a Watcher to notify when all
18
 *     registered targets are initialized.
19
 *   - Each target will initialize, either immediately or asynchronously, and will signal
20
 *     `ready` to the manager when initialized.
21
 *   - When all targets are initialized, the manager signals `ready` to the watcher it was given
22
 *     previously.
23
 *
24
 * Since there are several entities involved in this flow -- the owner of the manager, the targets
25
 * registered with the manager, and the manager itself -- it may be difficult or impossible in some
26
 * cases to guarantee that their lifetimes line up correctly to avoid use-after-free errors. The
27
 * interface design here in Init allows implementations to avoid the issue:
28
 *
29
 *   - A Target can only be initialized via a TargetHandle, which acts as a weak reference.
30
 *     Attempting to initialize a destroyed Target via its handle has no ill effects.
31
 *   - Likewise, a Watcher can only be notified that initialization was complete via a
32
 *     WatcherHandle, which acts as a weak reference as well.
33
 *
34
 * See target.h and watcher.h, as well as implementation in source/common/init for details.
35
 */
36
struct Manager {
37
116100
  virtual ~Manager() = default;
38

            
39
  /**
40
   * The manager's state, used e.g. for reporting in the admin server.
41
   */
42
  enum class State {
43
    /**
44
     * Targets have not been initialized.
45
     */
46
    Uninitialized,
47
    /**
48
     * Targets are currently being initialized.
49
     */
50
    Initializing,
51
    /**
52
     * All targets have been initialized.
53
     */
54
    Initialized
55
  };
56

            
57
  /**
58
   * @return the current state of the manager.
59
   */
60
  virtual State state() const PURE;
61

            
62
  /**
63
   * Register an initialization target. If the manager's current state is uninitialized, the target
64
   * will be saved for invocation later, when `initialize` is called. If the current state is
65
   * initializing, the target will be invoked immediately. It is an error to register a target with
66
   * a manager that is already in initialized state.
67
   * @param target the target to be invoked when initialization begins.
68
   */
69
  virtual void add(const Target& target) PURE;
70

            
71
  /**
72
   * Start initialization of all previously registered targets, and notify the given Watcher when
73
   * initialization is complete. It is an error to call initialize on a manager that is already in
74
   * initializing or initialized state. If the manager contains no targets, initialization completes
75
   * immediately.
76
   * @param watcher the watcher to notify when initialization is complete.
77
   */
78
  virtual void initialize(const Watcher& watcher) PURE;
79

            
80
  /**
81
   * Update the manager to notify a new watcher when initialization is complete. The previous
82
   * watcher will be discarded from the manager. It is an error to call this method on a manager
83
   * that is in initialized state.
84
   * @param watcher the watcher to notify when initialization is complete.
85
   */
86
  virtual void updateWatcher(const Watcher& watcher) PURE;
87

            
88
  /**
89
   * Add unready targets information into the config dump.
90
   */
91
  virtual void dumpUnreadyTargets(envoy::admin::v3::UnreadyTargetsDumps& dumps) PURE;
92
};
93

            
94
} // namespace Init
95
} // namespace Envoy