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 25namespace OHOS { 26namespace Contacts { 27namespace { 28std::mutex g_mtx; 29} 30 31const std::string DataBaseDisasterRecovery::BACKUP_LINK_SYMBOL = "_"; 32const std::string DataBaseDisasterRecovery::BACKUP_SUFFIX = ".db"; 33const std::string DataBaseDisasterRecovery::DB_OK = "ok"; 34std::shared_ptr<DataBaseDisasterRecovery> DataBaseDisasterRecovery::instance_ = nullptr; 35std::map<std::string, std::shared_ptr<OHOS::NativeRdb::RdbStore>> DataBaseDisasterRecovery::redbStoreMap; 36 37std::shared_ptr<DataBaseDisasterRecovery> DataBaseDisasterRecovery::GetInstance() 38{ 39 if (instance_ == nullptr) { 40 instance_.reset(new DataBaseDisasterRecovery()); 41 } 42 return instance_; 43} 44 45DataBaseDisasterRecovery::DataBaseDisasterRecovery() 46{ 47} 48 49DataBaseDisasterRecovery::~DataBaseDisasterRecovery() 50{ 51} 52 53int 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 84int 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 102int 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 134int 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 168std::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 184int 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