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