-
Notifications
You must be signed in to change notification settings - Fork 214
/
Copy pathconfig.cpp
233 lines (209 loc) · 10.7 KB
/
config.cpp
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
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
//*****************************************************************************
// Copyright 2020 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//*****************************************************************************
#include "config.hpp"
#include <filesystem>
#include <limits>
#include <regex>
#include <thread>
#include "logging.hpp"
// TODO: Write windows/linux specific status codes.
#ifdef __linux__
#include <sysexits.h>
#elif _WIN32
#include <ntstatus.h>
#endif
#include "capi_frontend/server_settings.hpp"
#include "cli_parser.hpp"
#include "modelconfig.hpp"
#include "systeminfo.hpp"
namespace ovms {
const uint32_t AVAILABLE_CORES = getCoreCount();
const uint32_t MAX_PORT_NUMBER = std::numeric_limits<uint16_t>::max();
// For drogon, we need to minimize the number of default workers since this value is set for both: unary and streaming (making it always double)
#if (USE_DROGON == 0)
const uint64_t DEFAULT_REST_WORKERS = AVAILABLE_CORES * 4.0;
#else
const uint64_t DEFAULT_REST_WORKERS = AVAILABLE_CORES;
#endif
const uint32_t DEFAULT_GRPC_MAX_THREADS = AVAILABLE_CORES * 8.0;
const size_t DEFAULT_GRPC_MEMORY_QUOTA = (size_t)2 * 1024 * 1024 * 1024; // 2GB
const uint64_t MAX_REST_WORKERS = 10'000;
Config& Config::parse(int argc, char** argv) {
ovms::CLIParser p;
ovms::ServerSettingsImpl serverSettings;
ovms::ModelsSettingsImpl modelsSettings;
p.parse(argc, argv);
p.prepare(&serverSettings, &modelsSettings);
if (!this->parse(&serverSettings, &modelsSettings))
#ifdef __linux__
exit(EX_USAGE);
#elif _WIN32
exit(3);
#endif
return *this;
}
bool Config::parse(ServerSettingsImpl* serverSettings, ModelsSettingsImpl* modelsSettings) {
this->serverSettings = *serverSettings;
this->modelsSettings = *modelsSettings;
return validate();
}
bool Config::check_hostname_or_ip(const std::string& input) {
if (input.size() > 255) {
return false;
}
bool all_numeric = true;
for (char c : input) {
if (c == '.') {
continue;
}
if (!::isdigit(c)) {
all_numeric = false;
}
}
if (all_numeric) {
std::regex valid_ip_regex("^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$");
return std::regex_match(input, valid_ip_regex);
} else {
std::regex valid_hostname_regex("^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]*[a-zA-Z0-9])\\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\\-]*[A-Za-z0-9])$");
return std::regex_match(input, valid_hostname_regex);
}
}
bool Config::validate() {
if (!configPath().empty() && (!modelName().empty() || !modelPath().empty())) {
std::cerr << "Use either config_path or model_path with model_name" << std::endl;
return false;
}
if (configPath().empty() && !(!modelName().empty() && !modelPath().empty())) {
std::cerr << "Use config_path or model_path with model_name" << std::endl;
return false;
}
if (!configPath().empty() && (!this->modelsSettings.batchSize.empty() || !shape().empty() ||
nireq() != 0 || !modelVersionPolicy().empty() || !this->modelsSettings.targetDevice.empty() ||
!pluginConfig().empty())) {
std::cerr << "Model parameters in CLI are exclusive with the config file" << std::endl;
return false;
}
// check grpc_workers value
if (((grpcWorkers() > AVAILABLE_CORES) || (grpcWorkers() < 1))) {
std::cerr << "grpc_workers count should be from 1 to CPU core count : " << AVAILABLE_CORES << std::endl;
return false;
}
// check rest_workers value
if (((restWorkers() > MAX_REST_WORKERS) || (restWorkers() < 2))) {
std::cerr << "rest_workers count should be from 2 to " << MAX_REST_WORKERS << std::endl;
return false;
}
if (this->serverSettings.restWorkers.has_value() && restPort() == 0) {
std::cerr << "rest_workers is set but rest_port is not set. rest_port is required to start rest servers" << std::endl;
return false;
}
if (port() && (port() > MAX_PORT_NUMBER)) {
std::cerr << "port number out of range from 0 to " << MAX_PORT_NUMBER << std::endl;
return false;
}
if (restPort() && (restPort() > MAX_PORT_NUMBER)) {
std::cerr << "rest_port number out of range from 0 to " << MAX_PORT_NUMBER << std::endl;
return false;
}
// metrics on rest port
if (metricsEnabled() && restPort() == 0) {
std::cerr << "rest_port setting is missing, metrics are enabled on rest port" << std::endl;
return false;
}
// metrics_list without metrics_enable
if (!metricsEnabled() && !metricsList().empty()) {
std::cerr << "metrics_enable setting is missing, required when metrics_list is provided" << std::endl;
return false;
}
// check bind addresses:
if (!restBindAddress().empty() && check_hostname_or_ip(restBindAddress()) == false) {
std::cerr << "rest_bind_address has invalid format: proper hostname or IP address expected." << std::endl;
return false;
}
if (!grpcBindAddress().empty() && check_hostname_or_ip(grpcBindAddress()) == false) {
std::cerr << "grpc_bind_address has invalid format: proper hostname or IP address expected." << std::endl;
return false;
}
// port and rest_port cannot be the same
if ((port() == restPort()) && (port() != 0)) {
std::cerr << "port and rest_port cannot have the same values" << std::endl;
return false;
}
// both ports cannot be unset
if (startedFromCLI() && ((restPort() == 0) && (port() == 0))) {
std::cerr << "port and rest_port cannot both be unset" << std::endl;
return false;
}
// check cpu_extension path:
if (!cpuExtensionLibraryPath().empty() && !std::filesystem::exists(cpuExtensionLibraryPath())) {
std::cerr << "File path provided as an --cpu_extension parameter does not exist in the filesystem: " << this->cpuExtensionLibraryPath() << std::endl;
return false;
}
// check log_level values
std::vector v({"TRACE", "DEBUG", "INFO", "WARNING", "ERROR"});
if (std::find(v.begin(), v.end(), logLevel()) == v.end()) {
std::cerr << "log_level should be one of: TRACE, DEBUG, INFO, WARNING, ERROR" << std::endl;
return false;
}
// check stateful flags:
if ((this->modelsSettings.lowLatencyTransformation.has_value() || this->modelsSettings.maxSequenceNumber.has_value() || this->modelsSettings.idleSequenceCleanup.has_value()) && !stateful()) {
std::cerr << "Setting low_latency_transformation, max_sequence_number and idle_sequence_cleanup require setting stateful flag for the model." << std::endl;
return false;
}
return true;
}
const std::string& Config::configPath() const { return this->modelsSettings.configPath; }
uint32_t Config::port() const { return this->serverSettings.grpcPort; }
const std::string Config::cpuExtensionLibraryPath() const { return this->serverSettings.cpuExtensionLibraryPath; }
const std::string Config::grpcBindAddress() const { return this->serverSettings.grpcBindAddress; }
uint32_t Config::restPort() const { return this->serverSettings.restPort; }
const std::string Config::restBindAddress() const { return this->serverSettings.restBindAddress; }
uint32_t Config::grpcWorkers() const { return this->serverSettings.grpcWorkers; }
uint32_t Config::grpcMaxThreads() const { return this->serverSettings.grpcMaxThreads.value_or(DEFAULT_GRPC_MAX_THREADS); }
size_t Config::grpcMemoryQuota() const { return this->serverSettings.grpcMemoryQuota.value_or(DEFAULT_GRPC_MEMORY_QUOTA); }
uint32_t Config::restWorkers() const { return this->serverSettings.restWorkers.value_or(DEFAULT_REST_WORKERS); }
const std::string& Config::modelName() const { return this->modelsSettings.modelName; }
const std::string& Config::modelPath() const { return this->modelsSettings.modelPath; }
const std::string& Config::batchSize() const {
static const std::string defaultBatch = "";
return this->modelsSettings.batchSize.empty() ? defaultBatch : this->modelsSettings.batchSize;
}
const std::string& Config::Config::shape() const { return this->modelsSettings.shape; }
const std::string& Config::layout() const { return this->modelsSettings.layout; }
const std::string& Config::modelVersionPolicy() const { return this->modelsSettings.modelVersionPolicy; }
uint32_t Config::nireq() const { return this->modelsSettings.nireq; }
const std::string& Config::targetDevice() const {
static const std::string defaultTargetDevice = "CPU";
return this->modelsSettings.targetDevice.empty() ? defaultTargetDevice : this->modelsSettings.targetDevice;
}
const std::string& Config::Config::pluginConfig() const { return this->modelsSettings.pluginConfig; }
bool Config::stateful() const { return this->modelsSettings.stateful.value_or(false); }
bool Config::metricsEnabled() const { return this->serverSettings.metricsEnabled; }
std::string Config::metricsList() const { return this->serverSettings.metricsList; }
bool Config::idleSequenceCleanup() const { return this->modelsSettings.idleSequenceCleanup.value_or(true); }
uint32_t Config::maxSequenceNumber() const { return this->modelsSettings.maxSequenceNumber.value_or(DEFAULT_MAX_SEQUENCE_NUMBER); }
bool Config::lowLatencyTransformation() const { return this->modelsSettings.lowLatencyTransformation.value_or(false); }
const std::string& Config::logLevel() const { return this->serverSettings.logLevel; }
const std::string& Config::logPath() const { return this->serverSettings.logPath; }
#ifdef MTR_ENABLED
const std::string& Config::tracePath() const { return this->serverSettings.tracePath; }
#endif
const std::string& Config::grpcChannelArguments() const { return this->serverSettings.grpcChannelArguments; }
uint32_t Config::filesystemPollWaitMilliseconds() const { return this->serverSettings.filesystemPollWaitMilliseconds; }
uint32_t Config::sequenceCleanerPollWaitMinutes() const { return this->serverSettings.sequenceCleanerPollWaitMinutes; }
uint32_t Config::resourcesCleanerPollWaitSeconds() const { return this->serverSettings.resourcesCleanerPollWaitSeconds; }
const std::string Config::cacheDir() const { return this->serverSettings.cacheDir; }
} // namespace ovms