Coverage Report

Created: 2025-05-21 15:45

/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
2.80k
std::string& trim(std::string& s) {
47
    // rtrim
48
2.80k
    s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char c) { return !std::isspace(c); })
49
2.80k
                    .base(),
50
2.80k
            s.end());
51
    // ltrim
52
2.80k
    s.erase(s.begin(),
53
2.80k
            std::find_if(s.begin(), s.end(), [](unsigned char c) { return !std::isspace(c); }));
54
2.80k
    return s;
55
2.80k
}
56
57
// split string by '='
58
100
void splitkv(const std::string& s, std::string& k, std::string& v) {
59
100
    const char sep = '=';
60
100
    int start = 0;
61
100
    int end = 0;
62
100
    if ((end = s.find(sep, start)) != std::string::npos) {
63
100
        k = s.substr(start, end - start);
64
100
        v = s.substr(end + 1);
65
100
    } else {
66
0
        k = s;
67
0
        v = "";
68
0
    }
69
100
}
70
71
// replace env variables
72
2.17k
bool replaceenv(std::string& s) {
73
2.17k
    std::size_t pos = 0;
74
2.17k
    std::size_t start = 0;
75
2.17k
    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.17k
    return true;
90
2.17k
}
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
68
bool strtox(const std::string& valstr, std::vector<T>& retval) {
101
68
    std::stringstream ss(valstr);
102
68
    std::string item;
103
68
    T t;
104
68
    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
68
    return true;
111
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
100
68
bool strtox(const std::string& valstr, std::vector<T>& retval) {
101
68
    std::stringstream ss(valstr);
102
68
    std::string item;
103
68
    T t;
104
68
    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
68
    return true;
111
68
}
112
113
496
bool strtox(const std::string& valstr, bool& retval) {
114
496
    if (valstr.compare("true") == 0) {
115
205
        retval = true;
116
291
    } else if (valstr.compare("false") == 0) {
117
291
        retval = false;
118
291
    } else {
119
0
        return false;
120
0
    }
121
496
    return true;
122
496
}
123
124
template <typename T>
125
995
bool strtointeger(const std::string& valstr, T& retval) {
126
995
    if (valstr.length() == 0) {
127
0
        return false; // empty-string is only allowed for string type.
128
0
    }
129
995
    char* end;
130
995
    errno = 0;
131
995
    const char* valcstr = valstr.c_str();
132
995
    int64_t ret64 = strtoll(valcstr, &end, 10);
133
995
    if (errno || end != valcstr + strlen(valcstr)) {
134
0
        return false; // bad parse
135
0
    }
136
995
    T tmp = retval;
137
995
    retval = static_cast<T>(ret64);
138
995
    if (retval != ret64) {
139
0
        retval = tmp;
140
0
        return false;
141
0
    }
142
995
    return true;
143
995
}
_ZN5doris5cloud6config12strtointegerIsEEbRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERT_
Line
Count
Source
125
17
bool strtointeger(const std::string& valstr, T& retval) {
126
17
    if (valstr.length() == 0) {
127
0
        return false; // empty-string is only allowed for string type.
128
0
    }
129
17
    char* end;
130
17
    errno = 0;
131
17
    const char* valcstr = valstr.c_str();
132
17
    int64_t ret64 = strtoll(valcstr, &end, 10);
133
17
    if (errno || end != valcstr + strlen(valcstr)) {
134
0
        return false; // bad parse
135
0
    }
136
17
    T tmp = retval;
137
17
    retval = static_cast<T>(ret64);
138
17
    if (retval != ret64) {
139
0
        retval = tmp;
140
0
        return false;
141
0
    }
142
17
    return true;
143
17
}
_ZN5doris5cloud6config12strtointegerIiEEbRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERT_
Line
Count
Source
125
476
bool strtointeger(const std::string& valstr, T& retval) {
126
476
    if (valstr.length() == 0) {
127
0
        return false; // empty-string is only allowed for string type.
128
0
    }
129
476
    char* end;
130
476
    errno = 0;
131
476
    const char* valcstr = valstr.c_str();
132
476
    int64_t ret64 = strtoll(valcstr, &end, 10);
133
476
    if (errno || end != valcstr + strlen(valcstr)) {
134
0
        return false; // bad parse
135
0
    }
136
476
    T tmp = retval;
137
476
    retval = static_cast<T>(ret64);
138
476
    if (retval != ret64) {
139
0
        retval = tmp;
140
0
        return false;
141
0
    }
142
476
    return true;
143
476
}
_ZN5doris5cloud6config12strtointegerIlEEbRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERT_
Line
Count
Source
125
502
bool strtointeger(const std::string& valstr, T& retval) {
126
502
    if (valstr.length() == 0) {
127
0
        return false; // empty-string is only allowed for string type.
128
0
    }
129
502
    char* end;
130
502
    errno = 0;
131
502
    const char* valcstr = valstr.c_str();
132
502
    int64_t ret64 = strtoll(valcstr, &end, 10);
133
502
    if (errno || end != valcstr + strlen(valcstr)) {
134
0
        return false; // bad parse
135
0
    }
136
502
    T tmp = retval;
137
502
    retval = static_cast<T>(ret64);
138
502
    if (retval != ret64) {
139
0
        retval = tmp;
140
0
        return false;
141
0
    }
142
502
    return true;
143
502
}
144
145
17
bool strtox(const std::string& valstr, int16_t& retval) {
146
17
    return strtointeger(valstr, retval);
147
17
}
148
149
476
bool strtox(const std::string& valstr, int32_t& retval) {
150
476
    return strtointeger(valstr, retval);
151
476
}
152
153
502
bool strtox(const std::string& valstr, int64_t& retval) {
154
502
    return strtointeger(valstr, retval);
155
502
}
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
618
bool strtox(const std::string& valstr, std::string& retval) {
172
618
    retval = valstr;
173
618
    return true;
174
618
}
175
176
template <typename T>
177
2.17k
bool convert(const std::string& value, T& retval) {
178
2.17k
    std::string valstr(value);
179
2.17k
    trim(valstr);
180
2.17k
    if (!replaceenv(valstr)) {
181
0
        return false;
182
0
    }
183
2.17k
    return strtox(valstr, retval);
184
2.17k
}
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
68
bool convert(const std::string& value, T& retval) {
178
68
    std::string valstr(value);
179
68
    trim(valstr);
180
68
    if (!replaceenv(valstr)) {
181
0
        return false;
182
0
    }
183
68
    return strtox(valstr, retval);
184
68
}
_ZN5doris5cloud6config7convertIbEEbRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERT_
Line
Count
Source
177
496
bool convert(const std::string& value, T& retval) {
178
496
    std::string valstr(value);
179
496
    trim(valstr);
180
496
    if (!replaceenv(valstr)) {
181
0
        return false;
182
0
    }
183
496
    return strtox(valstr, retval);
184
496
}
_ZN5doris5cloud6config7convertIsEEbRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERT_
Line
Count
Source
177
17
bool convert(const std::string& value, T& retval) {
178
17
    std::string valstr(value);
179
17
    trim(valstr);
180
17
    if (!replaceenv(valstr)) {
181
0
        return false;
182
0
    }
183
17
    return strtox(valstr, retval);
184
17
}
_ZN5doris5cloud6config7convertIiEEbRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERT_
Line
Count
Source
177
476
bool convert(const std::string& value, T& retval) {
178
476
    std::string valstr(value);
179
476
    trim(valstr);
180
476
    if (!replaceenv(valstr)) {
181
0
        return false;
182
0
    }
183
476
    return strtox(valstr, retval);
184
476
}
_ZN5doris5cloud6config7convertIlEEbRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERT_
Line
Count
Source
177
502
bool convert(const std::string& value, T& retval) {
178
502
    std::string valstr(value);
179
502
    trim(valstr);
180
502
    if (!replaceenv(valstr)) {
181
0
        return false;
182
0
    }
183
502
    return strtox(valstr, retval);
184
502
}
Unexecuted instantiation: _ZN5doris5cloud6config7convertIdEEbRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERT_
_ZN5doris5cloud6config7convertINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEEbRKS8_RT_
Line
Count
Source
177
618
bool convert(const std::string& value, T& retval) {
178
618
    std::string valstr(value);
179
618
    trim(valstr);
180
618
    if (!replaceenv(valstr)) {
181
0
        return false;
182
0
    }
183
618
    return strtox(valstr, retval);
184
618
}
185
186
// load conf file
187
21
bool Properties::load(const char* conf_file, bool must_exist) {
188
    // if conf_file is null, use the empty props
189
21
    if (conf_file == nullptr) {
190
5
        return true;
191
5
    }
192
193
    // open the conf file
194
16
    std::ifstream input(conf_file);
195
16
    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
16
    std::string line;
205
16
    std::string key;
206
16
    std::string value;
207
16
    line.reserve(512);
208
444
    while (input) {
209
        // read one line at a time
210
428
        std::getline(input, line);
211
212
        // remove left and right spaces
213
428
        trim(line);
214
215
        // ignore comments
216
428
        if (line.empty() || line[0] == '#') {
217
328
            continue;
218
328
        }
219
220
        // read key and value
221
100
        splitkv(line, key, value);
222
100
        trim(key);
223
100
        trim(value);
224
225
        // insert into file_conf_map
226
100
        file_conf_map[key] = value;
227
100
    }
228
229
    // close the conf file
230
16
    input.close();
231
232
16
    return true;
233
16
}
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.16k
                                bool* is_retval_set) const {
269
2.16k
    const auto& it = file_conf_map.find(std::string(key));
270
2.16k
    std::string valstr;
271
2.16k
    if (it == file_conf_map.end()) {
272
2.07k
        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.07k
        } else {
277
2.07k
            valstr = std::string(defstr);
278
2.07k
        }
279
2.07k
    } else {
280
92
        valstr = it->second;
281
92
    }
