From 9c8339151692ead9bf810a1b21fa19fff58c2302 Mon Sep 17 00:00:00 2001 From: zqq Date: Sat, 8 Nov 2025 15:42:41 +0800 Subject: [PATCH] modify db prorperties copy func as thread safe Signed-off-by: zqq --- .../common/include/schema_object.h | 4 +- .../common/src/schema_object.cpp | 33 ++++--- .../storage/include/db_properties.h | 11 ++- .../storage/include/kvdb_properties.h | 8 +- .../storage/include/relationaldb_properties.h | 10 ++- .../storage/src/db_properties.cpp | 31 +++++++ .../storage/src/kv/kvdb_properties.cpp | 29 +++++++ .../relational/relationaldb_properties.cpp | 37 +++++++- .../common/distributeddb_common_test.cpp | 87 +++++++++++++++++++ .../unittest/common/common/kv_general_ut.cpp | 2 +- 10 files changed, 225 insertions(+), 27 deletions(-) diff --git a/frameworks/libs/distributeddb/common/include/schema_object.h b/frameworks/libs/distributeddb/common/include/schema_object.h index e265565e445..106a8b3fbd5 100644 --- a/frameworks/libs/distributeddb/common/include/schema_object.h +++ b/frameworks/libs/distributeddb/common/include/schema_object.h @@ -17,6 +17,7 @@ #define SCHEMA_OBJECT_H #include +#include #include #ifndef OMIT_FLATBUFFER @@ -140,6 +141,7 @@ private: // CheckValueAndAmendIfNeed related sub methods int CheckValue(const ValueObject &inValue, std::set &lackingPaths) const; int AmendValueIfNeed(ValueObject &inValue, const std::set &lackingPaths, bool &amended) const; + void CopySchemaObject(const SchemaObject &other); // It is better using a class to represent flatBuffer-Schema related other than more private method(As well as for // Json-Schema in the future refactor). Delegation is chosen other than inheritance for accessing SchemaObject. @@ -194,7 +196,7 @@ private: SchemaObject &owner_; std::string description_; }; - + mutable std::mutex schemaMutex_; bool isValid_ = false; SchemaType schemaType_ = SchemaType::NONE; // Default NONE FlatBufferSchema flatbufferSchema_; diff --git a/frameworks/libs/distributeddb/common/src/schema_object.cpp b/frameworks/libs/distributeddb/common/src/schema_object.cpp index c4e90c6550a..fbe1c5d784f 100644 --- a/frameworks/libs/distributeddb/common/src/schema_object.cpp +++ b/frameworks/libs/distributeddb/common/src/schema_object.cpp @@ -88,28 +88,13 @@ SchemaObject::SchemaObject() : flatbufferSchema_(*this) {}; SchemaObject::SchemaObject(const SchemaObject &other) : flatbufferSchema_(*this) { - isValid_ = other.isValid_; - schemaType_ = other.schemaType_; - schemaString_ = other.schemaString_; - schemaVersion_ = other.schemaVersion_; - schemaMode_ = other.schemaMode_; - schemaSkipSize_ = other.schemaSkipSize_; - schemaIndexes_ = other.schemaIndexes_; - schemaDefine_ = other.schemaDefine_; + CopySchemaObject(other); } SchemaObject& SchemaObject::operator=(const SchemaObject &other) { if (&other != this) { - isValid_ = other.isValid_; - schemaType_ = other.schemaType_; - flatbufferSchema_.CopyFrom(other.flatbufferSchema_); - schemaString_ = other.schemaString_; - schemaVersion_ = other.schemaVersion_; - schemaMode_ = other.schemaMode_; - schemaSkipSize_ = other.schemaSkipSize_; - schemaIndexes_ = other.schemaIndexes_; - schemaDefine_ = other.schemaDefine_; + CopySchemaObject(other); } return *this; } @@ -1146,4 +1131,18 @@ int SchemaObject::AmendValueIfNeed(ValueObject &inValue, const std::set scopedLock(schemaMutex_, other.schemaMutex_); + isValid_ = other.isValid_; + schemaType_ = other.schemaType_; + flatbufferSchema_.CopyFrom(other.flatbufferSchema_); + schemaString_ = other.schemaString_; + schemaVersion_ = other.schemaVersion_; + schemaMode_ = other.schemaMode_; + schemaSkipSize_ = other.schemaSkipSize_; + schemaIndexes_ = other.schemaIndexes_; + schemaDefine_ = other.schemaDefine_; +} } // namespace DistributedDB diff --git a/frameworks/libs/distributeddb/storage/include/db_properties.h b/frameworks/libs/distributeddb/storage/include/db_properties.h index 6e4ac5976c5..117afddf3a9 100644 --- a/frameworks/libs/distributeddb/storage/include/db_properties.h +++ b/frameworks/libs/distributeddb/storage/include/db_properties.h @@ -17,6 +17,7 @@ #include #include +#include #include namespace DistributedDB { @@ -25,6 +26,12 @@ public: DBProperties() = default; virtual ~DBProperties() = default; + DBProperties(const DBProperties &other); + DBProperties &operator=(const DBProperties &other); + + DBProperties(DBProperties &&other) = delete; + DBProperties &operator=(DBProperties &&other) = delete; + // Get the string property according the name std::string GetStringProp(const std::string &name, const std::string &defaultValue) const; @@ -70,9 +77,9 @@ public: static constexpr const char *COMPRESS_ON_SYNC = "needCompressOnSync"; static constexpr const char *COMPRESSION_RATE = "compressionRate"; - protected: - + void CopyProperties(const DBProperties &other); + mutable std::mutex dataMutex_; std::map stringProperties_; std::map boolProperties_; std::map intProperties_; diff --git a/frameworks/libs/distributeddb/storage/include/kvdb_properties.h b/frameworks/libs/distributeddb/storage/include/kvdb_properties.h index 1e1e7479a3b..ada71561767 100644 --- a/frameworks/libs/distributeddb/storage/include/kvdb_properties.h +++ b/frameworks/libs/distributeddb/storage/include/kvdb_properties.h @@ -29,6 +29,12 @@ public: KvDBProperties(); ~KvDBProperties() override; + KvDBProperties(const KvDBProperties &other); + KvDBProperties &operator=(const KvDBProperties &other); + + KvDBProperties(KvDBProperties &&other) = delete; + KvDBProperties &operator=(KvDBProperties &&other) = delete; + // Get the sub directory for different type database. static std::string GetStoreSubDirectory(int type); @@ -76,8 +82,8 @@ public: static const int MULTI_VER_TYPE_SQLITE = 2; static const int SINGLE_VER_TYPE_SQLITE = 3; static const int SINGLE_VER_TYPE_RD_KERNAL = 4; - private: + void CopyKVProperties(const KvDBProperties &other); CipherType cipherType_; CipherPassword password_; SchemaObject schema_; diff --git a/frameworks/libs/distributeddb/storage/include/relationaldb_properties.h b/frameworks/libs/distributeddb/storage/include/relationaldb_properties.h index 9ff20074576..fd1a8e6499b 100644 --- a/frameworks/libs/distributeddb/storage/include/relationaldb_properties.h +++ b/frameworks/libs/distributeddb/storage/include/relationaldb_properties.h @@ -26,7 +26,13 @@ namespace DistributedDB { class RelationalDBProperties final : public DBProperties { public: RelationalDBProperties(); - ~RelationalDBProperties() override; + ~RelationalDBProperties() override = default; + + RelationalDBProperties(const RelationalDBProperties &other); + RelationalDBProperties &operator=(const RelationalDBProperties &other); + + RelationalDBProperties(RelationalDBProperties &&other) = delete; + RelationalDBProperties &operator=(RelationalDBProperties &&other) = delete; // set schema void SetSchema(const RelationalSchemaObject &schema); @@ -44,8 +50,8 @@ public: DistributedTableMode GetDistributedTableMode() const; static const std::string DISTRIBUTED_TABLE_MODE; - private: + void CopyRDBProperties(const RelationalDBProperties &other); RelationalSchemaObject schema_; bool isEncrypted_; diff --git a/frameworks/libs/distributeddb/storage/src/db_properties.cpp b/frameworks/libs/distributeddb/storage/src/db_properties.cpp index 28ae4485b4b..8cf43a11728 100644 --- a/frameworks/libs/distributeddb/storage/src/db_properties.cpp +++ b/frameworks/libs/distributeddb/storage/src/db_properties.cpp @@ -19,6 +19,7 @@ namespace DistributedDB { std::string DBProperties::GetStringProp(const std::string &name, const std::string &defaultValue) const { + std::lock_guard autoLock(dataMutex_); auto iter = stringProperties_.find(name); if (iter != stringProperties_.end()) { return iter->second; @@ -28,11 +29,13 @@ std::string DBProperties::GetStringProp(const std::string &name, const std::stri void DBProperties::SetStringProp(const std::string &name, const std::string &value) { + std::lock_guard autoLock(dataMutex_); stringProperties_[name] = value; } bool DBProperties::GetBoolProp(const std::string &name, bool defaultValue) const { + std::lock_guard autoLock(dataMutex_); auto iter = boolProperties_.find(name); if (iter != boolProperties_.end()) { return iter->second; @@ -42,11 +45,13 @@ bool DBProperties::GetBoolProp(const std::string &name, bool defaultValue) const void DBProperties::SetBoolProp(const std::string &name, bool value) { + std::lock_guard autoLock(dataMutex_); boolProperties_[name] = value; } int DBProperties::GetIntProp(const std::string &name, int defaultValue) const { + std::lock_guard autoLock(dataMutex_); auto iter = intProperties_.find(name); if (iter != intProperties_.end()) { return iter->second; @@ -56,11 +61,13 @@ int DBProperties::GetIntProp(const std::string &name, int defaultValue) const void DBProperties::SetIntProp(const std::string &name, int value) { + std::lock_guard autoLock(dataMutex_); intProperties_[name] = value; } uint32_t DBProperties::GetUIntProp(const std::string &name, uint32_t defaultValue) const { + std::lock_guard autoLock(dataMutex_); auto iter = uintProperties_.find(name); if (iter != uintProperties_.end()) { return iter->second; @@ -70,6 +77,7 @@ uint32_t DBProperties::GetUIntProp(const std::string &name, uint32_t defaultValu void DBProperties::SetUIntProp(const std::string &name, uint32_t value) { + std::lock_guard autoLock(dataMutex_); uintProperties_[name] = value; } @@ -87,4 +95,27 @@ void DBProperties::SetIdentifier(const std::string &userId, const std::string &a std::string dualIdentifier = DBCommon::TransferHashString(DBCommon::GenerateDualTupleIdentifierId(storeId, appId)); SetStringProp(DBProperties::DUAL_TUPLE_IDENTIFIER_DATA, dualIdentifier); } + +DBProperties::DBProperties(const DBProperties &other) +{ + CopyProperties(other); +} + +DBProperties &DBProperties::operator=(const DBProperties &other) +{ + if (&other == this) { + return *this; + } + CopyProperties(other); + return *this; +} + +void DBProperties::CopyProperties(const DBProperties &other) +{ + std::scoped_lock scopedLock(dataMutex_, other.dataMutex_); + stringProperties_ = other.stringProperties_; + boolProperties_ = other.boolProperties_; + intProperties_ = other.intProperties_; + uintProperties_ = other.uintProperties_; +} } \ No newline at end of file diff --git a/frameworks/libs/distributeddb/storage/src/kv/kvdb_properties.cpp b/frameworks/libs/distributeddb/storage/src/kv/kvdb_properties.cpp index 81dc2c96032..96049955b3b 100644 --- a/frameworks/libs/distributeddb/storage/src/kv/kvdb_properties.cpp +++ b/frameworks/libs/distributeddb/storage/src/kv/kvdb_properties.cpp @@ -58,23 +58,27 @@ std::string KvDBProperties::GetStoreSubDirectory(int type) void KvDBProperties::GetPassword(CipherType &type, CipherPassword &password) const { + std::lock_guard autoLock(dataMutex_); type = cipherType_; password = password_; } void KvDBProperties::SetPassword(CipherType type, const CipherPassword &password) { + std::lock_guard autoLock(dataMutex_); cipherType_ = type; password_ = password; } void KvDBProperties::SetSchema(const SchemaObject &schema) { + std::lock_guard autoLock(dataMutex_); schema_ = schema; } SchemaObject KvDBProperties::GetSchema() const { + std::lock_guard autoLock(dataMutex_); return schema_; } @@ -90,6 +94,31 @@ int KvDBProperties::GetSecFlag() const const SchemaObject &KvDBProperties::GetSchemaConstRef() const { + std::lock_guard autoLock(dataMutex_); return schema_; } + +KvDBProperties::KvDBProperties(const KvDBProperties &other) + : DBProperties(other) +{ + CopyKVProperties(other); +} + +KvDBProperties &KvDBProperties::operator=(const KvDBProperties &other) +{ + if (&other == this) { + return *this; + } + DBProperties::operator=(other); + CopyKVProperties(other); + return *this; +} + +void KvDBProperties::CopyKVProperties(const KvDBProperties &other) +{ + std::scoped_lock scopedLock(dataMutex_, other.dataMutex_); + schema_ = other.schema_; + cipherType_ = other.cipherType_; + password_ = other.password_; +} } // namespace DistributedDB diff --git a/frameworks/libs/distributeddb/storage/src/relational/relationaldb_properties.cpp b/frameworks/libs/distributeddb/storage/src/relational/relationaldb_properties.cpp index 65332e6c51e..f57d4b777ba 100644 --- a/frameworks/libs/distributeddb/storage/src/relational/relationaldb_properties.cpp +++ b/frameworks/libs/distributeddb/storage/src/relational/relationaldb_properties.cpp @@ -26,21 +26,21 @@ RelationalDBProperties::RelationalDBProperties() iterTimes_(0) {} -RelationalDBProperties::~RelationalDBProperties() -{} - void RelationalDBProperties::SetSchema(const RelationalSchemaObject &schema) { + std::lock_guard autoLock(dataMutex_); schema_ = schema; } RelationalSchemaObject RelationalDBProperties::GetSchema() const { + std::lock_guard autoLock(dataMutex_); return schema_; } void RelationalDBProperties::SetCipherArgs(CipherType cipherType, const CipherPassword &passwd, uint32_t iterTimes) { + std::lock_guard autoLock(dataMutex_); isEncrypted_ = true; cipherType_ = cipherType; passwd_ = passwd; @@ -49,21 +49,25 @@ void RelationalDBProperties::SetCipherArgs(CipherType cipherType, const CipherPa bool RelationalDBProperties::IsEncrypted() const { + std::lock_guard autoLock(dataMutex_); return isEncrypted_; } CipherType RelationalDBProperties::GetCipherType() const { + std::lock_guard autoLock(dataMutex_); return cipherType_; } const CipherPassword &RelationalDBProperties::GetPasswd() const { + std::lock_guard autoLock(dataMutex_); return passwd_; } uint32_t RelationalDBProperties::GetIterTimes() const { + std::lock_guard autoLock(dataMutex_); return iterTimes_; } @@ -72,5 +76,32 @@ DistributedTableMode RelationalDBProperties::GetDistributedTableMode() const auto defaultMode = static_cast(DistributedTableMode::SPLIT_BY_DEVICE); return static_cast(GetIntProp(RelationalDBProperties::DISTRIBUTED_TABLE_MODE, defaultMode)); } + + +RelationalDBProperties::RelationalDBProperties(const RelationalDBProperties &other) + : DBProperties(other) +{ + CopyRDBProperties(other); +} + +RelationalDBProperties &RelationalDBProperties::operator=(const RelationalDBProperties &other) +{ + if (&other == this) { + return *this; + } + DBProperties::operator=(other); + CopyRDBProperties(other); + return *this; +} + +void RelationalDBProperties::CopyRDBProperties(const RelationalDBProperties &other) +{ + std::scoped_lock scopedLock(dataMutex_, other.dataMutex_); + schema_ = other.schema_; + isEncrypted_ = other.isEncrypted_; + cipherType_ = other.cipherType_; + passwd_ = other.passwd_; + iterTimes_ = other.iterTimes_; +} } #endif \ No newline at end of file diff --git a/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_common_test.cpp b/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_common_test.cpp index 4bff8b66ede..4b322adc8ea 100644 --- a/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_common_test.cpp +++ b/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_common_test.cpp @@ -18,12 +18,14 @@ #include "db_errno.h" #include "db_common.h" #include "distributeddb_data_generate_unit_test.h" +#include "kvdb_properties.h" #include "lock_status_observer.h" #include "log_print.h" #include "platform_specific.h" #include "task_queue.h" #include "time_tick_monitor.h" #include "user_change_monitor.h" +#include "relationaldb_properties.h" #include "schema_utils.h" using namespace testing::ext; @@ -869,4 +871,89 @@ HWTEST_F(DistributedDBCommonTest, SchemaUtilsTest002, TestSize.Level0) errCode = SchemaUtils::ParseAndCheckSchemaAttribute(value, outAttr); EXPECT_EQ(errCode, E_OK); } + +void InitProperties(DBProperties &properties) +{ + std::string strKey = "strKey"; + std::string strValue = "value"; + properties.SetStringProp(strKey, strValue); + std::string intKey = "intKey"; + int intValue = 100; + properties.SetIntProp(intKey, intValue); + std::string boolKey = "boolKey"; + bool boolValue = true; + properties.SetBoolProp(boolKey, boolValue); + std::string uintKey = "uintKey"; + uint32_t uintValue = 100u; + properties.SetUIntProp(uintKey, uintValue); +} + +void CheckProperties(DBProperties &properties1, DBProperties &properties2) +{ + std::string strKey = "strKey"; + std::string strValue = "value"; + std::string intKey = "intKey"; + int intValue = 100; + std::string boolKey = "boolKey"; + bool boolValue = true; + std::string uintKey = "uintKey"; + uint32_t uintValue = 100u; + EXPECT_EQ(properties2.GetStringProp(strKey, ""), strValue); + EXPECT_EQ(properties2.GetIntProp(intKey, 0), intValue); + EXPECT_EQ(properties2.GetBoolProp(boolKey, false), boolValue); + EXPECT_EQ(properties2.GetUIntProp(uintKey, 0u), uintValue); +} + +/** + * @tc.name: PropertiesTest001 + * @tc.desc: Test KVDBProperties copy function. + * @tc.type: FUNC + * @tc.author: zqq + */ +HWTEST_F(DistributedDBCommonTest, PropertiesTest001, TestSize.Level0) +{ + KvDBProperties properties1; + CipherPassword password; + CipherType type = CipherType::AES_256_GCM; + properties1.SetPassword(type, password); + KvDBProperties properties2; + InitProperties(properties1); + properties2 = properties1; + EXPECT_NO_FATAL_FAILURE(CheckProperties(properties1, properties2)); + CipherPassword password2; + CipherType type2 = CipherType::AES_256_GCM; + properties2.GetPassword(type2, password2); + EXPECT_EQ(type, type2); + EXPECT_EQ(password, password2); + // copy self has no effect + auto flag = properties2.GetSecFlag(); + const auto ©Properties = properties2; + properties2 = copyProperties; + EXPECT_EQ(flag, properties2.GetSecFlag()); +} + +/** + * @tc.name: PropertiesTest002 + * @tc.desc: Test RDBProperties copy function. + * @tc.type: FUNC + * @tc.author: zqq + */ +HWTEST_F(DistributedDBCommonTest, PropertiesTest002, TestSize.Level0) +{ + RelationalDBProperties properties1; + properties1.SetCipherArgs(CipherType::AES_256_GCM, {}, 100); // 100 is iterTimes + RelationalDBProperties properties2; + InitProperties(properties1); + properties2 = properties1; + EXPECT_NO_FATAL_FAILURE(CheckProperties(properties1, properties2)); + EXPECT_EQ(properties1.IsEncrypted(), properties2.IsEncrypted()); + EXPECT_EQ(properties1.GetCipherType(), properties2.GetCipherType()); + EXPECT_EQ(properties1.GetPasswd(), properties2.GetPasswd()); + EXPECT_EQ(properties1.GetIterTimes(), properties2.GetIterTimes()); + // copy self has no effect + auto isEncrypted = properties2.IsEncrypted(); + const auto ©Properties = properties2; + properties2 = copyProperties; + EXPECT_EQ(isEncrypted, properties2.IsEncrypted()); +} } \ No newline at end of file diff --git a/frameworks/libs/distributeddb/test/unittest/common/common/kv_general_ut.cpp b/frameworks/libs/distributeddb/test/unittest/common/common/kv_general_ut.cpp index af120332fb2..87981799395 100644 --- a/frameworks/libs/distributeddb/test/unittest/common/common/kv_general_ut.cpp +++ b/frameworks/libs/distributeddb/test/unittest/common/common/kv_general_ut.cpp @@ -297,7 +297,7 @@ KvDBProperties KVGeneralUt::GetDBProperties(const StoreInfo &info) properties.SetStringProp(KvDBProperties::IDENTIFIER_DIR, idDir); properties.SetStringProp(KvDBProperties::IDENTIFIER_DATA, idDir + "KVGeneralUt"); properties.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::SINGLE_VER_TYPE_SQLITE); - return properties; + return static_cast(properties); } void KVGeneralUt::SetActionStatus(DBStatus status) -- Gitee