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 #include "rd_utils.h"
16 #include "db_errno.h"
17 #include "log_print.h"
18 #include "sqlite_single_ver_storage_executor_sql.h"
19
20 namespace {
21 using namespace DistributedDB;
22
CheckRdOptionMode(const KvStoreNbDelegate::Option & option)23 bool CheckRdOptionMode(const KvStoreNbDelegate::Option &option)
24 {
25 return (option.mode != 0 && option.mode != 1) || option.syncDualTupleMode;
26 }
27
CheckOption(const KvStoreNbDelegate::Option & option)28 bool CheckOption(const KvStoreNbDelegate::Option &option)
29 {
30 if (option.storageEngineType == GAUSSDB_RD &&
31 (CheckRdOptionMode(option) ||
32 option.isMemoryDb ||
33 option.isEncryptedDb ||
34 option.cipher != CipherType::DEFAULT ||
35 option.passwd != CipherPassword() ||
36 !option.schema.empty() ||
37 option.conflictType != 0 ||
38 option.notifier != nullptr ||
39 option.conflictResolvePolicy != LAST_WIN ||
40 option.isNeedCompressOnSync ||
41 option.compressionRate != 100 || // Valid in [1, 100].
42 option.localOnly)) {
43 return false;
44 }
45 return true;
46 }
47 }
48
49 namespace DistributedDB {
50
InitRdConfig()51 std::string InitRdConfig()
52 {
53 return R"("redoFlushByTrx": 1, "maxConnNum": 100, "crcCheckEnable": 0, "metaInfoBak": 1)";
54 }
55
56 struct GrdErrnoPair {
57 int32_t grdCode;
58 int kvDbCode;
59 };
60
61 const GrdErrnoPair GRD_ERRNO_MAP[] = {
62 { GRD_OK, E_OK },
63 { GRD_NOT_SUPPORT, -E_NOT_SUPPORT },
64 { GRD_OVER_LIMIT, -E_MAX_LIMITS },
65 { GRD_INVALID_ARGS, -E_INVALID_ARGS },
66 { GRD_FAILED_FILE_OPERATION, -E_SYSTEM_API_FAIL },
67 { GRD_INVALID_FILE_FORMAT, -E_INVALID_PASSWD_OR_CORRUPTED_DB },
68 { GRD_INSUFFICIENT_SPACE, -E_INTERNAL_ERROR },
69 { GRD_INNER_ERR, -E_INTERNAL_ERROR },
70 { GRD_RESOURCE_BUSY, -E_BUSY },
71 { GRD_NO_DATA, -E_NOT_FOUND },
72 { GRD_FAILED_MEMORY_ALLOCATE, -E_OUT_OF_MEMORY },
73 { GRD_FAILED_MEMORY_RELEASE, -E_OUT_OF_MEMORY },
74 { GRD_DATA_CONFLICT, -E_INVALID_DATA },
75 { GRD_NOT_AVAILABLE, -E_NOT_FOUND },
76 { GRD_INVALID_FORMAT, -E_INVALID_FORMAT },
77 { GRD_TIME_OUT, -E_TIMEOUT },
78 { GRD_DB_INSTANCE_ABNORMAL, -E_INTERNAL_ERROR },
79 { GRD_DISK_SPACE_FULL, -E_INTERNAL_ERROR },
80 { GRD_CRC_CHECK_DISABLED, -E_INVALID_ARGS },
81 { GRD_PERMISSION_DENIED, -E_DENIED_SQL },
82 { GRD_REBUILD_DATABASE, -E_REBUILD_DATABASE }, // rebuild database means ok
83 { GRD_DATA_CORRUPTED, -E_INVALID_PASSWD_OR_CORRUPTED_DB },
84 { GRD_DATA_EXCEPTION, -E_UNEXPECTED_DATA },
85 { GRD_DB_BUSY, -E_BUSY },
86 };
TransferGrdErrno(int err)87 int TransferGrdErrno(int err)
88 {
89 if (err > 0) {
90 return err;
91 }
92 for (const auto &item : GRD_ERRNO_MAP) {
93 if (item.grdCode == err) {
94 return item.kvDbCode;
95 }
96 }
97 return -E_INTERNAL_ERROR;
98 }
99
KvItemToBlob(GRD_KVItemT & item)100 static inline std::vector<uint8_t> KvItemToBlob(GRD_KVItemT &item)
101 {
102 return std::vector<uint8_t>((uint8_t *)item.data, (uint8_t *)item.data + item.dataLen);
103 }
104
GetCollNameFromType(SingleVerDataType type,std::string & collName)105 int GetCollNameFromType(SingleVerDataType type, std::string &collName)
106 {
107 switch (type) {
108 case SingleVerDataType::SYNC_TYPE:
109 collName = SYNC_COLLECTION_NAME;
110 break;
111 default:
112 LOGE("data type not support");
113 return -E_INVALID_ARGS;
114 }
115 return E_OK;
116 }
117
RdKVPut(GRD_DB * db,const char * collectionName,const Key & key,const Value & value)118 int RdKVPut(GRD_DB *db, const char *collectionName, const Key &key, const Value &value)
119 {
120 if (db == nullptr) {
121 LOGE("[rdUtils][RdKvPut] invalid db");
122 return -E_INVALID_DB;
123 }
124 GRD_KVItemT innerKey{(void *)&key[0], (uint32_t)key.size()};
125 GRD_KVItemT innerVal{(void *)&value[0], (uint32_t)value.size()};
126 int ret = TransferGrdErrno(GRD_KVPut(db, collectionName, &innerKey, &innerVal));
127 if (ret != E_OK) {
128 LOGE("[rdUtils][RdKvPut] ERROR:%d", ret);
129 }
130 return ret;
131 }
132
RdKVGet(GRD_DB * db,const char * collectionName,const Key & key,Value & value)133 int RdKVGet(GRD_DB *db, const char *collectionName, const Key &key, Value &value)
134 {
135 if (db == nullptr) {
136 LOGE("[rdUtils][RdKvGet] invalid db");
137 return -E_INVALID_DB;
138 }
139 GRD_KVItemT innerKey{(void *)&key[0], (uint32_t)key.size()};
140 GRD_KVItemT innerVal = { 0 };
141 int ret = TransferGrdErrno(GRD_KVGet(db, collectionName, &innerKey, &innerVal));
142 if (ret != E_OK) {
143 // log print on caller
144 return ret;
145 }
146 value = KvItemToBlob(innerVal);
147 (void)GRD_KVFreeItem(&innerVal);
148 return E_OK;
149 }
150
RdBackup(GRD_DB * db,const char * backupDbFile,uint8_t * encryptedKey,uint32_t encryptedKeyLen)151 int RdBackup(GRD_DB *db, const char *backupDbFile, uint8_t *encryptedKey, uint32_t encryptedKeyLen)
152 {
153 return TransferGrdErrno(GRD_DBBackup(db, backupDbFile, encryptedKey, encryptedKeyLen));
154 }
155
RdRestore(const char * dbFile,const char * backupDbFile,uint8_t * decryptedKey,uint32_t decryptedKeyLen)156 int RdRestore(const char *dbFile, const char *backupDbFile, uint8_t *decryptedKey, uint32_t decryptedKeyLen)
157 {
158 return TransferGrdErrno(GRD_DBRestore(dbFile, backupDbFile, decryptedKey, decryptedKeyLen));
159 }
160
RdKVDel(GRD_DB * db,const char * collectionName,const Key & key)161 int RdKVDel(GRD_DB *db, const char *collectionName, const Key &key)
162 {
163 if (db == nullptr) {
164 LOGE("[rdUtils][RdKvDel] invalid db");
165 return -E_INVALID_DB;
166 }
167 GRD_KVItemT innerKey{(void *)&key[0], (uint32_t)key.size()};
168 int ret = TransferGrdErrno(GRD_KVDel(db, collectionName, &innerKey));
169 if (ret < 0) {
170 LOGE("[rdUtils][RdKvDel] failed:%d", ret);
171 }
172 return ret;
173 }
174
RdKVScan(GRD_DB * db,const char * collectionName,const Key & key,GRD_KvScanModeE mode,GRD_ResultSet ** resultSet)175 int RdKVScan(GRD_DB *db, const char *collectionName, const Key &key, GRD_KvScanModeE mode,
176 GRD_ResultSet **resultSet)
177 {
178 if (db == nullptr) {
179 LOGE("[rdUtils][RdKVScan] invalid db");
180 return -E_INVALID_DB;
181 }
182 if (key.empty()) {
183 return TransferGrdErrno(GRD_KVScan(db, collectionName, NULL, mode, resultSet));
184 }
185 GRD_KVItemT innerKey{(void *)&key[0], (uint32_t)key.size()};
186 return TransferGrdErrno(GRD_KVScan(db, collectionName, &innerKey, mode, resultSet));
187 }
188
RdKVRangeScan(GRD_DB * db,const char * collectionName,const Key & beginKey,const Key & endKey,GRD_ResultSet ** resultSet)189 int RdKVRangeScan(GRD_DB *db, const char *collectionName, const Key &beginKey, const Key &endKey,
190 GRD_ResultSet **resultSet)
191 {
192 if (db == nullptr) {
193 LOGE("[rdUtils][RdKVScan] invalid db");
194 return -E_INVALID_DB;
195 }
196
197 GRD_FilterOptionT filterOpt = {};
198 filterOpt.mode = KV_SCAN_RANGE;
199 if (!beginKey.empty()) {
200 filterOpt.begin = {(void *)&beginKey[0], (uint32_t)beginKey.size()};
201 }
202 if (!endKey.empty()) {
203 filterOpt.end = {(void *)&endKey[0], (uint32_t)endKey.size()};
204 }
205
206 return TransferGrdErrno(GRD_KVFilter(db, collectionName, &filterOpt, resultSet));
207 }
208
RdKvFetch(GRD_ResultSet * resultSet,Key & key,Value & value)209 int RdKvFetch(GRD_ResultSet *resultSet, Key &key, Value &value)
210 {
211 uint32_t keyLen;
212 uint32_t valueLen;
213 int errCode = TransferGrdErrno(GRD_KVGetSize(resultSet, &keyLen, &valueLen));
214 if (errCode != E_OK && errCode != -E_NOT_FOUND) {
215 LOGE("[rdUtils][RdKvFetch] Can not Get value lens size from resultSet");
216 return errCode;
217 }
218 key.resize(keyLen);
219 value.resize(valueLen);
220 return TransferGrdErrno(GRD_GetItem(resultSet, key.data(), value.data()));
221 }
222
RdDBClose(GRD_DB * db,uint32_t flags)223 int RdDBClose(GRD_DB *db, uint32_t flags)
224 {
225 int ret = TransferGrdErrno(GRD_DBClose(db, flags));
226 if (ret != E_OK) {
227 LOGE("Can not close db %d", ret);
228 }
229 return ret;
230 }
231
RdFreeResultSet(GRD_ResultSet * resultSet)232 int RdFreeResultSet(GRD_ResultSet *resultSet)
233 {
234 return TransferGrdErrno(GRD_FreeResultSet(resultSet));
235 }
236
RdKVBatchPrepare(uint16_t itemNum,GRD_KVBatchT ** batch)237 int RdKVBatchPrepare(uint16_t itemNum, GRD_KVBatchT **batch)
238 {
239 return TransferGrdErrno(GRD_KVBatchPrepare(itemNum, batch));
240 }
241
RdKVBatchPushback(GRD_KVBatchT * batch,const Key & key,const Value & value)242 int RdKVBatchPushback(GRD_KVBatchT *batch, const Key &key, const Value &value)
243 {
244 GRD_KVItemT innerKey{(void *)&key[0], (uint32_t)key.size()};
245 GRD_KVItemT innerVal{nullptr, 0};
246
247 if (!value.empty()) {
248 innerVal.data = (void *)&value[0];
249 innerVal.dataLen = (uint32_t)value.size();
250 }
251 int ret = TransferGrdErrno(
252 GRD_KVBatchPushback(innerKey.data, innerKey.dataLen, innerVal.data, innerVal.dataLen, batch));
253 if (ret != E_OK) {
254 LOGE("[rdUtils][BatchSaveEntries] Can not push back entries to KVBatch structure");
255 }
256 return ret;
257 }
258
RdKVBatchPut(GRD_DB * db,const char * kvTableName,GRD_KVBatchT * batch)259 int RdKVBatchPut(GRD_DB *db, const char *kvTableName, GRD_KVBatchT *batch)
260 {
261 if (db == nullptr) {
262 LOGE("[rdUtils][RdKVBatchPut] invalid db");
263 return -E_INVALID_DB;
264 }
265 return TransferGrdErrno(GRD_KVBatchPut(db, kvTableName, batch));
266 }
267
RdFlush(GRD_DB * db,uint32_t flags)268 int RdFlush(GRD_DB *db, uint32_t flags)
269 {
270 if (db == nullptr) {
271 LOGE("[rdUtils][ForceCheckPoint] invalid db");
272 return -E_INVALID_DB;
273 }
274 // flags means options, input 0 in current version.
275 return TransferGrdErrno(GRD_Flush(db, flags));
276 }
277
RdKVBatchDel(GRD_DB * db,const char * kvTableName,GRD_KVBatchT * batch)278 int RdKVBatchDel(GRD_DB *db, const char *kvTableName, GRD_KVBatchT *batch)
279 {
280 if (db == nullptr) {
281 LOGE("[rdUtils][RdKVBatchDel] invalid db");
282 return -E_INVALID_DB;
283 }
284 return TransferGrdErrno(GRD_KVBatchDel(db, kvTableName, batch));
285 }
286
RdKVBatchDestroy(GRD_KVBatchT * batch)287 int RdKVBatchDestroy(GRD_KVBatchT *batch)
288 {
289 return TransferGrdErrno(GRD_KVBatchDestroy(batch));
290 }
291
RdDbOpen(const char * dbPath,const char * configStr,uint32_t flags,GRD_DB * & db)292 int RdDbOpen(const char *dbPath, const char *configStr, uint32_t flags, GRD_DB *&db)
293 {
294 return TransferGrdErrno(GRD_DBOpen(dbPath, configStr, flags, &db));
295 }
296
RdIndexPreload(GRD_DB * & db,const char * collectionName)297 int RdIndexPreload(GRD_DB *&db, const char *collectionName)
298 {
299 if (db == nullptr) {
300 LOGE("[rdUtils][RdIndexPreload] db is null");
301 return -E_INVALID_DB;
302 }
303 return TransferGrdErrno(GRD_IndexPreload(db, collectionName));
304 }
305
RdCreateCollection(GRD_DB * db,const char * collectionName,const char * optionStr,uint32_t flags)306 int RdCreateCollection(GRD_DB *db, const char *collectionName, const char *optionStr, uint32_t flags)
307 {
308 return TransferGrdErrno(GRD_CreateCollection(db, collectionName, optionStr, flags));
309 }
310
CheckParaOption(const KvStoreNbDelegate::Option & option,const std::function<void (DBStatus,KvStoreNbDelegate *)> & callback)311 bool CheckParaOption(const KvStoreNbDelegate::Option &option,
312 const std::function<void(DBStatus, KvStoreNbDelegate *)> &callback)
313 {
314 if (option.storageEngineType == SQLITE) {
315 if ((option.rdconfig.pageSize < SQLITE_PAGE_SIZE_MIN) ||
316 (option.rdconfig.pageSize > SQLITE_PAGE_SIZE_MAX)) {
317 callback(INVALID_ARGS, nullptr);
318 LOGE("Invalid config pageSize:%" PRIu32, option.rdconfig.pageSize);
319 return false;
320 }
321 if ((option.rdconfig.cacheSize % option.rdconfig.pageSize != 0) ||
322 ((option.rdconfig.pageSize & (option.rdconfig.pageSize - 1)) != 0) ||
323 (option.rdconfig.cacheSize / SQLITE_CACHE_SIZE_PAGE > option.rdconfig.pageSize)) {
324 callback(INVALID_ARGS, nullptr);
325 LOGE("Invalid config pageSize:%" PRIu32 "and cacheSize:%" PRIu32, option.rdconfig.pageSize,
326 option.rdconfig.cacheSize);
327 return false;
328 }
329 }
330 if (option.storageEngineType != GAUSSDB_RD && option.storageEngineType != SQLITE) {
331 callback(INVALID_ARGS, nullptr);
332 return false;
333 }
334 if (option.rdconfig.readOnly && option.isNeedRmCorruptedDb) {
335 callback(INVALID_ARGS, nullptr);
336 return false;
337 }
338 if (!CheckOption(option)) {
339 callback(NOT_SUPPORT, nullptr);
340 return false;
341 }
342 return true;
343 }
344 } // namespace DistributedDB