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