From 31d16fca88214a908db7601a4bdb28fb2b579684 Mon Sep 17 00:00:00 2001 From: htt1997 Date: Wed, 17 May 2023 15:57:19 +0800 Subject: [PATCH] update Signed-off-by: htt1997 --- .../app/src/uninstaller/uninstaller_impl.cpp | 114 +++--- .../app/src/uninstaller/uninstaller_impl.h | 15 +- .../distributeddataservice/framework/BUILD.gn | 1 + .../framework/cloud/cloud_info.cpp | 1 - .../framework/cloud/subscription.cpp | 75 ++++ .../framework/include/cloud/cloud_event.h | 6 +- .../framework/include/cloud/cloud_info.h | 1 - .../framework/include/cloud/subscription.h | 46 +++ .../include/serializable/serializable.h | 216 +++++++++--- .../framework/include/store/auto_cache.h | 2 +- .../framework/serializable/serializable.cpp | 18 +- .../framework/store/auto_cache.cpp | 6 +- .../framework/test/serializable_test.cpp | 75 ++++ .../distributeddataservice/service/BUILD.gn | 4 +- .../service/cloud/cloud_service_impl.cpp | 300 +++++++++++----- .../service/cloud/cloud_service_impl.h | 16 +- .../service/cloud/cloud_service_stub.cpp | 3 +- .../service/rdb/rdb_service_impl.cpp | 206 ++++++++--- .../service/rdb/rdb_service_impl.h | 25 +- .../service/rdb/rdb_service_stub.cpp | 23 +- .../service/rdb/rdb_syncer.cpp | 83 +---- .../service/rdb/rdb_syncer.h | 9 +- .../service/rdb/rdb_watcher.cpp | 43 +++ .../service/rdb/rdb_watcher.h | 37 ++ .../service/test/BUILD.gn | 2 +- .../service/test/cloud_data_test.cpp | 58 +-- .../frameworks/js/napi/cloud_data/BUILD.gn | 45 ++- .../js/napi/cloud_data/include/js_config.h | 50 +++ .../cloud_data/include/js_const_properties.h | 25 ++ .../napi/cloud_data/include/js_error_utils.h | 69 ++++ .../js/napi/cloud_data/include/napi_queue.h | 142 ++++++++ .../js/napi/cloud_data/src/entry_point.cpp | 41 +++ .../js/napi/cloud_data/src/js_config.cpp | 331 ++++++++++++++++++ .../cloud_data/src/js_const_properties.cpp | 53 +++ .../js/napi/cloud_data/src/js_error_utils.cpp | 93 +++++ .../js/napi/cloud_data/src/napi_queue.cpp | 166 +++++++++ .../cloud_data/include/cloud_service_proxy.h | 2 +- .../native/cloud_data/src/cloud_manager.cpp | 18 +- .../native/rdb/include/rdb_service_proxy.h | 5 +- .../native/rdb/include/rdb_store_impl.h | 1 - .../native/rdb/include/rdb_types_util.h | 5 + .../native/rdb/src/rdb_manager_impl.cpp | 15 +- .../native/rdb/src/rdb_service_proxy.cpp | 20 +- .../native/rdb/src/rdb_store_impl.cpp | 13 +- .../native/rdb/src/rdb_types_util.cpp | 14 + .../interfaces/inner_api/cloud_data/BUILD.gn | 6 +- .../cloud_data/include/cloud_manager.h | 6 +- .../cloud_data/include/cloud_service.h | 7 +- .../inner_api/rdb/include/rdb_service.h | 5 +- .../inner_api/rdb/include/rdb_types.h | 1 + 50 files changed, 2044 insertions(+), 474 deletions(-) create mode 100644 datamgr_service/services/distributeddataservice/framework/cloud/subscription.cpp create mode 100644 datamgr_service/services/distributeddataservice/framework/include/cloud/subscription.h create mode 100644 datamgr_service/services/distributeddataservice/service/rdb/rdb_watcher.cpp create mode 100644 datamgr_service/services/distributeddataservice/service/rdb/rdb_watcher.h create mode 100644 relational_store/frameworks/js/napi/cloud_data/include/js_config.h create mode 100644 relational_store/frameworks/js/napi/cloud_data/include/js_const_properties.h create mode 100644 relational_store/frameworks/js/napi/cloud_data/include/js_error_utils.h create mode 100644 relational_store/frameworks/js/napi/cloud_data/include/napi_queue.h create mode 100644 relational_store/frameworks/js/napi/cloud_data/src/entry_point.cpp create mode 100644 relational_store/frameworks/js/napi/cloud_data/src/js_config.cpp create mode 100644 relational_store/frameworks/js/napi/cloud_data/src/js_const_properties.cpp create mode 100644 relational_store/frameworks/js/napi/cloud_data/src/js_error_utils.cpp create mode 100644 relational_store/frameworks/js/napi/cloud_data/src/napi_queue.cpp diff --git a/datamgr_service/services/distributeddataservice/app/src/uninstaller/uninstaller_impl.cpp b/datamgr_service/services/distributeddataservice/app/src/uninstaller/uninstaller_impl.cpp index 80f0686a..cb6142eb 100644 --- a/datamgr_service/services/distributeddataservice/app/src/uninstaller/uninstaller_impl.cpp +++ b/datamgr_service/services/distributeddataservice/app/src/uninstaller/uninstaller_impl.cpp @@ -28,7 +28,6 @@ #include "metadata/store_meta_data.h" #include "permit_delegate.h" #include "cloud/cloud_info.h" -#include "utils/block_integer.h" namespace OHOS::DistributedKv { using namespace OHOS::AppDistributedKv; @@ -37,8 +36,13 @@ using namespace OHOS::AppExecFwk; using namespace OHOS::DistributedData; using namespace OHOS::EventFwk; -UninstallEventSubscriber::UninstallEventSubscriber(const CommonEventSubscribeInfo &info) : CommonEventSubscriber(info) +UninstallEventSubscriber::UninstallEventSubscriber(const CommonEventSubscribeInfo &info, + KvStoreDataService *kvStoreDataService) + : CommonEventSubscriber(info), kvStoreDataService_(kvStoreDataService) { + callbacks_ = { { CommonEventSupport::COMMON_EVENT_PACKAGE_REMOVED, &UninstallEventSubscriber::OnUninstall }, + { OHOS::AppExecFwk::COMMON_EVENT_SANDBOX_PACKAGE_REMOVED, &UninstallEventSubscriber::OnUninstall }, + { CommonEventSupport::COMMON_EVENT_PACKAGE_CHANGED, &UninstallEventSubscriber::OnUpdate } }; } void UninstallEventSubscriber::OnReceiveEvent(const CommonEventData &event) @@ -46,21 +50,57 @@ void UninstallEventSubscriber::OnReceiveEvent(const CommonEventData &event) ZLOGI("Intent Action Rec"); Want want = event.GetWant(); std::string action = want.GetAction(); - callbacks_.ComputeIfPresent(action, [&want](const auto& key, auto &callback) { + auto it = callbacks_.find(action); + if (it != callbacks_.end()) { std::string bundleName = want.GetElement().GetBundleName(); int32_t userId = want.GetIntParam(USER_ID, -1); int32_t appIndex = want.GetIntParam(SANDBOX_APP_INDEX, 0); ZLOGI("bundleName:%{public}s, user:%{public}d, appIndex:%{public}d", bundleName.c_str(), userId, appIndex); - callback(bundleName, userId, appIndex); - return true; - }); + (this->*(it->second))(bundleName, userId, appIndex); + } } -int32_t UninstallEventSubscriber::RegisterCallback(const std::string &action, UninstallEventCallback callback) + +void UninstallEventSubscriber::OnUninstall(const std::string &bundleName, int32_t userId, int32_t appIndex) { - callbacks_.InsertOrAssign(action, std::move(callback)); - return Status::SUCCESS; + kvStoreDataService_->OnUninstall(bundleName, userId, appIndex, IPCSkeleton::GetCallingTokenID()); + std::string prefix = StoreMetaData::GetPrefix( + { DeviceManagerAdapter::GetInstance().GetLocalDevice().uuid, std::to_string(userId), "default", bundleName }); + std::vector storeMetaData; + if (!MetaDataManager::GetInstance().LoadMeta(prefix, storeMetaData)) { + ZLOGE("load meta failed!"); + return; + } + for (auto &meta : storeMetaData) { + if (meta.instanceId == appIndex && !meta.appId.empty() && !meta.storeId.empty()) { + ZLOGI("uninstalled bundleName:%{public}s stordId:%{public}s", bundleName.c_str(), meta.storeId.c_str()); + MetaDataManager::GetInstance().DelMeta(meta.GetKey()); + MetaDataManager::GetInstance().DelMeta(meta.GetSecretKey(), true); + MetaDataManager::GetInstance().DelMeta(meta.GetStrategyKey()); + MetaDataManager::GetInstance().DelMeta(meta.appId, true); + MetaDataManager::GetInstance().DelMeta(meta.GetKeyLocal(), true); + MetaDataManager::GetInstance().DelMeta(CloudInfo::GetSchemaKey(meta), true); + PermitDelegate::GetInstance().DelCache(meta.GetKey()); + } + } } +void UninstallEventSubscriber::OnUpdate(const std::string &bundleName, int32_t userId, int32_t appIndex) +{ + kvStoreDataService_->OnUpdate(bundleName, userId, appIndex, IPCSkeleton::GetCallingTokenID()); + std::string prefix = StoreMetaData::GetPrefix( + { DeviceManagerAdapter::GetInstance().GetLocalDevice().uuid, std::to_string(userId), "default", bundleName }); + std::vector storeMetaData; + if (!MetaDataManager::GetInstance().LoadMeta(prefix, storeMetaData)) { + ZLOGE("load meta failed!"); + return; + } + for (auto &meta : storeMetaData) { + if (meta.instanceId == appIndex && !meta.appId.empty() && !meta.storeId.empty()) { + ZLOGI("updated bundleName:%{public}s, stordId:%{public}s", bundleName.c_str(), meta.storeId.c_str()); + MetaDataManager::GetInstance().DelMeta(CloudInfo::GetSchemaKey(meta), true); + } + } +} UninstallerImpl::~UninstallerImpl() { ZLOGD("destruct"); @@ -90,21 +130,7 @@ Status UninstallerImpl::Init(KvStoreDataService *kvStoreDataService, std::shared matchingSkills.AddEvent(CommonEventSupport::COMMON_EVENT_PACKAGE_CHANGED); CommonEventSubscribeInfo info(matchingSkills); - auto subscriber = std::make_shared(info); - auto removedCallback = [kvStoreDataService](const std::string &bundleName, int32_t userId, int32_t appIndex) { - kvStoreDataService->OnUninstall(bundleName, userId, appIndex, IPCSkeleton::GetCallingTokenID()); - OnUninstall(bundleName, userId, appIndex); - }; - - auto updatedCallback = [kvStoreDataService](const std::string &bundleName, int32_t userId, int32_t appIndex) { - kvStoreDataService->OnUpdate(bundleName, userId, appIndex, IPCSkeleton::GetCallingTokenID()); - OnUpdate(bundleName, userId, appIndex); - }; - - subscriber->RegisterCallback(CommonEventSupport::COMMON_EVENT_PACKAGE_REMOVED, removedCallback); - subscriber->RegisterCallback(OHOS::AppExecFwk::COMMON_EVENT_SANDBOX_PACKAGE_REMOVED, removedCallback); - subscriber->RegisterCallback(CommonEventSupport::COMMON_EVENT_PACKAGE_CHANGED, updatedCallback); - + auto subscriber = std::make_shared(info, kvStoreDataService); subscriber_ = subscriber; executors_ = executors; executors_->Execute(GetTask()); @@ -126,44 +152,4 @@ ExecutorPool::Task UninstallerImpl::GetTask() executors_->Schedule(std::chrono::milliseconds(RETRY_INTERVAL), GetTask()); }; } - -void UninstallerImpl::OnUninstall(const std::string &bundleName, int32_t userId, int32_t appIndex) -{ - std::string prefix = StoreMetaData::GetPrefix( - { DeviceManagerAdapter::GetInstance().GetLocalDevice().uuid, std::to_string(userId), "default", bundleName }); - std::vector storeMetaData; - if (!MetaDataManager::GetInstance().LoadMeta(prefix, storeMetaData)) { - ZLOGE("load meta failed!"); - return; - } - for (auto &meta : storeMetaData) { - if (meta.instanceId == appIndex && !meta.appId.empty() && !meta.storeId.empty()) { - ZLOGI("uninstalled bundleName:%{public}s stordId:%{public}s", bundleName.c_str(), meta.storeId.c_str()); - MetaDataManager::GetInstance().DelMeta(meta.GetKey()); - MetaDataManager::GetInstance().DelMeta(meta.GetSecretKey(), true); - MetaDataManager::GetInstance().DelMeta(meta.GetStrategyKey()); - MetaDataManager::GetInstance().DelMeta(meta.appId, true); - MetaDataManager::GetInstance().DelMeta(meta.GetKeyLocal(), true); - MetaDataManager::GetInstance().DelMeta(CloudInfo::GetSchemaKey(meta), true); - PermitDelegate::GetInstance().DelCache(meta.GetKey()); - } - } -} - -void UninstallerImpl::OnUpdate(const std::string &bundleName, int32_t userId, int32_t appIndex) -{ - std::string prefix = StoreMetaData::GetPrefix( - { DeviceManagerAdapter::GetInstance().GetLocalDevice().uuid, std::to_string(userId), "default", bundleName }); - std::vector storeMetaData; - if (!MetaDataManager::GetInstance().LoadMeta(prefix, storeMetaData)) { - ZLOGE("load meta failed!"); - return; - } - for (auto &meta : storeMetaData) { - if (meta.instanceId == appIndex && !meta.appId.empty() && !meta.storeId.empty()) { - ZLOGI("updated bundleName:%{public}s, stordId:%{public}s", bundleName.c_str(), meta.storeId.c_str()); - MetaDataManager::GetInstance().DelMeta(CloudInfo::GetSchemaKey(meta), true); - } - } -} } // namespace OHOS::DistributedKv diff --git a/datamgr_service/services/distributeddataservice/app/src/uninstaller/uninstaller_impl.h b/datamgr_service/services/distributeddataservice/app/src/uninstaller/uninstaller_impl.h index 4de54f49..3922fbad 100644 --- a/datamgr_service/services/distributeddataservice/app/src/uninstaller/uninstaller_impl.h +++ b/datamgr_service/services/distributeddataservice/app/src/uninstaller/uninstaller_impl.h @@ -21,12 +21,11 @@ #include "uninstaller.h" namespace OHOS::DistributedKv { -using UninstallEventCallback = std::function; - class UninstallEventSubscriber : public EventFwk::CommonEventSubscriber { public: - explicit UninstallEventSubscriber(const EventFwk::CommonEventSubscribeInfo &info); - int32_t RegisterCallback(const std::string &action, UninstallEventCallback callback); +using UninstallEventCallback = void (UninstallEventSubscriber::*) + (const std::string &bundleName, int32_t userId, int32_t appIndex); + UninstallEventSubscriber(const EventFwk::CommonEventSubscribeInfo &info, KvStoreDataService *kvStoreDataService); ~UninstallEventSubscriber() {} void OnReceiveEvent(const EventFwk::CommonEventData &event) override; @@ -34,8 +33,12 @@ public: private: static constexpr const char *USER_ID = "userId"; static constexpr const char *SANDBOX_APP_INDEX = "sandbox_app_index"; - ConcurrentMap callbacks_; + void OnUninstall(const std::string &bundleName, int32_t userId, int32_t appIndex); + void OnUpdate(const std::string &bundleName, int32_t userId, int32_t appIndex); + std::map callbacks_; + KvStoreDataService *kvStoreDataService_; }; + class UninstallerImpl : public Uninstaller { public: ~UninstallerImpl(); @@ -47,8 +50,6 @@ public: private: static constexpr int32_t RETRY_TIME = 300; static constexpr int32_t RETRY_INTERVAL = 100; - static void OnUninstall(const std::string &bundleName, int32_t userId, int32_t appIndex); - static void OnUpdate(const std::string &bundleName, int32_t userId, int32_t appIndex); int32_t retryTime_; ExecutorPool::Task GetTask(); std::shared_ptr subscriber_ {}; diff --git a/datamgr_service/services/distributeddataservice/framework/BUILD.gn b/datamgr_service/services/distributeddataservice/framework/BUILD.gn index 56855ff8..09a242ba 100644 --- a/datamgr_service/services/distributeddataservice/framework/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/framework/BUILD.gn @@ -50,6 +50,7 @@ ohos_shared_library("distributeddatasvcfwk") { "cloud/cloud_info.cpp", "cloud/cloud_server.cpp", "cloud/schema_meta.cpp", + "cloud/subscription.cpp", "eventcenter/event.cpp", "eventcenter/event_center.cpp", "feature/feature_system.cpp", diff --git a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_info.cpp b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_info.cpp index 55712749..a50f4d69 100644 --- a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_info.cpp +++ b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_info.cpp @@ -98,7 +98,6 @@ bool CloudInfo::IsExist(const std::string &bundleName) const } } return false; -// return apps.find(bundleName) != apps.end(); } std::string CloudInfo::GetPrefix(const std::initializer_list &fields) diff --git a/datamgr_service/services/distributeddataservice/framework/cloud/subscription.cpp b/datamgr_service/services/distributeddataservice/framework/cloud/subscription.cpp new file mode 100644 index 00000000..7bddb52c --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/cloud/subscription.cpp @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2023 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 "cloud/subscription.h" +#include "utils/constant.h" +namespace OHOS::DistributedData { +bool Subscription::Relation::Marshal(json &node) const +{ + SetValue(node[GET_NAME(id)], id); + SetValue(node[GET_NAME(bundleName)], bundleName); + SetValue(node[GET_NAME(relations)], relations); + return true; +} + +bool Subscription::Relation::Unmarshal(const json &node) +{ + GetValue(node, GET_NAME(id), id); + GetValue(node, GET_NAME(bundleName), bundleName); + GetValue(node, GET_NAME(relations), relations); + return true; +} + +bool Subscription::Marshal(json &node) const +{ + SetValue(node[GET_NAME(userId)], userId); + SetValue(node[GET_NAME(id)], id); + SetValue(node[GET_NAME(expiresTime)], expiresTime); + return true; +} + +bool Subscription::Unmarshal(const json &node) +{ + GetValue(node, GET_NAME(userId), userId); + GetValue(node, GET_NAME(id), id); + GetValue(node, GET_NAME(expiresTime), expiresTime); + return true; +} + +std::string Subscription::GetKey() +{ + return GetKey(userId); +} + +std::string Subscription::GetRelationKey(const std::string &bundleName) +{ + return GetRelationKey(userId, bundleName); +} + +std::string Subscription::GetKey(int32_t userId) +{ + return Constant::Join(PREFIX, Constant::KEY_SEPARATOR, { std::to_string(userId) }); +} + +std::string Subscription::GetRelationKey(int32_t userId, const std::string &bundleName) +{ + return Constant::Join(RELATION_PREFIX, Constant::KEY_SEPARATOR, { std::to_string(userId), bundleName }); +} + +std::string Subscription::GetPrefix(const std::initializer_list &fields) +{ + return Constant::Join(PREFIX, Constant::KEY_SEPARATOR, fields); +} +} // namespace OHOS::DistributedData \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_event.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_event.h index 5e3056e4..47c873c9 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_event.h +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_event.h @@ -25,14 +25,16 @@ public: enum : int32_t { FEATURE_INIT = EVT_CLOUD, GET_SCHEMA, + DATA_CHANGE, CLOUD_BUTT }; struct StoreInfo { uint32_t tokenId = 0; - std::string bundleName = ""; - std::string storeName = ""; + std::string bundleName; + std::string storeName; int32_t instanceId = 0; + int32_t user = 0; }; CloudEvent(int32_t evtId, StoreInfo storeInfo, const std::string &featureName = "relational_store"); diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_info.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_info.h index fab87705..dc732027 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_info.h +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_info.h @@ -35,7 +35,6 @@ public: uint64_t totalSpace = 0; uint64_t remainSpace = 0; bool enableCloud = false; -// std::map apps; std::vector apps; std::string GetKey() const; diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/subscription.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/subscription.h new file mode 100644 index 00000000..c0e8dec5 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/subscription.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2023 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_FRAMEWORK_CLOUD_SUBSCRIPTION_H +#define OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_SUBSCRIPTION_H +#include "serializable/serializable.h" +namespace OHOS::DistributedData { +struct API_EXPORT Subscription final : public Serializable { + int32_t userId = 0; + std::string id; + std::map expiresTime; + + struct API_EXPORT Relation final : public Serializable { + std::string id; + std::string bundleName; + std::map relations; + bool Marshal(json &node) const override; + bool Unmarshal(const json &node) override; + }; + + bool Marshal(json &node) const; + bool Unmarshal(const json &node); + std::string GetKey(); + std::string GetRelationKey(const std::string &bundleName); + static std::string GetKey(int32_t userId); + static std::string GetRelationKey(int32_t userId, const std::string &bundleName); + static std::string GetPrefix(const std::initializer_list &fields); +private: + static constexpr const char *PREFIX = "CLOUD_SUBSCRIPTION"; + static constexpr const char *RELATION_PREFIX = "CLOUD_RELATION"; + static constexpr uint64_t INVALID_TIME = 0; +}; +} // namespace OHOS::DistributedData +#endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_SUBSCRIPTION_H diff --git a/datamgr_service/services/distributeddataservice/framework/include/serializable/serializable.h b/datamgr_service/services/distributeddataservice/framework/include/serializable/serializable.h index 4b16f8dd..f652a684 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/serializable/serializable.h +++ b/datamgr_service/services/distributeddataservice/framework/include/serializable/serializable.h @@ -21,6 +21,7 @@ #ifndef JSON_NOEXCEPTION #define JSON_NOEXCEPTION #endif +#include #include namespace OHOS { namespace DistributedData { @@ -32,6 +33,7 @@ public: using json = nlohmann::json; using size_type = nlohmann::json::size_type; using error_handler_t = nlohmann::detail::error_handler_t; + API_EXPORT json Marshall() const; template static std::string Marshall(T &values) @@ -64,60 +66,192 @@ public: API_EXPORT static bool SetValue(json &node, const int32_t &value); API_EXPORT static bool SetValue(json &node, const int64_t &value); API_EXPORT static bool SetValue(json &node, const uint64_t &value); - API_EXPORT static bool SetValue(json &node, const bool &value); + // Use bool & to forbid the const T * auto convert to bool, const bool will convert to const uint32_t &value; + API_EXPORT static bool SetValue(json &node, bool &value); API_EXPORT static bool SetValue(json &node, const std::vector &value); API_EXPORT static bool SetValue(json &node, const Serializable &value); + + template + API_EXPORT static bool SetValue(json &node, const std::variant<_Types...> &input); + + template + API_EXPORT static bool GetValue(const json &node, const std::string &name, std::variant<_Types...> &value); protected: API_EXPORT ~Serializable() = default; template - static bool GetValue(const json &node, const std::string &name, T *&value) - { - auto &subNode = GetSubNode(node, name); - if (subNode.is_null()) { - return false; - } - value = new(std::nothrow) T(); - if (value == nullptr) { - return false; - } - bool result = GetValue(subNode, "", *value); - if (!result) { - delete value; - value = nullptr; - } - return result; - } + static bool GetValue(const json &node, const std::string &name, std::vector &values); + template - static bool GetValue(const json &node, const std::string &name, std::vector &values) - { - auto &subNode = GetSubNode(node, name); - if (subNode.is_null() || !subNode.is_array()) { + static bool SetValue(json &node, const std::vector &values); + + template + static bool GetValue(const json &node, const std::string &name, std::map &values); + + template + static bool SetValue(json &node, const std::map &values); + + template + static bool GetValue(const json &node, const std::string &name, T *&value); + + template + static bool SetValue(json &node, const T *value); + + template + static bool ReadVariant(const json &node, const std::string &name, uint32_t step, uint32_t index, _OutTp &output); + + template + static bool ReadVariant(const json &node, const std::string &name, uint32_t step, uint32_t index, _OutTp &output); + + template + static bool WriteVariant(json &node, uint32_t step, const _InTp &input); + + template + static bool WriteVariant(json &node, uint32_t step, const _InTp &input); + API_EXPORT static const json &GetSubNode(const json &node, const std::string &name); +}; + +template +bool Serializable::GetValue(const json &node, const std::string &name, std::vector &values) +{ + auto &subNode = GetSubNode(node, name); + if (subNode.is_null() || !subNode.is_array()) { + return false; + } + bool result = true; + values.resize(subNode.size()); + for (size_type i = 0; i < subNode.size(); ++i) { + result = GetValue(subNode[i], "", values[i]) && result; + } + return result; +} + +template +bool Serializable::SetValue(json &node, const std::vector &values) +{ + bool result = true; + size_type i = 0; + node = json::value_t::array; + for (const auto &value : values) { + result = SetValue(node[i], value) && result; + i++; + } + return result; +} + +template +bool Serializable::GetValue(const json &node, const std::string &name, std::map &values) +{ + auto &subNode = GetSubNode(node, name); + if (subNode.is_null() || !subNode.is_object()) { + return false; + } + bool result = true; + for (auto object = subNode.begin(); object != subNode.end(); ++object) { + result = GetValue(object.value(), "", values[object.key()]) && result; + } + return result; +} + +template +bool Serializable::SetValue(json &node, const std::map &values) +{ + bool result = true; + node = json::value_t::object; + for (const auto &[key, value] : values) { + result = SetValue(node[key], value) && result; + } + return result; +} + +template +bool Serializable::GetValue(const json &node, const std::string &name, T *&value) +{ + auto &subNode = GetSubNode(node, name); + if (subNode.is_null()) { + return false; + } + value = new(std::nothrow) T(); + if (value == nullptr) { + return false; + } + bool result = GetValue(subNode, "", *value); + if (!result) { + delete value; + value = nullptr; + } + return result; +} + +template +bool Serializable::SetValue(json &node, const T *value) +{ + if (value == nullptr) { + return false; + } + return SetValue(node, *value); +} + +template +bool Serializable::SetValue(json &node, const std::variant<_Types...> &input) +{ + bool ret = SetValue(node[GET_NAME(type)], input.index()); + if (!ret) { + return ret; + } + return WriteVariant(node[GET_NAME(value)], 0, input); +} + +template +bool Serializable::GetValue(const json &node, const std::string &name, std::variant<_Types...> &value) +{ + auto &subNode = GetSubNode(node, name); + if (subNode.is_null()) { + return false; + } + uint32_t index; + bool ret = GetValue(subNode, GET_NAME(type), index); + if (!ret) { + return ret; + } + + return Serializable::ReadVariant(subNode, GET_NAME(value), 0, index, value); +} + +template +bool Serializable::WriteVariant(json &node, uint32_t step, const _InTp &input) +{ + return false; +} + +template +bool Serializable::ReadVariant(const json &node, const std::string &name, uint32_t step, uint32_t index, _OutTp &output) +{ + if (step == index) { + _First result; + if (!Serializable::GetValue(node, name, result)) { return false; } - bool result = true; - values.resize(subNode.size()); - for (size_type i = 0; i < subNode.size(); ++i) { - result = GetValue(subNode[i], "", values[i]) && result; - } - return result; + output = result; + return true; } + return Serializable::ReadVariant<_OutTp, _Rest...>(node, name, step + 1, index, output); +} - template - static bool SetValue(json &node, const std::vector &values) - { - bool result = true; - size_type i = 0; - node = json::value_t::array; - for (const auto &value : values) { - result = SetValue(node[i], value) && result; - i++; - } - return result; +template +bool Serializable::WriteVariant(json &node, uint32_t step, const _InTp &input) +{ + if (step == input.index()) { + return Serializable::SetValue(node, std::get<_First>(input)); } + return WriteVariant<_InTp, _Rest...>(node, step + 1, input); +} - API_EXPORT static const json &GetSubNode(const json &node, const std::string &name); -}; +template +bool Serializable::ReadVariant(const json &node, const std::string &name, uint32_t step, uint32_t index, _OutTp &output) +{ + return false; +} } // namespace DistributedData } // namespace OHOS #endif // OHOS_DISTRIBUTED_DATA_FRAMEWORKS_COMMON_SERIALIZABLE_H diff --git a/datamgr_service/services/distributeddataservice/framework/include/store/auto_cache.h b/datamgr_service/services/distributeddataservice/framework/include/store/auto_cache.h index 11c3a117..600ed318 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/store/auto_cache.h +++ b/datamgr_service/services/distributeddataservice/framework/include/store/auto_cache.h @@ -44,7 +44,7 @@ public: API_EXPORT void Bind(std::shared_ptr executor); - API_EXPORT Store GetStore(const StoreMetaData &meta, const Watchers &watchers, bool setWatchers = true); + API_EXPORT Store GetStore(const StoreMetaData &meta, const Watchers &watchers); API_EXPORT void CloseStore(uint32_t tokenId, const std::string &storeId); diff --git a/datamgr_service/services/distributeddataservice/framework/serializable/serializable.cpp b/datamgr_service/services/distributeddataservice/framework/serializable/serializable.cpp index 509880a8..c1c7ca8b 100644 --- a/datamgr_service/services/distributeddataservice/framework/serializable/serializable.cpp +++ b/datamgr_service/services/distributeddataservice/framework/serializable/serializable.cpp @@ -116,11 +116,19 @@ bool Serializable::GetValue(const json &node, const std::string &name, uint64_t bool Serializable::GetValue(const json &node, const std::string &name, bool &value) { auto &subNode = GetSubNode(node, name); - if (subNode.is_null() || !subNode.is_boolean()) { - return false; + if (subNode.is_boolean()) { + subNode.get_to(value); + return true; } - subNode.get_to(value); - return true; + + if (subNode.is_number_unsigned()) { + uint32_t number = 0; + subNode.get_to(number); + value = number != 0; + return true; + } + + return false; } bool Serializable::GetValue(const json &node, const std::string &name, std::vector &value) @@ -172,7 +180,7 @@ bool Serializable::SetValue(json &node, const uint64_t &value) return true; } -bool Serializable::SetValue(json &node, const bool &value) +bool Serializable::SetValue(json &node, bool &value) { node = value; return true; diff --git a/datamgr_service/services/distributeddataservice/framework/store/auto_cache.cpp b/datamgr_service/services/distributeddataservice/framework/store/auto_cache.cpp index 37aff132..db51ad5c 100644 --- a/datamgr_service/services/distributeddataservice/framework/store/auto_cache.cpp +++ b/datamgr_service/services/distributeddataservice/framework/store/auto_cache.cpp @@ -52,7 +52,7 @@ AutoCache::~AutoCache() } } -AutoCache::Store AutoCache::GetStore(const StoreMetaData &meta, const Watchers &watchers, bool setWatchers) +AutoCache::Store AutoCache::GetStore(const StoreMetaData &meta, const Watchers &watchers) { Store store; if (meta.storeType >= MAX_CREATOR_NUM || meta.storeType < 0 || !creators_[meta.storeType]) { @@ -60,10 +60,10 @@ AutoCache::Store AutoCache::GetStore(const StoreMetaData &meta, const Watchers & } stores_.Compute(meta.tokenId, - [this, &meta, &watchers, &store, setWatchers](auto &, std::map &stores) -> bool { + [this, &meta, &watchers, &store](auto &, std::map &stores) -> bool { auto it = stores.find(meta.storeId); if (it != stores.end()) { - if (setWatchers) { + if (!watchers.empty()) { it->second.SetObservers(watchers); } store = it->second; diff --git a/datamgr_service/services/distributeddataservice/framework/test/serializable_test.cpp b/datamgr_service/services/distributeddataservice/framework/test/serializable_test.cpp index 95c0154b..697b33b5 100644 --- a/datamgr_service/services/distributeddataservice/framework/test/serializable_test.cpp +++ b/datamgr_service/services/distributeddataservice/framework/test/serializable_test.cpp @@ -159,3 +159,78 @@ HWTEST_F(SerializableTest, GetMutilVal, TestSize.Level2) normal1.Unmarshall(jstr); ASSERT_TRUE(normalEx == normal1) << normal1.name; } + +/** +* @tc.name: GetMap +* @tc.desc: mutil value case. +* @tc.type: FUNC +* @tc.require: +* @tc.author: Sven Wang +*/ +HWTEST_F(SerializableTest, GetMap, TestSize.Level2) +{ + ZLOGI("SerializableSuite GetMapVals begin."); + std::map marshData; + NormalEx normalEx; + normalEx.normals = { Normal() }; + normalEx.name = "normalEx"; + marshData.insert(std::pair{ "test1", normalEx }); + auto jsonData = NormalEx::Marshall(marshData); + + std::map unmarshData; + NormalEx::Unmarshall(jsonData, unmarshData); + ASSERT_TRUE((marshData["test1"] == unmarshData["test1"])) << jsonData; +} + +/** +* @tc.name: GetMapInStruct +* @tc.desc: mutil value case. +* @tc.type: FUNC +* @tc.require: +* @tc.author: Sven Wang +*/ +HWTEST_F(SerializableTest, GetMapInStruct, TestSize.Level2) +{ + struct TestMeta : public Serializable { + std::map data; + std::map *index = nullptr; + std::vector> others; + ~TestMeta() + { + delete index; + } + bool Marshal(json &node) const + { + SetValue(node[GET_NAME(data)], data); + SetValue(node[GET_NAME(index)], index); + SetValue(node[GET_NAME(others)], others); + return true; + } + + bool Unmarshal(const json &node) + { + GetValue(node, GET_NAME(data), data); + GetValue(node, GET_NAME(index), index); + GetValue(node, GET_NAME(others), others); + return true; + } + }; + ZLOGI("SerializableSuite GetMapVals begin."); + TestMeta marData; + NormalEx normalEx; + normalEx.normals = { Normal() }; + normalEx.name = "normalEx"; + marData.data.insert(std::pair{ "test1", normalEx }); + marData.others.push_back({ std::pair{ "test2", normalEx } }); + marData.index = new (std::nothrow) std::map; + ASSERT_NE(marData.index, nullptr); + marData.index->insert(std::pair{ "test1", true }); + marData.index->insert(std::pair{ "test2", true }); + auto jsonData = NormalEx::Marshall(marData); + TestMeta unmarData; + NormalEx::Unmarshall(jsonData, unmarData); + ASSERT_TRUE((marData.data == unmarData.data)) << jsonData; + ASSERT_TRUE((marData.others == unmarData.others)) << jsonData; + ASSERT_NE(unmarData.index, nullptr); + ASSERT_TRUE((*marData.index == *unmarData.index)) << jsonData; +} \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/BUILD.gn b/datamgr_service/services/distributeddataservice/service/BUILD.gn index 35707d65..e27030a9 100644 --- a/datamgr_service/services/distributeddataservice/service/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/BUILD.gn @@ -56,13 +56,13 @@ ohos_shared_library("distributeddatasvc") { "../../../../data_object/frameworks/innerkitsimpl/include", "../../../../relational_store/interfaces/inner_api/cloud_data/include", "../../../../relational_store/interfaces/inner_api/rdb/include", + "${kv_store_distributeddb_path}", ] sources = [ "backup/src/backup_manager.cpp", "bootstrap/src/bootstrap.cpp", "cloud/cloud_service_impl.cpp", "cloud/cloud_service_stub.cpp", - "cloud/cloud_syncer.cpp", "config/src/config_factory.cpp", "config/src/model/backup_config.cpp", "config/src/model/checker_config.cpp", @@ -108,7 +108,7 @@ ohos_shared_library("distributeddatasvc") { "rdb/rdb_service_stub.cpp", "rdb/rdb_store_observer_impl.cpp", "rdb/rdb_syncer.cpp", - "rdb/value_proxy.cpp", + "rdb/rdb_watcher.cpp", ] cflags = [ "-Wno-multichar" ] diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp index 4863cdba..8c855615 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp @@ -21,6 +21,7 @@ #include "checker/checker_manager.h" #include "cloud/cloud_event.h" #include "cloud/cloud_server.h" +#include "cloud/subscription.h" #include "communicator/device_manager_adapter.h" #include "eventcenter/event_center.h" #include "feature/feature_system.h" @@ -28,8 +29,8 @@ #include "log_print.h" #include "metadata/meta_data_manager.h" #include "metadata/store_meta_data.h" -#include "utils/anonymous.h" #include "store/auto_cache.h" +#include "utils/anonymous.h" namespace OHOS::CloudData { using namespace DistributedData; using DmAdapter = OHOS::DistributedData::DeviceManagerAdapter; @@ -52,11 +53,6 @@ CloudServiceImpl::Factory::~Factory() {} CloudServiceImpl::CloudServiceImpl() { - EventCenter::GetInstance().Subscribe(CloudEvent::FEATURE_INIT, [this](const Event &event) { - FeatureInit(event); - return; - }); - EventCenter::GetInstance().Subscribe(CloudEvent::GET_SCHEMA, [this](const Event &event) { GetSchema(event); return; @@ -66,8 +62,9 @@ CloudServiceImpl::CloudServiceImpl() int32_t CloudServiceImpl::EnableCloud(const std::string &id, const std::map &switches) { CloudInfo cloudInfo; - if (GetCloudInfo(IPCSkeleton::GetCallingTokenID(), id, cloudInfo) != SUCCESS) { - return INVALID_ARGUMENT; + auto status = GetCloudInfo(IPCSkeleton::GetCallingTokenID(), id, cloudInfo); + if (status != SUCCESS) { + return status; } cloudInfo.enableCloud = true; for (const auto &item : switches) { @@ -83,27 +80,31 @@ int32_t CloudServiceImpl::EnableCloud(const std::string &id, const std::map bool { @@ -117,14 +118,17 @@ int32_t CloudServiceImpl::ChangeAppSwitch(const std::string &id, const std::stri if (!MetaDataManager::GetInstance().SaveMeta(cloudInfo.GetKey(), cloudInfo, true)) { return ERROR; } + Execute(GetCloudTask(0, cloudInfo.user)); return SUCCESS; } int32_t CloudServiceImpl::Clean(const std::string &id, const std::map &actions) { CloudInfo cloudInfo; - if (GetCloudInfo(IPCSkeleton::GetCallingTokenID(), id, cloudInfo) != SUCCESS) { - return INVALID_ARGUMENT; + auto tokenId = IPCSkeleton::GetCallingTokenID(); + cloudInfo.user = DistributedKv::AccountDelegate::GetInstance()->GetUserByToken(tokenId); + if (GetCloudInfoFromMeta(cloudInfo) != SUCCESS) { + return ERROR; } auto keys = cloudInfo.GetSchemaKey(); for (const auto &action : actions) { @@ -133,6 +137,7 @@ int32_t CloudServiceImpl::Clean(const std::string &id, const std::mapGetUserByToken(tokenId); + if (GetCloudInfoFromMeta(cloudInfo) != SUCCESS) { + return ERROR; + } + if (cloudInfo.id != id) { + ZLOGE("invalid args, [input] id:%{public}s, [exist] id:%{public}s", Anonymous::Change(id).c_str(), + Anonymous::Change(cloudInfo.id).c_str()); + return INVALID_ARGUMENT; + } + if (!cloudInfo.enableCloud) { + return CLOUD_DISABLE; + } + auto it = std::find_if(cloudInfo.apps.begin(), cloudInfo.apps.end(), + [&bundleName](const CloudInfo::AppInfo &appInfo) -> bool { + return appInfo.bundleName == bundleName; + }); + if (it == cloudInfo.apps.end()) { + ZLOGE("bundleName:%{public}s", bundleName.c_str()); + return INVALID_ARGUMENT; + } + if (!it->cloudSwitch) { + return CLOUD_DISABLE_SWITCH; + } + + auto key = cloudInfo.GetSchemaKey(bundleName); + SchemaMeta schemaMeta; + if (!MetaDataManager::GetInstance().LoadMeta(key, schemaMeta, true)) { + ZLOGE("bundleName:%{public}s", bundleName.c_str()); + return INVALID_ARGUMENT; + } + for (const auto &database : schemaMeta.databases) { + EventCenter::Defer defer; + CloudEvent::StoreInfo storeInfo; + storeInfo.bundleName = it->bundleName; + storeInfo.instanceId = it->instanceId; + storeInfo.user = cloudInfo.user; + storeInfo.storeName = database.name; + auto evt = std::make_unique(CloudEvent::DATA_CHANGE, storeInfo); + EventCenter::GetInstance().PostEvent(std::move(evt)); + } + return SUCCESS; } int32_t CloudServiceImpl::OnInitialize() { - auto *cloudServer = CloudServer::GetInstance(); - if (cloudServer == nullptr) { - - } - return Feature::OnInitialize(); + FeatureInit(); + Execute(GetCloudTask(0, 0)); + return E_OK; } int32_t CloudServiceImpl::OnExecutor(std::shared_ptr executor) { + if (executor_ != nullptr || executor == nullptr) { + return E_INVALID_ARGS; + } + executor_ = std::move(executor); return E_OK; } +int32_t CloudServiceImpl::OnUserChange(uint32_t code, const std::string &user, const std::string &account) +{ + Execute(GetCloudTask(0, atoi(user.c_str()))); + return E_OK; +} + int32_t CloudServiceImpl::GetCloudInfo(uint32_t tokenId, const std::string &id, CloudInfo &cloudInfo) { cloudInfo.user = DistributedKv::AccountDelegate::GetInstance()->GetUserByToken(tokenId); - if (!MetaDataManager::GetInstance().LoadMeta(cloudInfo.GetKey(), cloudInfo, true) && - GetServerInfo(cloudInfo) != SUCCESS) { - ZLOGE("invalid args, user:%{public}d", cloudInfo.user); - return INVALID_ARGUMENT; + if (GetCloudInfoFromMeta(cloudInfo) != SUCCESS) { + auto status = GetCloudInfoFromServer(cloudInfo); + if (status != SUCCESS) { + ZLOGE("user:%{public}d", cloudInfo.user); + return status; + } } if (cloudInfo.id != id) { ZLOGE("invalid args, [input] id:%{public}s, [exist] id:%{public}s", Anonymous::Change(id).c_str(), @@ -174,35 +231,23 @@ int32_t CloudServiceImpl::GetCloudInfo(uint32_t tokenId, const std::string &id, return SUCCESS; } -int32_t CloudServiceImpl::GetServerInfo(CloudInfo &cloudInfo) +int32_t CloudServiceImpl::GetCloudInfoFromMeta(CloudInfo &cloudInfo) { - auto instance = CloudServer::GetInstance(); - if (instance == nullptr) { - return SERVER_UNAVAILABLE; - } - cloudInfo = instance->GetServerInfo(cloudInfo.user); - if (!cloudInfo.IsValid()) { + if (!MetaDataManager::GetInstance().LoadMeta(cloudInfo.GetKey(), cloudInfo, true)) { + ZLOGE("no exist meta, user:%{public}d", cloudInfo.user); return ERROR; } return SUCCESS; } -std::string CloudServiceImpl::GetAppId(const std::string &bundleName) +int32_t CloudServiceImpl::GetCloudInfoFromServer(CloudInfo &cloudInfo) { - CheckerManager::StoreInfo storeInfo; - storeInfo.uid = IPCSkeleton::GetCallingUid(); - storeInfo.tokenId = IPCSkeleton::GetCallingTokenID(); - storeInfo.bundleName = bundleName; - return CheckerManager::GetInstance().GetAppId(storeInfo); -} - -bool CloudServiceImpl::CheckAccess(const std::string &bundleName) -{ - CheckerManager::StoreInfo storeInfo; - storeInfo.uid = IPCSkeleton::GetCallingUid(); - storeInfo.tokenId = IPCSkeleton::GetCallingTokenID(); - storeInfo.bundleName = bundleName; - return CheckerManager::GetInstance().IsValid(storeInfo); + auto instance = CloudServer::GetInstance(); + if (instance == nullptr) { + return NOT_SUPPORT; + } + cloudInfo = instance->GetServerInfo(cloudInfo.user); + return SUCCESS; } void CloudServiceImpl::UpdateCloudInfo(CloudInfo &cloudInfo) @@ -244,25 +289,33 @@ int32_t CloudServiceImpl::GetAppSchema(int32_t user, const std::string &bundleNa return SUCCESS; } -//ExecutorPool::Task CloudServiceImpl::GetCloudTask(int32_t retry) -//{ -// return [this, retry]() -> void { -// std::vector users; -// auto success = Account::GetInstance()->QueryUsers(users); -// CloudServer *cloud = CloudServer::GetInstance(); -// for (auto user : users) { -// cloud->GetServerInfo(user); -// } -// -// if (cloud == nullptr) { -// -// } -// if (executor_ == nullptr) { -// return ; -// } -// executor_->Schedule(std::chrono::seconds(RETRY_INTERVAL), GetCloudTask(retry + 1)); -// }; -//} +ExecutorPool::Task CloudServiceImpl::GetCloudTask(int32_t retry, int32_t user) +{ + return [this, retry, user]() -> void { + auto executor = executor_; + if (retry >= RETRY_TIMES || executor == nullptr) { + return; + } + + bool finished = true; + std::vector users; + if (user == 0) { + finished = Account::GetInstance()->QueryUsers(users); + } else { + users.push_back(user); + } + + for (auto user : users) { + Subscription subscription; + subscription.userId = user; + MetaDataManager::GetInstance().LoadMeta(subscription.GetKey(), subscription, true); + finished = DoSubscribe(subscription) && finished; + } + if (!finished) { + executor->Schedule(std::chrono::seconds(RETRY_INTERVAL), GetCloudTask(retry + 1, user)); + } + }; +} SchemaMeta CloudServiceImpl::GetSchemaMata(int32_t userId, const std::string &bundleName, int32_t instanceId) { @@ -272,9 +325,21 @@ SchemaMeta CloudServiceImpl::GetSchemaMata(int32_t userId, const std::string &bu ZLOGE("instance is nullptr"); return schemaMeta; } - auto cloudInfo = instance->GetServerInfo(userId); - if (!cloudInfo.IsValid()) { - ZLOGE("cloudInfo is invalid"); + CloudInfo cloudInfo; + cloudInfo.user = userId; + if (!MetaDataManager::GetInstance().LoadMeta(cloudInfo.GetKey(), cloudInfo, true)) { + cloudInfo = instance->GetServerInfo(userId); + if (!cloudInfo.IsValid()) { + ZLOGE("cloudInfo is invalid"); + return schemaMeta; + } + MetaDataManager::GetInstance().SaveMeta(cloudInfo.GetKey(), cloudInfo, true); + } + if (std::find_if(cloudInfo.apps.begin(), cloudInfo.apps.end(), + [&bundleName, &instanceId](const CloudInfo::AppInfo &appInfo) { + return appInfo.bundleName == bundleName && appInfo.instanceId == instanceId; + }) == cloudInfo.apps.end()) { + ZLOGE("bundleName:%{public}s instanceId:%{public}d", bundleName.c_str(), instanceId); return schemaMeta; } std::string schemaKey = cloudInfo.GetSchemaKey(bundleName, instanceId); @@ -298,20 +363,25 @@ StoreMetaData CloudServiceImpl::GetStoreMata(int32_t userId, const std::string & return storeMetaData; } -void CloudServiceImpl::FeatureInit(const Event &event) +void CloudServiceImpl::FeatureInit() { CloudInfo cloudInfo; std::vector users; if (!DistributedKv::AccountDelegate::GetInstance()->QueryUsers(users) || users.empty()) { return; } - cloudInfo.user = *users.begin(); - if (GetServerInfo(cloudInfo) != SUCCESS) { - ZLOGE("failed, user:%{public}d", cloudInfo.user); - return; + for (const auto &user : users) { + if (user == USER_ID) { + continue; + } + cloudInfo.user = user; + if (GetCloudInfoFromServer(cloudInfo) != SUCCESS) { + ZLOGE("failed, user:%{public}d", user); + continue; + } + UpdateCloudInfo(cloudInfo); + AddSchema(cloudInfo); } - UpdateCloudInfo(cloudInfo); - AddSchema(cloudInfo); } void CloudServiceImpl::GetSchema(const Event &event) @@ -322,16 +392,12 @@ void CloudServiceImpl::GetSchema(const Event &event) rdbEvent.GetStoreInfo().instanceId); auto userId = DistributedKv::AccountDelegate::GetInstance()->GetUserByToken(rdbEvent.GetStoreInfo().tokenId); auto schemaMeta = GetSchemaMata(userId, rdbEvent.GetStoreInfo().bundleName, rdbEvent.GetStoreInfo().instanceId); + if (schemaMeta.databases.empty()) { + return; + } auto storeMeta = GetStoreMata(userId, rdbEvent.GetStoreInfo().bundleName, rdbEvent.GetStoreInfo().storeName, rdbEvent.GetStoreInfo().instanceId); - AutoCache::Watchers watchers; - auto store = AutoCache::GetInstance().GetStore(storeMeta, watchers, false); - if (store == nullptr) { - ZLOGE("store is nullptr"); - return; - } - store->SetSchema(schemaMeta); auto instance = CloudServer::GetInstance(); if (instance == nullptr) { ZLOGE("instance is nullptr"); @@ -341,15 +407,83 @@ void CloudServiceImpl::GetSchema(const Event &event) if (database.name != rdbEvent.GetStoreInfo().storeName /* || don't need sync */) { continue; } + ZLOGD("database: %{public}s sync start", database.name.c_str()); + // ConnectCloudDB and Bind to store auto cloudDB = instance->ConnectCloudDB(rdbEvent.GetStoreInfo().tokenId, database); if (cloudDB != nullptr) { + AutoCache::Watchers watchers; + auto store = AutoCache::GetInstance().GetStore(storeMeta, watchers); + if (store == nullptr) { + ZLOGE("store is nullptr"); + return; + } + store->SetSchema(schemaMeta); store->Bind(cloudDB); } for (auto &table : database.tables) { - ZLOGI("table: %{public}s sync start", table.name.c_str()); + ZLOGD("table: %{public}s sync start", table.name.c_str()); } // do sync } return; } + +bool CloudServiceImpl::DoSubscribe(const Subscription &sub) +{ + if (CloudServer::GetInstance() == nullptr) { + ZLOGI("not support cloud server"); + return true; + } + + CloudInfo cloudInfo; + cloudInfo.user = sub.userId; + auto exits = MetaDataManager::GetInstance().LoadMeta(cloudInfo.GetKey(), cloudInfo, true); + if (!exits) { + ZLOGW("error, there is no cloud info for user(%{public}d)", sub.userId); + return false; + } + + ZLOGD("begin cloud:%{public}d user:%{public}d apps:%{public}zu", cloudInfo.enableCloud, sub.userId, + cloudInfo.apps.size()); + auto onThreshold = (std::chrono::system_clock::now() + std::chrono::hours(EXPIRE_INTERVAL)).time_since_epoch(); + auto offThreshold = std::chrono::system_clock::now().time_since_epoch(); + std::map> subDbs; + std::map> unsubDbs; + for (auto &app : cloudInfo.apps) { + auto enabled = cloudInfo.enableCloud && app.cloudSwitch; + auto &dbs = enabled ? subDbs : unsubDbs; + auto it = sub.expiresTime.find(app.bundleName); + // cloud is enabled, but the subscription won't expire + if (enabled && (it != sub.expiresTime.end() && it->second >= onThreshold.count())) { + continue; + } + // cloud is disabled, we don't care the subscription which was expired or didn't subscribe. + if (!enabled && (it == sub.expiresTime.end() || it->second <= offThreshold.count())) { + continue; + } + + SchemaMeta schemaMeta; + exits = MetaDataManager::GetInstance().LoadMeta(cloudInfo.GetSchemaKey(app.bundleName), schemaMeta, true); + if (exits) { + dbs[app.bundleName] = std::move(schemaMeta.databases); + } + } + + ZLOGI("cloud switch:%{public}d user%{public}d, sub:%{public}zu, unsub:%{public}zu", cloudInfo.enableCloud, + sub.userId, subDbs.size(), unsubDbs.size()); + ZLOGD("Subscribe user%{public}d details:%{public}s", sub.userId, Serializable::Marshall(subDbs).c_str()); + ZLOGD("Unsubscribe user%{public}d details:%{public}s", sub.userId, Serializable::Marshall(unsubDbs).c_str()); + CloudServer::GetInstance()->Subscribe(sub.userId, subDbs); + CloudServer::GetInstance()->Unsubscribe(sub.userId, unsubDbs); + return subDbs.empty() && unsubDbs.empty(); +} + +void CloudServiceImpl::Execute(ExecutorPool::Task task) +{ + auto executor = executor_; + if (executor == nullptr) { + return; + } + executor->Execute(std::move(task)); +} } // namespace OHOS::CloudData \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.h b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.h index 276603e2..35121c57 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.h +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.h @@ -21,6 +21,7 @@ #include "cloud/cloud_info.h" #include "cloud/schema_meta.h" #include "cloud/cloud_event.h" +#include "cloud/subscription.h" namespace OHOS::CloudData { class CloudServiceImpl : public CloudServiceStub { @@ -35,8 +36,10 @@ public: int32_t NotifyDataChange(const std::string &id, const std::string &bundleName) override; int32_t OnInitialize() override; int32_t OnExecutor(std::shared_ptr executor) override; + int32_t OnUserChange(uint32_t code, const std::string &user, const std::string &account) override; private: + static const inline int USER_ID = 0; class Factory { public: Factory() noexcept; @@ -49,9 +52,11 @@ private: using CloudInfo = DistributedData::CloudInfo; using SchemaMeta = DistributedData::SchemaMeta; using Event = DistributedData::Event; + using Subscription = DistributedData::Subscription; static constexpr int32_t RETRY_TIMES = 10; static constexpr int32_t RETRY_INTERVAL = 30; + static constexpr int32_t EXPIRE_INTERVAL = 7 * 24; // 7 day void UpdateCloudInfo(CloudInfo &cloudInfo); void AddSchema(CloudInfo &cloudInfo); @@ -59,13 +64,14 @@ private: StoreMetaData GetStoreMata(int32_t userId, const std::string &bundleName, const std::string &storeName, int32_t instanceId); int32_t GetCloudInfo(uint32_t tokenId, const std::string &id, CloudInfo &cloudInfo); - int32_t GetServerInfo(CloudInfo &cloudInfo); + int32_t GetCloudInfoFromMeta(CloudInfo &cloudInfo); + int32_t GetCloudInfoFromServer(CloudInfo &cloudInfo); int32_t GetAppSchema(int32_t user, const std::string &bundleName, SchemaMeta &schemaMeta); - std::string GetAppId(const std::string &bundleName); - void FeatureInit(const Event &event); + void FeatureInit(); void GetSchema(const Event &event); -// ExecutorPool::Task GetCloudTask(int32_t retry); - bool CheckAccess(const std::string &bundleName); + ExecutorPool::Task GetCloudTask(int32_t retry, int32_t user); + void Execute(ExecutorPool::Task task); + bool DoSubscribe(const Subscription &sub); std::shared_ptr executor_; }; } // namespace OHOS::DistributedData diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.cpp b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.cpp index 61e9dc63..b14485f4 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.cpp +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.cpp @@ -48,7 +48,8 @@ int CloudServiceStub::OnRemoteRequest(uint32_t code, OHOS::MessageParcel &data, if (!TokenIdKit::IsSystemAppByFullTokenID(IPCSkeleton::GetCallingFullTokenID())) { ZLOGE("permission denied! code:%{public}u, BUTT:%{public}d", code, TRANS_BUTT); - return -1; + auto result = static_cast(PERMISSION_DENIED); + return ITypesUtil::Marshal(reply, result) ? ERR_NONE : IPC_STUB_WRITE_PARCEL_ERR; } std::string id; diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp index 16fd16ba..f7a9b2c7 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp @@ -24,11 +24,13 @@ #include "eventcenter/event_center.h" #include "ipc_skeleton.h" #include "log_print.h" +#include "metadata/appid_meta_data.h" #include "metadata/meta_data_manager.h" #include "metadata/store_meta_data.h" #include "permission/permission_validator.h" +#include "rdb_watcher.h" #include "rdb_notifier_proxy.h" -#include "store/auto_cache.h" +#include "rdb_query.h" #include "types_export.h" #include "utils/anonymous.h" #include "utils/constant.h" @@ -44,6 +46,7 @@ using namespace OHOS::DistributedData; using namespace OHOS::Security::AccessToken; using DistributedDB::RelationalStoreManager; using DmAdapter = OHOS::DistributedData::DeviceManagerAdapter; +using system_clock = std::chrono::system_clock; constexpr uint32_t ITERATE_TIMES = 10000; namespace OHOS::DistributedRdb { @@ -91,6 +94,30 @@ RdbServiceImpl::RdbServiceImpl() : autoLaunchObserver_(this) [this](const std::string& identifier, DistributedDB::AutoLaunchParam ¶m) { return ResolveAutoLaunch(identifier, param); }); + EventCenter::GetInstance().Subscribe(CloudEvent::DATA_CHANGE, [this](const Event &event) { + auto &evt = static_cast(event); + auto storeInfo = evt.GetStoreInfo(); + StoreMetaData meta; + meta.storeId = storeInfo.storeName; + meta.bundleName = storeInfo.bundleName; + meta.user = std::to_string(storeInfo.user); + meta.instanceId = storeInfo.instanceId; + meta.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + if (!MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta)) { + ZLOGE("meta empty, bundleName:%{public}s, storeId:%{public}s", + meta.bundleName.c_str(), meta.storeId.c_str()); + return; + } + auto watchers = GetWatchers(meta.tokenId, meta.storeId); + auto store = AutoCache::GetInstance().GetStore(meta, watchers); + if (store == nullptr) { + ZLOGE("store null, storeId:%{public}s", meta.storeId.c_str()); + return; + } + for (const auto &watcher : watchers) { // mock for datachange + watcher->OnChange(GeneralWatcher::Origin::ORIGIN_CLOUD, {}); + } + }); } int32_t RdbServiceImpl::ResolveAutoLaunch(const std::string &identifier, DistributedDB::AutoLaunchParam ¶m) @@ -139,6 +166,9 @@ void RdbServiceImpl::OnClientDied(pid_t pid) ZLOGI("client dead pid=%{public}d", pid); syncers_.ComputeIfPresent(pid, [this](const auto& key, StoreSyncersType& syncers) { syncerNum_ -= static_cast(syncers.size()); + for (const auto& [name, syncer] : syncers) { + executors_->Remove(syncer->GetTimerId()); + } return false; }); notifiers_.Erase(pid); @@ -259,12 +289,8 @@ std::shared_ptr RdbServiceImpl::GetRdbSyncer(const RdbSyncerParam &pa } syncers.erase(storeId); } - if (syncers.size() >= MAX_SYNCER_PER_PROCESS) { - ZLOGE("%{public}d exceed MAX_PROCESS_SYNCER_NUM", pid); - return !syncers.empty(); - } - if (syncerNum_ >= MAX_SYNCER_NUM) { - ZLOGE("no available syncer"); + if (syncers.size() >= MAX_SYNCER_PER_PROCESS || syncerNum_ >= MAX_SYNCER_NUM) { + ZLOGE("pid: %{public}d, syncers size: %{public}zu. syncerNum: %{public}d", pid, syncers.size(), syncerNum_); return !syncers.empty(); } auto rdbObserver = new (std::nothrow) RdbStoreObserverImpl(this, pid); @@ -272,7 +298,9 @@ std::shared_ptr RdbServiceImpl::GetRdbSyncer(const RdbSyncerParam &pa return !syncers.empty(); } auto syncer_ = std::make_shared(param, rdbObserver); - if (syncer_->Init(pid, uid, tokenId) != 0) { + StoreMetaData storeMetaData = GetStoreMetaData(param); + MetaDataManager::GetInstance().LoadMeta(storeMetaData.GetKey(), storeMetaData); + if (syncer_->Init(pid, uid, tokenId, storeMetaData) != 0) { return !syncers.empty(); } syncers[storeId] = syncer_; @@ -376,15 +404,74 @@ std::string RdbServiceImpl::GenIdentifier(const RdbSyncerParam ¶m) return TransferStringToHex(identifier); } -int32_t RdbServiceImpl::DoSubscribe(const RdbSyncerParam& param) +int32_t RdbServiceImpl::DoSubscribe(const RdbSyncerParam& param, const SubscribeOption &option) { pid_t pid = IPCSkeleton::GetCallingPid(); - auto identifier = GenIdentifier(param); - ZLOGI("%{public}s %{public}.6s %{public}d", param.storeName_.c_str(), identifier.c_str(), pid); - identifiers_.Insert(identifier, pid); + auto tokenId = IPCSkeleton::GetCallingTokenID(); + switch (option.mode) { + case SubscribeMode::REMOTE: { + auto identifier = GenIdentifier(param); + ZLOGI("%{public}s %{public}.6s %{public}d", param.storeName_.c_str(), identifier.c_str(), pid); + identifiers_.Insert(identifier, pid); + break; + } + case SubscribeMode::CLOUD: // fallthrough + case SubscribeMode::CLOUD_DETAIL: { + syncAgents_.Compute(tokenId, [this, pid, tokenId, ¶m, &option](auto &key, SyncAgent &value) { + if (pid != value.pid_) { + value.ReInit(pid, param.bundleName_); + } + auto storeName = RdbSyncer::RemoveSuffix(param.storeName_); + auto it = value.watchers_.find(storeName); + if (it == value.watchers_.end()) { + auto watcher = std::make_shared(this, tokenId, storeName); + value.watchers_[storeName] = { watcher }; + value.mode_[storeName] = option.mode; + } + return true; + }); + break; + } + default: + return RDB_ERROR; + } return RDB_OK; } +void RdbServiceImpl::OnChange(uint32_t tokenId, const std::string &storeName) +{ + pid_t pid = 0; + syncAgents_.ComputeIfPresent(tokenId, [&pid, &storeName](auto &key, SyncAgent &value) { + pid = value.pid_; + return true; + }); + notifiers_.ComputeIfPresent(pid, [&storeName](const auto& key, const sptr& value) { + value->OnChange(storeName, { storeName }); + return true; + }); +} + +AutoCache::Watchers RdbServiceImpl::GetWatchers(uint32_t tokenId, const std::string &storeName) +{ + AutoCache::Watchers watchers; + syncAgents_.ComputeIfPresent(tokenId, [&storeName, &watchers](auto, SyncAgent &agent) { + auto it = agent.watchers_.find(storeName); + if (it != agent.watchers_.end()) { + watchers = it->second; + } + return true; + }); + return watchers; +} + +void RdbServiceImpl::SyncAgent::ReInit(pid_t pid, const std::string &bundleName) +{ + pid_ = pid; + bundleName_ = bundleName; + watchers_.clear(); + mode_.clear(); +} + int32_t RdbServiceImpl::DoUnSubscribe(const RdbSyncerParam& param) { auto identifier = GenIdentifier(param); @@ -408,8 +495,7 @@ int32_t RdbServiceImpl::RemoteQuery(const RdbSyncerParam& param, const std::stri return syncer->RemoteQuery(device, sql, selectionArgs, resultSet); } -int32_t RdbServiceImpl::CreateRDBTable( - const RdbSyncerParam ¶m, const std::string &writePermission, const std::string &readPermission) +int32_t RdbServiceImpl::CreateRDBTable(const RdbSyncerParam ¶m) { if (!CheckAccess(param.bundleName_, param.storeName_)) { ZLOGE("permission error"); @@ -428,7 +514,9 @@ int32_t RdbServiceImpl::CreateRDBTable( } auto uid = IPCSkeleton::GetCallingUid(); auto tokenId = IPCSkeleton::GetCallingTokenID(); - if (syncer->Init(pid, uid, tokenId, writePermission, readPermission) != RDB_OK) { + StoreMetaData storeMetaData = GetStoreMetaData(param); + MetaDataManager::GetInstance().LoadMeta(storeMetaData.GetKey(), storeMetaData); + if (syncer->Init(pid, uid, tokenId, storeMetaData) != RDB_OK) { ZLOGE("Init error"); delete syncer; return RDB_ERROR; @@ -443,31 +531,12 @@ int32_t RdbServiceImpl::DestroyRDBTable(const RdbSyncerParam ¶m) ZLOGE("permission error"); return RDB_ERROR; } - pid_t pid = IPCSkeleton::GetCallingPid(); - auto rdbObserver = new (std::nothrow) RdbStoreObserverImpl(this, pid); - if (rdbObserver == nullptr) { - return RDB_ERROR; - } - auto syncer = new (std::nothrow) RdbSyncer(param, rdbObserver); - if (syncer == nullptr) { - ZLOGE("new syncer error"); - return RDB_ERROR; - } - - StoreMetaData meta; - if (syncer->DestroyMetaData(meta) != RDB_OK) { - ZLOGE("destroy meta data error"); - delete syncer; - return RDB_ERROR; - } - delete syncer; - return RDB_OK; + auto meta = GetStoreMetaData(param); + return MetaDataManager::GetInstance().DelMeta(meta.GetKey()) ? RDB_OK : RDB_ERROR; } int32_t RdbServiceImpl::OnInitialize() { - auto initEvt = std::make_unique(CloudEvent::FEATURE_INIT, CloudEvent::StoreInfo()); - EventCenter::GetInstance().PostEvent(std::move(initEvt)); return RDB_OK; } @@ -477,25 +546,12 @@ int32_t RdbServiceImpl::GetSchema(const RdbSyncerParam ¶m) ZLOGE("permission error"); return RDB_ERROR; } - auto syncer = GetRdbSyncer(param); - if (syncer == nullptr) { + StoreMetaData storeMeta; + if (CreateMetaData(param, storeMeta) != RDB_OK) { return RDB_ERROR; } -// auto storeMeta = GetStoreMetaData(param); -// StoreMetaData oldMeta; -// bool isCreated = MetaDataManager::GetInstance().LoadMeta(storeMeta.GetKey(), oldMeta); -// if (isCreated && (oldMeta.storeType != storeMeta.storeType || -// Constant::NotEqual(oldMeta.isEncrypt, storeMeta.isEncrypt) || -// oldMeta.area != storeMeta.area)) { -// ZLOGE("meta bundle:%{public}s store:%{public}s type:%{public}d->%{public}d encrypt:%{public}d->%{public}d " -// "area:%{public}d->%{public}d", -// storeMeta.bundleName.c_str(), storeMeta.storeId.c_str(), oldMeta.storeType, storeMeta.storeType, -// oldMeta.isEncrypt, storeMeta.isEncrypt, oldMeta.area, storeMeta.area); -// return RDB_ERROR; -// } -// if (!MetaDataManager::GetInstance().SaveMeta(storeMeta.GetKey(), storeMeta)) { -// return RDB_ERROR; -// } + + EventCenter::Defer defer; CloudEvent::StoreInfo storeInfo { IPCSkeleton::GetCallingTokenID(), param.bundleName_, RdbSyncer::RemoveSuffix(param.storeName_), RdbSyncer::GetInstIndex(IPCSkeleton::GetCallingTokenID(), param.bundleName_) }; @@ -526,6 +582,50 @@ StoreMetaData RdbServiceImpl::GetStoreMetaData(const RdbSyncerParam ¶m) return metaData; } +int32_t RdbServiceImpl::CreateMetaData(const RdbSyncerParam ¶m, StoreMetaData &old) +{ + auto meta = GetStoreMetaData(param); + bool isCreated = MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), old); + if (isCreated && (old.storeType != meta.storeType || Constant::NotEqual(old.isEncrypt, meta.isEncrypt) || + old.area != meta.area)) { + ZLOGE("meta bundle:%{public}s store:%{public}s type:%{public}d->%{public}d encrypt:%{public}d->%{public}d " + "area:%{public}d->%{public}d", + meta.bundleName.c_str(), meta.storeId.c_str(), old.storeType, meta.storeType, old.isEncrypt, + meta.isEncrypt, old.area, meta.area); + return RDB_ERROR; + } + + auto saved = MetaDataManager::GetInstance().SaveMeta(meta.GetKey(), meta); + if (!saved) { + return RDB_ERROR; + } + AppIDMetaData appIdMeta; + appIdMeta.bundleName = meta.bundleName; + appIdMeta.appId = meta.appId; + saved = MetaDataManager::GetInstance().SaveMeta(appIdMeta.GetKey(), appIdMeta, true); + if (!saved) { + return RDB_ERROR; + } + if (!param.isEncrypt_ || param.password_.empty()) { + return RDB_OK; + } + return SetSecretKey(param, meta); +} + +bool RdbServiceImpl::SetSecretKey(const RdbSyncerParam ¶m, const StoreMetaData &meta) +{ + SecretKeyMetaData newSecretKey; + newSecretKey.storeType = meta.storeType; + newSecretKey.sKey = CryptoManager::GetInstance().Encrypt(param.password_); + if (newSecretKey.sKey.empty()) { + ZLOGE("encrypt work key error."); + return RDB_ERROR; + } + auto time = system_clock::to_time_t(system_clock::now()); + newSecretKey.time = { reinterpret_cast(&time), reinterpret_cast(&time) + sizeof(time) }; + return MetaDataManager::GetInstance().SaveMeta(meta.GetSecretKey(), newSecretKey, true) ? RDB_OK : RDB_ERROR; +} + int32_t RdbServiceImpl::OnExecutor(std::shared_ptr executors) { executors_ = std::move(executors); diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.h b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.h index ca13cfba..c9f3eb54 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.h +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.h @@ -27,6 +27,7 @@ #include "rdb_notifier_proxy.h" #include "rdb_syncer.h" #include "store_observer.h" +#include "store/auto_cache.h" #include "visibility.h" namespace OHOS::DistributedRdb { class API_EXPORT RdbServiceImpl : public RdbServiceStub { @@ -49,8 +50,10 @@ public: void OnDataChange(pid_t pid, const DistributedDB::StoreChangedData& data); - int32_t CreateRDBTable( - const RdbSyncerParam ¶m, const std::string &writePermission, const std::string &readPermission) override; + void OnChange(uint32_t tokenId, const std::string &storeName); + + int32_t CreateRDBTable(const RdbSyncerParam ¶m) override; + int32_t DestroyRDBTable(const RdbSyncerParam ¶m) override; int32_t ResolveAutoLaunch(const std::string &identifier, DistributedDB::AutoLaunchParam ¶m) override; @@ -68,11 +71,22 @@ protected: int32_t DoAsync(const RdbSyncerParam& param, uint32_t seqNum, const SyncOption& option, const RdbPredicates& predicates) override; - int32_t DoSubscribe(const RdbSyncerParam& param) override; + int32_t DoSubscribe(const RdbSyncerParam& param, const SubscribeOption &option) override; int32_t DoUnSubscribe(const RdbSyncerParam& param) override; private: + using Watchers = DistributedData::AutoCache::Watchers; + struct SyncAgent { + pid_t pid_ = 0; + std::string bundleName_; + std::map mode_; + std::map watchers_; + void ReInit(pid_t pid, const std::string &bundleName); + }; + + Watchers GetWatchers(uint32_t tokenId, const std::string &storeName); + std::string GenIdentifier(const RdbSyncerParam& param); bool CheckAccess(const std::string& bundleName, const std::string& storeName); @@ -83,7 +97,9 @@ private: void OnAsyncComplete(pid_t pid, uint32_t seqNum, const SyncResult& result); - StoreMetaData GetStoreMetaData(const RdbSyncerParam& param); + int32_t CreateMetaData(const RdbSyncerParam ¶m, StoreMetaData &old); + StoreMetaData GetStoreMetaData(const RdbSyncerParam ¶m); + bool SetSecretKey(const RdbSyncerParam ¶m, const StoreMetaData &meta); class DeathRecipientImpl : public IRemoteObject::DeathRecipient { public: @@ -117,6 +133,7 @@ private: static constexpr int32_t MAX_SYNCER_PER_PROCESS = 10; static constexpr int32_t SYNCER_TIMEOUT = 60 * 1000; // ms std::shared_ptr executors_; + ConcurrentMap syncAgents_; }; } // namespace OHOS::DistributedRdb #endif diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.cpp index 39fd62d4..e879c523 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.cpp @@ -60,9 +60,9 @@ int32_t RdbServiceStub::OnRemoteInitNotifier(MessageParcel &data, MessageParcel { RdbSyncerParam param; sptr notifier; - if (!ITypesUtil::Unmarshal(data, param, notifier) || param.bundleName_.empty() || notifier == nullptr) { - ZLOGE("Unmarshal bundleName:%{public}s notifier is nullptr:%{public}d", param.bundleName_.c_str(), - notifier == nullptr); + if (!ITypesUtil::Unmarshal(data, param, notifier) || notifier == nullptr) { + ZLOGE("Unmarshal bundleName:%{public}s storeName_:%{public}s notifier is nullptr:%{public}d", + param.bundleName_.c_str(), param.storeName_.c_str(), notifier == nullptr); return IPC_STUB_INVALID_DATA_ERR; } auto status = InitNotifier(param, notifier); @@ -134,13 +134,14 @@ int32_t RdbServiceStub::OnRemoteDoAsync(MessageParcel &data, MessageParcel &repl int32_t RdbServiceStub::OnRemoteDoSubscribe(MessageParcel &data, MessageParcel &reply) { RdbSyncerParam param; - if (!ITypesUtil::Unmarshal(data, param)) { + SubscribeOption option; + if (!ITypesUtil::Unmarshal(data, param, option)) { ZLOGE("Unmarshal bundleName_:%{public}s storeName_:%{public}s", param.bundleName_.c_str(), param.storeName_.c_str()); return IPC_STUB_INVALID_DATA_ERR; } - auto status = DoSubscribe(param); + auto status = DoSubscribe(param, option); if (!ITypesUtil::Marshal(reply, status)) { ZLOGE("Marshal status:0x%{public}x", status); return IPC_STUB_WRITE_PARCEL_ERR; @@ -214,17 +215,13 @@ int RdbServiceStub::OnRemoteRequest(uint32_t code, MessageParcel& data, MessageP int32_t RdbServiceStub::OnRemoteDoCreateTable(MessageParcel &data, MessageParcel &reply) { RdbSyncerParam param; - std::string writePermission; - std::string readPermission; - if (!ITypesUtil::Unmarshal(data, param, writePermission, readPermission)) { - ZLOGE("Unmarshal bundleName_:%{public}s storeName_:%{public}s writePermission:%{public}s " - "readPermission:%{public}s", param.bundleName_.c_str(), param.storeName_.c_str(), - DistributedData::Anonymous::Change(writePermission).c_str(), - DistributedData::Anonymous::Change(readPermission).c_str()); + if (!ITypesUtil::Unmarshal(data, param)) { + ZLOGE("Unmarshal bundleName_:%{public}s storeName_:%{public}s", param.bundleName_.c_str(), + param.storeName_.c_str()); return IPC_STUB_INVALID_DATA_ERR; } - int32_t status = CreateRDBTable(param, writePermission, readPermission); + int32_t status = CreateRDBTable(param); if (!ITypesUtil::Marshal(reply, status)) { ZLOGE("Marshal status:0x%{public}x", status); return IPC_STUB_WRITE_PARCEL_ERR; diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_syncer.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_syncer.cpp index f8f6192a..1d1d1c35 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_syncer.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_syncer.cpp @@ -102,26 +102,19 @@ std::string RdbSyncer::GetStoreId() const return RemoveSuffix(param_.storeName_); } -int32_t RdbSyncer::Init( - pid_t pid, pid_t uid, uint32_t token, const std::string &writePermission, const std::string &readPermission) +int32_t RdbSyncer::Init(pid_t pid, pid_t uid, uint32_t token, const StoreMetaData &meta) { ZLOGI("enter"); pid_ = pid; uid_ = uid; token_ = token; - StoreMetaData oldMeta; - StoreMetaData meta; - if (CreateMetaData(meta, oldMeta) != RDB_OK) { - ZLOGE("create meta data failed"); - return RDB_ERROR; - } if (InitDBDelegate(meta) != RDB_OK) { ZLOGE("delegate is nullptr"); return RDB_ERROR; } - if (oldMeta.storeType == RDB_DEVICE_COLLABORATION && oldMeta.version < StoreMetaData::UUID_CHANGED_TAG) { + if (meta.storeType == RDB_DEVICE_COLLABORATION && meta.version < StoreMetaData::UUID_CHANGED_TAG) { delegate_->RemoveDeviceData(); } @@ -129,78 +122,6 @@ int32_t RdbSyncer::Init( return RDB_OK; } -int32_t RdbSyncer::DestroyMetaData(StoreMetaData &meta) -{ - FillMetaData(meta); - auto deleted = MetaDataManager::GetInstance().DelMeta(meta.GetKey(), true); - return deleted ? RDB_OK : RDB_ERROR; -} - -void RdbSyncer::FillMetaData(StoreMetaData &meta) -{ - meta.uid = uid_; - meta.tokenId = token_; - meta.instanceId = GetInstIndex(token_, param_.bundleName_); - meta.bundleName = param_.bundleName_; - meta.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; - meta.storeId = RemoveSuffix(param_.storeName_); - meta.user = std::to_string(AccountDelegate::GetInstance()->GetUserByToken(token_)); - meta.storeType = param_.type_; - meta.securityLevel = param_.level_; - meta.area = param_.area_; - meta.appId = CheckerManager::GetInstance().GetAppId(Converter::ConvertToStoreInfo(meta)); - meta.appType = "harmony"; - meta.hapName = param_.hapName_; - meta.dataDir = DirectoryManager::GetInstance().GetStorePath(meta) + "/" + param_.storeName_; - meta.account = AccountDelegate::GetInstance()->GetCurrentAccountId(); - meta.isEncrypt = param_.isEncrypt_; -} - -int32_t RdbSyncer::CreateMetaData(StoreMetaData &meta, StoreMetaData &old) -{ - FillMetaData(meta); - bool isCreated = MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), old); - if (isCreated && (old.storeType != meta.storeType || Constant::NotEqual(old.isEncrypt, meta.isEncrypt) || - old.area != meta.area)) { - ZLOGE("meta bundle:%{public}s store:%{public}s type:%{public}d->%{public}d encrypt:%{public}d->%{public}d " - "area:%{public}d->%{public}d", - meta.bundleName.c_str(), meta.storeId.c_str(), old.storeType, meta.storeType, old.isEncrypt, - meta.isEncrypt, old.area, meta.area); - return RDB_ERROR; - } - - auto saved = MetaDataManager::GetInstance().SaveMeta(meta.GetKey(), meta); - if (!saved) { - return RDB_ERROR; - } - AppIDMetaData appIdMeta; - appIdMeta.bundleName = meta.bundleName; - appIdMeta.appId = meta.appId; - saved = MetaDataManager::GetInstance().SaveMeta(appIdMeta.GetKey(), appIdMeta, true); - if (!saved) { - return RDB_ERROR; - } - if (!param_.isEncrypt_ || param_.password_.empty()) { - return RDB_OK; - } - return SetSecretKey(meta); -} - -bool RdbSyncer::SetSecretKey(const StoreMetaData &meta) -{ - SecretKeyMetaData newSecretKey; - newSecretKey.storeType = meta.storeType; - newSecretKey.sKey = CryptoManager::GetInstance().Encrypt(param_.password_); - if (newSecretKey.sKey.empty()) { - ZLOGE("encrypt work key error."); - return RDB_ERROR; - } - param_.password_.assign(param_.password_.size(), 0); - auto time = system_clock::to_time_t(system_clock::now()); - newSecretKey.time = { reinterpret_cast(&time), reinterpret_cast(&time) + sizeof(time) }; - return MetaDataManager::GetInstance().SaveMeta(meta.GetSecretKey(), newSecretKey, true) ? RDB_OK : RDB_ERROR; -} - bool RdbSyncer::GetPassword(const StoreMetaData &metaData, DistributedDB::CipherPassword &password) { if (!metaData.isEncrypt) { diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_syncer.h b/datamgr_service/services/distributeddataservice/service/rdb/rdb_syncer.h index b103c7ad..68d1e44f 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_syncer.h +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_syncer.h @@ -34,8 +34,7 @@ public: RdbSyncer(const RdbSyncerParam& param, RdbStoreObserverImpl* observer); ~RdbSyncer() noexcept; - int32_t Init(pid_t pid, pid_t uid, uint32_t token, const std::string &writePermission = "", - const std::string &readPermission = ""); + int32_t Init(pid_t pid, pid_t uid, uint32_t token, const StoreMetaData &meta); pid_t GetPid() const; @@ -56,8 +55,6 @@ public: int32_t RemoteQuery(const std::string& device, const std::string& sql, const std::vector& selectionArgs, sptr& resultSet); - int32_t DestroyMetaData(StoreMetaData &meta); - static std::string RemoveSuffix(const std::string& name); static int32_t GetInstIndex(uint32_t tokenId, const std::string &bundleName); @@ -73,10 +70,7 @@ private: std::string GetAppId() const; - int32_t CreateMetaData(StoreMetaData &meta, StoreMetaData &old); - void FillMetaData(StoreMetaData &meta); int32_t InitDBDelegate(const StoreMetaData &meta); - bool SetSecretKey(const StoreMetaData &meta); DistributedDB::RelationalStoreDelegate* GetDelegate(); @@ -95,7 +89,6 @@ private: static void HandleSyncStatus(const std::map>& SyncStatus, SyncResult& result); - static void EqualTo(const RdbPredicateOperation& operation, DistributedDB::Query& query); static void NotEqualTo(const RdbPredicateOperation& operation, DistributedDB::Query& query); static void And(const RdbPredicateOperation& operation, DistributedDB::Query& query); diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_watcher.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_watcher.cpp new file mode 100644 index 00000000..01572668 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_watcher.cpp @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2023 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 "RdbWatcher" + +#include "rdb_watcher.h" +#include "log_print.h" +#include "error/general_error.h" + +namespace OHOS::DistributedRdb { +using namespace DistributedData; +using Err = DistributedData::GeneralError; +RdbWatcher::RdbWatcher(RdbServiceImpl *rdbService, uint32_t tokenId, const std::string &storeName) + : rdbService_(rdbService), tokenId_(tokenId), storeName_(storeName) +{ +} + +int32_t RdbWatcher::OnChange(Origin origin, const std::string &id) +{ + if (rdbService_ == nullptr) { + return Err::E_ERROR; + } + rdbService_->OnChange(tokenId_, storeName_); + return Err::E_OK; +} + +int32_t RdbWatcher::OnChange(Origin origin, const std::string &id, const std::vector &values) +{ + return Err::E_NOT_SUPPORT; +} +} // namespace OHOS::DistributedRdb diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_watcher.h b/datamgr_service/services/distributeddataservice/service/rdb/rdb_watcher.h new file mode 100644 index 00000000..65af0216 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_watcher.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2023 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_DATAMGR_SERVICE_RDB_GENERAL_WATCHER_H +#define OHOS_DISTRIBUTED_DATA_DATAMGR_SERVICE_RDB_GENERAL_WATCHER_H +#include "rdb_service_impl.h" +#include "store/general_value.h" +#include "store/general_watcher.h" + +namespace OHOS::DistributedRdb { +class RdbServiceImpl; +class RdbWatcher : public DistributedData::GeneralWatcher { +public: + explicit RdbWatcher(RdbServiceImpl *rdbService, uint32_t tokenId, const std::string &storeName); + int32_t OnChange(Origin origin, const std::string &id) override; + int32_t OnChange(Origin origin, const std::string &id, + const std::vector &values) override; + +private: + RdbServiceImpl* rdbService_ {}; + uint32_t tokenId_ = 0; + std::string storeName_ {}; +}; +} // namespace OHOS::DistributedRdb +#endif // OHOS_DISTRIBUTED_DATA_DATAMGR_SERVICE_RDB_GENERAL_WATCHER_H diff --git a/datamgr_service/services/distributeddataservice/service/test/BUILD.gn b/datamgr_service/services/distributeddataservice/service/test/BUILD.gn index 5a7ff143..97d837b7 100644 --- a/datamgr_service/services/distributeddataservice/service/test/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/test/BUILD.gn @@ -43,7 +43,7 @@ ohos_unittest("CloudDataTest") { "mock/db_change_data_mock.cpp", "mock/db_store_mock.cpp", ] - + include_dirs = [ "../../../../../relational_store/interfaces/inner_api/rdb/include" ] diff --git a/datamgr_service/services/distributeddataservice/service/test/cloud_data_test.cpp b/datamgr_service/services/distributeddataservice/service/test/cloud_data_test.cpp index 031ea345..ddee440e 100644 --- a/datamgr_service/services/distributeddataservice/service/test/cloud_data_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/cloud_data_test.cpp @@ -44,11 +44,13 @@ public: void SetUp(); void TearDown(); + static SchemaMeta schemaMeta_; protected: static constexpr const char *TEST_DISTRIBUTEDDATA_BUNDLE = "test_distributeddata"; static constexpr const char *TEST_DISTRIBUTEDDATA_STORE = "test_service_meta"; void InitMetaData(); + void InitSchemaMeta(); static std::shared_ptr dbStoreMock_; StoreMetaData metaData_; }; @@ -83,29 +85,7 @@ CloudInfo CloudServerMock::GetServerInfo(int32_t userId) SchemaMeta CloudServerMock::GetAppSchema(int32_t userId, const std::string &bundleName) { - SchemaMeta::Field field1; - field1.colName = "test_cloud_field_name1"; - field1.alias = "test_cloud_field_alias1"; - SchemaMeta::Field field2; - field2.colName = "test_cloud_field_name2"; - field2.alias = "test_cloud_field_alias2"; - - SchemaMeta::Table table; - table.name = "test_cloud_table_name"; - table.alias = "test_cloud_table_alias"; - table.fields.emplace_back(field1); - table.fields.emplace_back(field2); - - SchemaMeta::Database database; - database.name = TEST_CLOUD_STORE; - database.alias = "test_cloud_database_alias"; - database.tables.emplace_back(table); - - SchemaMeta schemaMeta; - schemaMeta.version = 1; - schemaMeta.databases.emplace_back(database); - - return schemaMeta; + return CloudDataTest::schemaMeta_; } std::shared_ptr CloudDataTest::dbStoreMock_ = std::make_shared(); @@ -126,6 +106,30 @@ void CloudDataTest::InitMetaData() value.type = OHOS::DistributedKv::PolicyType::IMMEDIATE_SYNC_ON_ONLINE; } +void CloudDataTest::InitSchemaMeta() +{ + SchemaMeta::Field field1; + field1.colName = "test_cloud_field_name1"; + field1.alias = "test_cloud_field_alias1"; + SchemaMeta::Field field2; + field2.colName = "test_cloud_field_name2"; + field2.alias = "test_cloud_field_alias2"; + + SchemaMeta::Table table; + table.name = "test_cloud_table_name"; + table.alias = "test_cloud_table_alias"; + table.fields.emplace_back(field1); + table.fields.emplace_back(field2); + + SchemaMeta::Database database; + database.name = TEST_CLOUD_STORE; + database.alias = "test_cloud_database_alias"; + database.tables.emplace_back(table); + + schemaMeta_.version = 1; + schemaMeta_.databases.emplace_back(database); +} + void CloudDataTest::SetUpTestCase(void) { MetaDataManager::GetInstance().Initialize(dbStoreMock_, nullptr, [](const auto &, auto) { @@ -157,6 +161,7 @@ void CloudDataTest::SetUp() storeMetaData.user = std::to_string(DistributedKv::AccountDelegate::GetInstance()->GetUserByToken(storeMetaData.tokenId)); MetaDataManager::GetInstance().SaveMeta(storeMetaData.GetKey(), storeMetaData); + InitSchemaMeta(); } void CloudDataTest::TearDown() {} @@ -175,14 +180,15 @@ HWTEST_F(CloudDataTest, GetSchema, TestSize.Level0) auto cloudInfo = cloudServerMock->GetServerInfo( DistributedKv::AccountDelegate::GetInstance()->GetUserByToken(OHOS::IPCSkeleton::GetCallingTokenID())); ASSERT_TRUE(MetaDataManager::GetInstance().DelMeta(cloudInfo.GetSchemaKey(TEST_CLOUD_BUNDLE), true)); - StoreMetaData storeMetaData; + SchemaMeta schemaMeta; ASSERT_FALSE( - MetaDataManager::GetInstance().LoadMeta(cloudInfo.GetSchemaKey(TEST_CLOUD_BUNDLE), storeMetaData, true)); + MetaDataManager::GetInstance().LoadMeta(cloudInfo.GetSchemaKey(TEST_CLOUD_BUNDLE), schemaMeta, true)); CloudEvent::StoreInfo storeInfo { OHOS::IPCSkeleton::GetCallingTokenID(), TEST_CLOUD_BUNDLE, TEST_CLOUD_STORE, 0 }; auto event = std::make_unique(CloudEvent::GET_SCHEMA, std::move(storeInfo), "test_service"); EventCenter::GetInstance().PostEvent(move(event)); ASSERT_TRUE( - MetaDataManager::GetInstance().LoadMeta(cloudInfo.GetSchemaKey(TEST_CLOUD_BUNDLE), storeMetaData, true)); + MetaDataManager::GetInstance().LoadMeta(cloudInfo.GetSchemaKey(TEST_CLOUD_BUNDLE), schemaMeta, true)); + ASSERT_EQ(to_string(schemaMeta.Marshall()), to_string(schemaMeta_.Marshall())); } } // namespace DistributedDataTest } // namespace OHOS diff --git a/relational_store/frameworks/js/napi/cloud_data/BUILD.gn b/relational_store/frameworks/js/napi/cloud_data/BUILD.gn index 2d309564..ca870334 100644 --- a/relational_store/frameworks/js/napi/cloud_data/BUILD.gn +++ b/relational_store/frameworks/js/napi/cloud_data/BUILD.gn @@ -21,43 +21,40 @@ ohos_copy("relational_store_declaration") { module_install_name = "" } -config("cloud_data_config") { - visibility = [ ":*" ] +ohos_shared_library("clouddata") { + sources = [ + "${cloud_data_napi_path}/src/entry_point.cpp", + "${cloud_data_napi_path}/src/js_config.cpp", + "${cloud_data_napi_path}/src/js_const_properties.cpp", + "${cloud_data_napi_path}/src/js_error_utils.cpp", + "${cloud_data_napi_path}/src/napi_queue.cpp", + "${cloud_data_native_path}/src/cloud_manager.cpp", + "${cloud_data_native_path}/src/cloud_service_proxy.cpp", + "${relational_store_napi_path}/common/src/js_utils.cpp", + ] include_dirs = [ + "include", + "${relational_store_js_common_path}/include", "${cloud_data_native_path}/include", "${kvstore_path}/common", "${relational_store_innerapi_path}/rdb/include", "${relational_store_innerapi_path}/cloud_data/include", - "include", - ] - - defines = [ - "RELATIONAL_STORE", - "SQLITE_HAS_CODEC", + "${relational_store_napi_path}/cloud_data/include", + "${relational_store_napi_path}/common/include", ] -} - -ohos_shared_library("cloud_data") { - configs = [ ":cloud_data_config" ] - - deps = [] - ldflags = [ "-Wl,--exclude-libs,ALL" ] - cflags_cc = [ "-fvisibility=hidden" ] - - sources = [ - "${cloud_data_native_path}/src/cloud_manager.cpp", - "${cloud_data_native_path}/src/cloud_service_proxy.cpp", - ] - - public_deps = - [ "${relational_store_innerapi_path}/appdatafwk:native_appdatafwk" ] external_deps = [ + "ability_runtime:abilitykit_native", + "ability_runtime:napi_base_context", "c_utils:utils", "hilog_native:libhilog", "hitrace_native:hitrace_meter", + "hiviewdfx_hilog_native:libhilog", "ipc:ipc_core", + "napi:ace_napi", + "relational_store:native_appdatafwk", + "relational_store:native_rdb", "samgr:samgr_proxy", ] diff --git a/relational_store/frameworks/js/napi/cloud_data/include/js_config.h b/relational_store/frameworks/js/napi/cloud_data/include/js_config.h new file mode 100644 index 00000000..ff3b4ea7 --- /dev/null +++ b/relational_store/frameworks/js/napi/cloud_data/include/js_config.h @@ -0,0 +1,50 @@ +/* +* Copyright (c) 2023 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 LDBPROJ_JS_CONFIG_H +#define LDBPROJ_JS_CONFIG_H +#include "cloud_manager.h" +#include "js_const_properties.h" +#include "log_print.h" + +namespace OHOS::CloudData { +class JsConfig { +public: + JsConfig(); + ~JsConfig(); + static napi_value InitConfig(napi_env env, napi_value exports); + static napi_value New(napi_env env, napi_callback_info info); + + enum { + /* exported js Action is (CloudData::Action-1) */ + CLEAR_CLOUD_INFO = 0, + CLEAR_CLOUD_DATA_AND_INFO = 1, + }; + + static inline bool ValidSubscribeType(int32_t type) + { + return (CLEAR_CLOUD_INFO <= type) && (type <= CLEAR_CLOUD_DATA_AND_INFO); + } + + static napi_value EnableCloud(napi_env env, napi_callback_info info); + static napi_value DisableCloud(napi_env env, napi_callback_info info); + static napi_value ChangeAppCloudSwitch(napi_env env, napi_callback_info info); + static napi_value Clean(napi_env env, napi_callback_info info); + static napi_value NotifyDataChange(napi_env env, napi_callback_info info); +}; + +} // namespace OHOS::CloudData + +#endif //LDBPROJ_JS_CONFIG_H diff --git a/relational_store/frameworks/js/napi/cloud_data/include/js_const_properties.h b/relational_store/frameworks/js/napi/cloud_data/include/js_const_properties.h new file mode 100644 index 00000000..6245a158 --- /dev/null +++ b/relational_store/frameworks/js/napi/cloud_data/include/js_const_properties.h @@ -0,0 +1,25 @@ +/* +* Copyright (c) 2023 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 LDBPROJ_JS_CONST_PROPERTIES_H +#define LDBPROJ_JS_CONST_PROPERTIES_H +#include "napi/native_api.h" +#include "napi/native_common.h" +#include "napi/native_node_api.h" + +namespace OHOS::CloudData { +napi_status InitConstProperties(napi_env env, napi_value exports); +} // namespace OHOS::CloudData +#endif //LDBPROJ_JS_CONST_PROPERTIES_H diff --git a/relational_store/frameworks/js/napi/cloud_data/include/js_error_utils.h b/relational_store/frameworks/js/napi/cloud_data/include/js_error_utils.h new file mode 100644 index 00000000..c6567dfc --- /dev/null +++ b/relational_store/frameworks/js/napi/cloud_data/include/js_error_utils.h @@ -0,0 +1,69 @@ +/* +* Copyright (c) 2023 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 LDBPROJ_JS_ERROR_UTILS_H +#define LDBPROJ_JS_ERROR_UTILS_H +#include +#include + +#include "cloud_service.h" +#include "js_native_api.h" +#include "log_print.h" +#include "napi/native_common.h" + +namespace OHOS { +namespace CloudData { +using Status = OHOS::CloudData::CloudService::Status; + +struct JsErrorCode { + int32_t status; + int32_t jsCode; + const char *message; +}; + +const std::optional GetJsErrorCode(int32_t errorCode); +Status GenerateNapiError(int32_t status, int32_t &errCode, std::string &errMessage); +void ThrowNapiError(napi_env env, int32_t errCode, std::string errMessage, bool isParamsCheck = true); +napi_value GenerateErrorMsg(napi_env env, JsErrorCode jsInfo); + +#define ASSERT_ERR(env, assertion, errorCode, message) \ + do { \ + if (!(assertion)) { \ + ThrowNapiError(env, errorCode, message); \ + return nullptr; \ + } \ + } while (0) + +#define ASSERT_BUSINESS_ERR(ctxt, assertion, errorCode, message) \ + do { \ + if (!(assertion)) { \ + (ctxt)->isThrowError = true; \ + ThrowNapiError((ctxt)->env, errorCode, message); \ + return; \ + } \ + } while (0) + +#define ASSERT_PERMISSION_ERR(ctxt, assertion, errorCode, message) \ + do { \ + if (!(assertion)) { \ + (ctxt)->isThrowError = true; \ + ThrowNapiError((ctxt)->env, errorCode, message, false); \ + return; \ + } \ + } while (0) + +} // namespace CloudData +} // namespace OHOS +#endif //LDBPROJ_JS_ERROR_UTILS_H diff --git a/relational_store/frameworks/js/napi/cloud_data/include/napi_queue.h b/relational_store/frameworks/js/napi/cloud_data/include/napi_queue.h new file mode 100644 index 00000000..e21cbc83 --- /dev/null +++ b/relational_store/frameworks/js/napi/cloud_data/include/napi_queue.h @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2023 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 LDBPROJ_NAPI_QUEUE_H +#define LDBPROJ_NAPI_QUEUE_H +#include +#include +#include + +#include "log_print.h" +#include "napi/native_api.h" +#include "napi/native_common.h" +#include "napi/native_node_api.h" + +namespace OHOS::CloudData { +constexpr size_t ARGC_MAX = 6; +using NapiCbInfoParser = std::function; +using NapiAsyncExecute = std::function; +using NapiAsyncComplete = std::function; + +struct ContextBase { + virtual ~ContextBase(); + void GetCbInfo( + napi_env env, napi_callback_info info, NapiCbInfoParser parse = NapiCbInfoParser(), bool sync = false); + + inline void GetCbInfoSync(napi_env env, napi_callback_info info, NapiCbInfoParser parse = NapiCbInfoParser()) + { + /* sync = true, means no callback, not AsyncWork. */ + GetCbInfo(env, info, parse, true); + } + + napi_env env = nullptr; + napi_value output = nullptr; + napi_status status = napi_invalid_arg; + std::string error; + int32_t jsCode = 0; + bool isThrowError = false; + + napi_value self = nullptr; + void *native = nullptr; + +private: + napi_ref callbackRef = nullptr; + napi_ref selfRef = nullptr; + friend class NapiQueue; +}; + +/* check condition related to argc/argv, return and logging. */ +#define ASSERT_ARGS(ctxt, condition, message) \ + do { \ + if (!(condition)) { \ + (ctxt)->status = napi_invalid_arg; \ + (ctxt)->error = std::string(message); \ + ZLOGE("test (" #condition ") failed: " message); \ + return; \ + } \ + } while (0) + +#define ASSERT_STATUS(ctxt, message) \ + do { \ + if ((ctxt)->status != napi_ok) { \ + (ctxt)->error = std::string(message); \ + ZLOGE("test (ctxt->status == napi_ok) failed: " message); \ + return; \ + } \ + } while (0) + +/* check condition, return and logging if condition not true. */ +#define ASSERT(condition, message, retVal) \ + do { \ + if (!(condition)) { \ + ZLOGE("test (" #condition ") failed: " message); \ + return retVal; \ + } \ + } while (0) + +#define ASSERT_VOID(condition, message) \ + do { \ + if (!(condition)) { \ + ZLOGE("test (" #condition ") failed: " message); \ + return; \ + } \ + } while (0) + +#define ASSERT_NULL(condition, message) ASSERT(condition, message, nullptr) + +#define ASSERT_CALL(env, theCall, object) \ + do { \ + if ((theCall) != napi_ok) { \ + delete (object); \ + GET_AND_THROW_LAST_ERROR((env)); \ + return nullptr; \ + } \ + } while (0) + +class NapiQueue { +public: + static napi_value AsyncWork(napi_env env, std::shared_ptr ctxt, const std::string &name, + NapiAsyncExecute execute = NapiAsyncExecute(), NapiAsyncComplete complete = NapiAsyncComplete()); + +private: + enum { + /* AsyncCallback / Promise output result index */ + RESULT_ERROR = 0, + RESULT_DATA = 1, + RESULT_ALL = 2 + }; + + struct AsyncContext { + napi_env env = nullptr; + std::shared_ptr ctx; + NapiAsyncExecute execute = nullptr; + NapiAsyncComplete complete = nullptr; + napi_deferred deferred = nullptr; + napi_async_work work = nullptr; + ~AsyncContext() + { + execute = nullptr; + complete = nullptr; + ctx = nullptr; + if (env != nullptr) { + if (work != nullptr) { + napi_delete_async_work(env, work); + } + } + } + }; + static void GenerateOutput(AsyncContext &ctx, napi_value output); +}; +} // namespace OHOS::CloudData +#endif //LDBPROJ_NAPI_QUEUE_H diff --git a/relational_store/frameworks/js/napi/cloud_data/src/entry_point.cpp b/relational_store/frameworks/js/napi/cloud_data/src/entry_point.cpp new file mode 100644 index 00000000..a6f5e84a --- /dev/null +++ b/relational_store/frameworks/js/napi/cloud_data/src/entry_point.cpp @@ -0,0 +1,41 @@ +/* +* Copyright (c) 2023 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 "EntryPoint" +#include "js_config.h" +#include "js_const_properties.h" +#include "log_print.h" + +using namespace OHOS::CloudData; + +static napi_value Init(napi_env env, napi_value exports) +{ + exports = JsConfig::InitConfig(env, exports); + napi_status status = InitConstProperties(env, exports); + ZLOGI("init Enumerate Constants %{public}d", status); + return exports; +} + +static __attribute__((constructor)) void RegisterModule() +{ + static napi_module module = { .nm_version = 1, + .nm_flags = 0, + .nm_filename = nullptr, + .nm_register_func = Init, + .nm_modname = "data.cloudData", + .nm_priv = ((void *)0), + .reserved = { 0 } }; + napi_module_register(&module); + ZLOGI("module register data.cloudData"); +} diff --git a/relational_store/frameworks/js/napi/cloud_data/src/js_config.cpp b/relational_store/frameworks/js/napi/cloud_data/src/js_config.cpp new file mode 100644 index 00000000..cb0dbd99 --- /dev/null +++ b/relational_store/frameworks/js/napi/cloud_data/src/js_config.cpp @@ -0,0 +1,331 @@ +/* +* Copyright (c) 2023 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 "JsConfig" +#include "js_config.h" + +#include + +#include "cloud_manager.h" +#include "cloud_service.h" +#include "js_error_utils.h" +#include "js_utils.h" +#include "log_print.h" +#include "napi_queue.h" +#include + +using namespace OHOS::CloudData; +using namespace OHOS::AppDataMgrJsKit; +JsConfig::JsConfig() +{ +} + +JsConfig::~JsConfig() +{ +} + +/* + * [JS API Prototype] + * [AsyncCallback] + * enableCloud(accountId: string, switches: {[bundleName: string]: boolean}, callback: AsyncCallback): void; + * [Promise] + * enableCloud(accountId: string, switches: {[bundleName: string]: boolean}): Promise; + */ +napi_value JsConfig::EnableCloud(napi_env env, napi_callback_info info) +{ + struct EnableCloudContext : public ContextBase { + std::string accountId; + std::map tempSwitches; + std::map switches; + }; + auto ctxt = std::make_shared(); + ctxt->GetCbInfo(env, info, [env, ctxt](size_t argc, napi_value *argv) { + // required 2 arguments :: + ASSERT_BUSINESS_ERR(ctxt, argc >= 2, Status::INVALID_ARGUMENT, "The number of parameters is incorrect."); + // 0 is the index of argument accountId, 1 is the index of argument switches + int status = JSUtils::Convert2Value(env, argv[0], ctxt->accountId); + ASSERT_BUSINESS_ERR( + ctxt, status == JSUtils::OK, Status::INVALID_ARGUMENT, "The type of accountId must be string."); + status = JSUtils::Convert2Value(env, argv[1], ctxt->tempSwitches); + ASSERT_BUSINESS_ERR(ctxt, status == JSUtils::OK, Status::INVALID_ARGUMENT, + "The type of switches must be {[bundleName: string]: boolean}."); + for (auto item : ctxt->tempSwitches) { + ctxt->switches.insert(std::pair(item.first, static_cast(item.second))); + } + }); + + ASSERT_NULL(!ctxt->isThrowError, "EnableCloud exit"); + + auto execute = [ctxt]() { + auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); + if (proxy == nullptr) { + if (state != CloudService::SERVER_UNAVAILABLE) { + state = CloudService::NOT_SUPPORT; + } + ctxt->status = (GenerateNapiError(state, ctxt->jsCode, ctxt->error) == Status::SUCCESS) + ? napi_ok + : napi_generic_failure; + return; + } + int32_t cStatus = proxy->EnableCloud(ctxt->accountId, ctxt->switches); + ZLOGD("EnableCloud return %{public}d", cStatus); + ctxt->status = (GenerateNapiError(cStatus, ctxt->jsCode, ctxt->error) == Status::SUCCESS) + ? napi_ok + : napi_generic_failure; + }; + return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute); +} + +/* + * [JS API Prototype] + * [AsyncCallback] + * disableCloud(accountId: string, callback: AsyncCallback): void; + * [Promise] + * disableCloud(accountId: string): Promise; + */ +napi_value JsConfig::DisableCloud(napi_env env, napi_callback_info info) +{ + struct DisableCloudContext : public ContextBase { + std::string accountId; + }; + auto ctxt = std::make_shared(); + ctxt->GetCbInfo(env, info, [env, ctxt](size_t argc, napi_value *argv) { + // required 1 arguments :: + ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::INVALID_ARGUMENT, "The number of parameters is incorrect."); + // 0 is the index of argument accountId + int status = JSUtils::Convert2Value(env, argv[0], ctxt->accountId); + ASSERT_BUSINESS_ERR( + ctxt, status == JSUtils::OK, Status::INVALID_ARGUMENT, "The type of accountId must be string."); + }); + + ASSERT_NULL(!ctxt->isThrowError, "DisableCloud exit"); + + auto execute = [ctxt]() { + auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); + if (proxy == nullptr) { + if (state != CloudService::SERVER_UNAVAILABLE) { + state = CloudService::NOT_SUPPORT; + } + ctxt->status = (GenerateNapiError(state, ctxt->jsCode, ctxt->error) == Status::SUCCESS) + ? napi_ok + : napi_generic_failure; + return; + } + int32_t cStatus = proxy->DisableCloud(ctxt->accountId); + ZLOGD("DisableCloud return %{public}d", cStatus); + ctxt->status = (GenerateNapiError(cStatus, ctxt->jsCode, ctxt->error) == Status::SUCCESS) + ? napi_ok + : napi_generic_failure; + }; + return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute); +} + +/* + * [JS API Prototype] + * [AsyncCallback] + * changeAppCloudSwitch(accountId: string, bundleName: string, status :boolean, + * callback: AsyncCallback): void; + * [Promise] + * changeAppCloudSwitch(accountId: string, bundleName: string, status :boolean): Promise; + */ + +napi_value JsConfig::ChangeAppCloudSwitch(napi_env env, napi_callback_info info) +{ + struct ChangeAppSwitchContext : public ContextBase { + std::string accountId; + std::string bundleName; + bool state; + }; + auto ctxt = std::make_shared(); + ctxt->GetCbInfo(env, info, [env, ctxt](size_t argc, napi_value *argv) { + // required 3 arguments :: + ASSERT_BUSINESS_ERR(ctxt, argc >= 3, Status::INVALID_ARGUMENT, "The number of parameters is incorrect."); + // 0 is the index of argument accountId, 1 is the index of argument bundleName, 2 is the index of argument state + int status = JSUtils::Convert2Value(env, argv[0], ctxt->accountId); + ASSERT_BUSINESS_ERR( + ctxt, status == JSUtils::OK, Status::INVALID_ARGUMENT, "The type of accountId must be string."); + status = JSUtils::Convert2Value(env, argv[1], ctxt->bundleName); + ASSERT_BUSINESS_ERR( + ctxt, status == JSUtils::OK, Status::INVALID_ARGUMENT, "The type of bundleName must be string."); + status = JSUtils::Convert2Value(env, argv[2], ctxt->state); + ASSERT_BUSINESS_ERR( + ctxt, status == JSUtils::OK, Status::INVALID_ARGUMENT, "The type of status must be boolean."); + }); + + ASSERT_NULL(!ctxt->isThrowError, "ChangeAppCloudSwitch exit"); + + auto execute = [ctxt]() { + auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); + if (proxy == nullptr) { + if (state != CloudService::SERVER_UNAVAILABLE) { + state = CloudService::NOT_SUPPORT; + } + ctxt->status = (GenerateNapiError(state, ctxt->jsCode, ctxt->error) == Status::SUCCESS) + ? napi_ok + : napi_generic_failure; + return; + } + int32_t cStatus = proxy->ChangeAppSwitch(ctxt->accountId, ctxt->bundleName, ctxt->state); + ZLOGD("ChangeAppCloudSwitch return %{public}d", cStatus); + ctxt->status = (GenerateNapiError(cStatus, ctxt->jsCode, ctxt->error) == Status::SUCCESS) + ? napi_ok + : napi_generic_failure; + }; + return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute); +} + +/* + * [JS API Prototype] + * [AsyncCallback] + * clean(accountId: string, appActions: {[bundleName: string]: Action}, callback: AsyncCallback): void; + * [Promise] + * clean(accountId: string, appActions: {[bundleName: string]: Action}): Promise; + */ +napi_value JsConfig::Clean(napi_env env, napi_callback_info info) +{ + struct CleanContext : public ContextBase { + std::string accountId; + std::map appActions; + }; + auto ctxt = std::make_shared(); + ctxt->GetCbInfo(env, info, [env, ctxt](size_t argc, napi_value *argv) { + // required 2 arguments :: + ASSERT_BUSINESS_ERR(ctxt, argc >= 2, Status::INVALID_ARGUMENT, "The number of parameters is incorrect."); + // 0 is the index of argument accountId, 1 is the index of argument + int status = JSUtils::Convert2Value(env, argv[0], ctxt->accountId); + ASSERT_BUSINESS_ERR( + ctxt, status == JSUtils::OK, Status::INVALID_ARGUMENT, "The type of accountId must be string."); + status = JSUtils::Convert2Value(env, argv[1], ctxt->appActions); + ASSERT_BUSINESS_ERR(ctxt, status == JSUtils::OK, Status::INVALID_ARGUMENT, + "The type of actions must be {[bundleName: string]: int32_t}."); + for (auto item : ctxt->appActions) { + ASSERT_BUSINESS_ERR(ctxt, ValidSubscribeType(item.second), Status::INVALID_ARGUMENT, + "Action in map appActions is incorrect."); + } + }); + + ASSERT_NULL(!ctxt->isThrowError, "Clean exit"); + + auto execute = [ctxt]() { + auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); + if (proxy == nullptr) { + if (state != CloudService::SERVER_UNAVAILABLE) { + state = CloudService::NOT_SUPPORT; + } + ctxt->status = (GenerateNapiError(state, ctxt->jsCode, ctxt->error) == Status::SUCCESS) + ? napi_ok + : napi_generic_failure; + return; + } + int32_t cStatus = proxy->Clean(ctxt->accountId, ctxt->appActions); + ZLOGD("Clean return %{public}d", cStatus); + ctxt->status = (GenerateNapiError(cStatus, ctxt->jsCode, ctxt->error) == Status::SUCCESS) + ? napi_ok + : napi_generic_failure; + }; + return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute); +} + +/* + * [JS API Prototype] + * [AsyncCallback] + * notifyDataChange(accountId: string, bundleName: string, callback: AsyncCallback): void; + * [Promise] + * notifyDataChange(accountId: string, bundleName: string): Promise; + */ +napi_value JsConfig::NotifyDataChange(napi_env env, napi_callback_info info) +{ + struct ChangeAppSwitchContext : public ContextBase { + std::string accountId; + std::string bundleName; + }; + auto ctxt = std::make_shared(); + ctxt->GetCbInfo(env, info, [env, ctxt](size_t argc, napi_value *argv) { + // required 2 arguments :: + ASSERT_BUSINESS_ERR(ctxt, argc >= 2, Status::INVALID_ARGUMENT, "The number of parameters is incorrect."); + // 0 is the index of argument accountId, 1 is the index of argument bundleName + int status = JSUtils::Convert2Value(env, argv[0], ctxt->accountId); + ASSERT_BUSINESS_ERR( + ctxt, status == JSUtils::OK, Status::INVALID_ARGUMENT, "The type of accountId must be string."); + status = JSUtils::Convert2Value(env, argv[1], ctxt->bundleName); + ASSERT_BUSINESS_ERR( + ctxt, status == JSUtils::OK, Status::INVALID_ARGUMENT, "The type of bundleName must be string."); + }); + + ASSERT_NULL(!ctxt->isThrowError, "NotifyDataChange exit"); + + auto execute = [ctxt]() { + auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); + if (proxy == nullptr) { + if (state != CloudService::SERVER_UNAVAILABLE) { + state = CloudService::NOT_SUPPORT; + } + ctxt->status = (GenerateNapiError(state, ctxt->jsCode, ctxt->error) == Status::SUCCESS) + ? napi_ok + : napi_generic_failure; + return; + } + int32_t cStatus = proxy->NotifyDataChange(ctxt->accountId, ctxt->bundleName); + ZLOGD("NotifyDataChange return %{public}d", cStatus); + ctxt->status = (GenerateNapiError(cStatus, ctxt->jsCode, ctxt->error) == Status::SUCCESS) + ? napi_ok + : napi_generic_failure; + }; + return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute); +} + +napi_value JsConfig::New(napi_env env, napi_callback_info info) +{ + napi_value self = nullptr; + size_t argc = ARGC_MAX; + napi_value argv[ARGC_MAX] = { 0 }; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &self, nullptr)); + if (self == nullptr) { + napi_new_instance(env, JSUtils::GetClass(env, "ohos.cloudData", "Config"), argc, argv, &self); + return self; + } + + auto finalize = [](napi_env env, void *data, void *hint) { + ZLOGD("cloudConfig finalize."); + auto *config = reinterpret_cast(data); + ASSERT_VOID(config != nullptr, "finalize null!"); + delete config; + }; + JsConfig *cloudConfig = new (std::nothrow) JsConfig(); + ASSERT_ERR(env, cloudConfig != nullptr, Status::INVALID_ARGUMENT, "no memory for cloudConfig."); + napi_status status = napi_wrap(env, self, cloudConfig, finalize, nullptr, nullptr); + if (status != napi_ok) { + ZLOGE("JsConfig::Initialize napi_wrap failed! code:%{public}d!", status); + finalize(env, cloudConfig, nullptr); + return nullptr; + } + return self; +} + +napi_value JsConfig::InitConfig(napi_env env, napi_value exports) +{ + auto lambda = []() -> std::vector { + std::vector properties = { + DECLARE_NAPI_STATIC_FUNCTION("enableCloud", JsConfig::EnableCloud), + DECLARE_NAPI_STATIC_FUNCTION("disableCloud", JsConfig::DisableCloud), + DECLARE_NAPI_STATIC_FUNCTION("changeAppCloudSwitch", JsConfig::ChangeAppCloudSwitch), + DECLARE_NAPI_STATIC_FUNCTION("clean", JsConfig::Clean), + DECLARE_NAPI_STATIC_FUNCTION("notifyDataChange", JsConfig::NotifyDataChange), + }; + return properties; + }; + auto jsCtor = JSUtils::DefineClass(env, "Config", lambda, JsConfig::New); + NAPI_CALL(env, napi_set_named_property(env, exports, "Config", jsCtor)); + return exports; +} \ No newline at end of file diff --git a/relational_store/frameworks/js/napi/cloud_data/src/js_const_properties.cpp b/relational_store/frameworks/js/napi/cloud_data/src/js_const_properties.cpp new file mode 100644 index 00000000..60f4df42 --- /dev/null +++ b/relational_store/frameworks/js/napi/cloud_data/src/js_const_properties.cpp @@ -0,0 +1,53 @@ +/* +* Copyright (c) 2023 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 "Const_Properties" +#include "js_const_properties.h" + +#include "cloud_service.h" +#include "log_print.h" +#include "napi_queue.h" + +using Action = OHOS::CloudData::CloudService::Action; +namespace OHOS::CloudData { +static napi_status SetNamedProperty(napi_env env, napi_value &obj, const std::string &name, int32_t value) +{ + napi_value property = nullptr; + napi_status status = napi_create_int32(env, value, &property); + ASSERT(status == napi_ok, "int32_t to napi_value failed!", status); + status = napi_set_named_property(env, obj, name.c_str(), property); + ASSERT(status == napi_ok, "napi_set_named_property failed!", status); + return status; +} + +static napi_value ExportAction(napi_env env) +{ + napi_value action = nullptr; + napi_create_object(env, &action); + SetNamedProperty(env, action, "CLEAR_CLOUD_INFO", (int32_t)Action::CLEAR_CLOUD_INFO); + SetNamedProperty(env, action, "CLEAR_CLOUD_DATA_AND_INFO", (int32_t)Action::CLEAR_CLOUD_DATA_AND_INFO); + napi_object_freeze(env, action); + return action; +} + +napi_status InitConstProperties(napi_env env, napi_value exports) +{ + const napi_property_descriptor properties[] = { + DECLARE_NAPI_PROPERTY("Action", ExportAction(env)), + }; + size_t count = sizeof(properties) / sizeof(properties[0]); + + return napi_define_properties(env, exports, count, properties); +} +} // namespace OHOS::CloudData diff --git a/relational_store/frameworks/js/napi/cloud_data/src/js_error_utils.cpp b/relational_store/frameworks/js/napi/cloud_data/src/js_error_utils.cpp new file mode 100644 index 00000000..e7f8ea51 --- /dev/null +++ b/relational_store/frameworks/js/napi/cloud_data/src/js_error_utils.cpp @@ -0,0 +1,93 @@ +/* +* Copyright (c) 2023 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 "JS_ERROR_UTILS" + +#include "js_error_utils.h" + +#include + +namespace OHOS::CloudData { +using JsErrorCode = OHOS::CloudData::JsErrorCode; + +static constexpr JsErrorCode JS_ERROR_CODE_MSGS[] = { + { Status::INVALID_ARGUMENT, 401, "Parameter error." }, + { Status::NOT_SUPPORT, 801, "Not support." }, + { Status::PERMISSION_DENIED, 201, "Permission denied." } +}; + +const std::optional GetJsErrorCode(int32_t errorCode) +{ + auto jsErrorCode = JsErrorCode{ errorCode, -1, "" }; + auto iter = std::lower_bound(JS_ERROR_CODE_MSGS, + JS_ERROR_CODE_MSGS + sizeof(JS_ERROR_CODE_MSGS) / sizeof(JS_ERROR_CODE_MSGS[0]), jsErrorCode, + [](const JsErrorCode &jsErrorCode1, const JsErrorCode &jsErrorCode2) { + return jsErrorCode1.status < jsErrorCode2.status; + }); + if (iter < JS_ERROR_CODE_MSGS + sizeof(JS_ERROR_CODE_MSGS) / sizeof(JS_ERROR_CODE_MSGS[0]) + && iter->status == errorCode) { + return *iter; + } + return std::nullopt; +} + +Status GenerateNapiError(int32_t status, int32_t &errCode, std::string &errMessage) +{ + auto errorMsg = GetJsErrorCode(status); + if (errorMsg.has_value()) { + auto napiError = errorMsg.value(); + errCode = napiError.jsCode; + errMessage = napiError.message; + } else { + // unmatched status return unified error code + errCode = -1; + errMessage = ""; + } + ZLOGD("GenerateNapiError errCode is %{public}d", errCode); + if (errCode == 0) { + return Status::SUCCESS; + } + return static_cast(status); +} + +void ThrowNapiError(napi_env env, int32_t status, std::string errMessage, bool isParamsCheck) +{ + ZLOGD("ThrowNapiError message: %{public}s", errMessage.c_str()); + if (status == Status::SUCCESS) { + return; + } + auto errorMsg = GetJsErrorCode(status); + JsErrorCode napiError; + if (errorMsg.has_value()) { + napiError = errorMsg.value(); + } else { + napiError.jsCode = -1; + napiError.message = ""; + } + + std::string message(napiError.message); + if (isParamsCheck) { + napiError.jsCode = 401; + message += errMessage; + } + + std::string jsCode; + if (napiError.jsCode == -1) { + jsCode = ""; + } else { + jsCode = std::to_string(napiError.jsCode); + } + napi_throw_error(env, jsCode.c_str(), message.c_str()); +} +} // namespace OHOS::CloudData diff --git a/relational_store/frameworks/js/napi/cloud_data/src/napi_queue.cpp b/relational_store/frameworks/js/napi/cloud_data/src/napi_queue.cpp new file mode 100644 index 00000000..3647dc97 --- /dev/null +++ b/relational_store/frameworks/js/napi/cloud_data/src/napi_queue.cpp @@ -0,0 +1,166 @@ +/* +* Copyright (c) 2023 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 "NapiQueue" +#include "napi_queue.h" + +namespace OHOS::CloudData { +ContextBase::~ContextBase() +{ + ZLOGD("no memory leak after callback or promise[resolved/rejected]"); + if (env != nullptr) { + if (callbackRef != nullptr) { + auto status = napi_delete_reference(env, callbackRef); + ZLOGD("status:%{public}d", status); + } + if (selfRef != nullptr) { + auto status = napi_delete_reference(env, selfRef); + ZLOGD("status:%{public}d", status); + } + env = nullptr; + } +} + +void ContextBase::GetCbInfo(napi_env envi, napi_callback_info info, NapiCbInfoParser parse, bool sync) +{ + env = envi; + size_t argc = ARGC_MAX; + napi_value argv[ARGC_MAX] = { nullptr }; + status = napi_get_cb_info(env, info, &argc, argv, &self, nullptr); + ASSERT_STATUS(this, "napi_get_cb_info failed!"); + ASSERT_ARGS(this, argc <= ARGC_MAX, "too many arguments!"); + ASSERT_ARGS(this, self != nullptr, "no JavaScript this argument!"); + if (!sync) { + napi_create_reference(env, self, 1, &selfRef); + } + status = napi_unwrap(env, self, &native); + ASSERT_STATUS(this, "self unwrap failed!"); + + if (!sync && (argc > 0)) { + // get the last arguments :: + size_t index = argc - 1; + napi_valuetype type = napi_undefined; + napi_status tyst = napi_typeof(env, argv[index], &type); + if ((tyst == napi_ok) && (type == napi_function)) { + status = napi_create_reference(env, argv[index], 1, &callbackRef); + ASSERT_STATUS(this, "ref callback failed!"); + argc = index; + ZLOGD("async callback, no promise"); + } else { + ZLOGD("no callback, async pormose"); + } + } + + if (parse) { + parse(argc, argv); + } else { + ASSERT_ARGS(this, argc == 0, "required no arguments!"); + } +} + +napi_value NapiQueue::AsyncWork(napi_env env, std::shared_ptr ctxt, const std::string &name, + NapiAsyncExecute execute, NapiAsyncComplete complete) +{ + ZLOGD("name=%{public}s", name.c_str()); + AsyncContext *aCtx = new (std::nothrow) AsyncContext; + if (aCtx == nullptr) { + return nullptr; + } + aCtx->env = env; + aCtx->ctx = std::move(ctxt); + aCtx->execute = std::move(execute); + aCtx->complete = std::move(complete); + napi_value promise = nullptr; + if (aCtx->ctx->callbackRef == nullptr) { + napi_create_promise(env, &aCtx->deferred, &promise); + ZLOGD("create deferred promise"); + } else { + napi_get_undefined(env, &promise); + } + + napi_value resource = nullptr; + napi_create_string_utf8(env, name.c_str(), NAPI_AUTO_LENGTH, &resource); + napi_create_async_work( + env, nullptr, resource, + [](napi_env env, void *data) { + ASSERT_VOID(data != nullptr, "napi_async_execute_callback nullptr"); + auto actx = reinterpret_cast(data); + ZLOGD("napi_async_execute_callback ctxt->status=%{public}d", actx->ctx->status); + if (actx->execute && actx->ctx->status == napi_ok) { + actx->execute(); + } + }, + [](napi_env env, napi_status status, void *data) { + ASSERT_VOID(data != nullptr, "napi_async_complete_callback nullptr"); + auto actx = reinterpret_cast(data); + ZLOGD("napi_async_complete_callback status=%{public}d, ctxt->status=%{public}d", status, actx->ctx->status); + if ((status != napi_ok) && (actx->ctx->status == napi_ok)) { + actx->ctx->status = status; + } + napi_value output = nullptr; + if ((actx->complete) && (status == napi_ok) && (actx->ctx->status == napi_ok)) { + actx->complete(output); + } + GenerateOutput(*actx, output); + delete actx; + }, + reinterpret_cast(aCtx), &aCtx->work); + auto status = napi_queue_async_work(env, aCtx->work); + if (status != napi_ok) { + napi_get_undefined(env, &promise); + delete aCtx; + } + return promise; +} + +void NapiQueue::GenerateOutput(AsyncContext &ctx, napi_value output) +{ + napi_value result[RESULT_ALL] = { nullptr }; + if (ctx.ctx->status == napi_ok) { + napi_get_undefined(ctx.env, &result[RESULT_ERROR]); + if (output == nullptr) { + napi_get_undefined(ctx.env, &output); + } + result[RESULT_DATA] = output; + } else { + napi_value message = nullptr; + napi_value errorCode = nullptr; + if (ctx.ctx->jsCode != 0 && ctx.ctx->jsCode != -1) { + napi_create_string_utf8(ctx.env, std::to_string(ctx.ctx->jsCode).c_str(), NAPI_AUTO_LENGTH, &errorCode); + } + if (ctx.ctx->jsCode == -1) { + std::string jscode = ""; + napi_create_string_utf8(ctx.env, jscode.c_str(), NAPI_AUTO_LENGTH, &errorCode); + } + napi_create_string_utf8(ctx.env, ctx.ctx->error.c_str(), NAPI_AUTO_LENGTH, &message); + napi_create_error(ctx.env, errorCode, message, &result[RESULT_ERROR]); + napi_get_undefined(ctx.env, &result[RESULT_DATA]); + } + if (ctx.deferred != nullptr) { + if (ctx.ctx->status == napi_ok) { + ZLOGD("deferred promise resolved"); + napi_resolve_deferred(ctx.env, ctx.deferred, result[RESULT_DATA]); + } else { + ZLOGD("deferred promise rejected"); + napi_reject_deferred(ctx.env, ctx.deferred, result[RESULT_ERROR]); + } + } else { + napi_value callback = nullptr; + napi_get_reference_value(ctx.env, ctx.ctx->callbackRef, &callback); + napi_value callbackResult = nullptr; + ZLOGD("call callback function"); + napi_call_function(ctx.env, nullptr, callback, RESULT_ALL, result, &callbackResult); + } +} +} // namespace OHOS::CloudData diff --git a/relational_store/frameworks/native/cloud_data/include/cloud_service_proxy.h b/relational_store/frameworks/native/cloud_data/include/cloud_service_proxy.h index b94c8032..58aa6445 100644 --- a/relational_store/frameworks/native/cloud_data/include/cloud_service_proxy.h +++ b/relational_store/frameworks/native/cloud_data/include/cloud_service_proxy.h @@ -23,7 +23,7 @@ namespace OHOS::CloudData { class CloudServiceProxy : public IRemoteProxy { public: - explicit CloudServiceProxy(const sptr& object); + explicit CloudServiceProxy(const sptr &object); virtual ~CloudServiceProxy() = default; int32_t EnableCloud(const std::string &id, const std::map &switches) override; int32_t DisableCloud(const std::string &id) override; diff --git a/relational_store/frameworks/native/cloud_data/src/cloud_manager.cpp b/relational_store/frameworks/native/cloud_data/src/cloud_manager.cpp index 5f0e290d..e6d46b9a 100644 --- a/relational_store/frameworks/native/cloud_data/src/cloud_manager.cpp +++ b/relational_store/frameworks/native/cloud_data/src/cloud_manager.cpp @@ -51,34 +51,34 @@ CloudManager &CloudManager::GetInstance() return instance; } -std::shared_ptr CloudManager::GetCloudService() +std::pair> CloudManager::GetCloudService() { std::lock_guard lg(mutex_); if (cloudService_ != nullptr) { - return cloudService_; + return std::make_pair(CloudService::Status::SUCCESS, cloudService_); } auto saMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); if (saMgr == nullptr) { ZLOGE("get system ability manager failed"); - return nullptr; + return std::make_pair(CloudService::Status::SERVER_UNAVAILABLE, nullptr); } auto dataMgrObject = saMgr->CheckSystemAbility(DISTRIBUTED_KV_DATA_SERVICE_ABILITY_ID); if (dataMgrObject == nullptr) { ZLOGE("get distributed data manager failed"); - return nullptr; + return std::make_pair(CloudService::Status::SERVER_UNAVAILABLE, nullptr); } sptr dataMgr = new (std::nothrow) DataMgrService(dataMgrObject); if (dataMgr == nullptr) { ZLOGE("new CloudDataServiceProxy failed"); - return nullptr; + return std::make_pair(CloudService::Status::SERVER_UNAVAILABLE, nullptr); } auto cloudObject = dataMgr->GetFeatureInterface(CloudService::SERVICE_NAME); if (cloudObject == nullptr) { ZLOGE("get cloud service failed"); - return nullptr; + return std::make_pair(CloudService::Status::FEATURE_UNAVAILABLE, nullptr); } cloudObject->AddDeathRecipient(new CloudDeath([this]() { @@ -88,14 +88,14 @@ std::shared_ptr CloudManager::GetCloudService() sptr proxy = new (std::nothrow) CloudServiceProxy(cloudObject); if (proxy == nullptr) { - return nullptr; + return std::make_pair(CloudService::Status::FEATURE_UNAVAILABLE, nullptr); } cloudService_ = std::shared_ptr(proxy.GetRefPtr(), [holder = proxy](const auto *) {}); if (cloudService_ == nullptr) { - return nullptr; + return std::make_pair(CloudService::Status::FEATURE_UNAVAILABLE, nullptr); } - return cloudService_; + return std::make_pair(CloudService::Status::SUCCESS, cloudService_); } DataMgrService::DataMgrService(const sptr &impl) : IRemoteProxy(impl) diff --git a/relational_store/frameworks/native/rdb/include/rdb_service_proxy.h b/relational_store/frameworks/native/rdb/include/rdb_service_proxy.h index 6c7bc59d..5e28457e 100644 --- a/relational_store/frameworks/native/rdb/include/rdb_service_proxy.h +++ b/relational_store/frameworks/native/rdb/include/rdb_service_proxy.h @@ -49,8 +49,7 @@ public: int32_t RemoteQuery(const RdbSyncerParam& param, const std::string& device, const std::string& sql, const std::vector& selectionArgs, sptr& resultSet) override; - int32_t CreateRDBTable( - const RdbSyncerParam ¶m, const std::string &writePermission, const std::string &readPermission) override; + int32_t CreateRDBTable(const RdbSyncerParam ¶m) override; int32_t DestroyRDBTable(const RdbSyncerParam ¶m) override; ObserverMap ExportObservers(); @@ -65,7 +64,7 @@ protected: int32_t DoAsync(const RdbSyncerParam& param, uint32_t seqNum, const SyncOption& option, const RdbPredicates& predicates) override; - int32_t DoSubscribe(const RdbSyncerParam& param) override; + int32_t DoSubscribe(const RdbSyncerParam& param, const SubscribeOption &option) override; int32_t DoUnSubscribe(const RdbSyncerParam& param) override; diff --git a/relational_store/frameworks/native/rdb/include/rdb_store_impl.h b/relational_store/frameworks/native/rdb/include/rdb_store_impl.h index eb1d3df4..078a04c7 100644 --- a/relational_store/frameworks/native/rdb/include/rdb_store_impl.h +++ b/relational_store/frameworks/native/rdb/include/rdb_store_impl.h @@ -119,7 +119,6 @@ private: int FreeTransaction(SqliteConnection *connection, const std::string &sql); std::pair> GetInsertParams( std::map &&values, const std::string &table); - const RdbStoreConfig rdbStoreConfig; SqliteConnectionPool *connectionPool; static const int MAX_IDLE_SESSION_SIZE = 5; diff --git a/relational_store/frameworks/native/rdb/include/rdb_types_util.h b/relational_store/frameworks/native/rdb/include/rdb_types_util.h index 019b9ce4..cad89d6e 100644 --- a/relational_store/frameworks/native/rdb/include/rdb_types_util.h +++ b/relational_store/frameworks/native/rdb/include/rdb_types_util.h @@ -21,6 +21,7 @@ #include "values_bucket.h" #include "rdb_visibility.h" namespace OHOS::ITypesUtil { +using SubOption = DistributedRdb::SubscribeOption; using SyncerParam = DistributedRdb::RdbSyncerParam; using SyncOption = DistributedRdb::SyncOption; using RdbPredicates = DistributedRdb::RdbPredicates; @@ -45,6 +46,10 @@ API_EXPORT bool Marshalling(const RdbOperation &input, MessageParcel &data); template<> API_EXPORT bool Unmarshalling(RdbOperation &output, MessageParcel &data); template<> +API_EXPORT bool Marshalling(const SubOption &input, MessageParcel &data); +template<> +API_EXPORT bool Unmarshalling(SubOption &output, MessageParcel &data); +template<> API_EXPORT bool Marshalling(const ValueObject &input, MessageParcel &data); template<> API_EXPORT bool Unmarshalling(ValueObject &output, MessageParcel &data); diff --git a/relational_store/frameworks/native/rdb/src/rdb_manager_impl.cpp b/relational_store/frameworks/native/rdb/src/rdb_manager_impl.cpp index d7321f92..4023b536 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_manager_impl.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_manager_impl.cpp @@ -29,6 +29,7 @@ #include "rdb_errno.h" namespace OHOS::DistributedRdb { +using RdbServiceProxy = DistributedRdb::RdbServiceProxy; using namespace OHOS::NativeRdb; std::shared_ptr RdbManagerImpl::GetDistributedDataManager() { @@ -100,7 +101,19 @@ int RdbManagerImpl::GetRdbService(const RdbSyncerParam ¶m, std::shared_ptr serviceProxy = iface_cast(remote); + sptr serviceProxy = nullptr; + if (remote->IsProxyObject()) { + serviceProxy = iface_cast(remote); + } + + if (serviceProxy == nullptr) { + serviceProxy = new (std::nothrow) RdbServiceProxy(remote); + } + + if (serviceProxy == nullptr) { + return E_ERROR; + } +// sptr serviceProxy = iface_cast(remote); if (serviceProxy->InitNotifier(param) != RDB_OK) { ZLOGE("init notifier failed"); return E_ERROR; diff --git a/relational_store/frameworks/native/rdb/src/rdb_service_proxy.cpp b/relational_store/frameworks/native/rdb/src/rdb_service_proxy.cpp index fa87c474..bac75d40 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_service_proxy.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_service_proxy.cpp @@ -221,11 +221,11 @@ std::string RdbServiceProxy::RemoveSuffix(const std::string& name) int32_t RdbServiceProxy::Subscribe(const RdbSyncerParam ¶m, const SubscribeOption &option, RdbStoreObserver *observer) { - if (option.mode != SubscribeMode::REMOTE) { + if (option.mode < SubscribeMode::REMOTE || option.mode >= SUBSCRIBE_MODE_MAX) { ZLOGE("subscribe mode invalid"); return RDB_ERROR; } - if (DoSubscribe(param) != RDB_OK) { + if (DoSubscribe(param, option) != RDB_OK) { ZLOGI("communicate to server failed"); return RDB_ERROR; } @@ -244,10 +244,10 @@ int32_t RdbServiceProxy::Subscribe(const RdbSyncerParam ¶m, const SubscribeO return RDB_OK; } -int32_t RdbServiceProxy::DoSubscribe(const RdbSyncerParam ¶m) +int32_t RdbServiceProxy::DoSubscribe(const RdbSyncerParam ¶m, const SubscribeOption &option) { MessageParcel reply; - int32_t status = IPC_SEND(RDB_SERVICE_CMD_SUBSCRIBE, reply, param); + int32_t status = IPC_SEND(RDB_SERVICE_CMD_SUBSCRIBE, reply, param, option); if (status != RDB_OK) { ZLOGE("status:%{public}d, bundleName:%{public}s, storeName:%{public}s", status, param.bundleName_.c_str(), param.storeName_.c_str()); @@ -317,16 +317,14 @@ void RdbServiceProxy::ImportObservers(ObserverMap &observers) return false; }); } -int32_t RdbServiceProxy::CreateRDBTable( - const RdbSyncerParam ¶m, const std::string &writePermission, const std::string &readPermission) + +int32_t RdbServiceProxy::CreateRDBTable(const RdbSyncerParam ¶m) { MessageParcel reply; - int32_t status = IPC_SEND(RDB_SERVICE_CREATE_RDB_TABLE, reply, param, writePermission, readPermission); + int32_t status = IPC_SEND(RDB_SERVICE_CREATE_RDB_TABLE, reply, param); if (status != RDB_OK) { - ZLOGE("status:%{public}d, bundleName:%{public}s, storeName:%{public}s," - "writePermission:%{public}.6s, readPermission:%{public}.6s", - status, param.bundleName_.c_str(), param.storeName_.c_str(), - writePermission.c_str(), readPermission.c_str()); + ZLOGE("status:%{public}d, bundleName:%{public}s, storeName:%{public}s", status, param.bundleName_.c_str(), + param.storeName_.c_str()); } return status; } diff --git a/relational_store/frameworks/native/rdb/src/rdb_store_impl.cpp b/relational_store/frameworks/native/rdb/src/rdb_store_impl.cpp index ec086c35..2b8b7a56 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_store_impl.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_store_impl.cpp @@ -92,24 +92,15 @@ int RdbStoreImpl::InnerOpen(const RdbStoreConfig &config) syncerParam_.isEncrypt_ = config.IsEncrypt(); syncerParam_.password_ = {}; - //config.GetTokenType() == 1 - uint32_t id = IPCSkeleton::GetSelfTokenID() & 0xffffffff; - if (AccessTokenKit::GetTokenTypeFlag(id) != TOKEN_HAP) { - LOG_DEBUG("%{public}s is not a hap.", config.GetBundleName().c_str()); - return E_OK; - } std::shared_ptr service = nullptr; errCode = DistributedRdb::RdbManagerImpl::GetInstance().GetRdbService(syncerParam_, service); if (errCode != E_OK) { LOG_ERROR("GetRdbService failed, err is %{public}d.", errCode); return E_OK; } - errCode = service->GetSchema(syncerParam_); - if (errCode != E_OK) { - LOG_ERROR("GetSchema failed, err is %{public}d.", errCode); - } + service->GetSchema(syncerParam_); if (!config.GetUri().empty()) { - errCode = service->CreateRDBTable(syncerParam_, config.GetWritePermission(), config.GetReadPermission()); + errCode = service->CreateRDBTable(syncerParam_); if (errCode != E_OK) { LOG_ERROR("CreateRDBTable failed"); } else { diff --git a/relational_store/frameworks/native/rdb/src/rdb_types_util.cpp b/relational_store/frameworks/native/rdb/src/rdb_types_util.cpp index 444ba037..907d1223 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_types_util.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_types_util.cpp @@ -69,6 +69,20 @@ bool Unmarshalling(RdbOperation &output, MessageParcel &data) return ret; } +template<> +bool Marshalling(const SubOption &input, MessageParcel &data) +{ + return ITypesUtil::Marshal(data, static_cast(input.mode)); +} + +template<> +bool Unmarshalling(SubOption &output, MessageParcel &data) +{ + int32_t mode = static_cast(output.mode); + auto ret = ITypesUtil::Unmarshal(data, mode); + output.mode = static_cast(mode); + return ret; +} template<> bool Marshalling(const ValueObject &input, MessageParcel &data) { diff --git a/relational_store/interfaces/inner_api/cloud_data/BUILD.gn b/relational_store/interfaces/inner_api/cloud_data/BUILD.gn index 2a9adf45..9d72ca80 100644 --- a/relational_store/interfaces/inner_api/cloud_data/BUILD.gn +++ b/relational_store/interfaces/inner_api/cloud_data/BUILD.gn @@ -15,12 +15,10 @@ import("//foundation/distributeddatamgr/relational_store/relational_store.gni") config("cloud_public_config") { visibility = [ "../../../../datamgr_service/*", - "../../../../relational_store/*" + "../../../../relational_store/*", ] - include_dirs = [ - "include", - ] + include_dirs = [ "include" ] } ohos_static_library("cloud_data_inner") { diff --git a/relational_store/interfaces/inner_api/cloud_data/include/cloud_manager.h b/relational_store/interfaces/inner_api/cloud_data/include/cloud_manager.h index d067c2a7..7d369bea 100644 --- a/relational_store/interfaces/inner_api/cloud_data/include/cloud_manager.h +++ b/relational_store/interfaces/inner_api/cloud_data/include/cloud_manager.h @@ -19,12 +19,12 @@ #include #include "cloud_service.h" -#include "rdb_visibility.h" + namespace OHOS::CloudData { class CloudManager { public: - API_EXPORT static CloudManager &GetInstance(); - std::shared_ptr GetCloudService(); + static CloudManager &GetInstance(); + std::pair> GetCloudService(); private: CloudManager() = default; diff --git a/relational_store/interfaces/inner_api/cloud_data/include/cloud_service.h b/relational_store/interfaces/inner_api/cloud_data/include/cloud_service.h index 0e69ebba..13b0fa66 100644 --- a/relational_store/interfaces/inner_api/cloud_data/include/cloud_service.h +++ b/relational_store/interfaces/inner_api/cloud_data/include/cloud_service.h @@ -46,8 +46,13 @@ public: ERROR, INVALID_ARGUMENT, SERVER_UNAVAILABLE, + FEATURE_UNAVAILABLE, + NOT_SUPPORT, + CLOUD_DISABLE, + CLOUD_DISABLE_SWITCH, IPC_ERROR, - IPC_PARCEL_ERROR + IPC_PARCEL_ERROR, + PERMISSION_DENIED }; virtual ~CloudService() = default; diff --git a/relational_store/interfaces/inner_api/rdb/include/rdb_service.h b/relational_store/interfaces/inner_api/rdb/include/rdb_service.h index fc8f6ed3..9e82eda3 100644 --- a/relational_store/interfaces/inner_api/rdb/include/rdb_service.h +++ b/relational_store/interfaces/inner_api/rdb/include/rdb_service.h @@ -56,8 +56,7 @@ public: virtual int32_t RemoteQuery(const RdbSyncerParam ¶m, const std::string &device, const std::string &sql, const std::vector &selectionArgs, sptr &resultSet) = 0; - virtual int32_t CreateRDBTable(const RdbSyncerParam ¶m, const std::string &writePermission, - const std::string &readPermission) = 0; + virtual int32_t CreateRDBTable(const RdbSyncerParam ¶m) = 0; virtual int32_t DestroyRDBTable(const RdbSyncerParam ¶m) = 0; @@ -73,7 +72,7 @@ protected: virtual int32_t DoAsync(const RdbSyncerParam ¶m, uint32_t seqNum, const SyncOption &option, const RdbPredicates &predicates) = 0; - virtual int32_t DoSubscribe(const RdbSyncerParam ¶m) = 0; + virtual int32_t DoSubscribe(const RdbSyncerParam ¶m, const SubscribeOption &option) = 0; virtual int32_t DoUnSubscribe(const RdbSyncerParam ¶m) = 0; }; diff --git a/relational_store/interfaces/inner_api/rdb/include/rdb_types.h b/relational_store/interfaces/inner_api/rdb/include/rdb_types.h index ed0d372f..37111d40 100644 --- a/relational_store/interfaces/inner_api/rdb/include/rdb_types.h +++ b/relational_store/interfaces/inner_api/rdb/include/rdb_types.h @@ -100,6 +100,7 @@ struct RdbPredicates { enum SubscribeMode { REMOTE, CLOUD, + CLOUD_DETAIL, SUBSCRIBE_MODE_MAX }; -- Gitee