• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-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 "data_center/database/form_rdb_data_mgr.h"
16 
17 #include <cinttypes>
18 #include <thread>
19 #include <filesystem>
20 #include <sstream>
21 #include <sys/stat.h>
22 #include <unistd.h>
23 #include "fms_log_wrapper.h"
24 #include "form_constants.h"
25 #include "form_mgr_errors.h"
26 #include "common/util/form_util.h"
27 #include "common/util/scope_guard.h"
28 #include "common/event/form_event_report.h"
29 
30 namespace OHOS {
31 namespace AppExecFwk {
32 namespace {
33 const std::string FORM_KEY = "KEY";
34 const std::string FORM_VALUE = "VALUE";
35 const int32_t FORM_KEY_INDEX = 0;
36 const int32_t FORM_VALUE_INDEX = 1;
37 const int64_t MIN_FORM_RDB_REBUILD_INTERVAL = 10000; // 10s
38 } // namespace
RdbStoreDataCallBackFormInfoStorage(const std::string & rdbPath)39 RdbStoreDataCallBackFormInfoStorage::RdbStoreDataCallBackFormInfoStorage(const std::string &rdbPath)
40     : rdbPath_(rdbPath)
41 {
42     HILOG_DEBUG("Create rdb store callback instance");
43 }
44 
~RdbStoreDataCallBackFormInfoStorage()45 RdbStoreDataCallBackFormInfoStorage::~RdbStoreDataCallBackFormInfoStorage()
46 {
47     HILOG_DEBUG("Destroy rdb store callback instance");
48 }
49 
OnCreate(NativeRdb::RdbStore & rdbStore)50 int32_t RdbStoreDataCallBackFormInfoStorage::OnCreate(NativeRdb::RdbStore &rdbStore)
51 {
52     HILOG_DEBUG("OnCreate");
53     return NativeRdb::E_OK;
54 }
55 
OnUpgrade(NativeRdb::RdbStore & rdbStore,int currentVersion,int targetVersion)56 int32_t RdbStoreDataCallBackFormInfoStorage::OnUpgrade(
57     NativeRdb::RdbStore &rdbStore, int currentVersion, int targetVersion)
58 {
59     HILOG_DEBUG("OnUpgrade currentVersion: %{plubic}d, targetVersion: %{plubic}d",
60         currentVersion, targetVersion);
61     return NativeRdb::E_OK;
62 }
63 
OnDowngrade(NativeRdb::RdbStore & rdbStore,int currentVersion,int targetVersion)64 int32_t RdbStoreDataCallBackFormInfoStorage::OnDowngrade(
65     NativeRdb::RdbStore &rdbStore, int currentVersion, int targetVersion)
66 {
67     HILOG_DEBUG("OnDowngrade  currentVersion: %{plubic}d, targetVersion: %{plubic}d",
68         currentVersion, targetVersion);
69     return NativeRdb::E_OK;
70 }
71 
OnOpen(NativeRdb::RdbStore & rdbStore)72 int32_t RdbStoreDataCallBackFormInfoStorage::OnOpen(NativeRdb::RdbStore &rdbStore)
73 {
74     HILOG_DEBUG("OnOpen");
75     return NativeRdb::E_OK;
76 }
77 
onCorruption(std::string databaseFile)78 int32_t RdbStoreDataCallBackFormInfoStorage::onCorruption(std::string databaseFile)
79 {
80     FormEventReport::SendFormFailedEvent(FormEventName::CALLEN_DB_FAILED, HiSysEventType::FAULT,
81         static_cast<int64_t>(CallDbFiledErrorType::DATABASE_EXIT_ABNORMAL));
82     return NativeRdb::E_OK;
83 }
84 
FormRdbDataMgr()85 FormRdbDataMgr::FormRdbDataMgr()
86 {
87     HILOG_INFO("Create");
88 }
89 
~FormRdbDataMgr()90 FormRdbDataMgr::~FormRdbDataMgr()
91 {
92     HILOG_INFO("Destruct");
93 }
94 
InitFormRdbTable(const FormRdbTableConfig & formRdbTableConfig)95 ErrCode FormRdbDataMgr::InitFormRdbTable(const FormRdbTableConfig &formRdbTableConfig)
96 {
97     HILOG_INFO("Init");
98     if (formRdbTableConfig.tableName.empty()) {
99         HILOG_ERROR("empty FormRdbTableName");
100         return ERR_APPEXECFWK_FORM_COMMON_CODE;
101     }
102 
103     auto formRdbTableCfgIter = formRdbTableCfgMap_.find(formRdbTableConfig.tableName);
104     if (formRdbTableCfgIter != formRdbTableCfgMap_.end()) {
105         formRdbTableCfgMap_[formRdbTableConfig.tableName] = formRdbTableConfig;
106     } else {
107         formRdbTableCfgMap_.emplace(formRdbTableConfig.tableName, formRdbTableConfig);
108     }
109 
110     if (rdbStore_ == nullptr && LoadRdbStore() != ERR_OK) {
111         HILOG_ERROR("null FormInfoRdbStore");
112         return ERR_APPEXECFWK_FORM_COMMON_CODE;
113     }
114 
115     std::string createTableSql = !formRdbTableConfig.createTableSql.empty() ? formRdbTableConfig.createTableSql
116         : "CREATE TABLE IF NOT EXISTS " + formRdbTableConfig.tableName
117             + " (KEY TEXT NOT NULL PRIMARY KEY, VALUE TEXT NOT NULL);";
118 
119     int32_t ret = rdbStore_->ExecuteSql(createTableSql);
120     if (ret != NativeRdb::E_OK) {
121         HILOG_ERROR("Create rdb table failed, ret:%{public}" PRId32 "", ret);
122         return ERR_APPEXECFWK_FORM_COMMON_CODE;
123     }
124 
125     return ERR_OK;
126 }
127 
ExecuteSql(const std::string & sql)128 ErrCode FormRdbDataMgr::ExecuteSql(const std::string &sql)
129 {
130     if (!IsFormRdbLoaded()) {
131         HILOG_ERROR("null FormInfoRdbStore");
132         return ERR_APPEXECFWK_FORM_COMMON_CODE;
133     }
134 
135     int32_t ret = rdbStore_->ExecuteSql(sql);
136     if (ret == NativeRdb::E_OK) {
137         if (rdbStore_->IsSlaveDiffFromMaster()) {
138             auto backupRet = rdbStore_->Backup("");
139             HILOG_WARN("rdb slave corrupt, backup from master, ret=%{public}" PRId32, backupRet);
140         }
141     } else {
142         if (CheckAndRebuildRdbStore(ret) == ERR_OK) {
143             HILOG_WARN("Check rdb corrupt,rebuild form rdb successfully");
144             ret = rdbStore_->ExecuteSql(sql);
145         }
146     }
147 
148     if (ret == NativeRdb::E_OK) {
149         return ERR_OK;
150     }
151 
152     HILOG_WARN("ExecuteSql failed, ret=%{public}" PRId32, ret);
153     return ERR_APPEXECFWK_FORM_COMMON_CODE;
154 }
155 
InsertData(const std::string & tableName,const std::string & key)156 ErrCode FormRdbDataMgr::InsertData(const std::string &tableName, const std::string &key)
157 {
158     HILOG_DEBUG("InsertData start");
159     if (formRdbTableCfgMap_.find(tableName) == formRdbTableCfgMap_.end()) {
160         HILOG_ERROR("Form rdb hasn't initialized this table:%{public}s", tableName.c_str());
161         return ERR_APPEXECFWK_FORM_COMMON_CODE;
162     }
163 
164     if (!IsFormRdbLoaded()) {
165         HILOG_ERROR("null FormInfoRdbStore");
166         return ERR_APPEXECFWK_FORM_COMMON_CODE;
167     }
168 
169     NativeRdb::ValuesBucket valuesBucket;
170     valuesBucket.PutString(FORM_KEY, key);
171     int32_t ret = NativeRdb::E_OK;
172     int64_t rowId = -1;
173     ret = rdbStore_->InsertWithConflictResolution(rowId, tableName, valuesBucket,
174             NativeRdb::ConflictResolution::ON_CONFLICT_REPLACE);
175     if (ret == NativeRdb::E_OK) {
176         if (rdbStore_->IsSlaveDiffFromMaster()) {
177             auto backupRet = rdbStore_->Backup("");
178             HILOG_WARN("rdb slave corrupt, backup from master, ret=%{public}" PRId32, backupRet);
179         }
180     } else {
181         if (CheckAndRebuildRdbStore(ret) == ERR_OK) {
182             HILOG_WARN("Check rdb corrupt,rebuild form rdb successfully");
183             int64_t rowId = -1;
184             ret = rdbStore_->InsertWithConflictResolution(rowId, tableName, valuesBucket,
185                 NativeRdb::ConflictResolution::ON_CONFLICT_REPLACE);
186         }
187     }
188 
189     if (ret == NativeRdb::E_OK) {
190         return ERR_OK;
191     }
192     HILOG_WARN("Insert operation failed, key=%{public}s, ret=%{public}" PRId32, key.c_str(), ret);
193     return ERR_APPEXECFWK_FORM_COMMON_CODE;
194 }
195 
InsertData(const std::string & tableName,const std::string & key,const std::string & value)196 ErrCode FormRdbDataMgr::InsertData(const std::string &tableName, const std::string &key, const std::string &value)
197 {
198     HILOG_DEBUG("InsertData start");
199     if (formRdbTableCfgMap_.find(tableName) == formRdbTableCfgMap_.end()) {
200         HILOG_ERROR("Form rdb hasn't initialized this table:%{public}s", tableName.c_str());
201         return ERR_APPEXECFWK_FORM_COMMON_CODE;
202     }
203 
204     if (!IsFormRdbLoaded()) {
205         HILOG_ERROR("null FormInfoRdbStore");
206         return ERR_APPEXECFWK_FORM_COMMON_CODE;
207     }
208 
209     NativeRdb::ValuesBucket valuesBucket;
210     valuesBucket.PutString(FORM_KEY, key);
211     valuesBucket.PutString(FORM_VALUE, value);
212     int32_t ret = NativeRdb::E_OK;
213     int64_t rowId = -1;
214     ret = rdbStore_->InsertWithConflictResolution(rowId, tableName, valuesBucket,
215         NativeRdb::ConflictResolution::ON_CONFLICT_REPLACE);
216     if (ret == NativeRdb::E_OK) {
217         if (rdbStore_->IsSlaveDiffFromMaster()) {
218             auto backupRet = rdbStore_->Backup("");
219             HILOG_WARN("rdb slave corrupt, backup from master, ret=%{public}" PRId32, backupRet);
220         }
221     } else {
222         if (CheckAndRebuildRdbStore(ret) == ERR_OK) {
223             HILOG_WARN("Check rdb corrupt,rebuild form rdb successfully");
224             int64_t rowId = -1;
225             ret = rdbStore_->InsertWithConflictResolution(rowId, tableName, valuesBucket,
226                 NativeRdb::ConflictResolution::ON_CONFLICT_REPLACE);
227         }
228     }
229 
230     if (ret == NativeRdb::E_OK) {
231         return ERR_OK;
232     }
233 
234     HILOG_WARN("Insert operation failed, key=%{public}s, ret=%{public}" PRId32, key.c_str(), ret);
235     return ERR_APPEXECFWK_FORM_COMMON_CODE;
236 }
237 
DeleteData(const std::string & tableName,const std::string & key)238 ErrCode FormRdbDataMgr::DeleteData(const std::string &tableName, const std::string &key)
239 {
240     HILOG_DEBUG("DeleteData start");
241     if (formRdbTableCfgMap_.find(tableName) == formRdbTableCfgMap_.end()) {
242         HILOG_ERROR("Form rdb hasn't initialized this table:%{public}s", tableName.c_str());
243         return ERR_APPEXECFWK_FORM_COMMON_CODE;
244     }
245 
246     if (!IsFormRdbLoaded()) {
247         HILOG_ERROR("null FormInfoRdbStore");
248         return ERR_APPEXECFWK_FORM_COMMON_CODE;
249     }
250 
251     NativeRdb::AbsRdbPredicates absRdbPredicates(tableName);
252     absRdbPredicates.EqualTo(FORM_KEY, key);
253     int32_t ret = NativeRdb::E_OK;
254     int32_t rowId = -1;
255     ret = rdbStore_->Delete(rowId, absRdbPredicates);
256 
257     if (ret == NativeRdb::E_OK) {
258         if (rdbStore_->IsSlaveDiffFromMaster()) {
259             auto backupRet = rdbStore_->Backup("");
260             HILOG_WARN("rdb slave corrupt, backup from master, ret=%{public}" PRId32, backupRet);
261         }
262     } else {
263         if (CheckAndRebuildRdbStore(ret) == ERR_OK) {
264             HILOG_WARN("Check rdb corrupt,rebuild form rdb successfully");
265             int32_t rowId = -1;
266             ret = rdbStore_->Delete(rowId, absRdbPredicates);
267         }
268     }
269 
270     if (ret == NativeRdb::E_OK) {
271         return ERR_OK;
272     }
273 
274     HILOG_WARN("Delete operation failed, key=%{public}s, ret=%{public}" PRId32, key.c_str(), ret);
275     return ERR_APPEXECFWK_FORM_COMMON_CODE;
276 }
277 
QueryData(const std::string & tableName,const std::string & key,std::string & value)278 ErrCode FormRdbDataMgr::QueryData(const std::string &tableName, const std::string &key,
279     std::string &value)
280 {
281     HILOG_DEBUG("QueryData start");
282     if (formRdbTableCfgMap_.find(tableName) == formRdbTableCfgMap_.end()) {
283         HILOG_ERROR("Form rdb hasn't initialized this table:%{public}s", tableName.c_str());
284         return ERR_APPEXECFWK_FORM_COMMON_CODE;
285     }
286 
287     if (!IsFormRdbLoaded()) {
288         HILOG_ERROR("null FormInfoRdbStore");
289         return ERR_APPEXECFWK_FORM_COMMON_CODE;
290     }
291 
292     NativeRdb::AbsRdbPredicates absRdbPredicates(tableName);
293     absRdbPredicates.EqualTo(FORM_KEY, key);
294     auto absSharedResultSet = rdbStore_->Query(absRdbPredicates, std::vector<std::string>());
295 
296     if (absSharedResultSet == nullptr) {
297         HILOG_ERROR("null absSharedResultSet");
298         return ERR_APPEXECFWK_FORM_COMMON_CODE;
299     }
300 
301     ScopeGuard stateGuard([absSharedResultSet] {
302         if (absSharedResultSet) {
303             absSharedResultSet->Close();
304         }
305     });
306     if (!absSharedResultSet->HasBlock()) {
307         HILOG_ERROR("absSharedResultSet has no block");
308         return ERR_APPEXECFWK_FORM_COMMON_CODE;
309     }
310     int32_t ret = absSharedResultSet->GoToFirstRow();
311     if (ret != NativeRdb::E_OK) {
312         HILOG_ERROR("GoToFirstRow failed, ret:%{public}" PRId32 "", ret);
313     } else {
314         ret = absSharedResultSet->GetString(FORM_VALUE_INDEX, value);
315     }
316     absSharedResultSet->Close();
317 
318     if (ret == NativeRdb::E_OK) {
319         return ERR_OK;
320     }
321 
322     HILOG_WARN("Query operation failed, key=%{public}s", key.c_str());
323     if (CheckAndRebuildRdbStore(ret) == ERR_OK) {
324         HILOG_WARN("Check rdb corrupt,rebuild form rdb successfully");
325     }
326     return ERR_APPEXECFWK_FORM_COMMON_CODE;
327 }
328 
QueryData(const std::string & tableName,const std::string & key,std::unordered_map<std::string,std::string> & values)329 ErrCode FormRdbDataMgr::QueryData(const std::string &tableName, const std::string &key,
330     std::unordered_map<std::string, std::string> &values)
331 {
332     if (formRdbTableCfgMap_.find(tableName) == formRdbTableCfgMap_.end()) {
333         HILOG_ERROR("Form rdb hasn't initialized this table:%{public}s", tableName.c_str());
334         return ERR_APPEXECFWK_FORM_COMMON_CODE;
335     }
336 
337     if (!IsFormRdbLoaded()) {
338         HILOG_ERROR("null FormInfoRdbStore");
339         return ERR_APPEXECFWK_FORM_COMMON_CODE;
340     }
341 
342     NativeRdb::AbsRdbPredicates absRdbPredicates(tableName);
343     absRdbPredicates.BeginsWith(FORM_KEY, key);
344     auto absSharedResultSet = rdbStore_->Query(absRdbPredicates, std::vector<std::string>());
345     if (absSharedResultSet == nullptr) {
346         HILOG_ERROR("null absSharedResultSet");
347         return ERR_APPEXECFWK_FORM_COMMON_CODE;
348     }
349 
350     ScopeGuard stateGuard([absSharedResultSet] {
351         if (absSharedResultSet) {
352             absSharedResultSet->Close();
353         }
354     });
355 
356     if (!absSharedResultSet->HasBlock()) {
357         HILOG_ERROR("absSharedResultSet has no block");
358         return ERR_APPEXECFWK_FORM_COMMON_CODE;
359     }
360 
361     int32_t ret = absSharedResultSet->GoToFirstRow();
362     if (ret == NativeRdb::E_OK) {
363         do {
364             std::string resultKey;
365             ret = absSharedResultSet->GetString(FORM_KEY_INDEX, resultKey);
366             if (ret != NativeRdb::E_OK) {
367                 HILOG_ERROR("GetString key failed");
368                 break;
369             }
370 
371             std::string resultValue;
372             ret = absSharedResultSet->GetString(FORM_VALUE_INDEX, resultValue);
373             if (ret != NativeRdb::E_OK) {
374                 HILOG_ERROR("GetString value failed");
375                 break;
376             }
377 
378             values.emplace(resultKey, resultValue);
379         } while (absSharedResultSet->GoToNextRow() == NativeRdb::E_OK);
380     }
381     absSharedResultSet->Close();
382     if (ret == NativeRdb::E_OK) {
383         return ERR_OK;
384     }
385 
386     HILOG_WARN("Query operation failed, key=%{public}s", key.c_str());
387     if (CheckAndRebuildRdbStore(ret) == ERR_OK) {
388         HILOG_WARN("Check rdb corrupt,rebuild form rdb successfully");
389     }
390     return ERR_APPEXECFWK_FORM_COMMON_CODE;
391 }
392 
QueryAllData(const std::string & tableName,std::unordered_map<std::string,std::string> & datas)393 ErrCode FormRdbDataMgr::QueryAllData(const std::string &tableName,
394     std::unordered_map<std::string, std::string> &datas)
395 {
396     HILOG_DEBUG("QueryAllData start");
397     if (formRdbTableCfgMap_.find(tableName) == formRdbTableCfgMap_.end()) {
398         HILOG_ERROR("Form rdb hasn't initialized this table:%{public}s", tableName.c_str());
399         return ERR_APPEXECFWK_FORM_COMMON_CODE;
400     }
401 
402     if (!IsFormRdbLoaded()) {
403         HILOG_ERROR("null FormInfoRdbStore");
404         return ERR_APPEXECFWK_FORM_COMMON_CODE;
405     }
406 
407     NativeRdb::AbsRdbPredicates absRdbPredicates(tableName);
408     std::shared_lock<std::shared_mutex> guard(rdbStoreMutex_);
409     auto absSharedResultSet = rdbStore_->Query(absRdbPredicates, std::vector<std::string>());
410     guard.unlock();
411     if (absSharedResultSet == nullptr) {
412         HILOG_ERROR("null absSharedResultSet");
413         return ERR_APPEXECFWK_FORM_COMMON_CODE;
414     }
415 
416     ScopeGuard stateGuard([absSharedResultSet] {
417         if (absSharedResultSet) {
418             absSharedResultSet->Close();
419         }
420     });
421     if (!absSharedResultSet->HasBlock()) {
422         HILOG_ERROR("absSharedResultSet has no block");
423         return ERR_APPEXECFWK_FORM_COMMON_CODE;
424     }
425 
426     int32_t ret = absSharedResultSet->GoToFirstRow();
427     if (ret == NativeRdb::E_OK) {
428         do {
429             std::string resultKey;
430             ret = absSharedResultSet->GetString(FORM_KEY_INDEX, resultKey);
431             if (ret != NativeRdb::E_OK) {
432                 HILOG_ERROR("GetString key failed");
433                 break;
434             }
435 
436             std::string resultValue;
437             ret = absSharedResultSet->GetString(FORM_VALUE_INDEX, resultValue);
438             if (ret != NativeRdb::E_OK) {
439                 HILOG_ERROR("GetString value failed");
440                 break;
441             }
442 
443             datas.emplace(resultKey, resultValue);
444         } while (absSharedResultSet->GoToNextRow() == NativeRdb::E_OK);
445     }
446     absSharedResultSet->Close();
447 
448     if (ret == NativeRdb::E_OK) {
449         return ERR_OK;
450     }
451 
452     HILOG_WARN("Query all data operation failed");
453     if (CheckAndRebuildRdbStore(ret) == ERR_OK) {
454         HILOG_WARN("Check rdb corrupt,rebuild form rdb successfully");
455     }
456     return ERR_APPEXECFWK_FORM_COMMON_CODE;
457 }
458 
QueryAllKeys(const std::string & tableName,std::set<std::string> & datas)459 ErrCode FormRdbDataMgr::QueryAllKeys(const std::string &tableName, std::set<std::string> &datas)
460 {
461     HILOG_DEBUG("QueryAllKeys start");
462     if (formRdbTableCfgMap_.find(tableName) == formRdbTableCfgMap_.end()) {
463         HILOG_ERROR("Form rdb hasn't initialized this table:%{public}s", tableName.c_str());
464         return ERR_APPEXECFWK_FORM_COMMON_CODE;
465     }
466 
467     if (!IsFormRdbLoaded()) {
468         HILOG_ERROR("null FormInfoRdbStore");
469         return ERR_APPEXECFWK_FORM_COMMON_CODE;
470     }
471 
472     NativeRdb::AbsRdbPredicates absRdbPredicates(tableName);
473     std::shared_lock<std::shared_mutex> guard(rdbStoreMutex_);
474     auto absSharedResultSet = rdbStore_->Query(absRdbPredicates, std::vector<std::string>());
475     guard.unlock();
476     if (absSharedResultSet == nullptr) {
477         HILOG_ERROR("null absSharedResultSet");
478         return ERR_APPEXECFWK_FORM_COMMON_CODE;
479     }
480 
481     ScopeGuard stateGuard([absSharedResultSet] {
482         if (absSharedResultSet) {
483             absSharedResultSet->Close();
484         }
485     });
486 
487     if (!absSharedResultSet->HasBlock()) {
488         HILOG_ERROR("HasBlock failed");
489         return ERR_APPEXECFWK_FORM_COMMON_CODE;
490     }
491     int32_t ret = absSharedResultSet->GoToFirstRow();
492     if (ret == NativeRdb::E_OK) {
493         do {
494             std::string resultKey;
495             ret = absSharedResultSet->GetString(FORM_KEY_INDEX, resultKey);
496             if (ret != NativeRdb::E_OK) {
497                 HILOG_ERROR("GetString key failed");
498                 break;
499             }
500             datas.insert(resultKey);
501         } while (absSharedResultSet->GoToNextRow() == NativeRdb::E_OK);
502     }
503     absSharedResultSet->Close();
504 
505     if (ret == NativeRdb::E_OK) {
506         return ERR_OK;
507     }
508 
509     HILOG_WARN("Query all keys operation failed");
510     if (CheckAndRebuildRdbStore(ret) == ERR_OK) {
511         HILOG_WARN("Check rdb corrupt,rebuild form rdb successfully");
512     }
513     return ERR_APPEXECFWK_FORM_COMMON_CODE;
514 }
515 
QueryData(const NativeRdb::AbsRdbPredicates & absRdbPredicates)516 std::shared_ptr<NativeRdb::AbsSharedResultSet> FormRdbDataMgr::QueryData(
517     const NativeRdb::AbsRdbPredicates &absRdbPredicates)
518 {
519     HILOG_DEBUG("QueryData start");
520     if (!IsFormRdbLoaded()) {
521         HILOG_ERROR("null FormInfoRdbStore");
522         return nullptr;
523     }
524     return rdbStore_->Query(absRdbPredicates, std::vector<std::string>());
525 }
526 
QueryDataByStep(const NativeRdb::AbsRdbPredicates & absRdbPredicates)527 std::shared_ptr<NativeRdb::ResultSet> FormRdbDataMgr::QueryDataByStep(
528     const NativeRdb::AbsRdbPredicates &absRdbPredicates)
529 {
530     HILOG_DEBUG("QueryDataByStep start");
531     if (!IsFormRdbLoaded()) {
532         HILOG_ERROR("null FormInfoRdbStore");
533         return nullptr;
534     }
535 
536     std::shared_lock<std::shared_mutex> guard(rdbStoreMutex_);
537     return rdbStore_->QueryByStep(absRdbPredicates, std::vector<std::string>());
538 }
539 
QuerySql(const std::string & sql)540 std::shared_ptr<NativeRdb::AbsSharedResultSet> FormRdbDataMgr::QuerySql(const std::string &sql)
541 {
542     HILOG_DEBUG("QuerySql start");
543     if (!IsFormRdbLoaded()) {
544         HILOG_ERROR("null FormInfoRdbStore");
545         return nullptr;
546     }
547     std::shared_lock<std::shared_mutex> guard(rdbStoreMutex_);
548     return rdbStore_->QuerySql(sql, std::vector<std::string>());
549 }
550 
InsertData(const std::string & tableName,const NativeRdb::ValuesBucket & valuesBucket,int64_t & rowId)551 bool FormRdbDataMgr::InsertData(
552     const std::string &tableName, const NativeRdb::ValuesBucket &valuesBucket, int64_t &rowId)
553 {
554     HILOG_DEBUG("InsertData start");
555     if (formRdbTableCfgMap_.find(tableName) == formRdbTableCfgMap_.end()) {
556         HILOG_ERROR("Form rdb hasn't initialized this table:%{public}s", tableName.c_str());
557         return false;
558     }
559 
560     if (!IsFormRdbLoaded()) {
561         HILOG_ERROR("null FormInfoRdbStore");
562         return false;
563     }
564 
565     int32_t ret = NativeRdb::E_OK;
566     ret = rdbStore_->InsertWithConflictResolution(
567         rowId, tableName, valuesBucket, NativeRdb::ConflictResolution::ON_CONFLICT_REPLACE);
568     if (ret == NativeRdb::E_OK) {
569         if (rdbStore_->IsSlaveDiffFromMaster()) {
570             auto backupRet = rdbStore_->Backup("");
571             HILOG_WARN("rdb slave corrupt, backup from master, ret=%{public}" PRId32, backupRet);
572         }
573     } else {
574         if (CheckAndRebuildRdbStore(ret) == ERR_OK) {
575             HILOG_WARN("Check rdb corrupt,rebuild form rdb successfully");
576             ret = rdbStore_->InsertWithConflictResolution(
577                 rowId, tableName, valuesBucket, NativeRdb::ConflictResolution::ON_CONFLICT_REPLACE);
578         }
579     }
580 
581     if (ret == NativeRdb::E_OK) {
582         return true;
583     }
584 
585     HILOG_WARN("Insert operation failed, ret=%{public}" PRId32, ret);
586     return false;
587 }
588 
DeleteData(const NativeRdb::AbsRdbPredicates & absRdbPredicates)589 bool FormRdbDataMgr::DeleteData(const NativeRdb::AbsRdbPredicates &absRdbPredicates)
590 {
591     if (!IsFormRdbLoaded()) {
592         HILOG_ERROR("null FormInfoRdbStore");
593         return false;
594     }
595 
596     int32_t ret = NativeRdb::E_OK;
597     int32_t rowId = -1;
598     ret = rdbStore_->Delete(rowId, absRdbPredicates);
599 
600     if (ret == NativeRdb::E_OK) {
601         if (rdbStore_->IsSlaveDiffFromMaster()) {
602             auto backupRet = rdbStore_->Backup("");
603             HILOG_WARN("rdb slave corrupt, backup from master, ret=%{public}" PRId32, backupRet);
604         }
605     } else {
606         if (CheckAndRebuildRdbStore(ret) == ERR_OK) {
607             HILOG_WARN("Check rdb corrupt,rebuild form rdb successfully");
608             int32_t rowId = -1;
609             ret = rdbStore_->Delete(rowId, absRdbPredicates);
610         }
611     }
612 
613     if (ret == NativeRdb::E_OK) {
614         return true;
615     }
616 
617     HILOG_WARN("Delete operation failed, ret=%{public}" PRId32, ret);
618     return false;
619 }
620 
IsFormRdbLoaded()621 bool FormRdbDataMgr::IsFormRdbLoaded()
622 {
623     if (rdbStore_ != nullptr) {
624         return true;
625     }
626     std::unique_lock<std::shared_mutex> guard(rdbStoreMutex_);
627     if (rdbStore_ != nullptr) {
628         return true;
629     }
630 
631     HILOG_WARN("null Rdb, need to reload");
632     if (LoadRdbStore() != ERR_OK) {
633         HILOG_ERROR("Load rdb failed");
634         return false;
635     }
636 
637     for (auto iter = formRdbTableCfgMap_.begin(); iter != formRdbTableCfgMap_.end(); iter++) {
638         std::string createTableSql = !iter->second.createTableSql.empty() ? iter->second.createTableSql
639             : "CREATE TABLE IF NOT EXISTS " + iter->second.tableName
640             + " (KEY TEXT NOT NULL PRIMARY KEY, VALUE TEXT NOT NULL);";
641         int32_t ret = rdbStore_->ExecuteSql(createTableSql);
642         if (ret != NativeRdb::E_OK) {
643             HILOG_ERROR("Recreate form rdb table failed, ret:%{public}" PRId32 ", name is %{public}s",
644                 ret, iter->first.c_str());
645         }
646     }
647     return true;
648 }
649 
CheckAndRebuildRdbStore(int32_t rdbOperateRet)650 ErrCode FormRdbDataMgr::CheckAndRebuildRdbStore(int32_t rdbOperateRet)
651 {
652     if (rdbStore_ == nullptr) {
653         HILOG_ERROR("null FormInfoRdbStore");
654         return ERR_APPEXECFWK_FORM_COMMON_CODE;
655     }
656 
657     if (rdbOperateRet != NativeRdb::E_SQLITE_CORRUPT) {
658         HILOG_INFO("errorCode:%{public}" PRId32, rdbOperateRet);
659         return ERR_APPEXECFWK_FORM_COMMON_CODE;
660     }
661 
662     std::unique_lock<std::shared_mutex> guard(rdbStoreMutex_);
663     int64_t curTime = FormUtil::GetCurrentMillisecond();
664     if ((curTime - lastRdbBuildTime_) <= MIN_FORM_RDB_REBUILD_INTERVAL) {
665         return ERR_APPEXECFWK_FORM_RDB_REPEATED_BUILD;
666     }
667 
668     auto restoreRet = rdbStore_->Restore("");
669     if (restoreRet == NativeRdb::E_OK) {
670         HILOG_INFO("Restore rdb succeeded");
671     } else {
672         HILOG_WARN("Restore rdb failed, errorCode:%{public}" PRId32, restoreRet);
673     }
674 
675     ErrCode ret = LoadRdbStore();
676     if (ret != ERR_OK) {
677         HILOG_ERROR("Reload form rdb failed, ret:%{public}" PRId32 ".", ret);
678         return ERR_APPEXECFWK_FORM_COMMON_CODE;
679     }
680     lastRdbBuildTime_ = curTime;
681 
682     if (restoreRet != NativeRdb::E_OK) {
683         //fallback restoration if Restore() did not work
684         for (auto iter = formRdbTableCfgMap_.begin(); iter != formRdbTableCfgMap_.end(); iter++) {
685             std::string createTableSql = !iter->second.createTableSql.empty() ? iter->second.createTableSql
686                 : "CREATE TABLE IF NOT EXISTS " + iter->second.tableName
687                 + " (KEY TEXT NOT NULL PRIMARY KEY, VALUE TEXT NOT NULL);";
688             int32_t result = rdbStore_->ExecuteSql(createTableSql);
689             if (result != NativeRdb::E_OK) {
690                 HILOG_ERROR("Recreate form rdb table failed, ret:%{public}" PRId32 ", name is %{public}s",
691                     result, iter->first.c_str());
692             }
693         }
694     }
695     return ERR_OK;
696 }
697 
LoadRdbStore()698 ErrCode FormRdbDataMgr::LoadRdbStore()
699 {
700     std::string rdbPath = Constants::FORM_MANAGER_SERVICE_PATH + Constants::FORM_RDB_NAME;
701     NativeRdb::RdbStoreConfig rdbStoreConfig(
702         rdbPath,
703         NativeRdb::StorageMode::MODE_DISK,
704         false,
705         std::vector<uint8_t>(),
706         Constants::FORM_JOURNAL_MODE,
707         Constants::FORM_SYNC_MODE,
708         "",
709         NativeRdb::SecurityLevel::S1);
710     rdbStoreConfig.SetAllowRebuild(true);
711     rdbStoreConfig.SetHaMode(NativeRdb::HAMode::MAIN_REPLICA);
712     int32_t errCode = NativeRdb::E_OK;
713     RdbStoreDataCallBackFormInfoStorage rdbDataCallBack_(rdbPath);
714 
715     rdbStore_ = nullptr;
716     rdbStore_ = NativeRdb::RdbHelper::GetRdbStore(rdbStoreConfig, Constants::FORM_RDB_VERSION,
717         rdbDataCallBack_, errCode);
718     if (errCode != NativeRdb::E_OK) {
719         HILOG_ERROR("Form rdb store init fail, err code is %{public}" PRId32 "", errCode);
720         FormEventReport::SendFormFailedEvent(FormEventName::CALLEN_DB_FAILED, HiSysEventType::FAULT,
721             static_cast<int64_t>(CallDbFiledErrorType::DATABASE_RESET_CONNECT_FAILED));
722         rdbStore_ = nullptr;
723         return ERR_APPEXECFWK_FORM_COMMON_CODE;
724     }
725     return ERR_OK;
726 }
727 } // namespace AppExecFwk
728 } // namespace OHOS