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 HILOG_INFO("DataBaseDisasterRecovery SQLliteCheck start.");
57 redbStoreMap.clear();
58 if (redbStoreMap.empty()) {
59 HILOG_ERROR("DataBaseDisasterRecovery redbStoreMap init. nullptr!");
60 std::shared_ptr<ProfileDatabase> profile = ProfileDatabase::GetInstance();
61 std::shared_ptr<ContactsDataBase> contacts = ContactsDataBase::GetInstance();
62 redbStoreMap.insert(std::make_pair(PROFILE_DATABASE_NAME, profile->store_));
63 redbStoreMap.insert(std::make_pair(CONTACT_DATABASE_NAME, contacts->contactStore_));
64 }
65 if (redbStoreMap.empty()) {
66 HILOG_ERROR("DataBaseDisasterRecovery SQLliteCheck redbStoreMap is empty!");
67 g_mtx.unlock();
68 return RDB_OBJECT_EMPTY;
69 }
70 for (auto &kv : redbStoreMap) {
71 std::shared_ptr<OHOS::NativeRdb::RdbStore> store_ = kv.second;
72 int ret = SQLiteCheckDb(store_, kv.first);
73 if (ret != OHOS::NativeRdb::E_OK) {
74 HILOG_ERROR("DataBaseDisasterRecovery SQLiteCheckDb ERROR.");
75 g_mtx.unlock();
76 return ret;
77 }
78 }
79 g_mtx.unlock();
80 HILOG_INFO("DataBaseDisasterRecovery SQLliteCheck end.");
81 return RDB_EXECUTE_OK;
82 }
83
SQLiteCheckDb(std::shared_ptr<OHOS::NativeRdb::RdbStore> rdbStore,std::string dataBaseName)84 int DataBaseDisasterRecovery::SQLiteCheckDb(
85 std::shared_ptr<OHOS::NativeRdb::RdbStore> rdbStore, std::string dataBaseName)
86 {
87 // default switch
88 std::shared_ptr<OHOS::NativeRdb::RdbStore> &store_ = rdbStore;
89 if (store_ == nullptr) {
90 HILOG_ERROR("DataBaseDisasterRecovery SQLliteCheck %{public}s store_ is nullptr", dataBaseName.c_str());
91 return RDB_OBJECT_EMPTY;
92 }
93 std::string result;
94 store_->ExecuteAndGetString(result, "PRAGMA quick_check(0)");
95 HILOG_INFO("DataBaseDisasterRecovery check %{public}s result is %{public}s", dataBaseName.c_str(), result.c_str());
96 if (result == DB_OK) {
97 return RDB_EXECUTE_OK;
98 }
99 return RDB_EXECUTE_FAIL;
100 }
101
BackDatabase()102 int DataBaseDisasterRecovery::BackDatabase()
103 {
104 // Recovery
105 g_mtx.lock();
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 g_mtx.unlock();
120 return RDB_OBJECT_EMPTY;
121 }
122 for (auto &kv : redbStoreMap) {
123 std::shared_ptr<OHOS::NativeRdb::RdbStore> store_ = kv.second;
124 int version;
125 store_->GetVersion(version);
126 HILOG_INFO("backup version is %{public}d", version);
127 int ret = BackDatabase(kv.first);
128 HILOG_INFO("BackDatabase %{public}s status is %{public}d", kv.first.c_str(), ret);
129 }
130 g_mtx.unlock();
131 return RDB_EXECUTE_OK;
132 }
133
BackDatabase(std::string dataBaseName)134 int DataBaseDisasterRecovery::BackDatabase(std::string dataBaseName)
135 {
136 g_mtx.lock();
137 auto iter = redbStoreMap.find(dataBaseName);
138 HILOG_INFO("DataBaseDisasterRecovery BackDatabase redbStoreMap size is %{public}zu", redbStoreMap.size());
139 if (iter != redbStoreMap.end()) {
140 std::shared_ptr<OHOS::NativeRdb::RdbStore> store_ = iter->second;
141 if (store_ == nullptr) {
142 HILOG_ERROR("DataBaseDisasterRecovery BackDatabase %{public}s store_ is nullptr", dataBaseName.c_str());
143 g_mtx.unlock();
144 return RDB_OBJECT_EMPTY;
145 }
146 std::string dbPath = ContactsPath::RDB_BACKUP_PATH + dataBaseName + BACKUP_SUFFIX;
147 int64_t outRowId = 0;
148 OHOS::NativeRdb::ValuesBucket values;
149 values.PutString(DatabaseBackupColumns::BACKUP_PATH, dbPath);
150 int ret = store_->Insert(outRowId, ContactTableName::DATABASE_BACKUP_TASK, values);
151 if (ret != OHOS::NativeRdb::E_OK) {
152 HILOG_ERROR("DataBaseDisasterRecovery Insert failed, status is %{public}d.", ret);
153 g_mtx.unlock();
154 return RDB_EXECUTE_FAIL;
155 }
156 OHOS::NativeRdb::RdbHelper::DeleteRdbStore(dbPath);
157 ret = store_->Backup(dbPath, std::vector<uint8_t>());
158 if (ret != OHOS::NativeRdb::E_OK) {
159 HILOG_ERROR("DataBaseDisasterRecovery Backup failed, status is %{public}d.", ret);
160 g_mtx.unlock();
161 return RDB_EXECUTE_FAIL;
162 }
163 }
164 g_mtx.unlock();
165 return RDB_EXECUTE_OK;
166 }
167
GetBackUpDatabase(const std::shared_ptr<OHOS::NativeRdb::RdbStore> & store_)168 std::string DataBaseDisasterRecovery::GetBackUpDatabase(const std::shared_ptr<OHOS::NativeRdb::RdbStore> &store_)
169 {
170 std::string sql = "select backup_path from ";
171 sql.append(ContactTableName::DATABASE_BACKUP_TASK).append(" order by backup_time desc limit 0,1");
172 auto result = store_->QuerySql(sql, std::vector<std::string>());
173 std::string currValue;
174 if (result->GoToFirstRow() == OHOS::NativeRdb::E_OK) {
175 int currValueIndex;
176 result->GetColumnIndex(DatabaseBackupColumns::BACKUP_PATH, currValueIndex);
177 result->GetString(currValueIndex, currValue);
178 result->GoToNextRow();
179 }
180 result->Close();
181 return currValue;
182 }
183
RecoveryDatabase(std::string dataBaseName)184 int DataBaseDisasterRecovery::RecoveryDatabase(std::string dataBaseName)
185 {
186 if (dataBaseName == PROFILE_DATABASE_NAME) {
187 std::string backupPath = ContactsPath::RDB_BACKUP_PATH + dataBaseName + BACKUP_SUFFIX;
188 ProfileDatabase::DestroyInstanceAndRestore(backupPath);
189 } else if (dataBaseName == CONTACT_DATABASE_NAME) {
190 std::string backupPath = ContactsPath::RDB_BACKUP_PATH + dataBaseName + BACKUP_SUFFIX;
191 ContactsDataBase::DestroyInstanceAndRestore(backupPath);
192 }
193 return RDB_EXECUTE_OK;
194 }
195 } // namespace Contacts
196 } // namespace OHOS
197