Coverage Report

Created: 2025-07-30 19:38

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