1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "db_config.h"
17
18 #include <algorithm>
19 #include <cstring>
20 #include <functional>
21 #include <memory>
22
23 #include "doc_errno.h"
24 #include "doc_limit.h"
25 #include "rd_json_object.h"
26 #include "rd_log_print.h"
27
28 namespace DocumentDB {
29 namespace {
30 constexpr int MIN_REDO_BUFFER_SIZE = 256;
31 constexpr int MAX_REDO_BUFFER_SIZE = 16384;
32 constexpr int MIN_CONNECTION_NUM = 16;
33 constexpr int MAX_CONNECTION_NUM = 1024;
34 constexpr int MIN_BUFFER_POOL_SIZE = 1024;
35 constexpr int MAX_BUFFER_POOL_SIZE = 4 * 1024 * 1024;
36
37 constexpr const char *DB_CONFIG_PAGESIZE = "pagesize";
38 constexpr const char *DB_CONFIG_REDO_FLUSH_BY_TRX = "redoflushbytrx";
39 constexpr const char *DB_CONFIG_REDO_PUB_BUFF_SIZE = "redopubbufsize";
40 constexpr const char *DB_CONFIG_MAX_CONN_NUM = "maxconnnum";
41 constexpr const char *DB_CONFIG_BUFFER_POOL_SIZE = "bufferpoolsize";
42 constexpr const char *DB_CONFIG_CRC_CHECK_ENABLE = "crccheckenable";
43 constexpr const char *DB_CONFIG_BUFFPOOL_POLICY = "bufferpoolpolicy";
44 constexpr const char *DB_CONFIG_SHARED_MODE = "sharedmodeenable";
45
46 constexpr const char *DB_CONFIG[] = { DB_CONFIG_PAGESIZE, DB_CONFIG_REDO_FLUSH_BY_TRX,
47 DB_CONFIG_REDO_PUB_BUFF_SIZE, DB_CONFIG_MAX_CONN_NUM, DB_CONFIG_BUFFER_POOL_SIZE, DB_CONFIG_CRC_CHECK_ENABLE,
48 DB_CONFIG_BUFFPOOL_POLICY, DB_CONFIG_SHARED_MODE};
49
50 template<typename T>
CheckAndGetDBConfig(const JsonObject & config,const std::string & name,const std::function<bool (T)> & checkValid,T & val)51 bool CheckAndGetDBConfig(const JsonObject &config, const std::string &name, const std::function<bool(T)> &checkValid,
52 T &val)
53 {
54 const JsonFieldPath configField = { name };
55 if (!config.IsFieldExists(configField)) {
56 return true;
57 }
58
59 int errCode = E_OK;
60 ValueObject configValue = config.GetObjectByPath(configField, errCode);
61 if (errCode != E_OK) {
62 GLOGE("Can not find config Value");
63 return errCode;
64 }
65 if (configValue.GetValueType() != ValueObject::ValueType::VALUE_NUMBER) {
66 GLOGE("Check DB config failed, not found or type of %s is not NUMBER.", name.c_str());
67 return false;
68 }
69
70 if (checkValid && !checkValid(static_cast<T>(configValue.GetIntValue()))) {
71 GLOGE("Check DB config failed, invalid %s value.", name.c_str());
72 return false;
73 }
74
75 val = static_cast<T>(configValue.GetIntValue());
76 return true;
77 }
78
CheckPageSizeConfig(const JsonObject & config,int32_t & pageSize)79 bool CheckPageSizeConfig(const JsonObject &config, int32_t &pageSize)
80 {
81 std::function<bool(int32_t)> checkFunction = [](int32_t val) {
82 static const std::vector<int32_t> pageSizeValid = { 4, 8, 16, 32, 64 };
83 return std::find(pageSizeValid.begin(), pageSizeValid.end(), val) != pageSizeValid.end();
84 };
85 return CheckAndGetDBConfig(config, DB_CONFIG_PAGESIZE, checkFunction, pageSize);
86 }
87
CheckRedoFlushConfig(const JsonObject & config,uint32_t & redoFlush)88 bool CheckRedoFlushConfig(const JsonObject &config, uint32_t &redoFlush)
89 {
90 std::function<bool(uint32_t)> checkFunction = [](uint32_t val) {
91 return val == 0 || val == 1;
92 };
93 return CheckAndGetDBConfig(config, DB_CONFIG_REDO_FLUSH_BY_TRX, checkFunction, redoFlush);
94 }
95
CheckRedoBufSizeConfig(const JsonObject & config,int32_t pageSize,uint32_t & redoBufSize)96 bool CheckRedoBufSizeConfig(const JsonObject &config, int32_t pageSize, uint32_t &redoBufSize)
97 {
98 std::function<bool(uint32_t)> checkFunction = [pageSize](uint32_t val) {
99 return val >= MIN_REDO_BUFFER_SIZE && val <= MAX_REDO_BUFFER_SIZE &&
100 val > static_cast<uint32_t>(pageSize * 63); // 63: pool size should be 63 times larger then pageSize
101 };
102 return CheckAndGetDBConfig(config, DB_CONFIG_REDO_PUB_BUFF_SIZE, checkFunction, redoBufSize);
103 }
104
CheckMaxConnNumConfig(const JsonObject & config,int32_t & maxConnNum)105 bool CheckMaxConnNumConfig(const JsonObject &config, int32_t &maxConnNum)
106 {
107 std::function<bool(int32_t)> checkFunction = [](int32_t val) {
108 return val >= MIN_CONNECTION_NUM && val <= MAX_CONNECTION_NUM;
109 };
110 return CheckAndGetDBConfig(config, DB_CONFIG_MAX_CONN_NUM, checkFunction, maxConnNum);
111 }
112
CheckBufferPoolSizeConfig(const JsonObject & config,int32_t pageSize,uint32_t & redoBufSize)113 bool CheckBufferPoolSizeConfig(const JsonObject &config, int32_t pageSize, uint32_t &redoBufSize)
114 {
115 std::function<bool(uint32_t)> checkFunction = [pageSize](uint32_t val) {
116 return val >= MIN_BUFFER_POOL_SIZE && val <= MAX_BUFFER_POOL_SIZE &&
117 val >= static_cast<uint32_t>(pageSize * 64); // 64: pool size should be 64 times larger then pageSize
118 };
119 return CheckAndGetDBConfig(config, DB_CONFIG_BUFFER_POOL_SIZE, checkFunction, redoBufSize);
120 }
121
CheckCrcCheckEnableConfig(const JsonObject & config,uint32_t & crcCheckEnable)122 bool CheckCrcCheckEnableConfig(const JsonObject &config, uint32_t &crcCheckEnable)
123 {
124 std::function<bool(uint32_t)> checkFunction = [](uint32_t val) {
125 return val == 0 || val == 1;
126 };
127 return CheckAndGetDBConfig(config, DB_CONFIG_CRC_CHECK_ENABLE, checkFunction, crcCheckEnable);
128 }
129
CheckShareModeConfig(const JsonObject & config,uint32_t & shareModeCheckEnable)130 bool CheckShareModeConfig(const JsonObject &config, uint32_t &shareModeCheckEnable)
131 {
132 std::function<bool(uint32_t)> checkFunction = [](uint32_t val) {
133 return val == 0;
134 };
135 return CheckAndGetDBConfig(config, DB_CONFIG_SHARED_MODE, checkFunction, shareModeCheckEnable);
136 }
137
IsDbconfigValid(const JsonObject & config)138 int IsDbconfigValid(const JsonObject &config)
139 {
140 JsonObject child = config.GetChild();
141 while (!child.IsNull()) {
142 std::string fieldName = child.GetItemField();
143 bool isSupport = false;
144 for (uint32_t i = 0; i < sizeof(DB_CONFIG) / sizeof(char *); i++) {
145 if (strcmp(DB_CONFIG[i], fieldName.c_str()) == 0) {
146 isSupport = true;
147 break;
148 }
149 }
150
151 if (!isSupport) {
152 GLOGE("Invalid db config");
153 return -E_INVALID_CONFIG_VALUE;
154 }
155
156 child = child.GetNext();
157 }
158 return E_OK;
159 }
160 } // namespace
161
GetDBConfigFromJsonStr(const std::string & confStr,int & errCode)162 DBConfig DBConfig::GetDBConfigFromJsonStr(const std::string &confStr, int &errCode)
163 {
164 JsonObject dbConfig = JsonObject::Parse(confStr, errCode);
165 if (errCode != E_OK) {
166 GLOGE("Read DB config failed from str. %d", errCode);
167 return {};
168 }
169
170 errCode = IsDbconfigValid(dbConfig);
171 if (errCode != E_OK) {
172 GLOGE("Check DB config, not support config item. %d", errCode);
173 return {};
174 }
175
176 DBConfig conf;
177 if (!CheckPageSizeConfig(dbConfig, conf.pageSize_)) {
178 GLOGE("Check DB config 'pageSize' failed.");
179 errCode = -E_INVALID_CONFIG_VALUE;
180 return {};
181 }
182
183 if (!CheckRedoFlushConfig(dbConfig, conf.redoFlushByTrx_)) {
184 GLOGE("Check DB config 'redoFlushByTrx' failed.");
185 errCode = -E_INVALID_CONFIG_VALUE;
186 return {};
187 }
188
189 if (!CheckRedoBufSizeConfig(dbConfig, conf.pageSize_, conf.redoPubBufSize_)) {
190 GLOGE("Check DB config 'redoPubBufSize' failed.");
191 errCode = -E_INVALID_CONFIG_VALUE;
192 return {};
193 }
194
195 if (!CheckMaxConnNumConfig(dbConfig, conf.maxConnNum_)) {
196 GLOGE("Check DB config 'maxConnNum' failed.");
197 errCode = -E_INVALID_CONFIG_VALUE;
198 return {};
199 }
200
201 if (!CheckBufferPoolSizeConfig(dbConfig, conf.pageSize_, conf.bufferPoolSize_)) {
202 GLOGE("Check DB config 'bufferPoolSize' failed.");
203 errCode = -E_INVALID_CONFIG_VALUE;
204 return {};
205 }
206
207 if (!CheckCrcCheckEnableConfig(dbConfig, conf.crcCheckEnable_)) {
208 GLOGE("Check DB config 'crcCheckEnable' failed.");
209 errCode = -E_INVALID_CONFIG_VALUE;
210 return {};
211 }
212
213 if (!CheckShareModeConfig(dbConfig, conf.shareModeEnable_)) {
214 GLOGE("Check DB config 'shareModeEnable' failed.");
215 errCode = -E_INVALID_CONFIG_VALUE;
216 return {};
217 }
218
219 conf.configStr_ = confStr;
220 return conf;
221 }
222
ReadConfig(const std::string & confStr,int & errCode)223 DBConfig DBConfig::ReadConfig(const std::string &confStr, int &errCode)
224 {
225 if (confStr.empty()) {
226 return {};
227 }
228
229 if (confStr.length() + 1 > MAX_DB_CONFIG_LEN) {
230 GLOGE("Config json string is too long.");
231 errCode = -E_OVER_LIMIT;
232 return {};
233 }
234
235 std::string lowerCaseConfStr = confStr;
236 std::transform(lowerCaseConfStr.begin(), lowerCaseConfStr.end(), lowerCaseConfStr.begin(), [](unsigned char c) {
237 return std::tolower(c);
238 });
239
240 return GetDBConfigFromJsonStr(lowerCaseConfStr, errCode);
241 }
242
ToString() const243 std::string DBConfig::ToString() const
244 {
245 return configStr_;
246 }
247
GetPageSize() const248 int32_t DBConfig::GetPageSize() const
249 {
250 return pageSize_;
251 }
252
operator ==(const DBConfig & targetConfig) const253 bool DBConfig::operator==(const DBConfig &targetConfig) const
254 {
255 return pageSize_ == targetConfig.pageSize_ && redoFlushByTrx_ == targetConfig.redoFlushByTrx_ &&
256 redoPubBufSize_ == targetConfig.redoPubBufSize_ && maxConnNum_ == targetConfig.maxConnNum_ &&
257 bufferPoolSize_ == targetConfig.bufferPoolSize_ && crcCheckEnable_ == targetConfig.crcCheckEnable_;
258 }
259
operator !=(const DBConfig & targetConfig) const260 bool DBConfig::operator!=(const DBConfig &targetConfig) const
261 {
262 return !(*this == targetConfig);
263 }
264
CheckPersistenceEqual(const DBConfig & targetConfig) const265 bool DBConfig::CheckPersistenceEqual(const DBConfig &targetConfig) const
266 {
267 return pageSize_ == targetConfig.pageSize_ && crcCheckEnable_ == targetConfig.crcCheckEnable_;
268 }
269 } // namespace DocumentDB