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 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     GRD_KVItemT beginInnerKey{(void *)&beginKey[0], (uint32_t)beginKey.size()};
197     GRD_KVItemT endInnerKey{(void *)&endKey[0], (uint32_t)endKey.size()};
198     GRD_FilterOption filterOpt{KV_SCAN_RANGE, beginInnerKey, endInnerKey};
199     return TransferGrdErrno(GRD_KVFilter(db, collectionName, &filterOpt, resultSet));
200 }
201 
RdKvFetch(GRD_ResultSet * resultSet,Key & key,Value & value)202 int RdKvFetch(GRD_ResultSet *resultSet, Key &key, Value &value)
203 {
204     uint32_t keyLen;
205     uint32_t valueLen;
206     int errCode = TransferGrdErrno(GRD_KVGetSize(resultSet, &keyLen, &valueLen));
207     if (errCode != E_OK && errCode != -E_NOT_FOUND) {
208         LOGE("[rdUtils][RdKvFetch] Can not Get value lens size from resultSet");
209         return errCode;
210     }
211     key.resize(keyLen);
212     value.resize(valueLen);
213     return TransferGrdErrno(GRD_GetItem(resultSet, key.data(), value.data()));
214 }
215 
RdDBClose(GRD_DB * db,uint32_t flags)216 int RdDBClose(GRD_DB *db, uint32_t flags)
217 {
218     int ret = TransferGrdErrno(GRD_DBClose(db, flags));
219     if (ret != E_OK) {
220         LOGE("Can not close db %d", ret);
221     }
222     return ret;
223 }
224 
RdFreeResultSet(GRD_ResultSet * resultSet)225 int RdFreeResultSet(GRD_ResultSet *resultSet)
226 {
227     return TransferGrdErrno(GRD_FreeResultSet(resultSet));
228 }
229 
RdKVBatchPrepare(uint16_t itemNum,GRD_KVBatchT ** batch)230 int RdKVBatchPrepare(uint16_t itemNum, GRD_KVBatchT **batch)
231 {
232     return TransferGrdErrno(GRD_KVBatchPrepare(itemNum, batch));
233 }
234 
RdKVBatchPushback(GRD_KVBatchT * batch,const Key & key,const Value & value)235 int RdKVBatchPushback(GRD_KVBatchT *batch, const Key &key, const Value &value)
236 {
237     GRD_KVItemT innerKey{(void *)&key[0], (uint32_t)key.size()};
238     GRD_KVItemT innerVal{(void *)&value[0], (uint32_t)value.size()};
239     int ret = TransferGrdErrno(
240         GRD_KVBatchPushback(innerKey.data, innerKey.dataLen, innerVal.data, innerVal.dataLen, batch));
241     if (ret != E_OK) {
242         LOGE("[rdUtils][BatchSaveEntries] Can not push back entries to KVBatch structure");
243     }
244     return ret;
245 }
246 
RdKVBatchPut(GRD_DB * db,const char * kvTableName,GRD_KVBatchT * batch)247 int RdKVBatchPut(GRD_DB *db, const char *kvTableName, GRD_KVBatchT *batch)
248 {
249     if (db == nullptr) {
250         LOGE("[rdUtils][RdKVBatchPut] invalid db");
251         return -E_INVALID_DB;
252     }
253     return TransferGrdErrno(GRD_KVBatchPut(db, kvTableName, batch));
254 }
255 
RdFlush(GRD_DB * db,uint32_t flags)256 int RdFlush(GRD_DB *db, uint32_t flags)
257 {
258     if (db == nullptr) {
259         LOGE("[rdUtils][ForceCheckPoint] invalid db");
260         return -E_INVALID_DB;
261     }
262     // flags means options, input 0 in current version.
263     return TransferGrdErrno(GRD_Flush(db, flags));
264 }
265 
RdKVBatchDel(GRD_DB * db,const char * kvTableName,GRD_KVBatchT * batch)266 int RdKVBatchDel(GRD_DB *db, const char *kvTableName, GRD_KVBatchT *batch)
267 {
268     if (db == nullptr) {
269         LOGE("[rdUtils][RdKVBatchDel] invalid db");
270         return -E_INVALID_DB;
271     }
272     return TransferGrdErrno(GRD_KVBatchDel(db, kvTableName, batch));
273 }
274 
RdKVBatchDestroy(GRD_KVBatchT * batch)275 int RdKVBatchDestroy(GRD_KVBatchT *batch)
276 {
277     return TransferGrdErrno(GRD_KVBatchDestroy(batch));
278 }
279 
RdDbOpen(const char * dbPath,const char * configStr,uint32_t flags,GRD_DB * & db)280 int RdDbOpen(const char *dbPath, const char *configStr, uint32_t flags, GRD_DB *&db)
281 {
282     return TransferGrdErrno(GRD_DBOpen(dbPath, configStr, flags, &db));
283 }
284 
RdIndexPreload(GRD_DB * & db,const char * collectionName)285 int RdIndexPreload(GRD_DB *&db, const char *collectionName)
286 {
287     if (db == nullptr) {
288         LOGE("[rdUtils][RdIndexPreload] db is null");
289         return -E_INVALID_DB;
290     }
291     return TransferGrdErrno(GRD_IndexPreload(db, collectionName));
292 }
293 
RdCreateCollection(GRD_DB * db,const char * collectionName,const char * optionStr,uint32_t flags)294 int RdCreateCollection(GRD_DB *db, const char *collectionName, const char *optionStr, uint32_t flags)
295 {
296     return TransferGrdErrno(GRD_CreateCollection(db, collectionName, optionStr, flags));
297 }
298 
CheckParaOption(const KvStoreNbDelegate::Option & option,const std::function<void (DBStatus,KvStoreNbDelegate *)> & callback)299 bool CheckParaOption(const KvStoreNbDelegate::Option &option,
300     const std::function<void(DBStatus, KvStoreNbDelegate *)> &callback)
301 {
302     if (option.storageEngineType == SQLITE) {
303         if ((option.rdconfig.pageSize < SQLITE_PAGE_SIZE_MIN) ||
304            (option.rdconfig.pageSize > SQLITE_PAGE_SIZE_MAX)) {
305             callback(INVALID_ARGS, nullptr);
306             LOGE("Invalid config pageSize:%" PRIu32, option.rdconfig.pageSize);
307             return false;
308         }
309         if ((option.rdconfig.cacheSize % option.rdconfig.pageSize != 0) ||
310             ((option.rdconfig.pageSize & (option.rdconfig.pageSize - 1)) != 0) ||
311             (option.rdconfig.cacheSize / SQLITE_CACHE_SIZE_PAGE > option.rdconfig.pageSize)) {
312             callback(INVALID_ARGS, nullptr);
313             LOGE("Invalid config pageSize:%" PRIu32 "and cacheSize:%" PRIu32, option.rdconfig.pageSize,
314                 option.rdconfig.cacheSize);
315             return false;
316         }
317     }
318     if (option.storageEngineType != GAUSSDB_RD && option.storageEngineType != SQLITE) {
319         callback(INVALID_ARGS, nullptr);
320         return false;
321     }
322     if (option.rdconfig.readOnly && option.isNeedRmCorruptedDb) {
323         callback(INVALID_ARGS, nullptr);
324         return false;
325     }
326     if (!CheckOption(option)) {
327         callback(NOT_SUPPORT, nullptr);
328         return false;
329     }
330     return true;
331 }
332 } // namespace DistributedDB