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