282
2.16k
    *is_retval_set = true;
283
2.16k
    return convert(valstr, retval);
284
2.16k
}
_ZNK5doris5cloud6config10Properties14get_or_defaultIbEEbPKcS5_RT_Pb
Line
Count
Source
268
494
                                bool* is_retval_set) const {
269
494
    const auto& it = file_conf_map.find(std::string(key));
270
494
    std::string valstr;
271
494
    if (it == file_conf_map.end()) {
272
493
        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
493
        } else {
277
493
            valstr = std::string(defstr);
278
493
        }
279
493
    } else {
280
1
        valstr = it->second;
281
1
    }
282
494
    *is_retval_set = true;
283
494
    return convert(valstr, retval);
284
494
}
_ZNK5doris5cloud6config10Properties14get_or_defaultIsEEbPKcS5_RT_Pb
Line
Count
Source
268
17
                                bool* is_retval_set) const {
269
17
    const auto& it = file_conf_map.find(std::string(key));
270
17
    std::string valstr;
271
17
    if (it == file_conf_map.end()) {
272
17
        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
17
        } else {
277
17
            valstr = std::string(defstr);
278
17
        }
279
17
    } else {
280
0
        valstr = it->second;
281
0
    }
282
17
    *is_retval_set = true;
283
17
    return convert(valstr, retval);
