-
Notifications
You must be signed in to change notification settings - Fork 4.8k
/
stripped_main_base.cc
171 lines (144 loc) · 6.83 KB
/
stripped_main_base.cc
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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
#include "source/exe/stripped_main_base.h"
#include <fstream>
#include <iostream>
#include <memory>
#include <new>
#include "envoy/config/listener/v3/listener.pb.h"
#include "source/common/common/compiler_requirements.h"
#include "source/common/common/logger.h"
#include "source/common/common/perf_annotation.h"
#include "source/common/network/utility.h"
#include "source/common/stats/thread_local_store.h"
#include "source/exe/platform_impl.h"
#include "source/server/drain_manager_impl.h"
#include "source/server/hot_restart_nop_impl.h"
#include "source/server/listener_hooks.h"
#include "source/server/options_impl_base.h"
#include "source/server/server.h"
#include "absl/debugging/symbolize.h"
#include "absl/strings/str_split.h"
#ifdef ENVOY_HOT_RESTART
#include "source/server/hot_restart_impl.h"
#endif
namespace Envoy {
Server::DrainManagerPtr ProdComponentFactory::createDrainManager(Server::Instance& server) {
// The global drain manager only triggers on listener modification, which effectively is
// hot restart at the global level. The per-listener drain managers decide whether to
// to include /healthcheck/fail status.
return std::make_unique<Server::DrainManagerImpl>(
server, envoy::config::listener::v3::Listener::MODIFY_ONLY, server.dispatcher());
}
Runtime::LoaderPtr ProdComponentFactory::createRuntime(Server::Instance& server,
Server::Configuration::Initial& config) {
return Server::InstanceUtil::createRuntime(server, config);
}
StrippedMainBase::StrippedMainBase(const Server::Options& options, Event::TimeSystem& time_system,
ListenerHooks& listener_hooks,
Server::ComponentFactory& component_factory,
std::unique_ptr<Server::Platform> platform_impl,
std::unique_ptr<Random::RandomGenerator>&& random_generator,
std::unique_ptr<ProcessContext> process_context,
CreateInstanceFunction create_instance)
: platform_impl_(std::move(platform_impl)), options_(options),
component_factory_(component_factory), stats_allocator_(symbol_table_) {
// Process the option to disable extensions as early as possible,
// before we do any configuration loading.
OptionsImplBase::disableExtensions(options.disabledExtensions());
// Enable core dumps as early as possible.
if (options_.coreDumpEnabled()) {
const auto ret = platform_impl_->enableCoreDump();
if (ret) {
ENVOY_LOG_MISC(info, "core dump enabled");
} else {
ENVOY_LOG_MISC(warn, "failed to enable core dump");
}
}
switch (options_.mode()) {
case Server::Mode::InitOnly:
case Server::Mode::Serve: {
configureHotRestarter(*random_generator);
tls_ = std::make_unique<ThreadLocal::InstanceImpl>();
Thread::BasicLockable& log_lock = restarter_->logLock();
Thread::BasicLockable& access_log_lock = restarter_->accessLogLock();
logging_context_ = std::make_unique<Logger::Context>(options_.logLevel(), options_.logFormat(),
log_lock, options_.logFormatEscaped(),
options_.enableFineGrainLogging());
configureComponentLogLevels();
// Provide consistent behavior for out-of-memory, regardless of whether it occurs in a
// try/catch block or not.
std::set_new_handler([]() { PANIC("out of memory"); });
stats_store_ = std::make_unique<Stats::ThreadLocalStoreImpl>(stats_allocator_);
server_ = create_instance(*init_manager_, options_, time_system, listener_hooks, *restarter_,
*stats_store_, access_log_lock, component_factory,
std::move(random_generator), *tls_, platform_impl_->threadFactory(),
platform_impl_->fileSystem(), std::move(process_context), nullptr);
break;
}
case Server::Mode::Validate:
restarter_ = std::make_unique<Server::HotRestartNopImpl>();
logging_context_ =
std::make_unique<Logger::Context>(options_.logLevel(), options_.logFormat(),
restarter_->logLock(), options_.logFormatEscaped());
process_context_ = std::move(process_context);
break;
}
}
void StrippedMainBase::configureComponentLogLevels() {
for (auto& component_log_level : options_.componentLogLevels()) {
Logger::Logger* logger_to_change = Logger::Registry::logger(component_log_level.first);
ASSERT(logger_to_change);
logger_to_change->setLevel(component_log_level.second);
}
}
void StrippedMainBase::configureHotRestarter(Random::RandomGenerator& random_generator) {
#ifdef ENVOY_HOT_RESTART
if (!options_.hotRestartDisabled()) {
uint32_t base_id = options_.baseId();
if (options_.useDynamicBaseId()) {
ASSERT(options_.restartEpoch() == 0, "cannot use dynamic base id during hot restart");
std::unique_ptr<Server::HotRestart> restarter;
// Try 100 times to get an unused base ID and then give up under the assumption
// that some other problem has occurred to prevent binding the domain socket.
for (int i = 0; i < 100 && restarter == nullptr; i++) {
// HotRestartImpl is going to multiply this value by 10, so leave head room.
base_id = static_cast<uint32_t>(random_generator.random()) & 0x0FFFFFFF;
TRY_ASSERT_MAIN_THREAD {
restarter = std::make_unique<Server::HotRestartImpl>(
base_id, 0, options_.socketPath(), options_.socketMode(),
options_.skipHotRestartOnNoParent(), options_.skipHotRestartParentStats());
}
END_TRY
CATCH(Server::HotRestartDomainSocketInUseException & ex, {
// No luck, try again.
ENVOY_LOG_MISC(debug, "dynamic base id: {}", ex.what());
});
}
if (restarter == nullptr) {
throw EnvoyException("unable to select a dynamic base id");
}
restarter_.swap(restarter);
} else {
restarter_ = std::make_unique<Server::HotRestartImpl>(
base_id, options_.restartEpoch(), options_.socketPath(), options_.socketMode(),
options_.skipHotRestartOnNoParent(), options_.skipHotRestartParentStats());
}
// Write the base-id to the requested path whether we selected it
// dynamically or not.
if (!options_.baseIdPath().empty()) {
std::ofstream base_id_out_file(options_.baseIdPath());
if (!base_id_out_file) {
ENVOY_LOG_MISC(critical, "cannot open base id output file {} for writing.",
options_.baseIdPath());
} else {
base_id_out_file << base_id;
}
}
}
#else
UNREFERENCED_PARAMETER(random_generator);
#endif
if (restarter_ == nullptr) {
restarter_ = std::make_unique<Server::HotRestartNopImpl>();
}
}
} // namespace Envoy