• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-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 "database_disaster_recovery.h"
17 
18 #include <mutex>
19 
20 #include "calllog_database.h"
21 #include "contacts_database.h"
22 #include "file_utils.h"
23 #include "profile_database.h"
24 
25 namespace OHOS {
26 namespace Contacts {
27 namespace {
28 std::mutex g_mtx;
29 }
30 
31 const std::string DataBaseDisasterRecovery::BACKUP_LINK_SYMBOL = "_";
32 const std::string DataBaseDisasterRecovery::BACKUP_SUFFIX = ".db";
33 const std::string DataBaseDisasterRecovery::DB_OK = "ok";
34 std::shared_ptr<DataBaseDisasterRecovery> DataBaseDisasterRecovery::instance_ = nullptr;
35 std::map<std::string, std::shared_ptr<OHOS::NativeRdb::RdbStore>> DataBaseDisasterRecovery::redbStoreMap;
36 
GetInstance()37 std::shared_ptr<DataBaseDisasterRecovery> DataBaseDisasterRecovery::GetInstance()
38 {
39     if (instance_ == nullptr) {
40         instance_.reset(new DataBaseDisasterRecovery());
41     }
42     return instance_;
43 }
44 
DataBaseDisasterRecovery()45 DataBaseDisasterRecovery::DataBaseDisasterRecovery()
46 {
47 }
48 
~DataBaseDisasterRecovery()49 DataBaseDisasterRecovery::~DataBaseDisasterRecovery()
50 {
51 }
52 
SQLiteCheckDb()53 int DataBaseDisasterRecovery::SQLiteCheckDb()
54 {
55     g_mtx.lock();
56     int ret = OPERATION_ERROR;
57     HILOG_INFO("DataBaseDisasterRecovery SQLliteCheck start.");
58     redbStoreMap.clear();
59     if (redbStoreMap.empty()) {
60         HILOG_ERROR("DataBaseDisasterRecovery redbStoreMap init. nullptr");
61         std::shared_ptr<ProfileDatabase> profile = ProfileDatabase::GetInstance();
62         std::shared_ptr<ContactsDataBase> contacts = ContactsDataBase::GetInstance();
63         redbStoreMap.insert(std::make_pair(PROFILE_DATABASE_NAME, profile->store_));
64         redbStoreMap.insert(std::make_pair(CONTACT_DATABASE_NAME, contacts->contactStore_));
65     }
66     if (redbStoreMap.empty()) {
67         HILOG_ERROR("DataBaseDisasterRecovery SQLliteCheck redbStoreMap is empty");
68         g_mtx.unlock();
69         return RDB_OBJECT_EMPTY;
70     }
71     for (auto &kv : redbStoreMap) {
72         std::shared_ptr<OHOS::NativeRdb::RdbStore> store_ = kv.second;
73         ret = SQLiteCheckDb(store_, kv.first);
74         if (ret != OHOS::NativeRdb::E_OK) {
75             HILOG_ERROR("DataBaseDisasterRecovery SQLiteCheckDb ERROR.");
76             g_mtx.unlock();
77             return ret;
78         }
79     }
80     g_mtx.unlock();
81     HILOG_INFO("DataBaseDisasterRecovery SQLliteCheck end.");
82     return RDB_EXECUTE_OK;
83 }
84 
SQLiteCheckDb(std::shared_ptr<OHOS::NativeRdb::RdbStore> rdbStore,std::string dataBaseName)85 int DataBaseDisasterRecovery::SQLiteCheckDb(
86     std::shared_ptr<OHOS::NativeRdb::RdbStore> rdbStore, std::string dataBaseName)
87 {
88     // default switch
89     std::shared_ptr<OHOS::NativeRdb::RdbStore> &store_ = rdbStore;
90     if (store_ == nullptr) {
91         HILOG_ERROR("DataBaseDisasterRecovery SQLliteCheck %{public}s store_ is nullptr", dataBaseName.c_str());
92         return RDB_OBJECT_EMPTY;
93     }
94     std::string result;
95     store_->ExecuteAndGetString(result, "PRAGMA quick_check(0)");
96     HILOG_INFO("DataBaseDisasterRecovery check %{public}s result is %{public}s", dataBaseName.c_str(), result.c_str());
97     if (result == DB_OK) {
98         return RDB_EXECUTE_OK;
99     }
100     return RDB_EXECUTE_FAIL;
101 }
102 
BackDatabase()103 int DataBaseDisasterRecovery::BackDatabase()
104 {
105     // Recovery
106     HILOG_INFO("entry DataBaseDisasterRecovery");
107     FileUtils fileUtils;
108     fileUtils.Mkdir(ContactsPath::RDB_BACKUP_PATH);
109     redbStoreMap.clear();
110     if (redbStoreMap.empty()) {
111         HILOG_ERROR("DataBaseDisasterRecovery redbStoreMap init. nullptr");
112         std::shared_ptr<ProfileDatabase> profile = ProfileDatabase::GetInstance();
113         std::shared_ptr<ContactsDataBase> contacts = ContactsDataBase::GetInstance();
114         redbStoreMap.insert(std::make_pair(PROFILE_DATABASE_NAME, profile->store_));
115         redbStoreMap.insert(std::make_pair(CONTACT_DATABASE_NAME, contacts->contactStore_));
116     }
117     if (redbStoreMap.empty()) {
118         HILOG_ERROR("DataBaseDisasterRecovery SQLliteCheck redbStoreMap is empty");
119         return RDB_OBJECT_EMPTY;
120     }
121     for (auto &kv : redbStoreMap) {
122         std::shared_ptr<OHOS::NativeRdb::RdbStore> store_ = kv.second;
123         int version;
124         store_->GetVersion(version);
125         HILOG_INFO("backup version is %{public}d", version);
126         int ret = BackDatabase(kv.first);
127         HILOG_INFO("BackDatabase %{public}s status is %{public}d", kv.first.c_str(), ret);
128     }
129     return RDB_EXECUTE_OK;
130 }
131 
BackDatabase(std::string dataBaseName)132 int DataBaseDisasterRecovery::BackDatabase(std::string dataBaseName)
133 {
134     g_mtx.lock();
135     auto iter = redbStoreMap.find(dataBaseName);
136     HILOG_INFO("DataBaseDisasterRecovery BackDatabase redbStoreMap size is %{public}zu", redbStoreMap.size());
137     if (iter != redbStoreMap.end()) {
138         std::shared_ptr<OHOS::NativeRdb::RdbStore> store_ = iter->second;
139         if (store_ == nullptr) {
140             HILOG_ERROR("DataBaseDisasterRecovery BackDatabase %{public}s store_ is nullptr", dataBaseName.c_str());
141             g_mtx.unlock();
142             return RDB_OBJECT_EMPTY;
143         }
144         std::string dbPath = ContactsPath::RDB_BACKUP_PATH + dataBaseName + BACKUP_SUFFIX;
145         int64_t outRowId = 0;
146         OHOS::NativeRdb::ValuesBucket values;
147         values.PutString(DatabaseBackupColumns::BACKUP_PATH, dbPath);
148         int ret = store_->Insert(outRowId, ContactTableName::DATABASE_BACKUP_TASK, values);
149         if (ret != OHOS::NativeRdb::E_OK) {
150             HILOG_ERROR("DataBaseDisasterRecovery Insert failed, status is %{public}d.", ret);
151             g_mtx.unlock();
152             return RDB_EXECUTE_FAIL;
153         }
154         OHOS::NativeRdb::RdbHelper::DeleteRdbStore(dbPath);
155         ret = store_->Backup(dbPath, std::vector<uint8_t>());
156         if (ret != OHOS::NativeRdb::E_OK) {
157             HILOG_ERROR("DataBaseDisasterRecovery Backup failed, status is %{public}d.", ret);
158             g_mtx.unlock();
159             return RDB_EXECUTE_FAIL;
160         }
161     }
162     g_mtx.unlock();
163     return RDB_EXECUTE_OK;
164 }
165 
GetBackUpDatabase(const std::shared_ptr<OHOS::NativeRdb::RdbStore> & store_)166 std::string DataBaseDisasterRecovery::GetBackUpDatabase(const std::shared_ptr<OHOS::NativeRdb::RdbStore> &store_)
167 {
168     std::string sql = "select backup_path from ";
169     sql.append(ContactTableName::DATABASE_BACKUP_TASK).append(" order by backup_time desc limit 0,1");
170     std::unique_ptr<OHOS::NativeRdb::AbsSharedResultSet> result = store_->QuerySql(sql, std::vector<std::string>());
171     std::string currValue;
172     if (result->GoToFirstRow() == OHOS::NativeRdb::E_OK) {
173         int currValueIndex;
174         result->GetColumnIndex(DatabaseBackupColumns::BACKUP_PATH, currValueIndex);
175         result->GetString(currValueIndex, currValue);
176         result->GoToNextRow();
177     }
178     result->Close();
179     return currValue;
180 }
181 
RecoveryDatabase(std::string dataBaseName)182 int DataBaseDisasterRecovery::RecoveryDatabase(std::string dataBaseName)
183 {
184     if (dataBaseName == PROFILE_DATABASE_NAME) {
185         std::string backupPath = ContactsPath::RDB_BACKUP_PATH + dataBaseName + BACKUP_SUFFIX;
186         ProfileDatabase::DestroyInstanceAndRestore(backupPath);
187     } else if (dataBaseName == CONTACT_DATABASE_NAME) {
188         std::string backupPath = ContactsPath::RDB_BACKUP_PATH + dataBaseName + BACKUP_SUFFIX;
189         ContactsDataBase::DestroyInstanceAndRestore(backupPath);
190     }
191     return RDB_EXECUTE_OK;
192 }
193 } // namespace Contacts
194 } // namespace OHOS
195