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