1 /*
2  * Copyright (c) 2024 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 <map>
16 #include <thread>
17 #include "preferences_db_adapter.h"
18 #include "log_print.h"
19 #include "preferences_errno.h"
20 #include "preferences_file_operation.h"
21 
22 namespace OHOS {
23 namespace NativePreferences {
24 
25 void *PreferenceDbAdapter::gLibrary_ = NULL;
26 
27 std::mutex PreferenceDbAdapter::apiMutex_;
28 
29 GRD_APIInfo PreferenceDbAdapter::api_;
30 
31 std::atomic<bool> PreferenceDbAdapter::isInit_ = false;
32 
33 #if !defined(WINDOWS_PLATFORM)
34 static const std::chrono::milliseconds WAIT_REPAIRE_TIMEOUT(5);
35 #endif
36 
37 const char * const TABLENAME = "preferences_data";
38 const char * const TABLE_MODE = "{\"mode\" : \"kv\", \"indextype\" : \"hash\"}";
39 const char * const CONFIG_STR =
40     "{\"pageSize\": 4, \"redoFlushByTrx\": 2, \"redoPubBufSize\": 256, \"maxConnNum\": 100, "
41     "\"bufferPoolSize\": 1024, \"crcCheckEnable\": 0, \"bufferPoolPolicy\" : \"BUF_PRIORITY_INDEX\", "
42     "\"sharedModeEnable\" : 1, \"MetaInfoBak\": 1}";
43 const int CREATE_COLLECTION_RETRY_TIMES = 2;
44 const int DB_REPAIR_RETRY_TIMES = 3;
45 
GRDDBApiInitEnhance(GRD_APIInfo &GRD_DBApiInfo)46 void GRDDBApiInitEnhance(GRD_APIInfo &GRD_DBApiInfo)
47 {
48 #ifndef _WIN32
49     GRD_DBApiInfo.DbOpenApi = (DBOpen)dlsym(PreferenceDbAdapter::gLibrary_, "GRD_DBOpen");
50     GRD_DBApiInfo.DbCloseApi = (DBClose)dlsym(PreferenceDbAdapter::gLibrary_, "GRD_DBClose");
51     GRD_DBApiInfo.DbCreateCollectionApi = (DBCreateCollection)dlsym(PreferenceDbAdapter::gLibrary_,
52         "GRD_CreateCollection");
53     GRD_DBApiInfo.DbDropCollectionApi = (DBDropCollection)dlsym(PreferenceDbAdapter::gLibrary_, "GRD_DropCollection");
54     GRD_DBApiInfo.DbIndexPreloadApi = (DBIndexPreload)dlsym(PreferenceDbAdapter::gLibrary_, "GRD_IndexPreload");
55     GRD_DBApiInfo.DbKvPutApi = (DBKvPut)dlsym(PreferenceDbAdapter::gLibrary_, "GRD_KVPut");
56     GRD_DBApiInfo.DbKvGetApi = (DBKvGet)dlsym(PreferenceDbAdapter::gLibrary_, "GRD_KVGet");
57     GRD_DBApiInfo.DbKvDelApi = (DBKvDel)dlsym(PreferenceDbAdapter::gLibrary_, "GRD_KVDel");
58     GRD_DBApiInfo.DbKvFilterApi = (DBKvFilter)dlsym(PreferenceDbAdapter::gLibrary_, "GRD_KVFilter");
59     GRD_DBApiInfo.NextApi = (ResultNext)dlsym(PreferenceDbAdapter::gLibrary_, "GRD_Next");
60     GRD_DBApiInfo.GetValueApi = (GetValue)dlsym(PreferenceDbAdapter::gLibrary_, "GRD_GetValue");
61     GRD_DBApiInfo.GetItemApi = (GetItem)dlsym(PreferenceDbAdapter::gLibrary_, "GRD_GetItem");
62     GRD_DBApiInfo.GetItemSizeApi = (GetItemSize)dlsym(PreferenceDbAdapter::gLibrary_, "GRD_KVGetSize");
63     GRD_DBApiInfo.FetchApi = (Fetch)dlsym(PreferenceDbAdapter::gLibrary_, "GRD_Fetch");
64     GRD_DBApiInfo.FreeItemApi = (KVFreeItem)dlsym(PreferenceDbAdapter::gLibrary_, "GRD_KVFreeItem");
65     GRD_DBApiInfo.FreeResultSetApi = (FreeResultSet)dlsym(PreferenceDbAdapter::gLibrary_, "GRD_FreeResultSet");
66     GRD_DBApiInfo.DbRepairApi = (DBRepair)dlsym(PreferenceDbAdapter::gLibrary_, "GRD_DBRepair");
67     GRD_DBApiInfo.DbGetConfigApi = (DBGetConfig)dlsym(PreferenceDbAdapter::gLibrary_, "GRD_GetConfig");
68 #endif
69 }
70 
71 const std::map<int, int> GRDErrnoMap = {
72     { GRD_OK, E_OK },
73     { GRD_NOT_SUPPORT, E_NOT_SUPPORTED },
74     { GRD_OVER_LIMIT, E_DEFAULT_EXCEED_LENGTH_LIMIT },
75     { GRD_INVALID_ARGS, E_INVALID_ARGS },
76     { GRD_FAILED_MEMORY_ALLOCATE, E_OUT_OF_MEMORY },
77     { GRD_FAILED_MEMORY_RELEASE, E_OUT_OF_MEMORY },
78     { GRD_PERMISSION_DENIED, PERMISSION_DENIED },
79     { GRD_NO_DATA, E_NO_DATA }
80 };
81 
TransferGrdErrno(int err)82 int TransferGrdErrno(int err)
83 {
84     if (err > 0) {
85         return err;
86     }
87 
88     auto iter = GRDErrnoMap.find(err);
89     if (iter != GRDErrnoMap.end()) {
90         return iter->second;
91     }
92 
93     return E_ERROR;
94 }
95 
IsEnhandceDbEnable()96 bool PreferenceDbAdapter::IsEnhandceDbEnable()
97 {
98     return PreferenceDbAdapter::gLibrary_ != nullptr;
99 }
100 
GetApiInstance()101 GRD_APIInfo& PreferenceDbAdapter::GetApiInstance()
102 {
103     if (PreferenceDbAdapter::isInit_) {
104         return PreferenceDbAdapter::api_;
105     }
106     ApiInit();
107     return PreferenceDbAdapter::api_;
108 }
109 
ApiInit()110 void PreferenceDbAdapter::ApiInit()
111 {
112     if (PreferenceDbAdapter::isInit_) {
113         return;
114     }
115     std::lock_guard<std::mutex> lck(PreferenceDbAdapter::apiMutex_);
116     if (PreferenceDbAdapter::isInit_) {
117         return;
118     }
119     PreferenceDbAdapter::gLibrary_ = DBDlOpen();
120     if (PreferenceDbAdapter::gLibrary_ != nullptr) {
121         GRDDBApiInitEnhance(PreferenceDbAdapter::api_);
122     } else {
123         LOG_DEBUG("use default db kernel");
124     }
125     PreferenceDbAdapter::isInit_ = true;
126     return;
127 }
128 
PreferencesDb()129 PreferencesDb::PreferencesDb()
130 {
131 }
132 
~PreferencesDb()133 PreferencesDb::~PreferencesDb()
134 {
135     if (db_ != nullptr || PreferenceDbAdapter::GetApiInstance().DbCloseApi != nullptr) {
136         PreferenceDbAdapter::GetApiInstance().DbCloseApi(db_, GRD_DB_CLOSE_IGNORE_ERROR);
137         db_ = nullptr;
138         LOG_DEBUG("destructor: calling close db.");
139     } else {
140         LOG_DEBUG("destructor: db closed before or dbClose api not loaded, db closed before ? %{public}d.",
141             db_ == nullptr);
142     }
143 }
144 
GetReportParam(const std::string &info, uint32_t errCode)145 ReportParam PreferencesDb::GetReportParam(const std::string &info, uint32_t errCode)
146 {
147     ReportParam reportParam = {
148         bundleName_,
149         ENHANCE_DB,
150         ExtractFileName(dbPath_),
151         errCode,
152         errno,
153         info};
154     return reportParam;
155 }
156 
CloseDb()157 int PreferencesDb::CloseDb()
158 {
159     if (db_ != nullptr) {
160         if (PreferenceDbAdapter::GetApiInstance().DbCloseApi == nullptr) {
161             LOG_ERROR("api load failed: DbCloseApi");
162             return E_ERROR;
163         }
164         int errCode = PreferenceDbAdapter::GetApiInstance().DbCloseApi(db_, GRD_DB_CLOSE_IGNORE_ERROR);
165         if (errCode != E_OK) {
166             LOG_ERROR("close db failed, errcode=%{public}d, file: %{public}s", errCode,
167                 ExtractFileName(dbPath_).c_str());
168             return TransferGrdErrno(errCode);
169         }
170         LOG_INFO("db has been closed.");
171         db_ = nullptr;
172         return E_OK;
173     }
174     LOG_INFO("CloseDb: DB closed before.");
175     return E_OK;
176 }
177 
CreateCollection()178 int PreferencesDb::CreateCollection()
179 {
180     if (PreferenceDbAdapter::GetApiInstance().DbCreateCollectionApi == nullptr) {
181         LOG_ERROR("api load failed: DbCreateCollectionApi");
182         return E_ERROR;
183     }
184     int errCode = PreferenceDbAdapter::GetApiInstance().DbCreateCollectionApi(db_, TABLENAME,
185         TABLE_MODE, 0);
186     if (errCode != GRD_OK) {
187         LOG_ERROR("rd create table failed:%{public}d", errCode);
188     }
189     return TransferGrdErrno(errCode);
190 }
191 
OpenDb(bool isNeedRebuild)192 int PreferencesDb::OpenDb(bool isNeedRebuild)
193 {
194     if (PreferenceDbAdapter::GetApiInstance().DbOpenApi == nullptr) {
195         LOG_ERROR("api load failed: DbOpenApi");
196         return E_ERROR;
197     }
198     uint32_t flag = GRD_DB_OPEN_CREATE;
199     if (isNeedRebuild) {
200         flag |= GRD_DB_OPEN_CHECK;
201     }
202     int errCode = PreferenceDbAdapter::GetApiInstance().DbOpenApi(dbPath_.c_str(), CONFIG_STR, flag, &db_);
203     if (errCode != GRD_OK) {
204         // log outside
205         std::string errMsg = isNeedRebuild ? "open db failed with open_create | open_check" :
206                 "open db failed with open_create";
207         LOG_ERROR("%{public}s, errCode: %{public}d, isRebuild:%{public}d", errMsg.c_str(), errCode, isNeedRebuild);
208     }
209     return errCode;
210 }
211 
RepairDb()212 int PreferencesDb::RepairDb()
213 {
214     if (PreferenceDbAdapter::GetApiInstance().DbRepairApi == nullptr) {
215         LOG_ERROR("api load failed: DbRepairApi");
216         return E_ERROR;
217     }
218     int errCode = PreferenceDbAdapter::GetApiInstance().DbRepairApi(dbPath_.c_str(), CONFIG_STR);
219     if (errCode != GRD_OK) {
220         std::string errMsg = "db repair failed";
221         LOG_ERROR("repair db failed, errCode: %{public}d", errCode);
222     }
223     return errCode;
224 }
225 
TryRepairAndRebuild(int openCode)226 int PreferencesDb::TryRepairAndRebuild(int openCode)
227 {
228     LOG_ERROR("db corrupted, errCode: %{public}d, begin to rebuild, db: %{public}s", openCode,
229         ExtractFileName(dbPath_).c_str());
230     int retryTimes = DB_REPAIR_RETRY_TIMES;
231     int innerErr = GRD_OK;
232     do {
233         innerErr = RepairDb();
234         if (innerErr == GRD_OK) {
235             LOG_INFO("db repair success");
236             return innerErr;
237         } else if (innerErr == GRD_DB_BUSY) {
238             LOG_ERROR("db repair failed, busy, retry times : %{public}d, errCode: %{public}d",
239                 (DB_REPAIR_RETRY_TIMES - retryTimes + 1), innerErr);
240 #if !defined(WINDOWS_PLATFORM)
241             std::this_thread::sleep_for(WAIT_REPAIRE_TIMEOUT);
242 #endif
243         } else {
244             // other error, break to rebuild
245             LOG_ERROR("db repair failed: %{public}d, begin to rebuild", innerErr);
246             break;
247         }
248         retryTimes--;
249     } while (retryTimes > 0);
250 
251     innerErr = OpenDb(true);
252     if (innerErr == GRD_OK || innerErr == GRD_REBUILD_DATABASE) {
253         LOG_INFO("rebuild db success, errCode: %{public}d", innerErr);
254         return GRD_OK;
255     }
256     LOG_ERROR("rebuild db failed, errCode: %{public}d, file: %{public}s", innerErr, ExtractFileName(dbPath_).c_str());
257     return innerErr;
258 }
259 
Init(const std::string &dbPath, const std::string &bundleName)260 int PreferencesDb::Init(const std::string &dbPath, const std::string &bundleName)
261 {
262     if (db_ != nullptr) {
263         LOG_DEBUG("Init: already init.");
264         return E_OK;
265     }
266     if (PreferenceDbAdapter::GetApiInstance().DbIndexPreloadApi == nullptr) {
267         LOG_ERROR("api load failed: DbIndexPreloadApi");
268         return E_ERROR;
269     }
270     dbPath_ = dbPath + ".db";
271     bundleName_ = bundleName;
272     int errCode = OpenDb(false);
273     if (errCode == GRD_DATA_CORRUPTED) {
274         PreferencesDfxManager::ReportDbFault(GetReportParam("db corrupted", errCode));
275     }
276     if (errCode == GRD_DATA_CORRUPTED || errCode == GRD_INNER_ERR) {
277         int innerErr = TryRepairAndRebuild(errCode);
278         if (innerErr != GRD_OK) {
279             // log inside
280             return TransferGrdErrno(innerErr);
281         }
282         if (errCode == GRD_DATA_CORRUPTED) {
283             ReportParam param = GetReportParam("db repair success", GRD_OK);
284             param.errnoCode = 0;
285             PreferencesDfxManager::ReportDbFault(param);
286         }
287     } else if (errCode != GRD_OK) {
288         LOG_ERROR("db open failed, errCode: %{public}d", errCode);
289         return TransferGrdErrno(errCode);
290     }
291 
292     errCode = CreateCollection();
293     if (errCode != E_OK) {
294         LOG_ERROR("create collection failed when init: %{public}d, but ignored.", errCode);
295         // ignore create collection error
296     }
297 
298     errCode = TransferGrdErrno(PreferenceDbAdapter::GetApiInstance().DbIndexPreloadApi(db_, TABLENAME));
299     if (errCode != E_OK) {
300         LOG_ERROR("Init: Index preload FAILED %{public}d", errCode);
301         return errCode;
302     }
303     return errCode;
304 }
305 
Put(const std::vector<uint8_t> &key, const std::vector<uint8_t> &value)306 int PreferencesDb::Put(const std::vector<uint8_t> &key, const std::vector<uint8_t> &value)
307 {
308     if (db_ == nullptr) {
309         LOG_ERROR("Put failed, db has been closed.");
310         return E_ALREADY_CLOSED;
311     } else if (PreferenceDbAdapter::GetApiInstance().DbKvPutApi == nullptr) {
312         LOG_ERROR("api load failed: DbKvPutApi");
313         return E_ERROR;
314     }
315 
316     GRD_KVItemT innerKey = BlobToKvItem(key);
317     GRD_KVItemT innerVal = BlobToKvItem(value);
318 
319     int retryTimes = CREATE_COLLECTION_RETRY_TIMES;
320     int ret = E_OK;
321     do {
322         ret = PreferenceDbAdapter::GetApiInstance().DbKvPutApi(db_, TABLENAME, &innerKey, &innerVal);
323         if (ret == GRD_UNDEFINED_TABLE) {
324             LOG_INFO("CreateCollection called when Put, file: %{public}s", ExtractFileName(dbPath_).c_str());
325             (void)CreateCollection();
326         } else {
327             if (ret == GRD_OK) {
328                 return TransferGrdErrno(ret);
329             } else {
330                 LOG_ERROR("rd put failed:%{public}d", ret);
331                 return TransferGrdErrno(ret);
332             }
333         }
334         retryTimes--;
335     } while (retryTimes > 0);
336 
337     LOG_ERROR("rd put over retry times, errcode: :%{public}d", ret);
338     return TransferGrdErrno(ret);
339 }
340 
Delete(const std::vector<uint8_t> &key)341 int PreferencesDb::Delete(const std::vector<uint8_t> &key)
342 {
343     if (db_ == nullptr) {
344         LOG_ERROR("Delete failed, db has been closed.");
345         return E_ALREADY_CLOSED;
346     } else if (PreferenceDbAdapter::GetApiInstance().DbKvDelApi == nullptr) {
347         LOG_ERROR("api load failed: DbKvDelApi");
348         return E_ERROR;
349     }
350 
351     GRD_KVItemT innerKey = BlobToKvItem(key);
352 
353     int retryTimes = CREATE_COLLECTION_RETRY_TIMES;
354     int ret = E_OK;
355     do {
356         ret = PreferenceDbAdapter::GetApiInstance().DbKvDelApi(db_, TABLENAME, &innerKey);
357         if (ret == GRD_UNDEFINED_TABLE) {
358             LOG_INFO("CreateCollection called when Delete, file: %{public}s", ExtractFileName(dbPath_).c_str());
359             (void)CreateCollection();
360         } else {
361             if (ret == E_OK) {
362                 return TransferGrdErrno(ret);
363             } else {
364                 LOG_ERROR("rd delete failed:%{public}d", ret);
365                 return TransferGrdErrno(ret);
366             }
367         }
368         retryTimes--;
369     } while (retryTimes > 0);
370 
371     LOG_ERROR("rd delete over retry times, errcode: :%{public}d", ret);
372     return TransferGrdErrno(ret);
373 }
374 
Get(const std::vector<uint8_t> &key, std::vector<uint8_t> &value)375 int PreferencesDb::Get(const std::vector<uint8_t> &key, std::vector<uint8_t> &value)
376 {
377     if (db_ == nullptr) {
378         LOG_ERROR("Get failed, db has been closed.");
379         return E_ALREADY_CLOSED;
380     } else if (PreferenceDbAdapter::GetApiInstance().DbKvGetApi == nullptr ||
381         PreferenceDbAdapter::GetApiInstance().FreeItemApi == nullptr) {
382         LOG_ERROR("api load failed: DbKvGetApi or FreeItemApi");
383         return E_ERROR;
384     }
385 
386     GRD_KVItemT innerKey = BlobToKvItem(key);
387     GRD_KVItemT innerVal = { NULL, 0 };
388 
389     int retryTimes = CREATE_COLLECTION_RETRY_TIMES;
390     int ret = E_OK;
391     do {
392         ret = PreferenceDbAdapter::GetApiInstance().DbKvGetApi(db_, TABLENAME, &innerKey, &innerVal);
393         if (ret == GRD_UNDEFINED_TABLE) {
394             LOG_INFO("CreateCollection called when Get, file: %{public}s", ExtractFileName(dbPath_).c_str());
395             (void)CreateCollection();
396         } else {
397             if (ret == E_OK) {
398                 break;
399             } else {
400                 LOG_ERROR("rd get failed:%{public}d", ret);
401                 return TransferGrdErrno(ret);
402             }
403         }
404         retryTimes--;
405     } while (retryTimes > 0);
406 
407     if (retryTimes == 0) {
408         LOG_ERROR("rd get over retry times, errcode: :%{public}d", ret);
409         return TransferGrdErrno(ret);
410     }
411     value.resize(innerVal.dataLen);
412     value = KvItemToBlob(innerVal);
413     (void)PreferenceDbAdapter::GetApiInstance().FreeItemApi(&innerVal);
414     return TransferGrdErrno(ret);
415 }
416 
GetAllInner(std::list<std::pair<std::vector<uint8_t>, std::vector<uint8_t>>> &data, GRD_ResultSet *resultSet)417 int PreferencesDb::GetAllInner(std::list<std::pair<std::vector<uint8_t>, std::vector<uint8_t>>> &data,
418     GRD_ResultSet *resultSet)
419 {
420     int ret = E_OK;
421     while (TransferGrdErrno(PreferenceDbAdapter::GetApiInstance().NextApi(resultSet)) == E_OK) {
422         std::pair<std::vector<uint8_t>, std::vector<uint8_t>> dataItem;
423         uint32_t keySize = 0;
424         uint32_t valueSize = 0;
425         ret = PreferenceDbAdapter::GetApiInstance().GetItemSizeApi(resultSet, &keySize, &valueSize);
426         if (ret != GRD_OK) {
427             LOG_ERROR("ger reulstSet kv size failed %{public}d", ret);
428             return TransferGrdErrno(ret);
429         }
430         dataItem.first.resize(keySize);
431         dataItem.second.resize(valueSize);
432         ret = PreferenceDbAdapter::GetApiInstance().GetItemApi(resultSet, dataItem.first.data(),
433             dataItem.second.data());
434         if (ret != E_OK) {
435             LOG_ERROR("ger reulstSet failed %{public}d", ret);
436             return TransferGrdErrno(ret);
437         }
438         data.emplace_back(std::move(dataItem));
439     }
440     return TransferGrdErrno(ret);
441 }
442 
IsApiValid()443 static inline bool IsApiValid()
444 {
445     auto& apiInstance = PreferenceDbAdapter::GetApiInstance();
446     return (apiInstance.DbKvFilterApi != nullptr && apiInstance.NextApi != nullptr &&
447         apiInstance.GetItemSizeApi != nullptr && apiInstance.GetItemApi != nullptr &&
448         apiInstance.FreeResultSetApi != nullptr);
449 }
450 
GetAll(std::list<std::pair<std::vector<uint8_t>, std::vector<uint8_t>>> &data)451 int PreferencesDb::GetAll(std::list<std::pair<std::vector<uint8_t>, std::vector<uint8_t>>> &data)
452 {
453     if (db_ == nullptr) {
454         LOG_ERROR("GetAll failed, db has been closed.");
455         return E_ALREADY_CLOSED;
456     }
457     if (!IsApiValid()) {
458         LOG_ERROR("api load failed when get all");
459         return E_ERROR;
460     }
461 
462     GRD_FilterOptionT param;
463     param.mode = KV_SCAN_ALL;
464     GRD_ResultSet *resultSet = nullptr;
465 
466     int retryTimes = CREATE_COLLECTION_RETRY_TIMES;
467     int ret = E_OK;
468 
469     do {
470         ret = PreferenceDbAdapter::GetApiInstance().DbKvFilterApi(db_, TABLENAME, &param, &resultSet);
471         if (ret == GRD_UNDEFINED_TABLE) {
472             LOG_INFO("CreateCollection called when GetAll, file: %{public}s", ExtractFileName(dbPath_).c_str());
473             (void)CreateCollection();
474         } else if (ret == GRD_OK) {
475             int innerErr = GetAllInner(data, resultSet); // log inside when failed
476             PreferenceDbAdapter::GetApiInstance().FreeResultSetApi(resultSet);
477             return innerErr;
478         } else {
479             LOG_ERROR("rd kv filter failed:%{public}d", ret);
480             return TransferGrdErrno(ret);
481         }
482         retryTimes--;
483     } while (retryTimes > 0);
484 
485     LOG_ERROR("rd get over retry times, errcode: :%{public}d", ret);
486     return TransferGrdErrno(ret);
487 }
488 
DropCollection()489 int PreferencesDb::DropCollection()
490 {
491     if (db_ == nullptr) {
492         LOG_ERROR("DropCollection failed, db has been closed.");
493         return E_ALREADY_CLOSED;
494     } else if (PreferenceDbAdapter::GetApiInstance().DbDropCollectionApi == nullptr) {
495         LOG_ERROR("api load failed: DbDropCollectionApi");
496         return E_ERROR;
497     }
498 
499     int errCode = PreferenceDbAdapter::GetApiInstance().DbDropCollectionApi(db_, TABLENAME, 0);
500     if (errCode != E_OK) {
501         LOG_ERROR("rd drop collection failed:%{public}d", errCode);
502     }
503     return TransferGrdErrno(errCode);
504 }
505 
BlobToKvItem(const std::vector<uint8_t> &blob)506 GRD_KVItemT PreferencesDb::BlobToKvItem(const std::vector<uint8_t> &blob)
507 {
508     return {
509         .data = (void *)&blob[0],
510         .dataLen = (uint32_t)blob.size()
511     };
512 }
513 
KvItemToBlob(GRD_KVItemT &item)514 std::vector<uint8_t> PreferencesDb::KvItemToBlob(GRD_KVItemT &item)
515 {
516     return std::vector<uint8_t>(static_cast<uint8_t *>(item.data),
517         static_cast<uint8_t *>(item.data) + item.dataLen);
518 }
519 
GetKernelDataVersion(int64_t &dataVersion)520 int PreferencesDb::GetKernelDataVersion(int64_t &dataVersion)
521 {
522     if (db_ == nullptr) {
523         LOG_ERROR("Get kernel data version failed, db has been closed.");
524         return E_ALREADY_CLOSED;
525     } else if (PreferenceDbAdapter::GetApiInstance().DbGetConfigApi == nullptr) {
526         LOG_ERROR("api load failed: DbGetConfigApi");
527         return E_ERROR;
528     }
529 
530     GRD_DbValueT kernelDataVersion = PreferenceDbAdapter::GetApiInstance().DbGetConfigApi(db_,
531         GRD_ConfigTypeE::GRD_CONFIG_DATA_VERSION);
532     if (kernelDataVersion.type != GRD_DbDataTypeE::GRD_DB_DATATYPE_INTEGER) {
533         LOG_ERROR("get wrong data version type: %d", kernelDataVersion.type);
534         return E_ERROR;
535     }
536 
537     dataVersion = kernelDataVersion.value.longValue;
538     return E_OK;
539 }
540 } // End of namespace NativePreferences
541 } // End of namespace OHOS