From 9bd3447f9a374c99cea3b34e805cabd2f4986352 Mon Sep 17 00:00:00 2001 From: Sven Wang Date: Thu, 16 Jun 2022 11:00:28 +0800 Subject: [PATCH 1/3] split sync and store, implement auto sync service actions Signed-off-by: Sven Wang --- .../src/distributed_kv_data_manager.cpp | 4 +- .../src/ikvstore_data_service.cpp | 2 - .../distributeddatafwk/src/itypes_util.cpp | 6 +- .../distributed_kv_data_manager_test.cpp | 1 - .../innerkitsimpl/kvdb/src/store_factory.cpp | 2 +- .../include/distributed_kv_data_manager.h | 4 +- .../innerkits/distributeddata/include/types.h | 4 +- .../app/src/dump_helper.h | 1 + .../app/src/kvstore_app_manager.cpp | 2 +- .../app/src/kvstore_data_service.cpp | 7 +- .../app/src/kvstore_meta_manager.h | 8 +- .../app/src/kvstore_resultset_impl.cpp | 4 +- .../app/src/single_kvstore_impl.cpp | 10 +- .../app/test/unittest/kvstore_backup_test.cpp | 18 +- .../framework/include/utils/constant.h | 2 + .../framework/utils/constant.cpp | 38 ++- .../distributeddataservice/service/BUILD.gn | 4 + .../service/crypto/include/crypto_manager.h | 43 +++ .../service/crypto/src/crypto_manager.cpp | 189 ++++++++++++ .../service/kvdb/kvdb_service_impl.cpp | 269 +++++++++++++++--- .../service/kvdb/kvdb_service_impl.h | 45 ++- .../service/kvdb/store_cache.cpp | 143 ++++++++++ .../service/kvdb/store_cache.h | 59 ++++ 23 files changed, 780 insertions(+), 85 deletions(-) create mode 100644 services/distributeddataservice/service/crypto/include/crypto_manager.h create mode 100644 services/distributeddataservice/service/crypto/src/crypto_manager.cpp create mode 100644 services/distributeddataservice/service/kvdb/store_cache.cpp create mode 100644 services/distributeddataservice/service/kvdb/store_cache.h diff --git a/frameworks/innerkitsimpl/distributeddatafwk/src/distributed_kv_data_manager.cpp b/frameworks/innerkitsimpl/distributeddatafwk/src/distributed_kv_data_manager.cpp index 5278c59da..5e2fcc071 100644 --- a/frameworks/innerkitsimpl/distributeddatafwk/src/distributed_kv_data_manager.cpp +++ b/frameworks/innerkitsimpl/distributeddatafwk/src/distributed_kv_data_manager.cpp @@ -153,7 +153,7 @@ Status DistributedKvDataManager::CloseAllKvStore(const AppId &appId) return Status::SERVER_UNAVAILABLE; } -Status DistributedKvDataManager::DeleteKvStore(const AppId &appId, const StoreId &storeId) +Status DistributedKvDataManager::DeleteKvStore(const AppId &appId, const StoreId &storeId, const std::string &path) { DdsTrace trace(std::string(LOG_TAG "::") + std::string(__FUNCTION__), TraceSwitch::BYTRACE_ON | TraceSwitch::TRACE_CHAIN_ON); @@ -173,7 +173,7 @@ Status DistributedKvDataManager::DeleteKvStore(const AppId &appId, const StoreId return Status::SERVER_UNAVAILABLE; } -Status DistributedKvDataManager::DeleteAllKvStore(const AppId &appId) +Status DistributedKvDataManager::DeleteAllKvStore(const AppId &appId, const std::string &path) { DdsTrace trace(std::string(LOG_TAG "::") + std::string(__FUNCTION__), TraceSwitch::BYTRACE_ON | TraceSwitch::TRACE_CHAIN_ON); diff --git a/frameworks/innerkitsimpl/distributeddatafwk/src/ikvstore_data_service.cpp b/frameworks/innerkitsimpl/distributeddatafwk/src/ikvstore_data_service.cpp index 3dce5cf00..dba8e235f 100644 --- a/frameworks/innerkitsimpl/distributeddatafwk/src/ikvstore_data_service.cpp +++ b/frameworks/innerkitsimpl/distributeddatafwk/src/ikvstore_data_service.cpp @@ -59,7 +59,6 @@ Status KvStoreDataServiceProxy::GetSingleKvStore(const Options &options, const A optionsIpc.syncPolicy = options.syncPolicy; optionsIpc.kvStoreType = options.kvStoreType; optionsIpc.syncable = options.syncable; - optionsIpc.dataOwnership = true; // set default value std::string schemaString = options.schema; if (!data.WriteBuffer(&optionsIpc, sizeof(OptionsIpc)) || @@ -515,7 +514,6 @@ int32_t KvStoreDataServiceStub::GetSingleKvStoreOnRemote(MessageParcel &data, Me options.syncPolicy = optionsIpc.syncPolicy; options.kvStoreType = optionsIpc.kvStoreType; options.syncable = optionsIpc.syncable; - options.dataOwnership = optionsIpc.dataOwnership; options.schema = data.ReadString(); sptr proxyTmp; Status status = GetSingleKvStore(options, appId, storeId, diff --git a/frameworks/innerkitsimpl/distributeddatafwk/src/itypes_util.cpp b/frameworks/innerkitsimpl/distributeddatafwk/src/itypes_util.cpp index 20c1a811d..e1b46f8db 100644 --- a/frameworks/innerkitsimpl/distributeddatafwk/src/itypes_util.cpp +++ b/frameworks/innerkitsimpl/distributeddatafwk/src/itypes_util.cpp @@ -348,11 +348,11 @@ bool ITypesUtil::Marshalling(const Options &input, MessageParcel &data) target->persistent = input.persistent; target->backup = input.backup; target->autoSync = input.autoSync; + target->syncable = input.syncable; target->securityLevel = input.securityLevel; + target->area = input.area; target->syncPolicy = input.syncPolicy; target->kvStoreType = input.kvStoreType; - target->syncable = input.syncable; - target->dataOwnership = input.dataOwnership; return data.WriteRawData(buffer.get(), sizeof(input)); } @@ -372,10 +372,10 @@ bool ITypesUtil::Unmarshalling(Options &output, MessageParcel &data) output.backup = source->backup; output.autoSync = source->autoSync; output.securityLevel = source->securityLevel; + output.area = source->area; output.syncPolicy = source->syncPolicy; output.kvStoreType = source->kvStoreType; output.syncable = source->syncable; - output.dataOwnership = source->dataOwnership; return true; } diff --git a/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/distributed_kv_data_manager_test.cpp b/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/distributed_kv_data_manager_test.cpp index 76551654c..3d0e3dcea 100644 --- a/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/distributed_kv_data_manager_test.cpp +++ b/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/distributed_kv_data_manager_test.cpp @@ -89,7 +89,6 @@ void DistributedKvDataManagerTest::SetUpTestCase(void) noCreate.createIfMissing = false; noCreate.encrypt = false; noCreate.autoSync = true; - noCreate.dataOwnership = true; noCreate.kvStoreType = SINGLE_VERSION; userId.userId = "account0"; diff --git a/frameworks/innerkitsimpl/kvdb/src/store_factory.cpp b/frameworks/innerkitsimpl/kvdb/src/store_factory.cpp index 61b571a64..745d1355c 100644 --- a/frameworks/innerkitsimpl/kvdb/src/store_factory.cpp +++ b/frameworks/innerkitsimpl/kvdb/src/store_factory.cpp @@ -138,7 +138,7 @@ StoreFactory::DBOption StoreFactory::GetDBOption(const Options &options, const D } dbOption.schema = options.schema; - dbOption.createDirByStoreIdOnly = options.dataOwnership; + dbOption.createDirByStoreIdOnly = true; dbOption.secOption = StoreUtil::GetDBSecurity(options.securityLevel); return dbOption; } diff --git a/interfaces/innerkits/distributeddata/include/distributed_kv_data_manager.h b/interfaces/innerkits/distributeddata/include/distributed_kv_data_manager.h index d2456a462..1f644da9d 100644 --- a/interfaces/innerkits/distributeddata/include/distributed_kv_data_manager.h +++ b/interfaces/innerkits/distributeddata/include/distributed_kv_data_manager.h @@ -90,10 +90,10 @@ public: // Parameters: // appId: the name of the application. // storeId: the name of the kvstore. - API_EXPORT Status DeleteKvStore(const AppId &appId, const StoreId &storeId); + API_EXPORT Status DeleteKvStore(const AppId &appId, const StoreId &storeId, const std::string &path = ""); // delete all kvstore. - API_EXPORT Status DeleteAllKvStore(const AppId &appId); + API_EXPORT Status DeleteAllKvStore(const AppId &appId, const std::string &path = ""); API_EXPORT void RegisterKvStoreServiceDeathRecipient(std::shared_ptr deathRecipient); diff --git a/interfaces/innerkits/distributeddata/include/types.h b/interfaces/innerkits/distributeddata/include/types.h index c6828bf18..90cfcfc24 100644 --- a/interfaces/innerkits/distributeddata/include/types.h +++ b/interfaces/innerkits/distributeddata/include/types.h @@ -242,13 +242,13 @@ struct Options { bool persistent = true; bool backup = true; bool autoSync = true; + bool syncable = true; // let bms delete first int32_t securityLevel = NO_LABEL; int32_t area = EL1; SyncPolicy syncPolicy = SyncPolicy::HIGH; KvStoreType kvStoreType = DEVICE_COLLABORATION; - bool syncable = true; // let bms delete first std::string schema = ""; - bool dataOwnership = true; // true indicates the ownership of distributed data is DEVICE, otherwise, ACCOUNT + std::string baseDir = ""; inline bool IsValidType() const { diff --git a/services/distributeddataservice/app/src/dump_helper.h b/services/distributeddataservice/app/src/dump_helper.h index 77de756b3..c5fb314cf 100644 --- a/services/distributeddataservice/app/src/dump_helper.h +++ b/services/distributeddataservice/app/src/dump_helper.h @@ -20,6 +20,7 @@ #include #include #include +#include #include "store_errno.h" #include "singleton.h" diff --git a/services/distributeddataservice/app/src/kvstore_app_manager.cpp b/services/distributeddataservice/app/src/kvstore_app_manager.cpp index 95d0571d2..985392797 100644 --- a/services/distributeddataservice/app/src/kvstore_app_manager.cpp +++ b/services/distributeddataservice/app/src/kvstore_app_manager.cpp @@ -298,7 +298,7 @@ Status KvStoreAppManager::InitNbDbOption(const Options &options, const std::vect } dbOption.schema = options.schema; - dbOption.createDirByStoreIdOnly = options.dataOwnership; + dbOption.createDirByStoreIdOnly = true; dbOption.secOption = ConvertSecurity(options.securityLevel); return Status::SUCCESS; } diff --git a/services/distributeddataservice/app/src/kvstore_data_service.cpp b/services/distributeddataservice/app/src/kvstore_data_service.cpp index 89370e690..cae5b6c83 100644 --- a/services/distributeddataservice/app/src/kvstore_data_service.cpp +++ b/services/distributeddataservice/app/src/kvstore_data_service.cpp @@ -875,7 +875,11 @@ void KvStoreDataService::StartService() } auto autoLaunchRequestCallback = [this](const std::string &identifier, DistributedDB::AutoLaunchParam ¶m) -> bool { - return ResolveAutoLaunchParamByIdentifier(identifier, param); + auto status = ResolveAutoLaunchParamByIdentifier(identifier, param); + if (kvdbService_) { + kvdbService_->ResolveAutoLaunch(identifier, param); + } + return status; }; KvStoreDelegateManager::SetAutoLaunchRequestCallback(autoLaunchRequestCallback); @@ -996,7 +1000,6 @@ void KvStoreDataService::ResolveAutoLaunchCompatible(const MetaData &meta, const .autoSync = storeMeta.isAutoSync, .securityLevel = storeMeta.securityLevel, .kvStoreType = static_cast(storeMeta.kvStoreType), - .dataOwnership = true, }; DistributedDB::KvStoreNbDelegate::Option dbOptions; KvStoreAppManager::InitNbDbOption(options, meta.secretKeyMetaData.secretKey, dbOptions); diff --git a/services/distributeddataservice/app/src/kvstore_meta_manager.h b/services/distributeddataservice/app/src/kvstore_meta_manager.h index a9ce153ac..58ef4d364 100644 --- a/services/distributeddataservice/app/src/kvstore_meta_manager.h +++ b/services/distributeddataservice/app/src/kvstore_meta_manager.h @@ -200,12 +200,10 @@ public: Status WriteSecretKeyToFile(const std::string &secretKeyFile, const std::vector &key); - Status - RemoveSecretKey(pid_t uid, const std::string &bundleName, const std::string &storeId); + Status RemoveSecretKey(pid_t uid, const std::string &bundleName, const std::string &storeId); - Status - RecoverSecretKeyFromFile(const std::string &secretKeyFile, const std::vector &metaSecretKey, - std::vector &key, bool &outdated); + Status RecoverSecretKeyFromFile(const std::string &secretKeyFile, const std::vector &metaSecretKey, + std::vector &key, bool &outdated); void ReKey(const std::string &userId, const std::string &bundleName, const std::string &storeId, int32_t pathType, sptr store); diff --git a/services/distributeddataservice/app/src/kvstore_resultset_impl.cpp b/services/distributeddataservice/app/src/kvstore_resultset_impl.cpp index 0d22e3dbb..911194817 100644 --- a/services/distributeddataservice/app/src/kvstore_resultset_impl.cpp +++ b/services/distributeddataservice/app/src/kvstore_resultset_impl.cpp @@ -12,13 +12,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - #define LOG_TAG "KvStoreResultsetImpl" +#include "kvstore_resultset_impl.h" #include + #include "dds_trace.h" #include "log_print.h" -#include "kvstore_resultset_impl.h" namespace OHOS::DistributedKv { using namespace OHOS::DistributedDataDfx; diff --git a/services/distributeddataservice/app/src/single_kvstore_impl.cpp b/services/distributeddataservice/app/src/single_kvstore_impl.cpp index f834e8507..1513ce44f 100644 --- a/services/distributeddataservice/app/src/single_kvstore_impl.cpp +++ b/services/distributeddataservice/app/src/single_kvstore_impl.cpp @@ -12,28 +12,24 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - #define LOG_TAG "SingleKvStoreImpl" - #include "single_kvstore_impl.h" #include -#include "account_delegate.h" #include "auth_delegate.h" #include "backup_handler.h" #include "checker/checker_manager.h" #include "constant.h" #include "dds_trace.h" #include "device_kvstore_impl.h" -#include "kvstore_data_service.h" -#include "kvstore_utils.h" #include "ipc_skeleton.h" +#include "kvstore_utils.h" #include "log_print.h" +#include "metadata/meta_data_manager.h" #include "permission_validator.h" #include "query_helper.h" +#include "dump_helper.h" #include "reporter.h" #include "upgrade_manager.h" -#include "metadata/meta_data_manager.h" - #define DEFAUL_RETRACT " " namespace OHOS::DistributedKv { diff --git a/services/distributeddataservice/app/test/unittest/kvstore_backup_test.cpp b/services/distributeddataservice/app/test/unittest/kvstore_backup_test.cpp index 406de4f4d..bfbb15ecc 100644 --- a/services/distributeddataservice/app/test/unittest/kvstore_backup_test.cpp +++ b/services/distributeddataservice/app/test/unittest/kvstore_backup_test.cpp @@ -85,8 +85,7 @@ void KvStoreBackupTest::TearDown(void) */ HWTEST_F(KvStoreBackupTest, KvStoreBackupTest001, TestSize.Level1) { - Options options = { .createIfMissing = true, .encrypt = false, .backup = true, .autoSync = true, - .kvStoreType = KvStoreType::SINGLE_VERSION, .dataOwnership = true }; + Options options = { .kvStoreType = KvStoreType::SINGLE_VERSION}; AppId appId = { "backup1" }; StoreId storeId = { "store1" }; KvStoreDataService kvDataService; @@ -107,8 +106,7 @@ HWTEST_F(KvStoreBackupTest, KvStoreBackupTest001, TestSize.Level1) */ HWTEST_F(KvStoreBackupTest, KvStoreBackupTest002, TestSize.Level1) { - Options options = { .createIfMissing = true, .encrypt = false, .backup = true, .autoSync = true, - .kvStoreType = KvStoreType::SINGLE_VERSION, .dataOwnership = true }; + Options options = { .kvStoreType = KvStoreType::SINGLE_VERSION }; AppId appId = { "backup2" }; StoreId storeId = { "store2" }; @@ -155,8 +153,7 @@ HWTEST_F(KvStoreBackupTest, KvStoreBackupTest002, TestSize.Level1) */ HWTEST_F(KvStoreBackupTest, KvStoreBackupTest004, TestSize.Level1) { - Options options = { .createIfMissing = true, .encrypt = false, .backup = true, .autoSync = true, - .kvStoreType = KvStoreType::SINGLE_VERSION, .dataOwnership = true }; + Options options = { .kvStoreType = KvStoreType::SINGLE_VERSION}; AppId appId = { "backup4" }; StoreId storeId = { "store4" }; @@ -209,8 +206,7 @@ HWTEST_F(KvStoreBackupTest, KvStoreBackupTest004, TestSize.Level1) */ HWTEST_F(KvStoreBackupTest, KvStoreBackupTest005, TestSize.Level1) { - Options options = { .createIfMissing = true, .encrypt = false, .backup = true, .autoSync = true, - .securityLevel = SecurityLevel::S0, .kvStoreType = KvStoreType::SINGLE_VERSION, .dataOwnership = true }; + Options options = { .securityLevel = SecurityLevel::S0, .kvStoreType = KvStoreType::SINGLE_VERSION}; AppId appId = { "backup5" }; StoreId storeId = { "store5" }; @@ -257,8 +253,7 @@ HWTEST_F(KvStoreBackupTest, KvStoreBackupTest005, TestSize.Level1) */ HWTEST_F(KvStoreBackupTest, KvStoreBackupTest006, TestSize.Level1) { - Options options = { .createIfMissing = true, .encrypt = false, .backup = true, .autoSync = true, - .securityLevel = SecurityLevel::S2, .kvStoreType = KvStoreType::SINGLE_VERSION, .dataOwnership = true }; + Options options = { .securityLevel = SecurityLevel::S2, .kvStoreType = KvStoreType::SINGLE_VERSION}; AppId appId = { "backup6" }; StoreId storeId = { "store6" }; @@ -305,8 +300,7 @@ HWTEST_F(KvStoreBackupTest, KvStoreBackupTest006, TestSize.Level1) */ HWTEST_F(KvStoreBackupTest, KvStoreBackupTest007, TestSize.Level1) { - Options options = { .createIfMissing = true, .encrypt = false, .backup = true, .autoSync = true, - .securityLevel = SecurityLevel::S4, .kvStoreType = KvStoreType::SINGLE_VERSION, .dataOwnership = true }; + Options options = { .securityLevel = SecurityLevel::S4, .kvStoreType = KvStoreType::SINGLE_VERSION}; AppId appId = { "backup7" }; StoreId storeId = { "store7" }; diff --git a/services/distributeddataservice/framework/include/utils/constant.h b/services/distributeddataservice/framework/include/utils/constant.h index 41e391eb6..6d94dd363 100644 --- a/services/distributeddataservice/framework/include/utils/constant.h +++ b/services/distributeddataservice/framework/include/utils/constant.h @@ -35,6 +35,8 @@ public: API_EXPORT static std::string Join( const std::string &prefix, const std::string &separator, std::initializer_list params); + API_EXPORT static bool IsBackground(pid_t pid); + // delete left bland in s by reference. template static void LeftTrim(T &s); diff --git a/services/distributeddataservice/framework/utils/constant.cpp b/services/distributeddataservice/framework/utils/constant.cpp index d693692df..b6b777c4c 100644 --- a/services/distributeddataservice/framework/utils/constant.cpp +++ b/services/distributeddataservice/framework/utils/constant.cpp @@ -12,16 +12,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - +#define LOG_TAG "Constant" #include "utils/constant.h" + +#include #include +#include #include -#include +#include "log_print.h" namespace OHOS { namespace DistributedData { constexpr const char *Constant::KEY_SEPARATOR; - std::string Constant::Concatenate(std::initializer_list stringList) { std::string result; @@ -36,8 +38,8 @@ std::string Constant::Concatenate(std::initializer_list stringList) return result; } -std::string Constant::Join( - const std::string &prefix, const std::string &separator, std::initializer_list params) +std::string Constant::Join(const std::string &prefix, const std::string &separator, + std::initializer_list params) { std::string::size_type size = prefix.size(); for (const std::string ¶m : params) { @@ -51,5 +53,27 @@ std::string Constant::Join( } return result; } -} // namespace DistributedData -} // namespace OHOS + +bool Constant::IsBackground(pid_t pid) +{ + std::ifstream ifs("/proc/" + std::to_string(pid) + "/cgroup", std::ios::in); + ZLOGD("pid %d open %d", pid, ifs.good()); + if (!ifs.good()) { + return false; + } + + while (!ifs.eof()) { + const int MAX_LEN = 256; // enough + char buffer[MAX_LEN] = { 0 }; + ifs.getline(buffer, sizeof(buffer)); + std::string line = buffer; + + size_t pos = line.find("background"); + if (pos != std::string::npos) { + return true; + } + } + return false; +} +} // namespace DistributedData +} // namespace OHOS diff --git a/services/distributeddataservice/service/BUILD.gn b/services/distributeddataservice/service/BUILD.gn index 5b067b6b8..5acbfdc4d 100644 --- a/services/distributeddataservice/service/BUILD.gn +++ b/services/distributeddataservice/service/BUILD.gn @@ -21,6 +21,7 @@ config("module_public_config") { include_dirs = [ "bootstrap/include", "config/include", + "crypto/include", "directory/include", "kvdb", "rdb", @@ -46,6 +47,7 @@ ohos_shared_library("distributeddatasvc") { "config/src/model/global_config.cpp", "config/src/model/network_config.cpp", "config/src/model/protocol_config.cpp", + "crypto/src/crypto_manager.cpp", "directory/src/directory_manager.cpp", "kvdb/auth_delegate.cpp", "kvdb/executor_factory.cpp", @@ -53,6 +55,7 @@ ohos_shared_library("distributeddatasvc") { "kvdb/kvdb_service_stub.cpp", "kvdb/kvstore_sync_manager.cpp", "kvdb/query_helper.cpp", + "kvdb/store_cache.cpp", "kvdb/user_delegate.cpp", "object/object_manager.cpp", "object/object_service_impl.cpp", @@ -80,6 +83,7 @@ ohos_shared_library("distributeddatasvc") { "access_token:libaccesstoken_sdk", "deviceauth_standard:deviceauth_sdk", "hiviewdfx_hilog_native:libhilog", + "huks:libhukssdk", "ipc:ipc_core", ] subsystem_name = "distributeddatamgr" diff --git a/services/distributeddataservice/service/crypto/include/crypto_manager.h b/services/distributeddataservice/service/crypto/include/crypto_manager.h new file mode 100644 index 000000000..db049ee78 --- /dev/null +++ b/services/distributeddataservice/service/crypto/include/crypto_manager.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_DISTRIBUTED_DATA_SERVICES_SERVICE_CRYPTO_CRYPTO_MANAGER_H +#define OHOS_DISTRIBUTED_DATA_SERVICES_SERVICE_CRYPTO_CRYPTO_MANAGER_H +#include +#include +namespace OHOS::DistributedData { +class CryptoManager { +public: + static CryptoManager &GetInstance(); + int32_t GenerateRootKey(); + bool IsExistRootKey(); + std::vector Encrypt(const std::vector &key); + bool Decrypt(std::vector &source, std::vector &key); + +private: + static constexpr const char *ROOT_KEY_ALIAS = "distributed_db_root_key"; + static constexpr const char *HKS_BLOB_TYPE_NONCE = "Z5s0Bo571KoqwIi6"; + static constexpr const char *HKS_BLOB_TYPE_AAD = "distributeddata"; + static constexpr const char *ROOT_KEY_GENERATED = "RootKeyGenerated"; + static constexpr int KEY_SIZE = 32; + static constexpr int HOURS_PER_YEAR = (24 * 365); + CryptoManager(); + ~CryptoManager(); + std::vector vecRootKeyAlias_{}; + std::vector vecNonce_{}; + std::vector vecAad_{}; +}; +} // namespace OHOS::DistributedData +#endif // OHOS_DISTRIBUTED_DATA_SERVICES_SERVICE_CRYPTO_CRYPTO_MANAGER_H diff --git a/services/distributeddataservice/service/crypto/src/crypto_manager.cpp b/services/distributeddataservice/service/crypto/src/crypto_manager.cpp new file mode 100644 index 000000000..97a0c758f --- /dev/null +++ b/services/distributeddataservice/service/crypto/src/crypto_manager.cpp @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#define LOG_TAG "CryptoManager" +#include "crypto_manager.h" + +#include + +#include "hks_api.h" +#include "hks_param.h" +#include "log_print.h" +#include "securec.h" +namespace OHOS::DistributedData { +CryptoManager::CryptoManager() +{ + vecRootKeyAlias_ = std::vector(ROOT_KEY_ALIAS, ROOT_KEY_ALIAS + strlen(ROOT_KEY_ALIAS)); + vecNonce_ = std::vector(HKS_BLOB_TYPE_NONCE, HKS_BLOB_TYPE_NONCE + strlen(HKS_BLOB_TYPE_NONCE)); + vecAad_ = std::vector(HKS_BLOB_TYPE_AAD, HKS_BLOB_TYPE_AAD + strlen(HKS_BLOB_TYPE_AAD)); +} +CryptoManager::~CryptoManager() +{ +} + +CryptoManager &CryptoManager::GetInstance() +{ + static CryptoManager instance; + return instance; +} + +int32_t CryptoManager::GenerateRootKey() +{ + ZLOGI("GenerateRootKey."); + struct HksBlob rootKeyName = { uint32_t(vecRootKeyAlias_.size()), vecRootKeyAlias_.data() }; + struct HksParamSet *param = nullptr; + int32_t ret = HksInitParamSet(¶m); + if (ret != HKS_SUCCESS) { + ZLOGE("HksInitParamSet() failed with error %{public}d", ret); + return ret; + } + + struct HksParam genKeyParams[] = { + { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES }, + { .tag = HKS_TAG_KEY_SIZE, .uint32Param = HKS_AES_KEY_SIZE_256 }, + { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT | HKS_KEY_PURPOSE_DECRYPT }, + { .tag = HKS_TAG_DIGEST, .uint32Param = 0 }, + { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE }, + { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM }, + }; + + ret = HksAddParams(param, genKeyParams, sizeof(genKeyParams) / sizeof(genKeyParams[0])); + if (ret != HKS_SUCCESS) { + ZLOGE("HksAddParams failed with error %{public}d", ret); + HksFreeParamSet(¶m); + return ret; + } + + ret = HksBuildParamSet(¶m); + if (ret != HKS_SUCCESS) { + ZLOGE("HksBuildParamSet failed with error %{public}d", ret); + HksFreeParamSet(¶m); + return ret; + } + + ret = HksGenerateKey(&rootKeyName, param, nullptr); + if (ret != HKS_SUCCESS) { + ZLOGE("HksGenerateKey failed with error %{public}d", ret); + HksFreeParamSet(¶m); + return ret; + } + HksFreeParamSet(¶m); + ZLOGI("GenerateRootKey Succeed."); + return HKS_SUCCESS; +} + +bool CryptoManager::IsExistRootKey() +{ + return false; +} + +std::vector CryptoManager::Encrypt(const std::vector &key) +{ + struct HksBlob blobAad = { uint32_t(vecAad_.size()), vecAad_.data() }; + struct HksBlob blobNonce = { uint32_t(vecNonce_.size()), vecNonce_.data() }; + struct HksBlob rootKeyName = { uint32_t(vecRootKeyAlias_.size()), vecRootKeyAlias_.data() }; + struct HksBlob plainKey = { uint32_t(key.size()), const_cast(key.data()) }; + struct HksParamSet *params = nullptr; + int32_t ret = HksInitParamSet(¶ms); + if (ret != HKS_SUCCESS) { + ZLOGE("HksInitParamSet() failed with error %{public}d", ret); + return {}; + } + struct HksParam param[] = { + { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES }, + { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT }, + { .tag = HKS_TAG_DIGEST, .uint32Param = 0 }, + { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM }, + { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE }, + { .tag = HKS_TAG_NONCE, .blob = blobNonce }, + { .tag = HKS_TAG_ASSOCIATED_DATA, .blob = blobAad }, + }; + ret = HksAddParams(params, param, sizeof(param) / sizeof(param[0])); + if (ret != HKS_SUCCESS) { + ZLOGE("HksAddParams failed with error %{public}d", ret); + HksFreeParamSet(¶ms); + return {}; + } + + ret = HksBuildParamSet(¶ms); + if (ret != HKS_SUCCESS) { + ZLOGE("HksBuildParamSet failed with error %{public}d", ret); + HksFreeParamSet(¶ms); + return {}; + } + + uint8_t cipherBuf[256] = { 0 }; + struct HksBlob cipherText = { sizeof(cipherBuf), cipherBuf }; + ret = HksEncrypt(&rootKeyName, params, &plainKey, &cipherText); + if (ret != HKS_SUCCESS) { + ZLOGE("HksEncrypt failed with error %{public}d", ret); + HksFreeParamSet(¶ms); + return {}; + } + (void)HksFreeParamSet(¶ms); + std::vector encryptedKey(cipherText.data, cipherText.data + cipherText.size); + (void)memset_s(cipherBuf, sizeof(cipherBuf), 0, sizeof(cipherBuf)); + return encryptedKey; +} + +bool CryptoManager::Decrypt(std::vector &source, std::vector &key) +{ + struct HksBlob blobAad = { uint32_t(vecAad_.size()), &(vecAad_[0]) }; + struct HksBlob blobNonce = { uint32_t(vecNonce_.size()), &(vecNonce_[0]) }; + struct HksBlob rootKeyName = { uint32_t(vecRootKeyAlias_.size()), &(vecRootKeyAlias_[0]) }; + struct HksBlob encryptedKeyBlob = { uint32_t(source.size()), source.data() }; + + struct HksParamSet *params = nullptr; + int32_t ret = HksInitParamSet(¶ms); + if (ret != HKS_SUCCESS) { + ZLOGE("HksInitParamSet() failed with error %{public}d", ret); + return false; + } + struct HksParam param[] = { + { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES }, + { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_DECRYPT }, + { .tag = HKS_TAG_DIGEST, .uint32Param = 0 }, + { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM }, + { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE }, + { .tag = HKS_TAG_NONCE, .blob = blobNonce }, + { .tag = HKS_TAG_ASSOCIATED_DATA, .blob = blobAad }, + }; + ret = HksAddParams(params, param, sizeof(param) / sizeof(param[0])); + if (ret != HKS_SUCCESS) { + ZLOGE("HksAddParams failed with error %{public}d", ret); + HksFreeParamSet(¶ms); + return false; + } + + ret = HksBuildParamSet(¶ms); + if (ret != HKS_SUCCESS) { + ZLOGE("HksBuildParamSet failed with error %{public}d", ret); + HksFreeParamSet(¶ms); + return false; + } + uint8_t plainBuf[256] = { 0 }; + struct HksBlob plainKeyBlob = { sizeof(plainBuf), plainBuf }; + ret = HksDecrypt(&rootKeyName, params, &encryptedKeyBlob, &plainKeyBlob); + if (ret != HKS_SUCCESS) { + ZLOGW("HksDecrypt failed with error %{public}d", ret); + HksFreeParamSet(¶ms); + return false; + } + (void)HksFreeParamSet(¶ms); + + key.assign(plainKeyBlob.data, plainKeyBlob.data + plainKeyBlob.size); + (void)memset_s(plainBuf, sizeof(plainBuf), 0, sizeof(plainBuf)); + return true; +} +} // namespace OHOS::DistributedData \ No newline at end of file diff --git a/services/distributeddataservice/service/kvdb/kvdb_service_impl.cpp b/services/distributeddataservice/service/kvdb/kvdb_service_impl.cpp index d0d425d27..cad828c30 100644 --- a/services/distributeddataservice/service/kvdb/kvdb_service_impl.cpp +++ b/services/distributeddataservice/service/kvdb/kvdb_service_impl.cpp @@ -15,21 +15,25 @@ #define LOG_TAG "KVDBServiceImpl" #include "kvdb_service_impl.h" +#include + #include "accesstoken_kit.h" #include "account/account_delegate.h" #include "checker/checker_manager.h" #include "communication_provider.h" +#include "crypto_manager.h" #include "directory_manager.h" #include "ipc_skeleton.h" -#include "kvstore_sync_manager.h" #include "log_print.h" #include "metadata/meta_data_manager.h" #include "metadata/secret_key_meta_data.h" +#include "utils/constant.h" #include "utils/converter.h" namespace OHOS::DistributedKv { using namespace OHOS::DistributedData; using namespace OHOS::AppDistributedKv; using namespace OHOS::Security::AccessToken; +using system_clock = std::chrono::system_clock; KVDBServiceImpl::KVDBServiceImpl() { } @@ -58,6 +62,17 @@ Status KVDBServiceImpl::Delete(const AppId &appId, const StoreId &storeId) return ILLEGAL_STATE; } + auto tokenId = IPCSkeleton::GetCallingTokenID(); + syncAgents_.ComputeIfPresent(tokenId, [&storeId](auto &key, SyncAgent &syncAgent) { + if (syncAgent.pid_ != IPCSkeleton::GetCallingPid()) { + return true; + } + syncAgent.delayTimes_.erase(storeId); + syncAgent.observers_.erase(storeId); + syncAgent.conditions_.erase(storeId); + return true; + }); + MetaDataManager::GetInstance().DelMeta(metaData.GetKey()); auto key = SecretKeyMetaData::GetKey({ metaData.user, "default", metaData.bundleName, metaData.storeId }); MetaDataManager::GetInstance().DelMeta(key, true); @@ -66,21 +81,36 @@ Status KVDBServiceImpl::Delete(const AppId &appId, const StoreId &storeId) Status KVDBServiceImpl::Sync(const AppId &appId, const StoreId &storeId, const SyncInfo &syncInfo) { - return NOT_SUPPORT; + StoreMetaData metaData = GetStoreMetaData(appId, storeId); + MetaDataManager::GetInstance().LoadMeta(metaData.GetKey(), metaData); + auto delay = GetSyncDelayTime(syncInfo.delay, storeId); + return KvStoreSyncManager::GetInstance()->AddSyncOperation(reinterpret_cast(this), delay, + std::bind(&KVDBServiceImpl::DoSync, this, metaData, syncInfo, std::placeholders::_1), + std::bind(&KVDBServiceImpl::DoComplete, this, metaData, syncInfo, std::placeholders::_1)); } Status KVDBServiceImpl::RegisterSyncCallback(const AppId &appId, sptr callback) { - syncAgents_.InsertOrAssign(IPCSkeleton::GetCallingTokenID(), std::pair{ IPCSkeleton::GetCallingPid(), callback }); + auto tokenId = IPCSkeleton::GetCallingTokenID(); + syncAgents_.Compute(tokenId, [&appId, callback](const auto &, SyncAgent &value) { + if (value.pid_ != IPCSkeleton::GetCallingPid()) { + value.ReInit(IPCSkeleton::GetCallingPid(), appId); + } + value.callback_ = callback; + return true; + }); return SUCCESS; } Status KVDBServiceImpl::UnregisterSyncCallback(const AppId &appId) { - syncAgents_.ComputeIfPresent( - IPCSkeleton::GetCallingTokenID(), [](const auto &key, std::pair> &value) { - return !(value.first == IPCSkeleton::GetCallingPid()); - }); + syncAgents_.ComputeIfPresent(IPCSkeleton::GetCallingTokenID(), [](const auto &key, SyncAgent &value) { + if (value.pid_ != IPCSkeleton::GetCallingPid()) { + return false; + } + value.callback_ = nullptr; + return true; + }); return SUCCESS; } @@ -92,24 +122,31 @@ Status KVDBServiceImpl::SetSyncParam(const AppId &appId, const StoreId &storeId, if (syncParam.allowedDelayMs > KvStoreSyncManager::SYNC_MAX_DELAY_MS) { return Status::INVALID_ARGUMENT; } - delayTimes_.Compute( - IPCSkeleton::GetCallingTokenID(), [&storeId, &syncParam](auto &key, std::map &values) { - values[storeId] = syncParam.allowedDelayMs; - return !values.empty(); - }); + auto tokenId = IPCSkeleton::GetCallingTokenID(); + syncAgents_.Compute(tokenId, [&appId, &storeId, &syncParam](auto &key, SyncAgent &value) { + if (value.pid_ != IPCSkeleton::GetCallingPid()) { + value.ReInit(IPCSkeleton::GetCallingPid(), appId); + } + value.delayTimes_[storeId] = syncParam.allowedDelayMs; + return true; + }); return SUCCESS; } Status KVDBServiceImpl::GetSyncParam(const AppId &appId, const StoreId &storeId, KvSyncParam &syncParam) { - delayTimes_.ComputeIfPresent( - IPCSkeleton::GetCallingTokenID(), [&storeId, &syncParam](auto &key, std::map &values) { - auto it = values.find(storeId); - if (it != values.end()) { - syncParam.allowedDelayMs = it->second; - } - return !values.empty(); - }); + syncParam.allowedDelayMs = 0; + auto tokenId = IPCSkeleton::GetCallingTokenID(); + syncAgents_.ComputeIfPresent(tokenId, [&storeId, &syncParam](auto &key, SyncAgent &value) { + if (value.pid_ != IPCSkeleton::GetCallingPid()) { + return false; + } + auto it = value.delayTimes_.find(storeId); + if (it != value.delayTimes_.end()) { + syncParam.allowedDelayMs = it->second; + } + return true; + }); return SUCCESS; } @@ -151,25 +188,60 @@ Status KVDBServiceImpl::SetCapability(const AppId &appId, const StoreId &storeId return SUCCESS; } -Status KVDBServiceImpl::AddSubscribeInfo( - const AppId &appId, const StoreId &storeId, const std::vector &devices, const std::string &query) +Status KVDBServiceImpl::AddSubscribeInfo(const AppId &appId, const StoreId &storeId, + const std::vector &devices, const std::string &query) { - return NOT_SUPPORT; + auto tokenId = IPCSkeleton::GetCallingTokenID(); + syncAgents_.Compute(tokenId, [&appId, &storeId, &devices, &query](auto &key, SyncAgent &value) { + if (value.pid_ != IPCSkeleton::GetCallingPid()) { + value.ReInit(IPCSkeleton::GetCallingPid(), appId); + } + value.conditions_[storeId] = { devices, query }; + return true; + }); + return SUCCESS; } -Status KVDBServiceImpl::RmvSubscribeInfo( - const AppId &appId, const StoreId &storeId, const std::vector &devices, const std::string &query) +Status KVDBServiceImpl::RmvSubscribeInfo(const AppId &appId, const StoreId &storeId, + const std::vector &devices, const std::string &query) { - return NOT_SUPPORT; + auto tokenId = IPCSkeleton::GetCallingTokenID(); + syncAgents_.Compute(tokenId, [&appId, &storeId, &devices, &query](auto &key, SyncAgent &value) { + if (value.pid_ != IPCSkeleton::GetCallingPid()) { + value.ReInit(IPCSkeleton::GetCallingPid(), appId); + } + value.conditions_.erase(storeId); + return true; + }); + return SUCCESS; } Status KVDBServiceImpl::Subscribe(const AppId &appId, const StoreId &storeId, sptr observer) { + auto tokenId = IPCSkeleton::GetCallingTokenID(); + syncAgents_.Compute(tokenId, [&appId, &storeId, &observer](auto &key, SyncAgent &value) { + if (value.pid_ != IPCSkeleton::GetCallingPid()) { + value.ReInit(IPCSkeleton::GetCallingPid(), appId); + } + value.observers_[storeId].insert(observer); + return true; + }); return SUCCESS; } Status KVDBServiceImpl::Unsubscribe(const AppId &appId, const StoreId &storeId, sptr observer) { + auto tokenId = IPCSkeleton::GetCallingTokenID(); + syncAgents_.ComputeIfPresent(tokenId, [&storeId, &observer](auto &key, SyncAgent &value) { + if (value.pid_ != IPCSkeleton::GetCallingPid()) { + return false; + } + auto it = value.observers_.find(storeId); + if (it != value.observers_.end()) { + it->second.erase(observer); + } + return true; + }); return SUCCESS; } @@ -178,28 +250,43 @@ Status KVDBServiceImpl::BeforeCreate(const AppId &appId, const StoreId &storeId, return SUCCESS; } -Status KVDBServiceImpl::AfterCreate( - const AppId &appId, const StoreId &storeId, const Options &options, const std::vector &password) +Status KVDBServiceImpl::AfterCreate(const AppId &appId, const StoreId &storeId, const Options &options, + const std::vector &password) { if (!appId.IsValid() || !storeId.IsValid() || !options.IsValidType()) { return INVALID_ARGUMENT; } StoreMetaData metaData = GetStoreMetaData(appId, storeId); + AddOptions(options, metaData); StoreMetaData oldMeta; MetaDataManager::GetInstance().LoadMeta(metaData.GetKey(), oldMeta); if (oldMeta == metaData) { return SUCCESS; } - AddOptions(options, metaData); - return NOT_SUPPORT; + // implement update + + MetaDataManager::GetInstance().SaveMeta(metaData.GetKey(), metaData); + if (metaData.isEncrypt) { + SecretKeyMetaData secretKey; + secretKey.storeType = metaData.storeType; + secretKey.sKey = CryptoManager::GetInstance().Encrypt(password); + auto time = system_clock::to_time_t(system_clock::now()); + secretKey.time = { reinterpret_cast(&time), reinterpret_cast(&time) + sizeof(time) }; + auto storeKey = SecretKeyMetaData::GetKey({ metaData.user, "default", metaData.bundleName, metaData.storeId }); + MetaDataManager::GetInstance().SaveMeta(storeKey, secretKey, true); + } + return SUCCESS; } Status KVDBServiceImpl::AppExit(pid_t uid, pid_t pid, uint32_t tokenId, const AppId &appId) { - dataObservers_.ComputeIfPresent(tokenId, [pid](const auto &, auto &value) { return !(value.first == pid); }); - syncAgents_.ComputeIfPresent(tokenId, [pid](const auto &, auto &value) { return !(value.first == pid); }); - delayTimes_.Erase(tokenId); + syncAgents_.ComputeIfPresent(tokenId, [pid](auto &, auto &value) { return (value.pid_ == pid); }); + return SUCCESS; +} + +Status KVDBServiceImpl::ResolveAutoLaunch(const std::string &identifier, KVDBServiceImpl::DBLaunchParam ¶m) +{ return SUCCESS; } @@ -254,4 +341,120 @@ int32_t KVDBServiceImpl::GetInstIndex(uint32_t tokenId, const AppId &appId) } return tokenInfo.instIndex; } + +Status KVDBServiceImpl::DoSync(const StoreMetaData &metaData, const SyncInfo &syncInfo, const SyncEnd &complete) +{ + ZLOGD("start."); + std::vector uuids; + if (syncInfo.devices.empty()) { + auto remotes = AppDistributedKv::CommunicationProvider::GetInstance().GetRemoteDevices(); + for (auto &remote : remotes) { + uuids.push_back(std::move(remote.uuid)); + } + } + for (const auto &networkId : syncInfo.devices) { + auto uuid = AppDistributedKv::CommunicationProvider::GetInstance().GetDeviceInfo(networkId).uuid; + if (!uuid.empty()) { + uuids.push_back(std::move(uuid)); + } + } + if (uuids.empty()) { + ZLOGE("not found deviceIds."); + return Status::ERROR; + } + DistributedDB::DBStatus status; + auto store = storeCache_.GetStore(metaData, status); + if (store == nullptr) { + return ConvertDbStatus(status); + } + status = store->Sync(uuids, static_cast(syncInfo.mode), complete); + return ConvertDbStatus(status); +} + +Status KVDBServiceImpl::DoComplete(const StoreMetaData &metaData, const SyncInfo &syncInfo, const DBResult &dbResult) +{ + if (syncInfo.seqId == std::numeric_limits::max()) { + return SUCCESS; + } + sptr callback; + syncAgents_.ComputeIfPresent(metaData.tokenId, [&callback](auto &key, SyncAgent &agent) { + callback = agent.callback_; + return true; + }); + if (callback == nullptr) { + return SUCCESS; + } + + std::map result; + for (auto &[key, status] : dbResult) { + result[key] = ConvertDbStatus(status); + } + callback->SyncCompleted(result, syncInfo.seqId); + return SUCCESS; +} + +uint32_t KVDBServiceImpl::GetSyncDelayTime(uint32_t delay, const StoreId &storeId) +{ + if (delay == 0) { + bool isBackground = Constant::IsBackground(IPCSkeleton::GetCallingPid()); + if (isBackground) { + delay = KvStoreSyncManager::SYNC_DEFAULT_DELAY_MS; + syncAgents_.ComputeIfPresent(IPCSkeleton::GetCallingTokenID(), + [&delay, &storeId](auto &key, SyncAgent &agent) { + auto it = agent.delayTimes_.find(storeId); + if (it != agent.delayTimes_.end() && it->second != 0) { + delay = it->second; + } + return true; + }); + } + } else { + if (delay < KvStoreSyncManager::SYNC_MIN_DELAY_MS) { + delay = KvStoreSyncManager::SYNC_MIN_DELAY_MS; + } + if (delay > KvStoreSyncManager::SYNC_MAX_DELAY_MS) { + delay = KvStoreSyncManager::SYNC_MAX_DELAY_MS; + } + } + return delay; +} + +Status KVDBServiceImpl::ConvertDbStatus(DistributedDB::DBStatus status) +{ + switch (status) { + case DistributedDB::DBStatus::BUSY: // fallthrough + case DistributedDB::DBStatus::DB_ERROR: + return Status::DB_ERROR; + case DistributedDB::DBStatus::OK: + return Status::SUCCESS; + case DistributedDB::DBStatus::INVALID_ARGS: + return Status::INVALID_ARGUMENT; + case DistributedDB::DBStatus::NOT_FOUND: + return Status::KEY_NOT_FOUND; + case DistributedDB::DBStatus::INVALID_VALUE_FIELDS: + return Status::INVALID_VALUE_FIELDS; + case DistributedDB::DBStatus::INVALID_FIELD_TYPE: + return Status::INVALID_FIELD_TYPE; + case DistributedDB::DBStatus::CONSTRAIN_VIOLATION: + return Status::CONSTRAIN_VIOLATION; + case DistributedDB::DBStatus::INVALID_FORMAT: + return Status::INVALID_FORMAT; + case DistributedDB::DBStatus::INVALID_QUERY_FORMAT: + return Status::INVALID_QUERY_FORMAT; + case DistributedDB::DBStatus::INVALID_QUERY_FIELD: + return Status::INVALID_QUERY_FIELD; + case DistributedDB::DBStatus::NOT_SUPPORT: + return Status::NOT_SUPPORT; + case DistributedDB::DBStatus::TIME_OUT: + return Status::TIME_OUT; + case DistributedDB::DBStatus::OVER_MAX_LIMITS: + return Status::OVER_MAX_SUBSCRIBE_LIMITS; + case DistributedDB::DBStatus::EKEYREVOKED_ERROR: // fallthrough + case DistributedDB::DBStatus::SECURITY_OPTION_CHECK_ERROR: + return Status::SECURITY_LEVEL_ERROR; + default: + break; + } + return Status::ERROR; +} } // namespace OHOS::DistributedKv \ No newline at end of file diff --git a/services/distributeddataservice/service/kvdb/kvdb_service_impl.h b/services/distributeddataservice/service/kvdb/kvdb_service_impl.h index 681d27b4b..6b992710f 100644 --- a/services/distributeddataservice/service/kvdb/kvdb_service_impl.h +++ b/services/distributeddataservice/service/kvdb/kvdb_service_impl.h @@ -15,13 +15,20 @@ #ifndef OHOS_DISTRIBUTED_DATA_SERVICES_KVDB_SERVICE_IMPL_H #define OHOS_DISTRIBUTED_DATA_SERVICES_KVDB_SERVICE_IMPL_H +#include +#include + #include "concurrent_map.h" +#include "kv_store_nb_delegate.h" #include "kvdb_service_stub.h" +#include "kvstore_sync_manager.h" #include "metadata/store_meta_data.h" #include "metadata/strategy_meta_data.h" +#include "store_cache.h" namespace OHOS::DistributedKv { class API_EXPORT KVDBServiceImpl final : public KVDBServiceStub { public: + using DBLaunchParam = DistributedDB::AutoLaunchParam; API_EXPORT KVDBServiceImpl(); virtual ~KVDBServiceImpl(); Status GetStoreIds(const AppId &appId, std::vector &storeIds) override; @@ -45,18 +52,50 @@ public: Status Subscribe(const AppId &appId, const StoreId &storeId, sptr observer) override; Status Unsubscribe(const AppId &appId, const StoreId &storeId, sptr observer) override; Status AppExit(pid_t uid, pid_t pid, uint32_t tokenId, const AppId &appId); + Status ResolveAutoLaunch(const std::string &identifier, DBLaunchParam ¶m); private: using StoreMetaData = OHOS::DistributedData::StoreMetaData; using StrategyMeta = OHOS::DistributedData::StrategyMeta; + using DBStore = DistributedDB::KvStoreNbDelegate; + using SyncEnd = KvStoreSyncManager::SyncEnd; + using DBResult = std::map; void AddOptions(const Options &options, StoreMetaData &metaData); StoreMetaData GetStoreMetaData(const AppId &appId, const StoreId &storeId); StrategyMeta GetStrategyMeta(const AppId &appId, const StoreId &storeId); int32_t GetInstIndex(uint32_t tokenId, const AppId &appId); + Status DoSync(const StoreMetaData &metaData, const SyncInfo &syncInfo, const SyncEnd &complete); + Status DoComplete(const StoreMetaData &metaData, const SyncInfo &syncInfo, const DBResult &dbResult); + uint32_t GetSyncDelayTime(uint32_t delay, const StoreId &storeId); + Status ConvertDbStatus(DistributedDB::DBStatus status); - ConcurrentMap>> syncAgents_; - ConcurrentMap>> dataObservers_; - ConcurrentMap> delayTimes_; + template + struct Less { + public: + bool operator()(const sptr &__x, const sptr &__y) const + { + return __x.GetRefPtr() < __y.GetRefPtr(); + } + }; + struct SyncAgent { + pid_t pid_ = 0; + AppId appId_; + sptr callback_; + std::map delayTimes_; + std::map, Less>> observers_; + std::map, std::string>> conditions_; + void ReInit(pid_t pid, const AppId &appId) + { + pid_ = pid; + appId_ = appId; + callback_ = nullptr; + delayTimes_.clear(); + observers_.clear(); + conditions_.clear(); + } + }; + ConcurrentMap syncAgents_; + StoreCache storeCache_; }; } // namespace OHOS::DistributedKv #endif // OHOS_DISTRIBUTED_DATA_SERVICES_KVDB_SERVICE_IMPL_H diff --git a/services/distributeddataservice/service/kvdb/store_cache.cpp b/services/distributeddataservice/service/kvdb/store_cache.cpp new file mode 100644 index 000000000..a07843ad8 --- /dev/null +++ b/services/distributeddataservice/service/kvdb/store_cache.cpp @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "store_cache.h" + +#include "crypto_manager.h" +#include "directory_manager.h" +#include "metadata/meta_data_manager.h" +#include "metadata/secret_key_meta_data.h" +#include "types.h" +namespace OHOS::DistributedKv { +using namespace OHOS::DistributedData; +constexpr int64_t StoreCache::INTERVAL; +constexpr size_t StoreCache::TIME_TASK_NUM; +std::shared_ptr StoreCache::GetStore(const StoreMetaData &data, DBStatus &status) +{ + DBStore *store = nullptr; + status = DBStatus::NOT_FOUND; + stores_.Compute(data.tokenId, [this, &store, &data, &status](auto &key, auto &stores) { + auto it = stores.find(data.storeId); + if (it != stores.end()) { + store = it->second; + return true; + } + + DBManager manager(data.appId, data.user); + manager.SetKvStoreConfig({ DirectoryManager::GetInstance().GetStorePath(data) }); + manager.GetKvStore(data.storeId, GetDBOption(data), [&status, &store](auto dbStatus, auto *tmpStore) { + status = dbStatus; + store = tmpStore; + }); + + if (store != nullptr) { + stores.emplace(std::piecewise_construct, std::forward_as_tuple(data.storeId), std::forward_as_tuple(store)); + } + return !stores.empty(); + }); + + scheduler_.At(std::chrono::system_clock::now() + std::chrono::minutes(INTERVAL), + std::bind(&StoreCache::CollectGarbage, this)); + + return std::shared_ptr(store, [](DBStore *) {}); +} + +void StoreCache::CollectGarbage() +{ + DBManager manager("", ""); + auto current = std::chrono::system_clock::now(); + stores_.EraseIf([&manager, ¤t](auto &key, std::map &delegates) { + for (auto it = delegates.begin(); it != delegates.end();) { + // if the kv store is BUSY we wait more INTERVAL minutes again + if ((it->second < current) || manager.CloseKvStore(it->second) == DBStatus::BUSY) { + ++it; + } else { + it = delegates.erase(it); + } + } + return delegates.empty(); + }); + + if (!stores_.Empty()) { + scheduler_.At(current + std::chrono::minutes(INTERVAL), std::bind(&StoreCache::CollectGarbage, this)); + } +} + +StoreCache::DBOption StoreCache::GetDBOption(const StoreMetaData &data) const +{ + DBOption dbOption; + dbOption.syncDualTupleMode = true; // tuple of (appid+storeid) + dbOption.createIfNecessary = false; + dbOption.isMemoryDb = false; + dbOption.isEncryptedDb = data.isEncrypt; + if (data.isEncrypt) { + dbOption.cipher = DistributedDB::CipherType::AES_256_GCM; + SecretKeyMetaData secretKey; + secretKey.storeType = data.storeType; + auto storeKey = SecretKeyMetaData::GetKey({ data.user, "default", data.bundleName, data.storeId }); + MetaDataManager::GetInstance().SaveMeta(storeKey, secretKey, true); + std::vector password; + CryptoManager::GetInstance().Decrypt(secretKey.sKey, password); + dbOption.passwd.SetValue(password.data(), password.size()); + password.assign(password.size(), 0); + } + + if (data.storeType == KvStoreType::SINGLE_VERSION) { + dbOption.conflictResolvePolicy = DistributedDB::LAST_WIN; + } else if (data.storeType == KvStoreType::DEVICE_COLLABORATION) { + dbOption.conflictResolvePolicy = DistributedDB::DEVICE_COLLABORATION; + } + + dbOption.schema = data.schema; + dbOption.createDirByStoreIdOnly = true; + dbOption.secOption = GetDBSecurity(data.securityLevel); + return dbOption; +} + +StoreCache::DBSecurity StoreCache::GetDBSecurity(int32_t secLevel) const +{ + if (secLevel < SecurityLevel::NO_LABEL || secLevel > SecurityLevel::S4) { + return { DistributedDB::NOT_SET, DistributedDB::ECE }; + } + if (secLevel == SecurityLevel::S3) { + return { DistributedDB::S3, DistributedDB::SECE }; + } + if (secLevel == SecurityLevel::S4) { + return { DistributedDB::S4, DistributedDB::ECE }; + } + return { secLevel, DistributedDB::ECE }; +} + +StoreCache::DBStoreDelegate::DBStoreDelegate(DBStore *delegate) : delegate_(std::move(delegate)) +{ + time_ = std::chrono::system_clock::now() + std::chrono::minutes(INTERVAL); +} + +StoreCache::DBStoreDelegate::~DBStoreDelegate() +{ + delegate_ = nullptr; +} + +StoreCache::DBStoreDelegate::operator DBStore *() const +{ + time_ = std::chrono::system_clock::now() + std::chrono::minutes(INTERVAL); + return delegate_; +} + +bool StoreCache::DBStoreDelegate::operator<(const Time &time) const +{ + return time_ < time; +} +}; // namespace OHOS::DistributedKv diff --git a/services/distributeddataservice/service/kvdb/store_cache.h b/services/distributeddataservice/service/kvdb/store_cache.h new file mode 100644 index 000000000..4c6308a0d --- /dev/null +++ b/services/distributeddataservice/service/kvdb/store_cache.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_DISTRIBUTED_DATA_SERVICES_SERVICE_KVDB_STORE_CACHE_H +#define OHOS_DISTRIBUTED_DATA_SERVICES_SERVICE_KVDB_STORE_CACHE_H +#include + +#include +#include + +#include "concurrent_map.h" +#include "kv_scheduler.h" +#include "kv_store_nb_delegate.h" +#include "metadata/store_meta_data.h" +namespace OHOS::DistributedKv { +class StoreCache { +public: + using DBStatus = DistributedDB::DBStatus; + using DBStore = DistributedDB::KvStoreNbDelegate; + using StoreMetaData = OHOS::DistributedData::StoreMetaData; + using Time = std::chrono::system_clock::time_point; + struct DBStoreDelegate { + DBStoreDelegate(DBStore *delegate); + ~DBStoreDelegate(); + operator DBStore *() const; + bool operator < (const Time &time) const; + + private: + mutable Time time_; + DBStore *delegate_; + }; + std::shared_ptr GetStore(const StoreMetaData &data, DBStatus &status); + +private: + using DBManager = DistributedDB::KvStoreDelegateManager; + using DBOption = DistributedDB::KvStoreNbDelegate::Option; + using DBSecurity = DistributedDB::SecurityOption; + void CollectGarbage(); + DBOption GetDBOption(const StoreMetaData &data) const; + DBSecurity GetDBSecurity(int32_t secLevel) const; + static constexpr int64_t INTERVAL = 1; + static constexpr size_t TIME_TASK_NUM = 1; + ConcurrentMap> stores_; + KvScheduler scheduler_{ TIME_TASK_NUM }; +}; +} // namespace OHOS::DistributedKv +#endif // OHOS_DISTRIBUTED_DATA_SERVICES_SERVICE_KVDB_STORE_CACHE_H -- Gitee From 33819bad321f88bb2049b078146e45e0fdda6df8 Mon Sep 17 00:00:00 2001 From: Sven Wang Date: Thu, 16 Jun 2022 16:01:15 +0800 Subject: [PATCH 2/3] fixed auto launch the kv store and observers Signed-off-by: Sven Wang --- .../kvdb/include/observer_bridge.h | 11 +++ .../kvdb/src/observer_bridge.cpp | 37 ++++++++- .../service/kvdb/kvdb_service_impl.cpp | 75 +++++++++++++------ .../service/kvdb/kvdb_service_impl.h | 14 +--- .../service/kvdb/store_cache.cpp | 71 ++++++++++++++++-- .../service/kvdb/store_cache.h | 33 ++++++-- 6 files changed, 193 insertions(+), 48 deletions(-) diff --git a/frameworks/innerkitsimpl/kvdb/include/observer_bridge.h b/frameworks/innerkitsimpl/kvdb/include/observer_bridge.h index cb42aea52..35ef01dba 100644 --- a/frameworks/innerkitsimpl/kvdb/include/observer_bridge.h +++ b/frameworks/innerkitsimpl/kvdb/include/observer_bridge.h @@ -18,6 +18,7 @@ #include "kv_store_nb_delegate.h" #include "kv_store_observer.h" #include "kvstore_observer.h" +#include "kvstore_observer_client.h" #include "visibility.h" namespace OHOS::DistributedKv { class IKvStoreObserver; @@ -36,6 +37,16 @@ public: void OnChange(const DBChangedData &data) override; private: + class ObserverClient : public KvStoreObserverClient { + public: + ObserverClient(std::shared_ptr observer, Convert &convert); + void OnChange(const ChangeNotification &changeNotification) override; + + private: + std::vector ConvertDB(const std::vector &dbEntries, std::string &deviceId) const; + Convert &convert_; + }; + std::vector ConvertDB(const std::list &dbEntries, std::string &deviceId) const; AppId appId_; StoreId storeId_; diff --git a/frameworks/innerkitsimpl/kvdb/src/observer_bridge.cpp b/frameworks/innerkitsimpl/kvdb/src/observer_bridge.cpp index 17505a1d3..7081fb322 100644 --- a/frameworks/innerkitsimpl/kvdb/src/observer_bridge.cpp +++ b/frameworks/innerkitsimpl/kvdb/src/observer_bridge.cpp @@ -45,7 +45,7 @@ Status ObserverBridge::RegisterRemoteObserver() return SERVER_UNAVAILABLE; } - remote_ = new (std::nothrow) KvStoreObserverClient(observer_); + remote_ = new (std::nothrow) ObserverClient(observer_, convert_); return service->Subscribe(appId_, storeId_, remote_); } @@ -68,12 +68,41 @@ Status ObserverBridge::UnregisterRemoteObserver() void ObserverBridge::OnChange(const DBChangedData &data) { std::string deviceId; - ChangeNotification notice(ConvertDB(data.GetEntriesInserted(), deviceId), - ConvertDB(data.GetEntriesUpdated(), deviceId), ConvertDB(data.GetEntriesDeleted(), deviceId), deviceId, false); - + auto inserted = ConvertDB(data.GetEntriesInserted(), deviceId); + auto updated = ConvertDB(data.GetEntriesUpdated(), deviceId); + auto deleted = ConvertDB(data.GetEntriesDeleted(), deviceId); + ChangeNotification notice(std::move(inserted), std::move(updated), std::move(deleted), deviceId, false); observer_->OnChange(notice); } +ObserverBridge::ObserverClient::ObserverClient(std::shared_ptr observer, Convert &convert) + : KvStoreObserverClient(observer), convert_(convert) +{ +} + +void ObserverBridge::ObserverClient::OnChange(const ChangeNotification &data) +{ + std::string deviceId; + auto inserted = ConvertDB(data.GetInsertEntries(), deviceId); + auto updated = ConvertDB(data.GetInsertEntries(), deviceId); + auto deleted = ConvertDB(data.GetInsertEntries(), deviceId); + ChangeNotification notice(std::move(inserted), std::move(updated), std::move(deleted), deviceId, false); + KvStoreObserverClient::OnChange(notice); +} + +std::vector ObserverBridge::ObserverClient::ConvertDB(const std::vector &dbEntries, std::string &deviceId) const +{ + std::vector entries(dbEntries.size()); + auto it = entries.begin(); + for (const auto &dbEntry : dbEntries) { + Entry &entry = *it; + entry.key = convert_ ? convert_(dbEntry.key, deviceId) : Key(dbEntry.key); + entry.value = dbEntry.value; + ++it; + } + return entries; +} + std::vector ObserverBridge::ConvertDB(const std::list &dbEntries, std::string &deviceId) const { std::vector entries(dbEntries.size()); diff --git a/services/distributeddataservice/service/kvdb/kvdb_service_impl.cpp b/services/distributeddataservice/service/kvdb/kvdb_service_impl.cpp index cad828c30..fdf55f555 100644 --- a/services/distributeddataservice/service/kvdb/kvdb_service_impl.cpp +++ b/services/distributeddataservice/service/kvdb/kvdb_service_impl.cpp @@ -223,7 +223,11 @@ Status KVDBServiceImpl::Subscribe(const AppId &appId, const StoreId &storeId, sp if (value.pid_ != IPCSkeleton::GetCallingPid()) { value.ReInit(IPCSkeleton::GetCallingPid(), appId); } - value.observers_[storeId].insert(observer); + auto it = value.observers_.find(storeId); + if (it == value.observers_.end()) { + value.observers_[storeId] = std::make_shared(); + } + value.observers_[storeId]->insert(observer); return true; }); return SUCCESS; @@ -238,7 +242,7 @@ Status KVDBServiceImpl::Unsubscribe(const AppId &appId, const StoreId &storeId, } auto it = value.observers_.find(storeId); if (it != value.observers_.end()) { - it->second.erase(observer); + it->second->erase(observer); } return true; }); @@ -285,8 +289,37 @@ Status KVDBServiceImpl::AppExit(pid_t uid, pid_t pid, uint32_t tokenId, const Ap return SUCCESS; } -Status KVDBServiceImpl::ResolveAutoLaunch(const std::string &identifier, KVDBServiceImpl::DBLaunchParam ¶m) +Status KVDBServiceImpl::ResolveAutoLaunch(const std::string &identifier, DBLaunchParam ¶m) { + std::vector metaData; + auto prefix = StoreMetaData::GetPrefix( + { AppDistributedKv::CommunicationProvider::GetInstance().GetLocalDevice().uuid, param.userId, "default" }); + if (!MetaDataManager::GetInstance().LoadMeta(prefix, metaData)) { + ZLOGE("There is no store"); + return STORE_NOT_FOUND; + } + + for (const auto &storeMeta : metaData) { + auto storeIdentifier = DBManager::GetKvStoreIdentifier("", storeMeta.appId, storeMeta.storeId, true); + if (identifier != storeIdentifier) { + continue; + } + std::shared_ptr observers; + syncAgents_.ComputeIfPresent(storeMeta.tokenId, [&storeMeta, &observers](auto, SyncAgent &agent) { + auto it = agent.observers_.find(storeMeta.storeId); + if (it != agent.observers_.end()) { + observers = it->second; + } + return true; + }); + + if (observers == nullptr || observers->empty()) { + continue; + } + + DBStatus status; + storeCache_.GetStore(storeMeta, observers, status); + } return SUCCESS; } @@ -363,7 +396,7 @@ Status KVDBServiceImpl::DoSync(const StoreMetaData &metaData, const SyncInfo &sy return Status::ERROR; } DistributedDB::DBStatus status; - auto store = storeCache_.GetStore(metaData, status); + auto store = storeCache_.GetStore(metaData, nullptr, status); if (store == nullptr) { return ConvertDbStatus(status); } @@ -419,38 +452,38 @@ uint32_t KVDBServiceImpl::GetSyncDelayTime(uint32_t delay, const StoreId &storeI return delay; } -Status KVDBServiceImpl::ConvertDbStatus(DistributedDB::DBStatus status) +Status KVDBServiceImpl::ConvertDbStatus(DBStatus status) { switch (status) { - case DistributedDB::DBStatus::BUSY: // fallthrough - case DistributedDB::DBStatus::DB_ERROR: + case DBStatus::BUSY: // fallthrough + case DBStatus::DB_ERROR: return Status::DB_ERROR; - case DistributedDB::DBStatus::OK: + case DBStatus::OK: return Status::SUCCESS; - case DistributedDB::DBStatus::INVALID_ARGS: + case DBStatus::INVALID_ARGS: return Status::INVALID_ARGUMENT; - case DistributedDB::DBStatus::NOT_FOUND: + case DBStatus::NOT_FOUND: return Status::KEY_NOT_FOUND; - case DistributedDB::DBStatus::INVALID_VALUE_FIELDS: + case DBStatus::INVALID_VALUE_FIELDS: return Status::INVALID_VALUE_FIELDS; - case DistributedDB::DBStatus::INVALID_FIELD_TYPE: + case DBStatus::INVALID_FIELD_TYPE: return Status::INVALID_FIELD_TYPE; - case DistributedDB::DBStatus::CONSTRAIN_VIOLATION: + case DBStatus::CONSTRAIN_VIOLATION: return Status::CONSTRAIN_VIOLATION; - case DistributedDB::DBStatus::INVALID_FORMAT: + case DBStatus::INVALID_FORMAT: return Status::INVALID_FORMAT; - case DistributedDB::DBStatus::INVALID_QUERY_FORMAT: + case DBStatus::INVALID_QUERY_FORMAT: return Status::INVALID_QUERY_FORMAT; - case DistributedDB::DBStatus::INVALID_QUERY_FIELD: + case DBStatus::INVALID_QUERY_FIELD: return Status::INVALID_QUERY_FIELD; - case DistributedDB::DBStatus::NOT_SUPPORT: + case DBStatus::NOT_SUPPORT: return Status::NOT_SUPPORT; - case DistributedDB::DBStatus::TIME_OUT: + case DBStatus::TIME_OUT: return Status::TIME_OUT; - case DistributedDB::DBStatus::OVER_MAX_LIMITS: + case DBStatus::OVER_MAX_LIMITS: return Status::OVER_MAX_SUBSCRIBE_LIMITS; - case DistributedDB::DBStatus::EKEYREVOKED_ERROR: // fallthrough - case DistributedDB::DBStatus::SECURITY_OPTION_CHECK_ERROR: + case DBStatus::EKEYREVOKED_ERROR: // fallthrough + case DBStatus::SECURITY_OPTION_CHECK_ERROR: return Status::SECURITY_LEVEL_ERROR; default: break; diff --git a/services/distributeddataservice/service/kvdb/kvdb_service_impl.h b/services/distributeddataservice/service/kvdb/kvdb_service_impl.h index 6b992710f..c0ee47770 100644 --- a/services/distributeddataservice/service/kvdb/kvdb_service_impl.h +++ b/services/distributeddataservice/service/kvdb/kvdb_service_impl.h @@ -58,8 +58,10 @@ private: using StoreMetaData = OHOS::DistributedData::StoreMetaData; using StrategyMeta = OHOS::DistributedData::StrategyMeta; using DBStore = DistributedDB::KvStoreNbDelegate; + using DBManager = DistributedDB::KvStoreDelegateManager; using SyncEnd = KvStoreSyncManager::SyncEnd; using DBResult = std::map; + using DBStatus = DistributedDB::DBStatus; void AddOptions(const Options &options, StoreMetaData &metaData); StoreMetaData GetStoreMetaData(const AppId &appId, const StoreId &storeId); StrategyMeta GetStrategyMeta(const AppId &appId, const StoreId &storeId); @@ -67,22 +69,14 @@ private: Status DoSync(const StoreMetaData &metaData, const SyncInfo &syncInfo, const SyncEnd &complete); Status DoComplete(const StoreMetaData &metaData, const SyncInfo &syncInfo, const DBResult &dbResult); uint32_t GetSyncDelayTime(uint32_t delay, const StoreId &storeId); - Status ConvertDbStatus(DistributedDB::DBStatus status); + Status ConvertDbStatus(DBStatus status); - template - struct Less { - public: - bool operator()(const sptr &__x, const sptr &__y) const - { - return __x.GetRefPtr() < __y.GetRefPtr(); - } - }; struct SyncAgent { pid_t pid_ = 0; AppId appId_; sptr callback_; std::map delayTimes_; - std::map, Less>> observers_; + std::map> observers_; std::map, std::string>> conditions_; void ReInit(pid_t pid, const AppId &appId) { diff --git a/services/distributeddataservice/service/kvdb/store_cache.cpp b/services/distributeddataservice/service/kvdb/store_cache.cpp index a07843ad8..95ee5d1e5 100644 --- a/services/distributeddataservice/service/kvdb/store_cache.cpp +++ b/services/distributeddataservice/service/kvdb/store_cache.cpp @@ -24,13 +24,15 @@ namespace OHOS::DistributedKv { using namespace OHOS::DistributedData; constexpr int64_t StoreCache::INTERVAL; constexpr size_t StoreCache::TIME_TASK_NUM; -std::shared_ptr StoreCache::GetStore(const StoreMetaData &data, DBStatus &status) +StoreCache::DBStore *StoreCache::GetStore(const StoreMetaData &data, std::shared_ptr observers, + DBStatus &status) { DBStore *store = nullptr; status = DBStatus::NOT_FOUND; - stores_.Compute(data.tokenId, [this, &store, &data, &status](auto &key, auto &stores) { + stores_.Compute(data.tokenId, [this, &store, &data, &status, &observers](auto &key, auto &stores) { auto it = stores.find(data.storeId); if (it != stores.end()) { + it->second.SetObservers(observers); store = it->second; return true; } @@ -43,7 +45,8 @@ std::shared_ptr StoreCache::GetStore(const StoreMetaData &d }); if (store != nullptr) { - stores.emplace(std::piecewise_construct, std::forward_as_tuple(data.storeId), std::forward_as_tuple(store)); + stores.emplace(std::piecewise_construct, std::forward_as_tuple(data.storeId), + std::forward_as_tuple(store, observers)); } return !stores.empty(); }); @@ -51,7 +54,7 @@ std::shared_ptr StoreCache::GetStore(const StoreMetaData &d scheduler_.At(std::chrono::system_clock::now() + std::chrono::minutes(INTERVAL), std::bind(&StoreCache::CollectGarbage, this)); - return std::shared_ptr(store, [](DBStore *) {}); + return store; } void StoreCache::CollectGarbage() @@ -61,7 +64,7 @@ void StoreCache::CollectGarbage() stores_.EraseIf([&manager, ¤t](auto &key, std::map &delegates) { for (auto it = delegates.begin(); it != delegates.end();) { // if the kv store is BUSY we wait more INTERVAL minutes again - if ((it->second < current) || manager.CloseKvStore(it->second) == DBStatus::BUSY) { + if ((it->second < current) || !it->second.Close(manager)) { ++it; } else { it = delegates.erase(it); @@ -120,9 +123,13 @@ StoreCache::DBSecurity StoreCache::GetDBSecurity(int32_t secLevel) const return { secLevel, DistributedDB::ECE }; } -StoreCache::DBStoreDelegate::DBStoreDelegate(DBStore *delegate) : delegate_(std::move(delegate)) +StoreCache::DBStoreDelegate::DBStoreDelegate(DBStore *delegate, std::shared_ptr observers) + : delegate_(delegate), observers_(std::move(observers)) { time_ = std::chrono::system_clock::now() + std::chrono::minutes(INTERVAL); + if (observers_ != nullptr && !observers_->empty()) { + delegate_->RegisterObserver({}, DistributedDB::OBSERVER_CHANGES_FOREIGN, this); + } } StoreCache::DBStoreDelegate::~DBStoreDelegate() @@ -130,9 +137,12 @@ StoreCache::DBStoreDelegate::~DBStoreDelegate() delegate_ = nullptr; } -StoreCache::DBStoreDelegate::operator DBStore *() const +StoreCache::DBStoreDelegate::operator DBStore *() { time_ = std::chrono::system_clock::now() + std::chrono::minutes(INTERVAL); + if (observers_ != nullptr && !observers_->empty()) { + delegate_->RegisterObserver({}, DistributedDB::OBSERVER_CHANGES_FOREIGN, this); + } return delegate_; } @@ -140,4 +150,51 @@ bool StoreCache::DBStoreDelegate::operator<(const Time &time) const { return time_ < time; } + +bool StoreCache::DBStoreDelegate::Close(DBManager &manager) +{ + if (delegate_ != nullptr) { + delegate_->UnRegisterObserver(this); + } + + auto status = manager.CloseKvStore(delegate_); + if (status == DBStatus::BUSY) { + return false; + } + delegate_ = nullptr; + return true; +} + +void StoreCache::DBStoreDelegate::OnChange(const DistributedDB::KvStoreChangedData &data) +{ + if (observers_ == nullptr) { + return; + } + + const auto &dbInserts = data.GetEntriesInserted(); + const auto &dbUpdates = data.GetEntriesUpdated(); + const auto &dbDeletes = data.GetEntriesDeleted(); + ChangeNotification change(Convert(dbInserts), Convert(dbUpdates), Convert(dbDeletes), std::string(), false); + for (auto &observer : *observers_) { + observer->OnChange(change); + } +} + +void StoreCache::DBStoreDelegate::SetObservers(std::shared_ptr observers) +{ + if (observers_ != observers && observers != nullptr) { + observers_ = observers; + } +} +std::vector StoreCache::DBStoreDelegate::Convert(const std::list &dbEntries) +{ + std::vector entries; + for (const auto &entry : dbEntries) { + Entry tmpEntry; + tmpEntry.key = entry.key; + tmpEntry.value = entry.value; + entries.push_back(tmpEntry); + } + return entries; +} }; // namespace OHOS::DistributedKv diff --git a/services/distributeddataservice/service/kvdb/store_cache.h b/services/distributeddataservice/service/kvdb/store_cache.h index 4c6308a0d..44c142f12 100644 --- a/services/distributeddataservice/service/kvdb/store_cache.h +++ b/services/distributeddataservice/service/kvdb/store_cache.h @@ -24,27 +24,48 @@ #include "kv_scheduler.h" #include "kv_store_nb_delegate.h" #include "metadata/store_meta_data.h" +#include "refbase.h" +#include "ikvstore_observer.h" namespace OHOS::DistributedKv { class StoreCache { public: + template + struct Less { + public: + bool operator()(const sptr &__x, const sptr &__y) const + { + return __x.GetRefPtr() < __y.GetRefPtr(); + } + }; using DBStatus = DistributedDB::DBStatus; using DBStore = DistributedDB::KvStoreNbDelegate; + using DBManager = DistributedDB::KvStoreDelegateManager; + using DBObserver = DistributedDB::KvStoreObserver; + using DBChangeData = DistributedDB::KvStoreChangedData; + using DBEntry = DistributedDB::Entry; + using Observers = std::set, Less>; using StoreMetaData = OHOS::DistributedData::StoreMetaData; using Time = std::chrono::system_clock::time_point; - struct DBStoreDelegate { - DBStoreDelegate(DBStore *delegate); + + struct DBStoreDelegate : public DBObserver { + DBStoreDelegate(DBStore *delegate, std::shared_ptr observers); ~DBStoreDelegate(); - operator DBStore *() const; - bool operator < (const Time &time) const; + operator DBStore *(); + bool operator<(const Time &time) const; + bool Close(DBManager &manager); + void OnChange(const DBChangeData &data) override; + void SetObservers(std::shared_ptr observers); private: + std::vector Convert(const std::list &dbEntries); mutable Time time_; DBStore *delegate_; + std::shared_ptr observers_; }; - std::shared_ptr GetStore(const StoreMetaData &data, DBStatus &status); + + DBStore *GetStore(const StoreMetaData &data, std::shared_ptr observers, DBStatus &status); private: - using DBManager = DistributedDB::KvStoreDelegateManager; using DBOption = DistributedDB::KvStoreNbDelegate::Option; using DBSecurity = DistributedDB::SecurityOption; void CollectGarbage(); -- Gitee From 6e15d7118ad6337519ccd9493e36bcc2ec353174 Mon Sep 17 00:00:00 2001 From: Sven Wang Date: Thu, 16 Jun 2022 16:25:12 +0800 Subject: [PATCH 3/3] update Signed-off-by: Sven Wang --- frameworks/innerkitsimpl/kvdb/src/observer_bridge.cpp | 8 +++++++- frameworks/innerkitsimpl/kvdb/src/single_store_impl.cpp | 5 +---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/frameworks/innerkitsimpl/kvdb/src/observer_bridge.cpp b/frameworks/innerkitsimpl/kvdb/src/observer_bridge.cpp index 7081fb322..755b720da 100644 --- a/frameworks/innerkitsimpl/kvdb/src/observer_bridge.cpp +++ b/frameworks/innerkitsimpl/kvdb/src/observer_bridge.cpp @@ -82,6 +82,11 @@ ObserverBridge::ObserverClient::ObserverClient(std::shared_ptr observe void ObserverBridge::ObserverClient::OnChange(const ChangeNotification &data) { + if (convert_ == nullptr) { + KvStoreObserverClient::OnChange(data); + return; + } + std::string deviceId; auto inserted = ConvertDB(data.GetInsertEntries(), deviceId); auto updated = ConvertDB(data.GetInsertEntries(), deviceId); @@ -90,7 +95,8 @@ void ObserverBridge::ObserverClient::OnChange(const ChangeNotification &data) KvStoreObserverClient::OnChange(notice); } -std::vector ObserverBridge::ObserverClient::ConvertDB(const std::vector &dbEntries, std::string &deviceId) const +std::vector ObserverBridge::ObserverClient::ConvertDB(const std::vector &dbEntries, + std::string &deviceId) const { std::vector entries(dbEntries.size()); auto it = entries.begin(); diff --git a/frameworks/innerkitsimpl/kvdb/src/single_store_impl.cpp b/frameworks/innerkitsimpl/kvdb/src/single_store_impl.cpp index f74c3fbcd..e64970812 100644 --- a/frameworks/innerkitsimpl/kvdb/src/single_store_impl.cpp +++ b/frameworks/innerkitsimpl/kvdb/src/single_store_impl.cpp @@ -664,10 +664,7 @@ std::vector SingleStoreImpl::GetPrefix(const DataQuery &query) const SingleStoreImpl::Convert SingleStoreImpl::GetConvert() const { - return [](const DBKey &key, std::string &deviceId) { - deviceId = ""; - return Key(key); - }; + return nullptr; } Status SingleStoreImpl::DoSync(const SyncInfo &syncInfo, std::shared_ptr observer) -- Gitee