-
Notifications
You must be signed in to change notification settings - Fork 4.8k
/
hot_restart_impl.h
140 lines (119 loc) · 4.59 KB
/
hot_restart_impl.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#pragma once
#include <fcntl.h>
#include <sys/un.h>
#include <array>
#include <atomic>
#include <cstdint>
#include <string>
#include "envoy/common/platform.h"
#include "envoy/server/hot_restart.h"
#include "source/common/common/assert.h"
#include "source/common/stats/allocator_impl.h"
#include "source/server/hot_restarting_child.h"
#include "source/server/hot_restarting_parent.h"
namespace Envoy {
namespace Server {
// Increment this whenever there is a shared memory / RPC change that will prevent a hot restart
// from working. Operations code can then cope with this and do a full restart.
const uint64_t HOT_RESTART_VERSION = 11;
/**
* Shared memory segment. This structure is laid directly into shared memory and is used amongst
* all running envoy processes.
*/
struct SharedMemory {
uint64_t size_;
uint64_t version_;
pthread_mutex_t log_lock_;
pthread_mutex_t access_log_lock_;
std::atomic<uint64_t> flags_;
};
static const uint64_t SHMEM_FLAGS_INITIALIZING = 0x1;
/**
* Initialize the shared memory segment, depending on whether we are the first running
* envoy, or a host restarted envoy process.
*
* @param base_id uint32_t that is the base id flag used to start this Envoy.
* @param restart_epoch uint32_t the restart epoch flag used to start this Envoy.
*/
SharedMemory* attachSharedMemory(uint32_t base_id, uint32_t restart_epoch);
/**
* Initialize a pthread mutex for process shared locking.
*/
void initializeMutex(pthread_mutex_t& mutex);
/**
* Implementation of Thread::BasicLockable that operates on a process shared pthread mutex.
*/
class ProcessSharedMutex : public Thread::BasicLockable {
public:
ProcessSharedMutex(pthread_mutex_t& mutex) : mutex_(mutex) {}
void lock() ABSL_EXCLUSIVE_LOCK_FUNCTION() override {
// Deal with robust handling here. If the other process dies without unlocking, we are going
// to die shortly but try to make sure that we can handle any signals, etc. that happen without
// getting into a further messed up state.
int rc = pthread_mutex_lock(&mutex_);
ASSERT(rc == 0 || rc == EOWNERDEAD);
if (rc == EOWNERDEAD) {
pthread_mutex_consistent(&mutex_);
}
}
bool tryLock() ABSL_EXCLUSIVE_TRYLOCK_FUNCTION(true) override {
int rc = pthread_mutex_trylock(&mutex_);
if (rc == EBUSY) {
return false;
}
ASSERT(rc == 0 || rc == EOWNERDEAD);
if (rc == EOWNERDEAD) {
pthread_mutex_consistent(&mutex_);
}
return true;
}
void unlock() ABSL_UNLOCK_FUNCTION() override {
int rc = pthread_mutex_unlock(&mutex_);
ASSERT(rc == 0);
}
private:
pthread_mutex_t& mutex_;
};
/**
* Implementation of HotRestart built for Linux. Most of the "protocol" type logic is split out into
* HotRestarting{Base,Parent,Child}. This class ties all that to shared memory and version logic.
*/
class HotRestartImpl : public HotRestart {
public:
HotRestartImpl(uint32_t base_id, uint32_t restart_epoch, const std::string& socket_path,
mode_t socket_mode, bool skip_hot_restart_on_no_parent, bool skip_parent_stats);
// Server::HotRestart
void drainParentListeners() override;
int duplicateParentListenSocket(const std::string& address, uint32_t worker_index) override;
void registerUdpForwardingListener(
Network::Address::InstanceConstSharedPtr address,
std::shared_ptr<Network::UdpListenerConfig> listener_config) override;
OptRef<Network::ParentDrainedCallbackRegistrar> parentDrainedCallbackRegistrar() override;
void initialize(Event::Dispatcher& dispatcher, Server::Instance& server) override;
absl::optional<AdminShutdownResponse> sendParentAdminShutdownRequest() override;
void sendParentTerminateRequest() override;
ServerStatsFromParent mergeParentStatsIfAny(Stats::StoreRoot& stats_store) override;
void shutdown() override;
uint32_t baseId() override;
std::string version() override;
Thread::BasicLockable& logLock() override { return log_lock_; }
Thread::BasicLockable& accessLogLock() override { return access_log_lock_; }
/**
* envoy --hot_restart_version doesn't initialize Envoy, but computes the version string
* based on the configured options.
*/
static std::string hotRestartVersion();
private:
friend class HotRestartUdpForwardingTestHelper;
uint32_t base_id_;
uint32_t scaled_base_id_;
HotRestartingChild as_child_;
HotRestartingParent as_parent_;
// This pointer is shared memory, and is expected to exist until process end.
// It will automatically be unmapped when the process terminates.
SharedMemory* shmem_;
ProcessSharedMutex log_lock_;
ProcessSharedMutex access_log_lock_;
};
} // namespace Server
} // namespace Envoy