mirror of
https://gitee.com/openharmony/distributeddatamgr_relational_store
synced 2025-02-17 00:39:02 +00:00
同步代码
Signed-off-by: Yuanbo Feng <fengyuanbo2@huawei.com>
This commit is contained in:
commit
92352bb9bc
@ -22,6 +22,7 @@
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "rdb_common.h"
|
||||
#include "rdb_types.h"
|
||||
#include "statement.h"
|
||||
namespace OHOS::NativeRdb {
|
||||
@ -63,11 +64,10 @@ public:
|
||||
virtual int32_t Unsubscribe(const std::string &event,
|
||||
const std::shared_ptr<DistributedRdb::RdbStoreObserver> &observer) = 0;
|
||||
virtual int32_t Backup(const std::string &databasePath, const std::vector<uint8_t> &destEncryptKey,
|
||||
bool isAsync = false) = 0;
|
||||
virtual int32_t Restore(const std::string &databasePath, const std::vector<uint8_t> &destEncryptKey) = 0;
|
||||
virtual int32_t InterruptBackup() = 0;
|
||||
virtual int32_t GetBackupStatus() const = 0;
|
||||
virtual std::pair<bool, bool> IsExchange(const RdbStoreConfig &config) = 0;
|
||||
bool isAsync, SlaveStatus &slaveStatus) = 0;
|
||||
virtual int32_t Restore(const std::string &databasePath, const std::vector<uint8_t> &destEncryptKey,
|
||||
SlaveStatus &slaveStatus) = 0;
|
||||
virtual ExchangeStrategy GenerateExchangeStrategy(const SlaveStatus &status) = 0;
|
||||
|
||||
private:
|
||||
int32_t id_ = 0;
|
||||
|
@ -53,7 +53,7 @@ public:
|
||||
int RestartReaders();
|
||||
int ConfigLocale(const std::string &localeStr);
|
||||
int ChangeDbFileForRestore(const std::string &newPath, const std::string &backupPath,
|
||||
const std::vector<uint8_t> &newKey);
|
||||
const std::vector<uint8_t> &newKey, SlaveStatus &slaveStatus);
|
||||
std::stack<BaseTransaction> &GetTransactionStack();
|
||||
std::mutex &GetTransactionStackMutex();
|
||||
int AcquireTransaction();
|
||||
@ -115,7 +115,7 @@ private:
|
||||
int32_t GetMaxReaders(const RdbStoreConfig &config);
|
||||
std::shared_ptr<Connection> Convert2AutoConn(std::shared_ptr<ConnNode> node);
|
||||
void ReleaseNode(std::shared_ptr<ConnNode> node);
|
||||
int RestoreByDbSqliteType(const std::string &newPath, const std::string &backupPath);
|
||||
int RestoreByDbSqliteType(const std::string &newPath, const std::string &backupPath, SlaveStatus &slaveStatus);
|
||||
|
||||
static constexpr int LIMITATION = 1024;
|
||||
static constexpr uint32_t ITER_V1 = 5000;
|
||||
|
@ -55,11 +55,10 @@ public:
|
||||
int32_t Unsubscribe(const std::string& event,
|
||||
const std::shared_ptr<DistributedRdb::RdbStoreObserver>& observer) override;
|
||||
int32_t Backup(const std::string &databasePath, const std::vector<uint8_t> &destEncryptKey,
|
||||
bool isAsync = false) override;
|
||||
int32_t Restore(const std::string &databasePath, const std::vector<uint8_t> &destEncryptKey) override;
|
||||
int32_t InterruptBackup() override;
|
||||
int32_t GetBackupStatus() const override;
|
||||
std::pair<bool, bool> IsExchange(const RdbStoreConfig &config) override;
|
||||
bool isAsync, SlaveStatus &slaveStatus) override;
|
||||
int32_t Restore(const std::string &databasePath, const std::vector<uint8_t> &destEncryptKey,
|
||||
SlaveStatus &slaveStatus) override;
|
||||
ExchangeStrategy GenerateExchangeStrategy(const SlaveStatus &status) override;
|
||||
|
||||
private:
|
||||
static constexpr int MAX_VARIABLE_NUM = 500;
|
||||
|
@ -132,6 +132,7 @@ public:
|
||||
bool IsReadOnly() const override;
|
||||
bool IsMemoryRdb() const override;
|
||||
bool IsHoldingConnection() override;
|
||||
bool IsSlaveDiffFromMaster() const override;
|
||||
int ConfigLocale(const std::string &localeStr);
|
||||
int Restore(const std::string &backupPath, const std::vector<uint8_t> &newKey) override;
|
||||
std::string GetName();
|
||||
@ -189,6 +190,7 @@ public:
|
||||
int ModifyLockStatus(const AbsRdbPredicates &predicates, bool isLock) override;
|
||||
int InterruptBackup() override;
|
||||
int32_t GetDbType() const override;
|
||||
int32_t ExchangeSlaverToMaster();
|
||||
void AfterOpen(const RdbStoreConfig &config);
|
||||
std::pair<int32_t, uint32_t> LockCloudContainer() override;
|
||||
int32_t UnlockCloudContainer() override;
|
||||
@ -289,6 +291,7 @@ private:
|
||||
std::map<std::string, std::list<sptr<RdbStoreLocalSharedObserver>>> localSharedObservers_;
|
||||
ConcurrentMap<std::string, std::string> attachedInfo_;
|
||||
uint32_t rebuild_;
|
||||
SlaveStatus slaveStatus_;
|
||||
};
|
||||
} // namespace OHOS::NativeRdb
|
||||
#endif
|
||||
|
@ -24,7 +24,6 @@
|
||||
#include <vector>
|
||||
|
||||
#include "connection.h"
|
||||
#include "rdb_common.h"
|
||||
#include "rdb_local_db_observer.h"
|
||||
#include "rdb_store_config.h"
|
||||
#include "sqlite3sym.h"
|
||||
@ -65,11 +64,10 @@ public:
|
||||
int32_t Unsubscribe(const std::string &event,
|
||||
const std::shared_ptr<DistributedRdb::RdbStoreObserver> &observer) override;
|
||||
int32_t Backup(const std::string &databasePath, const std::vector<uint8_t> &destEncryptKey,
|
||||
bool isAsync = false) override;
|
||||
int32_t Restore(const std::string &databasePath, const std::vector<uint8_t> &destEncryptKey) override;
|
||||
int32_t InterruptBackup() override;
|
||||
int32_t GetBackupStatus() const override;
|
||||
std::pair<bool, bool> IsExchange(const RdbStoreConfig &config) override;
|
||||
bool isAsync, SlaveStatus &slaveStatus) override;
|
||||
int32_t Restore(const std::string &databasePath, const std::vector<uint8_t> &destEncryptKey,
|
||||
SlaveStatus &slaveStatus) override;
|
||||
ExchangeStrategy GenerateExchangeStrategy(const SlaveStatus &status) override;
|
||||
|
||||
protected:
|
||||
std::pair<int32_t, ValueObject> ExecuteForValue(const std::string &sql,
|
||||
@ -112,13 +110,16 @@ private:
|
||||
int LoadExtension(const RdbStoreConfig &config, sqlite3 *dbHandle);
|
||||
RdbStoreConfig GetSlaveRdbStoreConfig(const RdbStoreConfig rdbConfig);
|
||||
int CreateSlaveConnection(const RdbStoreConfig &config, bool isWrite, bool checkSlaveExist = true);
|
||||
int MasterSlaveExchange(bool isRestore = false);
|
||||
bool IsRepairable();
|
||||
std::pair<bool, int> ExchangeVerify(bool isRestore);
|
||||
int ExchangeSlaverToMaster(bool isRestore, SlaveStatus &status);
|
||||
int IsRepairable();
|
||||
int ExchangeVerify(bool isRestore);
|
||||
static std::pair<int32_t, std::shared_ptr<SqliteConnection>> InnerCreate(const RdbStoreConfig &config,
|
||||
bool isWrite);
|
||||
void ReportDbCorruptedEvent(int errCode, const std::string &checkResultInfo);
|
||||
|
||||
static constexpr int DEFAULT_BUSY_TIMEOUT_MS = 2000;
|
||||
static constexpr int BACKUP_PAGES_PRE_STEP = 12800; // 1024 * 4 * 12800 == 50m
|
||||
static constexpr int BACKUP_PRE_WAIT_TIME = 10;
|
||||
static constexpr uint32_t NO_ITER = 0;
|
||||
static const int32_t regCreator_;
|
||||
static const int32_t regRepairer_;
|
||||
|
@ -58,7 +58,8 @@ public:
|
||||
static int GetFileSize(const std::string &fileName);
|
||||
static bool IsSlaveDbName(const std::string &fileName);
|
||||
static std::string GetSlavePath(const std::string& name);
|
||||
static bool TryAccessSlaveLock(const std::string &dbPath, bool isDelete, bool needCreate);
|
||||
static bool TryAccessSlaveLock(const std::string &dbPath, bool isDelete, bool needCreate,
|
||||
bool isSlaveFailure = false);
|
||||
|
||||
private:
|
||||
struct SqlType {
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "rdb_common.h"
|
||||
#include "rdb_types.h"
|
||||
#include "statement.h"
|
||||
namespace OHOS::NativeRdb {
|
||||
@ -63,11 +64,10 @@ public:
|
||||
virtual int32_t Unsubscribe(const std::string &event,
|
||||
const std::shared_ptr<DistributedRdb::RdbStoreObserver> &observer) = 0;
|
||||
virtual int32_t Backup(const std::string &databasePath, const std::vector<uint8_t> &destEncryptKey,
|
||||
bool isAsync = false) = 0;
|
||||
virtual int32_t Restore(const std::string &databasePath, const std::vector<uint8_t> &destEncryptKey) = 0;
|
||||
virtual int32_t InterruptBackup() = 0;
|
||||
virtual int32_t GetBackupStatus() const = 0;
|
||||
virtual std::pair<bool, bool> IsExchange(const RdbStoreConfig &config) = 0;
|
||||
bool isAsync, SlaveStatus &slaveStatus) = 0;
|
||||
virtual int32_t Restore(const std::string &databasePath, const std::vector<uint8_t> &destEncryptKey,
|
||||
SlaveStatus &slaveStatus) = 0;
|
||||
virtual ExchangeStrategy GenerateExchangeStrategy(const SlaveStatus &status) = 0;
|
||||
|
||||
private:
|
||||
int32_t id_ = 0;
|
||||
|
@ -53,7 +53,7 @@ public:
|
||||
int RestartReaders();
|
||||
int ConfigLocale(const std::string &localeStr);
|
||||
int ChangeDbFileForRestore(const std::string &newPath, const std::string &backupPath,
|
||||
const std::vector<uint8_t> &newKey);
|
||||
const std::vector<uint8_t> &newKey, SlaveStatus &slaveStatus);
|
||||
std::stack<BaseTransaction> &GetTransactionStack();
|
||||
std::mutex &GetTransactionStackMutex();
|
||||
int AcquireTransaction();
|
||||
@ -115,7 +115,7 @@ private:
|
||||
int32_t GetMaxReaders(const RdbStoreConfig &config);
|
||||
std::shared_ptr<Connection> Convert2AutoConn(std::shared_ptr<ConnNode> node);
|
||||
void ReleaseNode(std::shared_ptr<ConnNode> node);
|
||||
int RestoreByDbSqliteType(const std::string &newPath, const std::string &backupPath);
|
||||
int RestoreByDbSqliteType(const std::string &newPath, const std::string &backupPath, SlaveStatus &slaveStatus);
|
||||
|
||||
static constexpr int LIMITATION = 1024;
|
||||
static constexpr uint32_t ITER_V1 = 5000;
|
||||
|
@ -83,6 +83,7 @@ public:
|
||||
bool IsReadOnly() const override;
|
||||
bool IsMemoryRdb() const override;
|
||||
bool IsHoldingConnection() override;
|
||||
bool IsSlaveDiffFromMaster() const override;
|
||||
int ConfigLocale(const std::string &localeStr);
|
||||
int Restore(const std::string &backupPath, const std::vector<uint8_t> &newKey) override;
|
||||
std::string GetName();
|
||||
@ -101,6 +102,7 @@ public:
|
||||
int GetRebuilt(RebuiltType &rebuilt) override;
|
||||
int InterruptBackup() override;
|
||||
int32_t GetBackupStatus() const override;
|
||||
int32_t ExchangeSlaverToMaster();
|
||||
std::pair<int32_t, int32_t> Attach(
|
||||
const RdbStoreConfig &config, const std::string &attachName, int32_t waitTime = 2) override;
|
||||
std::pair<int32_t, int32_t> Detach(const std::string &attachName, int32_t waitTime = 2) override;
|
||||
@ -166,6 +168,7 @@ private:
|
||||
std::shared_ptr<ConnectionPool> connectionPool_;
|
||||
ConcurrentMap<std::string, std::string> attachedInfo_;
|
||||
uint32_t rebuild_;
|
||||
SlaveStatus slaveStatus_;
|
||||
};
|
||||
} // namespace OHOS::NativeRdb
|
||||
#endif
|
||||
|
@ -24,7 +24,6 @@
|
||||
#include <vector>
|
||||
|
||||
#include "connection.h"
|
||||
#include "rdb_common.h"
|
||||
#include "rdb_local_db_observer.h"
|
||||
#include "rdb_store_config.h"
|
||||
#include "sqlite3sym.h"
|
||||
@ -65,11 +64,11 @@ public:
|
||||
int32_t Unsubscribe(const std::string &event,
|
||||
const std::shared_ptr<DistributedRdb::RdbStoreObserver> &observer) override;
|
||||
int32_t Backup(const std::string &databasePath, const std::vector<uint8_t> &destEncryptKey,
|
||||
bool isAsync = false) override;
|
||||
int32_t Restore(const std::string &databasePath, const std::vector<uint8_t> &destEncryptKey) override;
|
||||
int32_t InterruptBackup() override;
|
||||
int32_t GetBackupStatus() const override;
|
||||
std::pair<bool, bool> IsExchange(const RdbStoreConfig &config) override;
|
||||
bool isAsync, SlaveStatus &slaveStatus) override;
|
||||
int32_t Restore(const std::string &databasePath, const std::vector<uint8_t> &destEncryptKey,
|
||||
SlaveStatus &slaveStatus) override;
|
||||
ExchangeStrategy GenerateExchangeStrategy(const SlaveStatus &status) override;
|
||||
|
||||
|
||||
|
||||
protected:
|
||||
@ -114,13 +113,16 @@ private:
|
||||
int LoadExtension(const RdbStoreConfig &config, sqlite3 *dbHandle);
|
||||
RdbStoreConfig GetSlaveRdbStoreConfig(const RdbStoreConfig rdbConfig);
|
||||
int CreateSlaveConnection(const RdbStoreConfig &config, bool isWrite, bool checkSlaveExist = false);
|
||||
int MasterSlaveExchange(bool isRestore = false);
|
||||
bool IsRepairable();
|
||||
std::pair<bool, int> ExchangeVerify(bool isRestore);
|
||||
int ExchangeSlaverToMaster(bool isRestore, SlaveStatus &status);
|
||||
int IsRepairable();
|
||||
int ExchangeVerify(bool isRestore);
|
||||
static std::pair<int32_t, std::shared_ptr<SqliteConnection>> InnerCreate(const RdbStoreConfig &config,
|
||||
bool isWrite);
|
||||
void ReportDbCorruptedEvent(int errCode, const std::string &checkResultInfo);
|
||||
|
||||
static constexpr int DEFAULT_BUSY_TIMEOUT_MS = 2000;
|
||||
static constexpr int BACKUP_PAGES_PRE_STEP = 12800; // 1024 * 4 * 12800 == 50m
|
||||
static constexpr int BACKUP_PRE_WAIT_TIME = 10;
|
||||
static constexpr uint32_t NO_ITER = 0;
|
||||
static const int32_t regCreator_;
|
||||
static const int32_t regRepairer_;
|
||||
|
@ -326,7 +326,7 @@ int ConnPool::ConfigLocale(const std::string &localeStr)
|
||||
* Rename the backed up database.
|
||||
*/
|
||||
int ConnPool::ChangeDbFileForRestore(const std::string &newPath, const std::string &backupPath,
|
||||
const std::vector<uint8_t> &newKey)
|
||||
const std::vector<uint8_t> &newKey, SlaveStatus &slaveStatus)
|
||||
{
|
||||
if (!writers_.IsFull() || config_.GetPath() == backupPath || newPath == backupPath) {
|
||||
LOG_ERROR("Connection pool is busy now!");
|
||||
@ -340,8 +340,7 @@ int ConnPool::ChangeDbFileForRestore(const std::string &newPath, const std::stri
|
||||
LOG_ERROR("Get null connection.");
|
||||
return retVal;
|
||||
}
|
||||
|
||||
retVal = connection->Restore(backupPath, {});
|
||||
retVal = connection->Restore(backupPath, {}, slaveStatus);
|
||||
if (retVal != E_OK) {
|
||||
LOG_ERROR("RdDbRestore error.");
|
||||
return retVal;
|
||||
@ -350,10 +349,10 @@ int ConnPool::ChangeDbFileForRestore(const std::string &newPath, const std::stri
|
||||
auto [errCode, node] = Init();
|
||||
return errCode;
|
||||
}
|
||||
return RestoreByDbSqliteType(newPath, backupPath);
|
||||
return RestoreByDbSqliteType(newPath, backupPath, slaveStatus);
|
||||
}
|
||||
|
||||
int ConnPool::RestoreByDbSqliteType(const std::string &newPath, const std::string &backupPath)
|
||||
int ConnPool::RestoreByDbSqliteType(const std::string &newPath, const std::string &backupPath, SlaveStatus &slaveStatus)
|
||||
{
|
||||
int ret = E_OK;
|
||||
if (SqliteUtils::IsSlaveDbName(backupPath) && config_.GetHaMode() != HAMode::SINGLE) {
|
||||
@ -361,26 +360,7 @@ int ConnPool::RestoreByDbSqliteType(const std::string &newPath, const std::strin
|
||||
if (connection == nullptr) {
|
||||
return E_DATABASE_BUSY;
|
||||
}
|
||||
ret = connection->Restore(backupPath, {});
|
||||
if (ret == E_SQLITE_CORRUPT && config_.GetAllowRebuild()) {
|
||||
LOG_WARN("corrupt, rebuild:%{public}s", SqliteUtils::Anonymous(backupPath).c_str());
|
||||
CloseAllConnections();
|
||||
Connection::Delete(config_);
|
||||
auto [errCode, node] = Init();
|
||||
if (errCode != E_OK) {
|
||||
LOG_ERROR("init failed:%{public}d", errCode);
|
||||
return errCode;
|
||||
}
|
||||
auto newConn = AcquireConnection(false);
|
||||
if (newConn == nullptr) {
|
||||
return E_DATABASE_BUSY;
|
||||
}
|
||||
ret = newConn->Restore(backupPath, {});
|
||||
if (ret != E_OK) {
|
||||
LOG_ERROR("restore failed:%{public}d, %{public}s", ret, SqliteUtils::Anonymous(backupPath).c_str());
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
return connection->Restore(backupPath, {}, slaveStatus);
|
||||
}
|
||||
CloseAllConnections();
|
||||
Connection::Delete(config_);
|
||||
|
@ -207,7 +207,7 @@ int32_t RdConnection::Unsubscribe(const std::string& event,
|
||||
}
|
||||
|
||||
int32_t RdConnection::Backup(const std::string &databasePath, const std::vector<uint8_t> &destEncryptKey,
|
||||
bool isAsync)
|
||||
bool isAsync, SlaveStatus &slaveStatus)
|
||||
{
|
||||
uint32_t size = destEncryptKey.size();
|
||||
if (size != 0) {
|
||||
@ -216,7 +216,8 @@ int32_t RdConnection::Backup(const std::string &databasePath, const std::vector<
|
||||
return RdUtils::RdDbBackup(dbHandle_, databasePath.c_str(), nullptr, 0);
|
||||
}
|
||||
|
||||
int32_t RdConnection::Restore(const std::string &databasePath, const std::vector<uint8_t> &destEncryptKey)
|
||||
int32_t RdConnection::Restore(const std::string &databasePath, const std::vector<uint8_t> &destEncryptKey,
|
||||
SlaveStatus &slaveStatus)
|
||||
{
|
||||
uint32_t size = destEncryptKey.size();
|
||||
if (size != 0) {
|
||||
@ -225,19 +226,9 @@ int32_t RdConnection::Restore(const std::string &databasePath, const std::vector
|
||||
return RdUtils::RdDbRestore(dbHandle_, databasePath.c_str(), nullptr, 0);
|
||||
}
|
||||
|
||||
int32_t RdConnection::InterruptBackup()
|
||||
ExchangeStrategy RdConnection::GenerateExchangeStrategy(const SlaveStatus &status)
|
||||
{
|
||||
return E_NOT_SUPPORT;
|
||||
}
|
||||
|
||||
int32_t RdConnection::GetBackupStatus() const
|
||||
{
|
||||
return SlaveStatus::UNDEFINED;
|
||||
}
|
||||
|
||||
std::pair<bool, bool> RdConnection::IsExchange(const RdbStoreConfig &config)
|
||||
{
|
||||
return { false, false };
|
||||
return ExchangeStrategy::NOT_HANDLE;
|
||||
}
|
||||
} // namespace NativeRdb
|
||||
} // namespace OHOS
|
@ -481,11 +481,21 @@ bool RdbSecurityManager::LoadSecretKeyFromDisk(const std::string &keyPath, RdbSe
|
||||
}
|
||||
}
|
||||
|
||||
auto size = content.size();
|
||||
auto offset = 0;
|
||||
auto iter = content.begin();
|
||||
if (offset + 1 >= size) {
|
||||
return false;
|
||||
}
|
||||
keyData.distributed = *iter;
|
||||
iter++;
|
||||
offset++;
|
||||
|
||||
std::vector<uint8_t> createTime;
|
||||
if (offset + sizeof(time_t) / sizeof(uint8_t) >= size) {
|
||||
return false;
|
||||
}
|
||||
offset += sizeof(time_t) / sizeof(uint8_t);
|
||||
for (int i = 0; i < static_cast<int>(sizeof(time_t) / sizeof(uint8_t)); i++) {
|
||||
createTime.push_back(*iter);
|
||||
iter++;
|
||||
@ -495,6 +505,10 @@ bool RdbSecurityManager::LoadSecretKeyFromDisk(const std::string &keyPath, RdbSe
|
||||
keyData.timeValue = *reinterpret_cast<time_t *>(&createTime[0]);
|
||||
}
|
||||
|
||||
if (offset + AEAD_LEN >= size) {
|
||||
return false;
|
||||
}
|
||||
offset = size;
|
||||
keyData.secretKey.insert(keyData.secretKey.end(), iter, content.end());
|
||||
|
||||
return true;
|
||||
|
@ -117,6 +117,11 @@ void RdbStoreConfig::SetJournalMode(JournalMode journalMode)
|
||||
this->journalMode_ = GetJournalModeValue(journalMode);
|
||||
}
|
||||
|
||||
void RdbStoreConfig::SetJournalMode(const std::string &journalMode)
|
||||
{
|
||||
this->journalMode_ = journalMode;
|
||||
}
|
||||
|
||||
void RdbStoreConfig::SetDatabaseFileType(DatabaseFileType type)
|
||||
{
|
||||
this->databaseFileType = GetDatabaseFileTypeValue(type);
|
||||
|
@ -313,14 +313,15 @@ int RdbStoreImpl::CleanDirtyData(const std::string &table, uint64_t cursor)
|
||||
RdbStoreImpl::RdbStoreImpl(const RdbStoreConfig &config)
|
||||
: config_(config), isOpen_(false), isReadOnly_(config.IsReadOnly()), isMemoryRdb_(config.IsMemoryRdb()),
|
||||
isEncrypt_(config.IsEncrypt()), path_(config.GetPath()), name_(config.GetName()),
|
||||
fileType_(config.GetDatabaseFileType()), connectionPool_(nullptr), rebuild_(RebuiltType::NONE)
|
||||
fileType_(config.GetDatabaseFileType()), connectionPool_(nullptr), rebuild_(RebuiltType::NONE),
|
||||
slaveStatus_(SlaveStatus::UNDEFINED)
|
||||
{
|
||||
}
|
||||
|
||||
RdbStoreImpl::RdbStoreImpl(const RdbStoreConfig &config, int &errCode)
|
||||
: config_(config), isReadOnly_(config.IsReadOnly()), isMemoryRdb_(config.IsMemoryRdb()),
|
||||
isEncrypt_(config.IsEncrypt()), name_(config.GetName()), fileType_(config.GetDatabaseFileType()),
|
||||
rebuild_(RebuiltType::NONE)
|
||||
rebuild_(RebuiltType::NONE), slaveStatus_(SlaveStatus::UNDEFINED)
|
||||
{
|
||||
path_ = (config.GetRoleType() == VISITOR) ? config.GetVisitorDir() : config.GetPath();
|
||||
connectionPool_ = ConnectionPool::Create(config_, errCode);
|
||||
@ -360,6 +361,8 @@ void RdbStoreImpl::RemoveDbFiles(std::string &path)
|
||||
SqliteUtils::DeleteFile(path + "-shm");
|
||||
SqliteUtils::DeleteFile(path + "-wal");
|
||||
SqliteUtils::DeleteFile(path + "-journal");
|
||||
SqliteUtils::DeleteFile(path + "-slaveFailure");
|
||||
SqliteUtils::DeleteFile(path + "-syncInterrupt");
|
||||
}
|
||||
|
||||
const RdbStoreConfig &RdbStoreImpl::GetConfig()
|
||||
@ -1151,11 +1154,11 @@ int RdbStoreImpl::InnerBackup(const std::string &databasePath, const std::vector
|
||||
if (isEncrypt_) {
|
||||
return E_NOT_SUPPORT;
|
||||
}
|
||||
return conn->Backup(databasePath, {});
|
||||
return conn->Backup(databasePath, {}, false, slaveStatus_);
|
||||
}
|
||||
if (config_.GetHaMode() != HAMode::SINGLE && SqliteUtils::IsSlaveDbName(databasePath)) {
|
||||
auto conn = connectionPool_->AcquireConnection(false);
|
||||
return conn == nullptr ? E_BASE : conn->Backup(databasePath, {});
|
||||
return conn == nullptr ? E_BASE : conn->Backup(databasePath, {}, false, slaveStatus_);
|
||||
}
|
||||
auto [errCode, statement] = GetStatement(GlobalExpr::CIPHER_DEFAULT_ATTACH_HMAC_ALGO, true);
|
||||
if (statement == nullptr) {
|
||||
@ -1771,7 +1774,7 @@ int RdbStoreImpl::Restore(const std::string &backupPath, const std::vector<uint8
|
||||
service->Disable(syncerParam_);
|
||||
}
|
||||
#endif
|
||||
int errCode = connectionPool_->ChangeDbFileForRestore(path_, destPath, newKey);
|
||||
int errCode = connectionPool_->ChangeDbFileForRestore(path_, destPath, newKey, slaveStatus_);
|
||||
#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM)
|
||||
SecurityPolicy::SetSecurityLabel(config_);
|
||||
if (service != nullptr) {
|
||||
@ -1852,10 +1855,11 @@ int RdbStoreImpl::SetDistributedTables(const std::vector<std::string> &tables, i
|
||||
}
|
||||
if (type == DistributedRdb::DISTRIBUTED_CLOUD) {
|
||||
auto conn = connectionPool_->AcquireConnection(false);
|
||||
if (conn == nullptr) {
|
||||
LOG_WARN("acquire conn failed when set distributed.");
|
||||
} else if (conn->IsExchange(config_).first) {
|
||||
(void)conn->Backup({}, {});
|
||||
if (conn != nullptr) {
|
||||
auto strategy = conn->GenerateExchangeStrategy(slaveStatus_);
|
||||
if (strategy == ExchangeStrategy::BACKUP) {
|
||||
(void)conn->Backup({}, {}, false, slaveStatus_);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (type != DistributedRdb::DISTRIBUTED_CLOUD || !distributedConfig.autoSync) {
|
||||
@ -2443,16 +2447,11 @@ int RdbStoreImpl::InterruptBackup()
|
||||
if (config_.GetHaMode() != HAMode::MANUAL_TRIGGER) {
|
||||
return E_NOT_SUPPORT;
|
||||
}
|
||||
auto conn = connectionPool_->AcquireConnection(false);
|
||||
if (conn == nullptr) {
|
||||
return E_DATABASE_BUSY;
|
||||
if (slaveStatus_ == SlaveStatus::BACKING_UP) {
|
||||
slaveStatus_ = SlaveStatus::BACKUP_INTERRUPT;
|
||||
return E_OK;
|
||||
}
|
||||
int32_t ret = conn->InterruptBackup();
|
||||
if (ret != E_OK) {
|
||||
LOG_ERROR("InterruptBackup failed");
|
||||
return ret;
|
||||
}
|
||||
return E_OK;
|
||||
return E_INVALID_INTERRUPT;
|
||||
}
|
||||
|
||||
int32_t RdbStoreImpl::GetBackupStatus() const
|
||||
@ -2460,11 +2459,7 @@ int32_t RdbStoreImpl::GetBackupStatus() const
|
||||
if (config_.GetHaMode() != HAMode::MANUAL_TRIGGER && config_.GetHaMode() != HAMode::MAIN_REPLICA) {
|
||||
return SlaveStatus::UNDEFINED;
|
||||
}
|
||||
auto conn = connectionPool_->AcquireConnection(false);
|
||||
if (conn == nullptr) {
|
||||
return SlaveStatus::UNDEFINED;
|
||||
}
|
||||
return conn->GetBackupStatus();
|
||||
return slaveStatus_;
|
||||
}
|
||||
|
||||
bool RdbStoreImpl::TryGetMasterSlaveBackupPath(const std::string &srcPath, std::string &destPath, bool isRestore)
|
||||
@ -2483,4 +2478,36 @@ bool RdbStoreImpl::TryGetMasterSlaveBackupPath(const std::string &srcPath, std::
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RdbStoreImpl::IsSlaveDiffFromMaster() const
|
||||
{
|
||||
std::string failureFlagFile = config_.GetPath() + "-slaveFailure";
|
||||
std::string slaveDbPath = SqliteUtils::GetSlavePath(config_.GetPath());
|
||||
return access(failureFlagFile.c_str(), F_OK) == 0 || access(slaveDbPath.c_str(), F_OK) != 0;
|
||||
}
|
||||
|
||||
int32_t RdbStoreImpl::ExchangeSlaverToMaster()
|
||||
{
|
||||
if (config_.GetRoleType() == VISITOR || config_.IsReadOnly()) {
|
||||
return E_OK;
|
||||
}
|
||||
auto conn = connectionPool_->AcquireConnection(false);
|
||||
if (conn == nullptr) {
|
||||
return E_DATABASE_BUSY;
|
||||
}
|
||||
auto strategy = conn->GenerateExchangeStrategy(slaveStatus_);
|
||||
if (strategy != ExchangeStrategy::NOT_HANDLE) {
|
||||
LOG_WARN("exchange st:%{public}d, %{public}s,", strategy, config_.GetName().c_str());
|
||||
}
|
||||
int ret = E_OK;
|
||||
if (strategy == ExchangeStrategy::RESTORE) {
|
||||
conn = nullptr;
|
||||
// disable is required before restore
|
||||
ret = Restore({}, {});
|
||||
} else if (strategy == ExchangeStrategy::BACKUP) {
|
||||
// async backup
|
||||
ret = conn->Backup({}, {}, true, slaveStatus_);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
} // namespace OHOS::NativeRdb
|
@ -91,6 +91,7 @@ std::shared_ptr<RdbStore> RdbStoreManager::GetRdbStore(const RdbStoreConfig &con
|
||||
storeCache_[path] = rdbStore;
|
||||
return rdbStore;
|
||||
}
|
||||
(void)rdbStore->ExchangeSlaverToMaster();
|
||||
errCode = ProcessOpenCallback(*rdbStore, config, version, openCallback);
|
||||
if (errCode != E_OK) {
|
||||
LOG_ERROR("fail, storeName:%{public}s path:%{public}s ProcessOpenCallback errCode:%{public}d",
|
||||
|
@ -67,35 +67,7 @@ std::pair<int32_t, std::shared_ptr<Connection>> SqliteConnection::Create(const R
|
||||
{
|
||||
std::pair<int32_t, std::shared_ptr<Connection>> result = { E_ERROR, nullptr };
|
||||
auto &[errCode, conn] = result;
|
||||
std::shared_ptr<SqliteConnection> connection = std::make_shared<SqliteConnection>(config, isWrite);
|
||||
if (connection == nullptr) {
|
||||
LOG_ERROR("connection is nullptr.");
|
||||
return result;
|
||||
}
|
||||
|
||||
RdbStoreConfig rdbSlaveStoreConfig = connection->GetSlaveRdbStoreConfig(config);
|
||||
errCode = connection->InnerOpen(config);
|
||||
if (errCode != E_OK) {
|
||||
return result;
|
||||
}
|
||||
conn = connection;
|
||||
|
||||
if (isWrite) {
|
||||
int ret = connection->CreateSlaveConnection(rdbSlaveStoreConfig, isWrite);
|
||||
if (ret != E_OK) {
|
||||
return { E_OK, conn };
|
||||
}
|
||||
auto [isExchange, isRestore] = connection->IsExchange(rdbSlaveStoreConfig);
|
||||
if (isExchange) {
|
||||
LOG_INFO("exchange isRes:%{public}d, %{public}s,", isRestore,
|
||||
SqliteUtils::Anonymous(rdbSlaveStoreConfig.GetPath()).c_str());
|
||||
if (isRestore) {
|
||||
(void)connection->Restore({}, {});
|
||||
} else {
|
||||
(void)connection->Backup({}, {}, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
std::tie(errCode, conn) = InnerCreate(config, isWrite);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -106,6 +78,8 @@ int32_t SqliteConnection::Delete(const RdbStoreConfig &config)
|
||||
SqliteUtils::DeleteFile(path + "-shm");
|
||||
SqliteUtils::DeleteFile(path + "-wal");
|
||||
SqliteUtils::DeleteFile(path + "-journal");
|
||||
SqliteUtils::DeleteFile(path + "-slaveFailure");
|
||||
SqliteUtils::DeleteFile(path + "-syncInterrupt");
|
||||
return E_OK;
|
||||
}
|
||||
|
||||
@ -122,10 +96,7 @@ int SqliteConnection::CreateSlaveConnection(const RdbStoreConfig &config, bool i
|
||||
}
|
||||
bool isSlaveExist = access(config.GetPath().c_str(), F_OK) == 0;
|
||||
bool isSlaveLockExist = SqliteUtils::TryAccessSlaveLock(config_.GetPath(), false, false);
|
||||
if (!isSlaveExist) {
|
||||
slaveStatus_.store(SlaveStatus::DB_NOT_EXITS);
|
||||
}
|
||||
if (config.GetHaMode() == HAMode::MANUAL_TRIGGER && ((checkSlaveExist && !isSlaveExist) || isSlaveLockExist)) {
|
||||
if (config.GetHaMode() == HAMode::MANUAL_TRIGGER && (checkSlaveExist && (!isSlaveExist || isSlaveLockExist))) {
|
||||
LOG_INFO("not dual write on manual, slave:%{public}d, lock:%{public}d",
|
||||
isSlaveExist, isSlaveLockExist);
|
||||
return E_OK;
|
||||
@ -135,6 +106,7 @@ int SqliteConnection::CreateSlaveConnection(const RdbStoreConfig &config, bool i
|
||||
slaveConnection_ = connection;
|
||||
int errCode = slaveConnection_->InnerOpen(config);
|
||||
if (errCode != E_OK) {
|
||||
SqliteUtils::TryAccessSlaveLock(config_.GetPath(), false, true, true);
|
||||
if (errCode == E_SQLITE_CORRUPT) {
|
||||
LOG_WARN("slave corrupt, rebuild:%{public}s",
|
||||
SqliteUtils::Anonymous(config.GetPath()).c_str());
|
||||
@ -177,6 +149,7 @@ RdbStoreConfig SqliteConnection::GetSlaveRdbStoreConfig(const RdbStoreConfig rdb
|
||||
rdbStoreConfig.SetEncryptKey(rdbConfig.GetEncryptKey());
|
||||
rdbStoreConfig.SetNewEncryptKey(rdbConfig.GetNewEncryptKey());
|
||||
rdbStoreConfig.SetScalarFunctions(rdbConfig.GetScalarFunctions());
|
||||
rdbStoreConfig.SetJournalMode(rdbConfig.GetJournalMode());
|
||||
|
||||
rdbStoreConfig.SetModuleName(rdbConfig.GetModuleName());
|
||||
rdbStoreConfig.SetArea(rdbConfig.GetArea());
|
||||
@ -230,7 +203,7 @@ int SqliteConnection::InnerOpen(const RdbStoreConfig &config)
|
||||
static_cast<std::string>(checkResult).c_str(), sql);
|
||||
ReportDbCorruptedEvent(errCode, static_cast<std::string>(checkResult));
|
||||
} else {
|
||||
LOG_INFO("%{public}s integrity check err:%{public}d, result is %{public}s, sql:%{public}s",
|
||||
LOG_DEBUG("%{public}s integrity check err:%{public}d, result is %{public}s, sql:%{public}s",
|
||||
config.GetName().c_str(), errCode, static_cast<std::string>(checkResult).c_str(), sql);
|
||||
}
|
||||
}
|
||||
@ -439,7 +412,8 @@ std::pair<int, std::shared_ptr<Statement>> SqliteConnection::CreateStatement(
|
||||
slaveStmt->config_ = &slaveConnection_->config_;
|
||||
errCode = slaveStmt->Prepare(slaveConnection_->dbHandle_, sql);
|
||||
if (errCode != E_OK) {
|
||||
LOG_WARN("prepare slave stmt failed:%{public}d", errCode);
|
||||
LOG_WARN("prepare slave stmt failed:%{public}d, sql:%{public}s", errCode, sql.c_str());
|
||||
SqliteUtils::TryAccessSlaveLock(config_.GetPath(), false, true, true);
|
||||
return { E_OK, statement };
|
||||
}
|
||||
statement->slave_ = slaveStmt;
|
||||
@ -1158,12 +1132,16 @@ int32_t SqliteConnection::UnsubscribeLocalDetailAll(const std::string &event)
|
||||
}
|
||||
|
||||
int32_t SqliteConnection::Backup(const std::string &databasePath, const std::vector<uint8_t> &destEncryptKey,
|
||||
bool isAsync)
|
||||
bool isAsync, SlaveStatus &slaveStatus)
|
||||
{
|
||||
if (slaveStatus == SlaveStatus::BACKING_UP) {
|
||||
LOG_INFO("backing up, return:%{public}s", config_.GetName().c_str());
|
||||
return E_OK;
|
||||
}
|
||||
LOG_INFO("begin backup to slave:%{public}s, isAsync:%{public}d", SqliteUtils::Anonymous(databasePath).c_str(),
|
||||
isAsync);
|
||||
if (!isAsync) {
|
||||
if (config_.GetHaMode() == HAMode::MANUAL_TRIGGER && slaveConnection_ == nullptr) {
|
||||
if (slaveConnection_ == nullptr) {
|
||||
RdbStoreConfig rdbSlaveStoreConfig = GetSlaveRdbStoreConfig(config_);
|
||||
int errCode = CreateSlaveConnection(rdbSlaveStoreConfig, true, false);
|
||||
if (errCode != E_OK) {
|
||||
@ -1171,7 +1149,7 @@ int32_t SqliteConnection::Backup(const std::string &databasePath, const std::vec
|
||||
return errCode;
|
||||
}
|
||||
}
|
||||
return MasterSlaveExchange();
|
||||
return ExchangeSlaverToMaster(false, slaveStatus);
|
||||
}
|
||||
|
||||
if (backupId_ == TaskExecutor::INVALID_TASK_ID) {
|
||||
@ -1180,10 +1158,14 @@ int32_t SqliteConnection::Backup(const std::string &databasePath, const std::vec
|
||||
LOG_WARN("task pool err when restore");
|
||||
return E_OK;
|
||||
}
|
||||
backupId_ = pool->Execute([this]() {
|
||||
int ret = MasterSlaveExchange();
|
||||
if (ret != E_OK) {
|
||||
LOG_WARN("master backup to slave failed:%{public}d", ret);
|
||||
backupId_ = pool->Execute([this, &slaveStatus]() {
|
||||
auto [err, conn] = InnerCreate(config_, true);
|
||||
if (err != E_OK) {
|
||||
return;
|
||||
}
|
||||
err = conn->ExchangeSlaverToMaster(false, slaveStatus);
|
||||
if (err != E_OK) {
|
||||
LOG_WARN("master backup to slave failed:%{public}d", err);
|
||||
}
|
||||
backupId_ = TaskExecutor::INVALID_TASK_ID;
|
||||
});
|
||||
@ -1191,10 +1173,11 @@ int32_t SqliteConnection::Backup(const std::string &databasePath, const std::vec
|
||||
return E_OK;
|
||||
}
|
||||
|
||||
int32_t SqliteConnection::Restore(const std::string &databasePath, const std::vector<uint8_t> &destEncryptKey)
|
||||
int32_t SqliteConnection::Restore(const std::string &databasePath, const std::vector<uint8_t> &destEncryptKey,
|
||||
SlaveStatus &slaveStatus)
|
||||
{
|
||||
LOG_INFO("begin to restore from slave:%{public}s", SqliteUtils::Anonymous(databasePath).c_str());
|
||||
return MasterSlaveExchange(true);
|
||||
return ExchangeSlaverToMaster(true, slaveStatus);
|
||||
};
|
||||
|
||||
int SqliteConnection::LoadExtension(const RdbStoreConfig &config, sqlite3 *dbHandle)
|
||||
@ -1270,10 +1253,12 @@ int SqliteConnection::SetServiceKey(const RdbStoreConfig &config, int32_t errCod
|
||||
return errCode;
|
||||
}
|
||||
|
||||
int SqliteConnection::MasterSlaveExchange(bool isRestore)
|
||||
int SqliteConnection::ExchangeSlaverToMaster(bool isRestore, SlaveStatus &curStatus)
|
||||
{
|
||||
auto [isReturn, err] = ExchangeVerify(isRestore);
|
||||
if (isReturn) {
|
||||
curStatus = SlaveStatus::BACKING_UP;
|
||||
auto err = ExchangeVerify(isRestore);
|
||||
if (err != E_OK) {
|
||||
curStatus = SlaveStatus::UNDEFINED;
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -1282,106 +1267,87 @@ int SqliteConnection::MasterSlaveExchange(bool isRestore)
|
||||
sqlite3_backup *pBackup = sqlite3_backup_init(dbFrom, "main", dbTo, "main");
|
||||
if (pBackup == nullptr) {
|
||||
LOG_WARN("slave backup init failed");
|
||||
slaveStatus_.store(SlaveStatus::UNDEFINED);
|
||||
curStatus = SlaveStatus::UNDEFINED;
|
||||
return E_OK;
|
||||
}
|
||||
int rc = SQLITE_OK;
|
||||
do {
|
||||
if (!isRestore && slaveStatus_.load() == SlaveStatus::BACKUP_INTERRUPT) {
|
||||
if (!isRestore && curStatus == SlaveStatus::BACKUP_INTERRUPT) {
|
||||
LOG_INFO("backup slave was interrupt!");
|
||||
(void)sqlite3_backup_finish(pBackup);
|
||||
(void)SqliteConnection::Delete(slaveConnection_->config_);
|
||||
return E_OK;
|
||||
rc = E_BACKUP_INTERRUPT;
|
||||
break;
|
||||
}
|
||||
rc = sqlite3_backup_step(pBackup, BACKUP_PAGES_PRE_STEP);
|
||||
LOG_INFO("backup slave process cur/total:%{public}d/%{public}d, isRestore:%{public}d",
|
||||
LOG_INFO("backup slave process cur/total:%{public}d/%{public}d, rs:%{public}d, isRestore:%{public}d",
|
||||
sqlite3_backup_pagecount(pBackup) - sqlite3_backup_remaining(pBackup), sqlite3_backup_pagecount(pBackup),
|
||||
isRestore);
|
||||
} while (rc == SQLITE_OK || rc == SQLITE_BUSY || rc == SQLITE_LOCKED);
|
||||
rc, isRestore);
|
||||
if (!isRestore) {
|
||||
sqlite3_sleep(BACKUP_PRE_WAIT_TIME);
|
||||
}
|
||||
} while (sqlite3_backup_pagecount(pBackup) != 0 && (rc == SQLITE_OK || rc == SQLITE_BUSY || rc == SQLITE_LOCKED));
|
||||
(void)sqlite3_backup_finish(pBackup);
|
||||
if (rc != SQLITE_DONE) {
|
||||
slaveStatus_.store(SlaveStatus::BACKUP_INTERRUPT);
|
||||
LOG_WARN("backup slave err:%{public}d, isRestore:%{public}d", rc, isRestore);
|
||||
return SQLiteError::ErrNo(rc);
|
||||
} else {
|
||||
isRestore ? TryCheckPoint() : slaveConnection_->TryCheckPoint();
|
||||
slaveStatus_.store(SlaveStatus::BACKUP_FINISHED);
|
||||
if (!SqliteUtils::TryAccessSlaveLock(config_.GetPath(), true, false)) {
|
||||
LOG_WARN("try remove slave lock failed! isRestore:%{public}d", isRestore);
|
||||
LOG_ERROR("backup slave err:%{public}d, isRestore:%{public}d", rc, isRestore);
|
||||
if (!isRestore) {
|
||||
RdbStoreConfig slaveConfig(slaveConnection_->config_.GetPath());
|
||||
if (rc != SQLITE_BUSY && rc != SQLITE_LOCKED) {
|
||||
slaveConnection_ = nullptr;
|
||||
(void)SqliteConnection::Delete(slaveConfig);
|
||||
}
|
||||
curStatus = SlaveStatus::BACKUP_INTERRUPT;
|
||||
}
|
||||
LOG_INFO("backup slave success, isRestore:%{public}d", isRestore);
|
||||
return rc == E_BACKUP_INTERRUPT ? E_BACKUP_INTERRUPT : SQLiteError::ErrNo(rc);
|
||||
}
|
||||
isRestore ? TryCheckPoint() : slaveConnection_->TryCheckPoint();
|
||||
curStatus = SlaveStatus::BACKUP_FINISHED;
|
||||
SqliteUtils::TryAccessSlaveLock(config_.GetPath(), true, false);
|
||||
SqliteUtils::TryAccessSlaveLock(config_.GetPath(), true, false, true);
|
||||
LOG_INFO("backup slave success, isRestore:%{public}d", isRestore);
|
||||
return E_OK;
|
||||
}
|
||||
|
||||
std::pair<bool, bool> SqliteConnection::IsExchange(const RdbStoreConfig &config)
|
||||
ExchangeStrategy SqliteConnection::GenerateExchangeStrategy(const SlaveStatus &status)
|
||||
{
|
||||
std::pair<bool, bool> res = { false, false };
|
||||
auto &[isExchanged, isRestore] = res;
|
||||
if (dbHandle_ == nullptr || slaveConnection_ == nullptr || slaveConnection_->dbHandle_ == nullptr) {
|
||||
return res;
|
||||
}
|
||||
if (config.GetHaMode() != HAMode::MAIN_REPLICA) {
|
||||
return res;
|
||||
}
|
||||
SlaveStatus curSlaveStatus = slaveStatus_.load();
|
||||
if (curSlaveStatus == SlaveStatus::BACKING_UP) {
|
||||
return res;
|
||||
}
|
||||
if (curSlaveStatus == SlaveStatus::DB_NOT_EXITS || curSlaveStatus == SlaveStatus::BACKUP_INTERRUPT) {
|
||||
isExchanged = true;
|
||||
return res;
|
||||
if (dbHandle_ == nullptr || slaveConnection_ == nullptr || slaveConnection_->dbHandle_ == nullptr ||
|
||||
config_.GetHaMode() == HAMode::SINGLE || status == SlaveStatus::BACKING_UP) {
|
||||
return ExchangeStrategy::NOT_HANDLE;
|
||||
}
|
||||
static const std::string querySql = "SELECT COUNT(*) FROM sqlite_master WHERE type='table';";
|
||||
auto [mRet, mObj] = ExecuteForValue(querySql);
|
||||
if (mRet != E_OK) {
|
||||
return res;
|
||||
LOG_WARN("main abnormal, err:%{public}d", mRet);
|
||||
return ExchangeStrategy::RESTORE;
|
||||
}
|
||||
int64_t mCount = static_cast<int64_t>(mObj);
|
||||
// trigger mode only does restore, not backup
|
||||
if (config_.GetHaMode() == HAMode::MANUAL_TRIGGER) {
|
||||
return mCount == 0 ? ExchangeStrategy::RESTORE : ExchangeStrategy::NOT_HANDLE;
|
||||
}
|
||||
auto [sRet, sObj] = slaveConnection_->ExecuteForValue(querySql);
|
||||
if (sRet != E_OK) {
|
||||
LOG_WARN("slave db abnormal, need backup, err:%{public}d", sRet);
|
||||
isExchanged = true;
|
||||
return res;
|
||||
return ExchangeStrategy::BACKUP;
|
||||
}
|
||||
if (status == SlaveStatus::DB_NOT_EXITS || status == SlaveStatus::BACKUP_INTERRUPT) {
|
||||
return ExchangeStrategy::BACKUP;
|
||||
}
|
||||
int64_t mCount = static_cast<int64_t>(mObj);
|
||||
int64_t sCount = static_cast<int64_t>(sObj);
|
||||
if (mCount == sCount) {
|
||||
return res;
|
||||
std::string failureFlagFile = config_.GetPath() + "-slaveFailure";
|
||||
if (mCount == sCount && access(failureFlagFile.c_str(), F_OK) != 0) {
|
||||
LOG_INFO("equal, main:%{public}" PRId64 ",slave:%{public}" PRId64, mCount, sCount);
|
||||
return ExchangeStrategy::NOT_HANDLE;
|
||||
}
|
||||
isExchanged = true;
|
||||
if (mCount == 0) {
|
||||
isRestore = true;
|
||||
LOG_INFO("main empty, main:%{public}" PRId64 ",slave:%{public}" PRId64, mCount, sCount);
|
||||
} else {
|
||||
auto [cRet, cObj] = ExecuteForValue(INTEGRITIES[1]); // 1 is quick_check
|
||||
if (cRet != E_OK || (static_cast<std::string>(cObj) != "ok")) {
|
||||
LOG_ERROR("main corrupt, need restore, ret:%{public}s, cRet:%{public}d",
|
||||
static_cast<std::string>(cObj).c_str(), cRet);
|
||||
isRestore = true;
|
||||
} else {
|
||||
LOG_INFO("not equal, main:%{public}" PRId64 ",slave:%{public}" PRId64, mCount, sCount);
|
||||
}
|
||||
return ExchangeStrategy::RESTORE;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
int32_t SqliteConnection::InterruptBackup()
|
||||
{
|
||||
if (slaveStatus_.load() == SlaveStatus::BACKING_UP) {
|
||||
slaveStatus_.store(SlaveStatus::BACKUP_INTERRUPT);
|
||||
return E_OK;
|
||||
}
|
||||
return E_NOT_SUPPORT;
|
||||
}
|
||||
|
||||
int32_t SqliteConnection::GetBackupStatus() const
|
||||
{
|
||||
return slaveStatus_.load();
|
||||
LOG_INFO("backup, main:%{public}" PRId64 ",slave:%{public}" PRId64, mCount, sCount);
|
||||
return ExchangeStrategy::BACKUP;
|
||||
}
|
||||
|
||||
int32_t SqliteConnection::Repair(const RdbStoreConfig &config)
|
||||
{
|
||||
if (config.GetHaMode() != MAIN_REPLICA) {
|
||||
if (config.GetHaMode() != MAIN_REPLICA && config.GetHaMode() != MANUAL_TRIGGER) {
|
||||
return E_NOT_SUPPORT;
|
||||
}
|
||||
std::shared_ptr<SqliteConnection> connection = std::make_shared<SqliteConnection>(config, true);
|
||||
@ -1393,8 +1359,9 @@ int32_t SqliteConnection::Repair(const RdbStoreConfig &config)
|
||||
if (ret != E_OK) {
|
||||
return ret;
|
||||
}
|
||||
if (!connection->IsRepairable()) {
|
||||
return E_NOT_SUPPORT;
|
||||
ret = connection->IsRepairable();
|
||||
if (ret != E_OK) {
|
||||
return ret;
|
||||
}
|
||||
LOG_WARN("begin repair main:%{public}s", SqliteUtils::Anonymous(config.GetPath()).c_str());
|
||||
(void)SqliteConnection::Delete(config);
|
||||
@ -1403,57 +1370,103 @@ int32_t SqliteConnection::Repair(const RdbStoreConfig &config)
|
||||
LOG_ERROR("reopen db failed, err:%{public}d", ret);
|
||||
return ret;
|
||||
}
|
||||
ret = connection->MasterSlaveExchange(true);
|
||||
SlaveStatus curStatus;
|
||||
ret = connection->ExchangeSlaverToMaster(true, curStatus);
|
||||
if (ret != E_OK) {
|
||||
LOG_ERROR("repair failed, [%{public}s]->[%{public}s], err:%{public}d", rdbSlaveStoreConfig.GetName().c_str(),
|
||||
config.GetName().c_str(), ret);
|
||||
return ret;
|
||||
} else {
|
||||
LOG_INFO("repair main success:%{public}s", SqliteUtils::Anonymous(config.GetPath()).c_str());
|
||||
}
|
||||
LOG_INFO("repair main success:%{public}s", SqliteUtils::Anonymous(config.GetPath()).c_str());
|
||||
connection->slaveConnection_ = nullptr;
|
||||
connection = nullptr;
|
||||
return E_OK;
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool SqliteConnection::IsRepairable()
|
||||
int SqliteConnection::IsRepairable()
|
||||
{
|
||||
if (slaveConnection_ == nullptr || slaveConnection_->dbHandle_ == nullptr) {
|
||||
return false;
|
||||
return E_STORE_CLOSED;
|
||||
}
|
||||
static const std::string querySql = "SELECT COUNT(*) FROM sqlite_master WHERE type='table';";
|
||||
if (SqliteUtils::TryAccessSlaveLock(config_.GetPath(), false, false, false)) {
|
||||
LOG_ERROR("unavailable slave, %{public}s", config_.GetName().c_str());
|
||||
return E_DB_RESTORE_NOT_ALLOWED;
|
||||
}
|
||||
std::string querySql = "SELECT COUNT(*) FROM sqlite_master WHERE type='table';";
|
||||
auto [qRet, qObj] = slaveConnection_->ExecuteForValue(querySql);
|
||||
if (qRet != E_OK || (static_cast<int64_t>(qObj) == 0L)) {
|
||||
LOG_INFO("cancel repair, ret:%{public}d", qRet);
|
||||
return false;
|
||||
return E_DB_RESTORE_NOT_ALLOWED;
|
||||
}
|
||||
auto [cRet, cObj] = slaveConnection_->ExecuteForValue(INTEGRITIES[1]); // 1 is quick check
|
||||
if (cRet != E_OK || (static_cast<std::string>(cObj) != "ok")) {
|
||||
LOG_ERROR("cancel repair, ret:%{public}s, cRet:%{public}d", static_cast<std::string>(cObj).c_str(), cRet);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return E_OK;
|
||||
}
|
||||
|
||||
std::pair<bool, int> SqliteConnection::ExchangeVerify(bool isRestore)
|
||||
int SqliteConnection::ExchangeVerify(bool isRestore)
|
||||
{
|
||||
if (dbHandle_ == nullptr || slaveConnection_ == nullptr || slaveConnection_->dbHandle_ == nullptr) {
|
||||
LOG_WARN("slave conn invalid");
|
||||
return { true, E_OK };
|
||||
return E_STORE_CLOSED;
|
||||
}
|
||||
if (!SqliteUtils::TryAccessSlaveLock(config_.GetPath(), false, true)) {
|
||||
LOG_WARN("try create slave lock failed! isRestore:%{public}d", isRestore);
|
||||
if (access(config_.GetPath().c_str(), F_OK) != 0) {
|
||||
LOG_WARN("main no exist, isR:%{public}d, %{public}s", isRestore, config_.GetName().c_str());
|
||||
return E_DB_NOT_EXIST;
|
||||
}
|
||||
slaveStatus_.store(SlaveStatus::BACKING_UP);
|
||||
if (isRestore) {
|
||||
int err = IsRepairable();
|
||||
if (err != E_OK) {
|
||||
return err;
|
||||
}
|
||||
auto [cRet, cObj] = slaveConnection_->ExecuteForValue(INTEGRITIES[2]); // 2 is integrity_check
|
||||
if (cRet != E_OK || (static_cast<std::string>(cObj) != "ok")) {
|
||||
LOG_ERROR("slave may corrupt, cancel backup, ret:%{public}s, cRet:%{public}d",
|
||||
LOG_ERROR("slave may corrupt, cancel, ret:%{public}s, cRet:%{public}d",
|
||||
static_cast<std::string>(cObj).c_str(), cRet);
|
||||
slaveStatus_.store(SlaveStatus::DB_NOT_EXITS);
|
||||
return { true, E_SQLITE_CORRUPT };
|
||||
return E_SQLITE_CORRUPT;
|
||||
}
|
||||
std::string querySql = "SELECT COUNT(*) FROM sqlite_master WHERE type='table';";
|
||||
std::tie(cRet, cObj) = ExecuteForValue(querySql);
|
||||
if (cRet == E_OK && (static_cast<int64_t>(cObj) == 0L)) {
|
||||
LOG_INFO("main empty, need restore, %{public}s", config_.GetName().c_str());
|
||||
return E_OK;
|
||||
}
|
||||
if (SqliteUtils::TryAccessSlaveLock(config_.GetPath(), false, false, true)) {
|
||||
LOG_ERROR("incomplete slave, %{public}s", config_.GetName().c_str());
|
||||
return E_DB_RESTORE_NOT_ALLOWED;
|
||||
}
|
||||
} else {
|
||||
auto [cRet, cObj] = ExecuteForValue(INTEGRITIES[1]); // 1 is quick_check
|
||||
if (cRet != E_OK || (static_cast<std::string>(cObj) != "ok")) {
|
||||
LOG_ERROR("main corrupt, cancel, ret:%{public}s, qRet:%{public}d",
|
||||
static_cast<std::string>(cObj).c_str(), cRet);
|
||||
return E_SQLITE_CORRUPT;
|
||||
}
|
||||
if (!SqliteUtils::TryAccessSlaveLock(config_.GetPath(), false, true)) {
|
||||
LOG_WARN("try create slave lock failed! isRestore:%{public}d", isRestore);
|
||||
}
|
||||
}
|
||||
return { false, E_OK };
|
||||
return E_OK;
|
||||
}
|
||||
|
||||
std::pair<int32_t, std::shared_ptr<SqliteConnection>> SqliteConnection::InnerCreate(const RdbStoreConfig &config,
|
||||
bool isWrite)
|
||||
{
|
||||
std::pair<int32_t, std::shared_ptr<SqliteConnection>> result = { E_ERROR, nullptr };
|
||||
auto &[errCode, conn] = result;
|
||||
std::shared_ptr<SqliteConnection> connection = std::make_shared<SqliteConnection>(config, isWrite);
|
||||
if (connection == nullptr) {
|
||||
LOG_ERROR("connection is nullptr.");
|
||||
return result;
|
||||
}
|
||||
|
||||
RdbStoreConfig rdbSlaveStoreConfig = connection->GetSlaveRdbStoreConfig(config);
|
||||
errCode = connection->InnerOpen(config);
|
||||
if (errCode != E_OK) {
|
||||
return result;
|
||||
}
|
||||
conn = connection;
|
||||
if (isWrite) {
|
||||
(void)connection->CreateSlaveConnection(rdbSlaveStoreConfig, isWrite);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
} // namespace NativeRdb
|
||||
} // namespace OHOS
|
||||
|
@ -56,6 +56,7 @@ SqliteStatement::~SqliteStatement()
|
||||
SqlStatistic sqlStatistic("", SqlStatistic::Step::STEP_TOTAL_RES, seqId_);
|
||||
Finalize();
|
||||
conn_ = nullptr;
|
||||
config_ = nullptr;
|
||||
}
|
||||
|
||||
int SqliteStatement::Prepare(sqlite3 *dbHandle, const std::string &newSql)
|
||||
@ -186,6 +187,7 @@ int SqliteStatement::Prepare(const std::string &sql)
|
||||
int errCode = slave_->Prepare(sql);
|
||||
if (errCode != E_OK) {
|
||||
LOG_WARN("slave prepare Error:%{public}d", errCode);
|
||||
SqliteUtils::TryAccessSlaveLock(config_->GetPath(), false, true, true);
|
||||
}
|
||||
}
|
||||
return E_OK;
|
||||
@ -226,6 +228,7 @@ int SqliteStatement::Bind(const std::vector<ValueObject> &args)
|
||||
int errCode = slave_->Bind(args);
|
||||
if (errCode != E_OK) {
|
||||
LOG_ERROR("slave bind error:%{public}d", errCode);
|
||||
SqliteUtils::TryAccessSlaveLock(config_->GetPath(), false, true, true);
|
||||
}
|
||||
}
|
||||
return E_OK;
|
||||
@ -328,6 +331,7 @@ int SqliteStatement::Execute(const std::vector<ValueObject> &args)
|
||||
int errCode = slave_->Execute(args);
|
||||
if (errCode != E_OK) {
|
||||
LOG_ERROR("slave execute error:%{public}d", errCode);
|
||||
SqliteUtils::TryAccessSlaveLock(config_->GetPath(), false, true, true);
|
||||
}
|
||||
}
|
||||
return E_OK;
|
||||
@ -670,7 +674,6 @@ int SqliteStatement::InnerFinalize()
|
||||
columnCount_ = -1;
|
||||
numParameters_ = 0;
|
||||
types_ = std::vector<int32_t>();
|
||||
config_ = nullptr;
|
||||
if (errCode != SQLITE_OK) {
|
||||
LOG_ERROR("finalize ret is %{public}d, errno is %{public}d", errCode, errno);
|
||||
return SQLiteError::ErrNo(errCode);
|
||||
|
@ -184,15 +184,15 @@ bool SqliteUtils::IsSlaveDbName(const std::string &fileName)
|
||||
return (pos != std::string::npos) && (pos == fileName.size() - slaveSuffix.size());
|
||||
}
|
||||
|
||||
bool SqliteUtils::TryAccessSlaveLock(const std::string &dbPath, bool isDelete, bool needCreate)
|
||||
bool SqliteUtils::TryAccessSlaveLock(const std::string &dbPath, bool isDelete, bool needCreate,
|
||||
bool isSlaveFailure)
|
||||
{
|
||||
std::string lockFile = dbPath + "-locker";
|
||||
std::string lockFile = isSlaveFailure ? dbPath + "-slaveFailure" : dbPath + "-syncInterrupt";
|
||||
if (isDelete) {
|
||||
if (std::remove(lockFile.c_str()) != 0) {
|
||||
LOG_WARN("remove slave lock failed errno %{public}d %{public}s", errno, Anonymous(lockFile).c_str());
|
||||
return false;
|
||||
} else {
|
||||
LOG_INFO("remove slave lock %{public}s", Anonymous(lockFile).c_str());
|
||||
LOG_INFO("remove %{public}s", Anonymous(lockFile).c_str());
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
@ -202,11 +202,11 @@ bool SqliteUtils::TryAccessSlaveLock(const std::string &dbPath, bool isDelete, b
|
||||
if (needCreate) {
|
||||
std::ofstream src(lockFile.c_str(), std::ios::binary);
|
||||
if (src.is_open()) {
|
||||
LOG_INFO("create slave lock %{public}s", Anonymous(lockFile).c_str());
|
||||
LOG_INFO("open %{public}s", Anonymous(lockFile).c_str());
|
||||
src.close();
|
||||
return true;
|
||||
} else {
|
||||
LOG_WARN("open slave lock failed errno %{public}d %{public}s", errno, Anonymous(lockFile).c_str());
|
||||
LOG_WARN("open errno %{public}d %{public}s", errno, Anonymous(lockFile).c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -47,6 +47,12 @@ enum SlaveStatus : uint32_t {
|
||||
BACKUP_INTERRUPT,
|
||||
BACKUP_FINISHED,
|
||||
};
|
||||
|
||||
enum ExchangeStrategy : uint32_t {
|
||||
NOT_HANDLE,
|
||||
BACKUP,
|
||||
RESTORE,
|
||||
};
|
||||
} // namespace NativeRdb
|
||||
} // namespace OHOS
|
||||
|
||||
|
@ -399,6 +399,21 @@ static constexpr int E_SERVICE_NOT_FOUND = (E_BASE + 71);
|
||||
* @brief Database schema has changed.
|
||||
*/
|
||||
static constexpr int E_SQLITE_SCHEMA = (E_BASE + 72);
|
||||
|
||||
/**
|
||||
* @brief Database backup was interrupted.
|
||||
*/
|
||||
static constexpr int E_BACKUP_INTERRUPT = (E_BASE + 0x49);
|
||||
|
||||
/**
|
||||
* @brief Backup interrupt operation is invalid
|
||||
*/
|
||||
static constexpr int E_INVALID_INTERRUPT = (E_BASE + 0x4a);
|
||||
|
||||
/**
|
||||
* @brief Restore is not allowed
|
||||
*/
|
||||
static constexpr int E_DB_RESTORE_NOT_ALLOWED = (E_BASE + 0x4b);
|
||||
} // namespace NativeRdb
|
||||
} // namespace OHOS
|
||||
|
||||
|
@ -563,6 +563,14 @@ public:
|
||||
*/
|
||||
virtual int Notify(const std::string &event) = 0;
|
||||
|
||||
/**
|
||||
* @brief Check the slave database is different from current database.
|
||||
*/
|
||||
virtual bool IsSlaveDiffFromMaster() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual int32_t GetDbType() const
|
||||
{
|
||||
return DB_SQLITE;
|
||||
|
@ -625,6 +625,8 @@ public:
|
||||
|
||||
void SetScalarFunctions(const std::map<std::string, ScalarFunctionInfo> functions);
|
||||
|
||||
void SetJournalMode(const std::string &journalMode);
|
||||
|
||||
void EnableRekey(bool enable);
|
||||
|
||||
private:
|
||||
|
@ -40,6 +40,12 @@ enum SlaveStatus : uint32_t {
|
||||
BACKUP_INTERRUPT,
|
||||
BACKUP_FINISHED,
|
||||
};
|
||||
|
||||
enum ExchangeStrategy : uint32_t {
|
||||
NOT_HANDLE,
|
||||
BACKUP,
|
||||
RESTORE,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -113,7 +113,10 @@ public:
|
||||
{
|
||||
return E_OK;
|
||||
}
|
||||
|
||||
virtual bool IsSlaveDiffFromMaster() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
virtual int32_t GetBackupStatus() const
|
||||
{
|
||||
return SlaveStatus::UNDEFINED;
|
||||
|
@ -229,6 +229,7 @@ public:
|
||||
void SetHaMode(int32_t haMode);
|
||||
void SetNewEncryptKey(const std::vector<uint8_t> newEncryptKey);
|
||||
void SetScalarFunctions(const std::map<std::string, ScalarFunctionInfo> functions);
|
||||
void SetJournalMode(const std::string &journalMode);
|
||||
|
||||
void EnableRekey(bool enable);
|
||||
|
||||
|
@ -18,10 +18,14 @@
|
||||
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include "sys/types.h"
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "logger.h"
|
||||
#include "common.h"
|
||||
#include "sqlite_utils.h"
|
||||
#include "file_ex.h"
|
||||
#include "rdb_common.h"
|
||||
#include "rdb_errno.h"
|
||||
#include "rdb_helper.h"
|
||||
@ -43,8 +47,10 @@ public:
|
||||
void CheckBlob(std::shared_ptr<ResultSet> &resultSet);
|
||||
void CheckNumber(std::shared_ptr<RdbStore> &store, int num, int errCode = E_OK,
|
||||
const std::string &tableName = "test");
|
||||
void Insert(int64_t start, int count, bool isSlave = false);
|
||||
void WaitForBackupFinish(int32_t expectStatus);
|
||||
void Insert(int64_t start, int count, bool isSlave = false, int dataSize = 0);
|
||||
void WaitForBackupFinish(int32_t expectStatus, int maxTimes = 400);
|
||||
void TryInterruptBackup();
|
||||
void InitDb();
|
||||
|
||||
static const std::string DATABASE_NAME;
|
||||
static const std::string SLAVE_DATABASE_NAME;
|
||||
@ -102,6 +108,17 @@ void RdbDoubleWriteTest::TearDownTestCase(void)
|
||||
}
|
||||
|
||||
void RdbDoubleWriteTest::SetUp(void)
|
||||
{
|
||||
}
|
||||
|
||||
void RdbDoubleWriteTest::TearDown(void)
|
||||
{
|
||||
store = nullptr;
|
||||
slaveStore = nullptr;
|
||||
RdbHelper::DeleteRdbStore(RdbDoubleWriteTest::DATABASE_NAME);
|
||||
}
|
||||
|
||||
void RdbDoubleWriteTest::InitDb()
|
||||
{
|
||||
int errCode = E_OK;
|
||||
RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME);
|
||||
@ -118,13 +135,6 @@ void RdbDoubleWriteTest::SetUp(void)
|
||||
slaveStore->ExecuteSql("DELETE FROM test");
|
||||
}
|
||||
|
||||
void RdbDoubleWriteTest::TearDown(void)
|
||||
{
|
||||
RdbHelper::DeleteRdbStore(RdbDoubleWriteTest::DATABASE_NAME);
|
||||
RdbHelper::DeleteRdbStore(RdbDoubleWriteTest::SLAVE_DATABASE_NAME);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(200)); // 200ms delay
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: RdbStore_DoubleWrite_001
|
||||
* @tc.desc: test RdbStore doubleWrite
|
||||
@ -132,8 +142,7 @@ void RdbDoubleWriteTest::TearDown(void)
|
||||
*/
|
||||
HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_001, TestSize.Level1)
|
||||
{
|
||||
std::shared_ptr<RdbStore> &store = RdbDoubleWriteTest::store;
|
||||
std::shared_ptr<RdbStore> &slaveStore = RdbDoubleWriteTest::slaveStore;
|
||||
InitDb();
|
||||
int64_t id;
|
||||
ValuesBucket values;
|
||||
|
||||
@ -169,7 +178,7 @@ HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_001, TestSize.Level1)
|
||||
RdbDoubleWriteTest::CheckResultSet(slaveStore);
|
||||
}
|
||||
|
||||
void RdbDoubleWriteTest::Insert(int64_t start, int count, bool isSlave)
|
||||
void RdbDoubleWriteTest::Insert(int64_t start, int count, bool isSlave, int dataSize)
|
||||
{
|
||||
ValuesBucket values;
|
||||
int64_t id = start;
|
||||
@ -177,7 +186,11 @@ void RdbDoubleWriteTest::Insert(int64_t start, int count, bool isSlave)
|
||||
for (int i = 0; i < count; i++) {
|
||||
values.Clear();
|
||||
values.PutInt("id", id);
|
||||
values.PutString("name", std::string("zhangsan"));
|
||||
if (dataSize > 0) {
|
||||
values.PutString("name", std::string(dataSize, 'a'));
|
||||
} else {
|
||||
values.PutString("name", std::string("zhangsan"));
|
||||
}
|
||||
values.PutInt("age", CHECKAGE);
|
||||
values.PutDouble("salary", CHECKCOLUMN);
|
||||
values.PutBlob("blobType", std::vector<uint8_t>{ 1, 2, 3 });
|
||||
@ -191,17 +204,29 @@ void RdbDoubleWriteTest::Insert(int64_t start, int count, bool isSlave)
|
||||
}
|
||||
}
|
||||
|
||||
void RdbDoubleWriteTest::WaitForBackupFinish(int32_t expectStatus)
|
||||
void RdbDoubleWriteTest::WaitForBackupFinish(int32_t expectStatus, int maxTimes)
|
||||
{
|
||||
int32_t curStatus = store->GetBackupStatus();
|
||||
int tryTimes = 0;
|
||||
while (curStatus != expectStatus && (++tryTimes <= 5)) { // 5 is try time
|
||||
usleep(50000); // 50000 is wait time
|
||||
while (curStatus != expectStatus && (++tryTimes <= maxTimes)) {
|
||||
usleep(50000); // 50000 delay
|
||||
curStatus = store->GetBackupStatus();
|
||||
}
|
||||
LOG_INFO("----------cur backup Status:%{public}d---------", curStatus);
|
||||
ASSERT_EQ(curStatus, expectStatus);
|
||||
}
|
||||
|
||||
void RdbDoubleWriteTest::TryInterruptBackup()
|
||||
{
|
||||
int err = store->InterruptBackup();
|
||||
int tryTimes = 0;
|
||||
while (err != E_OK && (++tryTimes <= 1000)) { // 1000 is try time
|
||||
usleep(10000); // 10000 delay
|
||||
err = store->InterruptBackup();
|
||||
}
|
||||
EXPECT_EQ(err, E_OK);
|
||||
LOG_INFO("----------interrupt backup---------");
|
||||
}
|
||||
|
||||
void RdbDoubleWriteTest::CheckResultSet(std::shared_ptr<RdbStore> &store)
|
||||
{
|
||||
@ -316,32 +341,7 @@ void RdbDoubleWriteTest::CheckNumber(std::shared_ptr<RdbStore> &store, int num,
|
||||
EXPECT_EQ(ret, errCode);
|
||||
EXPECT_EQ(num, countNum);
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: RdbStore_DoubleWrite_002
|
||||
* @tc.desc: test RdbStore waL limit
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_002, TestSize.Level1)
|
||||
{
|
||||
std::shared_ptr<RdbStore> &store = RdbDoubleWriteTest::store;
|
||||
std::shared_ptr<RdbStore> &slaveStore = RdbDoubleWriteTest::slaveStore;
|
||||
int64_t id = 10;
|
||||
ValuesBucket values;
|
||||
for (int i = 0; i < 25158; i++) {
|
||||
id++;
|
||||
values.Clear();
|
||||
values.PutInt("id", id);
|
||||
values.PutString("name", std::string("zhangsan"));
|
||||
values.PutInt("age", CHECKAGE);
|
||||
values.PutDouble("salary", CHECKCOLUMN);
|
||||
values.PutBlob("blobType", std::vector<uint8_t>{ 1, 2, 3 });
|
||||
int ret = store->Insert(id, "test", values);
|
||||
EXPECT_EQ(ret, E_OK);
|
||||
}
|
||||
RdbDoubleWriteTest::CheckNumber(slaveStore, 25158);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @tc.name: RdbStore_DoubleWrite_003
|
||||
* @tc.desc: test RdbStore execute
|
||||
@ -349,8 +349,7 @@ HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_002, TestSize.Level1)
|
||||
*/
|
||||
HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_003, TestSize.Level1)
|
||||
{
|
||||
std::shared_ptr<RdbStore> &store = RdbDoubleWriteTest::store;
|
||||
std::shared_ptr<RdbStore> &slaveStore = RdbDoubleWriteTest::slaveStore;
|
||||
InitDb();
|
||||
|
||||
int64_t id;
|
||||
ValuesBucket values;
|
||||
@ -374,8 +373,7 @@ HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_003, TestSize.Level1)
|
||||
*/
|
||||
HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_004, TestSize.Level1)
|
||||
{
|
||||
std::shared_ptr<RdbStore> &store = RdbDoubleWriteTest::store;
|
||||
std::shared_ptr<RdbStore> &slaveStore = RdbDoubleWriteTest::slaveStore;
|
||||
InitDb();
|
||||
|
||||
int64_t id;
|
||||
|
||||
@ -404,8 +402,7 @@ HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_004, TestSize.Level1)
|
||||
*/
|
||||
HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_005, TestSize.Level1)
|
||||
{
|
||||
std::shared_ptr<RdbStore> &store = RdbDoubleWriteTest::store;
|
||||
std::shared_ptr<RdbStore> &slaveStore = RdbDoubleWriteTest::slaveStore;
|
||||
InitDb();
|
||||
|
||||
ValuesBucket values;
|
||||
int64_t id;
|
||||
@ -454,9 +451,6 @@ HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_005, TestSize.Level1)
|
||||
*/
|
||||
HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_007, TestSize.Level1)
|
||||
{
|
||||
RdbHelper::DeleteRdbStore(RdbDoubleWriteTest::DATABASE_NAME);
|
||||
RdbHelper::DeleteRdbStore(RdbDoubleWriteTest::SLAVE_DATABASE_NAME);
|
||||
|
||||
int errCode = E_OK;
|
||||
RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME);
|
||||
config.SetHaMode(HAMode::SINGLE);
|
||||
@ -490,7 +484,7 @@ HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_007, TestSize.Level1)
|
||||
*/
|
||||
HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_008, TestSize.Level1)
|
||||
{
|
||||
std::shared_ptr<RdbStore> &store = RdbDoubleWriteTest::store;
|
||||
InitDb();
|
||||
int64_t id = 10;
|
||||
int count = 100;
|
||||
Insert(id, count);
|
||||
@ -531,6 +525,7 @@ HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_008, TestSize.Level1)
|
||||
*/
|
||||
HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_009, TestSize.Level1)
|
||||
{
|
||||
InitDb();
|
||||
int64_t id = 10;
|
||||
Insert(id, 100);
|
||||
id = 200;
|
||||
@ -548,7 +543,7 @@ HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_009, TestSize.Level1)
|
||||
*/
|
||||
HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_010, TestSize.Level1)
|
||||
{
|
||||
std::shared_ptr<RdbStore> &store = RdbDoubleWriteTest::store;
|
||||
InitDb();
|
||||
int64_t id = 10;
|
||||
int count = 100;
|
||||
Insert(id, count);
|
||||
@ -581,7 +576,7 @@ HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_010, TestSize.Level1)
|
||||
RdbDoubleWriteTest::slaveStore = RdbHelper::GetRdbStore(slaveConfig, 1, slaveHelper, errCode);
|
||||
EXPECT_NE(RdbDoubleWriteTest::slaveStore, nullptr);
|
||||
LOG_INFO("RdbStore_DoubleWrite_010 reopen slave db finish");
|
||||
|
||||
WaitForBackupFinish(BACKUP_FINISHED);
|
||||
RdbDoubleWriteTest::CheckNumber(slaveStore, count);
|
||||
}
|
||||
|
||||
@ -592,7 +587,7 @@ HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_010, TestSize.Level1)
|
||||
*/
|
||||
HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_011, TestSize.Level1)
|
||||
{
|
||||
std::shared_ptr<RdbStore> &store = RdbDoubleWriteTest::store;
|
||||
InitDb();
|
||||
int64_t id = 10;
|
||||
int count = 100;
|
||||
Insert(id, count);
|
||||
@ -630,8 +625,7 @@ HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_011, TestSize.Level1)
|
||||
*/
|
||||
HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_012, TestSize.Level1)
|
||||
{
|
||||
std::shared_ptr<RdbStore> &store = RdbDoubleWriteTest::store;
|
||||
std::shared_ptr<RdbStore> &slaveStore = RdbDoubleWriteTest::slaveStore;
|
||||
InitDb();
|
||||
|
||||
int err = store->BeginTransaction();
|
||||
EXPECT_EQ(err, E_OK);
|
||||
@ -659,9 +653,6 @@ HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_012, TestSize.Level1)
|
||||
*/
|
||||
HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_013, TestSize.Level1)
|
||||
{
|
||||
RdbHelper::DeleteRdbStore(RdbDoubleWriteTest::DATABASE_NAME);
|
||||
RdbHelper::DeleteRdbStore(RdbDoubleWriteTest::SLAVE_DATABASE_NAME);
|
||||
|
||||
int errCode = E_OK;
|
||||
RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME);
|
||||
config.SetHaMode(HAMode::MANUAL_TRIGGER);
|
||||
@ -703,9 +694,6 @@ HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_013, TestSize.Level1)
|
||||
*/
|
||||
HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_014, TestSize.Level1)
|
||||
{
|
||||
RdbHelper::DeleteRdbStore(RdbDoubleWriteTest::DATABASE_NAME);
|
||||
RdbHelper::DeleteRdbStore(RdbDoubleWriteTest::SLAVE_DATABASE_NAME);
|
||||
|
||||
int errCode = E_OK;
|
||||
RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME);
|
||||
config.SetHaMode(HAMode::MANUAL_TRIGGER);
|
||||
@ -745,6 +733,7 @@ HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_014, TestSize.Level1)
|
||||
*/
|
||||
HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_015, TestSize.Level1)
|
||||
{
|
||||
InitDb();
|
||||
int64_t id = 10;
|
||||
int count = 100;
|
||||
ValuesBucket values;
|
||||
@ -800,12 +789,14 @@ HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_015, TestSize.Level1)
|
||||
*/
|
||||
HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_016, TestSize.Level1)
|
||||
{
|
||||
InitDb();
|
||||
int64_t id = 10;
|
||||
int count = 100;
|
||||
Insert(id, count);
|
||||
LOG_INFO("RdbStore_DoubleWrite_016 insert finish");
|
||||
|
||||
store = nullptr;
|
||||
LOG_INFO("RdbStore_DoubleWrite_016 close finish");
|
||||
|
||||
SqliteUtils::DeleteFile(DATABASE_NAME);
|
||||
SqliteUtils::DeleteFile(DATABASE_NAME + "-shm");
|
||||
@ -821,21 +812,92 @@ HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_016, TestSize.Level1)
|
||||
ASSERT_NE(store, nullptr);
|
||||
LOG_INFO("RdbStore_DoubleWrite_016 reopen db finish");
|
||||
|
||||
WaitForBackupFinish(BACKUP_FINISHED);
|
||||
|
||||
RdbDoubleWriteTest::CheckNumber(store, count);
|
||||
RdbDoubleWriteTest::CheckNumber(slaveStore, count);
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: RdbStore_DoubleWrite_017
|
||||
* @tc.desc: open MAIN_REPLICA db, write, close, reopen, corrupt db, restore, check count
|
||||
* @tc.name: RdbStore_DoubleWrite_018
|
||||
* @tc.desc: open MAIN_REPLICA db, update slave, insert, M succ && S failed,
|
||||
* check failureFlag, backup, check failureFlag
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_017, TestSize.Level1)
|
||||
HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_018, TestSize.Level1)
|
||||
{
|
||||
int64_t id = 10;
|
||||
int count = 100;
|
||||
Insert(id, count);
|
||||
LOG_INFO("RdbStore_DoubleWrite_017 insert finish");
|
||||
InitDb();
|
||||
|
||||
int64_t id;
|
||||
ValuesBucket values;
|
||||
values.PutInt("id", 1);
|
||||
values.PutString("name", std::string("zhangsan"));
|
||||
values.PutInt("age", 25);
|
||||
values.PutDouble("salary", CHECKCOLUMN);
|
||||
values.PutBlob("blobType", std::vector<uint8_t>{ 1, 2, 3 });
|
||||
int ret = store->Insert(id, "test", values);
|
||||
EXPECT_EQ(ret, E_OK);
|
||||
|
||||
auto [ret2, outValue2] = slaveStore->Execute("UPDATE test SET id = 3 WHERE id = 1");
|
||||
EXPECT_EQ(E_OK, ret2);
|
||||
|
||||
int64_t id2;
|
||||
ValuesBucket values2;
|
||||
values2.PutInt("id", 3);
|
||||
values2.PutString("name", std::string("zhangsan"));
|
||||
values2.PutInt("age", 25);
|
||||
values2.PutDouble("salary", CHECKCOLUMN);
|
||||
values2.PutBlob("blobType", std::vector<uint8_t>{ 1, 2, 3 });
|
||||
int ret3 = store->Insert(id2, "test", values2);
|
||||
EXPECT_EQ(E_OK, ret3);
|
||||
std::string failureFlagPath = RdbDoubleWriteTest::DATABASE_NAME + + "-slaveFailure";
|
||||
bool isFlagFileExists = OHOS::FileExists(failureFlagPath);
|
||||
ASSERT_TRUE(isFlagFileExists);
|
||||
ASSERT_TRUE(store->IsSlaveDiffFromMaster());
|
||||
|
||||
int errCode;
|
||||
errCode = store->Backup(std::string(""), {});
|
||||
EXPECT_EQ(errCode, E_OK);
|
||||
isFlagFileExists = OHOS::FileExists(failureFlagPath);
|
||||
ASSERT_FALSE(isFlagFileExists);
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: RdbStore_DoubleWrite_019
|
||||
* @tc.desc: open MAIN_REPLICA db, update slave, insert, M succ && S failed,
|
||||
* check failureFlag, reopen, check failureFlag
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_019, TestSize.Level1)
|
||||
{
|
||||
InitDb();
|
||||
|
||||
int64_t id;
|
||||
ValuesBucket values;
|
||||
values.PutInt("id", 1);
|
||||
values.PutString("name", std::string("zhangsan"));
|
||||
values.PutInt("age", 25);
|
||||
values.PutDouble("salary", CHECKCOLUMN);
|
||||
values.PutBlob("blobType", std::vector<uint8_t>{ 1, 2, 3 });
|
||||
int ret = store->Insert(id, "test", values);
|
||||
EXPECT_EQ(ret, E_OK);
|
||||
|
||||
auto [ret2, outValue2] = slaveStore->Execute("UPDATE test SET id = 3 WHERE id = 1");
|
||||
EXPECT_EQ(E_OK, ret2);
|
||||
|
||||
int64_t id2;
|
||||
ValuesBucket values2;
|
||||
values2.PutInt("id", 3);
|
||||
values2.PutString("name", std::string("zhangsan"));
|
||||
values2.PutInt("age", 25);
|
||||
values2.PutDouble("salary", CHECKCOLUMN);
|
||||
values2.PutBlob("blobType", std::vector<uint8_t>{ 1, 2, 3 });
|
||||
int ret3 = store->Insert(id2, "test", values2);
|
||||
EXPECT_EQ(E_OK, ret3);
|
||||
std::string failureFlagPath = RdbDoubleWriteTest::DATABASE_NAME + + "-slaveFailure";
|
||||
bool isFlagFileExists = OHOS::FileExists(failureFlagPath);
|
||||
ASSERT_TRUE(isFlagFileExists);
|
||||
ASSERT_TRUE(store->IsSlaveDiffFromMaster());
|
||||
|
||||
store = nullptr;
|
||||
RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME);
|
||||
@ -844,23 +906,333 @@ HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_017, TestSize.Level1)
|
||||
DoubleWriteTestOpenCallback helper;
|
||||
int errCode;
|
||||
store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
|
||||
WaitForBackupFinish(BACKUP_FINISHED);
|
||||
store = nullptr;
|
||||
isFlagFileExists = OHOS::FileExists(failureFlagPath);
|
||||
ASSERT_FALSE(isFlagFileExists);
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: RdbStore_DoubleWrite_022
|
||||
* @tc.desc: open SINGLE db, write, close, reopen MAIN_REPLICA db, wait for backup, insert, check count
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_022, TestSize.Level1)
|
||||
{
|
||||
int errCode = E_OK;
|
||||
RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME);
|
||||
config.SetHaMode(HAMode::SINGLE);
|
||||
DoubleWriteTestOpenCallback helper;
|
||||
store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
|
||||
EXPECT_NE(store, nullptr);
|
||||
|
||||
int64_t id = 10;
|
||||
int strSize = 1024 * 100;
|
||||
int count = 2000;
|
||||
Insert(id, count, false, strSize);
|
||||
LOG_INFO("RdbStore_DoubleWrite_022 insert finish");
|
||||
|
||||
store = nullptr;
|
||||
config.SetHaMode(HAMode::MAIN_REPLICA);
|
||||
store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
|
||||
ASSERT_NE(store, nullptr);
|
||||
LOG_INFO("RdbStore_DoubleWrite_022 reopen db finish");
|
||||
|
||||
WaitForBackupFinish(BACKUP_FINISHED);
|
||||
|
||||
id = 6666;
|
||||
Insert(id, count);
|
||||
LOG_INFO("RdbStore_DoubleWrite_022 insert db finish");
|
||||
|
||||
RdbStoreConfig slaveConfig(RdbDoubleWriteTest::SLAVE_DATABASE_NAME);
|
||||
DoubleWriteTestOpenCallback slaveHelper;
|
||||
RdbDoubleWriteTest::slaveStore = RdbHelper::GetRdbStore(slaveConfig, 1, slaveHelper, errCode);
|
||||
EXPECT_NE(RdbDoubleWriteTest::slaveStore, nullptr);
|
||||
LOG_INFO("RdbStore_DoubleWrite_022 reopen slave db finish");
|
||||
|
||||
RdbDoubleWriteTest::CheckNumber(store, count + count);
|
||||
RdbDoubleWriteTest::CheckNumber(slaveStore, count + count);
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: RdbStore_DoubleWrite_023
|
||||
* @tc.desc: open MANUAL_TRIGGER db, write, backup async, interrupt, backup async, wait finish, check count
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_023, TestSize.Level1)
|
||||
{
|
||||
int errCode = E_OK;
|
||||
RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME);
|
||||
config.SetHaMode(HAMode::MANUAL_TRIGGER);
|
||||
DoubleWriteTestOpenCallback helper;
|
||||
store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
|
||||
EXPECT_NE(store, nullptr);
|
||||
ASSERT_TRUE(store->IsSlaveDiffFromMaster());
|
||||
LOG_INFO("RdbStore_DoubleWrite_023 reopen finish");
|
||||
|
||||
int64_t id = 10;
|
||||
int strSize = 1024 * 100;
|
||||
int count = 2000;
|
||||
Insert(id, count, false, strSize);
|
||||
LOG_INFO("RdbStore_DoubleWrite_023 insert finish");
|
||||
|
||||
std::thread thread([this]() {
|
||||
LOG_INFO("RdbStore_DoubleWrite_023 t1 backup begin");
|
||||
EXPECT_EQ(store->Backup(std::string(""), {}), E_BACKUP_INTERRUPT);
|
||||
LOG_INFO("RdbStore_DoubleWrite_023 t1 backup end");
|
||||
});
|
||||
LOG_INFO("RdbStore_DoubleWrite_023 begin interrupt");
|
||||
TryInterruptBackup();
|
||||
LOG_INFO("RdbStore_DoubleWrite_023 interrupt end");
|
||||
EXPECT_EQ(store->GetBackupStatus(), SlaveStatus::BACKUP_INTERRUPT);
|
||||
thread.join();
|
||||
|
||||
std::thread thread1([this]() {
|
||||
LOG_INFO("RdbStore_DoubleWrite_023 t2 backup begin");
|
||||
EXPECT_EQ(store->Backup(std::string(""), {}), E_OK);
|
||||
LOG_INFO("RdbStore_DoubleWrite_023 t2 backup end");
|
||||
});
|
||||
WaitForBackupFinish(BACKUP_FINISHED);
|
||||
LOG_INFO("RdbStore_DoubleWrite_023 wait finish");
|
||||
thread1.join();
|
||||
|
||||
RdbStoreConfig slaveConfig(RdbDoubleWriteTest::SLAVE_DATABASE_NAME);
|
||||
DoubleWriteTestOpenCallback slaveHelper;
|
||||
RdbDoubleWriteTest::slaveStore = RdbHelper::GetRdbStore(slaveConfig, 1, slaveHelper, errCode);
|
||||
EXPECT_NE(RdbDoubleWriteTest::slaveStore, nullptr);
|
||||
LOG_INFO("RdbStore_DoubleWrite_023 reopen slave db finish");
|
||||
|
||||
RdbDoubleWriteTest::CheckNumber(store, count);
|
||||
RdbDoubleWriteTest::CheckNumber(slaveStore, count);
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: RdbStore_DoubleWrite_024
|
||||
* @tc.desc: open SINGLE db, write, close, reopen MAIN_REPLICA db, wait for backup, insert, check count
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_024, TestSize.Level1)
|
||||
{
|
||||
int errCode = E_OK;
|
||||
RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME);
|
||||
config.SetHaMode(HAMode::SINGLE);
|
||||
DoubleWriteTestOpenCallback helper;
|
||||
store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
|
||||
EXPECT_NE(store, nullptr);
|
||||
|
||||
int64_t id = 10;
|
||||
int strSize = 1024 * 200;
|
||||
int count = 1000;
|
||||
Insert(id, count, false, strSize);
|
||||
LOG_INFO("RdbStore_DoubleWrite_024 insert finish");
|
||||
|
||||
store = nullptr;
|
||||
LOG_INFO("RdbStore_DoubleWrite_024 close finish");
|
||||
config.SetHaMode(HAMode::MAIN_REPLICA);
|
||||
store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
|
||||
ASSERT_NE(store, nullptr);
|
||||
LOG_INFO("RdbStore_DoubleWrite_024 reopen db finish");
|
||||
|
||||
usleep(200000); // 200000 us delay
|
||||
store = nullptr;
|
||||
LOG_INFO("RdbStore_DoubleWrite_024 close again");
|
||||
|
||||
RdbStoreConfig slaveConfig(RdbDoubleWriteTest::SLAVE_DATABASE_NAME);
|
||||
DoubleWriteTestOpenCallback slaveHelper;
|
||||
RdbDoubleWriteTest::slaveStore = RdbHelper::GetRdbStore(slaveConfig, 1, slaveHelper, errCode);
|
||||
EXPECT_NE(RdbDoubleWriteTest::slaveStore, nullptr);
|
||||
LOG_INFO("RdbStore_DoubleWrite_024 reopen slave");
|
||||
RdbDoubleWriteTest::CheckNumber(slaveStore, count);
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: RdbStore_DoubleWrite_025
|
||||
* @tc.desc: open SINGLE db, write, close, reopen MAIN_REPLICA db, insert, wait for backup, check count
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_025, TestSize.Level1)
|
||||
{
|
||||
int errCode = E_OK;
|
||||
RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME);
|
||||
config.SetHaMode(HAMode::SINGLE);
|
||||
DoubleWriteTestOpenCallback helper;
|
||||
store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
|
||||
EXPECT_NE(store, nullptr);
|
||||
|
||||
int64_t id = 10;
|
||||
int strSize = 1024 * 200;
|
||||
int count = 1000;
|
||||
Insert(id, count, false, strSize);
|
||||
LOG_INFO("RdbStore_DoubleWrite_025 insert finish");
|
||||
|
||||
store = nullptr;
|
||||
LOG_INFO("RdbStore_DoubleWrite_025 close finish");
|
||||
config.SetHaMode(HAMode::MAIN_REPLICA);
|
||||
store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
|
||||
ASSERT_NE(store, nullptr);
|
||||
LOG_INFO("RdbStore_DoubleWrite_025 reopen db finish");
|
||||
|
||||
id = 6666;
|
||||
LOG_INFO("RdbStore_DoubleWrite_025 begin insert");
|
||||
Insert(id, count, false, strSize);
|
||||
LOG_INFO("RdbStore_DoubleWrite_025 insert end");
|
||||
|
||||
WaitForBackupFinish(BACKUP_FINISHED, 1000); // 1000 is max retry time
|
||||
LOG_INFO("RdbStore_DoubleWrite_025 wait finish");
|
||||
|
||||
RdbStoreConfig slaveConfig(RdbDoubleWriteTest::SLAVE_DATABASE_NAME);
|
||||
DoubleWriteTestOpenCallback slaveHelper;
|
||||
RdbDoubleWriteTest::slaveStore = RdbHelper::GetRdbStore(slaveConfig, 1, slaveHelper, errCode);
|
||||
EXPECT_NE(RdbDoubleWriteTest::slaveStore, nullptr);
|
||||
LOG_INFO("RdbStore_DoubleWrite_025 reopen slave");
|
||||
|
||||
RdbDoubleWriteTest::CheckNumber(store, count + count);
|
||||
std::shared_ptr<ResultSet> resultSet = slaveStore->QuerySql("SELECT * FROM test");
|
||||
ASSERT_NE(resultSet, nullptr);
|
||||
int countNum;
|
||||
EXPECT_EQ(resultSet->GetRowCount(countNum), errCode);
|
||||
EXPECT_GT(countNum, count);
|
||||
EXPECT_LE(countNum, count + count);
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: RdbStore_DoubleWrite_026
|
||||
* @tc.desc: open MANUAL_TRIGGER db, write, restore, insert, check count
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_026, TestSize.Level1)
|
||||
{
|
||||
int errCode = E_OK;
|
||||
RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME);
|
||||
config.SetHaMode(HAMode::MANUAL_TRIGGER);
|
||||
DoubleWriteTestOpenCallback helper;
|
||||
store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
|
||||
EXPECT_EQ(errCode, E_OK);
|
||||
ASSERT_NE(store, nullptr);
|
||||
LOG_INFO("RdbStore_DoubleWrite_017 reopen db finish");
|
||||
|
||||
int64_t id = 10;
|
||||
int count = 100;
|
||||
Insert(id, count);
|
||||
|
||||
EXPECT_EQ(store->Restore(std::string(""), {}), E_INVALID_FILE_PATH);
|
||||
|
||||
id = 2000;
|
||||
Insert(id, count);
|
||||
RdbDoubleWriteTest::CheckNumber(store, count + count);
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: RdbStore_DoubleWrite_027
|
||||
* @tc.desc: open MANUAL_TRIGGER db, write, close, corrupt db, reopen, insert, check count
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_027, TestSize.Level1)
|
||||
{
|
||||
int errCode = E_OK;
|
||||
RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME);
|
||||
config.SetHaMode(HAMode::MANUAL_TRIGGER);
|
||||
config.SetAllowRebuild(true);
|
||||
DoubleWriteTestOpenCallback helper;
|
||||
|
||||
RdbStoreConfig slaveConfig(RdbDoubleWriteTest::SLAVE_DATABASE_NAME);
|
||||
DoubleWriteTestOpenCallback slaveHelper;
|
||||
RdbDoubleWriteTest::slaveStore = RdbHelper::GetRdbStore(slaveConfig, 1, slaveHelper, errCode);
|
||||
EXPECT_NE(RdbDoubleWriteTest::slaveStore, nullptr);
|
||||
|
||||
store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
|
||||
EXPECT_EQ(errCode, E_OK);
|
||||
ASSERT_NE(store, nullptr);
|
||||
|
||||
int64_t id = 10;
|
||||
int count = 100;
|
||||
Insert(id, count);
|
||||
RdbDoubleWriteTest::CheckNumber(slaveStore, count);
|
||||
|
||||
store = nullptr;
|
||||
|
||||
std::fstream file(DATABASE_NAME, std::ios::in | std::ios::out | std::ios::binary);
|
||||
ASSERT_TRUE(file.is_open() == true);
|
||||
file.seekp(0, std::ios::beg);
|
||||
file.seekp(30, std::ios::beg);
|
||||
ASSERT_TRUE(file.good() == true);
|
||||
char bytes[2] = {0x6, 0x6};
|
||||
file.write(bytes, 2);
|
||||
ASSERT_TRUE(file.good() == true);
|
||||
file.close();
|
||||
LOG_INFO("RdbStore_DoubleWrite_017 corrupt db finish");
|
||||
|
||||
EXPECT_EQ(store->Restore(std::string(""), {}), E_OK);
|
||||
LOG_INFO("RdbStore_DoubleWrite_017 restore db finish");
|
||||
store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
|
||||
EXPECT_EQ(errCode, E_OK);
|
||||
ASSERT_NE(store, nullptr);
|
||||
|
||||
id = 1000;
|
||||
Insert(id, count);
|
||||
RdbDoubleWriteTest::CheckNumber(store, count + count);
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: RdbStore_DoubleWrite_029
|
||||
* @tc.desc: open db, write, corrupt slave db, backup, backup, check count
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_029, TestSize.Level1)
|
||||
{
|
||||
InitDb();
|
||||
int64_t id = 10;
|
||||
int count = 100;
|
||||
Insert(id, count);
|
||||
|
||||
std::fstream slaveFile(SLAVE_DATABASE_NAME, std::ios::in | std::ios::out | std::ios::trunc);
|
||||
ASSERT_TRUE(slaveFile.is_open() == true);
|
||||
slaveFile << "0000";
|
||||
slaveFile.flush();
|
||||
slaveFile.close();
|
||||
|
||||
std::fstream slaveWalFile(SLAVE_DATABASE_NAME + "-wal", std::ios::in | std::ios::out | std::ios::trunc);
|
||||
ASSERT_TRUE(slaveWalFile.is_open() == true);
|
||||
slaveWalFile << "0000";
|
||||
slaveWalFile.flush();
|
||||
slaveWalFile.close();
|
||||
|
||||
EXPECT_NE(store->Backup(std::string(""), {}), E_OK);
|
||||
LOG_INFO("RdbStore_DoubleWrite_029 backup again");
|
||||
EXPECT_EQ(store->Backup(std::string(""), {}), E_OK);
|
||||
|
||||
RdbDoubleWriteTest::CheckNumber(store, count);
|
||||
RdbDoubleWriteTest::CheckNumber(slaveStore, -1, E_SQLITE_IOERR);
|
||||
|
||||
int errCode = E_OK;
|
||||
slaveStore = nullptr;
|
||||
RdbStoreConfig slaveConfig(RdbDoubleWriteTest::SLAVE_DATABASE_NAME);
|
||||
DoubleWriteTestOpenCallback slaveHelper;
|
||||
RdbDoubleWriteTest::slaveStore = RdbHelper::GetRdbStore(slaveConfig, 1, slaveHelper, errCode);
|
||||
EXPECT_NE(RdbDoubleWriteTest::slaveStore, nullptr);
|
||||
|
||||
RdbDoubleWriteTest::CheckNumber(slaveStore, count);
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: RdbStore_DoubleWrite_030
|
||||
* @tc.desc: open db, write, update slave, insert, check failure, restore, check count
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_030, TestSize.Level1)
|
||||
{
|
||||
InitDb();
|
||||
int64_t id = 10;
|
||||
int count = 100;
|
||||
Insert(id, count);
|
||||
|
||||
auto [ret2, outValue2] = slaveStore->Execute("UPDATE test SET id = 666 WHERE id = 22");
|
||||
EXPECT_EQ(E_OK, ret2);
|
||||
|
||||
id = 666;
|
||||
Insert(id, 1);
|
||||
|
||||
std::string failureFlagPath = RdbDoubleWriteTest::DATABASE_NAME + + "-slaveFailure";
|
||||
bool isFlagFileExists = OHOS::FileExists(failureFlagPath);
|
||||
ASSERT_TRUE(isFlagFileExists);
|
||||
|
||||
EXPECT_NE(store->Restore(std::string(""), {}), E_OK);
|
||||
|
||||
RdbDoubleWriteTest::CheckNumber(store, count + 1);
|
||||
RdbDoubleWriteTest::CheckNumber(slaveStore, count);
|
||||
}
|
@ -21,6 +21,7 @@
|
||||
|
||||
#include "common.h"
|
||||
#include "rdb_errno.h"
|
||||
#include "file_ex.h"
|
||||
|
||||
using namespace testing::ext;
|
||||
using namespace OHOS::NativeRdb;
|
||||
@ -99,4 +100,24 @@ HWTEST_F(RdbSecurityManagerTest, LockUnlock, TestSize.Level1)
|
||||
ASSERT_TRUE(afterUnlock);
|
||||
thread.join();
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: LoadSecretKeyFromDiskTest
|
||||
* @tc.desc: test load secret key from disk test
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(RdbSecurityManagerTest, LoadSecretKeyFromDiskTest, TestSize.Level1)
|
||||
{
|
||||
std::string name = "secret_key_load_test";
|
||||
auto keyPath = RDB_TEST_PATH + "key/" + name + ".pub_key";
|
||||
RdbSecurityManager::KeyFiles keyFile(keyPath);
|
||||
|
||||
const std::string file = keyFile.GetKeyFile(RdbSecurityManager::KeyFileType::PUB_KEY_FILE);
|
||||
std::vector<char> content = { 'a' };
|
||||
bool ret = OHOS::SaveBufferToFile(file, content);
|
||||
ASSERT_TRUE(ret);
|
||||
RdbPassword pwd =
|
||||
RdbSecurityManager::GetInstance().GetRdbPassword(keyPath, RdbSecurityManager::KeyFileType::PUB_KEY_FILE);
|
||||
ASSERT_EQ(pwd.GetSize(), 0);
|
||||
}
|
||||
}
|
@ -501,15 +501,16 @@ HWTEST_F(RdbStoreImplTest, Rdb_ConnectionPoolTest_0023, TestSize.Level2)
|
||||
|
||||
// newPath == currentPath, writeConnectionUsed == true
|
||||
auto connection = connectionPool->AcquireConnection(false);
|
||||
errCode = connectionPool->ChangeDbFileForRestore(newPath, backupPath, newKey);
|
||||
SlaveStatus curStatus;
|
||||
errCode = connectionPool->ChangeDbFileForRestore(newPath, backupPath, newKey, curStatus);
|
||||
EXPECT_EQ(E_ERROR, errCode);
|
||||
connection = nullptr;
|
||||
// newPath == currentPath
|
||||
errCode = connectionPool->ChangeDbFileForRestore(newPath, backupPath, newKey);
|
||||
errCode = connectionPool->ChangeDbFileForRestore(newPath, backupPath, newKey, curStatus);
|
||||
EXPECT_NE(E_OK, errCode);
|
||||
// newPath != currentPath
|
||||
const std::string newPath2 = RDB_TEST_PATH + "tmp.db";
|
||||
errCode = connectionPool->ChangeDbFileForRestore(newPath2, backupPath, newKey);
|
||||
errCode = connectionPool->ChangeDbFileForRestore(newPath2, backupPath, newKey, curStatus);
|
||||
EXPECT_EQ(E_ERROR, errCode);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user