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 "json_object.h"
26 #include "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
44 const int DB_CONFIG_SIZE = 6; // db config size
45 const char *DB_CONFIG[DB_CONFIG_SIZE] = { DB_CONFIG_PAGESIZE, DB_CONFIG_REDO_FLUSH_BY_TRX,
46 DB_CONFIG_REDO_PUB_BUFF_SIZE, DB_CONFIG_MAX_CONN_NUM, DB_CONFIG_BUFFER_POOL_SIZE, DB_CONFIG_CRC_CHECK_ENABLE };
47
48 template<typename T>
CheckAndGetDBConfig(const JsonObject & config,const std::string & name,const std::function<bool (T)> & checkValid,T & val)49 bool CheckAndGetDBConfig(const JsonObject &config, const std::string &name, const std::function<bool(T)> &checkValid,
50 T &val)
51 {
52 const JsonFieldPath configField = { name };
53 if (!config.IsFieldExists(configField)) {
54 return true;
55 }
56
57 int errCode = E_OK;
58 ValueObject configValue = config.GetObjectByPath(configField, errCode);
59 if (errCode != E_OK) {
60 GLOGE("Can not find config Value");
61 return errCode;
62 }
63 if (configValue.GetValueType() != ValueObject::ValueType::VALUE_NUMBER) {
64 GLOGE("Check DB config failed, not found or type of %s is not NUMBER.", name.c_str());
65 return false;
66 }
67
68 if (checkValid && !checkValid(static_cast<T>(configValue.GetIntValue()))) {
69 GLOGE("Check DB config failed, invalid %s value.", name.c_str());
70 return false;
71 }
72
73 val = static_cast<T>(configValue.GetIntValue());
74 return true;
75 }
76
CheckPageSizeConfig(const JsonObject & config,int32_t & pageSize)77 bool CheckPageSizeConfig(const JsonObject &config, int32_t &pageSize)
78 {
79 std::function<bool(int32_t)> checkFunction = [](int32_t val) {
80 static const std::vector<int32_t> pageSizeValid = { 4, 8, 16, 32, 64 };
81 return std::find(pageSizeValid.begin(), pageSizeValid.end(), val) != pageSizeValid.end();
82 };
83 return CheckAndGetDBConfig(config, DB_CONFIG_PAGESIZE, checkFunction, pageSize);
84 }
85
CheckRedoFlushConfig(const JsonObject & config,uint32_t & redoFlush)86 bool CheckRedoFlushConfig(const JsonObject &config, uint32_t &redoFlush)
87 {
88 std::function<bool(uint32_t)> checkFunction = [](uint32_t val) {
89 return val == 0 || val == 1;
90 };
91 return CheckAndGetDBConfig(config, DB_CONFIG_REDO_FLUSH_BY_TRX, checkFunction, redoFlush);
92 }
93
CheckRedoBufSizeConfig(const JsonObject & config,int32_t pageSize,uint32_t & redoBufSize)94 bool CheckRedoBufSizeConfig(const JsonObject &config, int32_t pageSize, uint32_t &redoBufSize)
95 {
96 std::function<bool(uint32_t)> checkFunction = [pageSize](uint32_t val) {
97 return val >= MIN_REDO_BUFFER_SIZE && val <= MAX_REDO_BUFFER_SIZE &&
98 val > static_cast<uint32_t>(pageSize * 63); // 63: pool size should be 63 times larger then pageSize
99 };
100 return CheckAndGetDBConfig(config, DB_CONFIG_REDO_PUB_BUFF_SIZE, checkFunction, redoBufSize);
101 }
102
CheckMaxConnNumConfig(const JsonObject & config,int32_t & maxConnNum)103 bool CheckMaxConnNumConfig(const JsonObject &config, int32_t &maxConnNum)
104 {
105 std::function<bool(int32_t)> checkFunction = [](int32_t val) {
106 return val >= MIN_CONNECTION_NUM && val <= MAX_CONNECTION_NUM;
107 };
108 return CheckAndGetDBConfig(config, DB_CONFIG_MAX_CONN_NUM, checkFunction, maxConnNum);
109 }
110
CheckBufferPoolSizeConfig(const JsonObject & config,int32_t pageSize,uint32_t & redoBufSize)111 bool CheckBufferPoolSizeConfig(const JsonObject &config, int32_t pageSize, uint32_t &redoBufSize)
112 {
113 std::function<bool(uint32_t)> checkFunction = [pageSize](uint32_t val) {
114 return val >= MIN_BUFFER_POOL_SIZE && val <= MAX_BUFFER_POOL_SIZE &&
115 val >= static_cast<uint32_t>(pageSize * 64); // 64: pool size should be 64 times larger then pageSize
116 };
117 return CheckAndGetDBConfig(config, DB_CONFIG_BUFFER_POOL_SIZE, checkFunction, redoBufSize);
118 }
119
CheckCrcCheckEnableConfig(const JsonObject & config,uint32_t & crcCheckEnable)120 bool CheckCrcCheckEnableConfig(const JsonObject &config, uint32_t &crcCheckEnable)
121 {
122 std::function<bool(uint32_t)> checkFunction = [](uint32_t val) {
123 return val == 0 || val == 1;
124 };
125 return CheckAndGetDBConfig(config, DB_CONFIG_CRC_CHECK_ENABLE, checkFunction, crcCheckEnable);
126 }
127
CheckConfigValid(const JsonObject & config)128 int CheckConfigValid(const JsonObject &config)
129 {
130 JsonObject child = config.GetChild();
131 while (!child.IsNull()) {
132 std::string fieldName = child.GetItemField();
133 bool isSupport = false;
134 for (int i = 0; i < DB_CONFIG_SIZE; i++) {
135 if (strcmp(DB_CONFIG[i], fieldName.c_str()) == 0) {
136 isSupport = true;
137 break;
138 }
139 }
140
141 if (!isSupport) {
142 GLOGE("Invalid db config.");
143 return -E_INVALID_CONFIG_VALUE;
144 }
145
146 child = child.GetNext();
147 }
148 return E_OK;
149 }
150 } // namespace
151
GetDBConfigFromJsonStr(const std::string & confStr,int & errCode)152 DBConfig DBConfig::GetDBConfigFromJsonStr(const std::string &confStr, int &errCode)
153 {
154 JsonObject dbConfig = JsonObject::Parse(confStr, errCode);
155 if (errCode != E_OK) {
156 GLOGE("Read DB config failed from str. %d", errCode);
157 return {};
158 }
159
160 errCode = CheckConfigValid(dbConfig);
161 if (errCode != E_OK) {
162 GLOGE("Check DB config, not support config item. %d", errCode);
163 return {};
164 }
165
166 DBConfig conf;
167 if (!CheckPageSizeConfig(dbConfig, conf.pageSize_)) {
168 GLOGE("Check DB config 'pageSize' failed.");
169 errCode = -E_INVALID_CONFIG_VALUE;
170 return {};
171 }
172
173 if (!CheckRedoFlushConfig(dbConfig, conf.redoFlushByTrx_)) {
174 GLOGE("Check DB config 'redoFlushByTrx' failed.");
175 errCode = -E_INVALID_CONFIG_VALUE;
176 return {};
177 }
178
179 if (!CheckRedoBufSizeConfig(dbConfig, conf.pageSize_, conf.redoPubBufSize_)) {
180 GLOGE("Check DB config 'redoPubBufSize' failed.");
181 errCode = -E_INVALID_CONFIG_VALUE;
182 return {};
183 }
184
185 if (!CheckMaxConnNumConfig(dbConfig, conf.maxConnNum_)) {
186 GLOGE("Check DB config 'maxConnNum' failed.");
187 errCode = -E_INVALID_CONFIG_VALUE;
188 return {};
189 }
190
191 if (!CheckBufferPoolSizeConfig(dbConfig, conf.pageSize_, conf.bufferPoolSize_)) {
192 GLOGE("Check DB config 'bufferPoolSize' failed.");
193 errCode = -E_INVALID_CONFIG_VALUE;
194 return {};
195 }
196
197 if (!CheckCrcCheckEnableConfig(dbConfig, conf.crcCheckEnable_)) {
198 GLOGE("Check DB config 'crcCheckEnable' failed.");
199 errCode = -E_INVALID_CONFIG_VALUE;
200 return {};
201 }
202
203 conf.configStr_ = confStr;
204 errCode = E_OK;
205 return conf;
206 }
207
ReadConfig(const std::string & confStr,int & errCode)208 DBConfig DBConfig::ReadConfig(const std::string &confStr, int &errCode)
209 {
210 if (confStr.empty()) {
211 return {};
212 }
213
214 if (confStr.length() + 1 > MAX_DB_CONFIG_LEN) {
215 GLOGE("Config json string is too long.");
216 errCode = -E_OVER_LIMIT;
217 return {};
218 }
219
220 std::string lowerCaseConfStr = confStr;
221 std::transform(lowerCaseConfStr.begin(), lowerCaseConfStr.end(), lowerCaseConfStr.begin(), [](unsigned char c) {
222 return std::tolower(c);
223 });
224
225 return GetDBConfigFromJsonStr(lowerCaseConfStr, errCode);
226 }
227
ToString() const228 std::string DBConfig::ToString() const
229 {
230 return configStr_;
231 }
232
GetPageSize() const233 int32_t DBConfig::GetPageSize() const
234 {
235 return pageSize_;
236 }
237
operator ==(const DBConfig & targetConfig) const238 bool DBConfig::operator==(const DBConfig &targetConfig) const
239 {
240 return pageSize_ == targetConfig.pageSize_ && redoFlushByTrx_ == targetConfig.redoFlushByTrx_ &&
241 redoPubBufSize_ == targetConfig.redoPubBufSize_ && maxConnNum_ == targetConfig.maxConnNum_ &&
242 bufferPoolSize_ == targetConfig.bufferPoolSize_ && crcCheckEnable_ == targetConfig.crcCheckEnable_;
243 }
244
operator !=(const DBConfig & targetConfig) const245 bool DBConfig::operator!=(const DBConfig &targetConfig) const
246 {
247 return !(*this == targetConfig);
248 }
249
CheckPersistenceEqual(const DBConfig & targetConfig) const250 bool DBConfig::CheckPersistenceEqual(const DBConfig &targetConfig) const
251 {
252 return pageSize_ == targetConfig.pageSize_ && crcCheckEnable_ == targetConfig.crcCheckEnable_;
253 }
254 } // namespace DocumentDB