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