Coverage Report

Created: 2025-06-20 10:53

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