• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 <atomic>
16 #include <cstdlib>
17 #include "bundle_service_constants.h"
18 #include "rdb_data_manager.h"
19 
20 #include "app_log_wrapper.h"
21 #include "bundle_util.h"
22 #include "event_report.h"
23 #include "scope_guard.h"
24 
25 namespace OHOS {
26 namespace AppExecFwk {
27 namespace {
28 constexpr const char* BMS_KEY = "KEY";
29 constexpr const char* BMS_VALUE = "VALUE";
30 constexpr int8_t BMS_KEY_INDEX = 0;
31 constexpr int8_t BMS_VALUE_INDEX = 1;
32 constexpr int16_t WRITE_TIMEOUT = 300; // 300s
33 constexpr int32_t CLOSE_TIME = 20 * 1000; // delay 20s stop rdbStore
34 constexpr int32_t OPERATION_TYPE_OF_INSUFFICIENT_DISK = 3;
35 static std::atomic<int64_t> g_lastReportTime = 0;
36 constexpr int64_t REPORTING_INTERVAL = 1000 * 60 * 30; // 30min
37 constexpr int32_t RETRY_TIMES = 3;
38 constexpr int32_t RETRY_INTERVAL = 500; // 500ms
39 constexpr const char* INTEGRITY_CHECK = "PRAGMA integrity_check";
40 constexpr const char* CHECK_OK = "ok";
41 const std::unordered_map<int32_t, int32_t> RDB_ERR_MAP = {
42     {NativeRdb::E_OK, ERR_OK},
43     {NativeRdb::E_NOT_SELECT, ERR_APPEXECFWK_DB_SQL_MUST_BE_QUERY_STATEMENT},
44     {NativeRdb::E_COLUMN_OUT_RANGE, ERR_APPEXECFWK_DB_COLUMN_OUT_OF_BOUNDS},
45     {NativeRdb::E_INVALID_FILE_PATH, ERR_APPEXECFWK_DB_INVALID_DATABASE_PATH},
46     {NativeRdb::E_ROW_OUT_RANGE, ERR_APPEXECFWK_DB_ROW_OUT_OF_BOUNDS},
47     {NativeRdb::E_NO_ROW_IN_QUERY, ERR_APPEXECFWK_DB_NO_DATA_MEETS_CONDITION},
48     {NativeRdb::E_ALREADY_CLOSED, ERR_APPEXECFWK_DB_ALREADY_CLOSED},
49     {NativeRdb::E_DATABASE_BUSY, ERR_APPEXECFWK_DB_DO_NOT_RESPOND},
50     {NativeRdb::E_WAL_SIZE_OVER_LIMIT, ERR_APPEXECFWK_DB_THE_WAL_FILE_SIZE_OVER_DEFAULT_LIMIT},
51     {NativeRdb::E_GET_DATAOBSMGRCLIENT_FAIL, ERR_APPEXECFWK_DB_FAILED_TO_GET_DATA_OBS_MGR_CLIENT},
52     {NativeRdb::E_TYPE_MISMATCH, ERR_APPEXECFWK_DB_THE_TYPE_OF_DISTRIBUTED_TABLE_NOT_MATCH},
53     {NativeRdb::E_SQLITE_FULL, ERR_APPEXECFWK_DB_IS_FULL},
54     {NativeRdb::E_NOT_SUPPORT_THE_SQL, ERR_APPEXECFWK_DB_NOT_SUPPORT_THS_SQL},
55     {NativeRdb::E_ATTACHED_DATABASE_EXIST, ERR_APPEXECFWK_DB_IS_ALREADY_ATTACHED},
56     {NativeRdb::E_SQLITE_ERROR, ERR_APPEXECFWK_DB_SQL_GENERIC_ERROR},
57     {NativeRdb::E_SQLITE_CORRUPT, ERR_APPEXECFWK_DB_SQL_CORRUPTED},
58     {NativeRdb::E_SQLITE_ABORT, ERR_APPEXECFWK_DB_SQL_CALLBACK_ROUTINE_REQUESTED_AN_ABORT},
59     {NativeRdb::E_SQLITE_PERM, ERR_APPEXECFWK_DB_SQL_ACCESS_PERMISSION_DENIED},
60     {NativeRdb::E_SQLITE_BUSY, ERR_APPEXECFWK_DB_SQL_FILE_IS_LOCKED},
61     {NativeRdb::E_SQLITE_LOCKED, ERR_APPEXECFWK_DB_SQL_TABLE_IS_LOCKED},
62     {NativeRdb::E_SQLITE_NOMEM, ERR_APPEXECFWK_DB_SQL_DB_IS_OUT_OF_MEMORY},
63     {NativeRdb::E_SQLITE_READONLY, ERR_APPEXECFWK_DB_SQL_ATTEMPT_WRITE_READONLY_DB},
64     {NativeRdb::E_SQLITE_IOERR, ERR_APPEXECFWK_DB_SQL_SOME_KIND_OF_DISK_IO_ERROR},
65     {NativeRdb::E_SQLITE_CANTOPEN, ERR_APPEXECFWK_DB_SQL_UNABLE_OPEN_DB_FILE},
66     {NativeRdb::E_SQLITE_TOOBIG, ERR_APPEXECFWK_DB_SQL_TEXT_OR_BLOB_EXCEED_SIZE_LIMIT},
67     {NativeRdb::E_SQLITE_CONSTRAINT, ERR_APPEXECFWK_DB_SQL_ABORT_DUE_TO_CONSTRAINT_VIOLATION},
68     {NativeRdb::E_SQLITE_MISMATCH, ERR_APPEXECFWK_DB_SQL_DATA_TYPE_MISMATCH},
69     {NativeRdb::E_SQLITE_MISUSE, ERR_APPEXECFWK_DB_SQL_LIBRARY_USED_INCORRECTLY},
70     {NativeRdb::E_CONFIG_INVALID_CHANGE, ERR_APPEXECFWK_DB_CONFIG_CHANGED},
71     {NativeRdb::E_NOT_SUPPORT, ERR_APPEXECFWK_DB_CAPABILITY_NOT_SUPPORT},
72 };
73 }
74 
75 ffrt::mutex RdbDataManager::restoreRdbMapMutex_;
76 std::unordered_map<std::string, ffrt::mutex> RdbDataManager::restoreRdbMap_;
77 
RdbDataManager(const BmsRdbConfig & bmsRdbConfig)78 RdbDataManager::RdbDataManager(const BmsRdbConfig &bmsRdbConfig)
79     : bmsRdbConfig_(bmsRdbConfig)
80 {
81     delayedTaskMgr_ = std::make_shared<SingleDelayedTaskMgr>(bmsRdbConfig.tableName, CLOSE_TIME);
82 }
83 
~RdbDataManager()84 RdbDataManager::~RdbDataManager()
85 {
86     rdbStore_ = nullptr;
87 }
88 
ClearCache()89 void RdbDataManager::ClearCache()
90 {
91     NativeRdb::RdbHelper::ClearCache();
92 }
93 
GetRdbRestoreMutex(const std::string & dbName)94 ffrt::mutex &RdbDataManager::GetRdbRestoreMutex(const std::string &dbName)
95 {
96     std::lock_guard<ffrt::mutex> restoreLock(restoreRdbMapMutex_);
97     if (!isInitial_) {
98         isInitial_ = restoreRdbMap_.find(dbName) != restoreRdbMap_.end();
99     }
100     return restoreRdbMap_[dbName];
101 }
102 
GetRdbStoreFromNative()103 ErrCode RdbDataManager::GetRdbStoreFromNative()
104 {
105     auto &mutex = GetRdbRestoreMutex(bmsRdbConfig_.dbName);
106     std::lock_guard<ffrt::mutex> restoreLock(mutex);
107     NativeRdb::RdbStoreConfig rdbStoreConfig(bmsRdbConfig_.dbPath + bmsRdbConfig_.dbName);
108     rdbStoreConfig.SetSecurityLevel(NativeRdb::SecurityLevel::S1);
109     rdbStoreConfig.SetWriteTime(WRITE_TIMEOUT);
110     rdbStoreConfig.SetAllowRebuild(true);
111     rdbStoreConfig.SetHaMode(NativeRdb::HAMode::MAIN_REPLICA);
112     // for check db exist or not
113     if (access(rdbStoreConfig.GetPath().c_str(), F_OK) != 0) {
114         APP_LOGW("bms db :%{public}s is not exist, need to create. errno:%{public}d",
115             rdbStoreConfig.GetPath().c_str(), errno);
116     }
117     int32_t errCode = NativeRdb::E_OK;
118     BmsRdbOpenCallback bmsRdbOpenCallback(bmsRdbConfig_);
119     rdbStore_ = NativeRdb::RdbHelper::GetRdbStore(
120         rdbStoreConfig,
121         bmsRdbConfig_.version,
122         bmsRdbOpenCallback, errCode);
123     if (rdbStore_ == nullptr) {
124         APP_LOGE("GetRdbStore failed, errCode:%{public}d", errCode);
125         SendDbErrorEvent(bmsRdbConfig_.dbName, static_cast<int32_t>(DB_OPERATION_TYPE::OPEN), errCode);
126         return errCode;
127     }
128     CheckSystemSizeAndHisysEvent(bmsRdbConfig_.dbPath, bmsRdbConfig_.dbName);
129     bool isNeedRebuildDb = false;
130     if (!isInitial_) {
131         isNeedRebuildDb = RdbIntegrityCheckNeedRestore();
132         isInitial_ = true;
133     }
134     NativeRdb::RebuiltType rebuildType = NativeRdb::RebuiltType::NONE;
135     int32_t rebuildCode = rdbStore_->GetRebuilt(rebuildType);
136     if (rebuildType == NativeRdb::RebuiltType::REBUILT || isNeedRebuildDb) {
137         APP_LOGI("start %{public}s restore ret %{public}d, type:%{public}d", bmsRdbConfig_.dbName.c_str(),
138             rebuildCode, static_cast<int32_t>(rebuildType));
139         int32_t restoreRet = rdbStore_->Restore("");
140         if (restoreRet != NativeRdb::E_OK) {
141             APP_LOGE("rdb restore failed ret:%{public}d", restoreRet);
142         }
143         SendDbErrorEvent(bmsRdbConfig_.dbName, static_cast<int32_t>(DB_OPERATION_TYPE::REBUILD), rebuildCode);
144         return restoreRet;
145     }
146     return ERR_OK;
147 }
148 
GetRdbStore(ErrCode & result)149 std::shared_ptr<NativeRdb::RdbStore> RdbDataManager::GetRdbStore(ErrCode &result)
150 {
151     std::lock_guard<ffrt::mutex> lock(rdbMutex_);
152     if (rdbStore_ == nullptr) {
153         result = GetRdbStoreFromNative();
154     }
155     auto it = RDB_ERR_MAP.find(result);
156     if (it != RDB_ERR_MAP.end()) {
157         result = it->second;
158     } else {
159         result = ERR_APPEXECFWK_INSTALL_INTERNAL_ERROR;
160     }
161 
162     if (rdbStore_ != nullptr) {
163         DelayCloseRdbStore();
164     }
165     return rdbStore_;
166 }
167 
CheckSystemSizeAndHisysEvent(const std::string & path,const std::string & fileName)168 void RdbDataManager::CheckSystemSizeAndHisysEvent(const std::string &path, const std::string &fileName)
169 {
170     if (!CheckIsSatisfyTime()) {
171         APP_LOGD("not satisfy time");
172         return;
173     }
174     bool isInsufficientSpace = BundleUtil::CheckSystemSizeAndHisysEvent(path, fileName);
175     if (isInsufficientSpace) {
176         APP_LOGW("space not enough %{public}s", fileName.c_str());
177         EventReport::SendDiskSpaceEvent(fileName, 0, OPERATION_TYPE_OF_INSUFFICIENT_DISK);
178     }
179 }
180 
CheckIsSatisfyTime()181 bool RdbDataManager::CheckIsSatisfyTime()
182 {
183     int64_t now = BundleUtil::GetCurrentTimeMs();
184     if (abs(now - g_lastReportTime) < REPORTING_INTERVAL) {
185         APP_LOGD("time is not up yet");
186         return false;
187     }
188     g_lastReportTime = now;
189     return true;
190 }
191 
SendDbErrorEvent(const std::string & dbName,int32_t operationType,int32_t errorCode)192 void RdbDataManager::SendDbErrorEvent(const std::string &dbName, int32_t operationType, int32_t errorCode)
193 {
194     EventReport::SendDbErrorEvent(dbName, operationType, errorCode);
195 }
196 
InsertData(const std::string & key,const std::string & value)197 bool RdbDataManager::InsertData(const std::string &key, const std::string &value)
198 {
199     APP_LOGD("InsertData start");
200     ErrCode ret = ERR_OK;
201     auto rdbStore = GetRdbStore(ret);
202     if (rdbStore == nullptr) {
203         APP_LOGE("RdbStore is null");
204         return false;
205     }
206 
207     int64_t rowId = -1;
208     NativeRdb::ValuesBucket valuesBucket;
209     valuesBucket.PutString(BMS_KEY, key);
210     valuesBucket.PutString(BMS_VALUE, value);
211     ret = InsertWithRetry(rdbStore, rowId, valuesBucket);
212     return ret == NativeRdb::E_OK;
213 }
214 
InsertDataWithCode(const std::string & key,const std::string & value)215 ErrCode RdbDataManager::InsertDataWithCode(const std::string &key, const std::string &value)
216 {
217     APP_LOGD("InsertData start");
218     ErrCode ret = ERR_OK;
219     auto rdbStore = GetRdbStore(ret);
220     if (rdbStore == nullptr) {
221         APP_LOGE("RdbStore is null");
222         return ret;
223     }
224 
225     int64_t rowId = -1;
226     NativeRdb::ValuesBucket valuesBucket;
227     valuesBucket.PutString(BMS_KEY, key);
228     valuesBucket.PutString(BMS_VALUE, value);
229     return InsertWithRetry(rdbStore, rowId, valuesBucket);
230 }
231 
InsertData(const NativeRdb::ValuesBucket & valuesBucket)232 bool RdbDataManager::InsertData(const NativeRdb::ValuesBucket &valuesBucket)
233 {
234     APP_LOGD("InsertData start");
235     ErrCode ret = ERR_OK;
236     auto rdbStore = GetRdbStore(ret);
237     if (rdbStore == nullptr) {
238         APP_LOGE("RdbStore is null");
239         return false;
240     }
241 
242     int64_t rowId = -1;
243     ret = InsertWithRetry(rdbStore, rowId, valuesBucket);
244     return ret == NativeRdb::E_OK;
245 }
246 
BatchInsert(int64_t & outInsertNum,const std::vector<NativeRdb::ValuesBucket> & valuesBuckets)247 bool RdbDataManager::BatchInsert(int64_t &outInsertNum, const std::vector<NativeRdb::ValuesBucket> &valuesBuckets)
248 {
249     APP_LOGD("BatchInsert start");
250     ErrCode ret = ERR_OK;
251     auto rdbStore = GetRdbStore(ret);
252     if (rdbStore == nullptr) {
253         APP_LOGE("RdbStore is null");
254         return false;
255     }
256     ret = rdbStore->BatchInsert(outInsertNum, bmsRdbConfig_.tableName, valuesBuckets);
257     return ret == NativeRdb::E_OK;
258 }
259 
UpdateData(const std::string & key,const std::string & value)260 bool RdbDataManager::UpdateData(const std::string &key, const std::string &value)
261 {
262     APP_LOGD("UpdateData start");
263     ErrCode ret = ERR_OK;
264     auto rdbStore = GetRdbStore(ret);
265     if (rdbStore == nullptr) {
266         APP_LOGE("RdbStore is null");
267         return false;
268     }
269 
270     int32_t rowId = -1;
271     NativeRdb::AbsRdbPredicates absRdbPredicates(bmsRdbConfig_.tableName);
272     absRdbPredicates.EqualTo(BMS_KEY, key);
273     NativeRdb::ValuesBucket valuesBucket;
274     valuesBucket.PutString(BMS_KEY, key);
275     valuesBucket.PutString(BMS_VALUE, value);
276     ret = rdbStore->Update(rowId, valuesBucket, absRdbPredicates);
277     return ret == NativeRdb::E_OK;
278 }
279 
UpdateData(const NativeRdb::ValuesBucket & valuesBucket,const NativeRdb::AbsRdbPredicates & absRdbPredicates)280 bool RdbDataManager::UpdateData(
281     const NativeRdb::ValuesBucket &valuesBucket, const NativeRdb::AbsRdbPredicates &absRdbPredicates)
282 {
283     APP_LOGD("UpdateData start");
284     ErrCode ret = ERR_OK;
285     auto rdbStore = GetRdbStore(ret);
286     if (rdbStore == nullptr) {
287         APP_LOGE("RdbStore is null");
288         return false;
289     }
290     if (absRdbPredicates.GetTableName() != bmsRdbConfig_.tableName) {
291         APP_LOGE("RdbStore table is invalid");
292         return false;
293     }
294     int32_t rowId = -1;
295     ret = rdbStore->Update(rowId, valuesBucket, absRdbPredicates);
296     return ret == NativeRdb::E_OK;
297 }
298 
UpdateOrInsertData(const NativeRdb::ValuesBucket & valuesBucket,const NativeRdb::AbsRdbPredicates & absRdbPredicates)299 bool RdbDataManager::UpdateOrInsertData(
300     const NativeRdb::ValuesBucket &valuesBucket, const NativeRdb::AbsRdbPredicates &absRdbPredicates)
301 {
302     APP_LOGD("UpdateOrInsertData start");
303     ErrCode ret = ERR_OK;
304     auto rdbStore = GetRdbStore(ret);
305     if (rdbStore == nullptr) {
306         APP_LOGE("RdbStore is null");
307         return false;
308     }
309     if (absRdbPredicates.GetTableName() != bmsRdbConfig_.tableName) {
310         APP_LOGE("RdbStore table is invalid");
311         return false;
312     }
313     int32_t rowId = -1;
314     ret = rdbStore->Update(rowId, valuesBucket, absRdbPredicates);
315     if ((ret == NativeRdb::E_OK) && (rowId == 0)) {
316         APP_LOGI_NOFUNC("data not exist, need insert data");
317         int64_t rowIdInsert = -1;
318         ret = rdbStore->InsertWithConflictResolution(
319             rowIdInsert, bmsRdbConfig_.tableName, valuesBucket, NativeRdb::ConflictResolution::ON_CONFLICT_REPLACE);
320     }
321     return ret == NativeRdb::E_OK;
322 }
323 
DeleteData(const std::string & key)324 bool RdbDataManager::DeleteData(const std::string &key)
325 {
326     APP_LOGD("DeleteData start");
327     ErrCode ret = ERR_OK;
328     auto rdbStore = GetRdbStore(ret);
329     if (rdbStore == nullptr) {
330         APP_LOGE("RdbStore is null");
331         return false;
332     }
333 
334     int32_t rowId = -1;
335     NativeRdb::AbsRdbPredicates absRdbPredicates(bmsRdbConfig_.tableName);
336     absRdbPredicates.EqualTo(BMS_KEY, key);
337     ret = rdbStore->Delete(rowId, absRdbPredicates);
338     return ret == NativeRdb::E_OK;
339 }
340 
DeleteData(const NativeRdb::AbsRdbPredicates & absRdbPredicates)341 bool RdbDataManager::DeleteData(const NativeRdb::AbsRdbPredicates &absRdbPredicates)
342 {
343     ErrCode ret = ERR_OK;
344     auto rdbStore = GetRdbStore(ret);
345     if (rdbStore == nullptr) {
346         APP_LOGE("RdbStore is null");
347         return false;
348     }
349     if (absRdbPredicates.GetTableName() != bmsRdbConfig_.tableName) {
350         APP_LOGE("RdbStore table is invalid");
351         return false;
352     }
353     int32_t rowId = -1;
354     ret = rdbStore->Delete(rowId, absRdbPredicates);
355     return ret == NativeRdb::E_OK;
356 }
357 
QueryData(const std::string & key,std::string & value)358 bool RdbDataManager::QueryData(const std::string &key, std::string &value)
359 {
360     APP_LOGD("QueryData start");
361     ErrCode ret = ERR_OK;
362     auto rdbStore = GetRdbStore(ret);
363     if (rdbStore == nullptr) {
364         APP_LOGE("RdbStore is null");
365         return false;
366     }
367 
368     NativeRdb::AbsRdbPredicates absRdbPredicates(bmsRdbConfig_.tableName);
369     absRdbPredicates.EqualTo(BMS_KEY, key);
370     auto absSharedResultSet = rdbStore->QueryByStep(absRdbPredicates, std::vector<std::string>());
371     if (absSharedResultSet == nullptr) {
372         APP_LOGE("absSharedResultSet failed");
373         return false;
374     }
375     ScopeGuard stateGuard([&] { absSharedResultSet->Close(); });
376     ret = absSharedResultSet->GoToFirstRow();
377     if (ret != NativeRdb::E_OK) {
378         APP_LOGE("GoToFirstRow failed, ret: %{public}d", ret);
379         return false;
380     }
381 
382     ret = absSharedResultSet->GetString(BMS_VALUE_INDEX, value);
383     if (ret != NativeRdb::E_OK) {
384         APP_LOGE("QueryData failed, ret: %{public}d", ret);
385         return false;
386     }
387 
388     return true;
389 }
390 
QueryData(const NativeRdb::AbsRdbPredicates & absRdbPredicates)391 std::shared_ptr<NativeRdb::ResultSet> RdbDataManager::QueryData(
392     const NativeRdb::AbsRdbPredicates &absRdbPredicates)
393 {
394     APP_LOGD("QueryData start");
395     ErrCode ret = ERR_OK;
396     auto rdbStore = GetRdbStore(ret);
397     if (rdbStore == nullptr) {
398         APP_LOGE("RdbStore is null");
399         return nullptr;
400     }
401     if (absRdbPredicates.GetTableName() != bmsRdbConfig_.tableName) {
402         APP_LOGE("RdbStore table is invalid");
403         return nullptr;
404     }
405     auto absSharedResultSet = rdbStore->QueryByStep(absRdbPredicates, std::vector<std::string>());
406     if (absSharedResultSet == nullptr) {
407         APP_LOGE("absSharedResultSet failed");
408         return nullptr;
409     }
410     return absSharedResultSet;
411 }
412 
QueryAllData(std::map<std::string,std::string> & datas)413 bool RdbDataManager::QueryAllData(std::map<std::string, std::string> &datas)
414 {
415     APP_LOGD("QueryAllData start");
416     ErrCode ret = ERR_OK;
417     auto rdbStore = GetRdbStore(ret);
418     if (rdbStore == nullptr) {
419         APP_LOGE("RdbStore is null");
420         return false;
421     }
422 
423     NativeRdb::AbsRdbPredicates absRdbPredicates(bmsRdbConfig_.tableName);
424     auto absSharedResultSet = rdbStore->QueryByStep(absRdbPredicates, std::vector<std::string>());
425     if (absSharedResultSet == nullptr) {
426         APP_LOGE("absSharedResultSet failed");
427         return false;
428     }
429     ScopeGuard stateGuard([&] { absSharedResultSet->Close(); });
430 
431     if (absSharedResultSet->GoToFirstRow() != NativeRdb::E_OK) {
432         APP_LOGE("GoToFirstRow failed");
433         return false;
434     }
435 
436     do {
437         std::string key;
438         if (absSharedResultSet->GetString(BMS_KEY_INDEX, key) != NativeRdb::E_OK) {
439             APP_LOGE("GetString key failed");
440             return false;
441         }
442 
443         std::string value;
444         if (absSharedResultSet->GetString(BMS_VALUE_INDEX, value) != NativeRdb::E_OK) {
445             APP_LOGE("GetString value failed");
446             return false;
447         }
448 
449         datas.emplace(key, value);
450     } while (absSharedResultSet->GoToNextRow() == NativeRdb::E_OK);
451     return !datas.empty();
452 }
453 
CreateTable()454 bool RdbDataManager::CreateTable()
455 {
456     std::string createTableSql;
457     if (bmsRdbConfig_.createTableSql.empty()) {
458         createTableSql = std::string(
459             "CREATE TABLE IF NOT EXISTS "
460             + bmsRdbConfig_.tableName
461             + "(KEY TEXT NOT NULL PRIMARY KEY, VALUE TEXT NOT NULL);");
462     } else {
463         createTableSql = bmsRdbConfig_.createTableSql;
464     }
465     ErrCode ret = ERR_OK;
466     auto rdbStore = GetRdbStore(ret);
467     if (rdbStore == nullptr) {
468         APP_LOGE("RdbStore is null");
469         return false;
470     }
471     ret = rdbStore->ExecuteSql(createTableSql);
472     if (ret != NativeRdb::E_OK) {
473         APP_LOGE("CreateTable %{public}s failed, ret: %{public}d", bmsRdbConfig_.tableName.c_str(), ret);
474         return false;
475     }
476     for (const auto &sql : bmsRdbConfig_.insertColumnSql) {
477         int32_t insertRet = rdbStore->ExecuteSql(sql);
478         if (insertRet != NativeRdb::E_OK) {
479             APP_LOGW_NOFUNC("ExecuteSql insertColumnSql failed ret: %{public}d", insertRet);
480         }
481     }
482     return true;
483 }
484 
DelayCloseRdbStore()485 void RdbDataManager::DelayCloseRdbStore()
486 {
487     APP_LOGD("RdbDataManager DelayCloseRdbStore start");
488     std::weak_ptr<RdbDataManager> weakPtr = shared_from_this();
489     auto task = [weakPtr]() {
490         APP_LOGD("DelayCloseRdbStore thread begin");
491         auto sharedPtr = weakPtr.lock();
492         if (sharedPtr == nullptr) {
493             return;
494         }
495         std::lock_guard<ffrt::mutex> lock(sharedPtr->rdbMutex_);
496         sharedPtr->rdbStore_ = nullptr;
497         APP_LOGD("DelayCloseRdbStore of %{public}s thread end", sharedPtr->bmsRdbConfig_.tableName.c_str());
498     };
499     delayedTaskMgr_->ScheduleDelayedTask(task);
500 }
501 
RdbIntegrityCheckNeedRestore()502 bool RdbDataManager::RdbIntegrityCheckNeedRestore()
503 {
504     APP_LOGI("integrity check start db %{public}s", bmsRdbConfig_.dbName.c_str());
505     if (rdbStore_ == nullptr) {
506         APP_LOGE("RdbStore is null");
507         return false;
508     }
509     auto [ret, outValue] = rdbStore_->Execute(INTEGRITY_CHECK);
510     if (ret == NativeRdb::E_OK) {
511         std::string outputResult;
512         outValue.GetString(outputResult);
513         if (outputResult != CHECK_OK) {
514             APP_LOGW("rdb error need to restore");
515             return true;
516         }
517         APP_LOGI("integrity check succeed db %{public}s", bmsRdbConfig_.dbName.c_str());
518     }
519     return false;
520 }
521 
QueryByStep(const NativeRdb::AbsRdbPredicates & absRdbPredicates)522 std::shared_ptr<NativeRdb::ResultSet> RdbDataManager::QueryByStep(
523     const NativeRdb::AbsRdbPredicates &absRdbPredicates)
524 {
525     APP_LOGD("QueryByStep start");
526     ErrCode ret = ERR_OK;
527     auto rdbStore = GetRdbStore(ret);
528     if (rdbStore == nullptr) {
529         APP_LOGE("RdbStore is null");
530         return nullptr;
531     }
532     if (absRdbPredicates.GetTableName() != bmsRdbConfig_.tableName) {
533         APP_LOGE("RdbStore table is invalid");
534         return nullptr;
535     }
536     auto absSharedResultSet = rdbStore->QueryByStep(absRdbPredicates, std::vector<std::string>());
537     if (absSharedResultSet == nullptr) {
538         APP_LOGE("absSharedResultSet failed");
539         return nullptr;
540     }
541     return absSharedResultSet;
542 }
543 
InsertWithRetry(std::shared_ptr<NativeRdb::RdbStore> rdbStore,int64_t & rowId,const NativeRdb::ValuesBucket & valuesBucket)544 int32_t RdbDataManager::InsertWithRetry(std::shared_ptr<NativeRdb::RdbStore> rdbStore, int64_t &rowId,
545     const NativeRdb::ValuesBucket &valuesBucket)
546 {
547     int32_t retryCnt = 0;
548     int32_t ret = 0;
549     do {
550         ret = rdbStore->InsertWithConflictResolution(rowId, bmsRdbConfig_.tableName,
551             valuesBucket, NativeRdb::ConflictResolution::ON_CONFLICT_REPLACE);
552         if (ret == NativeRdb::E_OK || !IsRetryErrCode(ret)) {
553             break;
554         }
555         if (++retryCnt < RETRY_TIMES) {
556             std::this_thread::sleep_for(std::chrono::milliseconds(RETRY_INTERVAL));
557         }
558         APP_LOGW("rdb insert failed, retry count: %{public}d, ret: %{public}d", retryCnt, ret);
559     } while (retryCnt < RETRY_TIMES);
560     auto it = RDB_ERR_MAP.find(ret);
561     if (it != RDB_ERR_MAP.end()) {
562         ret = it->second;
563         return ret;
564     }
565     return ERR_APPEXECFWK_INSTALL_INTERNAL_ERROR;
566 }
567 
IsRetryErrCode(int32_t errCode)568 bool RdbDataManager::IsRetryErrCode(int32_t errCode)
569 {
570     if (errCode == NativeRdb::E_DATABASE_BUSY ||
571         errCode == NativeRdb::E_SQLITE_BUSY ||
572         errCode == NativeRdb::E_SQLITE_LOCKED ||
573         errCode == NativeRdb::E_SQLITE_NOMEM ||
574         errCode == NativeRdb::E_SQLITE_IOERR) {
575         return true;
576     }
577     return false;
578 }
579 }  // namespace AppExecFwk
580 }  // namespace OHOS
581