• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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 #define LOG_TAG "RdConnection"
16 #include "rd_connection.h"
17 
18 #include <securec.h>
19 
20 #include <string>
21 
22 #include "grd_api_manager.h"
23 #include "logger.h"
24 #include "rd_statement.h"
25 #include "rdb_errno.h"
26 #include "rdb_security_manager.h"
27 #include "sqlite_global_config.h"
28 #include "sqlite_utils.h"
29 namespace OHOS {
30 namespace NativeRdb {
31 using namespace OHOS::Rdb;
32 __attribute__((used))
33 const int32_t RdConnection::regCreator_ = Connection::RegisterCreator(DB_VECTOR, RdConnection::Create);
34 __attribute__((used))
35 const int32_t RdConnection::regRepairer_ = Connection::RegisterRepairer(DB_VECTOR, RdConnection::Repair);
36 __attribute__((used))
37 const int32_t RdConnection::regDeleter_ = Connection::RegisterDeleter(DB_VECTOR, RdConnection::Delete);
38 
Create(const RdbStoreConfig & config,bool isWrite)39 std::pair<int32_t, std::shared_ptr<Connection>> RdConnection::Create(const RdbStoreConfig &config, bool isWrite)
40 {
41     std::pair<int32_t, std::shared_ptr<Connection>> result = { E_ERROR, nullptr };
42     if (!IsUsingArkData() || config.GetStorageMode() == StorageMode::MODE_MEMORY) {
43         result.first = E_NOT_SUPPORT;
44         return result;
45     }
46     auto &[errCode, conn] = result;
47     for (size_t i = 0; i < ITERS_COUNT; i++) {
48         std::shared_ptr<RdConnection> connection = std::make_shared<RdConnection>(config, isWrite);
49         if (connection == nullptr) {
50             LOG_ERROR("SqliteConnection::Open new failed, connection is nullptr.");
51             return result;
52         }
53         errCode = connection->InnerOpen(config);
54         if (errCode == E_OK) {
55             conn = connection;
56             CheckConfig(connection, config);
57             break;
58         }
59     }
60     return result;
61 }
62 
CheckConfig(std::shared_ptr<Connection> conn,const RdbStoreConfig & config)63 void RdConnection::CheckConfig(std::shared_ptr<Connection> conn, const RdbStoreConfig &config)
64 {
65     if (config.GetNcandidates() != NCANDIDATES_DEFAULT_NUM) {
66         ExecuteSet(conn, "diskann_probe_ncandidates", config.GetNcandidates());
67     }
68 }
69 
ExecuteSet(std::shared_ptr<Connection> conn,const std::string & paramName,int num)70 void RdConnection::ExecuteSet(std::shared_ptr<Connection> conn, const std::string &paramName, int num)
71 {
72     std::string sql = "SET " + paramName + " = " + std::to_string(num);
73     auto [errCode, stmt] = conn->CreateStatement(sql, conn);
74     if (errCode != E_OK || stmt == nullptr) {
75         LOG_ERROR("Create statement failed, paramName: %{public}s, errCode: %{public}d",
76             paramName.c_str(), errCode);
77         return;
78     }
79     stmt->Step();
80     stmt->Finalize();
81 }
82 
Repair(const RdbStoreConfig & config)83 int32_t RdConnection::Repair(const RdbStoreConfig &config)
84 {
85     std::string dbPath = "";
86     auto errCode = SqliteGlobalConfig::GetDbPath(config, dbPath);
87     if (errCode != E_OK) {
88         LOG_ERROR("Can not get db path.");
89         return errCode;
90     }
91     std::vector<uint8_t> key = config.GetEncryptKey();
92     errCode = RdUtils::RdDbRepair(dbPath.c_str(), GetConfigStr(key, config.IsEncrypt()).c_str());
93     key.assign(key.size(), 0);
94     if (errCode != E_OK) {
95         LOG_ERROR("Fail to repair db.");
96     }
97     return errCode;
98 }
99 
100 static constexpr const char *RD_POST_FIXES[] = {
101     "",
102     ".redo",
103     ".undo",
104     ".ctrl",
105     ".ctrl.dwr",
106     ".safe",
107     ".map",
108     ".corruptedflg",
109 };
110 
Delete(const RdbStoreConfig & config)111 int32_t RdConnection::Delete(const RdbStoreConfig &config)
112 {
113     auto path = config.GetPath();
114     for (auto postFix : RD_POST_FIXES) {
115         std::string shmFilePath = path + postFix;
116         if (access(shmFilePath.c_str(), F_OK) == 0) {
117             remove(shmFilePath.c_str());
118         }
119     }
120     return E_OK;
121 }
122 
RdConnection(const RdbStoreConfig & config,bool isWriter)123 RdConnection::RdConnection(const RdbStoreConfig &config, bool isWriter) : isWriter_(isWriter), config_(config)
124 {
125 }
126 
~RdConnection()127 RdConnection::~RdConnection()
128 {
129     if (dbHandle_ != nullptr) {
130         int errCode = RdUtils::RdDbClose(dbHandle_, 0);
131         if (errCode != E_OK) {
132             LOG_ERROR("~RdConnection ~RdConnection: could not close database err = %{public}d", errCode);
133         }
134         dbHandle_ = nullptr;
135     }
136 }
137 
GetConfigStr(const std::vector<uint8_t> & keys,bool isEncrypt)138 std::string RdConnection::GetConfigStr(const std::vector<uint8_t> &keys, bool isEncrypt)
139 {
140     std::string config = "{";
141     if (isEncrypt) {
142         const size_t keyBuffSize = keys.size() * 2 + 1; // 2 hex number can represent a uint8_t, 1 is for '/0'
143         char keyBuff[keyBuffSize];
144         config += "\"isEncrypted\":1,";
145         config += "\"hexPassword\":\"";
146         config += RdUtils::GetEncryptKey(keys, keyBuff, keyBuffSize);
147         config += "\",";
148         (void)memset_s(keyBuff, keyBuffSize, 0, keyBuffSize);
149     }
150     config += RdConnection::GRD_OPEN_CONFIG_STR;
151     config += "}";
152     return config;
153 }
154 
InnerOpen(const RdbStoreConfig & config)155 int RdConnection::InnerOpen(const RdbStoreConfig &config)
156 {
157     std::string dbPath = "";
158     auto errCode = SqliteGlobalConfig::GetDbPath(config, dbPath);
159     if (errCode != E_OK) {
160         LOG_ERROR("Can not get db path.");
161         return errCode;
162     }
163     std::vector<uint8_t> newKey = config.GetNewEncryptKey();
164     if (!newKey.empty()) {
165         newKey.assign(newKey.size(), 0);
166         errCode = ReSetKey(config);
167         if (errCode != E_OK) {
168             LOG_ERROR("Can not reset key %{public}d.", errCode);
169             return errCode;
170         }
171     }
172 
173     std::vector<uint8_t> key = config.GetEncryptKey();
174     std::string configStr = GetConfigStr(key, config.IsEncrypt());
175     errCode = RdUtils::RdDbOpen(dbPath.c_str(), configStr.c_str(),
176         GRD_DB_OPEN_CREATE | GRD_DB_OPEN_IGNORE_DATA_CORRPUPTION, &dbHandle_);
177     if (errCode == E_CHANGE_UNENCRYPTED_TO_ENCRYPTED) {
178         errCode = RdUtils::RdDbRekey(dbPath.c_str(), GetConfigStr({}, false).c_str(), key);
179         if (errCode != E_OK) {
180             key.assign(key.size(), 0);
181             RdUtils::ClearAndZeroString(configStr);
182             LOG_ERROR("Can not rekey caylay db %{public}d.", errCode);
183             return errCode;
184         }
185         errCode = RdUtils::RdDbOpen(dbPath.c_str(), configStr.c_str(),
186             GRD_DB_OPEN_CREATE | GRD_DB_OPEN_IGNORE_DATA_CORRPUPTION, &dbHandle_);
187     }
188     key.assign(key.size(), 0);
189     RdUtils::ClearAndZeroString(configStr);
190     if (errCode != E_OK) {
191         LOG_ERROR("Can not open rd db %{public}d.", errCode);
192         return errCode;
193     }
194     errCode = RdUtils::RdSqlRegistryThreadPool(dbHandle_);
195     if (errCode != E_OK) {
196         LOG_ERROR("Can not registry ThreadPool rd db %{public}d.", errCode);
197         return errCode;
198     }
199     return errCode;
200 }
201 
VerifyAndRegisterHook(const RdbStoreConfig & config)202 int32_t RdConnection::VerifyAndRegisterHook(const RdbStoreConfig &config)
203 {
204     return E_NOT_SUPPORT;
205 }
206 
CreateStatement(const std::string & sql,Connection::SConn conn)207 std::pair<int32_t, RdConnection::Stmt> RdConnection::CreateStatement(const std::string &sql, Connection::SConn conn)
208 {
209     auto stmt = std::make_shared<RdStatement>();
210     stmt->conn_ = conn;
211     stmt->config_ = &config_;
212     stmt->setPragmas_["user_version"] = ([this](const int &value) -> int32_t {
213         return RdUtils::RdDbSetVersion(dbHandle_, GRD_CONFIG_USER_VERSION, value);
214     });
215     stmt->getPragmas_["user_version"] = ([this](int &version) -> int32_t {
216         return RdUtils::RdDbGetVersion(dbHandle_, GRD_CONFIG_USER_VERSION, version);
217     });
218     int32_t ret = stmt->Prepare(dbHandle_, sql);
219     if (ret != E_OK) {
220         return { ret, nullptr };
221     }
222     return { ret, stmt };
223 }
224 
GetDBType() const225 int32_t RdConnection::GetDBType() const
226 {
227     return DB_VECTOR;
228 }
229 
IsWriter() const230 bool RdConnection::IsWriter() const
231 {
232     return isWriter_;
233 }
234 
ReSetKey(const RdbStoreConfig & config)235 int32_t RdConnection::ReSetKey(const RdbStoreConfig &config)
236 {
237     if (!IsWriter()) {
238         return E_OK;
239     }
240     std::string dbPath = "";
241     int errCode = SqliteGlobalConfig::GetDbPath(config, dbPath);
242     if (errCode != E_OK) {
243         LOG_ERROR("Can not get db path.");
244         return errCode;
245     }
246     std::vector<uint8_t> key = config.GetEncryptKey();
247     std::vector<uint8_t> newKey = config.GetNewEncryptKey();
248     std::string configStr = GetConfigStr(key, config.IsEncrypt());
249     errCode = RdUtils::RdDbRekey(dbPath.c_str(), configStr.c_str(), newKey);
250     RdUtils::ClearAndZeroString(configStr);
251     key.assign(key.size(), 0);
252     newKey.assign(newKey.size(), 0);
253     if (errCode != E_OK) {
254         LOG_ERROR("ReKey failed, err = %{public}d, errno = %{public}d", errCode, errno);
255         RdbSecurityManager::GetInstance().DelKeyFile(
256             config.GetPath(), RdbSecurityManager::KeyFileType::PUB_KEY_FILE_NEW_KEY);
257         return E_OK;
258     }
259     config.ChangeEncryptKey();
260     return E_OK;
261 }
262 
TryCheckPoint(bool timeout)263 int32_t RdConnection::TryCheckPoint(bool timeout)
264 {
265     return E_NOT_SUPPORT;
266 }
267 
LimitWalSize()268 int32_t RdConnection::LimitWalSize()
269 {
270     return E_NOT_SUPPORT;
271 }
272 
ConfigLocale(const std::string & localeStr)273 int32_t RdConnection::ConfigLocale(const std::string &localeStr)
274 {
275     return E_NOT_SUPPORT;
276 }
277 
CleanDirtyData(const std::string & table,uint64_t cursor)278 int32_t RdConnection::CleanDirtyData(const std::string &table, uint64_t cursor)
279 {
280     return E_NOT_SUPPORT;
281 }
282 
SubscribeTableChanges(const Connection::Notifier & notifier)283 int32_t RdConnection::SubscribeTableChanges(const Connection::Notifier &notifier)
284 {
285     return E_NOT_SUPPORT;
286 }
287 
GetMaxVariable() const288 int32_t RdConnection::GetMaxVariable() const
289 {
290     return MAX_VARIABLE_NUM;
291 }
292 
GetJournalMode()293 int32_t RdConnection::GetJournalMode()
294 {
295     return E_NOT_SUPPORT;
296 }
297 
ClearCache()298 int32_t RdConnection::ClearCache()
299 {
300     return E_NOT_SUPPORT;
301 }
302 
Subscribe(const std::shared_ptr<DistributedDB::StoreObserver> & observer)303 int32_t RdConnection::Subscribe(const std::shared_ptr<DistributedDB::StoreObserver> &observer)
304 {
305     return E_NOT_SUPPORT;
306 }
307 
Unsubscribe(const std::shared_ptr<DistributedDB::StoreObserver> & observer)308 int32_t RdConnection::Unsubscribe(const std::shared_ptr<DistributedDB::StoreObserver> &observer)
309 {
310     return E_NOT_SUPPORT;
311 }
312 
Backup(const std::string & databasePath,const std::vector<uint8_t> & destEncryptKey,bool isAsync,SlaveStatus & slaveStatus)313 int32_t RdConnection::Backup(const std::string &databasePath, const std::vector<uint8_t> &destEncryptKey, bool isAsync,
314     SlaveStatus &slaveStatus)
315 {
316     if (!destEncryptKey.empty() && !config_.IsEncrypt()) {
317         return RdUtils::RdDbBackup(dbHandle_, databasePath.c_str(), destEncryptKey);
318     }
319     if (config_.IsEncrypt()) {
320         std::vector<uint8_t> key = config_.GetEncryptKey();
321         int32_t ret = RdUtils::RdDbBackup(dbHandle_, databasePath.c_str(), key);
322         key.assign(key.size(), 0);
323         return ret;
324     }
325     return RdUtils::RdDbBackup(dbHandle_, databasePath.c_str(), {});
326 }
327 
Restore(const std::string & databasePath,const std::vector<uint8_t> & destEncryptKey,SlaveStatus & slaveStatus)328 int32_t RdConnection::Restore(
329     const std::string &databasePath, const std::vector<uint8_t> &destEncryptKey, SlaveStatus &slaveStatus)
330 {
331     auto ret = RdUtils::RdDbClose(dbHandle_, 0);
332     if (ret != E_OK) {
333         LOG_ERROR("Close db failed");
334         return ret;
335     }
336 
337     if (destEncryptKey.empty()) {
338         std::vector<uint8_t> key = config_.GetEncryptKey();
339         ret = RdUtils::RdDbRestore(config_.GetPath().c_str(), databasePath.c_str(), key);
340         key.assign(key.size(), 0);
341     } else {
342         ret = RdUtils::RdDbRestore(config_.GetPath().c_str(), databasePath.c_str(), destEncryptKey);
343     }
344 
345     if (ret != E_OK) {
346         LOG_ERROR("Restore failed, original datapath:%{public}s, restorepath:%{public}s, errcode:%{public}d",
347             config_.GetPath().c_str(), databasePath.c_str(), ret);
348         return ret;
349     }
350 
351     ret = InnerOpen(config_);
352     if (ret != E_OK) {
353         LOG_ERROR("Reopen db failed:%{public}d", ret);
354         return ret;
355     }
356     return ret;
357 }
358 
GenerateExchangeStrategy(const SlaveStatus & status)359 ExchangeStrategy RdConnection::GenerateExchangeStrategy(const SlaveStatus &status)
360 {
361     return ExchangeStrategy::NOT_HANDLE;
362 }
363 } // namespace NativeRdb
364 } // namespace OHOS