1
#pragma once
2

            
3
#include <cstdint>
4
#include <string>
5

            
6
#include "envoy/common/pure.h"
7
#include "envoy/event/dispatcher.h"
8
#include "envoy/stats/store.h"
9
#include "envoy/thread/thread.h"
10

            
11
namespace Envoy {
12
namespace Server {
13

            
14
class Instance;
15

            
16
/**
17
 * Abstracts functionality required to "hot" (live) restart the server including code and
18
 * configuration. Right now this interface assumes a UNIX like socket interface for fd passing
19
 * but it could be relatively easily swapped with something else if necessary.
20
 */
21
class HotRestart {
22
public:
23
  struct ServerStatsFromParent {
24
    uint64_t parent_memory_allocated_ = 0;
25
    uint64_t parent_connections_ = 0;
26
  };
27

            
28
  struct AdminShutdownResponse {
29
    time_t original_start_time_;
30
    bool enable_reuse_port_default_;
31
  };
32

            
33
11791
  virtual ~HotRestart() = default;
34

            
35
  /**
36
   * Shutdown listeners in the parent process if applicable. Listeners will begin draining to
37
   * clear out old connections.
38
   */
39
  virtual void drainParentListeners() PURE;
40

            
41
  /**
42
   * Retrieve a listening socket on the specified address from the parent process. The socket will
43
   * be duplicated across process boundaries.
44
   * @param address supplies the address of the socket to duplicate, e.g. tcp://127.0.0.1:5000.
45
   * @param worker_index supplies the socket/worker index to fetch. When using reuse_port sockets
46
   *        each socket is fetched individually to ensure no connection loss.
47
   * @param network_namespace supplies the network namespace of the socket, if any.
48
   * @return int the fd or -1 if there is no bound listen port in the parent.
49
   */
50
  virtual int duplicateParentListenSocket(const std::string& address, uint32_t worker_index,
51
                                          absl::string_view network_namespace) PURE;
52

            
53
  /**
54
   * Registers a UdpListenerConfig as a possible receiver of udp packets forwarded from the
55
   * parent process to the child process. This is used to forward QUIC packets that are not for
56
   * connections belonging to the parent process during draining (in the absence of BPF delivery to
57
   * the correct process), via its listenerWorkerRouter.
58
   * The HotRestart instance is responsible for recognizing "any" addresses (e.g. "0.0.0.0").
59
   * @param address supplies the address and port of the listening socket.
60
   * @param listener_config is the UdpListenerConfig to receive packets forwarded for the given
61
   * address.
62
   */
63
  virtual void
64
  registerUdpForwardingListener(Network::Address::InstanceConstSharedPtr address,
65
                                std::shared_ptr<Network::UdpListenerConfig> listener_config) PURE;
66

            
67
  /**
68
   * @return An interface on which registerParentDrainedCallback can be called during
69
   *         creation of a listener, or nullopt if there is no parent instance.
70
   *
71
   *         If this is set, any UDP listener should start paused and only begin listening
72
   *         when the parent instance is drained; this allows draining QUIC listeners to
73
   *         catch their own packets and forward unrecognized packets to the child instance.
74
   */
75
  virtual OptRef<Network::ParentDrainedCallbackRegistrar> parentDrainedCallbackRegistrar() PURE;
76

            
77
  /**
78
   * Initialize the parent logic of our restarter. Meant to be called after initialization of a
79
   * new child has begun. The hot restart implementation needs to be created early to deal with
80
   * shared memory, logging, etc. so late initialization of needed interfaces is done here.
81
   */
82
  virtual void initialize(Event::Dispatcher& dispatcher, Server::Instance& server) PURE;
83

            
84
  /**
85
   * Shutdown admin processing in the parent process if applicable. This allows admin processing
86
   * to start up in the new process.
87
   * @return response if the parent is alive.
88
   */
89
  virtual absl::optional<AdminShutdownResponse> sendParentAdminShutdownRequest() PURE;
90

            
91
  /**
92
   * Tell our parent process to gracefully terminate itself.
93
   */
94
  virtual void sendParentTerminateRequest() PURE;
95

            
96
  /**
97
   * Retrieve stats from our parent process and merges them into stats_store, taking into account
98
   * the stats values we've already seen transferred.
99
   * Skips all of the above and returns 0s if there is not currently a parent.
100
   * @param stats_store the store whose stats will be updated.
101
   * @param stats_proto the stats values we are updating with.
102
   * @return special values relating to the "server" stats scope, whose
103
   *         merging has to be handled by Server::InstanceImpl.
104
   */
105
  virtual ServerStatsFromParent mergeParentStatsIfAny(Stats::StoreRoot& stats_store) PURE;
106

            
107
  /**
108
   * Shutdown the half of our hot restarter that acts as a parent.
109
   */
110
  virtual void shutdown() PURE;
111

            
112
  /**
113
   * Return the base id used to generate a domain socket name.
114
   */
115
  virtual uint32_t baseId() PURE;
116

            
117
  /**
118
   * Return the hot restart compatibility version so that operations code can decide whether to
119
   * perform a full or hot restart.
120
   */
121
  virtual std::string version() PURE;
122

            
123
  /**
124
   * @return Thread::BasicLockable& a lock for logging.
125
   */
126
  virtual Thread::BasicLockable& logLock() PURE;
127

            
128
  /**
129
   * @return Thread::BasicLockable& a lock for access logs.
130
   */
131
  virtual Thread::BasicLockable& accessLogLock() PURE;
132

            
133
  /**
134
   * @return bool whether the server is currently in the initializing state during hot restart.
135
   */
136
  virtual bool isInitializing() const PURE;
137
};
138

            
139
/**
140
 * HotRestartDomainSocketInUseException is thrown during HotRestart construction only when the
141
 * underlying domain socket is in use.
142
 */
143
class HotRestartDomainSocketInUseException : public EnvoyException {
144
public:
145
104
  HotRestartDomainSocketInUseException(const std::string& what) : EnvoyException(what) {}
146
};
147

            
148
} // namespace Server
149
} // namespace Envoy