• 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 constexpr int CONFIG_SIZE_EXCEPT_ENCRYPT = 167;  // When modifying config, this item needs to be modified
39 
Create(const RdbStoreConfig & config,bool isWrite)40 std::pair<int32_t, std::shared_ptr<Connection>> RdConnection::Create(const RdbStoreConfig &config, bool isWrite)
41 {
42     std::pair<int32_t, std::shared_ptr<Connection>> result = { E_ERROR, nullptr };
43     if (!IsUsingArkData() || config.GetStorageMode() == StorageMode::MODE_MEMORY) {
44         result.first = E_NOT_SUPPORT;
45         return result;
46     }
47     auto &[errCode, conn] = result;
48     for (size_t i = 0; i < ITERS_COUNT; i++) {
49         std::shared_ptr<RdConnection> connection = std::make_shared<RdConnection>(config, isWrite);
50         if (connection == nullptr) {
51             LOG_ERROR("SqliteConnection::Open new failed, connection is nullptr.");
52             return result;
53         }
54         errCode = connection->InnerOpen(config);
55         if (errCode == E_OK) {
56             conn = connection;
57             break;
58         }
59     }
60     return result;
61 }
62 
Repair(const RdbStoreConfig & config)63 int32_t RdConnection::Repair(const RdbStoreConfig &config)
64 {
65     std::string dbPath = "";
66     auto errCode = SqliteGlobalConfig::GetDbPath(config, dbPath);
67     if (errCode != E_OK) {
68         LOG_ERROR("Can not get db path.");
69         return errCode;
70     }
71     std::vector<uint8_t> key = config.GetEncryptKey();
72     errCode = RdUtils::RdDbRepair(dbPath.c_str(), GetConfigStr(key, config.IsEncrypt()).c_str());
73     key.assign(key.size(), 0);
74     if (errCode != E_OK) {
75         LOG_ERROR("Fail to repair db.");
76     }
77     return errCode;
78 }
79 
80 static constexpr const char *RD_POST_FIXES[] = {
81     "",
82     ".redo",
83     ".undo",
84     ".ctrl",
85     ".ctrl.dwr",
86     ".safe",
87     ".map",
88     ".corruptedflg",
89 };
90 
Delete(const RdbStoreConfig & config)91 int32_t RdConnection::Delete(const RdbStoreConfig &config)
92 {
93     auto path = config.GetPath();
94     for (auto postFix : RD_POST_FIXES) {
95         std::string shmFilePath = path + postFix;
96         if (access(shmFilePath.c_str(), F_OK) == 0) {
97             remove(shmFilePath.c_str());
98         }
99     }
100     return E_OK;
101 }
102 
RdConnection(const RdbStoreConfig & config,bool isWriter)103 RdConnection::RdConnection(const RdbStoreConfig &config, bool isWriter) : isWriter_(isWriter), config_(config)
104 {
105 }
106 
~RdConnection()107 RdConnection::~RdConnection()
108 {
109     if (dbHandle_ != nullptr) {
110         int errCode = RdUtils::RdDbClose(dbHandle_, 0);
111         if (errCode != E_OK) {
112             LOG_ERROR("~RdConnection ~RdConnection: could not close database err = %{public}d", errCode);
113         }
114         dbHandle_ = nullptr;
115     }
116 }
117 
GetConfigStr(const std::vector<uint8_t> & keys,bool isEncrypt)118 std::string RdConnection::GetConfigStr(const std::vector<uint8_t> &keys, bool isEncrypt)
119 {
120     std::string config = "{";
121     if (isEncrypt) {
122         const size_t keyBuffSize = keys.size() * 2 + 1; // 2 hex number can represent a uint8_t, 1 is for '/0'
123         config.reserve(CONFIG_SIZE_EXCEPT_ENCRYPT + keyBuffSize);
124         char keyBuff[keyBuffSize];
125         config += "\"isEncrypted\":1,";
126         config += "\"hexPassword\":\"";
127         config += RdUtils::GetEncryptKey(keys, keyBuff, keyBuffSize);
128         config += "\",";
129         std::fill(keyBuff, keyBuff + keyBuffSize, 0);
130     }
131     config += RdConnection::GRD_OPEN_CONFIG_STR;
132     config += "}";
133     return config;
134 }
135 
InnerOpen(const RdbStoreConfig & config)136 int RdConnection::InnerOpen(const RdbStoreConfig &config)
137 {
138     std::string dbPath = "";
139     auto errCode = SqliteGlobalConfig::GetDbPath(config, dbPath);
140     if (errCode != E_OK) {
141         LOG_ERROR("Can not get db path.");
142         return errCode;
143     }
144     std::vector<uint8_t> newKey = config.GetNewEncryptKey();
145     if (!newKey.empty()) {
146         newKey.assign(newKey.size(), 0);
147         errCode = ResetKey(config);
148         if (errCode != E_OK) {
149             LOG_ERROR("Can not reset key %{public}d.", errCode);
150             return errCode;
151         }
152     }
153 
154     std::vector<uint8_t> key = config.GetEncryptKey();
155     std::string configStr = GetConfigStr(key, config.IsEncrypt());
156     errCode = RdUtils::RdDbOpen(dbPath.c_str(), configStr.c_str(),
157         GRD_DB_OPEN_CREATE | GRD_DB_OPEN_IGNORE_DATA_CORRPUPTION, &dbHandle_);
158     if (errCode == E_CHANGE_UNENCRYPTED_TO_ENCRYPTED) {
159         errCode = RdUtils::RdDbRekey(dbPath.c_str(), GetConfigStr({}, false).c_str(), key);
160         if (errCode != E_OK) {
161             key.assign(key.size(), 0);
162             RdUtils::ClearAndZeroString(configStr);
163             LOG_ERROR("Can not rekey caylay db %{public}d.", errCode);
164             return errCode;
165         }
166         errCode = RdUtils::RdDbOpen(dbPath.c_str(), configStr.c_str(),
167             GRD_DB_OPEN_CREATE | GRD_DB_OPEN_IGNORE_DATA_CORRPUPTION, &dbHandle_);
168     }
169     key.assign(key.size(), 0);
170     RdUtils::ClearAndZeroString(configStr);
171     if (errCode != E_OK) {
172         LOG_ERROR("Can not open rd db %{public}d.", errCode);
173         return errCode;
174     }
175     errCode = RdUtils::RdSqlRegistryThreadPool(dbHandle_);
176     if (errCode != E_OK) {
177         LOG_ERROR("Can not registry ThreadPool rd db %{public}d.", errCode);
178         return errCode;
179     }
180     return errCode;
181 }
182 
VerifyAndRegisterHook(const RdbStoreConfig & config)183 int32_t RdConnection::VerifyAndRegisterHook(const RdbStoreConfig &config)
184 {
185     return E_NOT_SUPPORT;
186 }
187 
CreateStatement(const std::string & sql,Connection::SConn conn)188 std::pair<int32_t, RdConnection::Stmt> RdConnection::CreateStatement(const std::string &sql, Connection::SConn conn)
189 {
190     auto stmt = std::make_shared<RdStatement>();
191     stmt->conn_ = conn;
192     stmt->config_ = &config_;
193     stmt->setPragmas_["user_version"] = ([this](const int &value) -> int32_t {
194         return RdUtils::RdDbSetVersion(dbHandle_, GRD_CONFIG_USER_VERSION, value);
195     });
196     stmt->getPragmas_["user_version"] = ([this](int &version) -> int32_t {
197         return RdUtils::RdDbGetVersion(dbHandle_, GRD_CONFIG_USER_VERSION, version);
198     });
199     int32_t ret = stmt->Prepare(dbHandle_, sql);
200     if (ret != E_OK) {
201         return { ret, nullptr };
202     }
203     return { ret, stmt };
204 }
205 
CreateReplicaStatement(const std::string & sql,Connection::SConn conn)206 std::pair<int32_t, RdConnection::Stmt> RdConnection::CreateReplicaStatement([[gnu::unused]] const std::string &sql,
207     [[gnu::unused]] Connection::SConn conn)
208 {
209     return { E_NOT_SUPPORT, nullptr };
210 }
211 
CheckReplicaForRestore()212 int RdConnection::CheckReplicaForRestore()
213 {
214     return E_NOT_SUPPORT;
215 }
216 
GetDBType() const217 int32_t RdConnection::GetDBType() const
218 {
219     return DB_VECTOR;
220 }
221 
IsWriter() const222 bool RdConnection::IsWriter() const
223 {
224     return isWriter_;
225 }
226 
ResetKey(const RdbStoreConfig & config)227 int32_t RdConnection::ResetKey(const RdbStoreConfig &config)
228 {
229     if (!IsWriter()) {
230         return E_OK;
231     }
232     std::string dbPath = "";
233     int errCode = SqliteGlobalConfig::GetDbPath(config, dbPath);
234     if (errCode != E_OK) {
235         LOG_ERROR("Can not get db path.");
236         return errCode;
237     }
238     std::vector<uint8_t> key = config.GetEncryptKey();
239     std::vector<uint8_t> newKey = config.GetNewEncryptKey();
240     std::string configStr = GetConfigStr(key, config.IsEncrypt());
241     errCode = RdUtils::RdDbRekey(dbPath.c_str(), configStr.c_str(), newKey);
242     RdUtils::ClearAndZeroString(configStr);
243     key.assign(key.size(), 0);
244     newKey.assign(newKey.size(), 0);
245     if (errCode != E_OK) {
246         LOG_ERROR("ReKey failed, err = %{public}d, errno = %{public}d", errCode, errno);
247         RdbSecurityManager::GetInstance().DelKeyFile(
248             config.GetPath(), RdbSecurityManager::KeyFileType::PUB_KEY_FILE_NEW_KEY);
249         return E_OK;
250     }
251     config.ChangeEncryptKey();
252     return E_OK;
253 }
254 
Rekey(const RdbStoreConfig::CryptoParam & cryptoParam)255 int32_t RdConnection::Rekey(const RdbStoreConfig::CryptoParam &cryptoParam)
256 {
257     return E_NOT_SUPPORT;
258 }
259 
TryCheckPoint(bool timeout)260 int32_t RdConnection::TryCheckPoint(bool timeout)
261 {
262     return E_NOT_SUPPORT;
263 }
264 
LimitWalSize()265 int32_t RdConnection::LimitWalSize()
266 {
267     return E_NOT_SUPPORT;
268 }
269 
ConfigLocale(const std::string & localeStr)270 int32_t RdConnection::ConfigLocale(const std::string &localeStr)
271 {
272     return E_NOT_SUPPORT;
273 }
274 
CleanDirtyData(const std::string & table,uint64_t cursor)275 int32_t RdConnection::CleanDirtyData(const std::string &table, uint64_t cursor)
276 {
277     return E_NOT_SUPPORT;
278 }
279 
SubscribeTableChanges(const Connection::Notifier & notifier)280 int32_t RdConnection::SubscribeTableChanges(const Connection::Notifier &notifier)
281 {
282     return E_NOT_SUPPORT;
283 }
284 
GetMaxVariable() const285 int32_t RdConnection::GetMaxVariable() const
286 {
287     return MAX_VARIABLE_NUM;
288 }
289 
GetJournalMode()290 int32_t RdConnection::GetJournalMode()
291 {
292     return E_NOT_SUPPORT;
293 }
294 
ClearCache(bool isForceClear)295 int32_t RdConnection::ClearCache(bool isForceClear)
296 {
297     return E_NOT_SUPPORT;
298 }
299 
Subscribe(const std::shared_ptr<DistributedDB::StoreObserver> & observer)300 int32_t RdConnection::Subscribe(const std::shared_ptr<DistributedDB::StoreObserver> &observer)
301 {
302     return E_NOT_SUPPORT;
303 }
304 
Unsubscribe(const std::shared_ptr<DistributedDB::StoreObserver> & observer)305 int32_t RdConnection::Unsubscribe(const std::shared_ptr<DistributedDB::StoreObserver> &observer)
306 {
307     return E_NOT_SUPPORT;
308 }
309 
Backup(const std::string & databasePath,const std::vector<uint8_t> & destEncryptKey,bool isAsync,std::shared_ptr<SlaveStatus> slaveStatus,bool verifyDb)310 int32_t RdConnection::Backup(const std::string &databasePath, const std::vector<uint8_t> &destEncryptKey, bool isAsync,
311     std::shared_ptr<SlaveStatus> slaveStatus, bool verifyDb)
312 {
313     if (!destEncryptKey.empty() && !config_.IsEncrypt()) {
314         return RdUtils::RdDbBackup(dbHandle_, databasePath.c_str(), destEncryptKey);
315     }
316     if (config_.IsEncrypt()) {
317         std::vector<uint8_t> key = config_.GetEncryptKey();
318         int32_t ret = RdUtils::RdDbBackup(dbHandle_, databasePath.c_str(), key);
319         key.assign(key.size(), 0);
320         return ret;
321     }
322     return RdUtils::RdDbBackup(dbHandle_, databasePath.c_str(), {});
323 }
324 
Restore(const std::string & databasePath,const std::vector<uint8_t> & destEncryptKey,std::shared_ptr<SlaveStatus> slaveStatus)325 int32_t RdConnection::Restore(
326     const std::string &databasePath, const std::vector<uint8_t> &destEncryptKey,
327     std::shared_ptr<SlaveStatus> slaveStatus)
328 {
329     auto ret = RdUtils::RdDbClose(dbHandle_, 0);
330     if (ret != E_OK) {
331         LOG_ERROR("Close db failed");
332         return ret;
333     }
334 
335     if (destEncryptKey.empty()) {
336         std::vector<uint8_t> key = config_.GetEncryptKey();
337         ret = RdUtils::RdDbRestore(config_.GetPath().c_str(), databasePath.c_str(), key);
338         key.assign(key.size(), 0);
339     } else {
340         ret = RdUtils::RdDbRestore(config_.GetPath().c_str(), databasePath.c_str(), destEncryptKey);
341     }
342 
343     if (ret != E_OK) {
344         LOG_ERROR("Restore failed, original datapath:%{public}s, restorepath:%{public}s, errcode:%{public}d",
345             SqliteUtils::Anonymous(config_.GetPath()).c_str(),
346             SqliteUtils::Anonymous(databasePath).c_str(), ret);
347         return ret;
348     }
349 
350     ret = InnerOpen(config_);
351     if (ret != E_OK) {
352         LOG_ERROR("Reopen db failed:%{public}d", ret);
353         return ret;
354     }
355     return ret;
356 }
357 
GenerateExchangeStrategy(std::shared_ptr<SlaveStatus> status,bool isRelpay)358 ExchangeStrategy RdConnection::GenerateExchangeStrategy(std::shared_ptr<SlaveStatus> status, bool isRelpay)
359 {
360     return ExchangeStrategy::NOT_HANDLE;
361 }
362 
SetKnowledgeSchema(const DistributedRdb::RdbKnowledgeSchema & schema)363 int RdConnection::SetKnowledgeSchema([[gnu::unused]] const DistributedRdb::RdbKnowledgeSchema &schema)
364 {
365     return E_NOT_SUPPORT;
366 }
367 
CleanDirtyLog(const std::string & table,uint64_t cursor)368 int RdConnection::CleanDirtyLog([[gnu::unused]] const std::string &table, [[gnu::unused]] uint64_t cursor)
369 {
370     return E_NOT_SUPPORT;
371 }
372 
RegisterAlgo(const std::string & clstAlgoName,ClusterAlgoFunc func)373 int RdConnection::RegisterAlgo(const std::string &clstAlgoName, ClusterAlgoFunc func)
374 {
375     int errCode =
376         RdUtils::RdSqlRegistryClusterAlgo(dbHandle_, clstAlgoName.c_str(), reinterpret_cast<GRD_ClusterAlgoFunc>(func));
377     if (errCode != E_OK) {
378         LOG_ERROR("Can not registry cluster func in rd db %{public}d.", errCode);
379         return errCode;
380     }
381     return E_OK;
382 }
383 
384 } // namespace NativeRdb
385 } // namespace OHOS