/root/doris/cloud/src/common/configbase.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | // Licensed to the Apache Software Foundation (ASF) under one |
2 | | // or more contributor license agreements. See the NOTICE file |
3 | | // distributed with this work for additional information |
4 | | // regarding copyright ownership. The ASF licenses this file |
5 | | // to you under the Apache License, Version 2.0 (the |
6 | | // "License"); you may not use this file except in compliance |
7 | | // with the License. You may obtain a copy of the License at |
8 | | // |
9 | | // http://www.apache.org/licenses/LICENSE-2.0 |
10 | | // |
11 | | // Unless required by applicable law or agreed to in writing, |
12 | | // software distributed under the License is distributed on an |
13 | | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
14 | | // KIND, either express or implied. See the License for the |
15 | | // specific language governing permissions and limitations |
16 | | // under the License. |
17 | | |
18 | | #include <fmt/core.h> |
19 | | |
20 | | #include <algorithm> |
21 | | #include <cerrno> |
22 | | #include <cstring> |
23 | | #include <filesystem> |
24 | | #include <fstream> |
25 | | #include <iostream> |
26 | | #include <list> |
27 | | #include <map> |
28 | | #include <mutex> |
29 | | #include <sstream> |
30 | | #include <utility> |
31 | | |
32 | | #define __IN_CONFIGBASE_CPP__ |
33 | | #include "common/config.h" |
34 | | #undef __IN_CONFIGBASE_CPP__ |
35 | | |
36 | | namespace doris::cloud::config { |
37 | | |
38 | | std::map<std::string, Register::Field>* Register::_s_field_map = nullptr; |
39 | | std::map<std::string, std::function<bool()>>* RegisterConfValidator::_s_field_validator = nullptr; |
40 | | std::map<std::string, std::string>* full_conf_map = nullptr; |
41 | | std::mutex mutable_string_config_lock; |
42 | | std::mutex conf_persist_lock; |
43 | | |
44 | | // trim string |
45 | 2.68k | std::string& trim(std::string& s) { |
46 | | // rtrim |
47 | 2.68k | s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char c) { return !std::isspace(c); }) |
48 | 2.68k | .base(), |
49 | 2.68k | s.end()); |
50 | | // ltrim |
51 | 2.68k | s.erase(s.begin(), |
52 | 2.68k | std::find_if(s.begin(), s.end(), [](unsigned char c) { return !std::isspace(c); })); |
53 | 2.68k | return s; |
54 | 2.68k | } |
55 | | |
56 | | // split string by '=' |
57 | 89 | void splitkv(const std::string& s, std::string& k, std::string& v) { |
58 | 89 | const char sep = '='; |
59 | 89 | int start = 0; |
60 | 89 | int end = 0; |
61 | 89 | if ((end = s.find(sep, start)) != std::string::npos) { |
62 | 89 | k = s.substr(start, end - start); |
63 | 89 | v = s.substr(end + 1); |
64 | 89 | } else { |
65 | 0 | k = s; |
66 | 0 | v = ""; |
67 | 0 | } |
68 | 89 | } |
69 | | |
70 | | // replace env variables |
71 | 2.10k | bool replaceenv(std::string& s) { |
72 | 2.10k | std::size_t pos = 0; |
73 | 2.10k | std::size_t start = 0; |
74 | 2.10k | while ((start = s.find("${", pos)) != std::string::npos) { |
75 | 0 | std::size_t end = s.find("}", start + 2); |
76 | 0 | if (end == std::string::npos) { |
77 | 0 | return false; |
78 | 0 | } |
79 | 0 | std::string envkey = s.substr(start + 2, end - start - 2); |
80 | 0 | const char* envval = std::getenv(envkey.c_str()); |
81 | 0 | if (envval == nullptr) { |
82 | 0 | return false; |
83 | 0 | } |
84 | 0 | s.erase(start, end - start + 1); |
85 | 0 | s.insert(start, envval); |
86 | 0 | pos = start + strlen(envval); |
87 | 0 | } |
88 | 2.10k | return true; |
89 | 2.10k | } |
90 | | |
91 | | bool strtox(const std::string& valstr, bool& retval); |
92 | | bool strtox(const std::string& valstr, int16_t& retval); |
93 | | bool strtox(const std::string& valstr, int32_t& retval); |
94 | | bool strtox(const std::string& valstr, int64_t& retval); |
95 | | bool strtox(const std::string& valstr, double& retval); |
96 | | bool strtox(const std::string& valstr, std::string& retval); |
97 | | |
98 | | template <typename T> |
99 | 68 | bool strtox(const std::string& valstr, std::vector<T>& retval) { |
100 | 68 | std::stringstream ss(valstr); |
101 | 68 | std::string item; |
102 | 68 | T t; |
103 | 68 | while (std::getline(ss, item, ',')) { |
104 | 0 | if (!strtox(trim(item), t)) { |
105 | 0 | return false; |
106 | 0 | } |
107 | 0 | retval.push_back(t); |
108 | 0 | } |
109 | 68 | return true; |
110 | 68 | } Unexecuted instantiation: _ZN5doris5cloud6config6strtoxIbEEbRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERSt6vectorIT_SaISC_EE Unexecuted instantiation: _ZN5doris5cloud6config6strtoxIsEEbRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERSt6vectorIT_SaISC_EE Unexecuted instantiation: _ZN5doris5cloud6config6strtoxIiEEbRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERSt6vectorIT_SaISC_EE Unexecuted instantiation: _ZN5doris5cloud6config6strtoxIlEEbRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERSt6vectorIT_SaISC_EE Unexecuted instantiation: _ZN5doris5cloud6config6strtoxIdEEbRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERSt6vectorIT_SaISC_EE _ZN5doris5cloud6config6strtoxINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEEbRKS8_RSt6vectorIT_SaISC_EE Line | Count | Source | 99 | 68 | bool strtox(const std::string& valstr, std::vector<T>& retval) { | 100 | 68 | std::stringstream ss(valstr); | 101 | 68 | std::string item; | 102 | 68 | T t; | 103 | 68 | while (std::getline(ss, item, ',')) { | 104 | 0 | if (!strtox(trim(item), t)) { | 105 | 0 | return false; | 106 | 0 | } | 107 | 0 | retval.push_back(t); | 108 | 0 | } | 109 | 68 | return true; | 110 | 68 | } |
|
111 | | |
112 | 462 | bool strtox(const std::string& valstr, bool& retval) { |
113 | 462 | if (valstr.compare("true") == 0) { |
114 | 222 | retval = true; |
115 | 240 | } else if (valstr.compare("false") == 0) { |
116 | 240 | retval = false; |
117 | 240 | } else { |
118 | 0 | return false; |
119 | 0 | } |
120 | 462 | return true; |
121 | 462 | } |
122 | | |
123 | | template <typename T> |
124 | 978 | bool strtointeger(const std::string& valstr, T& retval) { |
125 | 978 | if (valstr.length() == 0) { |
126 | 0 | return false; // empty-string is only allowed for string type. |
127 | 0 | } |
128 | 978 | char* end; |
129 | 978 | errno = 0; |
130 | 978 | const char* valcstr = valstr.c_str(); |
131 | 978 | int64_t ret64 = strtoll(valcstr, &end, 10); |
132 | 978 | if (errno || end != valcstr + strlen(valcstr)) { |
133 | 0 | return false; // bad parse |
134 | 0 | } |
135 | 978 | T tmp = retval; |
136 | 978 | retval = static_cast<T>(ret64); |
137 | 978 | if (retval != ret64) { |
138 | 0 | retval = tmp; |
139 | 0 | return false; |
140 | 0 | } |
141 | 978 | return true; |
142 | 978 | } _ZN5doris5cloud6config12strtointegerIsEEbRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERT_ Line | Count | Source | 124 | 17 | bool strtointeger(const std::string& valstr, T& retval) { | 125 | 17 | if (valstr.length() == 0) { | 126 | 0 | return false; // empty-string is only allowed for string type. | 127 | 0 | } | 128 | 17 | char* end; | 129 | 17 | errno = 0; | 130 | 17 | const char* valcstr = valstr.c_str(); | 131 | 17 | int64_t ret64 = strtoll(valcstr, &end, 10); | 132 | 17 | if (errno || end != valcstr + strlen(valcstr)) { | 133 | 0 | return false; // bad parse | 134 | 0 | } | 135 | 17 | T tmp = retval; | 136 | 17 | retval = static_cast<T>(ret64); | 137 | 17 | if (retval != ret64) { | 138 | 0 | retval = tmp; | 139 | 0 | return false; | 140 | 0 | } | 141 | 17 | return true; | 142 | 17 | } |
_ZN5doris5cloud6config12strtointegerIiEEbRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERT_ Line | Count | Source | 124 | 476 | bool strtointeger(const std::string& valstr, T& retval) { | 125 | 476 | if (valstr.length() == 0) { | 126 | 0 | return false; // empty-string is only allowed for string type. | 127 | 0 | } | 128 | 476 | char* end; | 129 | 476 | errno = 0; | 130 | 476 | const char* valcstr = valstr.c_str(); | 131 | 476 | int64_t ret64 = strtoll(valcstr, &end, 10); | 132 | 476 | if (errno || end != valcstr + strlen(valcstr)) { | 133 | 0 | return false; // bad parse | 134 | 0 | } | 135 | 476 | T tmp = retval; | 136 | 476 | retval = static_cast<T>(ret64); | 137 | 476 | if (retval != ret64) { | 138 | 0 | retval = tmp; | 139 | 0 | return false; | 140 | 0 | } | 141 | 476 | return true; | 142 | 476 | } |
_ZN5doris5cloud6config12strtointegerIlEEbRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERT_ Line | Count | Source | 124 | 485 | bool strtointeger(const std::string& valstr, T& retval) { | 125 | 485 | if (valstr.length() == 0) { | 126 | 0 | return false; // empty-string is only allowed for string type. | 127 | 0 | } | 128 | 485 | char* end; | 129 | 485 | errno = 0; | 130 | 485 | const char* valcstr = valstr.c_str(); | 131 | 485 | int64_t ret64 = strtoll(valcstr, &end, 10); | 132 | 485 | if (errno || end != valcstr + strlen(valcstr)) { | 133 | 0 | return false; // bad parse | 134 | 0 | } | 135 | 485 | T tmp = retval; | 136 | 485 | retval = static_cast<T>(ret64); | 137 | 485 | if (retval != ret64) { | 138 | 0 | retval = tmp; | 139 | 0 | return false; | 140 | 0 | } | 141 | 485 | return true; | 142 | 485 | } |
|
143 | | |
144 | 17 | bool strtox(const std::string& valstr, int16_t& retval) { |
145 | 17 | return strtointeger(valstr, retval); |
146 | 17 | } |
147 | | |
148 | 476 | bool strtox(const std::string& valstr, int32_t& retval) { |
149 | 476 | return strtointeger(valstr, retval); |
150 | 476 | } |
151 | | |
152 | 485 | bool strtox(const std::string& valstr, int64_t& retval) { |
153 | 485 | return strtointeger(valstr, retval); |
154 | 485 | } |
155 | | |
156 | 0 | bool strtox(const std::string& valstr, double& retval) { |
157 | 0 | if (valstr.length() == 0) { |
158 | 0 | return false; // empty-string is only allowed for string type. |
159 | 0 | } |
160 | 0 | char* end = nullptr; |
161 | 0 | errno = 0; |
162 | 0 | const char* valcstr = valstr.c_str(); |
163 | 0 | retval = strtod(valcstr, &end); |
164 | 0 | if (errno || end != valcstr + strlen(valcstr)) { |
165 | 0 | return false; // bad parse |
166 | 0 | } |
167 | 0 | return true; |
168 | 0 | } |
169 | | |
170 | 595 | bool strtox(const std::string& valstr, std::string& retval) { |
171 | 595 | retval = valstr; |
172 | 595 | return true; |
173 | 595 | } |
174 | | |
175 | | template <typename T> |
176 | 2.10k | bool convert(const std::string& value, T& retval) { |
177 | 2.10k | std::string valstr(value); |
178 | 2.10k | trim(valstr); |
179 | 2.10k | if (!replaceenv(valstr)) { |
180 | 0 | return false; |
181 | 0 | } |
182 | 2.10k | return strtox(valstr, retval); |
183 | 2.10k | } Unexecuted instantiation: _ZN5doris5cloud6config7convertISt6vectorIbSaIbEEEEbRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERT_ Unexecuted instantiation: _ZN5doris5cloud6config7convertISt6vectorIsSaIsEEEEbRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERT_ Unexecuted instantiation: _ZN5doris5cloud6config7convertISt6vectorIiSaIiEEEEbRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERT_ Unexecuted instantiation: _ZN5doris5cloud6config7convertISt6vectorIlSaIlEEEEbRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERT_ Unexecuted instantiation: _ZN5doris5cloud6config7convertISt6vectorIdSaIdEEEEbRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERT_ _ZN5doris5cloud6config7convertISt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS9_EEEEbRKS9_RT_ Line | Count | Source | 176 | 68 | bool convert(const std::string& value, T& retval) { | 177 | 68 | std::string valstr(value); | 178 | 68 | trim(valstr); | 179 | 68 | if (!replaceenv(valstr)) { | 180 | 0 | return false; | 181 | 0 | } | 182 | 68 | return strtox(valstr, retval); | 183 | 68 | } |
_ZN5doris5cloud6config7convertIbEEbRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERT_ Line | Count | Source | 176 | 462 | bool convert(const std::string& value, T& retval) { | 177 | 462 | std::string valstr(value); | 178 | 462 | trim(valstr); | 179 | 462 | if (!replaceenv(valstr)) { | 180 | 0 | return false; | 181 | 0 | } | 182 | 462 | return strtox(valstr, retval); | 183 | 462 | } |
_ZN5doris5cloud6config7convertIsEEbRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERT_ Line | Count | Source | 176 | 17 | bool convert(const std::string& value, T& retval) { | 177 | 17 | std::string valstr(value); | 178 | 17 | trim(valstr); | 179 | 17 | if (!replaceenv(valstr)) { | 180 | 0 | return false; | 181 | 0 | } | 182 | 17 | return strtox(valstr, retval); | 183 | 17 | } |
_ZN5doris5cloud6config7convertIiEEbRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERT_ Line | Count | Source | 176 | 476 | bool convert(const std::string& value, T& retval) { | 177 | 476 | std::string valstr(value); | 178 | 476 | trim(valstr); | 179 | 476 | if (!replaceenv(valstr)) { | 180 | 0 | return false; | 181 | 0 | } | 182 | 476 | return strtox(valstr, retval); | 183 | 476 | } |
_ZN5doris5cloud6config7convertIlEEbRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERT_ Line | Count | Source | 176 | 485 | bool convert(const std::string& value, T& retval) { | 177 | 485 | std::string valstr(value); | 178 | 485 | trim(valstr); | 179 | 485 | if (!replaceenv(valstr)) { | 180 | 0 | return false; | 181 | 0 | } | 182 | 485 | return strtox(valstr, retval); | 183 | 485 | } |
Unexecuted instantiation: _ZN5doris5cloud6config7convertIdEEbRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERT_ _ZN5doris5cloud6config7convertINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEEbRKS8_RT_ Line | Count | Source | 176 | 595 | bool convert(const std::string& value, T& retval) { | 177 | 595 | std::string valstr(value); | 178 | 595 | trim(valstr); | 179 | 595 | if (!replaceenv(valstr)) { | 180 | 0 | return false; | 181 | 0 | } | 182 | 595 | return strtox(valstr, retval); | 183 | 595 | } |
|
184 | | |
185 | | // load conf file |
186 | 19 | bool Properties::load(const char* conf_file, bool must_exist) { |
187 | | // if conf_file is null, use the empty props |
188 | 19 | if (conf_file == nullptr) { |
189 | 5 | return true; |
190 | 5 | } |
191 | | |
192 | | // open the conf file |
193 | 14 | std::ifstream input(conf_file); |
194 | 14 | if (!input.is_open()) { |
195 | 0 | if (must_exist) { |
196 | 0 | std::cerr << "config::load() failed to open the file:" << conf_file << std::endl; |
197 | 0 | return false; |
198 | 0 | } |
199 | 0 | return true; |
200 | 0 | } |
201 | | |
202 | | // load properties |
203 | 14 | std::string line; |
204 | 14 | std::string key; |
205 | 14 | std::string value; |
206 | 14 | line.reserve(512); |
207 | 420 | while (input) { |
208 | | // read one line at a time |
209 | 406 | std::getline(input, line); |
210 | | |
211 | | // remove left and right spaces |
212 | 406 | trim(line); |
213 | | |
214 | | // ignore comments |
215 | 406 | if (line.empty() || line[0] == '#') { |
216 | 317 | continue; |
217 | 317 | } |
218 | | |
219 | | // read key and value |
220 | 89 | splitkv(line, key, value); |
221 | 89 | trim(key); |
222 | 89 | trim(value); |
223 | | |
224 | | // insert into file_conf_map |
225 | 89 | file_conf_map[key] = value; |
226 | 89 | } |
227 | | |
228 | | // close the conf file |
229 | 14 | input.close(); |
230 | | |
231 | 14 | return true; |
232 | 14 | } |
233 | | |
234 | 2 | bool Properties::dump(const std::string& conffile) { |
235 | 2 | std::string conffile_tmp = conffile + ".tmp"; |
236 | | |
237 | 2 | if (std::filesystem::exists(conffile)) { |
238 | | // copy for modify |
239 | 1 | std::ifstream in(conffile, std::ios::binary); |
240 | 1 | std::ofstream out(conffile_tmp, std::ios::binary); |
241 | 1 | out << in.rdbuf(); |
242 | 1 | in.close(); |
243 | 1 | out.close(); |
244 | 1 | } |
245 | | |
246 | 2 | std::ofstream file_writer; |
247 | | |
248 | 2 | file_writer.open(conffile_tmp, std::ios::out | std::ios::app); |
249 | | |
250 | 2 | file_writer << std::endl; |
251 | | |
252 | 3 | for (auto const& iter : file_conf_map) { |
253 | 3 | file_writer << iter.first << " = " << iter.second << std::endl; |
254 | 3 | } |
255 | | |
256 | 2 | file_writer.close(); |
257 | 2 | if (!file_writer.good()) { |
258 | 0 | return false; |
259 | 0 | } |
260 | | |
261 | 2 | std::filesystem::rename(conffile_tmp, conffile); |
262 | 2 | return std::filesystem::exists(conffile); |
263 | 2 | } |
264 | | |
265 | | template <typename T> |
266 | | bool Properties::get_or_default(const char* key, const char* defstr, T& retval, |
267 | 2.09k | bool* is_retval_set) const { |
268 | 2.09k | const auto& it = file_conf_map.find(std::string(key)); |
269 | 2.09k | std::string valstr; |
270 | 2.09k | if (it == file_conf_map.end()) { |
271 | 2.00k | if (defstr == nullptr) { |
272 | | // Not found in conf map, and no default value need to be set, just return |
273 | 0 | *is_retval_set = false; |
274 | 0 | return true; |
275 | 2.00k | } else { |
276 | 2.00k | valstr = std::string(defstr); |
277 | 2.00k | } |
278 | 2.00k | } else { |
279 | 89 | valstr = it->second; |
280 | 89 | } |
281 | 2.09k | *is_retval_set = true; |
282 | 2.09k | return convert(valstr, retval); |
283 | 2.09k | } _ZNK5doris5cloud6config10Properties14get_or_defaultIbEEbPKcS5_RT_Pb Line | Count | Source | 267 | 460 | bool* is_retval_set) const { | 268 | 460 | const auto& it = file_conf_map.find(std::string(key)); | 269 | 460 | std::string valstr; | 270 | 460 | if (it == file_conf_map.end()) { | 271 | 459 | if (defstr == nullptr) { | 272 | | // Not found in conf map, and no default value need to be set, just return | 273 | 0 | *is_retval_set = false; | 274 | 0 | return true; | 275 | 459 | } else { | 276 | 459 | valstr = std::string(defstr); | 277 | 459 | } | 278 | 459 | } else { | 279 | 1 | valstr = it->second; | 280 | 1 | } | 281 | 460 | *is_retval_set = true; | 282 | 460 | return convert(valstr, retval); | 283 | 460 | } |
_ZNK5doris5cloud6config10Properties14get_or_defaultIsEEbPKcS5_RT_Pb Line | Count | Source | 267 | 17 | bool* is_retval_set) const { | 268 | 17 | const auto& it = file_conf_map.find(std::string(key)); | 269 | 17 | std::string valstr; | 270 | 17 | if (it == file_conf_map.end()) { | 271 | 17 | if (defstr == nullptr) { | 272 | | // Not found in conf map, and no default value need to be set, just return | 273 | 0 | *is_retval_set = false; | 274 | 0 | return true; | 275 | 17 | } else { | 276 | 17 | valstr = std::string(defstr); | 277 | 17 | } | 278 | 17 | } else { | 279 | 0 | valstr = it->second; | 280 | 0 | } | 281 | 17 | *is_retval_set = true; | 282 | 17 | return convert(valstr, retval); | 283 | 17 | } |
_ZNK5doris5cloud6config10Properties14get_or_defaultIiEEbPKcS5_RT_Pb Line | Count | Source | 267 | 476 | bool* is_retval_set) const { | 268 | 476 | const auto& it = file_conf_map.find(std::string(key)); | 269 | 476 | std::string valstr; | 270 | 476 | if (it == file_conf_map.end()) { | 271 | 452 | if (defstr == nullptr) { | 272 | | // Not found in conf map, and no default value need to be set, just return | 273 | 0 | *is_retval_set = false; | 274 | 0 | return true; | 275 | 452 | } else { | 276 | 452 | valstr = std::string(defstr); | 277 | 452 | } | 278 | 452 | } else { | 279 | 24 | valstr = it->second; | 280 | 24 | } | 281 | 476 | *is_retval_set = true; | 282 | 476 | return convert(valstr, retval); | 283 | 476 | } |
_ZNK5doris5cloud6config10Properties14get_or_defaultIlEEbPKcS5_RT_Pb Line | Count | Source | 267 | 480 | bool* is_retval_set) const { | 268 | 480 | const auto& it = file_conf_map.find(std::string(key)); | 269 | 480 | std::string valstr; | 270 | 480 | if (it == file_conf_map.end()) { | 271 | 464 | if (defstr == nullptr) { | 272 | | // Not found in conf map, and no default value need to be set, just return | 273 | 0 | *is_retval_set = false; | 274 | 0 | return true; | 275 | 464 | } else { | 276 | 464 | valstr = std::string(defstr); | 277 | 464 | } | 278 | 464 | } else { | 279 | 16 | valstr = it->second; | 280 | 16 | } | 281 | 480 | *is_retval_set = true; | 282 | 480 | return convert(valstr, retval); | 283 | 480 | } |
Unexecuted instantiation: _ZNK5doris5cloud6config10Properties14get_or_defaultIdEEbPKcS5_RT_Pb _ZNK5doris5cloud6config10Properties14get_or_defaultINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEEbPKcSB_RT_Pb Line | Count | Source | 267 | 595 | bool* is_retval_set) const { | 268 | 595 | const auto& it = file_conf_map.find(std::string(key)); | 269 | 595 | std::string valstr; | 270 | 595 | if (it == file_conf_map.end()) { | 271 | 547 | if (defstr == nullptr) { | 272 | | // Not found in conf map, and no default value need to be set, just return | 273 | 0 | *is_retval_set = false; | 274 | 0 | return true; | 275 | 547 | } else { | 276 | 547 | valstr = std::string(defstr); | 277 | 547 | } | 278 | 547 | } else { | 279 | 48 | valstr = it->second; | 280 | 48 | } | 281 | 595 | *is_retval_set = true; | 282 | 595 | return convert(valstr, retval); | 283 | 595 | } |
Unexecuted instantiation: _ZNK5doris5cloud6config10Properties14get_or_defaultISt6vectorIbSaIbEEEEbPKcS8_RT_Pb Unexecuted instantiation: _ZNK5doris5cloud6config10Properties14get_or_defaultISt6vectorIsSaIsEEEEbPKcS8_RT_Pb Unexecuted instantiation: _ZNK5doris5cloud6config10Properties14get_or_defaultISt6vectorIiSaIiEEEEbPKcS8_RT_Pb Unexecuted instantiation: _ZNK5doris5cloud6config10Properties14get_or_defaultISt6vectorIlSaIlEEEEbPKcS8_RT_Pb Unexecuted instantiation: _ZNK5doris5cloud6config10Properties14get_or_defaultISt6vectorIdSaIdEEEEbPKcS8_RT_Pb _ZNK5doris5cloud6config10Properties14get_or_defaultISt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaISA_EEEEbPKcSE_RT_Pb Line | Count | Source | 267 | 68 | bool* is_retval_set) const { | 268 | 68 | const auto& it = file_conf_map.find(std::string(key)); | 269 | 68 | std::string valstr; | 270 | 68 | if (it == file_conf_map.end()) { | 271 | 68 | if (defstr == nullptr) { | 272 | | // Not found in conf map, and no default value need to be set, just return | 273 | 0 | *is_retval_set = false; | 274 | 0 | return true; | 275 | 68 | } else { | 276 | 68 | valstr = std::string(defstr); | 277 | 68 | } | 278 | 68 | } else { | 279 | 0 | valstr = it->second; | 280 | 0 | } | 281 | 68 | *is_retval_set = true; | 282 | 68 | return convert(valstr, retval); | 283 | 68 | } |
|
284 | | |
285 | 0 | void Properties::set(const std::string& key, const std::string& val) { |
286 | 0 | file_conf_map.emplace(key, val); |
287 | 0 | } |
288 | | |
289 | 3 | void Properties::set_force(const std::string& key, const std::string& val) { |
290 | 3 | file_conf_map[key] = val; |
291 | 3 | } |
292 | | |
293 | | template <typename T> |
294 | 68 | std::ostream& operator<<(std::ostream& out, const std::vector<T>& v) { |
295 | 68 | size_t last = v.size() - 1; |
296 | 68 | for (size_t i = 0; i < v.size(); ++i) { |
297 | 0 | out << v[i]; |
298 | 0 | if (i != last) { |
299 | 0 | out << ", "; |
300 | 0 | } |
301 | 0 | } |
302 | 68 | return out; |
303 | 68 | } Unexecuted instantiation: _ZN5doris5cloud6configlsIbEERSoS3_RKSt6vectorIT_SaIS5_EE Unexecuted instantiation: _ZN5doris5cloud6configlsIsEERSoS3_RKSt6vectorIT_SaIS5_EE Unexecuted instantiation: _ZN5doris5cloud6configlsIiEERSoS3_RKSt6vectorIT_SaIS5_EE Unexecuted instantiation: _ZN5doris5cloud6configlsIlEERSoS3_RKSt6vectorIT_SaIS5_EE Unexecuted instantiation: _ZN5doris5cloud6configlsIdEERSoS3_RKSt6vectorIT_SaIS5_EE _ZN5doris5cloud6configlsINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEERSoS9_RKSt6vectorIT_SaISB_EE Line | Count | Source | 294 | 68 | std::ostream& operator<<(std::ostream& out, const std::vector<T>& v) { | 295 | 68 | size_t last = v.size() - 1; | 296 | 68 | for (size_t i = 0; i < v.size(); ++i) { | 297 | 0 | out << v[i]; | 298 | 0 | if (i != last) { | 299 | 0 | out << ", "; | 300 | 0 | } | 301 | 0 | } | 302 | 68 | return out; | 303 | 68 | } |
|
304 | | |
305 | | #define SET_FIELD(FIELD, TYPE, FILL_CONF_MAP, SET_TO_DEFAULT) \ |
306 | 8.21k | if (strcmp((FIELD).type, #TYPE) == 0) { \ |
307 | 2.09k | TYPE new_value = TYPE(); \ |
308 | 2.09k | bool is_newval_set = false; \ |
309 | 2.09k | if (!props.get_or_default((FIELD).name, ((SET_TO_DEFAULT) ? (FIELD).defval : nullptr), \ |
310 | 2.09k | new_value, &is_newval_set)) { \ |
311 | 0 | std::cerr << "config field error: " << (FIELD).name << std::endl; \ |
312 | 0 | return false; \ |
313 | 0 | } \ |
314 | 2.09k | if (!is_newval_set) { \ |
315 | 0 | continue; \ |
316 | 0 | } \ |
317 | 2.09k | TYPE& ref_conf_value = *reinterpret_cast<TYPE*>((FIELD).storage); \ |
318 | 2.09k | TYPE old_value = ref_conf_value; \ |
319 | 2.09k | ref_conf_value = new_value; \ |
320 | 2.09k | if (RegisterConfValidator::_s_field_validator != nullptr) { \ |
321 | 2.09k | auto validator = RegisterConfValidator::_s_field_validator->find((FIELD).name); \ |
322 | 2.09k | if (validator != RegisterConfValidator::_s_field_validator->end() && \ |
323 | 2.09k | !(validator->second)()) { \ |
324 | 0 | ref_conf_value = old_value; \ |
325 | 0 | std::cerr << "validate " << (FIELD).name << "=" << new_value << " failed" \ |
326 | 0 | << std::endl; \ |
327 | 0 | return false; \ |
328 | 0 | } \ |
329 | 2.09k | } \ |
330 | 2.09k | if (FILL_CONF_MAP) { \ |
331 | 2.09k | std::ostringstream oss; \ |
332 | 2.09k | oss << ref_conf_value; \ |
333 | 2.09k | (*full_conf_map)[(FIELD).name] = oss.str(); \ |
334 | 2.09k | } \ |
335 | 2.09k | continue; \ |
336 | 2.09k | } |
337 | | |
338 | | #define UPDATE_FIELD(FIELD, VALUE, TYPE, PERSIST) \ |
339 | 22 | if (strcmp((FIELD).type, #TYPE) == 0) { \ |
340 | 7 | TYPE new_value; \ |
341 | 7 | if (!convert((VALUE), new_value)) { \ |
342 | 0 | std::cerr << "convert " << VALUE << "as" << #TYPE << "failed"; \ |
343 | 0 | return false; \ |
344 | 0 | } \ |
345 | 7 | TYPE& ref_conf_value = *reinterpret_cast<TYPE*>((FIELD).storage); \ |
346 | 7 | TYPE old_value = ref_conf_value; \ |
347 | 7 | if (RegisterConfValidator::_s_field_validator != nullptr) { \ |
348 | 7 | auto validator = RegisterConfValidator::_s_field_validator->find((FIELD).name); \ |
349 | 7 | if (validator != RegisterConfValidator::_s_field_validator->end() && \ |
350 | 7 | !(validator->second)()) { \ |
351 | 0 | ref_conf_value = old_value; \ |
352 | 0 | std::cerr << "validate " << (FIELD).name << "=" << new_value << " failed" \ |
353 | 0 | << std::endl; \ |
354 | 0 | return false; \ |
355 | 0 | } \ |
356 | 7 | } \ |
357 | 7 | ref_conf_value = new_value; \ |
358 | 7 | if (full_conf_map != nullptr) { \ |
359 | 7 | std::ostringstream oss; \ |
360 | 7 | oss << new_value; \ |
361 | 7 | (*full_conf_map)[(FIELD).name] = oss.str(); \ |
362 | 7 | } \ |
363 | 7 | if (PERSIST) { \ |
364 | 3 | props.set_force(std::string((FIELD).name), VALUE); \ |
365 | 3 | } \ |
366 | 7 | return true; \ |
367 | 7 | } |
368 | | |
369 | | // init conf fields |
370 | 17 | bool init(const char* conf_file, bool fill_conf_map, bool must_exist, bool set_to_default) { |
371 | 17 | Properties props; |
372 | | // load properties file |
373 | 17 | if (!props.load(conf_file, must_exist)) { |
374 | 0 | return false; |
375 | 0 | } |
376 | | // fill full_conf_map ? |
377 | 17 | if (fill_conf_map && full_conf_map == nullptr) { |
378 | 17 | full_conf_map = new std::map<std::string, std::string>(); |
379 | 17 | } |
380 | | |
381 | | // set conf fields |
382 | 2.09k | for (const auto& it : *Register::_s_field_map) { |
383 | 2.09k | SET_FIELD(it.second, bool, fill_conf_map, set_to_default); |
384 | 1.63k | SET_FIELD(it.second, int16_t, fill_conf_map, set_to_default); |
385 | 1.61k | SET_FIELD(it.second, int32_t, fill_conf_map, set_to_default); |
386 | 1.13k | SET_FIELD(it.second, int64_t, fill_conf_map, set_to_default); |
387 | 663 | SET_FIELD(it.second, double, fill_conf_map, set_to_default); |
388 | 663 | SET_FIELD(it.second, std::string, fill_conf_map, set_to_default); |
389 | 68 | SET_FIELD(it.second, std::vector<bool>, fill_conf_map, set_to_default); |
390 | 68 | SET_FIELD(it.second, std::vector<int16_t>, fill_conf_map, set_to_default); |
391 | 68 | SET_FIELD(it.second, std::vector<int32_t>, fill_conf_map, set_to_default); |
392 | 68 | SET_FIELD(it.second, std::vector<int64_t>, fill_conf_map, set_to_default); |
393 | 68 | SET_FIELD(it.second, std::vector<double>, fill_conf_map, set_to_default); |
394 | 68 | SET_FIELD(it.second, std::vector<std::string>, fill_conf_map, set_to_default); |
395 | 0 | } |
396 | | |
397 | 17 | return true; |
398 | 17 | } |
399 | | |
400 | | bool do_set_config(const Register::Field& feild, const std::string& value, bool need_persist, |
401 | 7 | Properties& props) { |
402 | 7 | UPDATE_FIELD(feild, value, bool, need_persist); |
403 | 5 | UPDATE_FIELD(feild, value, int16_t, need_persist); |
404 | 5 | UPDATE_FIELD(feild, value, int32_t, need_persist); |
405 | 5 | UPDATE_FIELD(feild, value, int64_t, need_persist); |
406 | 0 | UPDATE_FIELD(feild, value, double, need_persist); |
407 | 0 | { |
408 | | // add lock to ensure thread safe |
409 | 0 | std::lock_guard<std::mutex> lock(mutable_string_config_lock); |
410 | 0 | UPDATE_FIELD(feild, value, std::string, need_persist); |
411 | 0 | } |
412 | 0 | return false; |
413 | 0 | } |
414 | | |
415 | | std::pair<bool, std::string> set_config(const std::string& field, const std::string& value, |
416 | 9 | bool need_persist, Properties& props) { |
417 | 9 | auto it = Register::_s_field_map->find(field); |
418 | 9 | if (it == Register::_s_field_map->end()) { |
419 | 1 | return {false, fmt::format("config field={} not exists", field)}; |
420 | 1 | } |
421 | 8 | if (!it->second.valmutable) { |
422 | 1 | return {false, fmt::format("config field={} is immutable", field)}; |
423 | 1 | } |
424 | | |
425 | 7 | if (!do_set_config(it->second, value, need_persist, props)) { |
426 | 0 | return {false, fmt::format("not supported to modify field={}, value={}", field, value)}; |
427 | 0 | } |
428 | 7 | return {true, {}}; |
429 | 7 | } |
430 | | |
431 | | std::pair<bool, std::string> set_config(std::unordered_map<std::string, std::string> field_map, |
432 | 7 | bool need_persist, const std::string& custom_conf_path) { |
433 | 7 | Properties props; |
434 | 7 | auto set_conf_closure = [&]() -> std::pair<bool, std::string> { |
435 | 9 | for (const auto& [field, value] : field_map) { |
436 | 9 | if (auto [succ, cause] = set_config(field, value, need_persist, props); !succ) { |
437 | 2 | return {false, std::move(cause)}; |
438 | 2 | } |
439 | 9 | } |
440 | 5 | return {true, {}}; |
441 | 7 | }; |
442 | | |
443 | 7 | if (!need_persist) { |
444 | 5 | return set_conf_closure(); |
445 | 5 | } |
446 | | |
447 | | // lock to make sure only one thread can modify the conf file |
448 | 2 | std::lock_guard<std::mutex> l(conf_persist_lock); |
449 | 2 | auto [succ, cause] = set_conf_closure(); |
450 | 2 | if (!succ) { |
451 | 0 | return {succ, std::move(cause)}; |
452 | 0 | } |
453 | 2 | if (props.dump(custom_conf_path)) { |
454 | 2 | return {true, {}}; |
455 | 2 | } |
456 | 0 | return {false, fmt::format("dump config modification to custom_conf_path={} " |
457 | 0 | "failed, plz check config::custom_conf_path and io status", |
458 | 0 | custom_conf_path)}; |
459 | 2 | } |
460 | | } // namespace doris::cloud::config |