284
17
}
_ZNK5doris5cloud6config10Properties14get_or_defaultIiEEbPKcS5_RT_Pb
Line
Count
Source
268
476
                                bool* is_retval_set) const {
269
476
    const auto& it = file_conf_map.find(std::string(key));
270
476
    std::string valstr;
271
476
    if (it == file_conf_map.end()) {
272
452
        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
452
        } else {
277
452
            valstr = std::string(defstr);
278
452
        }
279
452
    } else {
280
24
        valstr = it->second;
281
24
    }
282
476
    *is_retval_set = true;
283
476
    return convert(valstr, retval);
284
476
}
_ZNK5doris5cloud6config10Properties14get_or_defaultIlEEbPKcS5_RT_Pb
Line
Count
Source
268
497
                                bool* is_retval_set) const {
269
497
    const auto& it = file_conf_map.find(std::string(key));
270
497
    std::string valstr;
271
497
    if (it == file_conf_map.end()) {
272
481
        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
481
        } else {
277
481
            valstr = std::string(defstr);
278
481
        }
279
481
    } else {
280
16
        valstr = it->second;
281
16
    }
282
497
    *is_retval_set = true;
283
497
    return convert(valstr, retval);
284
497
}
Unexecuted instantiation: _ZNK5doris5cloud6config10Properties14get_or_defaultIdEEbPKcS5_RT_Pb
_ZNK5doris5cloud6config10Properties14get_or_defaultINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEEbPKcSB_RT_Pb
Line
Count
Source
268
615
                                bool* is_retval_set) const {
269
615
    const auto& it = file_conf_map.find(std::string(key));
270
615
    std::string valstr;
271
615
    if (it == file_conf_map.end()) {
272
564
        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
564
        } else {
277
564
            valstr = std::string(defstr);
278
564
        }
279
564
    } else {
280
51
        valstr = it->second;
281
51
    }
282
615
    *is_retval_set = true;
283
615
    return convert(valstr, retval);
284
615
}
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
68
                                bool* is_retval_set) const {
269
68
    const auto& it = file_conf_map.find(std::string(key));
270
68
    std::string valstr;
271
68
    if (it == file_conf_map.end()) {
272
68
        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
68
        } else {
277
68
            valstr = std::string(defstr);
278
68
        }
279
68
    } else {
280
0
        valstr = it->second;
281
0
    }
