1 /*
2  * Copyright (c) 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 #define LOG_TAG "SqliteConnection"
17 #include "sqlite_connection.h"
18 
19 #include <cerrno>
20 #include <memory>
21 #include <sqlite3sym.h>
22 #include <sstream>
23 #include <string>
24 #include <sys/stat.h>
25 
26 #include "sqlite3.h"
27 #include "value_object.h"
28 
29 #ifdef RDB_SUPPORT_ICU
30 #include <unicode/ucol.h>
31 #endif
32 
33 #include <unistd.h>
34 
35 #include "logger.h"
36 #include "raw_data_parser.h"
37 #include "rdb_errno.h"
38 #include "rdb_security_manager.h"
39 #include "rdb_sql_statistic.h"
40 #include "rdb_store_config.h"
41 #include "relational_store_client.h"
42 #include "sqlite_errno.h"
43 #include "sqlite_global_config.h"
44 #include "sqlite_utils.h"
45 #include "rdb_fault_hiview_reporter.h"
46 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM)
47 #include "relational/relational_store_sqlite_ext.h"
48 #include "rdb_manager_impl.h"
49 #endif
50 #include "task_executor.h"
51 
52 namespace OHOS {
53 namespace NativeRdb {
54 using namespace OHOS::Rdb;
55 using namespace std::chrono;
56 using RdbKeyFile = RdbSecurityManager::KeyFileType;
57 using Reportor = RdbFaultHiViewReporter;
58 constexpr const char *INTEGRITIES[] = {nullptr, "PRAGMA quick_check", "PRAGMA integrity_check"};
59 constexpr SqliteConnection::Suffix SqliteConnection::FILE_SUFFIXES[];
60 constexpr const char *SqliteConnection::MERGE_ASSETS_FUNC;
61 constexpr const char *SqliteConnection::MERGE_ASSET_FUNC;
62 constexpr int SqliteConnection::DEFAULT_BUSY_TIMEOUT_MS;
63 constexpr int SqliteConnection::BACKUP_PAGES_PRE_STEP; // 1024 * 4 * 12800 == 50m
64 constexpr int SqliteConnection::BACKUP_PRE_WAIT_TIME;
65 constexpr ssize_t SqliteConnection::SLAVE_WAL_SIZE_LIMIT;
66 constexpr uint32_t SqliteConnection::NO_ITER;
67 constexpr uint32_t SqliteConnection::WAL_INDEX;
68 __attribute__((used))
69 const int32_t SqliteConnection::regCreator_ = Connection::RegisterCreator(DB_SQLITE, SqliteConnection::Create);
70 __attribute__((used))
71 const int32_t SqliteConnection::regRepairer_ = Connection::RegisterRepairer(DB_SQLITE, SqliteConnection::Repair);
72 __attribute__((used))
73 const int32_t SqliteConnection::regDeleter_ = Connection::RegisterDeleter(DB_SQLITE, SqliteConnection::Delete);
74 __attribute__((used))
75 const int32_t SqliteConnection::regCollector_ = Connection::RegisterCollector(DB_SQLITE, SqliteConnection::Collect);
76 
Create(const RdbStoreConfig & config,bool isWrite)77 std::pair<int32_t, std::shared_ptr<Connection>> SqliteConnection::Create(const RdbStoreConfig &config, bool isWrite)
78 {
79     std::pair<int32_t, std::shared_ptr<Connection>> result = { E_ERROR, nullptr };
80     auto &[errCode, conn] = result;
81     std::tie(errCode, conn) = InnerCreate(config, isWrite);
82     return result;
83 }
84 
Delete(const RdbStoreConfig & config)85 int32_t SqliteConnection::Delete(const RdbStoreConfig &config)
86 {
87     auto path = config.GetPath();
88     for (auto &suffix : FILE_SUFFIXES) {
89         SqliteUtils::DeleteFile(path + suffix.suffix_);
90     }
91     return E_OK;
92 }
93 
Collect(const RdbStoreConfig & config)94 std::map<std::string, Connection::Info> SqliteConnection::Collect(const RdbStoreConfig &config)
95 {
96     std::map<std::string, Connection::Info> collection;
97     std::string path;
98     Info info;
99     SqliteGlobalConfig::GetDbPath(config, path);
100     for (auto &suffix : FILE_SUFFIXES) {
101         if (suffix.debug_ == nullptr) {
102             continue;
103         }
104         auto file = path + suffix.suffix_;
105         struct stat fileStat;
106         if (stat(file.c_str(), &fileStat) != 0) {
107             continue;
108         }
109         info.inode_ = fileStat.st_ino;
110         info.oldInode_ = 0;
111         info.atime_.sec_ = fileStat.st_atime;
112         info.mtime_.sec_ = fileStat.st_mtime;
113         info.ctime_.sec_ = fileStat.st_ctime;
114 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM)
115         info.atime_.nsec_ = fileStat.st_atim.tv_nsec;
116         info.mtime_.nsec_ = fileStat.st_mtim.tv_nsec;
117         info.ctime_.nsec_ = fileStat.st_ctim.tv_nsec;
118 #endif
119         info.size_ = fileStat.st_size;
120         info.dev_ = fileStat.st_dev;
121         info.mode_ = fileStat.st_mode;
122         info.uid_ = fileStat.st_uid;
123         info.gid_ = fileStat.st_gid;
124         collection.insert(std::pair{ suffix.debug_, info });
125     }
126     return collection;
127 }
128 
SqliteConnection(const RdbStoreConfig & config,bool isWriteConnection)129 SqliteConnection::SqliteConnection(const RdbStoreConfig &config, bool isWriteConnection)
130     : dbHandle_(nullptr), isWriter_(isWriteConnection), isReadOnly_(false), maxVariableNumber_(0), filePath(""),
131       config_(config)
132 {
133     backupId_ = TaskExecutor::INVALID_TASK_ID;
134 }
135 
CreateSlaveConnection(const RdbStoreConfig & config,bool checkSlaveExist)136 int SqliteConnection::CreateSlaveConnection(const RdbStoreConfig &config, bool checkSlaveExist)
137 {
138     if (config.GetHaMode() != HAMode::MAIN_REPLICA && config.GetHaMode() != HAMode::MANUAL_TRIGGER) {
139         return E_OK;
140     }
141     std::map<std::string, DebugInfo> bugInfo = Connection::Collect(config);
142     bool isSlaveExist = access(config.GetPath().c_str(), F_OK) == 0;
143     bool isSlaveLockExist = SqliteUtils::TryAccessSlaveLock(config_.GetPath(), false, false);
144     bool hasFailure = SqliteUtils::TryAccessSlaveLock(config_.GetPath(), false, false, true);
145     bool walOverLimit = bugInfo.find(FILE_SUFFIXES[WAL_INDEX].debug_) != bugInfo.end() &&
146         bugInfo[FILE_SUFFIXES[WAL_INDEX].debug_].size_ > SLAVE_WAL_SIZE_LIMIT;
147     LOG_INFO("slave cfg:[%{public}d,%{public}d,%{public}d,%{public}d,%{public}d,%{public}d,%{public}d]%{public}s "
148              "%{public}s,[%{public}d,%{public}d,%{public}d,%{public}d]",
149         config.GetDBType(), config.GetHaMode(), config.IsEncrypt(), config.GetArea(), config.GetSecurityLevel(),
150         config.GetRoleType(), config.IsReadOnly(),
151         Reportor::FormatBrief(bugInfo, SqliteUtils::Anonymous(config.GetName())).c_str(),
152         Reportor::FormatBrief(Connection::Collect(config_), "master").c_str(), isSlaveExist, isSlaveLockExist,
153         hasFailure, walOverLimit);
154     if (config.GetHaMode() == HAMode::MANUAL_TRIGGER &&
155         (checkSlaveExist && (!isSlaveExist || isSlaveLockExist || hasFailure || walOverLimit))) {
156         if (walOverLimit) {
157             SqliteUtils::TryAccessSlaveLock(config_.GetPath(), false, true, true);
158         }
159         return E_OK;
160     }
161 
162     std::shared_ptr<SqliteConnection> connection = std::make_shared<SqliteConnection>(config, true);
163     int errCode = connection->InnerOpen(config);
164     if (errCode != E_OK) {
165         SqliteUtils::TryAccessSlaveLock(config_.GetPath(), false, true, true);
166         if (errCode == E_SQLITE_CORRUPT) {
167             LOG_WARN("slave corrupt, rebuild:%{public}s", SqliteUtils::Anonymous(config.GetPath()).c_str());
168             (void)Delete(config);
169             errCode = connection->InnerOpen(config);
170             if (errCode != E_OK) {
171                 LOG_ERROR("reopen slave failed:%{public}d", errCode);
172                 return errCode;
173             }
174         } else {
175             LOG_WARN("open slave failed:%{public}d, %{public}s", errCode,
176                 SqliteUtils::Anonymous(config.GetPath()).c_str());
177             return errCode;
178         }
179     }
180     slaveConnection_ = connection;
181     return errCode;
182 }
183 
GetSlaveRdbStoreConfig(const RdbStoreConfig & rdbConfig)184 RdbStoreConfig SqliteConnection::GetSlaveRdbStoreConfig(const RdbStoreConfig &rdbConfig)
185 {
186     RdbStoreConfig rdbStoreConfig(SqliteUtils::GetSlavePath(rdbConfig.GetPath()));
187     rdbStoreConfig.SetEncryptStatus(rdbConfig.IsEncrypt());
188     rdbStoreConfig.SetSearchable(rdbConfig.IsSearchable());
189     rdbStoreConfig.SetIsVector(rdbConfig.IsVector());
190     rdbStoreConfig.SetAutoClean(rdbConfig.GetAutoClean());
191     rdbStoreConfig.SetSecurityLevel(rdbConfig.GetSecurityLevel());
192     rdbStoreConfig.SetDataGroupId(rdbConfig.GetDataGroupId());
193     rdbStoreConfig.SetName(SqliteUtils::GetSlavePath(rdbConfig.GetName()));
194     rdbStoreConfig.SetCustomDir(rdbConfig.GetCustomDir());
195     rdbStoreConfig.SetAllowRebuild(rdbConfig.GetAllowRebuild());
196     rdbStoreConfig.SetReadOnly(rdbConfig.IsReadOnly());
197     rdbStoreConfig.SetAutoCheck(rdbConfig.IsAutoCheck());
198     rdbStoreConfig.SetCreateNecessary(rdbConfig.IsCreateNecessary());
199     rdbStoreConfig.SetJournalSize(rdbConfig.GetJournalSize());
200     rdbStoreConfig.SetPageSize(rdbConfig.GetPageSize());
201     rdbStoreConfig.SetReadConSize(rdbConfig.GetReadConSize());
202     rdbStoreConfig.SetReadTime(rdbConfig.GetReadTime());
203     rdbStoreConfig.SetDBType(rdbConfig.GetDBType());
204     rdbStoreConfig.SetVisitorDir(rdbConfig.GetVisitorDir());
205     rdbStoreConfig.SetScalarFunctions(rdbConfig.GetScalarFunctions());
206     rdbStoreConfig.SetJournalMode(rdbConfig.GetJournalMode());
207 
208     rdbStoreConfig.SetModuleName(rdbConfig.GetModuleName());
209     rdbStoreConfig.SetPluginLibs(rdbConfig.GetPluginLibs());
210     rdbStoreConfig.SetHaMode(rdbConfig.GetHaMode());
211 
212     rdbStoreConfig.SetCryptoParam(rdbConfig.GetCryptoParam());
213     return rdbStoreConfig;
214 }
215 
InnerOpen(const RdbStoreConfig & config)216 int SqliteConnection::InnerOpen(const RdbStoreConfig &config)
217 {
218     std::string dbPath;
219     auto errCode = SqliteGlobalConfig::GetDbPath(config, dbPath);
220     if (errCode != E_OK) {
221         return errCode;
222     }
223 
224 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM)
225     bool isDbFileExist = access(dbPath.c_str(), F_OK) == 0;
226     if (!isDbFileExist && (!config.IsCreateNecessary())) {
227         LOG_ERROR("db not exist errno is %{public}d", errno);
228         return E_DB_NOT_EXIST;
229     }
230 #endif
231     isReadOnly_ = !isWriter_ || config.IsReadOnly();
232     int openFileFlags = config.IsReadOnly() ? (SQLITE_OPEN_READONLY | SQLITE_OPEN_FULLMUTEX)
233                                     : (SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX);
234     errCode = OpenDatabase(dbPath, openFileFlags);
235     if (errCode != E_OK) {
236         return errCode;
237     }
238 
239     maxVariableNumber_ = sqlite3_limit(dbHandle_, SQLITE_LIMIT_VARIABLE_NUMBER, -1);
240     errCode = Configure(config, dbPath);
241     isConfigured_ = true;
242     if (errCode != E_OK) {
243         return errCode;
244     }
245 
246     if (isWriter_) {
247         ValueObject checkResult{"ok"};
248         auto index = static_cast<uint32_t>(config.GetIntegrityCheck());
249         if (index < static_cast<uint32_t>(sizeof(INTEGRITIES) / sizeof(INTEGRITIES[0]))) {
250             auto sql = INTEGRITIES[index];
251             if (sql != nullptr) {
252                 LOG_INFO("%{public}s : %{public}s, ", sql, SqliteUtils::Anonymous(config.GetName()).c_str());
253                 std::tie(errCode, checkResult) = ExecuteForValue(sql);
254             }
255             if (errCode == E_OK && static_cast<std::string>(checkResult) != "ok") {
256                 LOG_ERROR("%{public}s integrity check result is %{public}s, sql:%{public}s",
257                     SqliteUtils::Anonymous(config.GetName()).c_str(),
258                     static_cast<std::string>(checkResult).c_str(), sql);
259                 Reportor::ReportFault(Reportor::Create(config, errCode, static_cast<std::string>(checkResult)));
260             }
261         }
262     }
263 
264     filePath = dbPath;
265     return E_OK;
266 }
267 
OpenDatabase(const std::string & dbPath,int openFileFlags)268 int32_t SqliteConnection::OpenDatabase(const std::string &dbPath, int openFileFlags)
269 {
270     int errCode = sqlite3_open_v2(dbPath.c_str(), &dbHandle_, openFileFlags, nullptr);
271     if (errCode != SQLITE_OK) {
272         LOG_ERROR("fail to open database errCode=%{public}d, dbPath=%{public}s, flags=%{public}d, errno=%{public}d",
273             errCode, SqliteUtils::Anonymous(dbPath).c_str(), openFileFlags, errno);
274 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM)
275         auto const pos = dbPath.find_last_of("\\/");
276         if (pos != std::string::npos) {
277             std::string filepath = dbPath.substr(0, pos);
278             if (access(filepath.c_str(), F_OK | W_OK) != 0) {
279                 LOG_ERROR("The path to the database file to be created is not valid, err = %{public}d", errno);
280                 return E_INVALID_FILE_PATH;
281             }
282         }
283 #endif
284         return SQLiteError::ErrNo(errCode);
285     }
286     return E_OK;
287 }
288 
SetCustomFunctions(const RdbStoreConfig & config)289 int SqliteConnection::SetCustomFunctions(const RdbStoreConfig &config)
290 {
291     customScalarFunctions_ = config.GetScalarFunctions();
292     for (auto &it : customScalarFunctions_) {
293         int errCode = SetCustomScalarFunction(it.first, it.second.argc_, &it.second.function_);
294         if (errCode != E_OK) {
295             return errCode;
296         }
297     }
298     return E_OK;
299 }
300 
CustomScalarFunctionCallback(sqlite3_context * ctx,int argc,sqlite3_value ** argv)301 static void CustomScalarFunctionCallback(sqlite3_context *ctx, int argc, sqlite3_value **argv)
302 {
303     if (ctx == nullptr || argv == nullptr) {
304         LOG_ERROR("ctx or argv is nullptr.");
305         return;
306     }
307     auto function = static_cast<ScalarFunction *>(sqlite3_user_data(ctx));
308     if (function == nullptr) {
309         LOG_ERROR("function is nullptr.");
310         return;
311     }
312 
313     std::vector<std::string> argsVector;
314     for (int i = 0; i < argc; ++i) {
315         auto arg = reinterpret_cast<const char *>(sqlite3_value_text(argv[i]));
316         if (arg == nullptr) {
317             LOG_ERROR("arg is nullptr, index is %{public}d, errno is %{public}d", i, errno);
318             sqlite3_result_null(ctx);
319             return;
320         }
321         argsVector.emplace_back(std::string(arg));
322     }
323 
324     std::string result = (*function)(argsVector);
325     if (result.empty()) {
326         sqlite3_result_null(ctx);
327         return;
328     }
329     sqlite3_result_text(ctx, result.c_str(), -1, SQLITE_TRANSIENT);
330 }
331 
SetCustomScalarFunction(const std::string & functionName,int argc,ScalarFunction * function)332 int SqliteConnection::SetCustomScalarFunction(const std::string &functionName, int argc, ScalarFunction *function)
333 {
334     int err = sqlite3_create_function_v2(dbHandle_, functionName.c_str(), argc, SQLITE_UTF8, function,
335         &CustomScalarFunctionCallback, nullptr, nullptr, nullptr);
336     if (err != SQLITE_OK) {
337         LOG_ERROR("SetCustomScalarFunction errCode is %{public}d, errno is %{public}d.", err, errno);
338     }
339     return err;
340 }
341 
Configure(const RdbStoreConfig & config,std::string & dbPath)342 int SqliteConnection::Configure(const RdbStoreConfig &config, std::string &dbPath)
343 {
344     if (config.GetStorageMode() == StorageMode::MODE_MEMORY) {
345         return E_OK;
346     }
347 
348     if (config.GetRoleType() == VISITOR) {
349         return E_OK;
350     }
351 
352     auto errCode = RegDefaultFunctions(dbHandle_);
353     if (errCode != E_OK) {
354         return errCode;
355     }
356 
357     SetBusyTimeout(DEFAULT_BUSY_TIMEOUT_MS);
358 
359     LimitPermission(dbPath);
360 
361     errCode = SetPersistWal();
362     if (errCode != E_OK) {
363         return errCode;
364     }
365 
366     errCode = SetPageSize(config);
367     if (errCode != E_OK) {
368         return errCode;
369     }
370 
371     errCode = SetEncrypt(config);
372     if (errCode != E_OK) {
373         return errCode;
374     }
375 
376     errCode = SetJournalMode(config);
377     if (errCode != E_OK) {
378         return errCode;
379     }
380 
381     // set the user version to the wal file;
382     SetWalFile(config);
383 
384     errCode = SetJournalSizeLimit(config);
385     if (errCode != E_OK) {
386         return errCode;
387     }
388 
389     errCode = SetAutoCheckpoint(config);
390     if (errCode != E_OK) {
391         return errCode;
392     }
393 
394     errCode = SetCustomFunctions(config);
395     if (errCode != E_OK) {
396         return errCode;
397     }
398     return LoadExtension(config, dbHandle_);
399 }
400 
~SqliteConnection()401 SqliteConnection::~SqliteConnection()
402 {
403     if (backupId_ != TaskExecutor::INVALID_TASK_ID) {
404         auto pool = TaskExecutor::GetInstance().GetExecutor();
405         if (pool != nullptr) {
406             pool->Remove(backupId_, true);
407         }
408     }
409     if (dbHandle_ != nullptr) {
410         if (hasClientObserver_) {
411             UnRegisterClientObserver(dbHandle_);
412         }
413         if (isWriter_) {
414             UnregisterStoreObserver(dbHandle_);
415         }
416 
417         int errCode = sqlite3_close_v2(dbHandle_);
418         if (errCode != SQLITE_OK) {
419             LOG_ERROR("could not close database err = %{public}d, errno = %{public}d", errCode, errno);
420         }
421     }
422 }
423 
OnInitialize()424 int32_t SqliteConnection::OnInitialize()
425 {
426     return 0;
427 }
428 
CreateStatement(const std::string & sql,std::shared_ptr<Connection> conn)429 std::pair<int, std::shared_ptr<Statement>> SqliteConnection::CreateStatement(
430     const std::string &sql, std::shared_ptr<Connection> conn)
431 {
432     std::shared_ptr<SqliteStatement> statement = std::make_shared<SqliteStatement>();
433     statement->config_ = &config_;
434     int errCode = statement->Prepare(dbHandle_, sql);
435     if (errCode != E_OK) {
436         return { errCode, nullptr };
437     }
438     statement->conn_ = conn;
439     if (slaveConnection_ && IsWriter()) {
440         auto slaveStmt = std::make_shared<SqliteStatement>();
441         slaveStmt->config_ = &slaveConnection_->config_;
442         errCode = slaveStmt->Prepare(slaveConnection_->dbHandle_, sql);
443         if (errCode != E_OK) {
444             LOG_WARN("prepare slave stmt failed:%{public}d, sql:%{public}s", errCode, sql.c_str());
445             SqliteUtils::TryAccessSlaveLock(config_.GetPath(), false, true, true);
446             return { E_OK, statement };
447         }
448         statement->slave_ = slaveStmt;
449     }
450     return { E_OK, statement };
451 }
452 
IsWriter() const453 bool SqliteConnection::IsWriter() const
454 {
455     return isWriter_;
456 }
457 
SubscribeTableChanges(const Connection::Notifier & notifier)458 int SqliteConnection::SubscribeTableChanges(const Connection::Notifier &notifier)
459 {
460 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM)
461     if (!isWriter_ || notifier == nullptr) {
462         return E_OK;
463     }
464     hasClientObserver_ = true;
465     int32_t status = RegisterClientObserver(dbHandle_, [notifier](const ClientChangedData &clientData) {
466         std::set<std::string> tables;
467         for (auto &[key, val] : clientData.tableData) {
468             if (val.isTrackedDataChange) {
469                 tables.insert(key);
470             }
471         }
472         notifier(tables);
473     });
474     if (status != E_OK) {
475         LOG_ERROR("RegisterClientObserver error, status:%{public}d", status);
476     }
477     return status;
478 #endif
479     return E_OK;
480 }
481 
GetMaxVariable() const482 int SqliteConnection::GetMaxVariable() const
483 {
484     return maxVariableNumber_;
485 }
486 
GetJournalMode()487 int32_t SqliteConnection::GetJournalMode()
488 {
489     return (int32_t)mode_;
490 }
491 
GetDBType() const492 int32_t SqliteConnection::GetDBType() const
493 {
494     return DB_SQLITE;
495 }
496 
SetPageSize(const RdbStoreConfig & config)497 int SqliteConnection::SetPageSize(const RdbStoreConfig &config)
498 {
499     if (isReadOnly_ || config.GetPageSize() == GlobalExpr::DB_PAGE_SIZE) {
500         return E_OK;
501     }
502 
503     int targetValue = config.GetPageSize();
504     auto [errCode, object] = ExecuteForValue("PRAGMA page_size");
505     if (errCode != E_OK) {
506         LOG_ERROR("SetPageSize fail to get page size : %{public}d", errCode);
507         return errCode;
508     }
509 
510     if (static_cast<int64_t>(object) == targetValue) {
511         return E_OK;
512     }
513 
514     errCode = ExecuteSql("PRAGMA page_size=" + std::to_string(targetValue));
515     if (errCode != E_OK) {
516         LOG_ERROR("SetPageSize fail to set page size : %{public}d", errCode);
517     }
518     return errCode;
519 }
520 
SetEncryptAgo(const RdbStoreConfig & config)521 int SqliteConnection::SetEncryptAgo(const RdbStoreConfig &config)
522 {
523     if (!config.GetCryptoParam().IsValid()) {
524         LOG_ERROR("Invalid crypto param: %{public}s, %{public}d, %{public}d, %{public}d, %{public}d, %{public}u",
525             SqliteUtils::Anonymous(config.GetName()).c_str(), config.GetCryptoParam().iterNum,
526             config.GetCryptoParam().encryptAlgo, config.GetCryptoParam().hmacAlgo, config.GetCryptoParam().kdfAlgo,
527             config.GetCryptoParam().cryptoPageSize);
528         return E_INVALID_ARGS;
529     }
530 
531     if (config.GetIter() != NO_ITER) {
532         auto errCode = ExecuteSql(std::string(GlobalExpr::CIPHER_ALGO_PREFIX) +
533                                   SqliteUtils::EncryptAlgoDescription(config.GetEncryptAlgo()) +
534                                   std::string(GlobalExpr::ALGO_SUFFIX));
535         if (errCode != E_OK) {
536             LOG_ERROR("set cipher algo failed, err = %{public}d", errCode);
537             return errCode;
538         }
539 
540         errCode = ExecuteSql(std::string(GlobalExpr::CIPHER_KDF_ITER) + std::to_string(config.GetIter()));
541         if (errCode != E_OK) {
542             LOG_ERROR("set kdf iter number V1 failed, err = %{public}d", errCode);
543             return errCode;
544         }
545     }
546 
547     auto errCode = ExecuteSql(std::string(GlobalExpr::CODEC_HMAC_ALGO_PREFIX) +
548                               SqliteUtils::HmacAlgoDescription(config.GetCryptoParam().hmacAlgo) +
549                               std::string(GlobalExpr::ALGO_SUFFIX));
550     if (errCode != E_OK) {
551         LOG_ERROR("set codec hmac algo failed, err = %{public}d", errCode);
552         return errCode;
553     }
554 
555     errCode = ExecuteSql(std::string(GlobalExpr::CODEC_KDF_ALGO_PREFIX) +
556                          SqliteUtils::KdfAlgoDescription(config.GetCryptoParam().kdfAlgo) +
557                          std::string(GlobalExpr::ALGO_SUFFIX));
558     if (errCode != E_OK) {
559         LOG_ERROR("set codec kdf algo failed, err = %{public}d", errCode);
560         return errCode;
561     }
562 
563     errCode = ExecuteSql(
564         std::string(GlobalExpr::CODEC_PAGE_SIZE_PREFIX) + std::to_string(config.GetCryptoParam().cryptoPageSize));
565     if (errCode != E_OK) {
566         LOG_ERROR("set codec page size failed, err = %{public}d", errCode);
567         return errCode;
568     }
569 
570     errCode = ExecuteSql(GlobalExpr::CODEC_REKEY_HMAC_ALGO);
571     if (errCode != E_OK) {
572         LOG_ERROR("set rekey sha algo failed, err = %{public}d", errCode);
573         return errCode;
574     }
575     return E_OK;
576 }
577 
ReSetKey(const RdbStoreConfig & config)578 int SqliteConnection::ReSetKey(const RdbStoreConfig &config)
579 {
580     if (!IsWriter()) {
581         return E_OK;
582     }
583     LOG_INFO("name = %{public}s, iter = %{public}d", SqliteUtils::Anonymous(config.GetName()).c_str(),
584         config.GetIter());
585     std::vector<uint8_t> newKey = config.GetNewEncryptKey();
586     int errCode = sqlite3_rekey(dbHandle_, static_cast<const void *>(newKey.data()), static_cast<int>(newKey.size()));
587     newKey.assign(newKey.size(), 0);
588     if (errCode != SQLITE_OK) {
589         LOG_ERROR("ReKey failed, err = %{public}d, errno = %{public}d", errCode, errno);
590         RdbSecurityManager::GetInstance().DelKeyFile(config.GetPath(), RdbKeyFile::PUB_KEY_FILE_NEW_KEY);
591         return E_OK;
592     }
593     config.ChangeEncryptKey();
594     return E_OK;
595 }
596 
GetSecManagerName(const RdbStoreConfig & config)597 std::string SqliteConnection::GetSecManagerName(const RdbStoreConfig &config)
598 {
599     auto name = config.GetBundleName();
600     if (name.empty()) {
601         LOG_WARN("Bundle name is empty, using path instead.");
602         return std::string(config.GetPath()).substr(0, config.GetPath().rfind("/") + 1);
603     }
604     return name;
605 }
606 
SetEncrypt(const RdbStoreConfig & config)607 int SqliteConnection::SetEncrypt(const RdbStoreConfig &config)
608 {
609     if (!config.IsEncrypt()) {
610         return E_OK;
611     }
612 
613     std::vector<uint8_t> key = config.GetEncryptKey();
614     std::vector<uint8_t> newKey = config.GetNewEncryptKey();
615     auto errCode = SetEncryptKey(key, config);
616     key.assign(key.size(), 0);
617     if (errCode != E_OK) {
618         if (!newKey.empty()) {
619             LOG_INFO("use new key, iter=%{public}d err=%{public}d errno=%{public}d name=%{public}s", config.GetIter(),
620                 errCode, errno, SqliteUtils::Anonymous(config.GetName()).c_str());
621             errCode = SetEncryptKey(newKey, config);
622         }
623         newKey.assign(newKey.size(), 0);
624         if (errCode != E_OK) {
625             errCode = SetServiceKey(config, errCode);
626             LOG_ERROR("fail, iter=%{public}d err=%{public}d errno=%{public}d name=%{public}s", config.GetIter(),
627                 errCode, errno, SqliteUtils::Anonymous(config.GetName()).c_str());
628             return errCode;
629         }
630         config.ChangeEncryptKey();
631         newKey = {};
632     }
633 
634     if (!newKey.empty()) {
635         ReSetKey(config);
636     }
637     newKey.assign(newKey.size(), 0);
638     return E_OK;
639 }
640 
SetEncryptKey(const std::vector<uint8_t> & key,const RdbStoreConfig & config)641 int SqliteConnection::SetEncryptKey(const std::vector<uint8_t> &key, const RdbStoreConfig &config)
642 {
643     if (key.empty()) {
644         return E_INVALID_SECRET_KEY;
645     }
646 
647     auto errCode = sqlite3_key(dbHandle_, static_cast<const void *>(key.data()), static_cast<int>(key.size()));
648     if (errCode != SQLITE_OK) {
649         return SQLiteError::ErrNo(errCode);
650     }
651 
652     errCode = SetEncryptAgo(config);
653     if (errCode != E_OK) {
654         return errCode;
655     }
656 
657     if (IsWriter()) {
658         ValueObject version;
659         std::tie(errCode, version) = ExecuteForValue(GlobalExpr::PRAGMA_VERSION);
660         if (errCode != E_OK || version.GetType() == ValueObject::TYPE_NULL) {
661             return errCode;
662         }
663         return E_OK;
664     }
665     return errCode;
666 }
667 
SetPersistWal()668 int SqliteConnection::SetPersistWal()
669 {
670     int opcode = 1;
671     int errCode = sqlite3_file_control(dbHandle_, "main", SQLITE_FCNTL_PERSIST_WAL, &opcode);
672     if (errCode != SQLITE_OK) {
673         LOG_ERROR("failed.");
674         return E_SET_PERSIST_WAL;
675     }
676     return E_OK;
677 }
678 
SetBusyTimeout(int timeout)679 int SqliteConnection::SetBusyTimeout(int timeout)
680 {
681     auto errCode = sqlite3_busy_timeout(dbHandle_, timeout);
682     if (errCode != SQLITE_OK) {
683         LOG_ERROR("set buys timeout failed, errCode=%{public}d, errno=%{public}d", errCode, errno);
684         return errCode;
685     }
686     return E_OK;
687 }
688 
RegDefaultFunctions(sqlite3 * dbHandle)689 int SqliteConnection::RegDefaultFunctions(sqlite3 *dbHandle)
690 {
691     if (dbHandle == nullptr) {
692         return SQLITE_OK;
693     }
694     // The number of parameters is 2
695     int errCode = sqlite3_create_function_v2(dbHandle, MERGE_ASSETS_FUNC, 2, SQLITE_UTF8 | SQLITE_DETERMINISTIC,
696         nullptr, &MergeAssets, nullptr, nullptr, nullptr);
697     if (errCode != SQLITE_OK) {
698         LOG_ERROR("register function mergeAssets failed, errCode=%{public}d, errno=%{public}d", errCode, errno);
699         return errCode;
700     }
701     // The number of parameters is 2
702     errCode = sqlite3_create_function_v2(dbHandle, MERGE_ASSET_FUNC, 2, SQLITE_UTF8 | SQLITE_DETERMINISTIC, nullptr,
703         &MergeAsset, nullptr, nullptr, nullptr);
704     if (errCode != SQLITE_OK) {
705         LOG_ERROR("register function mergeAsset failed, errCode=%{public}d, errno=%{public}d", errCode, errno);
706         return errCode;
707     }
708     return SQLITE_OK;
709 }
710 
SetJournalMode(const RdbStoreConfig & config)711 int SqliteConnection::SetJournalMode(const RdbStoreConfig &config)
712 {
713     if (isReadOnly_) {
714         return E_OK;
715     }
716 
717     auto [errCode, object] = ExecuteForValue("PRAGMA journal_mode");
718     if (errCode != E_OK) {
719         LOG_ERROR("SqliteConnection SetJournalMode fail to get journal mode : %{public}d", errCode);
720         return errCode;
721     }
722 
723     if (config.GetJournalMode().compare(static_cast<std::string>(object)) == 0) {
724         return E_OK;
725     }
726 
727     std::string currentMode = SqliteUtils::StrToUpper(static_cast<std::string>(object));
728     if (currentMode != config.GetJournalMode()) {
729         auto [errorCode, journalMode] = ExecuteForValue("PRAGMA journal_mode=" + config.GetJournalMode());
730         if (errorCode != E_OK) {
731             LOG_ERROR("SqliteConnection SetJournalMode: fail to set journal mode err=%{public}d", errorCode);
732             return errorCode;
733         }
734 
735         if (SqliteUtils::StrToUpper(static_cast<std::string>(journalMode)) != config.GetJournalMode()) {
736             LOG_ERROR("SqliteConnection SetJournalMode: result incorrect.");
737             return E_EXECUTE_RESULT_INCORRECT;
738         }
739     }
740 
741     if (config.GetJournalMode() == "WAL") {
742         errCode = SetWalSyncMode(config.GetSyncMode());
743     }
744     if (config.GetJournalMode() == "TRUNCATE") {
745         mode_ = JournalMode::MODE_TRUNCATE;
746     }
747     return errCode;
748 }
749 
SetJournalSizeLimit(const RdbStoreConfig & config)750 int SqliteConnection::SetJournalSizeLimit(const RdbStoreConfig &config)
751 {
752     if (isReadOnly_ || config.GetJournalSize() == GlobalExpr::DB_JOURNAL_SIZE) {
753         return E_OK;
754     }
755 
756     int targetValue = SqliteGlobalConfig::GetJournalFileSize();
757     auto [errCode, currentValue] = ExecuteForValue("PRAGMA journal_size_limit");
758     if (errCode != E_OK) {
759         LOG_ERROR("SqliteConnection SetJournalSizeLimit fail to get journal_size_limit : %{public}d", errCode);
760         return errCode;
761     }
762 
763     if (static_cast<int64_t>(currentValue) == targetValue) {
764         return E_OK;
765     }
766 
767     std::tie(errCode, currentValue) = ExecuteForValue("PRAGMA journal_size_limit=" + std::to_string(targetValue));
768     if (errCode != E_OK) {
769         LOG_ERROR("SqliteConnection SetJournalSizeLimit fail to set journal_size_limit : %{public}d", errCode);
770     }
771     return errCode;
772 }
773 
SetAutoCheckpoint(const RdbStoreConfig & config)774 int SqliteConnection::SetAutoCheckpoint(const RdbStoreConfig &config)
775 {
776     if (isReadOnly_ || !config.IsAutoCheck()) {
777         return E_OK;
778     }
779 
780     int targetValue = SqliteGlobalConfig::GetWalAutoCheckpoint();
781     auto [errCode, value] = ExecuteForValue("PRAGMA wal_autocheckpoint");
782     if (errCode != E_OK) {
783         LOG_ERROR("SqliteConnection SetAutoCheckpoint fail to get wal_autocheckpoint : %{public}d", errCode);
784         return errCode;
785     }
786 
787     if (static_cast<int64_t>(value) == targetValue) {
788         return E_OK;
789     }
790 
791     std::tie(errCode, value) = ExecuteForValue("PRAGMA wal_autocheckpoint=" + std::to_string(targetValue));
792     if (errCode != E_OK) {
793         LOG_ERROR("SqliteConnection SetAutoCheckpoint fail to set wal_autocheckpoint : %{public}d", errCode);
794     }
795     return errCode;
796 }
797 
SetWalFile(const RdbStoreConfig & config)798 int SqliteConnection::SetWalFile(const RdbStoreConfig &config)
799 {
800     if (!IsWriter()) {
801         return E_OK;
802     }
803     auto [errCode, version] = ExecuteForValue(GlobalExpr::PRAGMA_VERSION);
804     if (errCode != E_OK) {
805         return errCode;
806     }
807     return ExecuteSql(std::string(GlobalExpr::PRAGMA_VERSION) + "=?", { std::move(version) });
808 }
809 
SetWalSyncMode(const std::string & syncMode)810 int SqliteConnection::SetWalSyncMode(const std::string &syncMode)
811 {
812     std::string targetValue = SqliteGlobalConfig::GetSyncMode();
813     if (syncMode.length() != 0) {
814         targetValue = syncMode;
815     }
816 
817     auto [errCode, object] = ExecuteForValue("PRAGMA synchronous");
818     if (errCode != E_OK) {
819         LOG_ERROR("get wal sync mode fail, errCode:%{public}d", errCode);
820         return errCode;
821     }
822 
823     std::string walSyncMode = SqliteUtils::StrToUpper(static_cast<std::string>(object));
824     if (walSyncMode == targetValue) {
825         return E_OK;
826     }
827 
828     errCode = ExecuteSql("PRAGMA synchronous=" + targetValue);
829     if (errCode != E_OK) {
830         LOG_ERROR("set wal sync mode fail, errCode:%{public}d", errCode);
831     }
832     return errCode;
833 }
834 
ExecuteSql(const std::string & sql,const std::vector<ValueObject> & bindArgs)835 int SqliteConnection::ExecuteSql(const std::string &sql, const std::vector<ValueObject> &bindArgs)
836 {
837     auto [errCode, statement] = CreateStatement(sql, nullptr);
838     if (statement == nullptr || errCode != E_OK) {
839         return errCode;
840     }
841     return statement->Execute(bindArgs);
842 }
843 
ExecuteForValue(const std::string & sql,const std::vector<ValueObject> & bindArgs)844 std::pair<int32_t, ValueObject> SqliteConnection::ExecuteForValue(const std::string &sql,
845     const std::vector<ValueObject> &bindArgs)
846 {
847     auto [errCode, statement] = CreateStatement(sql, nullptr);
848     if (statement == nullptr || errCode != E_OK) {
849         return { static_cast<int32_t>(errCode), ValueObject() };
850     }
851 
852     ValueObject object;
853     std::tie(errCode, object) = statement->ExecuteForValue(bindArgs);
854     if (errCode != E_OK) {
855         LOG_ERROR("execute sql failed, errCode:%{public}d, sql:%{public}s, args size:%{public}zu",
856             SQLiteError::ErrNo(errCode), sql.c_str(), bindArgs.size());
857     }
858     return { errCode, object };
859 }
860 
ClearCache()861 int SqliteConnection::ClearCache()
862 {
863     if (dbHandle_ != nullptr && mode_ == JournalMode::MODE_WAL) {
864         sqlite3_db_release_memory(dbHandle_);
865     }
866     if (slaveConnection_) {
867         int errCode = slaveConnection_->ClearCache();
868         if (errCode != E_OK) {
869             LOG_ERROR("slaveConnection clearCache failed:%{public}d", errCode);
870         }
871     }
872     return E_OK;
873 }
874 
LimitPermission(const std::string & dbPath) const875 void SqliteConnection::LimitPermission(const std::string &dbPath) const
876 {
877     struct stat st = { 0 };
878     if (stat(dbPath.c_str(), &st) == 0) {
879         if ((st.st_mode & (S_IXUSR | S_IXGRP | S_IRWXO)) != 0) {
880             int ret = chmod(dbPath.c_str(), st.st_mode & (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP));
881             if (ret != 0) {
882                 LOG_DEBUG("SqliteConnection LimitPermission chmod fail, err = %{public}d", errno);
883             }
884         }
885     } else {
886         LOG_ERROR("SqliteConnection LimitPermission stat fail, err = %{public}d", errno);
887     }
888 }
889 
890 #ifdef RDB_SUPPORT_ICU
Collate8Compare(void * p,int n1,const void * v1,int n2,const void * v2)891 int Collate8Compare(void *p, int n1, const void *v1, int n2, const void *v2)
892 {
893     UCollator *coll = reinterpret_cast<UCollator *>(p);
894     UCharIterator i1;
895     UCharIterator i2;
896     UErrorCode status = U_ZERO_ERROR;
897 
898     uiter_setUTF8(&i1, (const char *)v1, n1);
899     uiter_setUTF8(&i2, (const char *)v2, n2);
900 
901     UCollationResult result = ucol_strcollIter(coll, &i1, &i2, &status);
902 
903     if (U_FAILURE(status)) {
904         LOG_ERROR("Ucol strcoll error.");
905     }
906 
907     if (result == UCOL_LESS) {
908         return -1;
909     } else if (result == UCOL_GREATER) {
910         return 1;
911     }
912     return 0;
913 }
914 
LocalizedCollatorDestroy(UCollator * collator)915 void LocalizedCollatorDestroy(UCollator *collator)
916 {
917     ucol_close(collator);
918 }
919 #endif
920 
921 /**
922  * The database locale.
923  */
ConfigLocale(const std::string & localeStr)924 int SqliteConnection::ConfigLocale(const std::string &localeStr)
925 {
926 #ifdef RDB_SUPPORT_ICU
927     std::unique_lock<std::mutex> lock(mutex_);
928     UErrorCode status = U_ZERO_ERROR;
929     UCollator *collator = ucol_open(localeStr.c_str(), &status);
930     if (U_FAILURE(status)) {
931         LOG_ERROR("Can not open collator.");
932         return E_ERROR;
933     }
934     ucol_setAttribute(collator, UCOL_STRENGTH, UCOL_PRIMARY, &status);
935     if (U_FAILURE(status)) {
936         LOG_ERROR("Set attribute of collator failed.");
937         return E_ERROR;
938     }
939 
940     int err = sqlite3_create_collation_v2(dbHandle_, "LOCALES", SQLITE_UTF8, collator, Collate8Compare,
941         (void (*)(void *))LocalizedCollatorDestroy);
942     if (err != SQLITE_OK) {
943         LOG_ERROR("SCreate collator in sqlite3 failed.");
944         return err;
945     }
946 #endif
947     return E_OK;
948 }
949 
CleanDirtyData(const std::string & table,uint64_t cursor)950 int SqliteConnection::CleanDirtyData(const std::string &table, uint64_t cursor)
951 {
952     if (table.empty()) {
953         LOG_ERROR("table is empty");
954         return E_INVALID_ARGS;
955     }
956     uint64_t tmpCursor = cursor == UINT64_MAX ? 0 : cursor;
957     auto status = DropLogicDeletedData(dbHandle_, table, tmpCursor);
958     LOG_INFO("status:%{public}d, table:%{public}s, cursor:%{public}" PRIu64 "", status,
959         SqliteUtils::Anonymous(table).c_str(), cursor);
960     return status == DistributedDB::DBStatus::OK ? E_OK : E_ERROR;
961 }
962 
TryCheckPoint(bool timeout)963 int SqliteConnection::TryCheckPoint(bool timeout)
964 {
965     if (!isWriter_) {
966         return E_NOT_SUPPORT;
967     }
968 
969     std::shared_ptr<Connection> autoCheck(slaveConnection_.get(), [this, timeout](Connection *conn) {
970         if (conn != nullptr && backupId_ == TaskExecutor::INVALID_TASK_ID) {
971             conn->TryCheckPoint(timeout);
972         }
973     });
974     std::string walName = sqlite3_filename_wal(sqlite3_db_filename(dbHandle_, "main"));
975     ssize_t size = SqliteUtils::GetFileSize(walName);
976     if (size < 0) {
977         LOG_ERROR("Invalid size for WAL:%{public}s size:%{public}zd", SqliteUtils::Anonymous(walName).c_str(), size);
978         return E_ERROR;
979     }
980 
981     if (size <= config_.GetStartCheckpointSize()) {
982         return E_OK;
983     }
984 
985     if (!timeout && size < config_.GetCheckpointSize()) {
986         return E_INNER_WARNING;
987     }
988 
989     (void)sqlite3_busy_timeout(dbHandle_, CHECKPOINT_TIME);
990     int errCode = sqlite3_wal_checkpoint_v2(dbHandle_, nullptr, SQLITE_CHECKPOINT_TRUNCATE, nullptr, nullptr);
991     (void)sqlite3_busy_timeout(dbHandle_, DEFAULT_BUSY_TIMEOUT_MS);
992     if (errCode != SQLITE_OK) {
993         LOG_WARN("sqlite3_wal_checkpoint_v2 failed err:%{public}d,size:%{public}zd,wal:%{public}s.", errCode, size,
994             SqliteUtils::Anonymous(walName).c_str());
995         return SQLiteError::ErrNo(errCode);
996     }
997     return E_OK;
998 }
999 
LimitWalSize()1000 int SqliteConnection::LimitWalSize()
1001 {
1002     if (!isConfigured_ || !isWriter_) {
1003         return E_OK;
1004     }
1005 
1006     std::string walName = sqlite3_filename_wal(sqlite3_db_filename(dbHandle_, "main"));
1007     ssize_t fileSize = SqliteUtils::GetFileSize(walName);
1008     if (fileSize < 0 || fileSize > config_.GetWalLimitSize()) {
1009         LOG_ERROR("The WAL file size exceeds the limit, %{public}s size is %{public}zd",
1010             SqliteUtils::Anonymous(walName).c_str(), fileSize);
1011         return E_WAL_SIZE_OVER_LIMIT;
1012     }
1013     return E_OK;
1014 }
1015 
MergeAssets(sqlite3_context * ctx,int argc,sqlite3_value ** argv)1016 void SqliteConnection::MergeAssets(sqlite3_context *ctx, int argc, sqlite3_value **argv)
1017 {
1018     // 2 is the number of parameters
1019     if (ctx == nullptr || argc != 2 || argv == nullptr) {
1020         LOG_ERROR("Parameter does not meet restrictions.");
1021         return;
1022     }
1023     std::map<std::string, ValueObject::Asset> assets;
1024     auto data = static_cast<const uint8_t *>(sqlite3_value_blob(argv[0]));
1025     if (data != nullptr) {
1026         int len = sqlite3_value_bytes(argv[0]);
1027         RawDataParser::ParserRawData(data, len, assets);
1028     }
1029     std::map<std::string, ValueObject::Asset> newAssets;
1030     data = static_cast<const uint8_t *>(sqlite3_value_blob(argv[1]));
1031     if (data != nullptr) {
1032         int len = sqlite3_value_bytes(argv[1]);
1033         RawDataParser::ParserRawData(data, len, newAssets);
1034     }
1035     CompAssets(assets, newAssets);
1036     auto blob = RawDataParser::PackageRawData(assets);
1037     sqlite3_result_blob(ctx, blob.data(), blob.size(), SQLITE_TRANSIENT);
1038 }
1039 
MergeAsset(sqlite3_context * ctx,int argc,sqlite3_value ** argv)1040 void SqliteConnection::MergeAsset(sqlite3_context *ctx, int argc, sqlite3_value **argv)
1041 {
1042     // 2 is the number of parameters
1043     if (ctx == nullptr || argc != 2 || argv == nullptr) {
1044         LOG_ERROR("Parameter does not meet restrictions.");
1045         return;
1046     }
1047     ValueObject::Asset asset;
1048     size_t size = 0;
1049     auto data = static_cast<const uint8_t *>(sqlite3_value_blob(argv[0]));
1050     if (data != nullptr) {
1051         int len = sqlite3_value_bytes(argv[0]);
1052         size = RawDataParser::ParserRawData(data, len, asset);
1053     }
1054     ValueObject::Asset newAsset;
1055     data = static_cast<const uint8_t *>(sqlite3_value_blob(argv[1]));
1056     if (data != nullptr) {
1057         int len = sqlite3_value_bytes(argv[1]);
1058         RawDataParser::ParserRawData(data, len, newAsset);
1059     }
1060 
1061     if (size == 0) {
1062         asset = std::move(newAsset);
1063         if (asset.status != AssetValue::Status::STATUS_DELETE) {
1064             asset.status = AssetValue::Status::STATUS_INSERT;
1065         }
1066     } else if (asset.name == newAsset.name) {
1067         MergeAsset(asset, newAsset);
1068     } else {
1069         LOG_WARN("name change! old:%{public}s, new:%{public}s", SqliteUtils::Anonymous(asset.name).c_str(),
1070             SqliteUtils::Anonymous(newAsset.name).c_str());
1071     }
1072     auto blob = RawDataParser::PackageRawData(asset);
1073     sqlite3_result_blob(ctx, blob.data(), blob.size(), SQLITE_TRANSIENT);
1074 }
1075 
CompAssets(std::map<std::string,ValueObject::Asset> & assets,std::map<std::string,ValueObject::Asset> & newAssets)1076 void SqliteConnection::CompAssets(std::map<std::string, ValueObject::Asset> &assets,
1077     std::map<std::string, ValueObject::Asset> &newAssets)
1078 {
1079     auto oldIt = assets.begin();
1080     auto newIt = newAssets.begin();
1081     for (; oldIt != assets.end() && newIt != newAssets.end();) {
1082         if (oldIt->first == newIt->first) {
1083             MergeAsset(oldIt->second, newIt->second);
1084             oldIt++;
1085             newIt = newAssets.erase(newIt);
1086             continue;
1087         }
1088         if (oldIt->first < newIt->first) {
1089             ++oldIt;
1090             continue;
1091         }
1092         newIt++;
1093     }
1094     for (auto &[key, value] : newAssets) {
1095         value.status = ValueObject::Asset::Status::STATUS_INSERT;
1096         assets.insert(std::pair{ key, std::move(value) });
1097     }
1098 }
1099 
MergeAsset(ValueObject::Asset & oldAsset,ValueObject::Asset & newAsset)1100 void SqliteConnection::MergeAsset(ValueObject::Asset &oldAsset, ValueObject::Asset &newAsset)
1101 {
1102     using Status = ValueObject::Asset::Status;
1103     if (newAsset.status == Status::STATUS_DELETE) {
1104         oldAsset.status = Status::STATUS_DELETE;
1105         oldAsset.hash = "";
1106         oldAsset.modifyTime = "";
1107         oldAsset.size = "";
1108         return;
1109     }
1110     auto status = static_cast<int32_t>(oldAsset.status);
1111     switch (status) {
1112         case Status::STATUS_UNKNOWN:  // fallthrough
1113         case Status::STATUS_NORMAL:   // fallthrough
1114         case Status::STATUS_ABNORMAL: // fallthrough
1115         case Status::STATUS_INSERT:   // fallthrough
1116         case Status::STATUS_UPDATE:   // fallthrough
1117             if (oldAsset.modifyTime != newAsset.modifyTime || oldAsset.size != newAsset.size ||
1118                 oldAsset.uri != newAsset.uri || oldAsset.path != newAsset.path) {
1119                 if (oldAsset.modifyTime != newAsset.modifyTime || oldAsset.size != newAsset.size ||
1120                     oldAsset.uri == newAsset.uri || oldAsset.path == newAsset.path) {
1121                     oldAsset.expiresTime = newAsset.expiresTime;
1122                     oldAsset.hash = newAsset.hash;
1123                     oldAsset.status = Status::STATUS_UPDATE;
1124                 }
1125                 oldAsset.version = newAsset.version;
1126                 oldAsset.uri = newAsset.uri;
1127                 oldAsset.createTime = newAsset.createTime;
1128                 oldAsset.modifyTime = newAsset.modifyTime;
1129                 oldAsset.size = newAsset.size;
1130                 oldAsset.path = newAsset.path;
1131             }
1132             return;
1133         default:
1134             return;
1135     }
1136 }
1137 
Subscribe(const std::string & event,const std::shared_ptr<RdbStoreObserver> & observer)1138 int32_t SqliteConnection::Subscribe(const std::string &event, const std::shared_ptr<RdbStoreObserver> &observer)
1139 {
1140     if (!isWriter_ || observer == nullptr) {
1141         return E_OK;
1142     }
1143     std::lock_guard<std::mutex> lock(mutex_);
1144     observers_.try_emplace(event);
1145     auto &list = observers_.find(event)->second;
1146     for (auto it = list.begin(); it != list.end(); it++) {
1147         if ((*it)->GetObserver() == observer) {
1148             LOG_ERROR("duplicate subscribe.");
1149             return E_OK;
1150         }
1151     }
1152     auto localStoreObserver = std::make_shared<RdbStoreLocalDbObserver>(observer);
1153     int32_t errCode = RegisterStoreObserver(dbHandle_, localStoreObserver);
1154     if (errCode != E_OK) {
1155         LOG_ERROR("subscribe failed.");
1156         return errCode;
1157     }
1158     observers_[event].push_back(std::move(localStoreObserver));
1159     return E_OK;
1160 }
1161 
Unsubscribe(const std::string & event,const std::shared_ptr<RdbStoreObserver> & observer)1162 int32_t SqliteConnection::Unsubscribe(const std::string &event, const std::shared_ptr<RdbStoreObserver> &observer)
1163 {
1164     if (!isWriter_) {
1165         return E_OK;
1166     }
1167     if (observer) {
1168         return UnsubscribeLocalDetail(event, observer);
1169     }
1170     return UnsubscribeLocalDetailAll(event);
1171 }
1172 
UnsubscribeLocalDetail(const std::string & event,const std::shared_ptr<RdbStoreObserver> & observer)1173 int32_t SqliteConnection::UnsubscribeLocalDetail(const std::string &event,
1174     const std::shared_ptr<RdbStoreObserver> &observer)
1175 {
1176     std::lock_guard<std::mutex> lock(mutex_);
1177     auto observers = observers_.find(event);
1178     if (observers == observers_.end()) {
1179         return E_OK;
1180     }
1181 
1182     auto &list = observers->second;
1183     for (auto it = list.begin(); it != list.end(); it++) {
1184         if ((*it)->GetObserver() == observer) {
1185             int32_t err = UnregisterStoreObserver(dbHandle_, *it);
1186             if (err != 0) {
1187                 LOG_ERROR("unsubscribeLocalShared failed.");
1188                 return err;
1189             }
1190             list.erase(it);
1191             break;
1192         }
1193     }
1194     if (list.empty()) {
1195         observers_.erase(event);
1196     }
1197     return E_OK;
1198 }
1199 
UnsubscribeLocalDetailAll(const std::string & event)1200 int32_t SqliteConnection::UnsubscribeLocalDetailAll(const std::string &event)
1201 {
1202     std::lock_guard<std::mutex> lock(mutex_);
1203     auto observers = observers_.find(event);
1204     if (observers == observers_.end()) {
1205         return E_OK;
1206     }
1207 
1208     auto &list = observers->second;
1209     auto it = list.begin();
1210     while (it != list.end()) {
1211         int32_t err = UnregisterStoreObserver(dbHandle_, *it);
1212         if (err != 0) {
1213             LOG_ERROR("unsubscribe failed.");
1214             return err;
1215         }
1216         it = list.erase(it);
1217     }
1218 
1219     observers_.erase(event);
1220     return E_OK;
1221 }
1222 
Backup(const std::string & databasePath,const std::vector<uint8_t> & destEncryptKey,bool isAsync,SlaveStatus & slaveStatus)1223 int32_t SqliteConnection::Backup(const std::string &databasePath, const std::vector<uint8_t> &destEncryptKey,
1224     bool isAsync, SlaveStatus &slaveStatus)
1225 {
1226     if (slaveStatus == SlaveStatus::BACKING_UP) {
1227         LOG_INFO("backing up, return:%{public}s", config_.GetName().c_str());
1228         return E_OK;
1229     }
1230     LOG_INFO("begin backup to slave:%{public}s, isAsync:%{public}d",
1231         SqliteUtils::Anonymous(databasePath).c_str(), isAsync);
1232     if (!isAsync) {
1233         if (slaveConnection_ == nullptr) {
1234             RdbStoreConfig rdbSlaveStoreConfig = GetSlaveRdbStoreConfig(config_);
1235             int errCode = CreateSlaveConnection(rdbSlaveStoreConfig, false);
1236             if (errCode != E_OK) {
1237                 LOG_ERROR("manual slave conn failed:%{public}d", errCode);
1238                 return errCode;
1239             }
1240         }
1241         return ExchangeSlaverToMaster(false, slaveStatus);
1242     }
1243 
1244     if (backupId_ == TaskExecutor::INVALID_TASK_ID) {
1245         auto pool = TaskExecutor::GetInstance().GetExecutor();
1246         if (pool == nullptr) {
1247             LOG_WARN("task pool err when restore");
1248             return E_OK;
1249         }
1250         backupId_ = pool->Execute([this, &slaveStatus]() {
1251             auto [err, conn] = InnerCreate(config_, true);
1252             if (err != E_OK) {
1253                 return;
1254             }
1255             err = conn->ExchangeSlaverToMaster(false, slaveStatus);
1256             if (err != E_OK) {
1257                 LOG_WARN("master backup to slave failed:%{public}d", err);
1258             }
1259             backupId_ = TaskExecutor::INVALID_TASK_ID;
1260         });
1261     }
1262     return E_OK;
1263 }
1264 
Restore(const std::string & databasePath,const std::vector<uint8_t> & destEncryptKey,SlaveStatus & slaveStatus)1265 int32_t SqliteConnection::Restore(const std::string &databasePath, const std::vector<uint8_t> &destEncryptKey,
1266     SlaveStatus &slaveStatus)
1267 {
1268     LOG_INFO("begin to restore from slave:%{public}s", SqliteUtils::Anonymous(databasePath).c_str());
1269     return ExchangeSlaverToMaster(true, slaveStatus);
1270 };
1271 
LoadExtension(const RdbStoreConfig & config,sqlite3 * dbHandle)1272 int SqliteConnection::LoadExtension(const RdbStoreConfig &config, sqlite3 *dbHandle)
1273 {
1274     if (config.GetPluginLibs().empty() || dbHandle == nullptr) {
1275         return E_OK;
1276     }
1277     if (config.GetPluginLibs().size() > SqliteUtils::MAX_LOAD_EXTENSION_COUNT) {
1278         LOG_ERROR("failed, size %{public}zu is too large", config.GetPluginLibs().size());
1279         return E_INVALID_ARGS;
1280     }
1281     int err = sqlite3_db_config(dbHandle, SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, SqliteUtils::ENABLE_LOAD_EXTENSION,
1282         nullptr);
1283     if (err != SQLITE_OK) {
1284         LOG_ERROR("enable failed, err=%{public}d, errno=%{public}d", err, errno);
1285         return SQLiteError::ErrNo(err);
1286     }
1287     for (auto &path : config.GetPluginLibs()) {
1288         if (path.empty()) {
1289             continue;
1290         }
1291         if (access(path.c_str(), F_OK) != 0) {
1292             LOG_ERROR("no file, errno:%{public}d %{public}s", errno, SqliteUtils::Anonymous(path).c_str());
1293             return E_INVALID_FILE_PATH;
1294         }
1295         err = sqlite3_load_extension(dbHandle, path.c_str(), nullptr, nullptr);
1296         if (err != SQLITE_OK) {
1297             LOG_ERROR("load error. err=%{public}d, errno=%{public}d, errmsg:%{public}s, lib=%{public}s", err, errno,
1298                 sqlite3_errmsg(dbHandle), SqliteUtils::Anonymous(path).c_str());
1299             break;
1300         }
1301     }
1302     int ret = sqlite3_db_config(dbHandle, SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, SqliteUtils::DISABLE_LOAD_EXTENSION,
1303         nullptr);
1304     if (ret != SQLITE_OK) {
1305         LOG_ERROR("disable failed, err=%{public}d, errno=%{public}d", err, errno);
1306     }
1307     return SQLiteError::ErrNo(err == SQLITE_OK ? ret : err);
1308 }
1309 
SetServiceKey(const RdbStoreConfig & config,int32_t errCode)1310 int SqliteConnection::SetServiceKey(const RdbStoreConfig &config, int32_t errCode)
1311 {
1312     DistributedRdb::RdbSyncerParam param;
1313     param.bundleName_ = config.GetBundleName();
1314     param.hapName_ = config.GetModuleName();
1315     param.storeName_ = config.GetName();
1316     param.customDir_ = config.GetCustomDir();
1317     param.area_ = config.GetArea();
1318     param.level_ = static_cast<int32_t>(config.GetSecurityLevel());
1319     param.type_ = config.GetDistributedType();
1320     param.isEncrypt_ = config.IsEncrypt();
1321     param.isAutoClean_ = config.GetAutoClean();
1322     param.isSearchable_ = config.IsSearchable();
1323     param.haMode_ = config.GetHaMode();
1324     param.password_ = {};
1325     std::vector<uint8_t> key;
1326 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM)
1327     auto [svcErr, service] = DistributedRdb::RdbManagerImpl::GetInstance().GetRdbService(param);
1328     if (svcErr != E_OK) {
1329         return errCode;
1330     }
1331     svcErr = service->GetPassword(param, key);
1332     if (svcErr != RDB_OK) {
1333         return errCode;
1334     }
1335 #endif
1336 
1337     errCode = SetEncryptKey(key, config);
1338     if (errCode == E_OK) {
1339         config.RestoreEncryptKey(key);
1340     }
1341     key.assign(key.size(), 0);
1342     return errCode;
1343 }
1344 
ExchangeSlaverToMaster(bool isRestore,SlaveStatus & curStatus)1345 int SqliteConnection::ExchangeSlaverToMaster(bool isRestore, SlaveStatus &curStatus)
1346 {
1347     curStatus = SlaveStatus::BACKING_UP;
1348     auto err = ExchangeVerify(isRestore);
1349     if (err != E_OK) {
1350         curStatus = SlaveStatus::UNDEFINED;
1351         return err;
1352     }
1353 
1354     sqlite3 *dbFrom = isRestore ? dbHandle_ : slaveConnection_->dbHandle_;
1355     sqlite3 *dbTo = isRestore ? slaveConnection_->dbHandle_ : dbHandle_;
1356     sqlite3_backup *pBackup = sqlite3_backup_init(dbFrom, "main", dbTo, "main");
1357     if (pBackup == nullptr) {
1358         LOG_WARN("slave backup init failed");
1359         curStatus = SlaveStatus::UNDEFINED;
1360         return E_OK;
1361     }
1362     int rc = SQLITE_OK;
1363     do {
1364         if (!isRestore && curStatus == SlaveStatus::BACKUP_INTERRUPT) {
1365             LOG_INFO("backup slave was interrupt!");
1366             rc = E_BACKUP_INTERRUPT;
1367             break;
1368         }
1369         rc = sqlite3_backup_step(pBackup, BACKUP_PAGES_PRE_STEP);
1370         LOG_INFO("backup slave process cur/total:%{public}d/%{public}d, rs:%{public}d, isRestore:%{public}d",
1371             sqlite3_backup_pagecount(pBackup) - sqlite3_backup_remaining(pBackup), sqlite3_backup_pagecount(pBackup),
1372             rc, isRestore);
1373         if (!isRestore) {
1374             sqlite3_sleep(BACKUP_PRE_WAIT_TIME);
1375         }
1376     } while (sqlite3_backup_pagecount(pBackup) != 0 && (rc == SQLITE_OK || rc == SQLITE_BUSY || rc == SQLITE_LOCKED));
1377     (void)sqlite3_backup_finish(pBackup);
1378     if (rc != SQLITE_DONE) {
1379         LOG_ERROR("backup slave err:%{public}d, isRestore:%{public}d", rc, isRestore);
1380         if (!isRestore) {
1381             RdbStoreConfig slaveConfig(slaveConnection_->config_.GetPath());
1382             if (rc != SQLITE_BUSY && rc != SQLITE_LOCKED) {
1383                 slaveConnection_ = nullptr;
1384                 (void)SqliteConnection::Delete(slaveConfig);
1385             }
1386             curStatus = SlaveStatus::BACKUP_INTERRUPT;
1387         }
1388         return rc == E_BACKUP_INTERRUPT ? E_BACKUP_INTERRUPT : SQLiteError::ErrNo(rc);
1389     }
1390     rc = isRestore ? TryCheckPoint(true) : slaveConnection_->TryCheckPoint(true);
1391     if (rc != E_OK && config_.GetHaMode() == HAMode::MANUAL_TRIGGER) {
1392         if (!isRestore) {
1393             curStatus = SlaveStatus::BACKUP_INTERRUPT;
1394         }
1395         LOG_WARN("CheckPoint failed err:%{public}d, isRestore:%{public}d", rc, isRestore);
1396         return E_OK;
1397     }
1398     curStatus = SlaveStatus::BACKUP_FINISHED;
1399     SqliteUtils::TryAccessSlaveLock(config_.GetPath(), true, false);
1400     SqliteUtils::TryAccessSlaveLock(config_.GetPath(), true, false, true);
1401     LOG_INFO("backup slave success, isRestore:%{public}d", isRestore);
1402     return E_OK;
1403 }
1404 
GenerateExchangeStrategy(const SlaveStatus & status)1405 ExchangeStrategy SqliteConnection::GenerateExchangeStrategy(const SlaveStatus &status)
1406 {
1407     if (dbHandle_ == nullptr || slaveConnection_ == nullptr || slaveConnection_->dbHandle_ == nullptr ||
1408         config_.GetHaMode() == HAMode::SINGLE || status == SlaveStatus::BACKING_UP) {
1409         return ExchangeStrategy::NOT_HANDLE;
1410     }
1411     static const std::string querySql = "SELECT COUNT(*) FROM sqlite_master WHERE type='table';";
1412     auto [mRet, mObj] = ExecuteForValue(querySql);
1413     if (mRet != E_OK) {
1414         LOG_WARN("main abnormal, err:%{public}d", mRet);
1415         return ExchangeStrategy::RESTORE;
1416     }
1417     int64_t mCount = static_cast<int64_t>(mObj);
1418     // trigger mode only does restore, not backup
1419     if (config_.GetHaMode() == HAMode::MANUAL_TRIGGER) {
1420         return mCount == 0 ? ExchangeStrategy::RESTORE : ExchangeStrategy::NOT_HANDLE;
1421     }
1422     auto [sRet, sObj] = slaveConnection_->ExecuteForValue(querySql);
1423     if (sRet != E_OK) {
1424         LOG_WARN("slave db abnormal, need backup, err:%{public}d", sRet);
1425         return ExchangeStrategy::BACKUP;
1426     }
1427     if (status == SlaveStatus::DB_NOT_EXITS || status == SlaveStatus::BACKUP_INTERRUPT) {
1428         return ExchangeStrategy::BACKUP;
1429     }
1430     int64_t sCount = static_cast<int64_t>(sObj);
1431     std::string failureFlagFile = config_.GetPath() + "-slaveFailure";
1432     if (mCount == sCount && access(failureFlagFile.c_str(), F_OK) != 0) {
1433         LOG_INFO("equal, main:%{public}" PRId64 ",slave:%{public}" PRId64, mCount, sCount);
1434         return ExchangeStrategy::NOT_HANDLE;
1435     }
1436     if (mCount == 0) {
1437         LOG_INFO("main empty, main:%{public}" PRId64 ",slave:%{public}" PRId64, mCount, sCount);
1438         return ExchangeStrategy::RESTORE;
1439     }
1440     LOG_INFO("backup, main:%{public}" PRId64 ",slave:%{public}" PRId64, mCount, sCount);
1441     return ExchangeStrategy::BACKUP;
1442 }
1443 
Repair(const RdbStoreConfig & config)1444 int32_t SqliteConnection::Repair(const RdbStoreConfig &config)
1445 {
1446     if (config.GetHaMode() != MAIN_REPLICA && config.GetHaMode() != MANUAL_TRIGGER) {
1447         return E_NOT_SUPPORT;
1448     }
1449     std::shared_ptr<SqliteConnection> connection = std::make_shared<SqliteConnection>(config, true);
1450     if (connection == nullptr) {
1451         return E_NOT_SUPPORT;
1452     }
1453     RdbStoreConfig rdbSlaveStoreConfig = connection->GetSlaveRdbStoreConfig(config);
1454     int ret = connection->CreateSlaveConnection(rdbSlaveStoreConfig);
1455     if (ret != E_OK) {
1456         return ret;
1457     }
1458     ret = connection->IsRepairable();
1459     if (ret != E_OK) {
1460         return ret;
1461     }
1462     LOG_WARN("begin repair main:%{public}s", SqliteUtils::Anonymous(config.GetPath()).c_str());
1463     (void)SqliteConnection::Delete(config);
1464     ret = connection->InnerOpen(config);
1465     if (ret != E_OK) {
1466         LOG_ERROR("reopen db failed, err:%{public}d", ret);
1467         return ret;
1468     }
1469     connection->TryCheckPoint(true);
1470     SlaveStatus curStatus;
1471     ret = connection->ExchangeSlaverToMaster(true, curStatus);
1472     if (ret != E_OK) {
1473         LOG_ERROR("repair failed, [%{public}s]->[%{public}s], err:%{public}d", rdbSlaveStoreConfig.GetName().c_str(),
1474             SqliteUtils::Anonymous(config.GetName()).c_str(), ret);
1475     } else {
1476         LOG_INFO("repair main success:%{public}s", SqliteUtils::Anonymous(config.GetPath()).c_str());
1477     }
1478     connection->slaveConnection_ = nullptr;
1479     connection = nullptr;
1480     return ret;
1481 }
1482 
IsRepairable()1483 int SqliteConnection::IsRepairable()
1484 {
1485     if (slaveConnection_ == nullptr || slaveConnection_->dbHandle_ == nullptr) {
1486         return E_STORE_CLOSED;
1487     }
1488     if (SqliteUtils::TryAccessSlaveLock(config_.GetPath(), false, false, false)) {
1489         LOG_ERROR("unavailable slave, %{public}s", config_.GetName().c_str());
1490         return E_DB_RESTORE_NOT_ALLOWED;
1491     }
1492     std::string querySql = "SELECT COUNT(*) FROM sqlite_master WHERE type='table';";
1493     auto [qRet, qObj] = slaveConnection_->ExecuteForValue(querySql);
1494     if (qRet != E_OK || (static_cast<int64_t>(qObj) == 0L)) {
1495         LOG_INFO("cancel repair, ret:%{public}d", qRet);
1496         return E_DB_RESTORE_NOT_ALLOWED;
1497     }
1498     return E_OK;
1499 }
1500 
ExchangeVerify(bool isRestore)1501 int SqliteConnection::ExchangeVerify(bool isRestore)
1502 {
1503     if (dbHandle_ == nullptr || slaveConnection_ == nullptr || slaveConnection_->dbHandle_ == nullptr) {
1504         LOG_WARN("slave conn invalid");
1505         return E_STORE_CLOSED;
1506     }
1507     if (access(config_.GetPath().c_str(), F_OK) != 0) {
1508         LOG_WARN("main no exist, isR:%{public}d, %{public}s", isRestore, config_.GetName().c_str());
1509         return E_DB_NOT_EXIST;
1510     }
1511     if (isRestore) {
1512         int err = IsRepairable();
1513         if (err != E_OK) {
1514             return err;
1515         }
1516         auto [cRet, cObj] = slaveConnection_->ExecuteForValue(INTEGRITIES[2]); // 2 is integrity_check
1517         if (cRet != E_OK || (static_cast<std::string>(cObj) != "ok")) {
1518             LOG_ERROR("slave may corrupt, cancel, ret:%{public}s, cRet:%{public}d",
1519                 static_cast<std::string>(cObj).c_str(), cRet);
1520             return E_SQLITE_CORRUPT;
1521         }
1522         std::string querySql = "SELECT COUNT(*) FROM sqlite_master WHERE type='table';";
1523         std::tie(cRet, cObj) = ExecuteForValue(querySql);
1524         if (cRet == E_OK && (static_cast<int64_t>(cObj) == 0L)) {
1525             LOG_INFO("main empty, need restore, %{public}s", config_.GetName().c_str());
1526             return E_OK;
1527         }
1528         if (SqliteUtils::TryAccessSlaveLock(config_.GetPath(), false, false, true)) {
1529             LOG_ERROR("incomplete slave, %{public}s", config_.GetName().c_str());
1530             return E_DB_RESTORE_NOT_ALLOWED;
1531         }
1532     } else {
1533         auto [cRet, cObj] = ExecuteForValue(INTEGRITIES[1]); // 1 is quick_check
1534         if (cRet != E_OK || (static_cast<std::string>(cObj) != "ok")) {
1535             LOG_ERROR("main corrupt, cancel, ret:%{public}s, qRet:%{public}d",
1536                 static_cast<std::string>(cObj).c_str(), cRet);
1537             return E_SQLITE_CORRUPT;
1538         }
1539         if (!SqliteUtils::TryAccessSlaveLock(config_.GetPath(), false, true)) {
1540             LOG_WARN("try create slave lock failed! isRestore:%{public}d", isRestore);
1541         }
1542     }
1543     return E_OK;
1544 }
1545 
InnerCreate(const RdbStoreConfig & config,bool isWrite)1546 std::pair<int32_t, std::shared_ptr<SqliteConnection>> SqliteConnection::InnerCreate(const RdbStoreConfig &config,
1547     bool isWrite)
1548 {
1549     std::pair<int32_t, std::shared_ptr<SqliteConnection>> result = { E_ERROR, nullptr };
1550     auto &[errCode, conn] = result;
1551     std::shared_ptr<SqliteConnection> connection = std::make_shared<SqliteConnection>(config, isWrite);
1552     if (connection == nullptr) {
1553         LOG_ERROR("connection is nullptr.");
1554         return result;
1555     }
1556 
1557     RdbStoreConfig slaveCfg = connection->GetSlaveRdbStoreConfig(config);
1558     errCode = connection->InnerOpen(config);
1559     if (errCode != E_OK) {
1560         return result;
1561     }
1562     conn = connection;
1563     if (isWrite) {
1564         (void)connection->CreateSlaveConnection(slaveCfg, isWrite);
1565     }
1566     return result;
1567 }
1568 } // namespace NativeRdb
1569 } // namespace OHOS