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
16 #include "rdb_data_manager.h"
17
18 #include "app_log_wrapper.h"
19 #include "bundle_util.h"
20 #include "event_report.h"
21 #include "scope_guard.h"
22
23 namespace OHOS {
24 namespace AppExecFwk {
25 namespace {
26 constexpr const char* BMS_KEY = "KEY";
27 constexpr const char* BMS_VALUE = "VALUE";
28 constexpr int8_t BMS_KEY_INDEX = 0;
29 constexpr int8_t BMS_VALUE_INDEX = 1;
30 constexpr int16_t WRITE_TIMEOUT = 300; // 300s
31 constexpr int8_t CLOSE_TIME = 20; // delay 20s stop rdbStore
32 constexpr const char* BMS_BACK_UP_RDB_NAME = "bms-backup.db";
33 constexpr int32_t OPERATION_TYPE_OF_INSUFFICIENT_DISK = 3;
34 }
35
36 std::mutex RdbDataManager::restoreRdbMutex_;
37
RdbDataManager(const BmsRdbConfig &bmsRdbConfig)38 RdbDataManager::RdbDataManager(const BmsRdbConfig &bmsRdbConfig)
39 : bmsRdbConfig_(bmsRdbConfig)
40 {
41 }
42
~RdbDataManager()43 RdbDataManager::~RdbDataManager()
44 {
45 rdbStore_ = nullptr;
46 }
47
ClearCache()48 void RdbDataManager::ClearCache()
49 {
50 NativeRdb::RdbHelper::ClearCache();
51 }
52
GetRdbStore()53 std::shared_ptr<NativeRdb::RdbStore> RdbDataManager::GetRdbStore()
54 {
55 std::lock_guard<std::mutex> lock(rdbMutex_);
56 if (rdbStore_ != nullptr) {
57 return rdbStore_;
58 }
59 std::lock_guard<std::mutex> restoreLock(restoreRdbMutex_);
60 NativeRdb::RdbStoreConfig rdbStoreConfig(bmsRdbConfig_.dbPath + bmsRdbConfig_.dbName);
61 rdbStoreConfig.SetSecurityLevel(NativeRdb::SecurityLevel::S1);
62 rdbStoreConfig.SetWriteTime(WRITE_TIMEOUT);
63 rdbStoreConfig.SetAllowRebuild(true);
64 if (!isInitial_) {
65 rdbStoreConfig.SetIntegrityCheck(NativeRdb::IntegrityCheck::FULL);
66 isInitial_ = true;
67 }
68 // for check db exist or not
69 bool isNeedRebuildDb = false;
70 std::string rdbFilePath = bmsRdbConfig_.dbPath + std::string("/") + std::string(BMS_BACK_UP_RDB_NAME);
71 if (access(rdbStoreConfig.GetPath().c_str(), F_OK) != 0) {
72 APP_LOGW("bms db :%{public}s is not exist, need to create. errno:%{public}d",
73 rdbStoreConfig.GetPath().c_str(), errno);
74 if (access(rdbFilePath.c_str(), F_OK) == 0) {
75 isNeedRebuildDb = true;
76 }
77 }
78 int32_t errCode = NativeRdb::E_OK;
79 BmsRdbOpenCallback bmsRdbOpenCallback(bmsRdbConfig_);
80 rdbStore_ = NativeRdb::RdbHelper::GetRdbStore(
81 rdbStoreConfig,
82 bmsRdbConfig_.version,
83 bmsRdbOpenCallback,
84 errCode);
85 if (rdbStore_ == nullptr) {
86 APP_LOGE("GetRdbStore failed, errCode:%{public}d", errCode);
87 return nullptr;
88 }
89 CheckSystemSizeAndHisysEvent(bmsRdbConfig_.dbPath, bmsRdbConfig_.dbName);
90 NativeRdb::RebuiltType rebuildType = NativeRdb::RebuiltType::NONE;
91 int32_t rebuildCode = rdbStore_->GetRebuilt(rebuildType);
92 if (rebuildType == NativeRdb::RebuiltType::REBUILT || isNeedRebuildDb) {
93 APP_LOGI("start %{public}s restore ret %{public}d, type:%{public}d", bmsRdbConfig_.dbName.c_str(),
94 rebuildCode, static_cast<int32_t>(rebuildType));
95 int32_t restoreRet = rdbStore_->Restore(rdbFilePath);
96 if (restoreRet != NativeRdb::E_OK) {
97 APP_LOGE("rdb restore failed ret:%{public}d", restoreRet);
98 }
99 }
100
101 if (rdbStore_ != nullptr) {
102 DelayCloseRdbStore();
103 }
104 return rdbStore_;
105 }
106
CheckSystemSizeAndHisysEvent(const std::string &path, const std::string &fileName)107 void RdbDataManager::CheckSystemSizeAndHisysEvent(const std::string &path, const std::string &fileName)
108 {
109 bool flag = BundleUtil::CheckSystemSizeAndHisysEvent(path, fileName);
110 if (flag) {
111 APP_LOGW("space not enough %{public}s", fileName.c_str());
112 EventReport::SendDiskSpaceEvent(fileName, 0, OPERATION_TYPE_OF_INSUFFICIENT_DISK);
113 }
114 }
115
BackupRdb()116 void RdbDataManager::BackupRdb()
117 {
118 APP_LOGI("%{public}s backup start", bmsRdbConfig_.dbName.c_str());
119 auto rdbStore = GetRdbStore();
120 if (rdbStore == nullptr) {
121 APP_LOGE("RdbStore is null");
122 return;
123 }
124 auto ret = rdbStore->Backup(bmsRdbConfig_.dbPath + std::string("/") + std::string(BMS_BACK_UP_RDB_NAME));
125 if (ret != NativeRdb::E_OK) {
126 APP_LOGE("Backup failed, errCode:%{public}d", ret);
127 }
128 APP_LOGI("%{public}s backup end", bmsRdbConfig_.dbName.c_str());
129 }
130
InsertData(const std::string &key, const std::string &value)131 bool RdbDataManager::InsertData(const std::string &key, const std::string &value)
132 {
133 APP_LOGD("InsertData start");
134 auto rdbStore = GetRdbStore();
135 if (rdbStore == nullptr) {
136 APP_LOGE("RdbStore is null");
137 return false;
138 }
139
140 int64_t rowId = -1;
141 NativeRdb::ValuesBucket valuesBucket;
142 valuesBucket.PutString(BMS_KEY, key);
143 valuesBucket.PutString(BMS_VALUE, value);
144 auto ret = rdbStore->InsertWithConflictResolution(
145 rowId, bmsRdbConfig_.tableName, valuesBucket, NativeRdb::ConflictResolution::ON_CONFLICT_REPLACE);
146 return ret == NativeRdb::E_OK;
147 }
148
InsertData(const NativeRdb::ValuesBucket &valuesBucket)149 bool RdbDataManager::InsertData(const NativeRdb::ValuesBucket &valuesBucket)
150 {
151 APP_LOGD("InsertData start");
152 auto rdbStore = GetRdbStore();
153 if (rdbStore == nullptr) {
154 APP_LOGE("RdbStore is null");
155 return false;
156 }
157
158 int64_t rowId = -1;
159 auto ret = rdbStore->InsertWithConflictResolution(
160 rowId, bmsRdbConfig_.tableName, valuesBucket, NativeRdb::ConflictResolution::ON_CONFLICT_REPLACE);
161 return ret == NativeRdb::E_OK;
162 }
163
BatchInsert(int64_t &outInsertNum, const std::vector<NativeRdb::ValuesBucket> &valuesBuckets)164 bool RdbDataManager::BatchInsert(int64_t &outInsertNum, const std::vector<NativeRdb::ValuesBucket> &valuesBuckets)
165 {
166 APP_LOGD("BatchInsert start");
167 auto rdbStore = GetRdbStore();
168 if (rdbStore == nullptr) {
169 APP_LOGE("RdbStore is null");
170 return false;
171 }
172 auto ret = rdbStore->BatchInsert(outInsertNum, bmsRdbConfig_.tableName, valuesBuckets);
173 return ret == NativeRdb::E_OK;
174 }
175
UpdateData(const std::string &key, const std::string &value)176 bool RdbDataManager::UpdateData(const std::string &key, const std::string &value)
177 {
178 APP_LOGD("UpdateData start");
179 auto rdbStore = GetRdbStore();
180 if (rdbStore == nullptr) {
181 APP_LOGE("RdbStore is null");
182 return false;
183 }
184
185 int32_t rowId = -1;
186 NativeRdb::AbsRdbPredicates absRdbPredicates(bmsRdbConfig_.tableName);
187 absRdbPredicates.EqualTo(BMS_KEY, key);
188 NativeRdb::ValuesBucket valuesBucket;
189 valuesBucket.PutString(BMS_KEY, key);
190 valuesBucket.PutString(BMS_VALUE, value);
191 auto ret = rdbStore->Update(rowId, valuesBucket, absRdbPredicates);
192 return ret == NativeRdb::E_OK;
193 }
194
UpdateData( const NativeRdb::ValuesBucket &valuesBucket, const NativeRdb::AbsRdbPredicates &absRdbPredicates)195 bool RdbDataManager::UpdateData(
196 const NativeRdb::ValuesBucket &valuesBucket, const NativeRdb::AbsRdbPredicates &absRdbPredicates)
197 {
198 APP_LOGD("UpdateData start");
199 auto rdbStore = GetRdbStore();
200 if (rdbStore == nullptr) {
201 APP_LOGE("RdbStore is null");
202 return false;
203 }
204 if (absRdbPredicates.GetTableName() != bmsRdbConfig_.tableName) {
205 APP_LOGE("RdbStore table is invalid");
206 return false;
207 }
208 int32_t rowId = -1;
209 auto ret = rdbStore->Update(rowId, valuesBucket, absRdbPredicates);
210 return ret == NativeRdb::E_OK;
211 }
212
UpdateOrInsertData( const NativeRdb::ValuesBucket &valuesBucket, const NativeRdb::AbsRdbPredicates &absRdbPredicates)213 bool RdbDataManager::UpdateOrInsertData(
214 const NativeRdb::ValuesBucket &valuesBucket, const NativeRdb::AbsRdbPredicates &absRdbPredicates)
215 {
216 APP_LOGD("UpdateOrInsertData start");
217 auto rdbStore = GetRdbStore();
218 if (rdbStore == nullptr) {
219 APP_LOGE("RdbStore is null");
220 return false;
221 }
222 if (absRdbPredicates.GetTableName() != bmsRdbConfig_.tableName) {
223 APP_LOGE("RdbStore table is invalid");
224 return false;
225 }
226 int32_t rowId = -1;
227 auto ret = rdbStore->Update(rowId, valuesBucket, absRdbPredicates);
228 if ((ret == NativeRdb::E_OK) && (rowId == 0)) {
229 APP_LOGI_NOFUNC("data not exist, need insert data");
230 int64_t rowIdInsert = -1;
231 ret = rdbStore->InsertWithConflictResolution(
232 rowIdInsert, bmsRdbConfig_.tableName, valuesBucket, NativeRdb::ConflictResolution::ON_CONFLICT_REPLACE);
233 }
234 return ret == NativeRdb::E_OK;
235 }
236
DeleteData(const std::string &key)237 bool RdbDataManager::DeleteData(const std::string &key)
238 {
239 APP_LOGD("DeleteData start");
240 auto rdbStore = GetRdbStore();
241 if (rdbStore == nullptr) {
242 APP_LOGE("RdbStore is null");
243 return false;
244 }
245
246 int32_t rowId = -1;
247 NativeRdb::AbsRdbPredicates absRdbPredicates(bmsRdbConfig_.tableName);
248 absRdbPredicates.EqualTo(BMS_KEY, key);
249 auto ret = rdbStore->Delete(rowId, absRdbPredicates);
250 return ret == NativeRdb::E_OK;
251 }
252
DeleteData(const NativeRdb::AbsRdbPredicates &absRdbPredicates)253 bool RdbDataManager::DeleteData(const NativeRdb::AbsRdbPredicates &absRdbPredicates)
254 {
255 auto rdbStore = GetRdbStore();
256 if (rdbStore == nullptr) {
257 APP_LOGE("RdbStore is null");
258 return false;
259 }
260 if (absRdbPredicates.GetTableName() != bmsRdbConfig_.tableName) {
261 APP_LOGE("RdbStore table is invalid");
262 return false;
263 }
264 int32_t rowId = -1;
265 auto ret = rdbStore->Delete(rowId, absRdbPredicates);
266 return ret == NativeRdb::E_OK;
267 }
268
QueryData(const std::string &key, std::string &value)269 bool RdbDataManager::QueryData(const std::string &key, std::string &value)
270 {
271 APP_LOGD("QueryData start");
272 auto rdbStore = GetRdbStore();
273 if (rdbStore == nullptr) {
274 APP_LOGE("RdbStore is null");
275 return false;
276 }
277
278 NativeRdb::AbsRdbPredicates absRdbPredicates(bmsRdbConfig_.tableName);
279 absRdbPredicates.EqualTo(BMS_KEY, key);
280 auto absSharedResultSet = rdbStore->Query(absRdbPredicates, std::vector<std::string>());
281 if (absSharedResultSet == nullptr) {
282 APP_LOGE("absSharedResultSet failed");
283 return false;
284 }
285 ScopeGuard stateGuard([&] { absSharedResultSet->Close(); });
286 if (!absSharedResultSet->HasBlock()) {
287 APP_LOGE("absSharedResultSet has no block");
288 return false;
289 }
290 auto ret = absSharedResultSet->GoToFirstRow();
291 if (ret != NativeRdb::E_OK) {
292 APP_LOGE("GoToFirstRow failed, ret: %{public}d", ret);
293 return false;
294 }
295
296 ret = absSharedResultSet->GetString(BMS_VALUE_INDEX, value);
297 if (ret != NativeRdb::E_OK) {
298 APP_LOGE("QueryData failed, ret: %{public}d", ret);
299 return false;
300 }
301
302 return true;
303 }
304
QueryData( const NativeRdb::AbsRdbPredicates &absRdbPredicates)305 std::shared_ptr<NativeRdb::AbsSharedResultSet> RdbDataManager::QueryData(
306 const NativeRdb::AbsRdbPredicates &absRdbPredicates)
307 {
308 APP_LOGD("QueryData start");
309 auto rdbStore = GetRdbStore();
310 if (rdbStore == nullptr) {
311 APP_LOGE("RdbStore is null");
312 return nullptr;
313 }
314 if (absRdbPredicates.GetTableName() != bmsRdbConfig_.tableName) {
315 APP_LOGE("RdbStore table is invalid");
316 return nullptr;
317 }
318 auto absSharedResultSet = rdbStore->Query(absRdbPredicates, std::vector<std::string>());
319 if (absSharedResultSet == nullptr || !absSharedResultSet->HasBlock()) {
320 APP_LOGE("absSharedResultSet failed");
321 return nullptr;
322 }
323 return absSharedResultSet;
324 }
325
QueryAllData(std::map<std::string, std::string> &datas)326 bool RdbDataManager::QueryAllData(std::map<std::string, std::string> &datas)
327 {
328 APP_LOGD("QueryAllData start");
329 auto rdbStore = GetRdbStore();
330 if (rdbStore == nullptr) {
331 APP_LOGE("RdbStore is null");
332 return false;
333 }
334
335 NativeRdb::AbsRdbPredicates absRdbPredicates(bmsRdbConfig_.tableName);
336 auto absSharedResultSet = rdbStore->Query(absRdbPredicates, std::vector<std::string>());
337 if (absSharedResultSet == nullptr) {
338 APP_LOGE("absSharedResultSet failed");
339 return false;
340 }
341 ScopeGuard stateGuard([&] { absSharedResultSet->Close(); });
342 if (!absSharedResultSet->HasBlock()) {
343 APP_LOGE("absSharedResultSet has no block");
344 return false;
345 }
346
347 if (absSharedResultSet->GoToFirstRow() != NativeRdb::E_OK) {
348 APP_LOGE("GoToFirstRow failed");
349 return false;
350 }
351
352 do {
353 std::string key;
354 if (absSharedResultSet->GetString(BMS_KEY_INDEX, key) != NativeRdb::E_OK) {
355 APP_LOGE("GetString key failed");
356 return false;
357 }
358
359 std::string value;
360 if (absSharedResultSet->GetString(BMS_VALUE_INDEX, value) != NativeRdb::E_OK) {
361 APP_LOGE("GetString value failed");
362 return false;
363 }
364
365 datas.emplace(key, value);
366 } while (absSharedResultSet->GoToNextRow() == NativeRdb::E_OK);
367 return !datas.empty();
368 }
369
CreateTable()370 bool RdbDataManager::CreateTable()
371 {
372 std::string createTableSql;
373 if (bmsRdbConfig_.createTableSql.empty()) {
374 createTableSql = std::string(
375 "CREATE TABLE IF NOT EXISTS "
376 + bmsRdbConfig_.tableName
377 + "(KEY TEXT NOT NULL PRIMARY KEY, VALUE TEXT NOT NULL);");
378 } else {
379 createTableSql = bmsRdbConfig_.createTableSql;
380 }
381 auto rdbStore = GetRdbStore();
382 if (rdbStore == nullptr) {
383 APP_LOGE("RdbStore is null");
384 return false;
385 }
386 int ret = rdbStore->ExecuteSql(createTableSql);
387 if (ret != NativeRdb::E_OK) {
388 APP_LOGE("CreateTable failed, ret: %{public}d", ret);
389 return false;
390 }
391 for (const auto &sql : bmsRdbConfig_.insertColumnSql) {
392 int32_t insertRet = rdbStore->ExecuteSql(sql);
393 if (insertRet != NativeRdb::E_OK) {
394 APP_LOGW_NOFUNC("ExecuteSql insertColumnSql failed ret: %{public}d", insertRet);
395 }
396 }
397 return true;
398 }
399
DelayCloseRdbStore()400 void RdbDataManager::DelayCloseRdbStore()
401 {
402 APP_LOGD("RdbDataManager DelayCloseRdbStore start");
403 std::weak_ptr<RdbDataManager> weakPtr = shared_from_this();
404 auto task = [weakPtr]() {
405 APP_LOGD("RdbDataManager DelayCloseRdbStore thread begin");
406 std::this_thread::sleep_for(std::chrono::seconds(CLOSE_TIME));
407 auto sharedPtr = weakPtr.lock();
408 if (sharedPtr == nullptr) {
409 return;
410 }
411 std::lock_guard<std::mutex> lock(sharedPtr->rdbMutex_);
412 sharedPtr->rdbStore_ = nullptr;
413 APP_LOGD("RdbDataManager DelayCloseRdbStore thread end");
414 };
415 std::thread closeRdbStoreThread(task);
416 closeRdbStoreThread.detach();
417 }
418
QueryByStep( const NativeRdb::AbsRdbPredicates &absRdbPredicates)419 std::shared_ptr<NativeRdb::ResultSet> RdbDataManager::QueryByStep(
420 const NativeRdb::AbsRdbPredicates &absRdbPredicates)
421 {
422 APP_LOGD("QueryByStep start");
423 auto rdbStore = GetRdbStore();
424 if (rdbStore == nullptr) {
425 APP_LOGE("RdbStore is null");
426 return nullptr;
427 }
428 if (absRdbPredicates.GetTableName() != bmsRdbConfig_.tableName) {
429 APP_LOGE("RdbStore table is invalid");
430 return nullptr;
431 }
432 auto absSharedResultSet = rdbStore->QueryByStep(absRdbPredicates, std::vector<std::string>());
433 if (absSharedResultSet == nullptr) {
434 APP_LOGE("absSharedResultSet failed");
435 return nullptr;
436 }
437 return absSharedResultSet;
438 }
439 } // namespace AppExecFwk
440 } // namespace OHOS
441