282
68
    *is_retval_set = true;
283
68
    return convert(valstr, retval);
284
68
}
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
68
std::ostream& operator<<(std::ostream& out, const std::vector<T>& v) {
296
68
    size_t last = v.size() - 1;
297
68
    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
68
    return out;
304
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
295
68
std::ostream& operator<<(std::ostream& out, const std::vector<T>& v) {
296
68
    size_t last = v.size() - 1;
297
68
    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
68
    return out;
304
68
}
305
306
#define SET_FIELD(FIELD, TYPE, FILL_CONF_MAP, SET_TO_DEFAULT)                                  \
307
8.41k
    if (strcmp((FIELD).type, #TYPE) == 0) {                                                    \
308
2.15k
        TYPE new_value = TYPE();                                                               \
309
2.15k
        bool is_newval_set = false;                                                            \
310
2.15k
        if (!props.get_or_default((FIELD).name, ((SET_TO_DEFAULT) ? (FIELD).defval : nullptr), \
311
2.15k
                                  new_value, &is_newval_set)) {                                \
312
0
            std::cerr << "config field error: " << (FIELD).name << std::endl;                  \
313
0
            return false;                                                                      \
314
0
        }                                                                                      \
315
2.15k
        if (!is_newval_set) {                                                                  \
316
0
            continue;                                                                          \
317
0
        }                                                                                      \
318
2.15k
        TYPE& ref_conf_value = *reinterpret_cast<TYPE*>((FIELD).storage);                      \
319
2.15k
        TYPE old_value = ref_conf_value;                                                       \
320
2.15k
        ref_conf_value = new_value;                                                            \
321
2.15k
        if (RegisterConfValidator::_s_field_validator != nullptr) {                            \
322
2.15k
            auto validator = RegisterConfValidator::_s_field_validator->find((FIELD).name);    \
323
2.15k
            if (validator != RegisterConfValidator::_s_field_validator->end() &&               \
324
2.15k
                !(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.15k
        }                                                                                      \
331
2.15k
        if (FILL_CONF_MAP) {                                                                   \
332
2.15k
            std::ostringstream oss;                                                            \
333
2.15k
            oss << ref_conf_value;                                                             \
334
2.15k
            (*full_conf_map)[(FIELD).name] = oss.str();                                        \
335
2.15k
        }                                                                                      \
336
2.15k
        continue;                                                                              \
337
2.15k
    }
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
17
bool init(const char* conf_file, bool fill_conf_map, bool must_exist, bool set_to_default) {
372
17
    Properties props;
373
    // load properties file
374
17
    if (!props.load(conf_file, must_exist)) {
375
0
        return false;
376
0
    }
377
    // fill full_conf_map ?
378
17
    if (fill_conf_map && full_conf_map == nullptr) {
379
17
        full_conf_map = new std::map<std::string, std::string>();
380
17
    }
381
382
    // set conf fields
383
2.15k
    for (const auto& it : *Register::_s_field_map) {
384
2.15k
        SET_FIELD(it.second, bool, fill_conf_map, set_to_default);
385
1.66k
        SET_FIELD(it.second, int16_t, fill_conf_map, set_to_default);
386
1.64k
        SET_FIELD(it.second, int32_t, fill_conf_map, set_to_default);
387
1.17k
        SET_FIELD(it.second, int64_t, fill_conf_map, set_to_default);
388
680
        SET_FIELD(it.second, double, fill_conf_map, set_to_default);
389
680
        SET_FIELD(it.second, std::string, fill_conf_map, set_to_default);
390
68
        SET_FIELD(it.second, std::vector<bool>, fill_conf_map, set_to_default);
391
68
        SET_FIELD(it.second, std::vector<int16_t>, fill_conf_map, set_to_default);
392
68
        SET_FIELD(it.second, std::vector<int32_t>, fill_conf_map, set_to_default);
393
68
        SET_FIELD(it.second, std::vector<int64_t>, fill_conf_map, set_to_default);
394
68
        SET_FIELD(it.second, std::vector<double>, fill_conf_map, set_to_default);
395
68
        SET_FIELD(it.second, std::vector<std::string>, fill_conf_map, set_to_default);
396
0
    }
397
398
17
    return true;
399
17
}
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
476
std::shared_mutex* get_mutable_string_config_lock() {
463
476
    return &mutable_string_config_lock;
464
476
}
465
} // namespace doris::cloud::config