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