diff --git a/bin/update/updata.bat b/bin/update/updata.bat index 53dc71cf8ecdbd4f284eadc2d2ceedd19018e22f..364878b015f343a4e53fcd91e1786b69868a273f 100644 --- a/bin/update/updata.bat +++ b/bin/update/updata.bat @@ -7,9 +7,9 @@ cls @echo %date%-%time% mkdir tmp @echo "clone the datamgr_service" -git clone https://gitee.com/ding_dong_dong/distributeddatamgr_datamgr_service.git ./tmp/datamgr_service +git clone https://gitee.com/openharmony/distributeddatamgr_datamgr_service.git ./tmp/datamgr_service @echo "clone the kv_store" -git clone https://gitee.com/ding_dong_dong/distributeddatamgr_kv_store.git ./tmp/kv_store +git clone https://gitee.com/openharmony/distributeddatamgr_kv_store.git ./tmp/kv_store @echo "clone the relational_store" git clone https://gitee.com/openharmony/distributeddatamgr_relational_store.git ./tmp/relational_store @echo "clone the data_object" @@ -19,7 +19,7 @@ git clone https://gitee.com/openharmony/distributeddatamgr_data_share.git ./tmp/ @echo "clone the preferences" git clone https://gitee.com/openharmony/distributeddatamgr_preferences.git ./tmp/preferences @echo "clone the udmf" -git clone https://gitee.com/ding_dong_dong/distributeddatamgr_udmf.git ./tmp/udmf +git clone https://gitee.com/openharmony/distributeddatamgr_udmf.git ./tmp/udmf xcopy tmp\* ..\..\ /y /e /i /q rd /s /q tmp @echo "FINISHED" diff --git a/data_object/bundle.json b/data_object/bundle.json index 0112f2eb60e60acca76c0220a1d68333b30190b5..1c67d441cfddc847be2601c5837de2a45c13adcb 100644 --- a/data_object/bundle.json +++ b/data_object/bundle.json @@ -44,17 +44,13 @@ "ram": "1024KB", "deps": { "components": [ - "ability_base", "ability_runtime", - "hitrace_native", + "hitrace", "dsoftbus", - "distributeddatamgr", "napi", - "common", "samgr", "ipc", - "hiviewdfx_hilog_native", - "utils_base", + "hilog", "access_token", "c_utils", "device_manager", diff --git a/data_object/frameworks/innerkitsimpl/include/distributeddata_object_store_ipc_interface_code.h b/data_object/frameworks/innerkitsimpl/include/distributeddata_object_store_ipc_interface_code.h new file mode 100644 index 0000000000000000000000000000000000000000..143334b7c6eaf4cf00c9e6880d3014f6ca5b54a1 --- /dev/null +++ b/data_object/frameworks/innerkitsimpl/include/distributeddata_object_store_ipc_interface_code.h @@ -0,0 +1,39 @@ +/* + * 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. + */ + +/* SAID:1301 */ +/* FeatureSystem: object_service */ +#ifndef DISTRIBUTEDDATA_OBJECT_STORE_IPC_INTERFACE_H +#define DISTRIBUTEDDATA_OBJECT_STORE_IPC_INTERFACE_H + +namespace OHOS::DistributedObject { +namespace ObjectStoreService { +enum class ObjectServiceInterfaceCode { + OBJECTSTORE_SAVE, + OBJECTSTORE_REVOKE_SAVE, + OBJECTSTORE_RETRIEVE, + OBJECTSTORE_REGISTER_OBSERVER, + OBJECTSTORE_UNREGISTER_OBSERVER, + OBJECTSTORE_SERVICE_CMD_MAX +}; + +enum class KvStoreServiceInterfaceCode { + GET_FEATURE_INTERFACE = 0, + REGISTERCLIENTDEATHOBSERVER, +}; +} +} // namespace OHOS + +#endif // DISTRIBUTEDDATA_OBJECT_STORE_IPC_INTERFACE_H \ No newline at end of file diff --git a/data_object/frameworks/innerkitsimpl/include/iobject_service.h b/data_object/frameworks/innerkitsimpl/include/iobject_service.h index 85195a712afc95cdc0b6bf0174eafccd0ea820e8..1bc586104e78618eb3bb7893fb6db4741796ace0 100644 --- a/data_object/frameworks/innerkitsimpl/include/iobject_service.h +++ b/data_object/frameworks/innerkitsimpl/include/iobject_service.h @@ -20,6 +20,7 @@ #include #include "object_service.h" +#include "distributeddata_object_store_ipc_interface_code.h" namespace OHOS::DistributedObject { class IObjectService : public ObjectService, public IRemoteBroker { @@ -29,11 +30,6 @@ public: class IKvStoreDataService : public IRemoteBroker { public: - enum { - GET_FEATURE_INTERFACE = 0, - REGISTERCLIENTDEATHOBSERVER, - }; - DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.DistributedKv.IKvStoreDataService"); virtual sptr GetFeatureInterface(const std::string &name) = 0; diff --git a/data_object/frameworks/innerkitsimpl/include/object_service.h b/data_object/frameworks/innerkitsimpl/include/object_service.h index 6c8dbdb4ad54095cd61de81b85b19ddd42d3c2bf..2e49a85f8512958aae96022abda5d38f3885639b 100644 --- a/data_object/frameworks/innerkitsimpl/include/object_service.h +++ b/data_object/frameworks/innerkitsimpl/include/object_service.h @@ -19,18 +19,11 @@ #include #include #include +#include "distributeddata_object_store_ipc_interface_code.h" namespace OHOS::DistributedObject { class ObjectService { public: - enum { - OBJECTSTORE_SAVE, - OBJECTSTORE_REVOKE_SAVE, - OBJECTSTORE_RETRIEVE, - OBJECTSTORE_REGISTER_OBSERVER, - OBJECTSTORE_UNREGISTER_OBSERVER, - OBJECTSTORE_SERVICE_CMD_MAX - }; virtual int32_t ObjectStoreSave(const std::string &bundleName, const std::string &sessionId, const std::string &deviceId, const std::map> &data, sptr callback) = 0; diff --git a/data_object/frameworks/innerkitsimpl/src/adaptor/client_adaptor.cpp b/data_object/frameworks/innerkitsimpl/src/adaptor/client_adaptor.cpp index 1f16cc2473990019689dfdda1c4f1ceb60a4ed28..f47e6eda17be9161e259f17cbe4477b445b4ac62 100644 --- a/data_object/frameworks/innerkitsimpl/src/adaptor/client_adaptor.cpp +++ b/data_object/frameworks/innerkitsimpl/src/adaptor/client_adaptor.cpp @@ -25,6 +25,8 @@ namespace OHOS::ObjectStore { std::shared_ptr ClientAdaptor::distributedDataMgr_ = nullptr; +using KvStoreCode = OHOS::DistributedObject::ObjectStoreService::KvStoreServiceInterfaceCode; + sptr ClientAdaptor::GetObjectService() { if (distributedDataMgr_ == nullptr) { @@ -110,7 +112,7 @@ sptr ObjectStoreDataServiceProxy::GetFeatureInterface(const std:: MessageParcel reply; MessageOption mo { MessageOption::TF_SYNC }; - int32_t error = Remote()->SendRequest(GET_FEATURE_INTERFACE, data, reply, mo); + int32_t error = Remote()->SendRequest(static_cast(KvStoreCode::GET_FEATURE_INTERFACE), data, reply, mo); if (error != 0) { LOG_ERROR("SendRequest returned %{public}d", error); return nullptr; @@ -142,7 +144,8 @@ uint32_t ObjectStoreDataServiceProxy::RegisterClientDeathObserver( } MessageOption mo { MessageOption::TF_SYNC }; - int32_t error = Remote()->SendRequest(REGISTERCLIENTDEATHOBSERVER, data, reply, mo); + int32_t error = Remote()->SendRequest( + static_cast(KvStoreCode::REGISTERCLIENTDEATHOBSERVER), data, reply, mo); if (error != 0) { LOG_WARN("failed during IPC. errCode %d", error); return ERR_IPC; diff --git a/data_object/frameworks/innerkitsimpl/src/object_service_proxy.cpp b/data_object/frameworks/innerkitsimpl/src/object_service_proxy.cpp index 42bff35a50192c78d50d97c4da92f05d77bc77ef..8d23a2382b1bf0fc08c95edf4ca46fef788e4ee2 100644 --- a/data_object/frameworks/innerkitsimpl/src/object_service_proxy.cpp +++ b/data_object/frameworks/innerkitsimpl/src/object_service_proxy.cpp @@ -23,6 +23,9 @@ namespace OHOS::DistributedObject { using namespace ObjectStore; + +using ObjectCode = ObjectStoreService::ObjectServiceInterfaceCode; + ObjectServiceProxy::ObjectServiceProxy(const sptr &impl) : IRemoteProxy(impl) { ZLOGI("init service proxy."); @@ -43,7 +46,7 @@ int32_t ObjectServiceProxy::ObjectStoreSave(const std::string &bundleName, const } MessageParcel reply; MessageOption mo { MessageOption::TF_SYNC }; - int32_t error = Remote()->SendRequest(OBJECTSTORE_SAVE, data, reply, mo); + int32_t error = Remote()->SendRequest(static_cast(ObjectCode::OBJECTSTORE_SAVE), data, reply, mo); if (error != 0) { ZLOGE("SendRequest returned %d", error); return ERR_IPC; @@ -67,7 +70,7 @@ int32_t ObjectServiceProxy::ObjectStoreRevokeSave( MessageParcel reply; MessageOption mo { MessageOption::TF_SYNC }; - int32_t error = Remote()->SendRequest(OBJECTSTORE_REVOKE_SAVE, data, reply, mo); + int32_t error = Remote()->SendRequest(static_cast(ObjectCode::OBJECTSTORE_REVOKE_SAVE), data, reply, mo); if (error != 0) { ZLOGE("SendRequest returned %d", error); return ERR_IPC; @@ -91,7 +94,7 @@ int32_t ObjectServiceProxy::ObjectStoreRetrieve( MessageParcel reply; MessageOption mo { MessageOption::TF_SYNC }; - int32_t error = Remote()->SendRequest(OBJECTSTORE_RETRIEVE, data, reply, mo); + int32_t error = Remote()->SendRequest(static_cast(ObjectCode::OBJECTSTORE_RETRIEVE), data, reply, mo); if (error != 0) { ZLOGE("SendRequest returned %d", error); return ERR_IPC; @@ -115,7 +118,8 @@ int32_t ObjectServiceProxy::RegisterDataObserver(const std::string &bundleName, MessageParcel reply; MessageOption mo { MessageOption::TF_SYNC }; - int32_t error = Remote()->SendRequest(OBJECTSTORE_REGISTER_OBSERVER, data, reply, mo); + int32_t error = Remote()->SendRequest( + static_cast(ObjectCode::OBJECTSTORE_REGISTER_OBSERVER), data, reply, mo); if (error != 0) { ZLOGE("SendRequest returned %d", error); return ERR_IPC; @@ -138,7 +142,8 @@ int32_t ObjectServiceProxy::UnregisterDataChangeObserver(const std::string &bund MessageParcel reply; MessageOption mo { MessageOption::TF_SYNC }; - int32_t error = Remote()->SendRequest(OBJECTSTORE_UNREGISTER_OBSERVER, data, reply, mo); + int32_t error = Remote()->SendRequest( + static_cast(ObjectCode::OBJECTSTORE_UNREGISTER_OBSERVER), data, reply, mo); if (error != 0) { ZLOGE("SendRequest returned %d", error); return ERR_IPC; diff --git a/data_object/interfaces/innerkits/BUILD.gn b/data_object/interfaces/innerkits/BUILD.gn index 25a47e34800ded5013322a3b5c3fbfe1b91bcc98..fbe4aeb7254fa9ee7abf5b4e6702ad4d52bc7127 100644 --- a/data_object/interfaces/innerkits/BUILD.gn +++ b/data_object/interfaces/innerkits/BUILD.gn @@ -63,9 +63,9 @@ object_external_deps_config = [ "c_utils:utils", "device_manager:devicemanagersdk", "dsoftbus:softbus_client", - "hitrace_native:hitrace_meter", - "hitrace_native:libhitracechain", - "hiviewdfx_hilog_native:libhilog", + "hitrace:hitrace_meter", + "hitrace:libhitracechain", + "hilog:libhilog", "ipc:ipc_core", "kv_store:distributeddata_inner", "samgr:samgr_proxy", diff --git a/data_object/interfaces/jskits/BUILD.gn b/data_object/interfaces/jskits/BUILD.gn index ce5ff55b07d61c88d8c38eca5ec16ff44c57d4ab..b2b70587b900e1460332dd19c869a24b8dad9fa3 100644 --- a/data_object/interfaces/jskits/BUILD.gn +++ b/data_object/interfaces/jskits/BUILD.gn @@ -10,7 +10,8 @@ # 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. -import("//arkcompiler/ets_frontend/ts2panda/ts2abc_config.gni") + +import("//arkcompiler/ets_frontend/es2panda/es2abc_config.gni") import("//build/ohos.gni") import("//build/ohos/ace/ace.gni") import("//foundation/arkui/ace_engine/ace_config.gni") @@ -20,26 +21,13 @@ group("build_module") { } # compile .js to .abc. -action("gen_distributed_data_object_abc") { - visibility = [ ":*" ] - script = "//arkcompiler/ets_frontend/ts2panda/scripts/generate_js_bytecode.py" - - args = [ - "--src-js", - rebase_path("distributed_data_object.js"), - "--dst-file", - rebase_path(target_out_dir + "/distributed_data_object.abc"), - "--node", - rebase_path("${node_path}"), - "--frontend-tool-path", - rebase_path("${ts2abc_build_path}"), - "--node-modules", - rebase_path("${node_modules}"), - "--module", - ] - deps = [ "//arkcompiler/ets_frontend/ts2panda:ark_ts2abc_build" ] - inputs = [ "distributed_data_object.js" ] - outputs = [ target_out_dir + "/distributed_data_object.abc" ] +es2abc_gen_abc("gen_distributed_data_object_abc") { + extra_visibility = [ ":*" ] + src_js = rebase_path("distributed_data_object.js") + dst_file = rebase_path(target_out_dir + "/distributed_data_object.abc") + in_puts = [ "distributed_data_object.js" ] + out_puts = [ target_out_dir + "/distributed_data_object.abc" ] + extra_args = [ "--module" ] } config("objectstore_config") { @@ -118,7 +106,7 @@ ohos_shared_library("distributeddataobject") { "ability_runtime:napi_base_context", "access_token:libaccesstoken_sdk", "common_event_service:cesfwk_innerkits", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", "napi:ace_napi", ] diff --git a/data_share/CODEOWNERS b/data_share/CODEOWNERS new file mode 100644 index 0000000000000000000000000000000000000000..f59cc39e886e93147a9dbb62933fd7e497482ead --- /dev/null +++ b/data_share/CODEOWNERS @@ -0,0 +1,17 @@ +# 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. + +# any change to +# frameworks/native/common/include/distributeddata_data_share_ipc_interface_code.h +# needs to be reviewed by @leonchan5 +frameworks/native/common/include/distributeddata_data_share_ipc_interface_code.h @leonchan5 \ No newline at end of file diff --git a/data_share/bundle.json b/data_share/bundle.json index d13786713b555b31b1b72c0c833cf357a1b3c4d7..1f23b4c21cec07318ea3fb8f081688320e6b97c7 100644 --- a/data_share/bundle.json +++ b/data_share/bundle.json @@ -55,9 +55,9 @@ "access_token", "common_event_service", "c_utils", - "hisysevent_native", - "hitrace_native", - "hiviewdfx_hilog_native", + "hisysevent", + "hitrace", + "hilog", "ipc", "ipc_js", "libuv", diff --git a/data_share/frameworks/js/napi/common/include/napi_callbacks_manager.h b/data_share/frameworks/js/napi/common/include/napi_callbacks_manager.h index c8936fd567b782f84523c99f2d1fd345332162bc..1cf38af51975854be9a432a3ede86bdf1241be98 100644 --- a/data_share/frameworks/js/napi/common/include/napi_callbacks_manager.h +++ b/data_share/frameworks/js/napi/common/include/napi_callbacks_manager.h @@ -27,6 +27,7 @@ template class NapiCallbacksManager { public: std::vector AddObservers(const std::vector &keys, const std::shared_ptr observer, + std::function &, const std::shared_ptr &observer)>, std::function &, const std::shared_ptr &observer, std::vector &)>); @@ -58,12 +59,15 @@ private: }; template -std::vector NapiCallbacksManager::AddObservers(const std::vector &keys, - const std::shared_ptr observer, std::function &, - const std::shared_ptr &observer, std::vector &)> processOnFirstAdd) +std::vector NapiCallbacksManager::AddObservers( + const std::vector &keys, const std::shared_ptr observer, + std::function &, const std::shared_ptr &observer)> processOnLocalAdd, + std::function &, const std::shared_ptr &observer, + std::vector &)> processOnFirstAdd) { std::vector result; std::vector firstRegisterKey; + std::vector localRegisterKey; { std::lock_guard lck(mutex_); for (auto &key : keys) { @@ -77,10 +81,14 @@ std::vector NapiCallbacksManager::AddObservers(c result.emplace_back(static_cast(key), E_REGISTERED_REPEATED); continue; } + localRegisterKey.emplace_back(key); callbacks_[key].emplace_back(observer); result.emplace_back(key, E_OK); } } + if (!localRegisterKey.empty()) { + processOnLocalAdd(localRegisterKey, observer); + } processOnFirstAdd(firstRegisterKey, observer, result); return result; } @@ -98,8 +106,8 @@ bool NapiCallbacksManager::IsRegistered(const Observer &observer, } template -std::vector NapiCallbacksManager::DelObservers(const std::vector &keys, - const std::shared_ptr observer, +std::vector NapiCallbacksManager::DelObservers( + const std::vector &keys, const std::shared_ptr observer, std::function &, const std::shared_ptr &, std::vector &)> processOnLastDel) { diff --git a/data_share/frameworks/js/napi/dataShare/BUILD.gn b/data_share/frameworks/js/napi/dataShare/BUILD.gn index 0f58291d5b518c7e766819d5d7dafdd976e4f833..14e12a8c86cb0ee84a18bb2d45651d792db5f33e 100644 --- a/data_share/frameworks/js/napi/dataShare/BUILD.gn +++ b/data_share/frameworks/js/napi/dataShare/BUILD.gn @@ -48,7 +48,7 @@ ohos_shared_library("datashare") { "ability_runtime:napi_common", "c_utils:utils", "common_event_service:cesfwk_innerkits", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", "ipc:ipc_single", "napi:ace_napi", ] @@ -77,7 +77,7 @@ ohos_shared_library("datasharepredicates") { external_deps = [ "c_utils:utils", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", "ipc:ipc_single", "napi:ace_napi", ] diff --git a/data_share/frameworks/js/napi/observer/include/napi_subscriber_manager.h b/data_share/frameworks/js/napi/observer/include/napi_subscriber_manager.h index 0a4728142910745c47e83d37a79faf505362c615..160683005e984db64f08ad06a86665ce7cf67e63 100644 --- a/data_share/frameworks/js/napi/observer/include/napi_subscriber_manager.h +++ b/data_share/frameworks/js/napi/observer/include/napi_subscriber_manager.h @@ -67,7 +67,9 @@ public: void Emit(const RdbChangeNode &changeNode); private: + void Emit(const std::vector &keys, const std::shared_ptr &observer); std::weak_ptr dataShareHelper_; + std::map lastChangeNodeMap_; }; struct NapiPublishedObserverMapKey { @@ -110,7 +112,9 @@ public: void Emit(const PublishedDataChangeNode &changeNode); private: + void Emit(const std::vector &keys, const std::shared_ptr &observer); std::weak_ptr dataShareHelper_; + std::map lastChangeNodeMap_; }; } // namespace DataShare } // namespace OHOS diff --git a/data_share/frameworks/js/napi/observer/src/napi_subscriber_manager.cpp b/data_share/frameworks/js/napi/observer/src/napi_subscriber_manager.cpp index f686ff910203dc5872c001c544db6a181a0b9557..2745d00350a2d96beb0d7b9b90c4f019780b4701 100644 --- a/data_share/frameworks/js/napi/observer/src/napi_subscriber_manager.cpp +++ b/data_share/frameworks/js/napi/observer/src/napi_subscriber_manager.cpp @@ -32,7 +32,11 @@ std::vector NapiRdbSubscriberManager::AddObservers(napi_env env std::for_each(uris.begin(), uris.end(), [&keys, &templateId](auto &uri) { keys.emplace_back(uri, templateId); }); - return BaseCallbacks::AddObservers(keys, std::make_shared(env, callback), + return BaseCallbacks::AddObservers( + keys, std::make_shared(env, callback), + [this](const std::vector &localRegisterKeys, const std::shared_ptr observer) { + Emit(localRegisterKeys, observer); + }, [&datashareHelper, &templateId, this](const std::vector &firstAddKeys, const std::shared_ptr observer, std::vector &opResult) { std::vector firstAddUris; @@ -73,10 +77,11 @@ std::vector NapiRdbSubscriberManager::DelObservers(napi_env env keys.emplace_back(uri, templateId); }); return BaseCallbacks::DelObservers(keys, callback == nullptr ? nullptr : std::make_shared(env, callback), - [&dataShareHelper, &templateId](const std::vector &lastDelKeys, const std::shared_ptr &observer, - std::vector &opResult) { + [&dataShareHelper, &templateId, this](const std::vector &lastDelKeys, + const std::shared_ptr &observer, std::vector &opResult) { std::vector lastDelUris; - std::for_each(lastDelKeys.begin(), lastDelKeys.end(), [&lastDelUris](auto &result) { + std::for_each(lastDelKeys.begin(), lastDelKeys.end(), [&lastDelUris, this](auto &result) { + lastChangeNodeMap_.erase(result); lastDelUris.emplace_back(result); }); if (lastDelUris.empty()) { @@ -90,6 +95,7 @@ std::vector NapiRdbSubscriberManager::DelObservers(napi_env env void NapiRdbSubscriberManager::Emit(const RdbChangeNode &changeNode) { Key key(changeNode.uri_, changeNode.templateId_); + lastChangeNodeMap_[key] = changeNode; auto callbacks = BaseCallbacks::GetEnabledObservers(key); for (auto &obs : callbacks) { if (obs != nullptr) { @@ -98,6 +104,16 @@ void NapiRdbSubscriberManager::Emit(const RdbChangeNode &changeNode) } } +void NapiRdbSubscriberManager::Emit(const std::vector &keys, const std::shared_ptr &observer) +{ + for (auto const &key : keys) { + auto it = lastChangeNodeMap_.find(key); + if (it != lastChangeNodeMap_.end()) { + observer->OnChange(it->second); + } + } +} + std::vector NapiPublishedSubscriberManager::AddObservers(napi_env env, napi_value callback, const std::vector &uris, int64_t subscriberId) { @@ -111,7 +127,11 @@ std::vector NapiPublishedSubscriberManager::AddObservers(napi_e std::for_each(uris.begin(), uris.end(), [&keys, &subscriberId](auto &uri) { keys.emplace_back(uri, subscriberId); }); - return BaseCallbacks::AddObservers(keys, std::make_shared(env, callback), + return BaseCallbacks::AddObservers( + keys, std::make_shared(env, callback), + [this](const std::vector &localRegisterKeys, const std::shared_ptr observer) { + Emit(localRegisterKeys, observer); + }, [&dataShareHelper, &subscriberId, this](const std::vector &firstAddKeys, const std::shared_ptr observer, std::vector &opResult) { std::vector firstAddUris; @@ -152,10 +172,11 @@ std::vector NapiPublishedSubscriberManager::DelObservers(napi_e keys.emplace_back(uri, subscriberId); }); return BaseCallbacks::DelObservers(keys, callback == nullptr ? nullptr : std::make_shared(env, callback), - [&dataShareHelper, &subscriberId, &callback, &uris](const std::vector &lastDelKeys, + [&dataShareHelper, &subscriberId, &callback, &uris, this](const std::vector &lastDelKeys, const std::shared_ptr &observer, std::vector &opResult) { std::vector lastDelUris; - std::for_each(lastDelKeys.begin(), lastDelKeys.end(), [&lastDelUris](auto &result) { + std::for_each(lastDelKeys.begin(), lastDelKeys.end(), [&lastDelUris, this](auto &result) { + lastChangeNodeMap_.erase(result); lastDelUris.emplace_back(result); }); if (lastDelUris.empty()) { @@ -168,13 +189,20 @@ std::vector NapiPublishedSubscriberManager::DelObservers(napi_e void NapiPublishedSubscriberManager::Emit(const PublishedDataChangeNode &changeNode) { + for (auto &data : changeNode.datas_) { + Key key(data.key_, data.subscriberId_); + lastChangeNodeMap_[key].datas_.clear(); + } std::map, PublishedDataChangeNode> results; for (auto &data : changeNode.datas_) { Key key(data.key_, data.subscriberId_); auto callbacks = BaseCallbacks::GetEnabledObservers(key); if (callbacks.empty()) { LOG_WARN("%{private}s nobody subscribe, but still notify", data.key_.c_str()); + continue; } + lastChangeNodeMap_[key].datas_.emplace_back(data.key_, data.subscriberId_, data.GetData()); + lastChangeNodeMap_[key].ownerBundleName_ = changeNode.ownerBundleName_; for (auto const &obs : callbacks) { results[obs].datas_.emplace_back(data.key_, data.subscriberId_, data.GetData()); } @@ -184,5 +212,21 @@ void NapiPublishedSubscriberManager::Emit(const PublishedDataChangeNode &changeN callback->OnChange(node); } } + +void NapiPublishedSubscriberManager::Emit(const std::vector &keys, const std::shared_ptr &observer) +{ + PublishedDataChangeNode node; + for (auto &key : keys) { + auto it = lastChangeNodeMap_.find(key); + if (it == lastChangeNodeMap_.end()) { + continue; + } + for (auto &data : it->second.datas_) { + node.datas_.emplace_back(data.key_, data.subscriberId_, data.GetData()); + } + node.ownerBundleName_ = it->second.ownerBundleName_; + } + observer->OnChange(node); +} } // namespace DataShare } // namespace OHOS diff --git a/data_share/frameworks/native/common/include/callbacks_manager.h b/data_share/frameworks/native/common/include/callbacks_manager.h index 43ddf0a999ca9ccb34cd3d869cfc06cbde436b90..7dd33229e3cbd71d749056376e97eff3a36ba822 100644 --- a/data_share/frameworks/native/common/include/callbacks_manager.h +++ b/data_share/frameworks/native/common/include/callbacks_manager.h @@ -28,6 +28,7 @@ class CallbacksManager { public: std::vector AddObservers(const std::vector &keys, void *subscriber, const std::shared_ptr observer, + std::function &, const std::shared_ptr &observer)>, std::function &, const std::shared_ptr &observer, std::vector &)>); @@ -40,6 +41,7 @@ public: CallbacksManager::DefaultProcess); std::vector EnableObservers(const std::vector &keys, void *subscriber, + std::function>> &)> processOnLocalEnabled, std::function &, std::vector &)>); std::vector DisableObservers(const std::vector &keys, void *subscriber, @@ -73,11 +75,14 @@ private: template std::vector CallbacksManager::AddObservers(const std::vector &keys, - void *subscriber, const std::shared_ptr observer, std::function &, - const std::shared_ptr &observer, std::vector &)> processOnFirstAdd) + void *subscriber, const std::shared_ptr observer, + std::function &, const std::shared_ptr &observer)> processOnLocalAdd, + std::function &, + const std::shared_ptr &observer, std::vector &)> processOnFirstAdd) { std::vector result; std::vector firstRegisterKey; + std::vector localRegisterKey; { std::lock_guard lck(mutex_); for (auto &key : keys) { @@ -87,10 +92,14 @@ std::vector CallbacksManager::AddObservers(const firstRegisterKey.emplace_back(key); continue; } + localRegisterKey.emplace_back(key); callbacks_[key].emplace_back(observer, subscriber); result.emplace_back(key, E_OK); } } + if (!localRegisterKey.empty()) { + processOnLocalAdd(localRegisterKey, observer); + } processOnFirstAdd(firstRegisterKey, observer, result); return result; } @@ -207,10 +216,12 @@ std::vector> CallbacksManager::GetEnabl template std::vector CallbacksManager::EnableObservers( const std::vector &keys, void *subscriber, + std::function>> &)> processOnLocalEnabled, std::function &, std::vector &)> processOnFirstEnabled) { std::vector result; std::vector firstRegisterKey; + std::map>> localEnabledObservers; { std::lock_guard lck(mutex_); for (auto &key : keys) { @@ -223,6 +234,7 @@ std::vector CallbacksManager::EnableObservers( bool hasEnabled = false; for (auto &item : callbacks_[key]) { if (item.subscriber_ == subscriber) { + localEnabledObservers[key].emplace_back(item.observer_); item.enabled_ = true; hasEnabled = true; } @@ -235,16 +247,20 @@ std::vector CallbacksManager::EnableObservers( result.emplace_back(key, E_OK); continue; } + localEnabledObservers.erase(key); firstRegisterKey.emplace_back(key); } } + if (!localEnabledObservers.empty()) { + processOnLocalEnabled(localEnabledObservers); + } processOnFirstEnabled(firstRegisterKey, result); return result; } template -std::vector CallbacksManager::DisableObservers( - const std::vector &keys, void *subscriber, +std::vector CallbacksManager::DisableObservers(const std::vector &keys, + void *subscriber, std::function &, std::vector &)> processOnLastDisable) { std::vector result; diff --git a/data_share/frameworks/native/common/include/distributeddata_data_share_ipc_interface_code.h b/data_share/frameworks/native/common/include/distributeddata_data_share_ipc_interface_code.h new file mode 100644 index 0000000000000000000000000000000000000000..4000bafba70836522314b07e611b2b40d25cc3e7 --- /dev/null +++ b/data_share/frameworks/native/common/include/distributeddata_data_share_ipc_interface_code.h @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* SAID:1301 */ +/* FeatureSystem: data_share_service */ +#ifndef DISTRIBUTEDDATA_DATA_SHARE_IPC_INTERFACE_H +#define DISTRIBUTEDDATA_DATA_SHARE_IPC_INTERFACE_H + +namespace OHOS::DistributedShare { +namespace DataShare { +enum class IDataShareInterfaceCode { + CMD_GET_FILE_TYPES = 1, + CMD_OPEN_FILE, + CMD_OPEN_RAW_FILE, + CMD_INSERT, + CMD_UPDATE, + CMD_DELETE, + CMD_QUERY, + CMD_GET_TYPE, + CMD_BATCH_INSERT, + CMD_REGISTER_OBSERVER, + CMD_UNREGISTER_OBSERVER, + CMD_NOTIFY_CHANGE, + CMD_NORMALIZE_URI, + CMD_DENORMALIZE_URI, + CMD_EXECUTE_BATCH, +}; + +enum class ISharedResultInterfaceCode { + FUNC_GET_ROW_COUNT, + FUNC_GET_ALL_COLUMN_NAMES, + FUNC_ON_GO, + FUNC_CLOSE, + FUNC_GET_BLOB, + FUNC_GET_STRING, + FUNC_GET_INT, + FUNC_GET_LONG, + FUNC_GET_DOUBLE, + FUNC_IS_COLUMN_NULL, + FUNC_GO_TO, + FUNC_GO_TO_ROW, + FUNC_GO_TO_FISTR_ROW, + FUNC_GO_TO_LAST_ROW, + FUNC_GO_TO_NEXT_ROW, + FUNC_GO_TO_PREV_ROW, + FUNC_IS_AT_FIRST_ROW, + FUNC_IS_AT_LAST_ROW, + FUNC_IS_STARTED_ROW, + FUNC_IS_ENDED_ROW, + FUNC_IS_CLOSED, + FUNC_GET_COLUMN_COUNT, + FUNC_GET_COLUMN_INDEX, + FUNC_GET_COLUMN_NAME, + FUNC_GET_COLUMN_TYPE, + FUNC_GET_ROW_INDEX, + FUNC_BUTT, +}; + +enum class DataShareServiceInterfaceCode { + DATA_SHARE_SERVICE_CMD_INSERT, + DATA_SHARE_SERVICE_CMD_DELETE, + DATA_SHARE_SERVICE_CMD_UPDATE, + DATA_SHARE_SERVICE_CMD_QUERY, + DATA_SHARE_SERVICE_CMD_ADD_TEMPLATE, + DATA_SHARE_SERVICE_CMD_DEL_TEMPLATE, + DATA_SHARE_SERVICE_CMD_PUBLISH, + DATA_SHARE_SERVICE_CMD_GET_DATA, + DATA_SHARE_SERVICE_CMD_SUBSCRIBE_RDB, + DATA_SHARE_SERVICE_CMD_UNSUBSCRIBE_RDB, + DATA_SHARE_SERVICE_CMD_ENABLE_SUBSCRIBE_RDB, + DATA_SHARE_SERVICE_CMD_DISABLE_SUBSCRIBE_RDB, + DATA_SHARE_SERVICE_CMD_SUBSCRIBE_PUBLISHED, + DATA_SHARE_SERVICE_CMD_UNSUBSCRIBE_PUBLISHED, + DATA_SHARE_SERVICE_CMD_ENABLE_SUBSCRIBE_PUBLISHED, + DATA_SHARE_SERVICE_CMD_DISABLE_SUBSCRIBE_PUBLISHED, + DATA_SHARE_SERVICE_CMD_NOTIFY, + DATA_SHARE_SERVICE_CMD_NOTIFY_OBSERVERS, + DATA_SHARE_SERVICE_CMD_MAX +}; + +enum class IKvStoreDataInterfaceCode { + GET_FEATURE_INTERFACE = 0 +}; +} +} // namespace OHOS + +#endif // DISTRIBUTEDDATA_DATA_SHARE_IPC_INTERFACE_H \ No newline at end of file diff --git a/data_share/frameworks/native/common/include/idata_share_service.h b/data_share/frameworks/native/common/include/idata_share_service.h index 06f84e6a72847cb441fe22f49b9d72ce7b9744b0..0f9a5b9e2fab6107da248030521a0b713bfe0072 100644 --- a/data_share/frameworks/native/common/include/idata_share_service.h +++ b/data_share/frameworks/native/common/include/idata_share_service.h @@ -26,32 +26,13 @@ #include "datashare_result_set.h" #include "datashare_template.h" #include "datashare_values_bucket.h" +#include "distributeddata_data_share_ipc_interface_code.h" #include "uri.h" namespace OHOS::DataShare { class IDataShareService : public IRemoteBroker { public: DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.DataShare.IDataShareService"); - enum { - DATA_SHARE_SERVICE_CMD_INSERT, - DATA_SHARE_SERVICE_CMD_DELETE, - DATA_SHARE_SERVICE_CMD_UPDATE, - DATA_SHARE_SERVICE_CMD_QUERY, - DATA_SHARE_SERVICE_CMD_ADD_TEMPLATE, - DATA_SHARE_SERVICE_CMD_DEL_TEMPLATE, - DATA_SHARE_SERVICE_CMD_PUBLISH, - DATA_SHARE_SERVICE_CMD_GET_DATA, - DATA_SHARE_SERVICE_CMD_SUBSCRIBE_RDB, - DATA_SHARE_SERVICE_CMD_UNSUBSCRIBE_RDB, - DATA_SHARE_SERVICE_CMD_ENABLE_SUBSCRIBE_RDB, - DATA_SHARE_SERVICE_CMD_DISABLE_SUBSCRIBE_RDB, - DATA_SHARE_SERVICE_CMD_SUBSCRIBE_PUBLISHED, - DATA_SHARE_SERVICE_CMD_UNSUBSCRIBE_PUBLISHED, - DATA_SHARE_SERVICE_CMD_ENABLE_SUBSCRIBE_PUBLISHED, - DATA_SHARE_SERVICE_CMD_DISABLE_SUBSCRIBE_PUBLISHED, - DATA_SHARE_SERVICE_CMD_NOTIFY, - DATA_SHARE_SERVICE_CMD_MAX - }; enum { DATA_SHARE_ERROR = -1, @@ -98,6 +79,8 @@ public: virtual std::vector DisableSubscribePublishedData(const std::vector &uris, int64_t subscriberId) = 0; + + virtual void Notify(const std::string &uri) = 0; }; } // namespace OHOS::DataShare #endif diff --git a/data_share/frameworks/native/common/include/idatashare.h b/data_share/frameworks/native/common/include/idatashare.h index 0e28597ac382e708d36c0b9183a304361f7ed902..11bd40f96cf1219df8c9fe4cbf94e68d32d60d26 100644 --- a/data_share/frameworks/native/common/include/idatashare.h +++ b/data_share/frameworks/native/common/include/idatashare.h @@ -22,6 +22,7 @@ #include "datashare_predicates.h" #include "datashare_result_set.h" #include "datashare_values_bucket.h" +#include "distributeddata_data_share_ipc_interface_code.h" #include "uri.h" namespace OHOS { @@ -34,24 +35,6 @@ class IDataShare : public IRemoteBroker { public: DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.DataShare.IDataShare"); - enum { - CMD_GET_FILE_TYPES = 1, - CMD_OPEN_FILE, - CMD_OPEN_RAW_FILE, - CMD_INSERT, - CMD_UPDATE, - CMD_DELETE, - CMD_QUERY, - CMD_GET_TYPE, - CMD_BATCH_INSERT, - CMD_REGISTER_OBSERVER, - CMD_UNREGISTER_OBSERVER, - CMD_NOTIFY_CHANGE, - CMD_NORMALIZE_URI, - CMD_DENORMALIZE_URI, - CMD_EXECUTE_BATCH, - }; - virtual int OpenFile(const Uri &uri, const std::string &mode) = 0; virtual int OpenRawFile(const Uri &uri, const std::string &mode) = 0; diff --git a/data_share/frameworks/native/common/include/ikvstore_data_service.h b/data_share/frameworks/native/common/include/ikvstore_data_service.h index 55b33a929d0b7ec82059ddc3ab300bfe29138cb9..4dcfc497e56b2b808f6ba3b4a0c7e7c1da678d6e 100644 --- a/data_share/frameworks/native/common/include/ikvstore_data_service.h +++ b/data_share/frameworks/native/common/include/ikvstore_data_service.h @@ -19,15 +19,12 @@ #include "iremote_broker.h" #include "iremote_proxy.h" +#include "distributeddata_data_share_ipc_interface_code.h" namespace OHOS { namespace DataShare { class IKvStoreDataService : public IRemoteBroker { public: - enum { - GET_FEATURE_INTERFACE = 0 - }; - enum { DATA_SHARE_ERROR = -1, DATA_SHARE_OK = 0, diff --git a/data_share/frameworks/native/common/include/ishared_result_set.h b/data_share/frameworks/native/common/include/ishared_result_set.h index f8d7d1d129e124ffda53aa4ad0b5d78df1671abf..ffb5c33f25cdccec6f377ee0653481416780d2a1 100644 --- a/data_share/frameworks/native/common/include/ishared_result_set.h +++ b/data_share/frameworks/native/common/include/ishared_result_set.h @@ -18,6 +18,7 @@ #include #include "iremote_broker.h" #include "datashare_result_set.h" +#include "distributeddata_data_share_ipc_interface_code.h" namespace OHOS::DataShare { class ISharedResultSet : public DataShareResultSet, public IRemoteBroker { public: @@ -26,37 +27,6 @@ public: static sptr WriteToParcel(std::shared_ptr resultSet, MessageParcel &parcel); -protected: - enum { - FUNC_GET_ROW_COUNT, - FUNC_GET_ALL_COLUMN_NAMES, - FUNC_ON_GO, - FUNC_CLOSE, - FUNC_GET_BLOB, - FUNC_GET_STRING, - FUNC_GET_INT, - FUNC_GET_LONG, - FUNC_GET_DOUBLE, - FUNC_IS_COLUMN_NULL, - FUNC_GO_TO, - FUNC_GO_TO_ROW, - FUNC_GO_TO_FISTR_ROW, - FUNC_GO_TO_LAST_ROW, - FUNC_GO_TO_NEXT_ROW, - FUNC_GO_TO_PREV_ROW, - FUNC_IS_AT_FIRST_ROW, - FUNC_IS_AT_LAST_ROW, - FUNC_IS_STARTED_ROW, - FUNC_IS_ENDED_ROW, - FUNC_IS_CLOSED, - FUNC_GET_COLUMN_COUNT, - FUNC_GET_COLUMN_INDEX, - FUNC_GET_COLUMN_NAME, - FUNC_GET_COLUMN_TYPE, - FUNC_GET_ROW_INDEX, - FUNC_BUTT - }; - private: static std::function(MessageParcel &parcel)> consumerCreator_; static std::function(std::shared_ptr, diff --git a/data_share/frameworks/native/common/include/ishared_result_set_stub.h b/data_share/frameworks/native/common/include/ishared_result_set_stub.h index 46252492785cbe8b8e42942616ef9abb90db00bb..70993a9344729634f56346575b674491675f66ea 100644 --- a/data_share/frameworks/native/common/include/ishared_result_set_stub.h +++ b/data_share/frameworks/native/common/include/ishared_result_set_stub.h @@ -23,6 +23,8 @@ #include "iremote_stub.h" namespace OHOS::DataShare { +using ResultCode = OHOS::DistributedShare::DataShare::ISharedResultInterfaceCode; + class ISharedResultSetStub : public IRemoteStub { public: explicit ISharedResultSetStub(std::shared_ptr resultSet); @@ -40,7 +42,7 @@ protected: private: using Handler = int(ISharedResultSetStub::*)(MessageParcel &request, MessageParcel &reply); std::shared_ptr resultSet_; - static constexpr Handler handlers[FUNC_BUTT] { + static constexpr Handler handlers[static_cast(ResultCode::FUNC_BUTT)] { &ISharedResultSetStub::HandleGetRowCountRequest, &ISharedResultSetStub::HandleGetAllColumnNamesRequest, &ISharedResultSetStub::HandleOnGoRequest, diff --git a/data_share/frameworks/native/common/src/ikvstore_data_service.cpp b/data_share/frameworks/native/common/src/ikvstore_data_service.cpp index 341a1f226f12abdaad098dc7547adaf4a7b83d1b..29f746ce11eec1f5b8bd3dbc3ceca6c385318c20 100644 --- a/data_share/frameworks/native/common/src/ikvstore_data_service.cpp +++ b/data_share/frameworks/native/common/src/ikvstore_data_service.cpp @@ -16,6 +16,8 @@ #include "ikvstore_data_service.h" #include "datashare_log.h" +using namespace OHOS::DistributedShare::DataShare; + namespace OHOS { namespace DataShare { DataShareKvServiceProxy::DataShareKvServiceProxy(const sptr &impl) @@ -39,7 +41,8 @@ sptr DataShareKvServiceProxy::GetFeatureInterface(const std::stri MessageParcel reply; MessageOption mo { MessageOption::TF_SYNC }; - int32_t error = Remote()->SendRequest(GET_FEATURE_INTERFACE, data, reply, mo); + int32_t error = Remote()->SendRequest( + static_cast(IKvStoreDataInterfaceCode::GET_FEATURE_INTERFACE), data, reply, mo); if (error != 0) { LOG_ERROR("SendRequest returned %{public}d", error); return nullptr; diff --git a/data_share/frameworks/native/common/src/ishared_result_set_proxy.cpp b/data_share/frameworks/native/common/src/ishared_result_set_proxy.cpp index 2df45f5e7be43f01bdf35d39db0b3a43499ed418..cedc768a193f82e5d9aa5ce3f6f62f3a014bce78 100644 --- a/data_share/frameworks/native/common/src/ishared_result_set_proxy.cpp +++ b/data_share/frameworks/native/common/src/ishared_result_set_proxy.cpp @@ -19,6 +19,8 @@ #include "datashare_log.h" #include "iremote_proxy.h" +using namespace OHOS::DistributedShare::DataShare; + namespace OHOS::DataShare { std::function(MessageParcel &parcel)> ISharedResultSet::consumerCreator_ = ISharedResultSetProxy::CreateProxy; @@ -54,7 +56,8 @@ int ISharedResultSetProxy::GetAllColumnNames(std::vector &columnNam request.WriteInterfaceToken(GetDescriptor()); MessageParcel reply; MessageOption msgOption; - int errCode = Remote()->SendRequest(FUNC_GET_ALL_COLUMN_NAMES, request, reply, msgOption); + int errCode = Remote()->SendRequest( + static_cast(ISharedResultInterfaceCode::FUNC_GET_ALL_COLUMN_NAMES), request, reply, msgOption); if (errCode != 0) { LOG_ERROR("IPC Error %{public}x", errCode); return -errCode; @@ -81,7 +84,8 @@ int ISharedResultSetProxy::GetRowCount(int &count) request.WriteInterfaceToken(GetDescriptor()); MessageParcel reply; MessageOption msgOption; - int errCode = Remote()->SendRequest(FUNC_GET_ROW_COUNT, request, reply, msgOption); + int errCode = Remote()->SendRequest( + static_cast(ISharedResultInterfaceCode::FUNC_GET_ROW_COUNT), request, reply, msgOption); if (errCode != 0) { LOG_ERROR("IPC Error %{public}x", errCode); return -errCode; @@ -105,7 +109,8 @@ bool ISharedResultSetProxy::OnGo(int oldRowIndex, int newRowIndex, int *cachedIn request.WriteInt32(newRowIndex); MessageParcel reply; MessageOption msgOption; - int errCode = Remote()->SendRequest(FUNC_ON_GO, request, reply, msgOption); + int errCode = Remote()->SendRequest( + static_cast(ISharedResultInterfaceCode::FUNC_ON_GO), request, reply, msgOption); if (errCode != 0) { LOG_ERROR("IPC Error %{public}x", errCode); return false; @@ -127,7 +132,8 @@ int ISharedResultSetProxy::Close() request.WriteInterfaceToken(GetDescriptor()); MessageParcel reply; MessageOption msgOption; - int errCode = Remote()->SendRequest(FUNC_CLOSE, request, reply, msgOption); + int errCode = Remote()->SendRequest( + static_cast(ISharedResultInterfaceCode::FUNC_CLOSE), request, reply, msgOption); if (errCode != 0) { LOG_ERROR("IPC Error %{public}x", errCode); return -errCode; diff --git a/data_share/frameworks/native/common/src/ishared_result_set_stub.cpp b/data_share/frameworks/native/common/src/ishared_result_set_stub.cpp index 722daae49a57f75d8edadc2db8612e75171e9646..6fd0020bfb5210c1889865d813b04387894746c3 100644 --- a/data_share/frameworks/native/common/src/ishared_result_set_stub.cpp +++ b/data_share/frameworks/native/common/src/ishared_result_set_stub.cpp @@ -20,7 +20,7 @@ namespace OHOS::DataShare { std::function(std::shared_ptr, MessageParcel &)> ISharedResultSet::providerCreator_ = ISharedResultSetStub::CreateStub; -constexpr ISharedResultSetStub::Handler ISharedResultSetStub::handlers[ISharedResultSet::FUNC_BUTT]; +constexpr ISharedResultSetStub::Handler ISharedResultSetStub::handlers[static_cast(ResultCode::FUNC_BUTT)]; sptr ISharedResultSetStub::CreateStub(std::shared_ptr result, OHOS::MessageParcel &parcel) @@ -56,7 +56,7 @@ int ISharedResultSetStub::OnRemoteRequest(uint32_t code, OHOS::MessageParcel &da return INVALID_FD; } - if (code >= FUNC_BUTT) { + if (code >= static_cast(ResultCode::FUNC_BUTT)) { LOG_ERROR("method code(%{public}d) out of range", code); return IPCObjectStub::OnRemoteRequest(code, data, reply, option); } diff --git a/data_share/frameworks/native/consumer/controller/common/general_controller.h b/data_share/frameworks/native/consumer/controller/common/general_controller.h index 10a8d4ee3efd14edc517f75612d34cb262bbebd0..3fac63bd825766014999c2edec8407da62be61c2 100644 --- a/data_share/frameworks/native/consumer/controller/common/general_controller.h +++ b/data_share/frameworks/native/consumer/controller/common/general_controller.h @@ -46,6 +46,8 @@ public: virtual void RegisterObserver(const Uri &uri, const sptr &dataObserver) = 0; virtual void UnregisterObserver(const Uri &uri, const sptr &dataObserver) = 0; + + virtual void NotifyChange(const Uri &uri) = 0; }; } // namespace DataShare } // namespace OHOS diff --git a/data_share/frameworks/native/consumer/controller/provider/include/ext_special_controller.h b/data_share/frameworks/native/consumer/controller/provider/include/ext_special_controller.h index 32a5ba99895238b1ba27cd3cf3708aa9bb2132f4..4c3d7a69fbdd440efd3b874eaaac876acadb2a6d 100644 --- a/data_share/frameworks/native/consumer/controller/provider/include/ext_special_controller.h +++ b/data_share/frameworks/native/consumer/controller/provider/include/ext_special_controller.h @@ -41,8 +41,6 @@ public: Uri DenormalizeUri(const Uri &uri); std::vector GetFileTypes(const Uri &uri, const std::string &mimeTypeFilter); - - void NotifyChange(const Uri &uri); private: std::shared_ptr connection_ = nullptr; diff --git a/data_share/frameworks/native/consumer/controller/provider/include/general_controller_porvider_impl.h b/data_share/frameworks/native/consumer/controller/provider/include/general_controller_porvider_impl.h index 37c12b0f22fd758c9268d904085763ae7ed5a23f..1f75d74ce09037eb87a8199879b6ec5e19506348 100644 --- a/data_share/frameworks/native/consumer/controller/provider/include/general_controller_porvider_impl.h +++ b/data_share/frameworks/native/consumer/controller/provider/include/general_controller_porvider_impl.h @@ -45,6 +45,7 @@ public: void UnregisterObserver(const Uri &uri, const sptr &dataObserver) override; + void NotifyChange(const Uri &uri) override; private: std::shared_ptr connection_ = nullptr; sptr token_ = {}; diff --git a/data_share/frameworks/native/consumer/controller/provider/src/ext_special_controller.cpp b/data_share/frameworks/native/consumer/controller/provider/src/ext_special_controller.cpp index b931115b59f73b84473b52167bfa46f3b3898e8c..3da33f951fc951f225ad0dd4a700b3e4bf93033a 100644 --- a/data_share/frameworks/native/consumer/controller/provider/src/ext_special_controller.cpp +++ b/data_share/frameworks/native/consumer/controller/provider/src/ext_special_controller.cpp @@ -124,21 +124,6 @@ std::vector ExtSpecialController::GetFileTypes(const Uri &uri, cons return proxy->GetFileTypes(uri, mimeTypeFilter); } -void ExtSpecialController::NotifyChange(const Uri &uri) -{ - auto connection = connection_; - if (connection == nullptr) { - LOG_ERROR("connection is nullptr"); - return; - } - auto proxy = connection->GetDataShareProxy(uri_, token_); - if (proxy == nullptr) { - LOG_ERROR("proxy is nullptr"); - return; - } - proxy->NotifyChange(uri); -} - ExtSpecialController::ExtSpecialController(std::shared_ptr connection, const Uri &uri, const sptr &token) : connection_(connection), token_(token), uri_(uri) diff --git a/data_share/frameworks/native/consumer/controller/provider/src/general_controller_provider_impl.cpp b/data_share/frameworks/native/consumer/controller/provider/src/general_controller_provider_impl.cpp index ea3106236d517ed6c2ecf37127d9f1c61ef2b469..ccc8fc478ed208bb90c6f9d47e16d62d03e6608f 100644 --- a/data_share/frameworks/native/consumer/controller/provider/src/general_controller_provider_impl.cpp +++ b/data_share/frameworks/native/consumer/controller/provider/src/general_controller_provider_impl.cpp @@ -114,6 +114,21 @@ void GeneralControllerProviderImpl::UnregisterObserver(const Uri &uri, proxy->UnregisterObserver(uri, dataObserver); } +void GeneralControllerProviderImpl::NotifyChange(const Uri &uri) +{ + auto connection = connection_; + if (connection == nullptr) { + LOG_ERROR("connection is nullptr"); + return; + } + auto proxy = connection->GetDataShareProxy(uri_, token_); + if (proxy == nullptr) { + LOG_ERROR("proxy is nullptr"); + return; + } + proxy->NotifyChange(uri); +} + GeneralControllerProviderImpl::GeneralControllerProviderImpl(std::shared_ptr connection, const Uri &uri, const sptr &token) : connection_(connection), token_(token), uri_(uri) { diff --git a/data_share/frameworks/native/consumer/controller/service/include/general_controller_service_impl.h b/data_share/frameworks/native/consumer/controller/service/include/general_controller_service_impl.h index bed139b87225696501e502db4885548af4f61f36..c1b65efb2b98b4f56c1696f05e3b69abef66dc01 100644 --- a/data_share/frameworks/native/consumer/controller/service/include/general_controller_service_impl.h +++ b/data_share/frameworks/native/consumer/controller/service/include/general_controller_service_impl.h @@ -43,6 +43,8 @@ public: void RegisterObserver(const Uri &uri, const sptr &dataObserver) override; void UnregisterObserver(const Uri &uri, const sptr &dataObserver) override; + + void NotifyChange(const Uri &uri) override; }; } // namespace DataShare } // namespace OHOS diff --git a/data_share/frameworks/native/consumer/controller/service/src/general_controller_service_impl.cpp b/data_share/frameworks/native/consumer/controller/service/src/general_controller_service_impl.cpp index 1163df660c466b5e066a350a70fd3e16ccbf504f..7acb6999b07c2264b36345e696127cd6288c756b 100644 --- a/data_share/frameworks/native/consumer/controller/service/src/general_controller_service_impl.cpp +++ b/data_share/frameworks/native/consumer/controller/service/src/general_controller_service_impl.cpp @@ -90,5 +90,15 @@ void GeneralControllerServiceImpl::UnregisterObserver(const Uri &uri, LOG_ERROR("UnregisterObserver failed"); } } + +void GeneralControllerServiceImpl::NotifyChange(const Uri &uri) +{ + auto proxy = DataShareManagerImpl::GetInstance().GetServiceProxy(); + if (proxy == nullptr) { + LOG_ERROR("proxy is nullptr"); + return; + } + proxy->Notify(uri.ToString()); +} } // namespace DataShare } // namespace OHOS \ No newline at end of file diff --git a/data_share/frameworks/native/consumer/src/datashare_helper_impl.cpp b/data_share/frameworks/native/consumer/src/datashare_helper_impl.cpp index f845c62704d9de39c0924481f34189d51aa3efd8..5f7a8696e3575a36c03045046eab3bcfd936e086 100644 --- a/data_share/frameworks/native/consumer/src/datashare_helper_impl.cpp +++ b/data_share/frameworks/native/consumer/src/datashare_helper_impl.cpp @@ -185,12 +185,12 @@ void DataShareHelperImpl::UnregisterObserver(const Uri &uri, const sptrNotifyChange(uri); + return generalCtl->NotifyChange(uri); } Uri DataShareHelperImpl::NormalizeUri(Uri &uri) diff --git a/data_share/frameworks/native/consumer/src/datashare_proxy.cpp b/data_share/frameworks/native/consumer/src/datashare_proxy.cpp index 157f6119072f498bf83c174c988194badb2aa381..b0819336d9e32008ec587fe944f0396021b4a442 100644 --- a/data_share/frameworks/native/consumer/src/datashare_proxy.cpp +++ b/data_share/frameworks/native/consumer/src/datashare_proxy.cpp @@ -25,6 +25,8 @@ #include "ishared_result_set.h" #include "pac_map.h" +using namespace OHOS::DistributedShare::DataShare; + namespace OHOS { namespace DataShare { constexpr int32_t PERMISSION_ERR = 1; @@ -52,7 +54,8 @@ std::vector DataShareProxy::GetFileTypes(const Uri &uri, const std: return types; } - int32_t err = Remote()->SendRequest(CMD_GET_FILE_TYPES, data, reply, option); + int32_t err = Remote()->SendRequest( + static_cast(IDataShareInterfaceCode::CMD_GET_FILE_TYPES), data, reply, option); if (err != DATA_SHARE_NO_ERROR) { LOG_ERROR("GetFileTypes fail to SendRequest. err: %{public}d", err); } @@ -85,7 +88,8 @@ int DataShareProxy::OpenFile(const Uri &uri, const std::string &mode) MessageParcel reply; MessageOption option; - int32_t err = Remote()->SendRequest(CMD_OPEN_FILE, data, reply, option); + int32_t err = Remote()->SendRequest( + static_cast(IDataShareInterfaceCode::CMD_OPEN_FILE), data, reply, option); if (err != DATA_SHARE_NO_ERROR) { LOG_ERROR("OpenFile fail to SendRequest. err: %{public}d", err); return fd; @@ -121,7 +125,8 @@ int DataShareProxy::OpenRawFile(const Uri &uri, const std::string &mode) MessageParcel reply; MessageOption option; - int32_t err = Remote()->SendRequest(CMD_OPEN_RAW_FILE, data, reply, option); + int32_t err = Remote()->SendRequest( + static_cast(IDataShareInterfaceCode::CMD_OPEN_RAW_FILE), data, reply, option); if (err != DATA_SHARE_NO_ERROR) { LOG_ERROR("OpenRawFile fail to SendRequest. err: %{public}d", err); return fd; @@ -149,7 +154,8 @@ int DataShareProxy::Insert(const Uri &uri, const DataShareValuesBucket &value) } MessageParcel reply; MessageOption option; - int32_t err = Remote()->SendRequest(CMD_INSERT, data, reply, option); + int32_t err = Remote()->SendRequest( + static_cast(IDataShareInterfaceCode::CMD_INSERT), data, reply, option); if (err != DATA_SHARE_NO_ERROR) { LOG_ERROR("Insert fail to SendRequest. err: %{public}d", err); return err == PERMISSION_ERR ? PERMISSION_ERR_CODE : index; @@ -162,8 +168,7 @@ int DataShareProxy::Insert(const Uri &uri, const DataShareValuesBucket &value) return index; } -int DataShareProxy::Update(const Uri &uri, const DataSharePredicates &predicates, - const DataShareValuesBucket &value) +int DataShareProxy::Update(const Uri &uri, const DataSharePredicates &predicates, const DataShareValuesBucket &value) { int index = -1; MessageParcel data; @@ -177,7 +182,8 @@ int DataShareProxy::Update(const Uri &uri, const DataSharePredicates &predicates } MessageParcel reply; MessageOption option; - int32_t err = Remote()->SendRequest(CMD_UPDATE, data, reply, option); + int32_t err = Remote()->SendRequest( + static_cast(IDataShareInterfaceCode::CMD_UPDATE), data, reply, option); if (err != DATA_SHARE_NO_ERROR) { LOG_ERROR("Update fail to SendRequest. err: %{public}d", err); return err == PERMISSION_ERR ? PERMISSION_ERR_CODE : index; @@ -204,7 +210,8 @@ int DataShareProxy::Delete(const Uri &uri, const DataSharePredicates &predicates MessageParcel reply; MessageOption option; - int32_t err = Remote()->SendRequest(CMD_DELETE, data, reply, option); + int32_t err = Remote()->SendRequest( + static_cast(IDataShareInterfaceCode::CMD_DELETE), data, reply, option); if (err != DATA_SHARE_NO_ERROR) { LOG_ERROR("Delete fail to SendRequest. err: %{public}d", err); return err == PERMISSION_ERR ? PERMISSION_ERR_CODE : index; @@ -216,8 +223,8 @@ int DataShareProxy::Delete(const Uri &uri, const DataSharePredicates &predicates return index; } -std::shared_ptr DataShareProxy::Query(const Uri &uri, - const DataSharePredicates &predicates, std::vector &columns, DatashareBusinessError &businessError) +std::shared_ptr DataShareProxy::Query(const Uri &uri, const DataSharePredicates &predicates, + std::vector &columns, DatashareBusinessError &businessError) { MessageParcel data; if (!data.WriteInterfaceToken(DataShareProxy::GetDescriptor())) { @@ -230,7 +237,8 @@ std::shared_ptr DataShareProxy::Query(const Uri &uri, } MessageParcel reply; MessageOption option; - int32_t err = Remote()->SendRequest(CMD_QUERY, data, reply, option); + int32_t err = Remote()->SendRequest( + static_cast(IDataShareInterfaceCode::CMD_QUERY), data, reply, option); auto result = ISharedResultSet::ReadFromParcel(reply); businessError.SetCode(reply.ReadInt32()); businessError.SetMessage(reply.ReadString()); @@ -258,7 +266,8 @@ std::string DataShareProxy::GetType(const Uri &uri) MessageParcel reply; MessageOption option; - int32_t err = Remote()->SendRequest(CMD_GET_TYPE, data, reply, option); + int32_t err = Remote()->SendRequest( + static_cast(IDataShareInterfaceCode::CMD_GET_TYPE), data, reply, option); if (err != DATA_SHARE_NO_ERROR) { LOG_ERROR("GetFileTypes fail to SendRequest. err: %{public}d", err); return type; @@ -292,7 +301,8 @@ int DataShareProxy::BatchInsert(const Uri &uri, const std::vectorSendRequest(CMD_BATCH_INSERT, data, reply, option); + int32_t err = Remote()->SendRequest( + static_cast(IDataShareInterfaceCode::CMD_BATCH_INSERT), data, reply, option); if (err != DATA_SHARE_NO_ERROR) { LOG_ERROR("fail to SendRequest. err: %{public}d", err); return err == PERMISSION_ERR ? PERMISSION_ERR_CODE : ret; @@ -321,7 +331,8 @@ bool DataShareProxy::RegisterObserver(const Uri &uri, const sptrSendRequest(CMD_REGISTER_OBSERVER, data, reply, option); + int32_t result = Remote()->SendRequest( + static_cast(IDataShareInterfaceCode::CMD_REGISTER_OBSERVER), data, reply, option); if (result == ERR_NONE) { LOG_INFO("SendRequest ok, retval is %{public}d", reply.ReadInt32()); } else { @@ -347,7 +358,8 @@ bool DataShareProxy::UnregisterObserver(const Uri &uri, const sptrSendRequest(CMD_UNREGISTER_OBSERVER, data, reply, option); + int32_t result = Remote()->SendRequest( + static_cast(IDataShareInterfaceCode::CMD_UNREGISTER_OBSERVER), data, reply, option); if (result == ERR_NONE) { LOG_INFO("SendRequest ok, retval is %{public}d", reply.ReadInt32()); } else { @@ -373,7 +385,8 @@ bool DataShareProxy::NotifyChange(const Uri &uri) MessageParcel reply; MessageOption option; - int32_t result = Remote()->SendRequest(CMD_NOTIFY_CHANGE, data, reply, option); + int32_t result = Remote()->SendRequest( + static_cast(IDataShareInterfaceCode::CMD_NOTIFY_CHANGE), data, reply, option); if (result == ERR_NONE) { LOG_INFO("SendRequest ok, retval is %{public}d", reply.ReadInt32()); } else { @@ -399,7 +412,8 @@ Uri DataShareProxy::NormalizeUri(const Uri &uri) MessageParcel reply; MessageOption option; - int32_t err = Remote()->SendRequest(CMD_NORMALIZE_URI, data, reply, option); + int32_t err = Remote()->SendRequest( + static_cast(IDataShareInterfaceCode::CMD_NORMALIZE_URI), data, reply, option); if (err != DATA_SHARE_NO_ERROR) { LOG_ERROR("NormalizeUri fail to SendRequest. err: %{public}d", err); return Uri(""); @@ -429,7 +443,8 @@ Uri DataShareProxy::DenormalizeUri(const Uri &uri) MessageParcel reply; MessageOption option; - int32_t err = Remote()->SendRequest(CMD_DENORMALIZE_URI, data, reply, option); + int32_t err = Remote()->SendRequest( + static_cast(IDataShareInterfaceCode::CMD_DENORMALIZE_URI), data, reply, option); if (err != DATA_SHARE_NO_ERROR) { LOG_ERROR("DenormalizeUri fail to SendRequest. err: %{public}d", err); return Uri(""); @@ -444,4 +459,4 @@ Uri DataShareProxy::DenormalizeUri(const Uri &uri) return info; } } // namespace DataShare -} // namespace OHOS \ No newline at end of file +} // namespace OHOS diff --git a/data_share/frameworks/native/provider/src/datashare_stub.cpp b/data_share/frameworks/native/provider/src/datashare_stub.cpp index 03ff16b1b805973c04ce1c1770b45d11294989fb..019359dceba541336f4a1a3ffb3b52fc33e0f90b 100644 --- a/data_share/frameworks/native/provider/src/datashare_stub.cpp +++ b/data_share/frameworks/native/provider/src/datashare_stub.cpp @@ -22,26 +22,31 @@ #include "ishared_result_set.h" #include "unistd.h" +using namespace OHOS::DistributedShare::DataShare; + namespace OHOS { namespace DataShare { constexpr int DEFAULT_NUMBER = -1; constexpr int PERMISSION_ERROR_NUMBER = -2; DataShareStub::DataShareStub() { - stubFuncMap_[CMD_GET_FILE_TYPES] = &DataShareStub::CmdGetFileTypes; - stubFuncMap_[CMD_OPEN_FILE] = &DataShareStub::CmdOpenFile; - stubFuncMap_[CMD_OPEN_RAW_FILE] = &DataShareStub::CmdOpenRawFile; - stubFuncMap_[CMD_INSERT] = &DataShareStub::CmdInsert; - stubFuncMap_[CMD_UPDATE] = &DataShareStub::CmdUpdate; - stubFuncMap_[CMD_DELETE] = &DataShareStub::CmdDelete; - stubFuncMap_[CMD_QUERY] = &DataShareStub::CmdQuery; - stubFuncMap_[CMD_GET_TYPE] = &DataShareStub::CmdGetType; - stubFuncMap_[CMD_BATCH_INSERT] = &DataShareStub::CmdBatchInsert; - stubFuncMap_[CMD_REGISTER_OBSERVER] = &DataShareStub::CmdRegisterObserver; - stubFuncMap_[CMD_UNREGISTER_OBSERVER] = &DataShareStub::CmdUnregisterObserver; - stubFuncMap_[CMD_NOTIFY_CHANGE] = &DataShareStub::CmdNotifyChange; - stubFuncMap_[CMD_NORMALIZE_URI] = &DataShareStub::CmdNormalizeUri; - stubFuncMap_[CMD_DENORMALIZE_URI] = &DataShareStub::CmdDenormalizeUri; + stubFuncMap_[static_cast(IDataShareInterfaceCode::CMD_GET_FILE_TYPES)] = &DataShareStub::CmdGetFileTypes; + stubFuncMap_[static_cast(IDataShareInterfaceCode::CMD_OPEN_FILE)] = &DataShareStub::CmdOpenFile; + stubFuncMap_[static_cast(IDataShareInterfaceCode::CMD_OPEN_RAW_FILE)] = &DataShareStub::CmdOpenRawFile; + stubFuncMap_[static_cast(IDataShareInterfaceCode::CMD_INSERT)] = &DataShareStub::CmdInsert; + stubFuncMap_[static_cast(IDataShareInterfaceCode::CMD_UPDATE)] = &DataShareStub::CmdUpdate; + stubFuncMap_[static_cast(IDataShareInterfaceCode::CMD_DELETE)] = &DataShareStub::CmdDelete; + stubFuncMap_[static_cast(IDataShareInterfaceCode::CMD_QUERY)] = &DataShareStub::CmdQuery; + stubFuncMap_[static_cast(IDataShareInterfaceCode::CMD_GET_TYPE)] = &DataShareStub::CmdGetType; + stubFuncMap_[static_cast(IDataShareInterfaceCode::CMD_BATCH_INSERT)] = &DataShareStub::CmdBatchInsert; + stubFuncMap_[static_cast(IDataShareInterfaceCode::CMD_REGISTER_OBSERVER)] = + &DataShareStub::CmdRegisterObserver; + stubFuncMap_[static_cast(IDataShareInterfaceCode::CMD_UNREGISTER_OBSERVER)] = + &DataShareStub::CmdUnregisterObserver; + stubFuncMap_[static_cast(IDataShareInterfaceCode::CMD_NOTIFY_CHANGE)] = &DataShareStub::CmdNotifyChange; + stubFuncMap_[static_cast(IDataShareInterfaceCode::CMD_NORMALIZE_URI)] = &DataShareStub::CmdNormalizeUri; + stubFuncMap_[static_cast(IDataShareInterfaceCode::CMD_DENORMALIZE_URI)] = + &DataShareStub::CmdDenormalizeUri; } DataShareStub::~DataShareStub() diff --git a/data_share/frameworks/native/provider/src/js_datashare_ext_ability.cpp b/data_share/frameworks/native/provider/src/js_datashare_ext_ability.cpp index 7e95f7063a3ad5f9d2df50b7718edd99b12e9b45..de48819b22153d98c82ed307e7cc519b659ef316 100644 --- a/data_share/frameworks/native/provider/src/js_datashare_ext_ability.cpp +++ b/data_share/frameworks/native/provider/src/js_datashare_ext_ability.cpp @@ -32,6 +32,8 @@ #include "napi_remote_object.h" #include "system_ability_definition.h" +using namespace OHOS::DistributedShare::DataShare; + namespace OHOS { namespace DataShare { using namespace AbilityRuntime; @@ -882,7 +884,8 @@ void JsDataShareExtAbility::NotifyToDataShareService() LOG_ERROR("Write descriptor failed!"); return; } - remote->SendRequest(IDataShareService::DATA_SHARE_SERVICE_CMD_NOTIFY, data, reply, option); + remote->SendRequest( + static_cast(DataShareServiceInterfaceCode::DATA_SHARE_SERVICE_CMD_NOTIFY), data, reply, option); } bool MakeNapiColumn(napi_env env, napi_value &napiColumns, const std::vector &columns) diff --git a/data_share/frameworks/native/proxy/include/data_share_service_proxy.h b/data_share/frameworks/native/proxy/include/data_share_service_proxy.h index 413405039691d757fd8081579ee0adf9bc015cf0..23690e910ec60a0c8beca302c1484e1064add55a 100644 --- a/data_share/frameworks/native/proxy/include/data_share_service_proxy.h +++ b/data_share/frameworks/native/proxy/include/data_share_service_proxy.h @@ -67,6 +67,7 @@ public: std::vector DisableSubscribePublishedData( const std::vector &uris, int64_t subscriberId) override; + void Notify(const std::string &uri) override; private: static inline BrokerDelegator delegator_; diff --git a/data_share/frameworks/native/proxy/include/published_data_subscriber_manager.h b/data_share/frameworks/native/proxy/include/published_data_subscriber_manager.h index d24f11f7d2c4df6586e2eac7a796f076dd845b66..a5db17c4aaefb46872bc35c2f366c22e594c84fc 100644 --- a/data_share/frameworks/native/proxy/include/published_data_subscriber_manager.h +++ b/data_share/frameworks/native/proxy/include/published_data_subscriber_manager.h @@ -92,10 +92,13 @@ public: void Emit(PublishedDataChangeNode &changeNode); private: + void Emit(const std::vector &keys, const std::shared_ptr &observer); + void Emit(std::map>> &obsMap); PublishedDataSubscriberManager(); bool Init(); void Destroy(); sptr serviceCallback_; + std::map lastChangeNodeMap_; }; } // namespace DataShare } // namespace OHOS diff --git a/data_share/frameworks/native/proxy/include/rdb_subscriber_manager.h b/data_share/frameworks/native/proxy/include/rdb_subscriber_manager.h index 47462d0994ecac81f642e149692d766fbf826a7a..45e296c5183de773a264377744974c02eea1face 100644 --- a/data_share/frameworks/native/proxy/include/rdb_subscriber_manager.h +++ b/data_share/frameworks/native/proxy/include/rdb_subscriber_manager.h @@ -93,10 +93,13 @@ public: void Emit(const RdbChangeNode &changeNode); private: + void Emit(const std::vector &keys, const std::shared_ptr &observer); + void Emit(std::map>> &obsMap); RdbSubscriberManager(); bool Init(); void Destroy(); sptr serviceCallback_; + std::map lastChangeNodeMap_; }; } // namespace DataShare } // namespace OHOS diff --git a/data_share/frameworks/native/proxy/src/data_share_service_proxy.cpp b/data_share/frameworks/native/proxy/src/data_share_service_proxy.cpp index 2f87464077ae03f86a2c59e774edd1ee488f74c9..ef0ddd8a25a8986fd91a2e813b8f352246d3376f 100644 --- a/data_share/frameworks/native/proxy/src/data_share_service_proxy.cpp +++ b/data_share/frameworks/native/proxy/src/data_share_service_proxy.cpp @@ -21,6 +21,8 @@ namespace OHOS { namespace DataShare { +using InterfaceCode = OHOS::DistributedShare::DataShare::DataShareServiceInterfaceCode; + DataShareServiceProxy::DataShareServiceProxy(const sptr &object) : IRemoteProxy(object) { @@ -42,7 +44,8 @@ int32_t DataShareServiceProxy::Insert(const Uri &uri, const DataShareValuesBucke MessageParcel reply; MessageOption option; - int32_t err = Remote()->SendRequest(DATA_SHARE_SERVICE_CMD_INSERT, data, reply, option); + int32_t err = Remote()->SendRequest( + static_cast(InterfaceCode::DATA_SHARE_SERVICE_CMD_INSERT), data, reply, option); if (err != NO_ERROR) { LOG_ERROR("Insert fail to SendRequest. uri: %{public}s, err: %{public}d", uriStr.c_str(), err); return DATA_SHARE_ERROR; @@ -66,7 +69,8 @@ int32_t DataShareServiceProxy::Update(const Uri &uri, MessageParcel reply; MessageOption option; - int32_t err = Remote()->SendRequest(DATA_SHARE_SERVICE_CMD_UPDATE, data, reply, option); + int32_t err = Remote()->SendRequest( + static_cast(InterfaceCode::DATA_SHARE_SERVICE_CMD_UPDATE), data, reply, option); if (err != NO_ERROR) { LOG_ERROR("Update fail to SendRequest. uri: %{public}s, err: %{public}d", uriStr.c_str(), err); return DATA_SHARE_ERROR; @@ -89,7 +93,8 @@ int32_t DataShareServiceProxy::Delete(const Uri &uri, const DataSharePredicates MessageParcel reply; MessageOption option; - int32_t err = Remote()->SendRequest(DATA_SHARE_SERVICE_CMD_DELETE, data, reply, option); + int32_t err = Remote()->SendRequest( + static_cast(InterfaceCode::DATA_SHARE_SERVICE_CMD_DELETE), data, reply, option); if (err != NO_ERROR) { LOG_ERROR("Delete fail to SendRequest. uri: %{public}s, err: %{public}d", uriStr.c_str(), err); return DATA_SHARE_ERROR; @@ -114,7 +119,8 @@ std::shared_ptr DataShareServiceProxy::Query(const Uri &uri, MessageParcel reply; MessageOption option; - int32_t err = Remote()->SendRequest(DATA_SHARE_SERVICE_CMD_QUERY, data, reply, option); + int32_t err = Remote()->SendRequest( + static_cast(InterfaceCode::DATA_SHARE_SERVICE_CMD_QUERY), data, reply, option); auto result = ISharedResultSet::ReadFromParcel(reply); businessError.SetCode(reply.ReadInt32()); @@ -139,7 +145,8 @@ int DataShareServiceProxy::AddQueryTemplate(const std::string &uri, int64_t subs MessageParcel reply; MessageOption option; - int32_t err = Remote()->SendRequest(DATA_SHARE_SERVICE_CMD_ADD_TEMPLATE, data, reply, option); + int32_t err = Remote()->SendRequest( + static_cast(InterfaceCode::DATA_SHARE_SERVICE_CMD_ADD_TEMPLATE), data, reply, option); if (err != NO_ERROR) { LOG_ERROR("AddTemplate fail to SendRequest. uri: %{public}s, err: %{public}d", uri.c_str(), err); return DATA_SHARE_ERROR; @@ -161,7 +168,8 @@ int DataShareServiceProxy::DelQueryTemplate(const std::string &uri, int64_t subs MessageParcel reply; MessageOption option; - int32_t err = Remote()->SendRequest(DATA_SHARE_SERVICE_CMD_DEL_TEMPLATE, data, reply, option); + int32_t err = Remote()->SendRequest( + static_cast(InterfaceCode::DATA_SHARE_SERVICE_CMD_DEL_TEMPLATE), data, reply, option); if (err != NO_ERROR) { LOG_ERROR("AddTemplate fail to SendRequest. uri: %{public}s, err: %{public}d", uri.c_str(), err); return DATA_SHARE_ERROR; @@ -184,7 +192,8 @@ std::vector DataShareServiceProxy::Publish(const Data &data, co MessageParcel reply; MessageOption option; - int32_t err = Remote()->SendRequest(DATA_SHARE_SERVICE_CMD_PUBLISH, parcel, reply, option); + int32_t err = Remote()->SendRequest( + static_cast(InterfaceCode::DATA_SHARE_SERVICE_CMD_PUBLISH), parcel, reply, option); if (err != NO_ERROR) { LOG_ERROR("Publish fail to SendRequest. err: %{public}d", err); return results; @@ -209,7 +218,8 @@ Data DataShareServiceProxy::GetPublishedData(const std::string &bundleName, int MessageParcel reply; MessageOption option; - int32_t err = Remote()->SendRequest(DATA_SHARE_SERVICE_CMD_GET_DATA, data, reply, option); + int32_t err = Remote()->SendRequest( + static_cast(InterfaceCode::DATA_SHARE_SERVICE_CMD_GET_DATA), data, reply, option); if (err != NO_ERROR) { LOG_ERROR("AddTemplate fail to SendRequest, err: %{public}d", err); return results; @@ -239,7 +249,8 @@ std::vector DataShareServiceProxy::SubscribeRdbData(const std:: MessageParcel reply; MessageOption option; - int32_t err = Remote()->SendRequest(DATA_SHARE_SERVICE_CMD_SUBSCRIBE_RDB, data, reply, option); + int32_t err = Remote()->SendRequest( + static_cast(InterfaceCode::DATA_SHARE_SERVICE_CMD_SUBSCRIBE_RDB), data, reply, option); if (err != NO_ERROR) { LOG_ERROR("SubscribeRdbData fail to SendRequest. err: %{public}d", err); return results; @@ -265,7 +276,8 @@ std::vector DataShareServiceProxy::UnSubscribeRdbData( MessageParcel reply; MessageOption option; - int32_t err = Remote()->SendRequest(DATA_SHARE_SERVICE_CMD_UNSUBSCRIBE_RDB, data, reply, option); + int32_t err = Remote()->SendRequest( + static_cast(InterfaceCode::DATA_SHARE_SERVICE_CMD_UNSUBSCRIBE_RDB), data, reply, option); if (err != NO_ERROR) { LOG_ERROR("fail to SendRequest. err: %{public}d", err); return results; @@ -291,7 +303,8 @@ std::vector DataShareServiceProxy::EnableSubscribeRdbData( MessageParcel reply; MessageOption option; - int32_t err = Remote()->SendRequest(DATA_SHARE_SERVICE_CMD_ENABLE_SUBSCRIBE_RDB, data, reply, option); + int32_t err = Remote()->SendRequest( + static_cast(InterfaceCode::DATA_SHARE_SERVICE_CMD_ENABLE_SUBSCRIBE_RDB), data, reply, option); if (err != NO_ERROR) { LOG_ERROR("fail to SendRequest. err: %{public}d", err); return results; @@ -317,7 +330,8 @@ std::vector DataShareServiceProxy::DisableSubscribeRdbData( MessageParcel reply; MessageOption option; - int32_t err = Remote()->SendRequest(DATA_SHARE_SERVICE_CMD_DISABLE_SUBSCRIBE_RDB, data, reply, option); + int32_t err = Remote()->SendRequest( + static_cast(InterfaceCode::DATA_SHARE_SERVICE_CMD_DISABLE_SUBSCRIBE_RDB), data, reply, option); if (err != NO_ERROR) { LOG_ERROR("AddTemplate fail to SendRequest. err: %{public}d", err); return results; @@ -346,7 +360,8 @@ std::vector DataShareServiceProxy::SubscribePublishedData( MessageParcel reply; MessageOption option; - int32_t err = Remote()->SendRequest(DATA_SHARE_SERVICE_CMD_SUBSCRIBE_PUBLISHED, data, reply, option); + int32_t err = Remote()->SendRequest( + static_cast(InterfaceCode::DATA_SHARE_SERVICE_CMD_SUBSCRIBE_PUBLISHED), data, reply, option); if (err != NO_ERROR) { LOG_ERROR("AddTemplate fail to SendRequest. err: %{public}d", err); return results; @@ -371,7 +386,8 @@ std::vector DataShareServiceProxy::UnSubscribePublishedData( MessageParcel reply; MessageOption option; - int32_t err = Remote()->SendRequest(DATA_SHARE_SERVICE_CMD_UNSUBSCRIBE_PUBLISHED, data, reply, option); + int32_t err = Remote()->SendRequest( + static_cast(InterfaceCode::DATA_SHARE_SERVICE_CMD_UNSUBSCRIBE_PUBLISHED), data, reply, option); if (err != NO_ERROR) { LOG_ERROR("AddTemplate fail to SendRequest. err: %{public}d", err); return results; @@ -396,7 +412,8 @@ std::vector DataShareServiceProxy::EnableSubscribePublishedData MessageParcel reply; MessageOption option; - int32_t err = Remote()->SendRequest(DATA_SHARE_SERVICE_CMD_ENABLE_SUBSCRIBE_PUBLISHED, data, reply, option); + int32_t err = Remote()->SendRequest( + static_cast(InterfaceCode::DATA_SHARE_SERVICE_CMD_ENABLE_SUBSCRIBE_PUBLISHED), data, reply, option); if (err != NO_ERROR) { LOG_ERROR("AddTemplate fail to SendRequest. err: %{public}d", err); return results; @@ -421,7 +438,8 @@ std::vector DataShareServiceProxy::DisableSubscribePublishedDat MessageParcel reply; MessageOption option; - int32_t err = Remote()->SendRequest(DATA_SHARE_SERVICE_CMD_DISABLE_SUBSCRIBE_PUBLISHED, data, reply, option); + int32_t err = Remote()->SendRequest( + static_cast(InterfaceCode::DATA_SHARE_SERVICE_CMD_DISABLE_SUBSCRIBE_PUBLISHED), data, reply, option); if (err != NO_ERROR) { LOG_ERROR("AddTemplate fail to SendRequest. err: %{public}d", err); return results; @@ -429,5 +447,27 @@ std::vector DataShareServiceProxy::DisableSubscribePublishedDat ITypesUtil::Unmarshal(reply, results); return results; } + +void DataShareServiceProxy::Notify(const std::string &uri) +{ + MessageParcel data; + if (!data.WriteInterfaceToken(IDataShareService::GetDescriptor())) { + LOG_ERROR("Write descriptor failed!"); + return; + } + if (!ITypesUtil::Marshal(data, uri)) { + LOG_ERROR("Write to message parcel failed!"); + return; + } + + MessageParcel reply; + MessageOption option; + int32_t err = Remote()->SendRequest( + static_cast(InterfaceCode::DATA_SHARE_SERVICE_CMD_NOTIFY_OBSERVERS), data, reply, option); + if (err != NO_ERROR) { + LOG_ERROR("Notify fail to SendRequest. err: %{public}d", err); + return; + } +} } // namespace DataShare } // namespace OHOS diff --git a/data_share/frameworks/native/proxy/src/published_data_subscriber_manager.cpp b/data_share/frameworks/native/proxy/src/published_data_subscriber_manager.cpp index 59f75d18f88b4e36a713983d76539d2fb565c855..01a49f2e09b4b7de14ee73214641c3d6d1a408d2 100644 --- a/data_share/frameworks/native/proxy/src/published_data_subscriber_manager.cpp +++ b/data_share/frameworks/native/proxy/src/published_data_subscriber_manager.cpp @@ -32,7 +32,11 @@ std::vector PublishedDataSubscriberManager::AddObservers(void * std::for_each(uris.begin(), uris.end(), [&keys, &subscriberId](auto &uri) { keys.emplace_back(uri, subscriberId); }); - return BaseCallbacks::AddObservers(keys, subscriber, std::make_shared(callback), + return BaseCallbacks::AddObservers( + keys, subscriber, std::make_shared(callback), + [this](const std::vector &localRegisterKeys, const std::shared_ptr observer) { + Emit(localRegisterKeys, observer); + }, [&proxy, subscriber, &subscriberId, this](const std::vector &firstAddKeys, const std::shared_ptr observer, std::vector &opResult) { std::vector firstAddUris; @@ -72,6 +76,7 @@ std::vector PublishedDataSubscriberManager::DelObservers(void * // delete all obs by subscriber std::map> keysMap; for (auto const &key : lastDelKeys) { + lastChangeNodeMap_.erase(key); keysMap[key.subscriberId_].emplace_back(key.uri_); } for (auto const &[subscriberId, uris] : keysMap) { @@ -100,7 +105,8 @@ std::vector PublishedDataSubscriberManager::DelObservers(void * return BaseCallbacks::DelObservers(keys, subscriber, [&proxy, &subscriberId, this](const std::vector &lastDelKeys, std::vector &opResult) { std::vector lastDelUris; - std::for_each(lastDelKeys.begin(), lastDelKeys.end(), [&lastDelUris](auto &result) { + std::for_each(lastDelKeys.begin(), lastDelKeys.end(), [&lastDelUris, this](auto &result) { + lastChangeNodeMap_.erase(result); lastDelUris.emplace_back(result); }); if (lastDelUris.empty()) { @@ -127,7 +133,10 @@ std::vector PublishedDataSubscriberManager::EnableObservers(voi std::for_each(uris.begin(), uris.end(), [&keys, &subscriberId](auto &uri) { keys.emplace_back(uri, subscriberId); }); - return BaseCallbacks::EnableObservers(keys, subscriber, + return BaseCallbacks::EnableObservers( + keys, subscriber, [this](std::map>> &obsMap) { + Emit(obsMap); + }, [&proxy, &subscriberId, subscriber, this](const std::vector &firstAddKeys, std::vector &opResult) { std::vector firstAddUris; @@ -204,6 +213,10 @@ void PublishedDataSubscriberManager::RecoverObservers(std::shared_ptr, PublishedDataChangeNode> results; for (auto &data : changeNode.datas_) { PublishedObserverMapKey key(data.key_, data.subscriberId_); @@ -212,6 +225,8 @@ void PublishedDataSubscriberManager::Emit(PublishedDataChangeNode &changeNode) LOG_WARN("%{private}s nobody subscribe, but still notify", data.key_.c_str()); continue; } + lastChangeNodeMap_[key].datas_.emplace_back(data.key_, data.subscriberId_, data.GetData()); + lastChangeNodeMap_[key].ownerBundleName_ = changeNode.ownerBundleName_; for (auto const &obs : callbacks) { results[obs].datas_.emplace_back(data.key_, data.subscriberId_, data.GetData()); } @@ -222,6 +237,43 @@ void PublishedDataSubscriberManager::Emit(PublishedDataChangeNode &changeNode) } } +void PublishedDataSubscriberManager::Emit(const std::vector &keys, const std::shared_ptr &observer) +{ + PublishedDataChangeNode node; + for (auto &key : keys) { + auto it = lastChangeNodeMap_.find(key); + if (it == lastChangeNodeMap_.end()) { + continue; + } + for (auto &data : it->second.datas_) { + node.datas_.emplace_back(data.key_, data.subscriberId_, data.GetData()); + } + node.ownerBundleName_ = it->second.ownerBundleName_; + } + observer->OnChange(node); +} + +void PublishedDataSubscriberManager::Emit(std::map>> &obsMap) +{ + std::map, PublishedDataChangeNode> results; + for (auto &[key, obsVector] : obsMap) { + auto it = lastChangeNodeMap_.find(key); + if (it == lastChangeNodeMap_.end()) { + continue; + } + for (auto &data : it->second.datas_) { + PublishedObserverMapKey mapKey(data.key_, data.subscriberId_); + for (auto &obs : obsVector) { + results[obs].datas_.emplace_back(data.key_, data.subscriberId_, data.GetData()); + results[obs].ownerBundleName_ = it->second.ownerBundleName_; + } + } + } + for (auto &[callback, node] : results) { + callback->OnChange(node); + } +} + bool PublishedDataSubscriberManager::Init() { if (serviceCallback_ == nullptr) { diff --git a/data_share/frameworks/native/proxy/src/rdb_subscriber_manager.cpp b/data_share/frameworks/native/proxy/src/rdb_subscriber_manager.cpp index 6ffb4208791c070cc8949bb7ac64071e9ad2100d..88692dc0c2fc1af9cd45d75fe02b145064b5531e 100644 --- a/data_share/frameworks/native/proxy/src/rdb_subscriber_manager.cpp +++ b/data_share/frameworks/native/proxy/src/rdb_subscriber_manager.cpp @@ -43,7 +43,11 @@ std::vector RdbSubscriberManager::AddObservers(void *subscriber std::for_each(uris.begin(), uris.end(), [&keys, &templateId](auto &uri) { keys.emplace_back(uri, templateId); }); - return BaseCallbacks::AddObservers(keys, subscriber, std::make_shared(callback), + return BaseCallbacks::AddObservers( + keys, subscriber, std::make_shared(callback), + [this](const std::vector &localRegisterKeys, const std::shared_ptr observer) { + Emit(localRegisterKeys, observer); + }, [&proxy, subscriber, &templateId, this](const std::vector &firstAddKeys, const std::shared_ptr observer, std::vector &opResult) { std::vector firstAddUris; @@ -89,8 +93,9 @@ std::vector RdbSubscriberManager::DelObservers(void *subscriber return BaseCallbacks::DelObservers(keys, subscriber, [&proxy, &templateId, this](const std::vector &lastDelKeys, std::vector &opResult) { std::vector lastDelUris; - std::for_each(lastDelKeys.begin(), lastDelKeys.end(), [&lastDelUris](auto &result) { + std::for_each(lastDelKeys.begin(), lastDelKeys.end(), [&lastDelUris, this](auto &result) { lastDelUris.emplace_back(result); + lastChangeNodeMap_.erase(result); }); if (lastDelUris.empty()) { return; @@ -116,6 +121,7 @@ std::vector RdbSubscriberManager::DelObservers(void *subscriber [&proxy, this](const std::vector &lastDelKeys, std::vector &opResult) { // delete all obs by subscriber for (const auto &key : lastDelKeys) { + lastChangeNodeMap_.erase(key); auto unsubResult = proxy->UnSubscribeRdbData(std::vector(1, key.uri_), key.templateId_); opResult.insert(opResult.end(), unsubResult.begin(), unsubResult.end()); } @@ -135,6 +141,9 @@ std::vector RdbSubscriberManager::EnableObservers(void *subscri keys.emplace_back(uri, templateId); }); return BaseCallbacks::EnableObservers(keys, subscriber, + [this](std::map>> &obsMap) { + Emit(obsMap); + }, [&proxy, subscriber, &templateId, this](const std::vector &firstAddKeys, std::vector &opResult) { std::vector firstAddUris; @@ -182,7 +191,6 @@ std::vector RdbSubscriberManager::DisableObservers(void *subscr auto results = proxy->DisableSubscribeRdbData(lastDisabledUris, templateId); opResult.insert(opResult.end(), results.begin(), results.end()); - Destroy(); }); } @@ -212,6 +220,7 @@ void RdbSubscriberManager::RecoverObservers(std::shared_ptr &keys, const std::shared_ptr &observer) +{ + for (auto const &key : keys) { + auto it = lastChangeNodeMap_.find(key); + if (it != lastChangeNodeMap_.end()) { + observer->OnChange(it->second); + } + } +} + +void RdbSubscriberManager::Emit(std::map>> &obsMap) +{ + for (auto &[key, obsVector] : obsMap) { + auto it = lastChangeNodeMap_.find(key); + if (it == lastChangeNodeMap_.end()) { + continue; + } + for (auto &obs : obsVector) { + obs->OnChange(it->second); + } + } +} + bool RdbSubscriberManager::Init() { if (serviceCallback_ == nullptr) { diff --git a/data_share/interfaces/inner_api/BUILD.gn b/data_share/interfaces/inner_api/BUILD.gn index bb6d232c4ad1c45db27df5508b53c8e6c1c2b78d..5ac401be97206055dce72e579c7c3550b4f86eb7 100644 --- a/data_share/interfaces/inner_api/BUILD.gn +++ b/data_share/interfaces/inner_api/BUILD.gn @@ -86,7 +86,7 @@ ohos_shared_library("datashare_consumer") { "ability_runtime:dataobs_manager", "c_utils:utils", "common_event_service:cesfwk_innerkits", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", "ipc:ipc_single", "ipc_js:rpc", "napi:ace_napi", @@ -127,7 +127,7 @@ ohos_shared_library("datashare_provider") { "access_token:libaccesstoken_sdk", "c_utils:utils", "common_event_service:cesfwk_innerkits", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", "ipc:ipc_single", "ipc_js:rpc", "napi:ace_napi", @@ -154,7 +154,7 @@ ohos_shared_library("datashare_ext_ability_module") { "ability_runtime:runtime", "c_utils:utils", "common_event_service:cesfwk_innerkits", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", ] relative_install_dir = "extensionability/" diff --git a/data_share/interfaces/inner_api/common/BUILD.gn b/data_share/interfaces/inner_api/common/BUILD.gn index 14d97ae0adfaf17c6b0a546662b0dbbfad0192e5..878748b1bda37edf2d2278a663076d2f68284847 100644 --- a/data_share/interfaces/inner_api/common/BUILD.gn +++ b/data_share/interfaces/inner_api/common/BUILD.gn @@ -73,10 +73,10 @@ ohos_shared_library("datashare_common") { "ability_base:zuri", "ability_runtime:abilitykit_native", "c_utils:utils", - "hisysevent_native:libhisysevent", - "hitrace_native:hitrace_meter", - "hitrace_native:libhitracechain", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", + "hisysevent:libhisysevent", + "hitrace:hitrace_meter", + "hitrace:libhitracechain", "ipc:ipc_napi_common", "ipc:ipc_single", "napi:ace_napi", diff --git a/data_share/test/native/BUILD.gn b/data_share/test/native/BUILD.gn index dbb1d37d2d80091100024a6d53adddbb632a5e5d..00e5a302a7066b268e806d6d8928c321be44c66b 100644 --- a/data_share/test/native/BUILD.gn +++ b/data_share/test/native/BUILD.gn @@ -68,8 +68,8 @@ ohos_unittest("NativeDataShareTest") { "access_token:libtoken_setproc", "c_utils:utils", "common_event_service:cesfwk_innerkits", - "hilog_native:libhilog", - "hitrace_native:hitrace_meter", + "hilog:libhilog", + "hitrace:hitrace_meter", "ipc:ipc_single", "media_library:media_library", "relational_store:rdb_data_ability_adapter", @@ -107,7 +107,7 @@ ohos_unittest("SlientAccessTest") { "access_token:libtoken_setproc", "c_utils:utils", "common_event_service:cesfwk_innerkits", - "hilog_native:libhilog", + "hilog:libhilog", "ipc:ipc_single", "safwk:system_ability_fwk", "samgr:samgr_proxy", diff --git a/datamgr_service/BUILD.gn b/datamgr_service/BUILD.gn index f25102073259ae5ace6ff0d0de23f748d5e7d495..e759bcf16d04461c11e7fd8a5e1e3a62a2a33be3 100644 --- a/datamgr_service/BUILD.gn +++ b/datamgr_service/BUILD.gn @@ -29,6 +29,9 @@ group("fuzztest") { testonly = true deps = [] deps += [ + "services/distributeddataservice/adapter/test:fuzztest", + "services/distributeddataservice/app/test/fuzztest:fuzztest", + "services/distributeddataservice/service/test/fuzztest:fuzztest", "test/fuzztest/autolaunch_fuzzer:fuzztest", "test/fuzztest/kvstoredisksize_fuzzer:fuzztest", ] diff --git a/datamgr_service/bundle.json b/datamgr_service/bundle.json index 683a81f1ad2e49871ec5e1c9567feb3d49700178..3b5839adf548bed0d326637e49a229eb8635b730 100644 --- a/datamgr_service/bundle.json +++ b/datamgr_service/bundle.json @@ -39,7 +39,8 @@ "subsystem": "distributeddatamgr", "syscap": [], "features": [ - "datamgr_service_config" + "datamgr_service_config", + "datamgr_service_udmf" ], "adapted_system_type": [ "standard" @@ -55,7 +56,6 @@ "ability_runtime", "access_token", "bundle_framework", - "common", "common_event_service", "c_utils", "dataclassification", @@ -63,26 +63,25 @@ "device_auth", "device_manager", "dsoftbus", - "hisysevent_native", - "hitrace_native", - "hiviewdfx_hilog_native", + "hilog", + "hisysevent", + "hitrace", "huks", - "init", "kv_store", "ipc", "napi", "os_account", "relational_store", "safwk", - "samgr" + "samgr", + "udmf" ], "third_party": [ "cjson", + "jsoncpp", + "libuv", "openssl", "sqlite", - "libuv", - "libz", - "jsoncpp", "zlib" ] }, diff --git a/datamgr_service/datamgr_service.gni b/datamgr_service/datamgr_service.gni index 3a7b7e96be97c5e083790758c3bad6659baa5a62..ac2f5ccbe23c9dc964b99cd328ed7d57cb43bc52 100644 --- a/datamgr_service/datamgr_service.gni +++ b/datamgr_service/datamgr_service.gni @@ -32,6 +32,12 @@ ipc_core_path = "//foundation/communication/ipc/interfaces/innerkits/ipc_core" device_manager_path = "//foundation/distributedhardware/device_manager" +data_service_path = "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice" + +udmf_path = "//foundation/distributeddatamgr/udmf" + +dataobject_path = "//foundation/distributeddatamgr/data_object" + declare_args() { datamgr_service_power = true if (!defined(global_parts_info.power_manager_native_powermgr_client) || @@ -47,4 +53,6 @@ declare_args() { } datamgr_service_config = true + + datamgr_service_udmf = false } diff --git a/datamgr_service/services/distributeddataservice/adapter/BUILD.gn b/datamgr_service/services/distributeddataservice/adapter/BUILD.gn index 515866a6a1c192ac02ab1c1a051a3235e9447ac6..7c5cebe19fb10d5e8bf84fe7331ae29a4506b575 100644 --- a/datamgr_service/services/distributeddataservice/adapter/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/adapter/BUILD.gn @@ -52,10 +52,10 @@ ohos_shared_library("distributeddata_adapter") { external_deps = [ "c_utils:utils", - "hisysevent_native:libhisysevent", - "hitrace_native:hitrace_meter", - "hitrace_native:libhitracechain", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", + "hisysevent:libhisysevent", + "hitrace:hitrace_meter", + "hitrace:libhitracechain", ] public_configs = [ ":distributeddata_adapter_public_config" ] diff --git a/datamgr_service/services/distributeddataservice/adapter/account/BUILD.gn b/datamgr_service/services/distributeddataservice/adapter/account/BUILD.gn index d2a449b8a939396f56c8312e7b37be02b0a74aac..e94286519f5542a49a1bf6e0103624d8e99426fd 100644 --- a/datamgr_service/services/distributeddataservice/adapter/account/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/adapter/account/BUILD.gn @@ -42,7 +42,7 @@ ohos_static_library("distributeddata_account_static") { "ability_base:want", "c_utils:utils", "common_event_service:cesfwk_innerkits", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", ] if (os_account_part_is_enabled) { diff --git a/datamgr_service/services/distributeddataservice/adapter/account/test/BUILD.gn b/datamgr_service/services/distributeddataservice/adapter/account/test/BUILD.gn index fa8c3d6edc219124ea89d6af7383eaf84476a4bd..34a2846e3514bf12d2a036ca9fad7ea2f7bdae4e 100644 --- a/datamgr_service/services/distributeddataservice/adapter/account/test/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/adapter/account/test/BUILD.gn @@ -38,7 +38,7 @@ ohos_unittest("AccountDelegateTest") { "ability_base:want", "bundle_framework:appexecfwk_base", "c_utils:utils", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", "ipc:ipc_core", ] defines = [ "OPENSSL_SUPPRESS_DEPRECATED" ] diff --git a/datamgr_service/services/distributeddataservice/adapter/broadcaster/BUILD.gn b/datamgr_service/services/distributeddataservice/adapter/broadcaster/BUILD.gn index fe0fc348fa18a324750a9c9b28a4a35f69bea101..472bef0cfdef4ba3ff5ad54cc40e426cac4ae024 100644 --- a/datamgr_service/services/distributeddataservice/adapter/broadcaster/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/adapter/broadcaster/BUILD.gn @@ -30,13 +30,12 @@ ohos_static_library("distributeddata_broadcaster_static") { cflags_cc = [ "-fvisibility=hidden" ] external_deps = [ - # "ces:libcommonevent", "ability_base:base", "ability_base:want", "bundle_framework:appexecfwk_base", "c_utils:utils", "common_event_service:cesfwk_innerkits", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", "ipc:ipc_core", ] subsystem_name = "distributeddatamgr" diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/BUILD.gn b/datamgr_service/services/distributeddataservice/adapter/communicator/BUILD.gn index be70a5dda4425ec3388336297927fcfc90c380b8..451b8de670ce2ed02e9a5a4e8e90c0053780ff4a 100644 --- a/datamgr_service/services/distributeddataservice/adapter/communicator/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/BUILD.gn @@ -58,7 +58,7 @@ ohos_static_library("distributeddata_communicator_static") { "c_utils:utils", "device_manager:devicemanagersdk", "dsoftbus:softbus_client", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", ] subsystem_name = "distributeddatamgr" diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/test/BUILD.gn b/datamgr_service/services/distributeddataservice/adapter/communicator/test/BUILD.gn index a3fa43ac1ad48518221acd752132beaee2811fdc..b3dbad12f7c0f3ef2c8067325330b2a9b202de2f 100644 --- a/datamgr_service/services/distributeddataservice/adapter/communicator/test/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/test/BUILD.gn @@ -30,7 +30,7 @@ ohos_unittest("CommunicationProviderTest") { ] external_deps = [ "dsoftbus:softbus_client", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", "ipc:ipc_core", ] deps = [ @@ -55,7 +55,7 @@ ohos_unittest("DeviceManagerAdapterTest") { ] external_deps = [ "dsoftbus:softbus_client", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", "ipc:ipc_core", ] deps = [ diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/test/fuzztest/BUILD.gn b/datamgr_service/services/distributeddataservice/adapter/communicator/test/fuzztest/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..dacf421df4682cdbe259f46e31535df42a1e347c --- /dev/null +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/test/fuzztest/BUILD.gn @@ -0,0 +1,21 @@ +# 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. + +import("//build/ohos.gni") + +######################################################################################### +group("fuzztest") { + testonly = true + + deps = [ "softbusadapter_fuzzer:fuzztest" ] +} diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/test/fuzztest/softbusadapter_fuzzer/BUILD.gn b/datamgr_service/services/distributeddataservice/adapter/communicator/test/fuzztest/softbusadapter_fuzzer/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..25df6bdb94d26f73be10de4d43ef1587bfc08b05 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/test/fuzztest/softbusadapter_fuzzer/BUILD.gn @@ -0,0 +1,68 @@ +# 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. +##############################hydra-fuzz######################################## +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/datamgr_service/datamgr_service.gni") + +##############################fuzztest########################################## +ohos_fuzztest("SoftBusAdapterFuzzTest") { + module_out_path = "datamgr_service/adapter" + + include_dirs = [ + "${data_service_path}/adapter/include/communicator", + "${data_service_path}/adapter/include/dfx", + "${data_service_path}/adapter/include/log", + "${data_service_path}/adapter/include/autils", + "${data_service_path}/adapter/include/utils", + "${data_service_path}/adapter/communicator/src", + "${dsoftbus_core_path}", + "${kv_store_common_path}", + "${kv_store_distributeddb_path}/interfaces/include", + "${kv_store_distributeddb_path}/include", + "${kv_store_distributeddb_path}/interfaces/include/relational", + "${kv_store_path}/interfaces/innerkits/distributeddata/include", + ] + + fuzz_config_file = "${data_service_path}/adapter/communicator/test/fuzztest/softbusadapter_fuzzer" + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + sources = [ "softbusadapter_fuzzer.cpp" ] + + deps = [ + "${data_service_path}/adapter/communicator:distributeddata_communicator_static", + "${data_service_path}/adapter/dfx:distributeddata_dfx_static", + "${data_service_path}/adapter/utils:distributeddata_utils_static", + ] + + external_deps = [ + "c_utils:utils", + "device_manager:devicemanagersdk", + "dsoftbus:softbus_client", + "hilog:libhilog", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + + deps = [ ":SoftBusAdapterFuzzTest" ] +} +############################################################################### diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/test/fuzztest/softbusadapter_fuzzer/corpus/init b/datamgr_service/services/distributeddataservice/adapter/communicator/test/fuzztest/softbusadapter_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..2b595da0c26af63ffb2d5f4132c086b2e5986fce --- /dev/null +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/test/fuzztest/softbusadapter_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/test/fuzztest/softbusadapter_fuzzer/project.xml b/datamgr_service/services/distributeddataservice/adapter/communicator/test/fuzztest/softbusadapter_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..3fdba3e8b151bbb9026792021977b81e8a1851a6 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/test/fuzztest/softbusadapter_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/test/fuzztest/softbusadapter_fuzzer/softbusadapter_fuzzer.cpp b/datamgr_service/services/distributeddataservice/adapter/communicator/test/fuzztest/softbusadapter_fuzzer/softbusadapter_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cc9721064055b98521dca506f5b5618d70c9a3c1 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/test/fuzztest/softbusadapter_fuzzer/softbusadapter_fuzzer.cpp @@ -0,0 +1,47 @@ +/* + * 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 "softbusadapter_fuzzer.h" + +#include +#include + +#include "softbus_adapter_standard.cpp" +#include "message_parcel.h" +#include "securec.h" + +using namespace OHOS::AppDistributedKv; + +namespace OHOS { +bool OnBytesReceivedFuzz(const uint8_t *data, size_t size) +{ + int connId = static_cast(*data); + unsigned int dataLen = static_cast(size); + AppDataListenerWrap::OnBytesReceived(connId, data, dataLen); + return true; +} +} // namespace OHOS + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + if (data == nullptr) { + return 0; + } + + OHOS::OnBytesReceivedFuzz(data, size); + + return 0; +} \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/test/fuzztest/softbusadapter_fuzzer/softbusadapter_fuzzer.h b/datamgr_service/services/distributeddataservice/adapter/communicator/test/fuzztest/softbusadapter_fuzzer/softbusadapter_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..d77e3037e5a2c2ce48f13fd258a21a9d1404eb97 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/test/fuzztest/softbusadapter_fuzzer/softbusadapter_fuzzer.h @@ -0,0 +1,21 @@ +/* + * 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 SOFTBUSADAPTER_FUZZER_H +#define SOFTBUSADAPTER_FUZZER_H + +#define FUZZ_PROJECT_NAME "softbusadapter_fuzzer" + +#endif // SOFTBUSADAPTER_FUZZER_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/adapter/dfx/BUILD.gn b/datamgr_service/services/distributeddataservice/adapter/dfx/BUILD.gn index 2818cae48ad4bf7d1a469ec75e12d7b3f66a5c0a..9d23ea69a0912a7c7dd7b0d09bc5343deaa280fe 100644 --- a/datamgr_service/services/distributeddataservice/adapter/dfx/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/adapter/dfx/BUILD.gn @@ -44,10 +44,10 @@ ohos_static_library("distributeddata_dfx_static") { deps = [ "//third_party/openssl:libcrypto_shared" ] external_deps = [ "c_utils:utils", - "hisysevent_native:libhisysevent", - "hitrace_native:hitrace_meter", - "hitrace_native:libhitracechain", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", + "hisysevent:libhisysevent", + "hitrace:hitrace_meter", + "hitrace:libhitracechain", ] subsystem_name = "distributeddatamgr" part_name = "datamgr_service" diff --git a/datamgr_service/services/distributeddataservice/adapter/dfx/test/BUILD.gn b/datamgr_service/services/distributeddataservice/adapter/dfx/test/BUILD.gn index 4b4df71f6eeb82ea69a2df6b890fd771cd7e6f85..fe26d017b5bbed375bf6bd608a8c277d9fb48bd1 100644 --- a/datamgr_service/services/distributeddataservice/adapter/dfx/test/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/adapter/dfx/test/BUILD.gn @@ -41,9 +41,9 @@ ohos_unittest("DistributeddataDfxMSTTest") { external_deps = [ "c_utils:utils", - "hisysevent_native:libhisysevent", - "hitrace_native:hitrace_meter", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", + "hisysevent:libhisysevent", + "hitrace:hitrace_meter", ] ldflags = [ "-Wl,--exclude-libs,ALL" ] deps = [ @@ -99,9 +99,9 @@ ohos_unittest("DistributeddataDfxUTTest") { external_deps = [ "c_utils:utils", - "hisysevent_native:libhisysevent", - "hitrace_native:hitrace_meter", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", + "hisysevent:libhisysevent", + "hitrace:hitrace_meter", ] ldflags = [ "-Wl,--exclude-libs,ALL" ] deps = [ diff --git a/datamgr_service/services/distributeddataservice/adapter/permission/BUILD.gn b/datamgr_service/services/distributeddataservice/adapter/permission/BUILD.gn index 48e7792729a88cd4c0a65108c0645116ba273ced..2c47874654b0952eb3fd89fc8deb162c446fade3 100644 --- a/datamgr_service/services/distributeddataservice/adapter/permission/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/adapter/permission/BUILD.gn @@ -35,7 +35,7 @@ ohos_static_library("distributeddata_permission_static") { external_deps = [ "access_token:libaccesstoken_sdk", "c_utils:utils", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", ] subsystem_name = "distributeddatamgr" part_name = "datamgr_service" diff --git a/datamgr_service/services/distributeddataservice/adapter/permission/test/BUILD.gn b/datamgr_service/services/distributeddataservice/adapter/permission/test/BUILD.gn index a19f4c30fdd885df876c31c845aa60eb9a77ed61..509f49b312a16d8c8a3cd5e9dcca8793a34bc74a 100644 --- a/datamgr_service/services/distributeddataservice/adapter/permission/test/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/adapter/permission/test/BUILD.gn @@ -42,7 +42,7 @@ ohos_unittest("PermissionValidatorTest") { "//third_party/googletest:gtest_main", ] - external_deps = [ "hiviewdfx_hilog_native:libhilog" ] + external_deps = [ "hilog:libhilog" ] defines = [ "OPENSSL_SUPPRESS_DEPRECATED" ] } diff --git a/datamgr_service/services/distributeddataservice/adapter/test/BUILD.gn b/datamgr_service/services/distributeddataservice/adapter/test/BUILD.gn index 206f581e396c2d3ed29f003694960ad882585e30..f85ada83e4e6922db5824e910fc8c5e187a4b800 100644 --- a/datamgr_service/services/distributeddataservice/adapter/test/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/adapter/test/BUILD.gn @@ -24,3 +24,9 @@ group("unittest") { "../permission/test:unittest", ] } + +group("fuzztest") { + testonly = true + + deps = [ "../communicator/test/fuzztest:fuzztest" ] +} diff --git a/datamgr_service/services/distributeddataservice/adapter/utils/BUILD.gn b/datamgr_service/services/distributeddataservice/adapter/utils/BUILD.gn index b57d430bb0024e90d3d89eb9714d1db9e93e3422..6442a139ccbf9ea9f26422f6cef0c13a1955be23 100644 --- a/datamgr_service/services/distributeddataservice/adapter/utils/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/adapter/utils/BUILD.gn @@ -35,7 +35,7 @@ ohos_static_library("distributeddata_utils_static") { external_deps = [ "c_utils:utils", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", ] subsystem_name = "distributeddatamgr" part_name = "datamgr_service" diff --git a/datamgr_service/services/distributeddataservice/app/BUILD.gn b/datamgr_service/services/distributeddataservice/app/BUILD.gn index 5df04bddf37feb118841c56315e176dc1577d32a..607c673207dabb0b9bc30aee8731d4b4a6dcf4e8 100644 --- a/datamgr_service/services/distributeddataservice/app/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/app/BUILD.gn @@ -118,10 +118,10 @@ ohos_shared_library("distributeddataservice") { "bundle_framework:appexecfwk_core", "c_utils:utils", "dataclassification:data_transit_mgr", - "hisysevent_native:libhisysevent", - "hitrace_native:hitrace_meter", - "hitrace_native:libhitracechain", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", + "hisysevent:libhisysevent", + "hitrace:hitrace_meter", + "hitrace:libhitracechain", "ipc:ipc_core", "kv_store:distributeddata_inner", "safwk:system_ability_fwk", diff --git a/datamgr_service/services/distributeddataservice/app/CMakeLists.txt b/datamgr_service/services/distributeddataservice/app/CMakeLists.txt index 017b7ac7a8a64d39278f44ba97ad6c9c7d8158ba..262fa5da26167abbbfc4b9321eb6a796d1e1be97 100644 --- a/datamgr_service/services/distributeddataservice/app/CMakeLists.txt +++ b/datamgr_service/services/distributeddataservice/app/CMakeLists.txt @@ -38,7 +38,6 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../adapter/include/utils) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../service/bootstrap/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../service/config/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../service/crypto/include) -include_directories(../framework/directory/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../service/permission/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../service/rdb) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../service/kvdb) diff --git a/datamgr_service/services/distributeddataservice/app/src/checker/BUILD.gn b/datamgr_service/services/distributeddataservice/app/src/checker/BUILD.gn index 1f59492cac8717e5eb1cff7ae28164ceff672cd3..0cb0a4f85db0286e026232eb390b4055408e8fe2 100644 --- a/datamgr_service/services/distributeddataservice/app/src/checker/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/app/src/checker/BUILD.gn @@ -40,7 +40,7 @@ ohos_static_library("distributeddata_checker_static") { "bundle_framework:appexecfwk_base", "bundle_framework:appexecfwk_core", "c_utils:utils", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", "ipc:ipc_core", "samgr:samgr_proxy", ] diff --git a/datamgr_service/services/distributeddataservice/app/src/uninstaller/BUILD.gn b/datamgr_service/services/distributeddataservice/app/src/uninstaller/BUILD.gn index 04daeef74ee9c727d74f853a64e6476bb4b0f640..54196c83138db01c24ff501e6b04b7400148fc3d 100644 --- a/datamgr_service/services/distributeddataservice/app/src/uninstaller/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/app/src/uninstaller/BUILD.gn @@ -42,14 +42,12 @@ ohos_static_library("distributeddata_uninstaller_static") { ] external_deps = [ + "ability_base:want", "bundle_framework:appexecfwk_base", "c_utils:utils", - - # "ces:libcommonevent", - "ability_base:want", "common_event_service:cesfwk_innerkits", "dataclassification:data_transit_mgr", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", "ipc:ipc_core", "safwk:system_ability_fwk", "samgr:samgr_proxy", diff --git a/datamgr_service/services/distributeddataservice/app/test/BUILD.gn b/datamgr_service/services/distributeddataservice/app/test/BUILD.gn index 3ce6b41dd8e7d85ef5a82b764a513797a1eb192d..f471e188e2aad5bb64b0a3904fa923d27d1aa264 100644 --- a/datamgr_service/services/distributeddataservice/app/test/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/app/test/BUILD.gn @@ -87,10 +87,10 @@ ohos_unittest("KvStoreDataServiceTest") { "c_utils:utils", "dataclassification:data_transit_mgr", "device_auth:deviceauth_sdk", - "hisysevent_native:libhisysevent", - "hitrace_native:hitrace_meter", - "hitrace_native:libhitracechain", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", + "hisysevent:libhisysevent", + "hitrace:hitrace_meter", + "hitrace:libhitracechain", "ipc:ipc_core", "safwk:system_ability_fwk", "samgr:samgr_proxy", @@ -138,7 +138,7 @@ ohos_unittest("SessionManagerTest") { "c_utils:utils", "dataclassification:data_transit_mgr", "device_auth:deviceauth_sdk", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", "ipc:ipc_core", "safwk:system_ability_fwk", "samgr:samgr_proxy", @@ -177,7 +177,7 @@ ohos_unittest("KvStoreFlowCtrlManagerTest") { "c_utils:utils", "dataclassification:data_transit_mgr", "device_auth:deviceauth_sdk", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", "ipc:ipc_core", "safwk:system_ability_fwk", "samgr:samgr_proxy", diff --git a/datamgr_service/services/distributeddataservice/app/test/fuzztest/BUILD.gn b/datamgr_service/services/distributeddataservice/app/test/fuzztest/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..d7c29a7ae886e1c2e0f1b8a4b0e3b506c6d385d1 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/app/test/fuzztest/BUILD.gn @@ -0,0 +1,21 @@ +# 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. + +import("//build/ohos.gni") + +######################################################################################### +group("fuzztest") { + testonly = true + + deps = [ "dataservicestub_fuzzer:fuzztest" ] +} diff --git a/datamgr_service/services/distributeddataservice/app/test/fuzztest/dataservicestub_fuzzer/BUILD.gn b/datamgr_service/services/distributeddataservice/app/test/fuzztest/dataservicestub_fuzzer/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..3e594bee1c03cdb18fbefca2eedb3b5338bb6e4e --- /dev/null +++ b/datamgr_service/services/distributeddataservice/app/test/fuzztest/dataservicestub_fuzzer/BUILD.gn @@ -0,0 +1,116 @@ +# 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. +##############################hydra-fuzz######################################## +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/datamgr_service/datamgr_service.gni") + +##############################fuzztest########################################## +ohos_fuzztest("DataServiceStubFuzzTest") { + module_out_path = "datamgr_service/app" + + include_dirs = [ + "${kv_store_common_path}", + "${kv_store_path}/frameworks/innerkitsimpl/distributeddatafwk/include", + "${data_service_path}/service/bootstrap/include", + "${data_service_path}/service/config/include", + "${data_service_path}/service/crypto/include", + "${data_service_path}/service/directory/include", + "${data_service_path}/service/permission/include", + "${data_service_path}/service/matrix/include", + "${data_service_path}/app/src", + "${data_service_path}/app/src/backup_rule/include", + "${data_service_path}/app/src/checker", + "${data_service_path}/app/src/flowctrl_manager", + "${data_service_path}/app/src/security", + "${data_service_path}/app/src/session_manager", + "${data_service_path}/app/src/uninstaller", + "${data_service_path}/framework/include", + "${data_service_path}/service/backup/include", + "${data_service_path}/service/kvdb", + "${data_service_path}/adapter/include/account", + "${data_service_path}/adapter/include/permission", + "${data_service_path}/adapter/include/uninstaller", + "${data_service_path}/adapter/include/broadcaster", + "${data_service_path}/adapter/include/utils", + "${data_service_path}/adapter/include/dfx", + "${data_service_path}/adapter/include", + "${device_manager_path}/interfaces/inner_kits/native_cpp/include", + "${distributedfilejs_path}/interfaces/kits/js/src/mod_securitylabel", + "//third_party/json/single_include", + ] + + fuzz_config_file = + "${data_service_path}/app/test/fuzztest/dataservicestub_fuzzer" + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + sources = [ + "${data_service_path}/app/src/dump_helper.cpp", + "${data_service_path}/app/src/feature_stub_impl.cpp", + "${data_service_path}/app/src/kvstore_account_observer.cpp", + "${data_service_path}/app/src/kvstore_data_service.cpp", + "${data_service_path}/app/src/kvstore_device_listener.cpp", + "${data_service_path}/app/src/kvstore_meta_manager.cpp", + "${data_service_path}/app/src/security/security.cpp", + "${data_service_path}/app/src/security/sensitive.cpp", + "${data_service_path}/app/src/session_manager/route_head_handler_impl.cpp", + "${data_service_path}/app/src/session_manager/session_manager.cpp", + "${data_service_path}/app/src/session_manager/upgrade_manager.cpp", + "${data_service_path}/app/src/task_manager.cpp", + "dataservicestub_fuzzer.cpp", + ] + + deps = [ + "${data_service_path}/adapter:distributeddata_adapter", + "${data_service_path}/adapter/broadcaster:distributeddata_broadcaster_static", + "${data_service_path}/adapter/utils:distributeddata_utils_static", + "${data_service_path}/app/src/checker:distributeddata_checker_static", + "${data_service_path}/app/src/flowctrl_manager:distributeddata_flowctrl_static", + "${data_service_path}/app/src/uninstaller:distributeddata_uninstaller_static", + "${data_service_path}/framework:distributeddatasvcfwk", + "${data_service_path}/service:distributeddatasvc", + "${kv_store_distributeddb_path}:distributeddb", + ] + + external_deps = [ + "ability_base:base", + "ability_base:want", + "access_token:libaccesstoken_sdk", + "bundle_framework:appexecfwk_base", + "bundle_framework:appexecfwk_core", + "c_utils:utils", + "dataclassification:data_transit_mgr", + "hilog:libhilog", + "hisysevent:libhisysevent", + "hitrace:hitrace_meter", + "hitrace:libhitracechain", + "ipc:ipc_core", + "kv_store:distributeddata_inner", + "safwk:system_ability_fwk", + "samgr:samgr_proxy", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + + deps = [ ":DataServiceStubFuzzTest" ] +} +############################################################################### diff --git a/datamgr_service/services/distributeddataservice/app/test/fuzztest/dataservicestub_fuzzer/corpus/init b/datamgr_service/services/distributeddataservice/app/test/fuzztest/dataservicestub_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..2b595da0c26af63ffb2d5f4132c086b2e5986fce --- /dev/null +++ b/datamgr_service/services/distributeddataservice/app/test/fuzztest/dataservicestub_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/app/test/fuzztest/dataservicestub_fuzzer/dataservicestub_fuzzer.cpp b/datamgr_service/services/distributeddataservice/app/test/fuzztest/dataservicestub_fuzzer/dataservicestub_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e5164c9424b81e5de3a566e98209b206d5520b4d --- /dev/null +++ b/datamgr_service/services/distributeddataservice/app/test/fuzztest/dataservicestub_fuzzer/dataservicestub_fuzzer.cpp @@ -0,0 +1,57 @@ +/* + * 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 "dataservicestub_fuzzer.h" + +#include +#include + +#include "kvstore_data_service.h" +#include "message_parcel.h" +#include "securec.h" + +using namespace OHOS::DistributedKv; + +namespace OHOS { +const std::u16string INTERFACE_TOKEN = u"OHOS.DistributedKv.IKvStoreDataService"; +const uint32_t CODE_MIN = 0; +const uint32_t CODE_MAX = 10; + +bool OnRemoteRequestFuzz(const uint8_t *data, size_t size) +{ + uint32_t code = static_cast(*data) % (CODE_MAX - CODE_MIN + 1) + CODE_MIN; + MessageParcel request; + request.WriteInterfaceToken(INTERFACE_TOKEN); + request.WriteBuffer(data, size); + request.RewindRead(0); + MessageParcel reply; + MessageOption option; + std::shared_ptr kvStoreDataServiceStub = std::make_shared(); + kvStoreDataServiceStub->OnRemoteRequest(code, request, reply, option); + return true; +} +} // namespace OHOS + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + if (data == nullptr) { + return 0; + } + + OHOS::OnRemoteRequestFuzz(data, size); + + return 0; +} \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/app/test/fuzztest/dataservicestub_fuzzer/dataservicestub_fuzzer.h b/datamgr_service/services/distributeddataservice/app/test/fuzztest/dataservicestub_fuzzer/dataservicestub_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..02e3b8df3e7d6d285bb49a42ea9bf140c5914b5d --- /dev/null +++ b/datamgr_service/services/distributeddataservice/app/test/fuzztest/dataservicestub_fuzzer/dataservicestub_fuzzer.h @@ -0,0 +1,21 @@ +/* + * 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 DATAMGR_SERVICE_DATA_SERVICE_STUB_FUZZER_H +#define DATAMGR_SERVICE_DATA_SERVICE_STUB_FUZZER_H + +#define FUZZ_PROJECT_NAME "dataservicestub_fuzzer" + +#endif // DATAMGR_SERVICE_DATA_SERVICE_STUB_FUZZER_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/app/test/fuzztest/dataservicestub_fuzzer/project.xml b/datamgr_service/services/distributeddataservice/app/test/fuzztest/dataservicestub_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..3fdba3e8b151bbb9026792021977b81e8a1851a6 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/app/test/fuzztest/dataservicestub_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/BUILD.gn b/datamgr_service/services/distributeddataservice/framework/BUILD.gn index b09c9c74f1e84ae72c177affcba29a72ef4c224b..b13f8c456b23fccb3439cd14ae27e3c2a7adbed9 100644 --- a/datamgr_service/services/distributeddataservice/framework/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/framework/BUILD.gn @@ -90,7 +90,7 @@ ohos_shared_library("distributeddatasvcfwk") { external_deps = [ "access_token:libaccesstoken_sdk", "c_utils:utils", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", ] subsystem_name = "distributeddatamgr" diff --git a/datamgr_service/services/distributeddataservice/framework/cloud/sync_event.cpp b/datamgr_service/services/distributeddataservice/framework/cloud/sync_event.cpp index 7c2d3d93547e72f21b7804540ad0f42c746a2d14..f165e4f74000b3006b38e45a7c3ad905cf975620 100644 --- a/datamgr_service/services/distributeddataservice/framework/cloud/sync_event.cpp +++ b/datamgr_service/services/distributeddataservice/framework/cloud/sync_event.cpp @@ -16,8 +16,8 @@ #include "cloud/sync_event.h" namespace OHOS::DistributedData { -SyncEvent::EventInfo::EventInfo(int32_t mode, int32_t wait, std::shared_ptr query, GenAsync async) - : mode_(mode), wait_(wait), query_(std::move(query)), asyncDetail_(std::move(async)) +SyncEvent::EventInfo::EventInfo(int32_t mode, int32_t wait, bool retry, std::shared_ptr query, GenAsync async) + : retry_(retry), mode_(mode), wait_(wait), query_(std::move(query)), asyncDetail_(std::move(async)) { } @@ -31,6 +31,7 @@ SyncEvent::EventInfo &SyncEvent::EventInfo::operator=(SyncEvent::EventInfo &&inf if (this == &info) { return *this; } + retry_ = info.retry_; mode_ = info.mode_; wait_ = info.wait_; query_ = std::move(info.query_); @@ -58,6 +59,11 @@ int32_t SyncEvent::GetWait() const return info_.wait_; } +bool SyncEvent::AutoRetry() const +{ + return info_.retry_; +} + std::shared_ptr SyncEvent::GetQuery() const { return info_.query_; diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/sync_event.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/sync_event.h index 351a919a21fca56b65cf5dc7fac9841107bc5988..fb25f1a3d5bd642ed5a3a9d6a4128aefccb1f732 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/cloud/sync_event.h +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/sync_event.h @@ -23,13 +23,14 @@ class API_EXPORT SyncEvent : public CloudEvent { public: class EventInfo { public: - API_EXPORT EventInfo(int32_t mode, int32_t wait, std::shared_ptr query, GenAsync async); + API_EXPORT EventInfo(int32_t mode, int32_t wait, bool retry, std::shared_ptr query, GenAsync async); API_EXPORT EventInfo(EventInfo &&info) noexcept; EventInfo(const EventInfo &info) = default; API_EXPORT EventInfo &operator=(EventInfo &&info) noexcept; EventInfo &operator=(const EventInfo &info) = default; private: friend SyncEvent; + bool retry_ = false; int32_t mode_ = -1; int32_t wait_ = 0; std::shared_ptr query_; @@ -39,6 +40,7 @@ public: ~SyncEvent() override = default; int32_t GetMode() const; int32_t GetWait() const; + bool AutoRetry() const; std::shared_ptr GetQuery() const; GenAsync GetAsyncDetail() const; diff --git a/datamgr_service/services/distributeddataservice/framework/include/store/general_store.h b/datamgr_service/services/distributeddataservice/framework/include/store/general_store.h index 0ee2012abefb39111d2d94bffda8fb14d35950d5..0da33a6ec9df9d9489e0fa639730bb8776c55b99 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/store/general_store.h +++ b/datamgr_service/services/distributeddataservice/framework/include/store/general_store.h @@ -43,6 +43,12 @@ public: CLOUD_END, MODE_BUTT = CLOUD_END, }; + enum CleanMode { + NEARBY_DATA = 0, + CLOUD_DATA, + CLOUD_INFO, + LOCAL_DATA, + }; struct BindInfo { BindInfo(std::shared_ptr db = nullptr, std::shared_ptr loader = nullptr) @@ -72,6 +78,8 @@ public: virtual int32_t Sync(const Devices &devices, int32_t mode, GenQuery &query, DetailAsync async, int32_t wait) = 0; + virtual int32_t Clean(const std::vector &devices, int32_t mode, const std::string &tableName) = 0; + virtual int32_t Watch(int32_t origin, Watcher &watcher) = 0; virtual int32_t Unwatch(int32_t origin, Watcher &watcher) = 0; diff --git a/datamgr_service/services/distributeddataservice/framework/include/store/general_value.h b/datamgr_service/services/distributeddataservice/framework/include/store/general_value.h index c482b94063b6bd04c1e5ccde5adcbe941481af65..4bf696fe7860d1a056e5b86ecb6ae0352697aace 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/store/general_value.h +++ b/datamgr_service/services/distributeddataservice/framework/include/store/general_value.h @@ -32,10 +32,10 @@ enum GenProgress { }; struct GenStatistic { - int32_t total; - int32_t success; - int32_t failed; - int32_t untreated; + uint32_t total; + uint32_t success; + uint32_t failed; + uint32_t untreated; }; struct GenTableDetail { diff --git a/datamgr_service/services/distributeddataservice/framework/include/store/general_watcher.h b/datamgr_service/services/distributeddataservice/framework/include/store/general_watcher.h index 4583aa9d9638a608b33b6b9434205de6273e043f..bcf226d6647d08b40bb8675c5d42b7d001838a45 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/store/general_watcher.h +++ b/datamgr_service/services/distributeddataservice/framework/include/store/general_watcher.h @@ -29,7 +29,13 @@ public: ORIGIN_ALL, ORIGIN_BUTT, }; + enum DataType : int32_t { + BASIC_DATA, + ASSET_DATA, + TYPE_BUTT, + }; int32_t origin = ORIGIN_BUTT; + int32_t dataType = BASIC_DATA; // origin is ORIGIN_LOCAL, the id is empty // origin is ORIGIN_NEARBY, the id is networkId; // origin is ORIGIN_CLOUD, the id is the cloud account id @@ -43,7 +49,7 @@ public: OP_BUTT, }; // PK primary key - using PRIValue = std::variant; + using PRIValue = std::variant; using PRIFields = std::map; using ChangeInfo = std::map[OP_BUTT]>; virtual ~GeneralWatcher() = default; diff --git a/datamgr_service/services/distributeddataservice/framework/test/BUILD.gn b/datamgr_service/services/distributeddataservice/framework/test/BUILD.gn index 1e2ccfa56878f30e7d2cf6cbccd3e45f39836add..ba13118563d60acb0ca051e54f4ee6b8a91e2e58 100644 --- a/datamgr_service/services/distributeddataservice/framework/test/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/framework/test/BUILD.gn @@ -37,7 +37,7 @@ ohos_unittest("CheckerManagerTest") { "access_token:libaccesstoken_sdk", "access_token:libnativetoken", "c_utils:utils", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", "ipc:ipc_core", ] @@ -60,7 +60,7 @@ ohos_unittest("EventCenterTest") { external_deps = [ "c_utils:utils", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", "ipc:ipc_core", ] @@ -83,7 +83,7 @@ ohos_unittest("SerializableTest") { "ability_base:base", "ability_base:want", "c_utils:utils", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", "ipc:ipc_core", ] diff --git a/datamgr_service/services/distributeddataservice/service/BUILD.gn b/datamgr_service/services/distributeddataservice/service/BUILD.gn index 4fbe91e39d543a6d71b29c54f363b330696408aa..42b0e4b6848986a26944cf6f13d3907d941ae14b 100644 --- a/datamgr_service/services/distributeddataservice/service/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/BUILD.gn @@ -16,6 +16,10 @@ import("//foundation/distributeddatamgr/datamgr_service/datamgr_service.gni") group("build_module") { deps = [ ":distributeddatasvc" ] + + if (datamgr_service_udmf) { + deps += [ "${data_service_path}/service/udmf:udmf_server" ] + } } config("module_public_config") { visibility = [ ":*" ] @@ -124,7 +128,7 @@ ohos_shared_library("distributeddatasvc") { "c_utils:utils", "device_auth:deviceauth_sdk", "device_manager:devicemanagersdk", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", "huks:libhukssdk", "ipc:ipc_core", "kv_store:distributeddata_inner", diff --git a/datamgr_service/services/distributeddataservice/service/CMakeLists.txt b/datamgr_service/services/distributeddataservice/service/CMakeLists.txt index b872f11bb68ba4aa7dc2c2dba8aa4273b033f51a..c04eacd413b0eebf9acf83501e80bc8eac3cf59f 100644 --- a/datamgr_service/services/distributeddataservice/service/CMakeLists.txt +++ b/datamgr_service/services/distributeddataservice/service/CMakeLists.txt @@ -14,7 +14,6 @@ aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/backup/src serviceSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/bootstrap/src serviceSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/config/src serviceSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/config/src/model serviceSrc) -aux_source_directory(../framework/directory/src serviceSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/crypto/src serviceSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/rdb serviceSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/kvdb serviceSrc) @@ -40,7 +39,6 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}/backup/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/config/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/crypto/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/bootstrap/include) -include_directories(../framework/directory/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/permission/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/matrix/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/data_share/common) @@ -73,6 +71,7 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../adapter/include/security) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../adapter/include/utils) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../app/src) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../../../relational_store/interfaces/inner_api/appdatafwk/include) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../../../relational_store/interfaces/inner_api/cloud_data/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../../../relational_store/interfaces/inner_api/rdb/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../../../relational_store/interfaces/inner_api/rdb_data_share_adapter/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../../../relational_store/interfaces/inner_api/rdb_bms_adapter/include) 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 547ed0741c750910239baf29c88e3bb9fad9bcef..844f2ed3e6b073cc7c842bdb11ed118398fa9c70 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp @@ -16,7 +16,7 @@ #define LOG_TAG "CloudServiceImpl" #include "cloud_service_impl.h" - +#include "accesstoken_kit.h" #include "account/account_delegate.h" #include "checker/checker_manager.h" #include "cloud/cloud_server.h" @@ -29,10 +29,13 @@ #include "runtime_config.h" #include "store/auto_cache.h" #include "utils/anonymous.h" +#include "sync_manager.h" namespace OHOS::CloudData { using namespace DistributedData; +using namespace std::chrono; using DmAdapter = OHOS::DistributedData::DeviceManagerAdapter; using Account = OHOS::DistributedKv::AccountDelegate; +using AccessTokenKit = Security::AccessToken::AccessTokenKit; __attribute__((used)) CloudServiceImpl::Factory CloudServiceImpl::factory_; const CloudServiceImpl::Work CloudServiceImpl::HANDLERS[WORK_BUTT] = { &CloudServiceImpl::DoSubscribe, @@ -122,14 +125,8 @@ int32_t CloudServiceImpl::ChangeAppSwitch(const std::string &id, const std::stri return SUCCESS; } -int32_t CloudServiceImpl::Clean(const std::string &id, const std::map &actions) +int32_t CloudServiceImpl::DoClean(CloudInfo &cloudInfo, const std::map &actions) { - CloudInfo cloudInfo; - auto tokenId = IPCSkeleton::GetCallingTokenID(); - cloudInfo.user = DistributedKv::AccountDelegate::GetInstance()->GetUserByToken(tokenId); - if (GetCloudInfoFromMeta(cloudInfo) != SUCCESS) { - return ERROR; - } syncManager_.StopCloudSync(cloudInfo.user); auto keys = cloudInfo.GetSchemaKey(); for (const auto &[bundle, action] : actions) { @@ -137,13 +134,56 @@ int32_t CloudServiceImpl::Clean(const std::string &id, const std::mapClean({}, action, ""); + if (status != E_OK) { + ZLOGW("remove device data status:%{public}d, user:%{pubilc}d, bundleName:%{public}s, " + "storeId:%{public}s", + status, static_cast(cloudInfo.user), meta.bundleName.c_str(), meta.GetStoreAlias().c_str()); + continue; + } } } return SUCCESS; } +int32_t CloudServiceImpl::Clean(const std::string &id, const std::map &actions) +{ + CloudInfo cloudInfo; + auto tokenId = IPCSkeleton::GetCallingTokenID(); + cloudInfo.user = DistributedKv::AccountDelegate::GetInstance()->GetUserByToken(tokenId); + if (GetCloudInfoFromMeta(cloudInfo) != SUCCESS) { + ZLOGE("get cloud meta failed user:%{public}d", static_cast(cloudInfo.user)); + return ERROR; + } + if (id != cloudInfo.id) { + ZLOGE("different id, [server] id:%{public}s, [meta] id:%{public}s", Anonymous::Change(cloudInfo.id).c_str(), + Anonymous::Change(id).c_str()); + } + return DoClean(cloudInfo, actions); +} + int32_t CloudServiceImpl::NotifyDataChange(const std::string &id, const std::string &bundleName) { CloudInfo cloudInfo; @@ -254,14 +294,21 @@ bool CloudServiceImpl::UpdateCloudInfo(int32_t user) return true; } if (oldInfo.id != cloudInfo.id) { - ZLOGE("different id, [server] id:%{public}s, [meta] id:%{public}s", - Anonymous::Change(cloudInfo.id).c_str(), Anonymous::Change(oldInfo.id).c_str()); + ZLOGE("different id, [server] id:%{public}s, [meta] id:%{public}s", Anonymous::Change(cloudInfo.id).c_str(), + Anonymous::Change(oldInfo.id).c_str()); std::map actions; for (auto &[bundle, app] : cloudInfo.apps) { actions[bundle] = CLEAR_CLOUD_INFO; } + DoClean(oldInfo, actions); + } + if (cloudInfo.enableCloud) { + for (auto &[bundle, app] : cloudInfo.apps) { + if (app.cloudSwitch && !oldInfo.apps[bundle].cloudSwitch) { + syncManager_.DoCloudSync({ cloudInfo.user, bundle }); + } + } } - MetaDataManager::GetInstance().SaveMeta(cloudInfo.GetKey(), cloudInfo, true); return true; } @@ -426,8 +473,8 @@ bool CloudServiceImpl::DoSubscribe(int32_t user) 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(); + auto onThreshold = duration_cast((system_clock::now() + hours(EXPIRE_INTERVAL)).time_since_epoch()); + auto offThreshold = duration_cast(system_clock::now().time_since_epoch()); std::map> subDbs; std::map> unsubDbs; for (auto &[bundle, app] : cloudInfo.apps) { 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 554d8301b9de31ac7d1b7ac2c33150e355738dc8..31599142002dd75d23c9f2dc7c993ddcc5eee4d1 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.h +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.h @@ -80,6 +80,7 @@ private: ExecutorPool::Task GenTask(int32_t retry, int32_t user, AsyncWork work); void Execute(Tasks tasks); bool DoSubscribe(int32_t user); + int32_t DoClean(CloudInfo &cloudInfo, const std::map &actions); std::shared_ptr executor_; SyncManager syncManager_; static const Work HANDLERS[WORK_BUTT]; diff --git a/datamgr_service/services/distributeddataservice/service/cloud/sync_manager.cpp b/datamgr_service/services/distributeddataservice/service/cloud/sync_manager.cpp index 20eb86370083c5ad4e20a5bdbf5971a761014197..8bc0025dd790328d880ef6ebfe34b4f822cbb0c6 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/sync_manager.cpp +++ b/datamgr_service/services/distributeddataservice/service/cloud/sync_manager.cpp @@ -28,12 +28,15 @@ namespace OHOS::CloudData { using namespace DistributedData; using DmAdapter = OHOS::DistributedData::DeviceManagerAdapter; +using Defer = EventCenter::Defer; +std::atomic SyncManager::genId_ = 0; SyncManager::SyncInfo::SyncInfo(int32_t user, const std::string &bundleName, const Store &store, const Tables &tables) : user_(user), bundleName_(bundleName) { if (!store.empty()) { tables_[store] = tables; } + syncId_ = SyncManager::GenerateId(user); } SyncManager::SyncInfo::SyncInfo(int32_t user, const std::string &bundleName, const Stores &stores) @@ -42,11 +45,14 @@ SyncManager::SyncInfo::SyncInfo(int32_t user, const std::string &bundleName, con for (auto &store : stores) { tables_[store] = {}; } + syncId_ = SyncManager::GenerateId(user); } SyncManager::SyncInfo::SyncInfo(int32_t user, const std::string &bundleName, const MutliStoreTables &tables) : user_(user), bundleName_(bundleName), tables_(tables) { + tables_ = tables; + syncId_ = SyncManager::GenerateId(user); } void SyncManager::SyncInfo::SetMode(int32_t mode) @@ -69,7 +75,7 @@ void SyncManager::SyncInfo::SetQuery(std::shared_ptr query) query_ = query; } -void SyncManager::SyncInfo::SetError(int32_t code) +void SyncManager::SyncInfo::SetError(int32_t code) const { if (async_) { GenDetails details; @@ -136,8 +142,8 @@ int32_t SyncManager::DoCloudSync(SyncInfo syncInfo) return E_NOT_INIT; } - actives_.Compute(GenSyncId(syncInfo.user_), [this, &syncInfo](const uint64_t &key, TaskId &taskId) mutable { - taskId = executor_->Execute(GetSyncTask(0, GenSyncRef(key), std::move(syncInfo))); + actives_.Compute(GenerateId(syncInfo.user_), [this, &syncInfo](const uint64_t &key, TaskId &taskId) mutable { + taskId = executor_->Execute(GetSyncTask(0, true, GenSyncRef(key), std::move(syncInfo))); return true; }); @@ -158,11 +164,11 @@ int32_t SyncManager::StopCloudSync(int32_t user) return E_OK; } -ExecutorPool::Task SyncManager::GetSyncTask(int32_t retry, RefCount ref, SyncInfo &&syncInfo) +ExecutorPool::Task SyncManager::GetSyncTask(int32_t times, bool retry, RefCount ref, SyncInfo &&syncInfo) { - retry++; - return [this, retry, ref = std::move(ref), info = std::move(syncInfo)]() mutable { - EventCenter::Defer defer(GetSyncHandler(), CloudEvent::CLOUD_SYNC); + times++; + return [this, times, retry, ref = std::move(ref), info = std::move(syncInfo)]() mutable { + activeInfos_.Erase(info.syncId_); CloudInfo cloud; cloud.user = info.user_; if (!MetaDataManager::GetInstance().LoadMeta(cloud.GetKey(), cloud, true)) { @@ -179,11 +185,14 @@ ExecutorPool::Task SyncManager::GetSyncTask(int32_t retry, RefCount ref, SyncInf std::vector schemas; auto key = cloud.GetSchemaPrefix(info.bundleName_); + auto retryer = GetRetryer(times, info); if (!MetaDataManager::GetInstance().LoadMeta(key, schemas, true)) { - DoRetry(retry, std::move(info)); + UpdateSchema(info); + retryer(RETRY_INTERVAL, E_RETRY_TIMEOUT); return; } + Defer defer(GetSyncHandler(std::move(retryer)), CloudEvent::CLOUD_SYNC); for (auto &schema : schemas) { if (!cloud.IsOn(schema.bundleName)) { continue; @@ -197,24 +206,18 @@ ExecutorPool::Task SyncManager::GetSyncTask(int32_t retry, RefCount ref, SyncInf storeInfo.instanceId = cloud.apps[schema.bundleName].instanceId; auto query = info.GenerateQuery(database.name, database.GetTableNames()); auto evt = std::make_unique(std::move(storeInfo), - SyncEvent::EventInfo { info.mode_, info.wait_, std::move(query), info.async_ }); + SyncEvent::EventInfo { info.mode_, info.wait_, retry, std::move(query), info.async_ }); EventCenter::GetInstance().PostEvent(std::move(evt)); } } }; } -std::function SyncManager::GetSyncHandler() +std::function SyncManager::GetSyncHandler(Retryer retryer) { - return [](const Event &event) { + return [retryer](const Event &event) { auto &evt = static_cast(event); auto &storeInfo = evt.GetStoreInfo(); - auto instance = CloudServer::GetInstance(); - if (instance == nullptr) { - ZLOGD("not support cloud sync"); - return; - } - StoreMetaData meta; meta.storeId = storeInfo.storeName; meta.bundleName = storeInfo.bundleName; @@ -226,35 +229,32 @@ std::function SyncManager::GetSyncHandler() meta.GetStoreAlias().c_str()); return; } - auto store = AutoCache::GetInstance().GetStore(meta, {}); + auto store = GetStore(meta, storeInfo.user); if (store == nullptr) { ZLOGE("store null, storeId:%{public}s", meta.GetStoreAlias().c_str()); return; } - if (!store->IsBound()) { - CloudInfo info; - info.user = storeInfo.user; - SchemaMeta schemaMeta; - std::string schemaKey = info.GetSchemaKey(storeInfo.bundleName, storeInfo.instanceId); - if (!MetaDataManager::GetInstance().LoadMeta(std::move(schemaKey), schemaMeta, true)) { - ZLOGE("failed, no schema bundleName:%{public}s, storeId:%{public}s", storeInfo.bundleName.c_str(), - Anonymous::Change(storeInfo.storeName).c_str()); - return; - } - auto dbMeta = schemaMeta.GetDataBase(storeInfo.storeName); - auto cloudDB = instance->ConnectCloudDB(meta.tokenId, dbMeta); - auto assetLoader = instance->ConnectAssetLoader(meta.tokenId, dbMeta); - if (cloudDB == nullptr || assetLoader == nullptr) { - ZLOGE("failed, no cloud DB or no assetLoader <0x%{public}x %{public}s<->%{public}s>", storeInfo.tokenId, - dbMeta.name.c_str(), dbMeta.alias.c_str()); - return; + ZLOGD("database:<%{public}d:%{public}s:%{public}s> sync start", storeInfo.user, storeInfo.bundleName.c_str(), + meta.GetStoreAlias().c_str()); + auto status = store->Sync({ SyncInfo::DEFAULT_ID }, evt.GetMode(), *(evt.GetQuery()), evt.AutoRetry() + ? [retryer](const GenDetails &details) { + if (details.empty()) { + ZLOGE("retry, details empty"); + return; + } + int32_t code = details.begin()->second.code; + retryer(code == E_ALREADY_LOCKED ? LOCKED_INTERVAL : RETRY_INTERVAL, code); } - store->Bind(dbMeta, {cloudDB, assetLoader}); + : evt.GetAsyncDetail(), evt.GetWait()); + GenAsync async = evt.GetAsyncDetail(); + if (status != E_OK && async) { + GenDetails details; + auto &detail = details[SyncInfo::DEFAULT_ID]; + detail.progress = SYNC_FINISH; + detail.code = status; + async(std::move(details)); } - ZLOGD("database:<%{public}d:%{public}s:%{public}s> sync start", storeInfo.user, storeInfo.bundleName.c_str(), - Anonymous::Change(storeInfo.storeName).c_str()); - store->Sync({ SyncInfo::DEFAULT_ID }, evt.GetMode(), *(evt.GetQuery()), evt.GetAsyncDetail(), evt.GetWait()); }; } @@ -268,15 +268,44 @@ std::function SyncManager::GetClientChangeHandler() syncInfo.SetWait(evt.GetWait()); syncInfo.SetAsyncDetail(evt.GetAsyncDetail()); syncInfo.SetQuery(evt.GetQuery()); - auto task = GetSyncTask(RETRY_TIMES, RefCount(), std::move(syncInfo)); + auto times = evt.AutoRetry() ? RETRY_TIMES - CLIENT_RETRY_TIMES : RETRY_TIMES; + auto task = GetSyncTask(times, evt.AutoRetry(), RefCount(), std::move(syncInfo)); task(); }; } -uint64_t SyncManager::GenSyncId(int32_t user) +SyncManager::Retryer SyncManager::GetRetryer(int32_t times, const SyncInfo &syncInfo) +{ + if (times >= RETRY_TIMES) { + return [info = SyncInfo(syncInfo)](Duration, int32_t code) mutable { + if (code == E_OK) { + return true; + } + info.SetError(code); + return true; + }; + } + return [this, times, info = SyncInfo(syncInfo)](Duration interval, int32_t code) mutable { + if (code == E_OK) { + return true; + } + + activeInfos_.ComputeIfAbsent(info.syncId_, [this, times, interval, &info](uint64_t key) mutable { + auto syncId = GenerateId(info.user_); + actives_.Compute(syncId, [this, times, interval, &info](const uint64_t &key, TaskId &value) mutable { + value = executor_->Schedule(interval, GetSyncTask(times, true, GenSyncRef(key), std::move(info))); + return true; + }); + return syncId; + }); + return true; + }; +} + +uint64_t SyncManager::GenerateId(int32_t user) { uint64_t syncId = static_cast(user) & 0xFFFFFFFF; - return (syncId << MV_BIT) | (++syncId_); + return (syncId << MV_BIT) | (++genId_); } RefCount SyncManager::GenSyncRef(uint64_t syncId) @@ -292,19 +321,51 @@ int32_t SyncManager::Compare(uint64_t syncId, int32_t user) return (syncId & USER_MARK) == (inner << MV_BIT); } -void SyncManager::DoRetry(int32_t retry, SyncInfo &&info) +void SyncManager::UpdateSchema(const SyncManager::SyncInfo &syncInfo) { CloudEvent::StoreInfo storeInfo; - storeInfo.user = info.user_; - storeInfo.bundleName = info.bundleName_; + storeInfo.user = syncInfo.user_; + storeInfo.bundleName = syncInfo.bundleName_; EventCenter::GetInstance().PostEvent(std::make_unique(CloudEvent::GET_SCHEMA, storeInfo)); - if (retry > RETRY_TIMES) { - info.SetError(E_RETRY_TIMEOUT); - return; +} + +AutoCache::Store SyncManager::GetStore(const StoreMetaData &meta, int32_t user, bool mustBind) +{ + auto instance = CloudServer::GetInstance(); + if (instance == nullptr) { + ZLOGD("not support cloud sync"); + return nullptr; } - actives_.Compute(GenSyncId(info.user_), [this, retry, &info](const uint64_t &key, TaskId &value) mutable { - value = executor_->Schedule(RETRY_INTERVAL, GetSyncTask(retry, GenSyncRef(key), std::move(info))); - return true; - }); + + auto store = AutoCache::GetInstance().GetStore(meta, {}); + if (store == nullptr) { + ZLOGE("store null, storeId:%{public}s", meta.GetStoreAlias().c_str()); + return nullptr; + } + + if (!store->IsBound()) { + CloudInfo info; + info.user = user; + SchemaMeta schemaMeta; + std::string schemaKey = info.GetSchemaKey(meta.bundleName, meta.instanceId); + if (!MetaDataManager::GetInstance().LoadMeta(std::move(schemaKey), schemaMeta, true)) { + ZLOGE("failed, no schema bundleName:%{public}s, storeId:%{public}s", meta.bundleName.c_str(), + meta.GetStoreAlias().c_str()); + return nullptr; + } + auto dbMeta = schemaMeta.GetDataBase(meta.storeId); + auto cloudDB = instance->ConnectCloudDB(meta.tokenId, dbMeta); + auto assetLoader = instance->ConnectAssetLoader(meta.tokenId, dbMeta); + if (mustBind && (cloudDB == nullptr || assetLoader == nullptr)) { + ZLOGE("failed, no cloud DB <0x%{public}x %{public}s<->%{public}s>", meta.tokenId, dbMeta.name.c_str(), + dbMeta.alias.c_str()); + return nullptr; + } + + if (cloudDB != nullptr || assetLoader != nullptr) { + store->Bind(dbMeta, { std::move(cloudDB), std::move(assetLoader) }); + } + } + return store; } } // namespace OHOS::CloudData \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/cloud/sync_manager.h b/datamgr_service/services/distributeddataservice/service/cloud/sync_manager.h index b08fcf4ac9930f17db9b134c0dabc86617974b4f..5f19611d598e45c9abe87e25ad5fbea9ad0bc2d1 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/sync_manager.h +++ b/datamgr_service/services/distributeddataservice/service/cloud/sync_manager.h @@ -17,6 +17,7 @@ #define OHOS_DISTRIBUTED_DATA_SERVICES_CLOUD_SYNC_MANAGER_H #include "eventcenter/event.h" #include "executor_pool.h" +#include "store/auto_cache.h" #include "store/general_store.h" #include "store/general_value.h" #include "utils/ref_count.h" @@ -28,6 +29,9 @@ public: using GenStore = DistributedData::GeneralStore; using GenQuery = DistributedData::GenQuery; using RefCount = DistributedData::RefCount; + using AutoCache = DistributedData::AutoCache; + using StoreMetaData = DistributedData::StoreMetaData; + static AutoCache::Store GetStore(const StoreMetaData &meta, int32_t user, bool mustBind = true); class SyncInfo final { public: using Store = std::string; @@ -41,12 +45,13 @@ public: void SetWait(int32_t wait); void SetAsyncDetail(GenAsync asyncDetail); void SetQuery(std::shared_ptr query); - void SetError(int32_t code); + void SetError(int32_t code) const; std::shared_ptr GenerateQuery(const std::string &store, const Tables &tables); inline static constexpr const char *DEFAULT_ID = "default"; private: friend SyncManager; + uint64_t syncId_ = 0; int32_t mode_ = GenStore::CLOUD_TIME_FIRST; int32_t user_ = 0; int32_t wait_ = 0; @@ -66,22 +71,29 @@ private: using Event = DistributedData::Event; using Task = ExecutorPool::Task; using TaskId = ExecutorPool::TaskId; + using Duration = ExecutorPool::Duration; + using Retryer = std::function; + static constexpr ExecutorPool::Duration RETRY_INTERVAL = std::chrono::seconds(10); // second - static constexpr int32_t RETRY_TIMES = 6; // second + static constexpr ExecutorPool::Duration LOCKED_INTERVAL = std::chrono::seconds(30); // second + static constexpr int32_t RETRY_TIMES = 6; // normal retry + static constexpr int32_t CLIENT_RETRY_TIMES = 3; // normal retry static constexpr uint64_t USER_MARK = 0xFFFFFFFF00000000; // high 32 bit static constexpr int32_t MV_BIT = 32; - Task GetSyncTask(int32_t retry, RefCount ref, SyncInfo &&syncInfo); - void DoRetry(int32_t retry, SyncInfo &&info); - std::function GetSyncHandler(); + Task GetSyncTask(int32_t times, bool retry, RefCount ref, SyncInfo &&syncInfo); + void UpdateSchema(const SyncInfo &syncInfo); + std::function GetSyncHandler(Retryer retryer); std::function GetClientChangeHandler(); - uint64_t GenSyncId(int32_t user); + Retryer GetRetryer(int32_t times, const SyncInfo &syncInfo); + static uint64_t GenerateId(int32_t user); RefCount GenSyncRef(uint64_t syncId); int32_t Compare(uint64_t syncId, int32_t user); - std::atomic syncId_ = 0; + static std::atomic genId_; std::shared_ptr executor_; ConcurrentMap actives_; + ConcurrentMap activeInfos_; }; } // namespace OHOS::CloudData #endif // OHOS_DISTRIBUTED_DATA_SERVICES_CLOUD_SYNC_MANAGER_H diff --git a/datamgr_service/services/distributeddataservice/service/data_share/BUILD.gn b/datamgr_service/services/distributeddataservice/service/data_share/BUILD.gn index 2d8ffad46a2457495d8ec68dd369e1940ea9d150..8cb08cb8e615c4a2a1d75cc6f780e9417b00f9d2 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/data_share/BUILD.gn @@ -68,6 +68,7 @@ ohos_shared_library("data_share_service") { "strategies/insert_strategy.cpp", "strategies/publish_strategy.cpp", "strategies/query_strategy.cpp", + "strategies/rdb_notify_strategy.cpp", "strategies/subscribe_strategy.cpp", "strategies/template_strategy.cpp", "strategies/update_strategy.cpp", @@ -99,7 +100,7 @@ ohos_shared_library("data_share_service") { "c_utils:utils", "data_share:datashare_common", "device_manager:devicemanagersdk", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", "ipc:ipc_core", "relational_store:native_rdb", "relational_store:rdb_bms_adapter", diff --git a/datamgr_service/services/distributeddataservice/service/data_share/common/kv_delegate.cpp b/datamgr_service/services/distributeddataservice/service/data_share/common/kv_delegate.cpp index d073668504abb73c20587c23fa2e46e8290c3b2c..9e36164adaed8b19c14a2ccf6743d041f5f5cc3a 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/common/kv_delegate.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/common/kv_delegate.cpp @@ -138,9 +138,9 @@ int32_t KvDelegate::Get(const std::string &collectionName, const Id &id, std::st std::string filter = DistributedData::Serializable::Marshall(id); if (Get(collectionName, filter, "{}", value) != E_OK) { ZLOGE("Get failed, %{public}s %{public}s", collectionName.c_str(), filter.c_str()); - return false; + return E_ERROR; } - return true; + return E_OK; } bool KvDelegate::GetVersion(const std::string &collectionName, const std::string &filter, int &version) diff --git a/datamgr_service/services/distributeddataservice/service/data_share/data/published_data.cpp b/datamgr_service/services/distributeddataservice/service/data_share/data/published_data.cpp index a3cb46ed155125dc8511c6f697fb33d147de5779..416b27c9e08e7d6ce24b24376540bb017c095c04 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/data/published_data.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/data/published_data.cpp @@ -16,6 +16,7 @@ #include "published_data.h" #include "log_print.h" +#include "subscriber_managers/published_data_subscriber_manager.h" namespace OHOS::DataShare { bool PublishedData::HasVersion() const @@ -33,8 +34,7 @@ std::string PublishedData::GetValue() const return DistributedData::Serializable::Marshall(value); } -PublishedData::PublishedData(const PublishedDataNode &node, const int version) - : PublishedData(node) +PublishedData::PublishedData(const PublishedDataNode &node, const int version) : PublishedData(node) { value.SetVersion(version); } @@ -84,10 +84,13 @@ bool PublishedDataNode::Unmarshal(const DistributedData::Serializable::json &nod bool ret = GetValue(node, GET_NAME(key), key); ret = ret && GetValue(node, GET_NAME(bundleName), bundleName); ret = ret && GetValue(node, GET_NAME(subscriberId), subscriberId); - ret = ret && GetValue(node, GET_NAME(value), value); + if (ret) { + GetValue(node, GET_NAME(value), value); + VersionData::Unmarshal(node); + } ret = ret && GetValue(node, GET_NAME(timestamp), timestamp); ret = ret && GetValue(node, GET_NAME(userId), userId); - return ret && VersionData::Unmarshal(node); + return ret; } PublishedDataNode::PublishedDataNode(const std::string &key, const std::string &bundleName, int64_t subscriberId, @@ -159,7 +162,10 @@ void PublishedData::ClearAging() return; } std::vector queryResults; - int32_t status = delegate->GetBatch(KvDBDelegate::DATA_TABLE, "{}", "{}", queryResults); + int32_t status = delegate->GetBatch(KvDBDelegate::DATA_TABLE, "{}", + "{\"id_\": true, \"timestamp\": true, \"key\": true, \"bundleName\": true, \"subscriberId\": true, " + "\"userId\": true}", + queryResults); if (status != E_OK) { ZLOGE("db GetBatch failed %{public}d", status); return; @@ -171,8 +177,8 @@ void PublishedData::ClearAging() ZLOGE("Unmarshall %{public}s failed", result.c_str()); continue; } - - if (data.timestamp < lastValidTime) { + if (data.timestamp < lastValidTime && PublishedDataSubscriberManager::GetInstance() + .GetCount(PublishedDataKey(data.key, data.bundleName, data.subscriberId)) == 0) { status = delegate->Delete(KvDBDelegate::DATA_TABLE, Id(PublishedData::GenId(data.key, data.bundleName, data.subscriberId), data.userId)); if (status != E_OK) { @@ -186,4 +192,36 @@ void PublishedData::ClearAging() } return; } + +void PublishedData::UpdateTimestamp( + const std::string &key, const std::string &bundleName, int64_t subscriberId, const int32_t userId) +{ + auto delegate = KvDBDelegate::GetInstance(); + if (delegate == nullptr) { + ZLOGE("db open failed"); + return; + } + std::string queryResult; + int32_t status = + delegate->Get(KvDBDelegate::DATA_TABLE, Id(GenId(key, bundleName, subscriberId), userId), queryResult); + if (status != E_OK) { + ZLOGE("db Get failed, %{private}s %{public}d", queryResult.c_str(), status); + return; + } + PublishedDataNode data; + if (!PublishedDataNode::Unmarshall(queryResult, data)) { + ZLOGE("Unmarshall failed, %{private}s", queryResult.c_str()); + return; + } + auto now = time(nullptr); + if (now <= 0) { + ZLOGE("time failed"); + return; + } + data.timestamp = now; + status = delegate->Upsert(KvDBDelegate::DATA_TABLE, PublishedData(data)); + if (status == E_OK) { + ZLOGI("update timestamp %{private}s", data.key.c_str()); + } +} } // namespace OHOS::DataShare \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/data_share/data/published_data.h b/datamgr_service/services/distributeddataservice/service/data_share/data/published_data.h index aba9ee9f448343eb40225dadb74a2a029bd1904b..cff038a3bf972267ceb9219043839cf1aacd0e2b 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/data/published_data.h +++ b/datamgr_service/services/distributeddataservice/service/data_share/data/published_data.h @@ -42,6 +42,8 @@ public: explicit PublishedData(const PublishedDataNode &node); static std::vector Query(const std::string &bundleName, int32_t userId); static void Delete(const std::string &bundleName, const int32_t userId); + static void UpdateTimestamp( + const std::string &key, const std::string &bundleName, int64_t subscriberId, const int32_t userId); static void ClearAging(); static int32_t Query(const std::string &filter, PublishedDataNode::Data &publishedData); static std::string GenId(const std::string &key, const std::string &bundleName, int64_t subscriberId); @@ -51,6 +53,7 @@ public: int GetVersion() const override; std::string GetValue() const override; friend class GetDataStrategy; + private: PublishedDataNode value; }; diff --git a/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_impl.cpp b/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_impl.cpp index 48f23f9181c61476498fa3d12457ca21163c5b75..568c10463ecf45c2ce1c0d865110046c7c8bce77 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_impl.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_impl.cpp @@ -214,7 +214,7 @@ std::vector DataShareServiceImpl::SubscribeRdbData( std::vector results; for (const auto &uri : uris) { auto context = std::make_shared(uri); - results.emplace_back(uri, subscribeStrategy_.Execute(context, [&id, &observer, &context, this]() -> bool { + results.emplace_back(uri, subscribeStrategy_.Execute(context, [&id, &observer, &context, this]() { return RdbSubscriberManager::GetInstance().Add( Key(context->uri, id.subscriberId_, id.bundleName_), observer, context, binderInfo_.executors); })); @@ -228,7 +228,7 @@ std::vector DataShareServiceImpl::UnsubscribeRdbData( std::vector results; for (const auto &uri : uris) { auto context = std::make_shared(uri); - results.emplace_back(uri, subscribeStrategy_.Execute(context, [&id, &context]() -> bool { + results.emplace_back(uri, subscribeStrategy_.Execute(context, [&id, &context]() { return RdbSubscriberManager::GetInstance().Delete( Key(context->uri, id.subscriberId_, id.bundleName_), context->callerTokenId); })); @@ -242,7 +242,7 @@ std::vector DataShareServiceImpl::EnableRdbSubs( std::vector results; for (const auto &uri : uris) { auto context = std::make_shared(uri); - results.emplace_back(uri, subscribeStrategy_.Execute(context, [&id, &context]() -> bool { + results.emplace_back(uri, subscribeStrategy_.Execute(context, [&id, &context]() { return RdbSubscriberManager::GetInstance().Enable( Key(context->uri, id.subscriberId_, id.bundleName_), context); })); @@ -256,7 +256,7 @@ std::vector DataShareServiceImpl::DisableRdbSubs( std::vector results; for (const auto &uri : uris) { auto context = std::make_shared(uri); - results.emplace_back(uri, subscribeStrategy_.Execute(context, [&id, &context]() -> bool { + results.emplace_back(uri, subscribeStrategy_.Execute(context, [&id, &context]() { return RdbSubscriberManager::GetInstance().Disable( Key(context->uri, id.subscriberId_, id.bundleName_), context->callerTokenId); })); @@ -281,7 +281,7 @@ std::vector DataShareServiceImpl::SubscribePublishedData(const PublishedDataKey key(uri, callerBundleName, subscriberId); context->callerBundleName = callerBundleName; context->calledBundleName = key.bundleName; - result = subscribeStrategy_.Execute(context, [&subscriberId, &observer, &context]() -> bool { + result = subscribeStrategy_.Execute(context, [&subscriberId, &observer, &context]() { return PublishedDataSubscriberManager::GetInstance().Add( PublishedDataKey(context->uri, context->callerBundleName, subscriberId), observer, context->callerTokenId); @@ -289,6 +289,12 @@ std::vector DataShareServiceImpl::SubscribePublishedData(const results.emplace_back(uri, result); if (result == E_OK) { publishedKeys.emplace_back(context->uri, context->callerBundleName, subscriberId); + if (binderInfo_.executors != nullptr) { + binderInfo_.executors->Execute([context, subscriberId]() { + PublishedData::UpdateTimestamp( + context->uri, context->calledBundleName, subscriberId, context->currentUserId); + }); + } userId = context->currentUserId; } } @@ -312,9 +318,16 @@ std::vector DataShareServiceImpl::UnsubscribePublishedData(cons PublishedDataKey key(uri, callerBundleName, subscriberId); context->callerBundleName = callerBundleName; context->calledBundleName = key.bundleName; - results.emplace_back(uri, subscribeStrategy_.Execute(context, [&subscriberId, &context]() -> bool { - return PublishedDataSubscriberManager::GetInstance().Delete( + results.emplace_back(uri, subscribeStrategy_.Execute(context, [&subscriberId, &context, this]() { + auto result = PublishedDataSubscriberManager::GetInstance().Delete( PublishedDataKey(context->uri, context->callerBundleName, subscriberId), context->callerTokenId); + if (result == E_OK && binderInfo_.executors != nullptr) { + binderInfo_.executors->Execute([context, subscriberId]() { + PublishedData::UpdateTimestamp( + context->uri, context->calledBundleName, subscriberId, context->currentUserId); + }); + } + return result; })); } return results; @@ -337,10 +350,16 @@ std::vector DataShareServiceImpl::EnablePubSubs(const std::vect PublishedDataKey key(uri, callerBundleName, subscriberId); context->callerBundleName = callerBundleName; context->calledBundleName = key.bundleName; - result = subscribeStrategy_.Execute(context, [&subscriberId, &context]() -> bool { + result = subscribeStrategy_.Execute(context, [&subscriberId, &context]() { return PublishedDataSubscriberManager::GetInstance().Enable( PublishedDataKey(context->uri, context->callerBundleName, subscriberId), context->callerTokenId); }); + if (result == E_OK && binderInfo_.executors != nullptr) { + binderInfo_.executors->Execute([context, subscriberId]() { + PublishedData::UpdateTimestamp( + context->uri, context->calledBundleName, subscriberId, context->currentUserId); + }); + } results.emplace_back(uri, result); if (result == E_OK) { publishedKeys.emplace_back(context->uri, context->callerBundleName, subscriberId); @@ -367,9 +386,16 @@ std::vector DataShareServiceImpl::DisablePubSubs(const std::vec PublishedDataKey key(uri, callerBundleName, subscriberId); context->callerBundleName = callerBundleName; context->calledBundleName = key.bundleName; - results.emplace_back(uri, subscribeStrategy_.Execute(context, [&subscriberId, &context]() -> bool { - return PublishedDataSubscriberManager::GetInstance().Disable( + results.emplace_back(uri, subscribeStrategy_.Execute(context, [&subscriberId, &context, this]() { + auto result = PublishedDataSubscriberManager::GetInstance().Disable( PublishedDataKey(context->uri, context->callerBundleName, subscriberId), context->callerTokenId); + if (result == E_OK && binderInfo_.executors != nullptr) { + binderInfo_.executors->Execute([context, subscriberId]() { + PublishedData::UpdateTimestamp( + context->uri, context->calledBundleName, subscriberId, context->currentUserId); + }); + } + return result; })); } return results; @@ -434,4 +460,19 @@ int32_t DataShareServiceImpl::OnAppUninstall( RdbHelper::ClearCache(); return EOK; } + +void DataShareServiceImpl::NotifyObserver(const std::string &uri) +{ + ZLOGD("%{private}s try notified", uri.c_str()); + auto context = std::make_shared(uri); + if (!GetCallerBundleName(context->callerBundleName)) { + ZLOGE("get bundleName error, %{private}s", uri.c_str()); + return; + } + auto ret = rdbNotifyStrategy_.Execute(context); + if (ret) { + ZLOGI("%{private}s start notified", uri.c_str()); + RdbSubscriberManager::GetInstance().Emit(uri, context); + } +} } // namespace OHOS::DataShare diff --git a/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_impl.h b/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_impl.h index 493882da6418fa5e1bf65aaed92f4da247905568..72d102ca4adfc4cbf038f5dfdd12b05685acd7e0 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_impl.h +++ b/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_impl.h @@ -27,6 +27,7 @@ #include "insert_strategy.h" #include "publish_strategy.h" #include "query_strategy.h" +#include "rdb_notify_strategy.h" #include "subscribe_strategy.h" #include "template_strategy.h" #include "update_strategy.h" @@ -67,6 +68,7 @@ public: int32_t OnBind(const BindInfo &binderInfo) override; int32_t OnUserChange(uint32_t code, const std::string &user, const std::string &account) override; int32_t OnAppUninstall(const std::string &bundleName, int32_t user, int32_t index, uint32_t tokenId) override; + void NotifyObserver(const std::string &uri) override; private: class Factory { @@ -87,6 +89,7 @@ private: QueryStrategy queryStrategy_; UpdateStrategy updateStrategy_; TemplateStrategy templateStrategy_; + RdbNotifyStrategy rdbNotifyStrategy_; BindInfo binderInfo_; }; } // namespace OHOS::DataShare diff --git a/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_stub.cpp b/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_stub.cpp index 852b874bd7e3c954bc8b97f25d9df45d60695adc..99383d0849b352dc1b020af6346195ab883ea0c7 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_stub.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_stub.cpp @@ -329,5 +329,16 @@ int DataShareServiceStub::OnRemoteRequest(uint32_t code, MessageParcel &data, Me } return -1; } + +int32_t DataShareServiceStub::OnRemoteNotifyObserver(MessageParcel &data, MessageParcel &reply) +{ + std::string uri; + if (!ITypesUtil::Unmarshal(data, uri)) { + ZLOGE("read device list failed."); + return -1; + } + NotifyObserver(uri); + return 0; +} } // namespace DataShare } // namespace OHOS \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_stub.h b/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_stub.h index d7e1dc27cc332518c0edac0db751134156e373b3..17ac116ac1b3b4fdd04473f0a894251491bb7281 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_stub.h +++ b/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_stub.h @@ -44,6 +44,7 @@ private: int32_t OnRemoteEnablePubSubs(MessageParcel& data, MessageParcel& reply); int32_t OnRemoteDisablePubSubs(MessageParcel& data, MessageParcel& reply); int32_t OnRemoteNotifyConnectDone(MessageParcel& data, MessageParcel& reply); + int32_t OnRemoteNotifyObserver(MessageParcel& data, MessageParcel& reply); using RequestHandle = int (DataShareServiceStub::*)(MessageParcel &, MessageParcel &); static constexpr RequestHandle HANDLERS[DATA_SHARE_SERVICE_CMD_MAX] = { &DataShareServiceStub::OnRemoteInsert, @@ -62,7 +63,8 @@ private: &DataShareServiceStub::OnRemoteUnsubscribePublishedData, &DataShareServiceStub::OnRemoteEnablePubSubs, &DataShareServiceStub::OnRemoteDisablePubSubs, - &DataShareServiceStub::OnRemoteNotifyConnectDone }; + &DataShareServiceStub::OnRemoteNotifyConnectDone, + &DataShareServiceStub::OnRemoteNotifyObserver }; }; } // namespace DataShare } // namespace OHOS diff --git a/datamgr_service/services/distributeddataservice/service/data_share/gaussdb_rd/BUILD.gn b/datamgr_service/services/distributeddataservice/service/data_share/gaussdb_rd/BUILD.gn index 47128f8c80d67b921fc167490beeee2ead9e6e6c..293099f30c6956f235bcf8c96c02adf9901b3f9f 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/gaussdb_rd/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/data_share/gaussdb_rd/BUILD.gn @@ -82,9 +82,9 @@ ohos_shared_library("gaussdb_rd") { external_deps = [ "c_utils:utils", - "hisysevent_native:libhisysevent", - "hitrace_native:hitrace_meter", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", + "hisysevent:libhisysevent", + "hitrace:hitrace_meter", ] subsystem_name = "distributeddatamgr" diff --git a/datamgr_service/services/distributeddataservice/service/data_share/gaussdb_rd/src/executor/document/check_common.cpp b/datamgr_service/services/distributeddataservice/service/data_share/gaussdb_rd/src/executor/document/check_common.cpp index 01513f9f83652c107f714e2e1e4e41d288db0c66..52891fe1b5efbc223f844115b7adba2c1237d29f 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/gaussdb_rd/src/executor/document/check_common.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/gaussdb_rd/src/executor/document/check_common.cpp @@ -155,34 +155,50 @@ int CheckCommon::CheckDocument(JsonObject &documentObj) return E_OK; } -int CheckCommon::CheckUpdata(JsonObject &updataObj, std::vector> &path) +int SplitFieldName(const std::string &fieldName, std::vector &allFieldsName) { - if (updataObj.GetDeep() > JSON_DEEP_MAX) { - GLOGE("projectionObj's json deep is deeper than JSON_DEEP_MAX"); - return -E_INVALID_ARGS; - } - for (size_t i = 0; i < path.size(); i++) { - if (path[i].empty()) { - return -E_INVALID_JSON_FORMAT; + std::string tempParseName; + std::string priFieldName = fieldName; + for (size_t j = 0; j < priFieldName.size(); j++) { + if (priFieldName[j] != '.') { + tempParseName += priFieldName[j]; } - for (size_t j = 0; j < path[i].size(); j++) { - if (path[i][j].empty()) { + if (priFieldName[j] == '.' || j == priFieldName.size() - 1) { + if ((j > 0 && priFieldName[j] == '.' && priFieldName[j - 1] == '.') || + (priFieldName[j] == '.' && j == priFieldName.size() - 1)) { return -E_INVALID_ARGS; } - for (auto oneChar : path[i][j]) { + allFieldsName.emplace_back(tempParseName); + tempParseName.clear(); + } + } + return E_OK; +} + +int CheckCommon::CheckUpdata(JsonObject &updataObj) +{ + JsonObject jsonTemp = updataObj.GetChild(); + size_t maxDeep = 0; + while (!jsonTemp.IsNull()) { + std::vector allFieldsName; + int errCode = SplitFieldName(jsonTemp.GetItemField(), allFieldsName); + if (errCode != E_OK) { + return errCode; + } + for (auto fieldName : allFieldsName) { + for (auto oneChar : fieldName) { if (!((isalpha(oneChar)) || (isdigit(oneChar)) || (oneChar == '_'))) { + GLOGE("updata fieldName is illegal"); return -E_INVALID_ARGS; } } } - if (!path[i].empty() && !path[i][0].empty() && isdigit(path[i][0][0])) { - return -E_INVALID_ARGS; - } - } - for (const auto &singlePath : path) { - if (singlePath.size() > JSON_DEEP_MAX) { + maxDeep = std::max(allFieldsName.size() + jsonTemp.GetDeep(), maxDeep); + if (maxDeep > JSON_DEEP_MAX) { + GLOGE("document's json deep is deeper than JSON_DEEP_MAX"); return -E_INVALID_ARGS; } + jsonTemp = jsonTemp.GetNext(); } bool isIdExist = true; CheckIdFormat(updataObj, isIdExist); diff --git a/datamgr_service/services/distributeddataservice/service/data_share/gaussdb_rd/src/executor/document/check_common.h b/datamgr_service/services/distributeddataservice/service/data_share/gaussdb_rd/src/executor/document/check_common.h index 2985bd679b8acbd9e09a3d73d6a282cb3f7dda73..e9ae11809381d9ceca10f2b748b1b559e71408b4 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/gaussdb_rd/src/executor/document/check_common.h +++ b/datamgr_service/services/distributeddataservice/service/data_share/gaussdb_rd/src/executor/document/check_common.h @@ -32,7 +32,7 @@ public: static int CheckFilter(JsonObject &filterObj, bool &isOnlyId, std::vector> &filterPath); static int CheckIdFormat(JsonObject &filterJson, bool &isIdExisit); static int CheckDocument(JsonObject &documentObj); - static int CheckUpdata(JsonObject &updataObj, std::vector> &path); + static int CheckUpdata(JsonObject &updata); static int CheckProjection(JsonObject &projectionObj, std::vector> &path); }; using Key = std::vector; diff --git a/datamgr_service/services/distributeddataservice/service/data_share/gaussdb_rd/src/interface/src/document_store.cpp b/datamgr_service/services/distributeddataservice/service/data_share/gaussdb_rd/src/interface/src/document_store.cpp index 1b50f92a66f800c39f275457bbf5be22a5a94c6c..caa230c13c31e7ef833204429db5c9241335a8d8 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/gaussdb_rd/src/interface/src/document_store.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/gaussdb_rd/src/interface/src/document_store.cpp @@ -157,13 +157,7 @@ int UpdateArgsCheck(const std::string &collection, const std::string &filter, co return errCode; } if (update != "{}") { - std::vector> allPath; - allPath = JsonCommon::ParsePath(updateObj, errCode); - if (errCode != E_OK) { - GLOGE("updateObj ParsePath failed"); - return errCode; - } - errCode = CheckCommon::CheckUpdata(updateObj, allPath); + errCode = CheckCommon::CheckUpdata(updateObj); if (errCode != E_OK) { GLOGE("Updata format is illegal"); return errCode; @@ -343,12 +337,7 @@ int UpsertDocumentFormatCheck(const std::string &document, JsonObject &documentO { int errCode = E_OK; if (document != "{}") { - std::vector> allPath; - allPath = JsonCommon::ParsePath(documentObj, errCode); - if (errCode != E_OK) { - return errCode; - } - errCode = CheckCommon::CheckUpdata(documentObj, allPath); + errCode = CheckCommon::CheckUpdata(documentObj); if (errCode != E_OK) { GLOGE("UpsertDocument document format is illegal"); return errCode; diff --git a/datamgr_service/services/distributeddataservice/service/data_share/gaussdb_rd/src/interface/src/projection_tree.cpp b/datamgr_service/services/distributeddataservice/service/data_share/gaussdb_rd/src/interface/src/projection_tree.cpp index 5c37b84bf1a2e65b985790fdccce431e1217125d..4ab699c391b76942f6a9512b545c408308f9ebd3 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/gaussdb_rd/src/interface/src/projection_tree.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/gaussdb_rd/src/interface/src/projection_tree.cpp @@ -58,11 +58,11 @@ bool ProjectionTree::SearchTree(std::vector &singlePath, size_t &in { ProjectionNode *node = &node_; for (size_t i = 0; i < singlePath.size(); i++) { - if (node->isDeepest) { - index = i; - } if (node->sonNode[singlePath[i]] != nullptr) { node = node->sonNode[singlePath[i]]; + if (node->isDeepest) { + index = i + 1; + } } else { return false; } diff --git a/datamgr_service/services/distributeddataservice/service/data_share/gaussdb_rd/src/interface/src/result_set.cpp b/datamgr_service/services/distributeddataservice/service/data_share/gaussdb_rd/src/interface/src/result_set.cpp index 6c221daa464e189efd046028ad0cc9f40154ee70..225a8bc8fa67d6f8c9776714198b8828a32731bb 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/gaussdb_rd/src/interface/src/result_set.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/gaussdb_rd/src/interface/src/result_set.cpp @@ -190,22 +190,25 @@ int ResultSet::CheckCutNode(JsonObject *node, std::vector singlePat GLOGE("No node to cut"); return -E_NO_DATA; } - singlePath.emplace_back(node->GetItemField()); - size_t index = 0; - if (!context_->projectionTree.SearchTree(singlePath, index) && index == 0) { - allCutPath.emplace_back(singlePath); - } - if (!node->GetChild().IsNull()) { - JsonObject nodeNew = node->GetChild(); - CheckCutNode(&nodeNew, singlePath, allCutPath); - } - if (!node->GetNext().IsNull()) { + JsonObject nodeInstance = *node; + while (!nodeInstance.IsNull()) { + singlePath.emplace_back(nodeInstance.GetItemField()); + size_t index = 0; + bool isMatch = context_->projectionTree.SearchTree(singlePath, index); + if ((nodeInstance.GetType() == JsonObject::Type::JSON_ARRAY && isMatch && index == 0) || + (!isMatch && index == 0)) { + allCutPath.emplace_back(singlePath); + } + if (nodeInstance.GetType() != JsonObject::Type::JSON_ARRAY && !nodeInstance.GetChild().IsNull()) { + JsonObject nodeChiled = nodeInstance.GetChild(); + CheckCutNode(&nodeChiled, singlePath, allCutPath); + } singlePath.pop_back(); - JsonObject nodeNew = node->GetNext(); - CheckCutNode(&nodeNew, singlePath, allCutPath); + nodeInstance = nodeInstance.GetNext(); } return E_OK; } + int ResultSet::CutJsonBranch(std::string &jsonData) { int errCode; diff --git a/datamgr_service/services/distributeddataservice/service/data_share/gaussdb_rd/src/oh_adapter/include/json_object.h b/datamgr_service/services/distributeddataservice/service/data_share/gaussdb_rd/src/oh_adapter/include/json_object.h index afd0489dd033c0a8c6928ab4ed4dd4a1e93c33ff..9680c82c81f41804bf5256a936d0ebd240a695b6 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/gaussdb_rd/src/oh_adapter/include/json_object.h +++ b/datamgr_service/services/distributeddataservice/service/data_share/gaussdb_rd/src/oh_adapter/include/json_object.h @@ -106,8 +106,8 @@ public: private: JsonObject(); int Init(const std::string &str, bool isFilter = false); - int CheckJsonRepeatField(cJSON *object); - int CheckSubObj(std::set &fieldSet, cJSON *subObj, int parentType); + int CheckJsonRepeatField(cJSON *object, bool isFirstFloor); + int CheckSubObj(std::set &fieldSet, cJSON *subObj, int parentType, bool isFirstFloor); int GetDeep(cJSON *cjson); int CheckNumber(cJSON *cjson, int &errCode); cJSON *cjson_ = nullptr; diff --git a/datamgr_service/services/distributeddataservice/service/data_share/gaussdb_rd/src/oh_adapter/src/json_object.cpp b/datamgr_service/services/distributeddataservice/service/data_share/gaussdb_rd/src/oh_adapter/src/json_object.cpp index 7ac3a08c0717fc083ac31ac794a74bb24002bb12..86357c71822dad65221577933e22d3914d84654d 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/gaussdb_rd/src/oh_adapter/src/json_object.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/gaussdb_rd/src/oh_adapter/src/json_object.cpp @@ -14,9 +14,9 @@ */ #include "json_object.h" - #include #include +#include #include "doc_errno.h" #include "log_print.h" @@ -152,17 +152,23 @@ int JsonObject::GetDeep(cJSON *cjson) int JsonObject::CheckNumber(cJSON *item, int &errCode) { - if (item != NULL && cJSON_IsNumber(item)) { - double value = cJSON_GetNumberValue(item); - if (value > __DBL_MAX__ || value < -__DBL_MAX__) { - errCode = -E_INVALID_ARGS; + std::queue cjsonQueue; + cjsonQueue.push(item); + while (!cjsonQueue.empty()) { + cJSON *node = cjsonQueue.front(); + cjsonQueue.pop(); + if (node != NULL && cJSON_IsNumber(node)) { + double value = cJSON_GetNumberValue(node); + if (value > __DBL_MAX__ || value < -__DBL_MAX__) { + errCode = -E_INVALID_ARGS; + } + } + if (node->child != nullptr) { + cjsonQueue.push(node->child); + } + if (node->next != nullptr) { + cjsonQueue.push(node->next); } - } - if (item->child != nullptr) { - return CheckNumber(item->child, errCode); - } - if (item->next != nullptr) { - return CheckNumber(item->next, errCode); } return E_OK; } @@ -189,7 +195,8 @@ int JsonObject::Init(const std::string &str, bool isFilter) return -E_INVALID_ARGS; } if (!isFilter) { - ret = CheckJsonRepeatField(cjson_); + bool isFirstFloor = true; + ret = CheckJsonRepeatField(cjson_, isFirstFloor); if (ret != E_OK) { return ret; } @@ -197,7 +204,7 @@ int JsonObject::Init(const std::string &str, bool isFilter) return E_OK; } -int JsonObject::CheckJsonRepeatField(cJSON *object) +int JsonObject::CheckJsonRepeatField(cJSON *object, bool isFirstFloor) { if (object == nullptr) { return -E_INVALID_ARGS; @@ -210,7 +217,7 @@ int JsonObject::CheckJsonRepeatField(cJSON *object) std::set fieldSet; cJSON *subObj = object->child; while (subObj != nullptr) { - ret = CheckSubObj(fieldSet, subObj, type); + ret = CheckSubObj(fieldSet, subObj, type, isFirstFloor); if (ret != E_OK) { break; } @@ -219,7 +226,7 @@ int JsonObject::CheckJsonRepeatField(cJSON *object) return ret; } -int JsonObject::CheckSubObj(std::set &fieldSet, cJSON *subObj, int parentType) +int JsonObject::CheckSubObj(std::set &fieldSet, cJSON *subObj, int parentType, bool isFirstFloor) { if (subObj == nullptr) { return -E_INVALID_ARGS; @@ -227,9 +234,20 @@ int JsonObject::CheckSubObj(std::set &fieldSet, cJSON *subObj, int std::string fieldName; if (subObj->string != nullptr) { fieldName = subObj->string; + if (!isFirstFloor) { + for (auto oneChar : fieldName) { + if (!((isalpha(oneChar)) || (isdigit(oneChar)) || (oneChar == '_'))) { + return -E_INVALID_ARGS; + } + } + } + if (!fieldName.empty() && isdigit(fieldName[0])) { + return -E_INVALID_ARGS; + } } + isFirstFloor = false; if (parentType == cJSON_Array) { - return CheckJsonRepeatField(subObj); + return CheckJsonRepeatField(subObj, isFirstFloor); } if (fieldName.empty()) { return -E_INVALID_JSON_FORMAT; @@ -239,7 +257,7 @@ int JsonObject::CheckSubObj(std::set &fieldSet, cJSON *subObj, int } else { return -E_INVALID_JSON_FORMAT; } - return CheckJsonRepeatField(subObj); + return CheckJsonRepeatField(subObj, isFirstFloor); } std::string JsonObject::Print() const @@ -657,7 +675,6 @@ int JsonObject::DeleteItemOnTarget(const JsonFieldPath &path) cJSON *nodeFather = MoveToPath(cjson_, patherPath, caseSensitive_); if (nodeFather == nullptr) { - GLOGE("Delete item failed, json field path not found."); return -E_JSON_PATH_NOT_EXISTS; } @@ -690,7 +707,6 @@ int JsonObject::DeleteItemDeeplyOnTarget(const JsonFieldPath &path) cJSON *nodeFather = MoveToPath(cjson_, patherPath, caseSensitive_); if (nodeFather == nullptr) { - GLOGE("Delete item failed, json field path not found."); return -E_JSON_PATH_NOT_EXISTS; } diff --git a/datamgr_service/services/distributeddataservice/service/data_share/gaussdb_rd/test/unittest/BUILD.gn b/datamgr_service/services/distributeddataservice/service/data_share/gaussdb_rd/test/unittest/BUILD.gn index b4cc59a3ae64003eaf9c8e7dc43b34fdb12a7ed1..81eb4698a30f1ed6cd94898d24a03fb0cb152de7 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/gaussdb_rd/test/unittest/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/data_share/gaussdb_rd/test/unittest/BUILD.gn @@ -81,9 +81,9 @@ ohos_source_set("src_file") { deps += [ "//third_party/cJSON:cjson" ] external_deps = [ "c_utils:utils", - "hisysevent_native:libhisysevent", - "hitrace_native:hitrace_meter", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", + "hisysevent:libhisysevent", + "hitrace:hitrace_meter", ] subsystem_name = "distributeddatamgr" @@ -115,9 +115,9 @@ template("gaussdb_rd_unittest") { ] external_deps = [ "c_utils:utils", - "hisysevent_native:libhisysevent", - "hitrace_native:hitrace_meter", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", + "hisysevent:libhisysevent", + "hitrace:hitrace_meter", ] } } diff --git a/datamgr_service/services/distributeddataservice/service/data_share/gaussdb_rd/test/unittest/api/documentdb_find_test.cpp b/datamgr_service/services/distributeddataservice/service/data_share/gaussdb_rd/test/unittest/api/documentdb_find_test.cpp index f77761d8ca25eb7806bdf2e801a8fa2a136ab88a..654294a3c924d00700f184eecbb24f1bb28b27e5 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/gaussdb_rd/test/unittest/api/documentdb_find_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/gaussdb_rd/test/unittest/api/documentdb_find_test.cpp @@ -35,6 +35,7 @@ namespace { std::string g_path = "./document.db"; GRD_DB *g_db = nullptr; constexpr const char *COLLECTION_NAME = "student"; +constexpr const char *colName = "data_"; const int MAX_COLLECTION_NAME = 511; const int MAX_ID_LENS = 899; @@ -1464,4 +1465,41 @@ HWTEST_F(DocumentDBFindTest, DocumentDBFindTest062, TestSize.Level1) Query query = { filter, projection }; EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, 1, &resultSet), GRD_INVALID_ARGS); } + +HWTEST_F(DocumentDBFindTest, DocumentDBFindTest063, TestSize.Level1) +{ + GRD_DB *test_db = nullptr; + std::string path = "./dataShare.db"; + int status = GRD_DBOpen(path.c_str(), nullptr, GRD_DB_OPEN_CREATE, &test_db); + EXPECT_EQ(status, GRD_OK); + EXPECT_EQ(GRD_CreateCollection(test_db, colName, "", 0), GRD_OK); + string document1 = "{\"_id\":\"key2_11_com.acts.ohos.data.datasharetestclient_100\",\ + \"bundleName\":\"com.acts.ohos.data.datasharetestclient\",\"key\":\"key2\",\ + \"subscriberId\":11,\"timestamp\":1509100700,""\"userId\":100,\"value\":{\"type\":0,"; + string document2 = "\"value\":["; + string document3 = "5,"; + string document4 = document3; + for (int i = 0; i < 100000; i++) { + document4 += document3; + } + document4.push_back('5'); + string document5 = "]}}"; + string document0635 = document1 + document2 + document4 + document5; + EXPECT_EQ(GRD_InsertDoc(test_db, colName, document0635.c_str(), 0), GRD_OK); + EXPECT_EQ(status, GRD_OK); + const char *filter = "{}"; + GRD_ResultSet *resultSet = nullptr; + const char *projection = "{\"id_\":true, \"timestamp\":true, \"key\":true, \"bundleName\": true, " + "\"subscriberId\": true}"; + Query query = { filter, projection }; + EXPECT_EQ(GRD_FindDoc(test_db, colName, query, 1, &resultSet), GRD_OK); + char *value; + while (GRD_Next(resultSet) == GRD_OK) { + EXPECT_EQ(GRD_GetValue(resultSet, &value), GRD_OK); + GRD_FreeValue(value); + } + EXPECT_EQ(GRD_FreeResultSet(resultSet), GRD_OK); + EXPECT_EQ(GRD_DBClose(test_db, 0), GRD_OK); + DocumentDBTestUtils::RemoveTestDbFiles(path.c_str()); +} } // namespace diff --git a/datamgr_service/services/distributeddataservice/service/data_share/gaussdb_rd/test/unittest/oh_adapter/documentdb_json_common_test.cpp b/datamgr_service/services/distributeddataservice/service/data_share/gaussdb_rd/test/unittest/oh_adapter/documentdb_json_common_test.cpp index bec7c70ae6d54df431a954fdf29d6fa6a836869a..3e92ba176beeba13e6c5b2d16771788f07681113 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/gaussdb_rd/test/unittest/oh_adapter/documentdb_json_common_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/gaussdb_rd/test/unittest/oh_adapter/documentdb_json_common_test.cpp @@ -147,25 +147,6 @@ HWTEST_F(DocumentDBJsonCommonTest, JsonObjectAppendTest005, TestSize.Level0) EXPECT_EQ(itemCase.GetItemValue().GetStringValue(), "GG"); } -HWTEST_F(DocumentDBJsonCommonTest, JsonObjectAppendTest006, TestSize.Level0) -{ - std::string document = R""({"name":{"first":"Tno", "last":"moray"}})""; - std::string updateDoc = R""({"name":{"midle.AA":"GG"}})""; - - int errCode = E_OK; - JsonObject src = JsonObject::Parse(document, errCode); - EXPECT_EQ(errCode, E_OK); - JsonObject add = JsonObject::Parse(updateDoc, errCode); - EXPECT_EQ(errCode, E_OK); - - EXPECT_EQ(JsonCommon::Append(src, add, false), E_OK); - GLOGD("result: %s", src.Print().c_str()); - - JsonObject itemCase = src.FindItem({ "name", "midle.AA" }, errCode); - EXPECT_EQ(errCode, E_OK); - EXPECT_EQ(itemCase.GetItemValue().GetStringValue(), "GG"); -} - HWTEST_F(DocumentDBJsonCommonTest, JsonObjectAppendTest007, TestSize.Level0) { std::string document = R""({"name":{"first":["XX", "CC"], "last":"moray"}})""; diff --git a/datamgr_service/services/distributeddataservice/service/data_share/idata_share_service.h b/datamgr_service/services/distributeddataservice/service/data_share/idata_share_service.h index 1ae6824fe5edf68db22a02efa72a2efd654e6174..ce2ff44b7c94ad6dd69d2754d078d1fe0b69075e 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/idata_share_service.h +++ b/datamgr_service/services/distributeddataservice/service/data_share/idata_share_service.h @@ -46,6 +46,7 @@ public: DATA_SHARE_SERVICE_CMD_ENABLE_SUBSCRIBE_PUBLISHED, DATA_SHARE_SERVICE_CMD_DISABLE_SUBSCRIBE_PUBLISHED, DATA_SHARE_SERVICE_CMD_NOTIFY, + DATA_SHARE_SERVICE_CMD_NOTIFY_OBSERVERS, DATA_SHARE_SERVICE_CMD_MAX }; @@ -79,6 +80,7 @@ public: virtual std::vector DisablePubSubs(const std::vector &uris, const int64_t subscriberId) = 0; virtual void OnConnectDone() = 0; + virtual void NotifyObserver(const std::string &uri) = 0; }; } // namespace OHOS::DataShare #endif diff --git a/datamgr_service/services/distributeddataservice/service/data_share/strategies/rdb_notify_strategy.cpp b/datamgr_service/services/distributeddataservice/service/data_share/strategies/rdb_notify_strategy.cpp new file mode 100644 index 0000000000000000000000000000000000000000..52cb98161aa191bc95708ed2837f9c14614a3540 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/data_share/strategies/rdb_notify_strategy.cpp @@ -0,0 +1,65 @@ +/* + * 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 "RdbNotifyStrategy" + +#include "rdb_notify_strategy.h" + +#include "general/load_config_common_strategy.h" +#include "general/load_config_data_info_strategy.h" +#include "general/load_config_from_bundle_info_strategy.h" +#include "log_print.h" +#include "utils/anonymous.h" + +namespace OHOS::DataShare { +bool RdbNotifyStrategy::Execute(std::shared_ptr context) +{ + auto &preProcess = GetStrategy(); + if (preProcess.IsEmpty()) { + ZLOGE("get strategy fail, maybe memory not enough"); + return false; + } + if (!preProcess(context)) { + ZLOGE("pre process fail, uri: %{public}s", DistributedData::Anonymous::Change(context->uri).c_str()); + return false; + } + if (context->callerBundleName != context->calledBundleName) { + ZLOGE("not your data, cannot notify, callerBundleName: %{public}s, calledBundleName: %{public}s", + context->callerBundleName.c_str(), context->calledBundleName.c_str()); + return false; + } + return true; +} + +SeqStrategy &RdbNotifyStrategy::GetStrategy() +{ + std::lock_guard lock(mutex_); + if (!strategies_.IsEmpty()) { + return strategies_; + } + std::initializer_list list = { + new (std::nothrow)LoadConfigCommonStrategy(), + new (std::nothrow)LoadConfigFromBundleInfoStrategy(), + new (std::nothrow)LoadConfigDataInfoStrategy() + }; + auto ret = strategies_.Init(list); + if (!ret) { + std::for_each(list.begin(), list.end(), [](Strategy *item) { + delete item; + }); + return strategies_; + } + return strategies_; +} +} // namespace OHOS::DataShare \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/data_share/strategies/rdb_notify_strategy.h b/datamgr_service/services/distributeddataservice/service/data_share/strategies/rdb_notify_strategy.h new file mode 100644 index 0000000000000000000000000000000000000000..22eae10d8f31c4daaa6b540df6579485cc117ed3 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/data_share/strategies/rdb_notify_strategy.h @@ -0,0 +1,34 @@ +/* + * 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 DATASHARESERVICE_RDB_NOTIFY_STRAGETY_H +#define DATASHARESERVICE_RDB_NOTIFY_STRAGETY_H + +#include + +#include "datashare_values_bucket.h" +#include "seq_strategy.h" + +namespace OHOS::DataShare { +class RdbNotifyStrategy final { +public: + bool Execute(std::shared_ptr context); + +private: + SeqStrategy &GetStrategy(); + std::mutex mutex_; + SeqStrategy strategies_; +}; +} // namespace OHOS::DataShare +#endif diff --git a/datamgr_service/services/distributeddataservice/service/data_share/strategies/subscribe_strategy.cpp b/datamgr_service/services/distributeddataservice/service/data_share/strategies/subscribe_strategy.cpp index 067c8cda6aa061d419ec03ce4acf0620144a525c..4b7314c88ba32cbdac295d6b30f14089464e8869 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/strategies/subscribe_strategy.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/strategies/subscribe_strategy.cpp @@ -24,7 +24,7 @@ #include "utils/anonymous.h" namespace OHOS::DataShare { -int32_t SubscribeStrategy::Execute(std::shared_ptr context, std::function process) +int32_t SubscribeStrategy::Execute(std::shared_ptr context, std::function process) { auto &preProcess = GetStrategy(); if (preProcess.IsEmpty()) { diff --git a/datamgr_service/services/distributeddataservice/service/data_share/strategies/subscribe_strategy.h b/datamgr_service/services/distributeddataservice/service/data_share/strategies/subscribe_strategy.h index 7395b90f5ecaa86e4233f39317758bf5f47af733..3456b66cd4a798112bb168bcbf173d61c53a96de 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/strategies/subscribe_strategy.h +++ b/datamgr_service/services/distributeddataservice/service/data_share/strategies/subscribe_strategy.h @@ -23,7 +23,7 @@ namespace OHOS::DataShare { class SubscribeStrategy final { public: - int32_t Execute(std::shared_ptr context, std::function process); + int32_t Execute(std::shared_ptr context, std::function process); private: SeqStrategy &GetStrategy(); diff --git a/datamgr_service/services/distributeddataservice/service/data_share/subscriber_managers/published_data_subscriber_manager.cpp b/datamgr_service/services/distributeddataservice/service/data_share/subscriber_managers/published_data_subscriber_manager.cpp index 6aea095b891521d917ce92de3231cbbfaae531e9..af1570d4da670ef39c67689d459748268549b810 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/subscriber_managers/published_data_subscriber_manager.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/subscriber_managers/published_data_subscriber_manager.cpp @@ -80,6 +80,8 @@ int PublishedDataSubscriberManager::Delete(const PublishedDataKey &key, const ui publishedDataCache.ComputeIfPresent(key, [&callerTokenId](const auto &key, std::vector &value) { for (auto it = value.begin(); it != value.end();) { if (it->callerTokenId == callerTokenId) { + ZLOGI("delete publish subscriber, uri %{private}s tokenId %{public}d", key.key.c_str(), + callerTokenId); it = value.erase(it); } else { it++; @@ -175,11 +177,22 @@ void PublishedDataSubscriberManager::PutInto( } } } + void PublishedDataSubscriberManager::Clear() { publishedDataCache.Clear(); } +int PublishedDataSubscriberManager::GetCount(const PublishedDataKey &key) +{ + int count = 0; + publishedDataCache.ComputeIfPresent(key, [&count](const auto &key, std::vector &value) { + count = value.size(); + return true; + }); + return count; +} + PublishedDataKey::PublishedDataKey(const std::string &key, const std::string &bundle, const int64_t subscriberId) : key(key), bundleName(bundle), subscriberId(subscriberId) { diff --git a/datamgr_service/services/distributeddataservice/service/data_share/subscriber_managers/published_data_subscriber_manager.h b/datamgr_service/services/distributeddataservice/service/data_share/subscriber_managers/published_data_subscriber_manager.h index 221fd7eeb92a722615c77872ba6495ba04d4b636..de3149d2d525ee95aa5512a15efadc9477c441f1 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/subscriber_managers/published_data_subscriber_manager.h +++ b/datamgr_service/services/distributeddataservice/service/data_share/subscriber_managers/published_data_subscriber_manager.h @@ -49,7 +49,7 @@ public: void Emit(const std::vector &keys, const int32_t userId, const std::string &ownerBundleName, const sptr observer = nullptr); void Clear(); - + int GetCount(const PublishedDataKey &key); private: struct ObserverNode { ObserverNode(const sptr &observer, uint32_t callerTokenId); diff --git a/datamgr_service/services/distributeddataservice/service/data_share/subscriber_managers/rdb_subscriber_manager.cpp b/datamgr_service/services/distributeddataservice/service/data_share/subscriber_managers/rdb_subscriber_manager.cpp index ed60230737fb3c7158f55e1cf3daaf11502321c1..faf0cb57b5c1ccbfc3c68e593dd26550d93b0ed4 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/subscriber_managers/rdb_subscriber_manager.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/subscriber_managers/rdb_subscriber_manager.cpp @@ -232,6 +232,10 @@ void RdbSubscriberManager::Emit(const std::string &uri, std::shared_ptr if (!URIUtils::IsDataProxyURI(uri)) { return; } + if (context->calledSourceDir.empty()) { + LoadConfigDataInfoStrategy loadDataInfo; + loadDataInfo(context); + } rdbCache_.ForEach([&uri, &context, this](const Key &key, std::vector &val) { if (key.uri != uri) { return false; diff --git a/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_stub.cpp b/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_stub.cpp index 8894c4ade4fe5e128e70afde19bc187e52100bf0..1da51ce462fb7232c9cd535dba3ad376547de188 100644 --- a/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_stub.cpp +++ b/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_stub.cpp @@ -23,7 +23,8 @@ #include "utils/anonymous.h" namespace OHOS::DistributedKv { using namespace OHOS::DistributedData; -const KVDBServiceStub::Handler KVDBServiceStub::HANDLERS[TRANS_BUTT] = { +const KVDBServiceStub::Handler + KVDBServiceStub::HANDLERS[static_cast(KVDBServiceInterfaceCode::TRANS_BUTT)] = { &KVDBServiceStub::OnGetStoreIds, &KVDBServiceStub::OnBeforeCreate, &KVDBServiceStub::OnAfterCreate, @@ -53,8 +54,10 @@ int KVDBServiceStub::OnRemoteRequest(uint32_t code, MessageParcel &data, Message return -1; } - if (TRANS_HEAD > code || code >= TRANS_BUTT || HANDLERS[code] == nullptr) { - ZLOGE("not support code:%{public}u, BUTT:%{public}d", code, TRANS_BUTT); + if (static_cast(KVDBServiceInterfaceCode::TRANS_HEAD) > code || + code >= static_cast(KVDBServiceInterfaceCode::TRANS_BUTT) || HANDLERS[code] == nullptr) { + ZLOGE("not support code:%{public}u, BUTT:%{public}d", code, + static_cast(KVDBServiceInterfaceCode::TRANS_BUTT)); return -1; } diff --git a/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_stub.h b/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_stub.h index ab0bacc494d2e6df8019b6a077d2e563102f7c99..00b1763def44b6c8f646ad4139525b3046e34129 100644 --- a/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_stub.h +++ b/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_stub.h @@ -15,6 +15,7 @@ #ifndef OHOS_DISTRIBUTED_DATA_SERVICE_KVDB_SERVICE_STUB_H #define OHOS_DISTRIBUTED_DATA_SERVICE_KVDB_SERVICE_STUB_H +#include "distributeddata_kvdb_ipc_interface_code.h" #include "iremote_stub.h" #include "kvdb_service.h" #include "feature/feature_system.h" @@ -43,7 +44,7 @@ private: int32_t OnSubscribe(const AppId &appId, const StoreId &storeId, MessageParcel &data, MessageParcel &reply); int32_t OnUnsubscribe(const AppId &appId, const StoreId &storeId, MessageParcel &data, MessageParcel &reply); int32_t OnGetBackupPassword(const AppId &appId, const StoreId &storeId, MessageParcel &data, MessageParcel &reply); - static const Handler HANDLERS[TRANS_BUTT]; + static const Handler HANDLERS[static_cast(KVDBServiceInterfaceCode::TRANS_BUTT)]; }; } // namespace OHOS::DistributedKv #endif // OHOS_DISTRIBUTED_DATA_SERVICE_KVDB_SERVICE_STUB_H diff --git a/datamgr_service/services/distributeddataservice/service/object/object_service_stub.cpp b/datamgr_service/services/distributeddataservice/service/object/object_service_stub.cpp index 9a5281bfed6fb4a1598df12a124a81cf61514e7c..a97dd72dcb1c1b940a9fb8b3a202b545fe9821d6 100644 --- a/datamgr_service/services/distributeddataservice/service/object/object_service_stub.cpp +++ b/datamgr_service/services/distributeddataservice/service/object/object_service_stub.cpp @@ -150,7 +150,7 @@ int ObjectServiceStub::OnRemoteRequest(uint32_t code, MessageParcel& data, Messa if (!CheckInterfaceToken(data)) { return -1; } - if (code >= 0 && code < OBJECTSTORE_SERVICE_CMD_MAX) { + if (code >= 0 && code < static_cast(ObjectCode::OBJECTSTORE_SERVICE_CMD_MAX)) { return (this->*HANDLERS[code])(data, reply); } return -1; diff --git a/datamgr_service/services/distributeddataservice/service/object/object_service_stub.h b/datamgr_service/services/distributeddataservice/service/object/object_service_stub.h index c3e319fa5f0912b1a277bf61209985e471fb6bdf..6acd6c758867dddc9057be907bfa8a049fc15d76 100644 --- a/datamgr_service/services/distributeddataservice/service/object/object_service_stub.h +++ b/datamgr_service/services/distributeddataservice/service/object/object_service_stub.h @@ -20,6 +20,8 @@ #include "iobject_service.h" #include "feature/feature_system.h" namespace OHOS::DistributedObject { +using ObjectCode = ObjectStoreService::ObjectServiceInterfaceCode; + class ObjectServiceStub : public ObjectService, public DistributedData::FeatureSystem::Feature { public: int OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply) override; @@ -33,7 +35,7 @@ private: int32_t OnUnsubscribeRequest(MessageParcel &data, MessageParcel &reply); using RequestHandle = int (ObjectServiceStub::*)(MessageParcel &, MessageParcel &); - static constexpr RequestHandle HANDLERS[OBJECTSTORE_SERVICE_CMD_MAX] = { + static constexpr RequestHandle HANDLERS[static_cast(ObjectCode::OBJECTSTORE_SERVICE_CMD_MAX)] = { &ObjectServiceStub::ObjectStoreSaveOnRemote, &ObjectServiceStub::ObjectStoreRevokeSaveOnRemote, &ObjectServiceStub::ObjectStoreRetrieveOnRemote, diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_asset_loader.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_asset_loader.cpp index b7d4d938342b3be3bc3651556d25b22c31ec5ab5..a0d9f538501c4ce565fe32082ed92a8fb9017bc0 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_asset_loader.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_asset_loader.cpp @@ -31,8 +31,8 @@ DBStatus RdbAssetLoader::Download(const std::string &tableName, const std::strin std::map &assets) { DistributedData::VBucket downLoadAssets = ValueProxy::Convert(assets); - - auto error = assetLoader_->Download(tableName, gid, (const DistributedData::Value &)prefix, downLoadAssets); + DistributedDB::Type prefixTemp = prefix; + auto error = assetLoader_->Download(tableName, gid, ValueProxy::Convert(std::move(prefixTemp)), downLoadAssets); if (error == DistributedData::GeneralError::E_OK) { assets = ValueProxy::Convert(std::move(downLoadAssets)); } diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.cpp index 03d904305ba94d1f820087a23eaf793abf62646a..88a5e0eb3dd1532da26cc953e295601424a28bdb 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.cpp @@ -14,7 +14,7 @@ */ #define LOG_TAG "RdbGeneralStore" #include "rdb_general_store.h" - +#include "cloud_service.h" #include "cloud/asset_loader.h" #include "cloud/cloud_db.h" #include "cloud/schema_meta.h" @@ -32,9 +32,12 @@ namespace OHOS::DistributedRdb { using namespace DistributedData; using namespace DistributedDB; using namespace NativeRdb; +using namespace CloudData; using DBField = DistributedDB::Field; using DBTable = DistributedDB::TableSchema; using DBSchema = DistributedDB::DataBaseSchema; +using ClearMode = DistributedDB::ClearMode; +using DBStatus = DistributedDB::DBStatus; class RdbOpenCallbackImpl : public RdbOpenCallback { public: int OnCreate(RdbStore &rdbStore) override @@ -103,10 +106,6 @@ int32_t RdbGeneralStore::Bind(const Database &database, BindInfo bindInfo) rdbCloud_ = std::make_shared(bindInfo_.db_); delegate_->SetCloudDB(rdbCloud_); rdbLoader_ = std::make_shared(bindInfo_.loader_); - if (rdbLoader_ == nullptr) { - ZLOGE("rdb_AssetLoader is null"); - return GeneralError::E_ERROR; - } delegate_->SetIAssetLoader(rdbLoader_); DBSchema schema; schema.tables.resize(database.tables.size()); @@ -197,6 +196,36 @@ int32_t RdbGeneralStore::Sync(const Devices &devices, int32_t mode, GenQuery &qu return status == DistributedDB::OK ? GeneralError::E_OK : GeneralError::E_ERROR; } +int32_t RdbGeneralStore::Clean(const std::vector &devices, int32_t mode, const std::string &tableName) +{ + if (mode < 0 || mode > CloudService::CLEAR_CLOUD_BUTT) { + return GeneralError::E_INVALID_ARGS; + } + int32_t dbMode; + DBStatus status; + switch (mode) { + case CloudService::CLEAR_CLOUD_INFO: + dbMode = CleanMode::CLOUD_INFO; + status = delegate_->RemoveDeviceData("", static_cast(dbMode)); + break; + case CloudService::CLEAR_CLOUD_DATA_AND_INFO: + dbMode = CleanMode::CLOUD_DATA; + status = delegate_->RemoveDeviceData("", static_cast(dbMode)); + break; + default: + if (devices.empty()) { + status = delegate_->RemoveDeviceData(); + break; + } + + for (auto device : devices) { + status = delegate_->RemoveDeviceData(device, tableName); + } + break; + } + return status == DistributedDB::OK ? GeneralError::E_OK : GeneralError::E_ERROR; +} + int32_t RdbGeneralStore::Watch(int32_t origin, Watcher &watcher) { if (origin != Watcher::Origin::ORIGIN_ALL || observer_.watcher_ != nullptr) { @@ -284,6 +313,7 @@ void RdbGeneralStore::ObserverProxy::OnChange(DBOrigin origin, const std::string genOrigin.origin = (origin == DBOrigin::ORIGIN_LOCAL) ? GenOrigin::ORIGIN_LOCAL : (origin == DBOrigin::ORIGIN_CLOUD) ? GenOrigin::ORIGIN_CLOUD : GenOrigin::ORIGIN_NEARBY; + genOrigin.dataType = data.type == DistributedDB::ASSET ? GenOrigin::ASSET_DATA : GenOrigin::BASIC_DATA; genOrigin.id.push_back(originalId); genOrigin.store = storeId_; Watcher::PRIFields fields; diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.h b/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.h index 2a27c83a7cdb1434f9402cdbf29ad2bf8ead2622..3213be87e184139833e74d32e75fa67d0521f307 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.h +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.h @@ -49,6 +49,7 @@ public: std::shared_ptr Query(const std::string &table, const std::string &sql, Values &&args) override; std::shared_ptr Query(const std::string &table, GenQuery &query) override; int32_t Sync(const Devices &devices, int32_t mode, GenQuery &query, DetailAsync async, int32_t wait) override; + int32_t Clean(const std::vector &devices, int32_t mode, const std::string &tableName) override; int32_t Watch(int32_t origin, Watcher &watcher) override; int32_t Unwatch(int32_t origin, Watcher &watcher) override; int32_t Close() override; diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_notifier_proxy.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_notifier_proxy.cpp index 92aee4fafa8f06352c45f7f43fc1d5843be22884..1d9d74015d16237f7c5896830d665ba17fbd8b44 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_notifier_proxy.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_notifier_proxy.cpp @@ -17,6 +17,8 @@ #include "itypes_util.h" #include "log_print.h" namespace OHOS::DistributedRdb { +using NotifierIFCode = RelationalStore::IRdbNotifierInterfaceCode; + RdbNotifierProxy::RdbNotifierProxy(const sptr &object) : IRemoteProxy(object) { ZLOGI("construct"); @@ -40,7 +42,8 @@ int32_t RdbNotifierProxy::OnComplete(uint32_t seqNum, Details &&result) MessageParcel reply; MessageOption option(MessageOption::TF_ASYNC); - if (Remote()->SendRequest(RDB_NOTIFIER_CMD_SYNC_COMPLETE, data, reply, option) != 0) { + if (Remote()->SendRequest( + static_cast(NotifierIFCode::RDB_NOTIFIER_CMD_SYNC_COMPLETE), data, reply, option) != 0) { ZLOGE("send request failed"); return RDB_ERROR; } @@ -61,7 +64,8 @@ int32_t RdbNotifierProxy::OnChange(const Origin &origin, const PrimaryFields &pr MessageParcel reply; MessageOption option; - if (Remote()->SendRequest(RDB_NOTIFIER_CMD_DATA_CHANGE, data, reply, option) != 0) { + if (Remote()->SendRequest( + static_cast(NotifierIFCode::RDB_NOTIFIER_CMD_DATA_CHANGE), data, reply, option) != 0) { ZLOGE("send request failed"); return RDB_ERROR; } 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 bf493d2cfd8720b9b5c7dd84c760ae3d8adad621..8e602e5cda5dc604daf024be61889ab602ae39f3 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.cpp @@ -207,7 +207,7 @@ int RdbServiceStub::OnRemoteRequest(uint32_t code, MessageParcel& data, MessageP if (!CheckInterfaceToken(data)) { return RDB_ERROR; } - if (code >= 0 && code < RDB_SERVICE_CMD_MAX) { + if (code >= 0 && code < static_cast(RdbServiceCode::RDB_SERVICE_CMD_MAX)) { return (this->*HANDLERS[code])(data, reply); } return RDB_ERROR; diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.h b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.h index b67c3e5b1c60b702561b635d758ae96de6d721b3..fbd2173a40ffc8a64c0ccce8ce216273371c86a6 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.h +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.h @@ -22,6 +22,8 @@ #include "feature/feature_system.h" namespace OHOS::DistributedRdb { +using RdbServiceCode = OHOS::DistributedRdb::RelationalStore::RdbServiceInterfaceCode; + class RdbServiceStub : public RdbService, public DistributedData::FeatureSystem::Feature { public: DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.DistributedRdb.IRdbService"); @@ -49,16 +51,18 @@ private: int32_t OnRemoteDoRemoteQuery(MessageParcel& data, MessageParcel& reply); using RequestHandle = int (RdbServiceStub::*)(MessageParcel &, MessageParcel &); - static constexpr RequestHandle HANDLERS[RDB_SERVICE_CMD_MAX] = { - [RDB_SERVICE_CMD_OBTAIN_TABLE] = &RdbServiceStub::OnRemoteObtainDistributedTableName, - [RDB_SERVICE_CMD_INIT_NOTIFIER] = &RdbServiceStub::OnRemoteInitNotifier, - [RDB_SERVICE_CMD_SET_DIST_TABLE] = &RdbServiceStub::OnRemoteSetDistributedTables, - [RDB_SERVICE_CMD_SYNC] = &RdbServiceStub::OnRemoteDoSync, - [RDB_SERVICE_CMD_ASYNC] = &RdbServiceStub::OnRemoteDoAsync, - [RDB_SERVICE_CMD_SUBSCRIBE] = &RdbServiceStub::OnRemoteDoSubscribe, - [RDB_SERVICE_CMD_UNSUBSCRIBE] = &RdbServiceStub::OnRemoteDoUnSubscribe, - [RDB_SERVICE_CMD_REMOTE_QUERY] = &RdbServiceStub::OnRemoteDoRemoteQuery, - [RDB_SERVICE_CMD_GET_SCHEMA] = &RdbServiceStub::OnGetSchema + static constexpr RequestHandle HANDLERS[static_cast(RdbServiceCode::RDB_SERVICE_CMD_MAX)] = { + [static_cast(RdbServiceCode::RDB_SERVICE_CMD_OBTAIN_TABLE)] = + &RdbServiceStub::OnRemoteObtainDistributedTableName, + [static_cast(RdbServiceCode::RDB_SERVICE_CMD_INIT_NOTIFIER)] = &RdbServiceStub::OnRemoteInitNotifier, + [static_cast(RdbServiceCode::RDB_SERVICE_CMD_SET_DIST_TABLE)] = + &RdbServiceStub::OnRemoteSetDistributedTables, + [static_cast(RdbServiceCode::RDB_SERVICE_CMD_SYNC)] = &RdbServiceStub::OnRemoteDoSync, + [static_cast(RdbServiceCode::RDB_SERVICE_CMD_ASYNC)] = &RdbServiceStub::OnRemoteDoAsync, + [static_cast(RdbServiceCode::RDB_SERVICE_CMD_SUBSCRIBE)] = &RdbServiceStub::OnRemoteDoSubscribe, + [static_cast(RdbServiceCode::RDB_SERVICE_CMD_UNSUBSCRIBE)] = &RdbServiceStub::OnRemoteDoUnSubscribe, + [static_cast(RdbServiceCode::RDB_SERVICE_CMD_REMOTE_QUERY)] = &RdbServiceStub::OnRemoteDoRemoteQuery, + [static_cast(RdbServiceCode::RDB_SERVICE_CMD_GET_SCHEMA)] = &RdbServiceStub::OnGetSchema }; }; } // namespace OHOS::DistributedRdb diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_syncer.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_syncer.cpp index 1f65915f059ee50ecd44e892f7571a4fea54983a..9fbd7642d852d3158dbb2b92561e6fdbbd76da7e 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_syncer.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_syncer.cpp @@ -167,11 +167,11 @@ int32_t RdbSyncer::InitDBDelegate(const StoreMetaData &meta) } option.observer = observer_; std::string fileName = meta.dataDir; - ZLOGI("path=%{public}s storeId=%{public}s", fileName.c_str(), meta.GetStoreAlias().c_str()); + ZLOGI("path=%{public}s storeId=%{public}s", Anonymous::Change(fileName).c_str(), meta.GetStoreAlias().c_str()); auto status = manager_->OpenStore(fileName, meta.storeId, option, delegate_); if (status != DistributedDB::DBStatus::OK) { ZLOGE("open store failed, path=%{public}s storeId=%{public}s status=%{public}d", - fileName.c_str(), meta.GetStoreAlias().c_str(), status); + Anonymous::Change(fileName).c_str(), meta.GetStoreAlias().c_str(), status); return RDB_ERROR; } ZLOGI("open store success"); @@ -385,8 +385,8 @@ int32_t RdbSyncer::DoSync(const Option &option, const PredicatesMemo &predicates query->query_.FromTable(predicates.tables_); } - auto info = ChangeEvent::EventInfo(option.mode, (option.isAsync ? 0 : WAIT_TIME), query, - [async](const GenDetails &details) { + auto info = ChangeEvent::EventInfo(option.mode, (option.isAsync ? 0 : WAIT_TIME), + (option.isAsync && option.seqNum == 0), query, [async](const GenDetails &details) { async(HandleGenDetails(details)); }); auto evt = std::make_unique(std::move(storeInfo), std::move(info)); diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_watcher.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_watcher.cpp index c929a7692689b6f85c01369e49bfc823f8898942..a0d4d0ed9ab07b23d9583bc01495a89cc609f64a 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_watcher.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_watcher.cpp @@ -35,6 +35,7 @@ int32_t RdbWatcher::OnChange(const Origin &origin, const PRIFields &primaryField } DistributedRdb::Origin rdbOrigin; rdbOrigin.origin = origin.origin; + rdbOrigin.dataType = origin.dataType; rdbOrigin.id = origin.id; rdbOrigin.store = origin.store; notifier->OnChange(rdbOrigin, primaryFields, std::move(values)); diff --git a/datamgr_service/services/distributeddataservice/service/rdb/value_proxy.cpp b/datamgr_service/services/distributeddataservice/service/rdb/value_proxy.cpp index db4ef2fe822067c14681b856920f880c0eb15e00..23bac1a7f8ce127e0eedc39e225a4173201e9544 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/value_proxy.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/value_proxy.cpp @@ -125,7 +125,7 @@ ValueProxy::Asset::Asset(NativeRdb::AssetValue asset) asset_ = DistributedData::Asset { .version = asset.version, .status = asset.status, .expiresTime = asset.expiresTime, - .id = asset.id, + .id = std::move(asset.id), .name = std::move(asset.name), .uri = std::move(asset.uri), .createTime = std::move(asset.createTime), @@ -199,8 +199,7 @@ ValueProxy::Asset::operator DistributedDB::Asset() .createTime = std::move(asset_.createTime), .size = std::move(asset_.size), .hash = std::move(asset_.hash), - .flag = ConvertToDBStatus(asset_).second, - .status = ConvertToDBStatus(asset_).first }; + .status = ConvertToDBStatus(asset_) }; } uint32_t ValueProxy::Asset::ConvertToDataStatus(const DistributedDB::Asset &asset) @@ -209,7 +208,7 @@ uint32_t ValueProxy::Asset::ConvertToDataStatus(const DistributedDB::Asset &asse return DistributedData::Asset::STATUS_DOWNLOADING; } else if (asset.status == DistributedDB::AssetStatus::ABNORMAL) { return DistributedData::Asset::STATUS_ABNORMAL; - } else if (asset.status == DistributedDB::AssetStatus::NORMAL) { + } else { switch (asset.flag) { case static_cast(DistributedDB::AssetOpType::INSERT): return DistributedData::Asset::STATUS_INSERT; @@ -224,30 +223,23 @@ uint32_t ValueProxy::Asset::ConvertToDataStatus(const DistributedDB::Asset &asse return DistributedData::Asset::STATUS_UNKNOWN; } -std::pair ValueProxy::Asset::ConvertToDBStatus(const DistributedData::Asset &asset) +uint32_t ValueProxy::Asset::ConvertToDBStatus(const DistributedData::Asset &asset) { switch (asset.status) { case DistributedData::Asset::STATUS_NORMAL: - return { static_cast(DistributedDB::AssetStatus::NORMAL), - static_cast(DistributedDB::AssetOpType::NO_CHANGE) }; + return static_cast(DistributedDB::AssetStatus::NORMAL); case DistributedData::Asset::STATUS_ABNORMAL: - return { static_cast(DistributedDB::AssetStatus::ABNORMAL), - static_cast(DistributedDB::AssetOpType::NO_CHANGE) }; + return static_cast(DistributedDB::AssetStatus::ABNORMAL); case DistributedData::Asset::STATUS_INSERT: - return { static_cast(DistributedDB::AssetStatus::NORMAL), - static_cast(DistributedDB::AssetOpType::INSERT) }; + return static_cast(DistributedDB::AssetStatus::INSERT); case DistributedData::Asset::STATUS_UPDATE: - return { static_cast(DistributedDB::AssetStatus::NORMAL), - static_cast(DistributedDB::AssetOpType::UPDATE) }; + return static_cast(DistributedDB::AssetStatus::UPDATE); case DistributedData::Asset::STATUS_DELETE: - return { static_cast(DistributedDB::AssetStatus::NORMAL), - static_cast(DistributedDB::AssetOpType::DELETE) }; + return static_cast(DistributedDB::AssetStatus::DELETE); case DistributedData::Asset::STATUS_DOWNLOADING: - return { static_cast(DistributedDB::AssetStatus::DOWNLOADING), - static_cast(DistributedDB::AssetOpType::NO_CHANGE) }; + return static_cast(DistributedDB::AssetStatus::DOWNLOADING); default: - return { static_cast(DistributedDB::AssetStatus::NORMAL), - static_cast(DistributedDB::AssetOpType::NO_CHANGE) }; + return static_cast(DistributedDB::AssetStatus::NORMAL); } } diff --git a/datamgr_service/services/distributeddataservice/service/rdb/value_proxy.h b/datamgr_service/services/distributeddataservice/service/rdb/value_proxy.h index 83790b761cdd1e3831c0ecc085b80ca7f6bc7687..3c351ee58ad9f30fa04b27b7f12143e5a19bb56c 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/value_proxy.h +++ b/datamgr_service/services/distributeddataservice/service/rdb/value_proxy.h @@ -61,7 +61,7 @@ public: operator DistributedData::Asset(); operator DistributedDB::Asset(); static uint32_t ConvertToDataStatus(const DistributedDB::Asset &asset); - static std::pair ConvertToDBStatus(const DistributedData::Asset &asset); + static uint32_t ConvertToDBStatus(const DistributedData::Asset &asset); private: DistributedData::Asset asset_; diff --git a/datamgr_service/services/distributeddataservice/service/test/BUILD.gn b/datamgr_service/services/distributeddataservice/service/test/BUILD.gn index c28c697afe26f75c491f9f5b6ba14cd4975ecdcc..a951e0527c4b498c927e5e078046c1fc75bfdbd4 100644 --- a/datamgr_service/services/distributeddataservice/service/test/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/test/BUILD.gn @@ -54,7 +54,7 @@ ohos_unittest("CloudDataTest") { "ability_base:base", "ability_base:want", "c_utils:utils", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", "ipc:ipc_core", "kv_store:distributeddata_inner", ] @@ -84,7 +84,7 @@ ohos_unittest("ValueProxyTest") { "ability_base:base", "ability_base:want", "c_utils:utils", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", "ipc:ipc_core", "kv_store:distributeddata_inner", ] @@ -109,7 +109,7 @@ ohos_unittest("ConfigFactoryTest") { "ability_base:base", "ability_base:want", "c_utils:utils", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", "ipc:ipc_core", ] @@ -135,7 +135,7 @@ ohos_unittest("DirectoryManagerTest") { "access_token:libaccesstoken_sdk", "access_token:libnativetoken", "c_utils:utils", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", "ipc:ipc_core", ] @@ -160,7 +160,7 @@ ohos_unittest("CryptoManagerTest") { "access_token:libaccesstoken_sdk", "access_token:libnativetoken", "c_utils:utils", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", "ipc:ipc_core", ] @@ -189,7 +189,7 @@ ohos_unittest("DeviceMatrixTest") { "access_token:libaccesstoken_sdk", "access_token:libnativetoken", "c_utils:utils", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", "ipc:ipc_core", ] diff --git a/datamgr_service/services/distributeddataservice/service/test/config_factory_test.cpp b/datamgr_service/services/distributeddataservice/service/test/config_factory_test.cpp index 0210610981332ce8a419440097b0adbb46801ff5..70a6a5ad833c9303b948e0b4c40ae979dd2ec8da 100644 --- a/datamgr_service/services/distributeddataservice/service/test/config_factory_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/config_factory_test.cpp @@ -61,7 +61,7 @@ HWTEST_F(ConfigFactoryTest, ComponentConfig, TestSize.Level0) { auto *components = ConfigFactory::GetInstance().GetComponentConfig(); ASSERT_NE(components, nullptr); - ASSERT_EQ(components->size(), 4); + ASSERT_EQ(components->size(), 3); const ComponentConfig &config = (*components)[0]; ASSERT_EQ(config.description, "3rd party adapter"); ASSERT_EQ(config.lib, "libconfigdemo.z.so"); diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/BUILD.gn b/datamgr_service/services/distributeddataservice/service/test/fuzztest/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..59ad2cd8f59790fab04a7c4a76f39cfb158ae93c --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/BUILD.gn @@ -0,0 +1,32 @@ +# 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. + +import("//build/ohos.gni") +import("//foundation/distributeddatamgr/datamgr_service/datamgr_service.gni") + +######################################################################################### +group("fuzztest") { + testonly = true + + deps = [ + "cloudservicestub_fuzzer:fuzztest", + "datashareservicestub_fuzzer:fuzztest", + "kvdbservicestub_fuzzer:fuzztest", + "objectservicestub_fuzzer:fuzztest", + "rdbresultsetstub_fuzzer:fuzztest", + "rdbservicestub_fuzzer:fuzztest", + ] + if (datamgr_service_udmf) { + deps += [ "udmfservice_fuzzer:fuzztest" ] + } +} diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/cloudservicestub_fuzzer/BUILD.gn b/datamgr_service/services/distributeddataservice/service/test/fuzztest/cloudservicestub_fuzzer/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..d39a5b8267016c0560e7a643db72767f62fd877e --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/cloudservicestub_fuzzer/BUILD.gn @@ -0,0 +1,113 @@ +# 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. +##############################hydra-fuzz######################################## +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/datamgr_service/datamgr_service.gni") + +##############################fuzztest########################################## +ohos_fuzztest("CloudServiceStubFuzzTest") { + module_out_path = "datamgr_service/service" + + include_dirs = [ + "${data_service_path}/adapter/include", + "${data_service_path}/app/src", + "${data_service_path}/framework/include", + "${data_service_path}/service/backup/include", + "${data_service_path}/service/bootstrap/include", + "${data_service_path}/service/cloud", + "${data_service_path}/service/config/include", + "${data_service_path}/service/crypto/include", + "${data_service_path}/service/kvdb", + "${data_service_path}/service/matrix/include", + "${data_service_path}/service/object", + "${data_service_path}/service/permission/include", + "${data_service_path}/service/rdb", + "${kv_store_common_path}", + "${kv_store_path}/frameworks/innerkitsimpl/distributeddatafwk/include", + "${kv_store_path}/frameworks/innerkitsimpl/kvdb/include", + "${kv_store_distributeddb_path}", + "${kv_store_distributeddb_path}/include/", + "${kv_store_distributeddb_path}/interfaces/include/", + "${kv_store_distributeddb_path}/interfaces/include/relational", + "${dataobject_path}/frameworks/innerkitsimpl/include", + "${relational_store_path}/interfaces/inner_api/cloud_data/include", + "${relational_store_path}/interfaces/inner_api/rdb/include", + "//third_party/json/single_include", + ] + + fuzz_config_file = + "${data_service_path}/service/test/fuzztest/cloudservicestub_fuzzer" + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + sources = [ + "${data_service_path}/service/cloud/cloud_service_impl.cpp", + "${data_service_path}/service/cloud/cloud_service_stub.cpp", + "${data_service_path}/service/cloud/sync_manager.cpp", + "${data_service_path}/service/rdb/rdb_asset_loader.cpp", + "${data_service_path}/service/rdb/rdb_cloud.cpp", + "${data_service_path}/service/rdb/rdb_cloud_data_translate.cpp", + "${data_service_path}/service/rdb/rdb_cursor.cpp", + "${data_service_path}/service/rdb/rdb_general_store.cpp", + "${data_service_path}/service/rdb/rdb_notifier_proxy.cpp", + "${data_service_path}/service/rdb/rdb_query.cpp", + "${data_service_path}/service/rdb/rdb_result_set_impl.cpp", + "${data_service_path}/service/rdb/rdb_result_set_stub.cpp", + "${data_service_path}/service/rdb/rdb_service_impl.cpp", + "${data_service_path}/service/rdb/rdb_service_stub.cpp", + "${data_service_path}/service/rdb/rdb_store_observer_impl.cpp", + "${data_service_path}/service/rdb/rdb_syncer.cpp", + "${data_service_path}/service/rdb/rdb_watcher.cpp", + "${data_service_path}/service/rdb/value_proxy.cpp", + "cloudservicestub_fuzzer.cpp", + ] + + deps = [ + "${data_service_path}/adapter:distributeddata_adapter", + "${data_service_path}/adapter/utils:distributeddata_utils_static", + "${data_service_path}/framework:distributeddatasvcfwk", + "${data_service_path}/service:distributeddatasvc", + "${kv_store_distributeddb_path}:distributeddb", + ] + + external_deps = [ + "ability_base:want", + "ability_base:zuri", + "ability_runtime:ability_manager", + "ability_runtime:dataobs_manager", + "access_token:libaccesstoken_sdk", + "access_token:libtokenid_sdk", + "c_utils:utils", + "device_auth:deviceauth_sdk", + "device_manager:devicemanagersdk", + "hilog:libhilog", + "huks:libhukssdk", + "ipc:ipc_core", + "kv_store:distributeddata_inner", + "relational_store:native_rdb", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + + deps = [ ":CloudServiceStubFuzzTest" ] +} +############################################################################### diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/cloudservicestub_fuzzer/cloudservicestub_fuzzer.cpp b/datamgr_service/services/distributeddataservice/service/test/fuzztest/cloudservicestub_fuzzer/cloudservicestub_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1dada5adfc7697857845403aca1850a326461264 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/cloudservicestub_fuzzer/cloudservicestub_fuzzer.cpp @@ -0,0 +1,56 @@ +/* + * 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 "cloudservicestub_fuzzer.h" + +#include +#include + +#include "cloud_service_impl.h" +#include "message_parcel.h" +#include "securec.h" + +using namespace OHOS::CloudData; + +namespace OHOS { +const std::u16string INTERFACE_TOKEN = u"OHOS.CloudData.CloudServer"; +const uint32_t CODE_MIN = 0; +const uint32_t CODE_MAX = 4; + +bool OnRemoteRequestFuzz(const uint8_t *data, size_t size) +{ + uint32_t code = static_cast(*data) % (CODE_MAX - CODE_MIN + 1) + CODE_MIN; + MessageParcel request; + request.WriteInterfaceToken(INTERFACE_TOKEN); + request.WriteBuffer(data, size); + request.RewindRead(0); + MessageParcel reply; + std::shared_ptr cloudServiceStub = std::make_shared(); + cloudServiceStub->OnRemoteRequest(code, request, reply); + return true; +} +} // namespace OHOS + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + if (data == nullptr) { + return 0; + } + + OHOS::OnRemoteRequestFuzz(data, size); + + return 0; +} \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/cloudservicestub_fuzzer/cloudservicestub_fuzzer.h b/datamgr_service/services/distributeddataservice/service/test/fuzztest/cloudservicestub_fuzzer/cloudservicestub_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..c007ebba589b7ea13961acac7845188f30ecaa8d --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/cloudservicestub_fuzzer/cloudservicestub_fuzzer.h @@ -0,0 +1,21 @@ +/* + * 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 DATAMGR_SERVICE_CLOUD_SERVICE_STUB_FUZZER_H +#define DATAMGR_SERVICE_CLOUD_SERVICE_STUB_FUZZER_H + +#define FUZZ_PROJECT_NAME "cloudservicestub_fuzzer" + +#endif // DATAMGR_SERVICE_CLOUD_SERVICE_STUB_FUZZER_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/cloudservicestub_fuzzer/corpus/init b/datamgr_service/services/distributeddataservice/service/test/fuzztest/cloudservicestub_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..2b595da0c26af63ffb2d5f4132c086b2e5986fce --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/cloudservicestub_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/cloudservicestub_fuzzer/project.xml b/datamgr_service/services/distributeddataservice/service/test/fuzztest/cloudservicestub_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..3fdba3e8b151bbb9026792021977b81e8a1851a6 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/cloudservicestub_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/datashareservicestub_fuzzer/BUILD.gn b/datamgr_service/services/distributeddataservice/service/test/fuzztest/datashareservicestub_fuzzer/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..e2cbf7fe23f061823321c7592632b2ef2be0a6d9 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/datashareservicestub_fuzzer/BUILD.gn @@ -0,0 +1,124 @@ +# 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. +##############################hydra-fuzz######################################## +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/datamgr_service/datamgr_service.gni") + +##############################fuzztest########################################## +ohos_fuzztest("DataShareServiceStubFuzzTest") { + module_out_path = "datamgr_service/service" + + include_dirs = [ + "${data_service_path}/adapter/include", + "${data_service_path}/app/src", + "${data_service_path}/framework/include", + "${data_service_path}/service/data_share/common", + "${data_service_path}/service/data_share/data", + "${data_service_path}/service/data_share/strategies", + "${data_service_path}/service/data_share/subscriber_managers", + "${data_service_path}/service/data_share", + "${datashare_path}/frameworks/native/common/include", + "${datashare_path}/interfaces/inner_api/common/include", + "${datashare_path}/interfaces/inner_api/consumer/include", + "//third_party/json/single_include", + ] + + fuzz_config_file = + "${data_service_path}/service/test/fuzztest/datashareservicestub_fuzzer" + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + sources = [ + "${data_service_path}/service/data_share/common/app_connect_manager.cpp", + "${data_service_path}/service/data_share/common/bundle_mgr_proxy.cpp", + "${data_service_path}/service/data_share/common/db_delegate.cpp", + "${data_service_path}/service/data_share/common/div_strategy.cpp", + "${data_service_path}/service/data_share/common/extension_connect_adaptor.cpp", + "${data_service_path}/service/data_share/common/kv_delegate.cpp", + "${data_service_path}/service/data_share/common/rdb_delegate.cpp", + "${data_service_path}/service/data_share/common/scheduler_manager.cpp", + "${data_service_path}/service/data_share/common/seq_strategy.cpp", + "${data_service_path}/service/data_share/common/uri_utils.cpp", + "${data_service_path}/service/data_share/data/published_data.cpp", + "${data_service_path}/service/data_share/data/resultset_json_formatter.cpp", + "${data_service_path}/service/data_share/data/template_data.cpp", + "${data_service_path}/service/data_share/data_share_obs_proxy.cpp", + "${data_service_path}/service/data_share/data_share_service_impl.cpp", + "${data_service_path}/service/data_share/data_share_service_stub.cpp", + "${data_service_path}/service/data_share/data_share_types_util.cpp", + "${data_service_path}/service/data_share/strategies/data_proxy/load_config_from_data_proxy_node_strategy.cpp", + "${data_service_path}/service/data_share/strategies/data_share/load_config_from_data_share_bundle_info_strategy.cpp", + "${data_service_path}/service/data_share/strategies/delete_strategy.cpp", + "${data_service_path}/service/data_share/strategies/general/check_is_data_proxy_strategy.cpp", + "${data_service_path}/service/data_share/strategies/general/check_is_single_app_strategy.cpp", + "${data_service_path}/service/data_share/strategies/general/cross_permission_strategy.cpp", + "${data_service_path}/service/data_share/strategies/general/empty_strategy.cpp", + "${data_service_path}/service/data_share/strategies/general/load_config_common_strategy.cpp", + "${data_service_path}/service/data_share/strategies/general/load_config_data_info_strategy.cpp", + "${data_service_path}/service/data_share/strategies/general/load_config_from_bundle_info_strategy.cpp", + "${data_service_path}/service/data_share/strategies/general/permission_strategy.cpp", + "${data_service_path}/service/data_share/strategies/general/process_single_app_user_cross_strategy.cpp", + "${data_service_path}/service/data_share/strategies/get_data_strategy.cpp", + "${data_service_path}/service/data_share/strategies/insert_strategy.cpp", + "${data_service_path}/service/data_share/strategies/publish_strategy.cpp", + "${data_service_path}/service/data_share/strategies/query_strategy.cpp", + "${data_service_path}/service/data_share/strategies/rdb_notify_strategy.cpp", + "${data_service_path}/service/data_share/strategies/subscribe_strategy.cpp", + "${data_service_path}/service/data_share/strategies/template_strategy.cpp", + "${data_service_path}/service/data_share/strategies/update_strategy.cpp", + "${data_service_path}/service/data_share/subscriber_managers/published_data_subscriber_manager.cpp", + "${data_service_path}/service/data_share/subscriber_managers/rdb_subscriber_manager.cpp", + "datashareservicestub_fuzzer.cpp", + ] + + deps = [ + "${data_service_path}/adapter:distributeddata_adapter", + "${data_service_path}/framework:distributeddatasvcfwk", + "${data_service_path}/service/data_share:data_share_service", + "${data_service_path}/service/data_share/gaussdb_rd:gaussdb_rd", + ] + + external_deps = [ + "ability_base:want", + "ability_base:zuri", + "ability_runtime:ability_manager", + "ability_runtime:dataobs_manager", + "access_token:libaccesstoken_sdk", + "access_token:libtokenid_sdk", + "bundle_framework:appexecfwk_base", + "bundle_framework:appexecfwk_core", + "c_utils:utils", + "data_share:datashare_common", + "device_manager:devicemanagersdk", + "hilog:libhilog", + "ipc:ipc_core", + "relational_store:native_rdb", + "relational_store:rdb_bms_adapter", + "relational_store:rdb_data_share_adapter", + "samgr:samgr_proxy", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + + deps = [ ":DataShareServiceStubFuzzTest" ] +} +############################################################################### diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/datashareservicestub_fuzzer/corpus/init b/datamgr_service/services/distributeddataservice/service/test/fuzztest/datashareservicestub_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..2b595da0c26af63ffb2d5f4132c086b2e5986fce --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/datashareservicestub_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/datashareservicestub_fuzzer/datashareservicestub_fuzzer.cpp b/datamgr_service/services/distributeddataservice/service/test/fuzztest/datashareservicestub_fuzzer/datashareservicestub_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7fb0269f2d493c312b7c0026f6bee6575b53ea58 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/datashareservicestub_fuzzer/datashareservicestub_fuzzer.cpp @@ -0,0 +1,56 @@ +/* + * 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 "datashareservicestub_fuzzer.h" + +#include +#include + +#include "data_share_service_impl.h" +#include "message_parcel.h" +#include "securec.h" + +using namespace OHOS::DataShare; + +namespace OHOS { +const std::u16string INTERFACE_TOKEN = u"OHOS.DataShare.IDataShare"; +const uint32_t CODE_MIN = 0; +const uint32_t CODE_MAX = 16; + +bool OnRemoteRequestFuzz(const uint8_t *data, size_t size) +{ + uint32_t code = static_cast(*data) % (CODE_MAX - CODE_MIN + 1) + CODE_MIN; + MessageParcel request; + request.WriteInterfaceToken(INTERFACE_TOKEN); + request.WriteBuffer(data, size); + request.RewindRead(0); + MessageParcel reply; + std::shared_ptr dataShareServiceStub = std::make_shared(); + dataShareServiceStub->OnRemoteRequest(code, request, reply); + return true; +} +} // namespace OHOS + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + if (data == nullptr) { + return 0; + } + + OHOS::OnRemoteRequestFuzz(data, size); + + return 0; +} \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/datashareservicestub_fuzzer/datashareservicestub_fuzzer.h b/datamgr_service/services/distributeddataservice/service/test/fuzztest/datashareservicestub_fuzzer/datashareservicestub_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..28399e52d198b12eb999b22616319c0c90132dd3 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/datashareservicestub_fuzzer/datashareservicestub_fuzzer.h @@ -0,0 +1,21 @@ +/* + * 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 DATAMGR_SERVICE_DATA_SHARE_SERVICE_STUB_FUZZER_H +#define DATAMGR_SERVICE_DATA_SHARE_SERVICE_STUB_FUZZER_H + +#define FUZZ_PROJECT_NAME "datashareservicestub_fuzzer" + +#endif // DATAMGR_SERVICE_DATA_SHARE_SERVICE_STUB_FUZZER_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/datashareservicestub_fuzzer/project.xml b/datamgr_service/services/distributeddataservice/service/test/fuzztest/datashareservicestub_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..3fdba3e8b151bbb9026792021977b81e8a1851a6 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/datashareservicestub_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/kvdbservicestub_fuzzer/BUILD.gn b/datamgr_service/services/distributeddataservice/service/test/fuzztest/kvdbservicestub_fuzzer/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..8998072c19865af556eeeb126a33989bc68d2150 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/kvdbservicestub_fuzzer/BUILD.gn @@ -0,0 +1,110 @@ +# 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. +##############################hydra-fuzz######################################## +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/datamgr_service/datamgr_service.gni") + +##############################fuzztest########################################## +ohos_fuzztest("KvdbServiceStubFuzzTest") { + module_out_path = "datamgr_service/service" + + include_dirs = [ + "${data_service_path}/adapter/include", + "${data_service_path}/app/src", + "${data_service_path}/framework/include", + "${data_service_path}/service/backup/include", + "${data_service_path}/service/bootstrap/include", + "${data_service_path}/service/config/include", + "${data_service_path}/service/crypto/include", + "${data_service_path}/service/kvdb", + "${data_service_path}/service/matrix/include", + "${data_service_path}/service/permission/include", + "${kv_store_common_path}", + "${kv_store_path}/frameworks/innerkitsimpl/distributeddatafwk/include", + "${kv_store_path}/frameworks/innerkitsimpl/kvdb/include", + "${kv_store_distributeddb_path}", + "${kv_store_distributeddb_path}/include/", + "${kv_store_distributeddb_path}/interfaces/include/", + "${kv_store_distributeddb_path}/interfaces/include/relational", + "//third_party/json/single_include", + ] + + fuzz_config_file = + "${data_service_path}/service/test/fuzztest/kvdbservicestub_fuzzer" + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + sources = [ + "${data_service_path}/service/backup/src/backup_manager.cpp", + "${data_service_path}/service/bootstrap/src/bootstrap.cpp", + "${data_service_path}/service/config/src/config_factory.cpp", + "${data_service_path}/service/config/src/model/backup_config.cpp", + "${data_service_path}/service/config/src/model/checker_config.cpp", + "${data_service_path}/service/config/src/model/component_config.cpp", + "${data_service_path}/service/config/src/model/directory_config.cpp", + "${data_service_path}/service/config/src/model/global_config.cpp", + "${data_service_path}/service/config/src/model/network_config.cpp", + "${data_service_path}/service/config/src/model/protocol_config.cpp", + "${data_service_path}/service/crypto/src/crypto_manager.cpp", + "${data_service_path}/service/kvdb/auth_delegate.cpp", + "${data_service_path}/service/kvdb/kvdb_exporter.cpp", + "${data_service_path}/service/kvdb/kvdb_service_impl.cpp", + "${data_service_path}/service/kvdb/kvdb_service_stub.cpp", + "${data_service_path}/service/kvdb/kvstore_sync_manager.cpp", + "${data_service_path}/service/kvdb/query_helper.cpp", + "${data_service_path}/service/kvdb/store_cache.cpp", + "${data_service_path}/service/kvdb/upgrade.cpp", + "${data_service_path}/service/kvdb/user_delegate.cpp", + "${data_service_path}/service/matrix/src/device_matrix.cpp", + "${data_service_path}/service/matrix/src/matrix_event.cpp", + "${data_service_path}/service/permission/src/permit_delegate.cpp", + "kvdbservicestub_fuzzer.cpp", + ] + + deps = [ + "${data_service_path}/adapter:distributeddata_adapter", + "${data_service_path}/adapter/utils:distributeddata_utils_static", + "${data_service_path}/framework:distributeddatasvcfwk", + "${kv_store_distributeddb_path}:distributeddb", + ] + + external_deps = [ + "ability_base:want", + "ability_base:zuri", + "ability_runtime:ability_manager", + "ability_runtime:dataobs_manager", + "access_token:libaccesstoken_sdk", + "access_token:libtokenid_sdk", + "c_utils:utils", + "device_auth:deviceauth_sdk", + "device_manager:devicemanagersdk", + "hilog:libhilog", + "huks:libhukssdk", + "ipc:ipc_core", + "kv_store:distributeddata_inner", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + + deps = [ ":KvdbServiceStubFuzzTest" ] +} +############################################################################### diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/kvdbservicestub_fuzzer/corpus/init b/datamgr_service/services/distributeddataservice/service/test/fuzztest/kvdbservicestub_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..2b595da0c26af63ffb2d5f4132c086b2e5986fce --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/kvdbservicestub_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/kvdbservicestub_fuzzer/kvdbservicestub_fuzzer.cpp b/datamgr_service/services/distributeddataservice/service/test/fuzztest/kvdbservicestub_fuzzer/kvdbservicestub_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b01aa99967f793421d1ff0747fcd14bcbceae904 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/kvdbservicestub_fuzzer/kvdbservicestub_fuzzer.cpp @@ -0,0 +1,56 @@ +/* + * 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 "kvdbservicestub_fuzzer.h" + +#include +#include + +#include "kvdb_service_impl.h" +#include "message_parcel.h" +#include "securec.h" + +using namespace OHOS::DistributedKv; + +namespace OHOS { +const std::u16string INTERFACE_TOKEN = u"OHOS.DistributedKv.KVFeature"; +const uint32_t CODE_MIN = 0; +const uint32_t CODE_MAX = 16; + +bool OnRemoteRequestFuzz(const uint8_t *data, size_t size) +{ + uint32_t code = static_cast(*data) % (CODE_MAX - CODE_MIN + 1) + CODE_MIN; + MessageParcel request; + request.WriteInterfaceToken(INTERFACE_TOKEN); + request.WriteBuffer(data, size); + request.RewindRead(0); + MessageParcel reply; + std::shared_ptr kvdbServiceStub = std::make_shared(); + kvdbServiceStub->OnRemoteRequest(code, request, reply); + return true; +} +} // namespace OHOS + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + if (data == nullptr) { + return 0; + } + + OHOS::OnRemoteRequestFuzz(data, size); + + return 0; +} \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/kvdbservicestub_fuzzer/kvdbservicestub_fuzzer.h b/datamgr_service/services/distributeddataservice/service/test/fuzztest/kvdbservicestub_fuzzer/kvdbservicestub_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..9fba238a6cf9cee15cd6cdf4c785235ebc5932f1 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/kvdbservicestub_fuzzer/kvdbservicestub_fuzzer.h @@ -0,0 +1,21 @@ +/* + * 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 DATAMGR_SERVICE_KVDB_SERVICE_STUB_FUZZER_H +#define DATAMGR_SERVICE_KVDB_SERVICE_STUB_FUZZER_H + +#define FUZZ_PROJECT_NAME "kvdbservicestub_fuzzer" + +#endif // DATAMGR_SERVICE_KVDB_SERVICE_STUB_FUZZER_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/kvdbservicestub_fuzzer/project.xml b/datamgr_service/services/distributeddataservice/service/test/fuzztest/kvdbservicestub_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..3fdba3e8b151bbb9026792021977b81e8a1851a6 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/kvdbservicestub_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectservicestub_fuzzer/BUILD.gn b/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectservicestub_fuzzer/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..2db37d6efe47357f88cc30d1fd09f343e68f773a --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectservicestub_fuzzer/BUILD.gn @@ -0,0 +1,110 @@ +# 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. +##############################hydra-fuzz######################################## +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/datamgr_service/datamgr_service.gni") + +##############################fuzztest########################################## +ohos_fuzztest("ObjectServiceStubFuzzTest") { + module_out_path = "datamgr_service/service" + + include_dirs = [ + "${data_service_path}/adapter/include", + "${data_service_path}/app/src", + "${data_service_path}/framework/include", + "${data_service_path}/service/backup/include", + "${data_service_path}/service/bootstrap/include", + "${data_service_path}/service/cloud", + "${data_service_path}/service/config/include", + "${data_service_path}/service/crypto/include", + "${data_service_path}/service/data_share", + "${data_service_path}/service/kvdb", + "${data_service_path}/service/matrix/include", + "${data_service_path}/service/object", + "${data_service_path}/service/permission/include", + "${data_service_path}/service/rdb", + "${kv_store_common_path}", + "${kv_store_path}/frameworks/innerkitsimpl/distributeddatafwk/include", + "${kv_store_path}/frameworks/innerkitsimpl/kvdb/include", + "${kv_store_distributeddb_path}", + "${kv_store_distributeddb_path}/include/", + "${kv_store_distributeddb_path}/interfaces/include/", + "${kv_store_distributeddb_path}/interfaces/include/relational", + "${dataobject_path}/frameworks/innerkitsimpl/include", + "//third_party/json/single_include", + ] + + fuzz_config_file = + "${data_service_path}/service/test/fuzztest/objectservicestub_fuzzer" + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + sources = [ + "${data_service_path}/service/bootstrap/src/bootstrap.cpp", + "${data_service_path}/service/config/src/config_factory.cpp", + "${data_service_path}/service/config/src/model/backup_config.cpp", + "${data_service_path}/service/config/src/model/checker_config.cpp", + "${data_service_path}/service/config/src/model/component_config.cpp", + "${data_service_path}/service/config/src/model/directory_config.cpp", + "${data_service_path}/service/config/src/model/global_config.cpp", + "${data_service_path}/service/config/src/model/network_config.cpp", + "${data_service_path}/service/config/src/model/protocol_config.cpp", + "${data_service_path}/service/crypto/src/crypto_manager.cpp", + "${data_service_path}/service/matrix/src/device_matrix.cpp", + "${data_service_path}/service/matrix/src/matrix_event.cpp", + "${data_service_path}/service/object/object_callback_proxy.cpp", + "${data_service_path}/service/object/object_data_listener.cpp", + "${data_service_path}/service/object/object_manager.cpp", + "${data_service_path}/service/object/object_service_impl.cpp", + "${data_service_path}/service/object/object_service_stub.cpp", + "${data_service_path}/service/permission/src/permit_delegate.cpp", + "objectservicestub_fuzzer.cpp", + ] + + deps = [ + "${data_service_path}/adapter:distributeddata_adapter", + "${data_service_path}/adapter/utils:distributeddata_utils_static", + "${data_service_path}/framework:distributeddatasvcfwk", + "${kv_store_distributeddb_path}:distributeddb", + ] + + external_deps = [ + "ability_base:want", + "ability_base:zuri", + "ability_runtime:ability_manager", + "ability_runtime:dataobs_manager", + "access_token:libaccesstoken_sdk", + "access_token:libtokenid_sdk", + "c_utils:utils", + "device_auth:deviceauth_sdk", + "device_manager:devicemanagersdk", + "hilog:libhilog", + "huks:libhukssdk", + "ipc:ipc_core", + "kv_store:distributeddata_inner", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + + deps = [ ":ObjectServiceStubFuzzTest" ] +} +############################################################################### diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectservicestub_fuzzer/corpus/init b/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectservicestub_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..2b595da0c26af63ffb2d5f4132c086b2e5986fce --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectservicestub_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectservicestub_fuzzer/objectservicestub_fuzzer.cpp b/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectservicestub_fuzzer/objectservicestub_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..410f53b1885bcab750e9b615e0c9acc590f76ed0 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectservicestub_fuzzer/objectservicestub_fuzzer.cpp @@ -0,0 +1,56 @@ +/* + * 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 "objectservicestub_fuzzer.h" + +#include +#include + +#include "object_service_impl.h" +#include "message_parcel.h" +#include "securec.h" + +using namespace OHOS::DistributedObject; + +namespace OHOS { +const std::u16string INTERFACE_TOKEN = u"OHOS.DistributedObject.IObjectService"; +const uint32_t CODE_MIN = 0; +const uint32_t CODE_MAX = 4; + +bool OnRemoteRequestFuzz(const uint8_t *data, size_t size) +{ + uint32_t code = static_cast(*data) % (CODE_MAX - CODE_MIN + 1) + CODE_MIN; + MessageParcel request; + request.WriteInterfaceToken(INTERFACE_TOKEN); + request.WriteBuffer(data, size); + request.RewindRead(0); + MessageParcel reply; + std::shared_ptr objectServiceStub = std::make_shared(); + objectServiceStub->OnRemoteRequest(code, request, reply); + return true; +} +} // namespace OHOS + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + if (data == nullptr) { + return 0; + } + + OHOS::OnRemoteRequestFuzz(data, size); + + return 0; +} \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectservicestub_fuzzer/objectservicestub_fuzzer.h b/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectservicestub_fuzzer/objectservicestub_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..019e06f5f660c8e2097558524def59e6a4e05597 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectservicestub_fuzzer/objectservicestub_fuzzer.h @@ -0,0 +1,21 @@ +/* + * 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 DATAMGR_SERVICE_OBJECT_SERVICE_STUB_FUZZER_H +#define DATAMGR_SERVICE_OBJECT_SERVICE_STUB_FUZZER_H + +#define FUZZ_PROJECT_NAME "objectservicestub_fuzzer" + +#endif // DATAMGR_SERVICE_OBJECT_SERVICE_STUB_FUZZER_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectservicestub_fuzzer/project.xml b/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectservicestub_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..3fdba3e8b151bbb9026792021977b81e8a1851a6 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectservicestub_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/rdbresultsetstub_fuzzer/BUILD.gn b/datamgr_service/services/distributeddataservice/service/test/fuzztest/rdbresultsetstub_fuzzer/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..494fd1c028fb78d54c3faab3298a37e79f6f1072 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/rdbresultsetstub_fuzzer/BUILD.gn @@ -0,0 +1,123 @@ +# 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. +##############################hydra-fuzz######################################## +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/datamgr_service/datamgr_service.gni") + +##############################fuzztest########################################## +ohos_fuzztest("RdbResultSetStubFuzzTest") { + module_out_path = "datamgr_service/service" + + include_dirs = [ + "${data_service_path}/adapter/include", + "${data_service_path}/app/src", + "${data_service_path}/framework/include", + "${data_service_path}/service/backup/include", + "${data_service_path}/service/bootstrap/include", + "${data_service_path}/service/cloud", + "${data_service_path}/service/config/include", + "${data_service_path}/service/crypto/include", + "${data_service_path}/service/data_share", + "${data_service_path}/service/kvdb", + "${data_service_path}/service/matrix/include", + "${data_service_path}/service/object", + "${data_service_path}/service/permission/include", + "${data_service_path}/service/rdb", + "${kv_store_common_path}", + "${kv_store_path}/frameworks/innerkitsimpl/distributeddatafwk/include", + "${kv_store_path}/frameworks/innerkitsimpl/kvdb/include", + "${kv_store_distributeddb_path}", + "${kv_store_distributeddb_path}/include/", + "${kv_store_distributeddb_path}/interfaces/include/", + "${kv_store_distributeddb_path}/interfaces/include/relational", + "${dataobject_path}/frameworks/innerkitsimpl/include", + "${relational_store_path}/interfaces/inner_api/cloud_data/include", + "${relational_store_path}/interfaces/inner_api/rdb/include", + "//third_party/json/single_include", + ] + + fuzz_config_file = + "${data_service_path}/service/test/fuzztest/rdbresultsetstub_fuzzer" + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + sources = [ + "${data_service_path}/service/bootstrap/src/bootstrap.cpp", + "${data_service_path}/service/config/src/config_factory.cpp", + "${data_service_path}/service/config/src/model/backup_config.cpp", + "${data_service_path}/service/config/src/model/checker_config.cpp", + "${data_service_path}/service/config/src/model/component_config.cpp", + "${data_service_path}/service/config/src/model/directory_config.cpp", + "${data_service_path}/service/config/src/model/global_config.cpp", + "${data_service_path}/service/config/src/model/network_config.cpp", + "${data_service_path}/service/config/src/model/protocol_config.cpp", + "${data_service_path}/service/crypto/src/crypto_manager.cpp", + "${data_service_path}/service/matrix/src/device_matrix.cpp", + "${data_service_path}/service/matrix/src/matrix_event.cpp", + "${data_service_path}/service/permission/src/permit_delegate.cpp", + "${data_service_path}/service/rdb/rdb_asset_loader.cpp", + "${data_service_path}/service/rdb/rdb_cloud.cpp", + "${data_service_path}/service/rdb/rdb_cloud_data_translate.cpp", + "${data_service_path}/service/rdb/rdb_cursor.cpp", + "${data_service_path}/service/rdb/rdb_general_store.cpp", + "${data_service_path}/service/rdb/rdb_notifier_proxy.cpp", + "${data_service_path}/service/rdb/rdb_query.cpp", + "${data_service_path}/service/rdb/rdb_result_set_impl.cpp", + "${data_service_path}/service/rdb/rdb_result_set_stub.cpp", + "${data_service_path}/service/rdb/rdb_service_impl.cpp", + "${data_service_path}/service/rdb/rdb_service_stub.cpp", + "${data_service_path}/service/rdb/rdb_store_observer_impl.cpp", + "${data_service_path}/service/rdb/rdb_syncer.cpp", + "${data_service_path}/service/rdb/rdb_watcher.cpp", + "${data_service_path}/service/rdb/value_proxy.cpp", + "rdbresultsetstub_fuzzer.cpp", + ] + + deps = [ + "${data_service_path}/adapter:distributeddata_adapter", + "${data_service_path}/adapter/utils:distributeddata_utils_static", + "${data_service_path}/framework:distributeddatasvcfwk", + "${kv_store_distributeddb_path}:distributeddb", + ] + + external_deps = [ + "ability_base:want", + "ability_base:zuri", + "ability_runtime:ability_manager", + "ability_runtime:dataobs_manager", + "access_token:libaccesstoken_sdk", + "access_token:libtokenid_sdk", + "c_utils:utils", + "device_auth:deviceauth_sdk", + "device_manager:devicemanagersdk", + "hilog:libhilog", + "huks:libhukssdk", + "ipc:ipc_core", + "kv_store:distributeddata_inner", + "relational_store:native_rdb", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + + deps = [ ":RdbResultSetStubFuzzTest" ] +} +############################################################################### diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/rdbresultsetstub_fuzzer/corpus/init b/datamgr_service/services/distributeddataservice/service/test/fuzztest/rdbresultsetstub_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..2b595da0c26af63ffb2d5f4132c086b2e5986fce --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/rdbresultsetstub_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/rdbresultsetstub_fuzzer/project.xml b/datamgr_service/services/distributeddataservice/service/test/fuzztest/rdbresultsetstub_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..3fdba3e8b151bbb9026792021977b81e8a1851a6 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/rdbresultsetstub_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/rdbresultsetstub_fuzzer/rdbresultsetstub_fuzzer.cpp b/datamgr_service/services/distributeddataservice/service/test/fuzztest/rdbresultsetstub_fuzzer/rdbresultsetstub_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a154212224b16d60e43742a50c7622bc55fd7042 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/rdbresultsetstub_fuzzer/rdbresultsetstub_fuzzer.cpp @@ -0,0 +1,58 @@ +/* + * 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 "rdbresultsetstub_fuzzer.h" + +#include +#include + +#include "rdb_result_set_impl.h" +#include "message_parcel.h" +#include "securec.h" + +using namespace OHOS::DistributedRdb; + +namespace OHOS { +const std::u16string INTERFACE_TOKEN = u"OHOS::NativeRdb.IResultSet"; +const uint32_t CODE_MIN = 0; +const uint32_t CODE_MAX = 24; + +bool OnRemoteRequestFuzz(const uint8_t *data, size_t size) +{ + uint32_t code = static_cast(*data) % (CODE_MAX - CODE_MIN + 1) + CODE_MIN; + MessageParcel request; + request.WriteInterfaceToken(INTERFACE_TOKEN); + request.WriteBuffer(data, size); + request.RewindRead(0); + MessageParcel reply; + MessageOption option; + std::shared_ptr dbResultSet; + std::shared_ptr rdbResultSetStub = std::make_shared(dbResultSet); + rdbResultSetStub->OnRemoteRequest(code, request, reply, option); + return true; +} +} // namespace OHOS + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + if (data == nullptr) { + return 0; + } + + OHOS::OnRemoteRequestFuzz(data, size); + + return 0; +} \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/rdbresultsetstub_fuzzer/rdbresultsetstub_fuzzer.h b/datamgr_service/services/distributeddataservice/service/test/fuzztest/rdbresultsetstub_fuzzer/rdbresultsetstub_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..b8f8cc3703e020b88e5ae9befa89fb227bbcbb72 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/rdbresultsetstub_fuzzer/rdbresultsetstub_fuzzer.h @@ -0,0 +1,21 @@ +/* + * 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 DATAMGR_SERVICE_RDB_RESULT_SET_STUB_FUZZER_H +#define DATAMGR_SERVICE_RDB_RESULT_SET_STUB_FUZZER_H + +#define FUZZ_PROJECT_NAME "rdbresultsetstub_fuzzer" + +#endif // DATAMGR_SERVICE_RDB_RESULT_SET_STUB_FUZZER_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/rdbservicestub_fuzzer/BUILD.gn b/datamgr_service/services/distributeddataservice/service/test/fuzztest/rdbservicestub_fuzzer/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..9fef09470c932bc9f5d706e3864e2d35da2b8e5e --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/rdbservicestub_fuzzer/BUILD.gn @@ -0,0 +1,111 @@ +# 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. +##############################hydra-fuzz######################################## +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/datamgr_service/datamgr_service.gni") + +##############################fuzztest########################################## +ohos_fuzztest("RdbServiceStubFuzzTest") { + module_out_path = "datamgr_service/service" + + include_dirs = [ + "${data_service_path}/adapter/include", + "${data_service_path}/app/src", + "${data_service_path}/framework/include", + "${data_service_path}/service/backup/include", + "${data_service_path}/service/bootstrap/include", + "${data_service_path}/service/cloud", + "${data_service_path}/service/config/include", + "${data_service_path}/service/crypto/include", + "${data_service_path}/service/data_share", + "${data_service_path}/service/kvdb", + "${data_service_path}/service/matrix/include", + "${data_service_path}/service/object", + "${data_service_path}/service/permission/include", + "${data_service_path}/service/rdb", + "${kv_store_common_path}", + "${kv_store_path}/frameworks/innerkitsimpl/distributeddatafwk/include", + "${kv_store_path}/frameworks/innerkitsimpl/kvdb/include", + "${kv_store_distributeddb_path}", + "${kv_store_distributeddb_path}/include/", + "${kv_store_distributeddb_path}/interfaces/include/", + "${kv_store_distributeddb_path}/interfaces/include/relational", + "${dataobject_path}/frameworks/innerkitsimpl/include", + "${relational_store_path}/interfaces/inner_api/cloud_data/include", + "${relational_store_path}/interfaces/inner_api/rdb/include", + "//third_party/json/single_include", + ] + + fuzz_config_file = + "${data_service_path}/service/test/fuzztest/rdbservicestub_fuzzer" + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + sources = [ + "${data_service_path}/service/rdb/rdb_asset_loader.cpp", + "${data_service_path}/service/rdb/rdb_cloud.cpp", + "${data_service_path}/service/rdb/rdb_cloud_data_translate.cpp", + "${data_service_path}/service/rdb/rdb_cursor.cpp", + "${data_service_path}/service/rdb/rdb_general_store.cpp", + "${data_service_path}/service/rdb/rdb_notifier_proxy.cpp", + "${data_service_path}/service/rdb/rdb_query.cpp", + "${data_service_path}/service/rdb/rdb_result_set_impl.cpp", + "${data_service_path}/service/rdb/rdb_result_set_stub.cpp", + "${data_service_path}/service/rdb/rdb_service_impl.cpp", + "${data_service_path}/service/rdb/rdb_service_stub.cpp", + "${data_service_path}/service/rdb/rdb_store_observer_impl.cpp", + "${data_service_path}/service/rdb/rdb_syncer.cpp", + "${data_service_path}/service/rdb/rdb_watcher.cpp", + "${data_service_path}/service/rdb/value_proxy.cpp", + "rdbservicestub_fuzzer.cpp", + ] + + deps = [ + "${data_service_path}/adapter:distributeddata_adapter", + "${data_service_path}/adapter/utils:distributeddata_utils_static", + "${data_service_path}/framework:distributeddatasvcfwk", + "${data_service_path}/service:distributeddatasvc", + "${kv_store_distributeddb_path}:distributeddb", + ] + + external_deps = [ + "ability_base:want", + "ability_base:zuri", + "ability_runtime:ability_manager", + "ability_runtime:dataobs_manager", + "access_token:libaccesstoken_sdk", + "access_token:libtokenid_sdk", + "c_utils:utils", + "device_auth:deviceauth_sdk", + "device_manager:devicemanagersdk", + "hilog:libhilog", + "huks:libhukssdk", + "ipc:ipc_core", + "kv_store:distributeddata_inner", + "relational_store:native_rdb", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + + deps = [ ":RdbServiceStubFuzzTest" ] +} +############################################################################### diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/rdbservicestub_fuzzer/corpus/init b/datamgr_service/services/distributeddataservice/service/test/fuzztest/rdbservicestub_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..2b595da0c26af63ffb2d5f4132c086b2e5986fce --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/rdbservicestub_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/rdbservicestub_fuzzer/project.xml b/datamgr_service/services/distributeddataservice/service/test/fuzztest/rdbservicestub_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..3fdba3e8b151bbb9026792021977b81e8a1851a6 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/rdbservicestub_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/rdbservicestub_fuzzer/rdbservicestub_fuzzer.cpp b/datamgr_service/services/distributeddataservice/service/test/fuzztest/rdbservicestub_fuzzer/rdbservicestub_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..aa7737e8a951fb777ae699293a004716e86ab002 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/rdbservicestub_fuzzer/rdbservicestub_fuzzer.cpp @@ -0,0 +1,56 @@ +/* + * 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 "rdbservicestub_fuzzer.h" + +#include +#include + +#include "rdb_service_impl.h" +#include "message_parcel.h" +#include "securec.h" + +using namespace OHOS::DistributedRdb; + +namespace OHOS { +const std::u16string INTERFACE_TOKEN = u"OHOS.DistributedRdb.IRdbService"; +const uint32_t CODE_MIN = 0; +const uint32_t CODE_MAX = 10; + +bool OnRemoteRequestFuzz(const uint8_t *data, size_t size) +{ + uint32_t code = static_cast(*data) % (CODE_MAX - CODE_MIN + 1) + CODE_MIN; + MessageParcel request; + request.WriteInterfaceToken(INTERFACE_TOKEN); + request.WriteBuffer(data, size); + request.RewindRead(0); + MessageParcel reply; + std::shared_ptr rdbServiceStub = std::make_shared(); + rdbServiceStub->OnRemoteRequest(code, request, reply); + return true; +} +} // namespace OHOS + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + if (data == nullptr) { + return 0; + } + + OHOS::OnRemoteRequestFuzz(data, size); + + return 0; +} \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/rdbservicestub_fuzzer/rdbservicestub_fuzzer.h b/datamgr_service/services/distributeddataservice/service/test/fuzztest/rdbservicestub_fuzzer/rdbservicestub_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..582118e945c66c0176dfb4a0f4328120a1cbd0a8 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/rdbservicestub_fuzzer/rdbservicestub_fuzzer.h @@ -0,0 +1,21 @@ +/* + * 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 DATAMGR_SERVICE_RDB_SERVICE_STUB_FUZZER_H +#define DATAMGR_SERVICE_RDB_SERVICE_STUB_FUZZER_H + +#define FUZZ_PROJECT_NAME "rdbservicestub_fuzzer" + +#endif // DATAMGR_SERVICE_RDB_SERVICE_STUB_FUZZER_HH \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/udmfservice_fuzzer/BUILD.gn b/datamgr_service/services/distributeddataservice/service/test/fuzztest/udmfservice_fuzzer/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..4656e9aa1061f4e7e75f2e9d794fa9c8a3666f52 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/udmfservice_fuzzer/BUILD.gn @@ -0,0 +1,71 @@ +# 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. +##############################hydra-fuzz######################################## +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/datamgr_service/datamgr_service.gni") + +##############################fuzztest########################################## +ohos_fuzztest("UdmfServiceFuzzTest") { + module_out_path = "datamgr_service/service" + + include_dirs = [ + "${udmf_path}/framework/common", + "${udmf_path}/interfaces/innerkits/common", + "${udmf_path}/interfaces/innerkits/data", + "${data_service_path}/framework/include", + "${data_service_path}/service/udmf/lifecycle", + "${data_service_path}/service/udmf/permission", + "${data_service_path}/service/udmf/preprocess", + "${data_service_path}/service/udmf/store", + "${data_service_path}/service/udmf", + "${kv_store_path}/frameworks/common", + ] + + fuzz_config_file = + "${data_service_path}/service/test/fuzztest/udmfservice_fuzzer" + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + sources = [ "udmfservice_fuzzer.cpp" ] + + deps = [ + "${data_service_path}/framework:distributeddatasvcfwk", + "${data_service_path}/service/udmf:udmf_server", + ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:uri_permission_mgr", + "access_token:libaccesstoken_sdk", + "bundle_framework:appexecfwk_core", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:distributeddata_inner", + "udmf:udmf_client", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + + deps = [ ":UdmfServiceFuzzTest" ] +} +############################################################################### diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/udmfservice_fuzzer/corpus/init b/datamgr_service/services/distributeddataservice/service/test/fuzztest/udmfservice_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..2b595da0c26af63ffb2d5f4132c086b2e5986fce --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/udmfservice_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/udmfservice_fuzzer/project.xml b/datamgr_service/services/distributeddataservice/service/test/fuzztest/udmfservice_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..3fdba3e8b151bbb9026792021977b81e8a1851a6 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/udmfservice_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/udmfservice_fuzzer/udmfservice_fuzzer.cpp b/datamgr_service/services/distributeddataservice/service/test/fuzztest/udmfservice_fuzzer/udmfservice_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..010f5bda2ed59c77b4dd844b105bf3e9afc43804 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/udmfservice_fuzzer/udmfservice_fuzzer.cpp @@ -0,0 +1,54 @@ +/* + * 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 "udmfservice_fuzzer.h" + +#include +#include + +#include "udmf_service_impl.h" +#include "message_parcel.h" +#include "securec.h" + +using namespace OHOS::UDMF; + +namespace OHOS { +const std::u16string INTERFACE_TOKEN = u"OHOS.UDMF.UdmfService"; + +bool OnRemoteRequestFuzz(const uint8_t* data, size_t size) +{ + uint32_t code = static_cast(*data); + MessageParcel request; + request.WriteInterfaceToken(INTERFACE_TOKEN); + request.WriteBuffer(data, size); + request.RewindRead(0); + MessageParcel reply; + std::shared_ptr udmfServiceStub = std::make_shared(); + udmfServiceStub->OnRemoteRequest(code, request, reply); + return true; +} +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + if (data == nullptr) { + return 0; + } + + OHOS::OnRemoteRequestFuzz(data, size); + + return 0; +} \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/udmfservice_fuzzer/udmfservice_fuzzer.h b/datamgr_service/services/distributeddataservice/service/test/fuzztest/udmfservice_fuzzer/udmfservice_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..d86d273e4424aeb50d7c2d1a3854d2e8be9e6fab --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/udmfservice_fuzzer/udmfservice_fuzzer.h @@ -0,0 +1,21 @@ +/* + * 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 UDMF_SERVICE_FUZZER_H +#define UDMF_SERVICE_FUZZER_H + +#define FUZZ_PROJECT_NAME "udmfservice_fuzzer" + +#endif // UDMF_SERVICE_FUZZER_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/udmf/BUILD.gn b/datamgr_service/services/distributeddataservice/service/udmf/BUILD.gn index 64077d4560ad95ff48208b9bbac566fc0a462c9d..9997263e4b77f2ad29f69953fe0d89f4c4dfb7ce 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/udmf/BUILD.gn @@ -13,10 +13,6 @@ import("//build/ohos.gni") import("//foundation/distributeddatamgr/datamgr_service/datamgr_service.gni") -group("build_module") { - deps = [ ":udmf_server" ] -} - config("module_public_config") { visibility = [ ":*" ] @@ -62,7 +58,7 @@ ohos_shared_library("udmf_server") { "access_token:libaccesstoken_sdk", "bundle_framework:appexecfwk_core", "c_utils:utils", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", "ipc:ipc_core", "kv_store:distributeddata_inner", "udmf:udmf_client", diff --git a/datamgr_service/services/distributeddataservice/service/udmf/data_manager.cpp b/datamgr_service/services/distributeddataservice/service/udmf/data_manager.cpp index c2d3b94f22a2a7acad9bed5880599082d8c0e987..7b4bc0a30bf23c308010ca79b8bb7267c3dbe420 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/data_manager.cpp +++ b/datamgr_service/services/distributeddataservice/service/udmf/data_manager.cpp @@ -56,13 +56,13 @@ int32_t DataManager::SaveData(CustomOption &option, UnifiedData &unifiedData, st } // imput runtime info before put it into store and save one privilege - PreProcessUtils utils = PreProcessUtils::GetInstance(); - if (!utils.RuntimeDataImputation(unifiedData, option)) { - ZLOGE("Imputation failed, %{public}s", utils.errorStr.c_str()); + if (PreProcessUtils::RuntimeDataImputation(unifiedData, option) != E_OK) { + ZLOGE("Imputation failed"); return E_UNKNOWN; } - for (const auto &record : unifiedData.GetRecords()) { - record->SetUid(PreProcessUtils::GetInstance().IdGenerator()); + for (auto &record : unifiedData.GetRecords()) { + std::string uid = PreProcessUtils::IdGenerator(); + record->SetUid(uid); } std::string intention = unifiedData.GetRuntime()->key.intention; @@ -113,7 +113,7 @@ int32_t DataManager::RetrieveData(const QueryOption &query, UnifiedData &unified return E_NO_PERMISSION; } std::string bundleName; - if (!PreProcessUtils::GetInstance().GetHapBundleNameByToken(query.tokenId, bundleName)) { + if (!PreProcessUtils::GetHapBundleNameByToken(query.tokenId, bundleName)) { return E_ERROR; } if (runtime->createPackage != bundleName) { @@ -185,10 +185,10 @@ int32_t DataManager::UpdateData(const QueryOption &query, UnifiedData &unifiedDa return E_INVALID_PARAMETERS; } std::shared_ptr runtime = data.GetRuntime(); - runtime->lastModifiedTime = PreProcessUtils::GetInstance().GetTimeStamp(); + runtime->lastModifiedTime = PreProcessUtils::GetTimeStamp(); unifiedData.SetRuntime(*runtime); - for (const auto &record : unifiedData.GetRecords()) { - record->SetUid(PreProcessUtils::GetInstance().IdGenerator()); + for (auto &record : unifiedData.GetRecords()) { + record->SetUid(PreProcessUtils::IdGenerator()); } if (store->Update(unifiedData) != E_OK) { ZLOGE("Update unified data failed, intention: %{public}s.", key.intention.c_str()); @@ -253,9 +253,7 @@ int32_t DataManager::AddPrivilege(const QueryOption &query, const Privilege &pri } std::string processName; - PreProcessUtils utils = PreProcessUtils::GetInstance(); - if (!utils.GetNativeProcessNameByToken(query.tokenId, processName)) { - ZLOGE("%{public}s", utils.errorStr.c_str()); + if (!PreProcessUtils::GetNativeProcessNameByToken(query.tokenId, processName)) { return E_UNKNOWN; } diff --git a/datamgr_service/services/distributeddataservice/service/udmf/data_manager.h b/datamgr_service/services/distributeddataservice/service/udmf/data_manager.h index 518e288d16a0de8bd2f025c4a10ed435988e2b70..aab4039812200fc860b68f370418e20557798cc4 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/data_manager.h +++ b/datamgr_service/services/distributeddataservice/service/udmf/data_manager.h @@ -22,9 +22,10 @@ #include #include "error_code.h" -#include "store_cache1.h" +#include "store/store_cache.h" #include "unified_data.h" #include "unified_types.h" +#include "store.h" namespace OHOS { namespace UDMF { @@ -46,7 +47,7 @@ public: private: DataManager(); int32_t QueryDataCommon(const QueryOption &query, std::vector &dataSet, std::shared_ptr &store); - StoreCache1 storeCache_; + StoreCache storeCache_; std::map authorizationMap_; }; } // namespace UDMF diff --git a/datamgr_service/services/distributeddataservice/service/udmf/lifecycle/lifecycle_policy.cpp b/datamgr_service/services/distributeddataservice/service/udmf/lifecycle/lifecycle_policy.cpp index 280866e666e61a538ef6648c78e33acf5220f1a6..7e790fb94a4ee964e99ae4efb1a0280ca3225aa5 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/lifecycle/lifecycle_policy.cpp +++ b/datamgr_service/services/distributeddataservice/service/udmf/lifecycle/lifecycle_policy.cpp @@ -88,7 +88,7 @@ Status LifeCyclePolicy::GetTimeoutKeys( ZLOGD("entries is empty."); return E_OK; } - auto curTime = PreProcessUtils::GetInstance().GetTimeStamp(); + auto curTime = PreProcessUtils::GetTimeStamp(); for (const auto &data : datas) { if (curTime > data.GetRuntime()->createTime + duration_cast(interval).count() || curTime < data.GetRuntime()->createTime) { diff --git a/datamgr_service/services/distributeddataservice/service/udmf/lifecycle/lifecycle_policy.h b/datamgr_service/services/distributeddataservice/service/udmf/lifecycle/lifecycle_policy.h index 175c997cb74a645f602d2ad514d1857c7e596e9d..c3f45d8d23c30d90c6d29225d7058223675138dc 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/lifecycle/lifecycle_policy.h +++ b/datamgr_service/services/distributeddataservice/service/udmf/lifecycle/lifecycle_policy.h @@ -18,9 +18,10 @@ #include #include -#include "store.h" -#include "store_cache1.h" +#include "store/store_cache.h" #include "unified_key.h" +#include "error_code.h" +#include "store.h" namespace OHOS { namespace UDMF { @@ -37,7 +38,7 @@ public: private: static const std::string DATA_PREFIX; - StoreCache1 storeCache_; + StoreCache storeCache_; }; } // namespace UDMF } // namespace OHOS diff --git a/datamgr_service/services/distributeddataservice/service/udmf/preprocess/preprocess_utils.cpp b/datamgr_service/services/distributeddataservice/service/udmf/preprocess/preprocess_utils.cpp index 6962c69b7f3676542fafdd4fa138732482f0d17a..130ffa20ea4b276e50a9447088b3184c8115bc4a 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/preprocess/preprocess_utils.cpp +++ b/datamgr_service/services/distributeddataservice/service/udmf/preprocess/preprocess_utils.cpp @@ -17,6 +17,7 @@ #include +#include "error_code.h" #include "accesstoken_kit.h" #include "bundlemgr/bundle_mgr_client_impl.h" #include "ipc_skeleton.h" @@ -25,18 +26,11 @@ namespace OHOS { namespace UDMF { static constexpr int ID_LEN = 32; const char SPECIAL = '^'; -PreProcessUtils &PreProcessUtils::GetInstance() -{ - static auto instance = new PreProcessUtils(); - return *instance; -} - -bool PreProcessUtils::RuntimeDataImputation(UnifiedData &data, CustomOption &option) +int32_t PreProcessUtils::RuntimeDataImputation(UnifiedData &data, CustomOption &option) { auto it = UD_INTENTION_MAP.find(option.intention); if (it == UD_INTENTION_MAP.end()) { - errorStr = "invalid intention"; - return false; + return E_UNKNOWN; } std::string bundleName; GetHapBundleNameByToken(option.tokenId, bundleName); @@ -51,7 +45,7 @@ bool PreProcessUtils::RuntimeDataImputation(UnifiedData &data, CustomOption &opt runtime.sourcePackage = bundleName; runtime.createPackage = bundleName; data.SetRuntime(runtime); - return true; + return E_OK; } std::string PreProcessUtils::IdGenerator() @@ -82,7 +76,6 @@ bool PreProcessUtils::GetHapBundleNameByToken(int tokenId, std::string &bundleNa Security::AccessToken::HapTokenInfo hapInfo; if (Security::AccessToken::AccessTokenKit::GetHapTokenInfo(tokenId, hapInfo) != Security::AccessToken::AccessTokenKitRet::RET_SUCCESS) { - errorStr = "get bundle info error"; return false; } bundleName = hapInfo.bundleName; @@ -94,7 +87,6 @@ bool PreProcessUtils::GetNativeProcessNameByToken(int tokenId, std::string &proc Security::AccessToken::NativeTokenInfo nativeInfo; if (Security::AccessToken::AccessTokenKit::GetNativeTokenInfo(tokenId, nativeInfo) != Security::AccessToken::AccessTokenKitRet::RET_SUCCESS) { - errorStr = "get native info error"; return false; } processName = nativeInfo.processName; diff --git a/datamgr_service/services/distributeddataservice/service/udmf/preprocess/preprocess_utils.h b/datamgr_service/services/distributeddataservice/service/udmf/preprocess/preprocess_utils.h index 2ab12d0f2fa1afbbfd819577f9c1cab8f41f0713..175027ea86ab06855f698ca9ab1bdd1907a6e59f 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/preprocess/preprocess_utils.h +++ b/datamgr_service/services/distributeddataservice/service/udmf/preprocess/preprocess_utils.h @@ -27,16 +27,11 @@ namespace OHOS { namespace UDMF { class PreProcessUtils { public: - static PreProcessUtils &GetInstance(); - /* - * Data Imputation - */ - bool RuntimeDataImputation(UnifiedData &data, CustomOption &option); - std::string IdGenerator(); - time_t GetTimeStamp(); - bool GetHapBundleNameByToken(int tokenId, std::string &bundleName); - bool GetNativeProcessNameByToken(int tokenId, std::string &processName); - std::string errorStr; + static int32_t RuntimeDataImputation(UnifiedData &data, CustomOption &option); + static std::string IdGenerator(); + static time_t GetTimeStamp(); + static bool GetHapBundleNameByToken(int tokenId, std::string &bundleName); + static bool GetNativeProcessNameByToken(int tokenId, std::string &processName); }; } // namespace UDMF } // namespace OHOS diff --git a/datamgr_service/services/distributeddataservice/service/udmf/store/runtime_store.cpp b/datamgr_service/services/distributeddataservice/service/udmf/store/runtime_store.cpp index 3a2dc11b2f90d57265f7c817aea0fe5286222419..cb957545ce631ce8a5c81fd1a436dc9e50ce4e13 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/store/runtime_store.cpp +++ b/datamgr_service/services/distributeddataservice/service/udmf/store/runtime_store.cpp @@ -32,6 +32,7 @@ const std::string RuntimeStore::BASE_DIR = "/data/service/el1/public/database/di RuntimeStore::RuntimeStore(const std::string &storeId) : storeId_({ storeId }) { + UpdateTime(); ZLOGI("Construct runtimeStore: %{public}s.", storeId_.storeId.c_str()); } @@ -43,6 +44,7 @@ RuntimeStore::~RuntimeStore() Status RuntimeStore::Put(const UnifiedData &unifiedData) { + UpdateTime(); std::vector entries; std::string unifiedKey = unifiedData.GetRuntime()->key.GetUnifiedKey(); // add unified record @@ -77,6 +79,7 @@ Status RuntimeStore::Put(const UnifiedData &unifiedData) Status RuntimeStore::Get(const std::string &key, UnifiedData &unifiedData) { + UpdateTime(); std::vector entries; if (GetEntries(key, entries) != E_OK) { ZLOGI("GetEntries failed, dataPrefix: %{public}s.", key.c_str()); @@ -91,6 +94,7 @@ Status RuntimeStore::Get(const std::string &key, UnifiedData &unifiedData) Status RuntimeStore::GetSummary(const std::string &key, Summary &summary) { + UpdateTime(); UnifiedData unifiedData; if (Get(key, unifiedData) != E_OK) { ZLOGE("Get unified data failed."); @@ -112,6 +116,7 @@ Status RuntimeStore::GetSummary(const std::string &key, Summary &summary) Status RuntimeStore::Update(const UnifiedData &unifiedData) { + UpdateTime(); std::string key = unifiedData.GetRuntime()->key.key; if (Delete(key) != E_OK) { ZLOGE("Delete unified data failed."); @@ -126,6 +131,7 @@ Status RuntimeStore::Update(const UnifiedData &unifiedData) Status RuntimeStore::Delete(const std::string &key) { + UpdateTime(); std::vector entries; if (GetEntries(key, entries) != E_OK) { ZLOGE("GetEntries failed, dataPrefix: %{public}s.", key.c_str()); @@ -144,6 +150,7 @@ Status RuntimeStore::Delete(const std::string &key) Status RuntimeStore::DeleteBatch(const std::vector &unifiedKeys) { + UpdateTime(); ZLOGD("called!"); if (unifiedKeys.empty()) { ZLOGD("No need to delete!"); @@ -160,6 +167,7 @@ Status RuntimeStore::DeleteBatch(const std::vector &unifiedKeys) Status RuntimeStore::Sync(const std::vector &devices) { + UpdateTime(); SameProcessIpcGuard ipcGuard; DistributedKv::Status status = kvStore_->Sync(devices, SyncMode::PULL); if (status != DistributedKv::Status::SUCCESS) { @@ -171,11 +179,13 @@ Status RuntimeStore::Sync(const std::vector &devices) Status RuntimeStore::Clear() { + UpdateTime(); return Delete(DATA_PREFIX); } Status RuntimeStore::GetBatchData(const std::string &dataPrefix, std::vector &unifiedDataSet) { + UpdateTime(); std::vector entries; auto status = GetEntries(dataPrefix, entries); if (status != E_OK) { diff --git a/datamgr_service/services/distributeddataservice/service/udmf/store/store.h b/datamgr_service/services/distributeddataservice/service/udmf/store/store.h index ccd1c41bccfc977346b46d3d00c04a361eefc13e..ab5de3eb61abfb1d71994c5665e741c02390d8e9 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/store/store.h +++ b/datamgr_service/services/distributeddataservice/service/udmf/store/store.h @@ -16,7 +16,9 @@ #ifndef UDMF_STORE_H #define UDMF_STORE_H +#include #include +#include #include "error_code.h" #include "unified_data.h" @@ -27,6 +29,7 @@ namespace OHOS { namespace UDMF { class Store { public: + using Time = std::chrono::steady_clock::time_point; virtual Status Put(const UnifiedData &unifiedData) = 0; virtual Status Get(const std::string &key, UnifiedData &unifiedData) = 0; virtual Status GetSummary(const std::string &key, Summary &summary) = 0; @@ -38,6 +41,22 @@ public: virtual bool Init() = 0; virtual void Close() = 0; virtual Status GetBatchData(const std::string &dataPrefix, std::vector &unifiedDataSet) = 0; + + bool operator<(const Time &time) const + { + std::shared_lock lock(timeMutex_); + return time_ < time; + } + + void UpdateTime() + { + std::unique_lock lock(timeMutex_); + time_ = std::chrono::steady_clock::now() + std::chrono::minutes(INTERVAL); + } +private: + static constexpr int64_t INTERVAL = 1; // 1 min + mutable Time time_; + mutable std::shared_mutex timeMutex_; }; } // namespace UDMF } // namespace OHOS diff --git a/datamgr_service/services/distributeddataservice/service/udmf/store/store_cache1.cpp b/datamgr_service/services/distributeddataservice/service/udmf/store/store_cache.cpp similarity index 55% rename from datamgr_service/services/distributeddataservice/service/udmf/store/store_cache1.cpp rename to datamgr_service/services/distributeddataservice/service/udmf/store/store_cache.cpp index ce5a3da917efac9170946f633cf9dd78edb49a4a..ba0c258c922c6314264a6984ec2557ac92148472 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/store/store_cache1.cpp +++ b/datamgr_service/services/distributeddataservice/service/udmf/store/store_cache.cpp @@ -12,9 +12,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#define LOG_TAG "StoreCache1" +#define LOG_TAG "StoreCache" -#include "store_cache1.h" +#include "store_cache.h" +#include #include "log_print.h" #include "runtime_store.h" @@ -22,7 +23,9 @@ namespace OHOS { namespace UDMF { -std::shared_ptr StoreCache1::GetStore(std::string intention) +std::shared_ptr StoreCache::executorPool_ = std::make_shared(2, 1); + +std::shared_ptr StoreCache::GetStore(std::string intention) { std::shared_ptr store; stores_.Compute(intention, [&store](const auto &intention, std::shared_ptr &storePtr) -> bool { @@ -43,7 +46,31 @@ std::shared_ptr StoreCache1::GetStore(std::string intention) } return false; }); + + std::unique_lock lock(taskMutex_); + if (taskId_ == ExecutorPool::INVALID_TASK_ID) { + taskId_ = executorPool_->Schedule(std::chrono::minutes(INTERVAL), std::bind(&StoreCache::GarbageCollect, this)); + } return store; } + +void StoreCache::GarbageCollect() +{ + auto current = std::chrono::steady_clock::now(); + stores_.EraseIf([¤t](auto &key, std::shared_ptr &storePtr) { + if (*storePtr < current) { + ZLOGD("GarbageCollect, stores:%{public}s time limit, will be close.", key.c_str()); + return true; + } + return false; + }); + std::unique_lock lock(taskMutex_); + if (!stores_.Empty()) { + ZLOGE("GarbageCollect, stores size:%{public}zu", stores_.Size()); + taskId_ = executorPool_->Schedule(std::chrono::minutes(INTERVAL), std::bind(&StoreCache::GarbageCollect, this)); + } else { + taskId_ = ExecutorPool::INVALID_TASK_ID; + } +} } // namespace UDMF } // namespace OHOS \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/udmf/store/store_cache1.h b/datamgr_service/services/distributeddataservice/service/udmf/store/store_cache.h similarity index 77% rename from datamgr_service/services/distributeddataservice/service/udmf/store/store_cache1.h rename to datamgr_service/services/distributeddataservice/service/udmf/store/store_cache.h index 4d90dac34291165929919e69eab399dc88d38ea5..a66e4c658ca62febeeb8c7dbf5d27a2ec5334c82 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/store/store_cache1.h +++ b/datamgr_service/services/distributeddataservice/service/udmf/store/store_cache.h @@ -17,19 +17,28 @@ #define UDMF_STORE_CACHE_H #include +#include #include "concurrent_map.h" +#include "executor_pool.h" #include "store.h" #include "unified_meta.h" namespace OHOS { namespace UDMF { -class StoreCache1 { +class StoreCache { public: std::shared_ptr GetStore(std::string intention); private: + void GarbageCollect(); + ConcurrentMap> stores_; + std::mutex taskMutex_; + ExecutorPool::TaskId taskId_ = ExecutorPool::INVALID_TASK_ID; + + static constexpr int64_t INTERVAL = 1; // 1 min + static std::shared_ptr executorPool_; }; } // namespace UDMF } // namespace OHOS diff --git a/datamgr_service/services/distributeddataservice/service/udmf/udmf_service_stub.cpp b/datamgr_service/services/distributeddataservice/service/udmf/udmf_service_stub.cpp index febb3a3d3c026398277c3b1088ba97727dec35d8..ca92a0fbf8bbe8b00517da6dc08765ee554508c1 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/udmf_service_stub.cpp +++ b/datamgr_service/services/distributeddataservice/service/udmf/udmf_service_stub.cpp @@ -27,23 +27,8 @@ namespace OHOS { namespace UDMF { -UdmfServiceStub::UdmfServiceStub() -{ - memberFuncMap_[static_cast(SET_DATA)] = &UdmfServiceStub::OnSetData; - memberFuncMap_[static_cast(GET_DATA)] = &UdmfServiceStub::OnGetData; - memberFuncMap_[static_cast(GET_BATCH_DATA)] = &UdmfServiceStub::OnGetBatchData; - memberFuncMap_[static_cast(UPDATE_DATA)] = &UdmfServiceStub::OnUpdateData; - memberFuncMap_[static_cast(DELETE_DATA)] = &UdmfServiceStub::OnDeleteData; - memberFuncMap_[static_cast(GET_SUMMARY)] = &UdmfServiceStub::OnGetSummary; - memberFuncMap_[static_cast(ADD_PRIVILEGE)] = &UdmfServiceStub::OnAddPrivilege; - memberFuncMap_[static_cast(SYNC)] = &UdmfServiceStub::OnSync; -} - -UdmfServiceStub::~UdmfServiceStub() -{ - memberFuncMap_.clear(); -} - +constexpr UdmfServiceStub::Handler + UdmfServiceStub::HANDLERS[static_cast(UdmfServiceInterfaceCode::CODE_BUTT)]; int UdmfServiceStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply) { ZLOGI("start##code = %{public}u", code); @@ -53,18 +38,11 @@ int UdmfServiceStub::OnRemoteRequest(uint32_t code, MessageParcel &data, Message ZLOGE("end##descriptor checked fail"); return -1; } - if (CODE_HEAD > code || code >= CODE_BUTT) { + if (static_cast(UdmfServiceInterfaceCode::CODE_HEAD) > code || + code >= static_cast(UdmfServiceInterfaceCode::CODE_BUTT)) { return -1; } - auto itFunc = memberFuncMap_.find(code); - if (itFunc != memberFuncMap_.end()) { - auto memberFunc = itFunc->second; - if (memberFunc != nullptr) { - return (this->*memberFunc)(data, reply); - } - } - ZLOGI("end##ret = -1"); - return -1; + return (this->*HANDLERS[code])(data, reply); } int32_t UdmfServiceStub::OnSetData(MessageParcel &data, MessageParcel &reply) diff --git a/datamgr_service/services/distributeddataservice/service/udmf/udmf_service_stub.h b/datamgr_service/services/distributeddataservice/service/udmf/udmf_service_stub.h index 9684d2ec976b9c49cbbb6fe8f349ab2ffa5b703c..d3a739999eff4280cb5d19a98be564dab15c4aa2 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/udmf_service_stub.h +++ b/datamgr_service/services/distributeddataservice/service/udmf/udmf_service_stub.h @@ -22,6 +22,7 @@ #include "feature/feature_system.h" #include "message_parcel.h" +#include "distributeddata_udmf_ipc_interface_code.h" #include "error_code.h" #include "udmf_service.h" @@ -32,8 +33,6 @@ namespace UDMF { */ class UdmfServiceStub : public UdmfService, public DistributedData::FeatureSystem::Feature { public: - UdmfServiceStub(); - virtual ~UdmfServiceStub() override; int OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply) override; private: @@ -52,8 +51,17 @@ private: const std::string WRITE_PERMISSION = "ohos.permission.WRITE_UDMF_DATA"; const std::string SYNC_PERMISSION = "ohos.permission.SYNC_UDMF_DATA"; - using UdmfServiceFunc = int32_t (UdmfServiceStub::*)(MessageParcel &data, MessageParcel &reply); - std::map memberFuncMap_; + using Handler = int32_t (UdmfServiceStub::*)(MessageParcel &data, MessageParcel &reply); + static constexpr Handler HANDLERS[static_cast(UdmfServiceInterfaceCode::CODE_BUTT)] = { + &UdmfServiceStub::OnSetData, + &UdmfServiceStub::OnGetData, + &UdmfServiceStub::OnGetBatchData, + &UdmfServiceStub::OnUpdateData, + &UdmfServiceStub::OnDeleteData, + &UdmfServiceStub::OnGetSummary, + &UdmfServiceStub::OnAddPrivilege, + &UdmfServiceStub::OnSync + }; }; } // namespace UDMF } // namespace OHOS diff --git a/datamgr_service/services/distributeddataservice/test/fuzztest/schemaquery_fuzzer/BUILD.gn b/datamgr_service/services/distributeddataservice/test/fuzztest/schemaquery_fuzzer/BUILD.gn index d223694029b9c52221fc57e871e4275fc1a37772..2cc4e27734b93c9ab1a459852dcdae3d541667ff 100644 --- a/datamgr_service/services/distributeddataservice/test/fuzztest/schemaquery_fuzzer/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/test/fuzztest/schemaquery_fuzzer/BUILD.gn @@ -69,7 +69,7 @@ ohos_fuzztest("SchemaQueryFuzzTest") { external_deps = [ "c_utils:utils", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", "ipc:ipc_core", ] } diff --git a/datamgr_service/test/fuzztest/autolaunch_fuzzer/BUILD.gn b/datamgr_service/test/fuzztest/autolaunch_fuzzer/BUILD.gn index fb3e4402dca8637e48a9dc91c7ef701aa02b0a7a..92344ab4c02b9b97f49192a543f9048af666b183 100644 --- a/datamgr_service/test/fuzztest/autolaunch_fuzzer/BUILD.gn +++ b/datamgr_service/test/fuzztest/autolaunch_fuzzer/BUILD.gn @@ -89,7 +89,7 @@ ohos_fuzztest("AutoLaunchFuzzTest") { external_deps = [ "c_utils:utils", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", ] } diff --git a/datamgr_service/test/fuzztest/kvstoredisksize_fuzzer/BUILD.gn b/datamgr_service/test/fuzztest/kvstoredisksize_fuzzer/BUILD.gn index 9ee8840fe0628534ba4f8cfba0ad1cba72e4b125..d6de3de8e84b3ce70dae1eb3e0860047fc55e02c 100644 --- a/datamgr_service/test/fuzztest/kvstoredisksize_fuzzer/BUILD.gn +++ b/datamgr_service/test/fuzztest/kvstoredisksize_fuzzer/BUILD.gn @@ -90,7 +90,7 @@ ohos_fuzztest("KvStoreDiskSizeFuzzTest") { external_deps = [ "c_utils:utils", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", ] } diff --git a/kv_store/bundle.json b/kv_store/bundle.json index df1ee903f4cf446470c6038b069e8ba79c10f30d..63a0761f21ee296a43a153d5956db5237f2bf404 100644 --- a/kv_store/bundle.json +++ b/kv_store/bundle.json @@ -50,7 +50,6 @@ "third_party": [ "jsoncpp", "libuv", - "libz", "openssl", "sqlite", "zlib" @@ -60,23 +59,16 @@ "components": [ "ability_base", "ability_runtime", - "access_token", "bundle_framework", - "common", "common_event_service", "c_utils", - "dataclassification", - "device_auth", "device_manager", - "dsoftbus", - "hisysevent_native", - "hitrace_native", - "hiviewdfx_hilog_native", + "hilog", + "hisysevent", + "hitrace", "huks", - "init", "ipc", "napi", - "os_account", "safwk", "samgr" ] diff --git a/kv_store/frameworks/common/test/executor_pool_test.cpp b/kv_store/frameworks/common/test/executor_pool_test.cpp index 77dc4841c9b307d2c424f9ef8871c6d3a88944b0..66eccd3484286515fd89ab39e1c0b69c9e1466eb 100644 --- a/kv_store/frameworks/common/test/executor_pool_test.cpp +++ b/kv_store/frameworks/common/test/executor_pool_test.cpp @@ -89,7 +89,7 @@ HWTEST_F(ExecutorPoolTest, Schedule, TestSize.Level0) expiredTime); ASSERT_NE(taskId, ExecutorPool::INVALID_TASK_ID); std::this_thread::sleep_for(std::chrono::milliseconds(SHORT_INTERVAL * 10)); - ASSERT_EQ(testData, 10); + ASSERT_EQ(testData->data, 10); executorPool_->Remove(taskId); } @@ -114,6 +114,7 @@ HWTEST_F(ExecutorPoolTest, MultiSchedule, TestSize.Level0) } std::this_thread::sleep_for(std::chrono::milliseconds(LONG_INTERVAL * 10)); ASSERT_EQ(data->data, 100); + auto it = ids.begin(); while (it != ids.end()) { executorPool_->Remove(*it); it++; diff --git a/kv_store/frameworks/common/test/traits_test.cpp b/kv_store/frameworks/common/test/traits_test.cpp index 939fcd200325b735807065048cf8dfde57156878..c0d9844f8a92605d0713b549e063514a4ea2b808 100644 --- a/kv_store/frameworks/common/test/traits_test.cpp +++ b/kv_store/frameworks/common/test/traits_test.cpp @@ -29,8 +29,8 @@ public: class Convertible { public: // Convertible is auto convert type, do not add explicit to stop the type convert. - Convertible(const From &){}; - Convertible(){} + Convertible(const From &) {}; + Convertible() {} Convertible(Convertible &&) noexcept {}; Convertible &operator=(Convertible &&) noexcept { diff --git a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/include/distributeddata_ipc_interface_code.h b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/include/distributeddata_ipc_interface_code.h new file mode 100644 index 0000000000000000000000000000000000000000..ea279de239037b45f788b38b856c08bf34a277dd --- /dev/null +++ b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/include/distributeddata_ipc_interface_code.h @@ -0,0 +1,29 @@ +/* + * 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 DISTRIBUTEDDATA_IPC_INTERFACE_CODE_H +#define DISTRIBUTEDDATA_IPC_INTERFACE_CODE_H + +#include + +/* SAID:1301 */ +namespace OHOS::DistributedKv { +enum class KvStoreDataServiceInterfaceCode : uint32_t { + GET_FEATURE_INTERFACE = 0, + REGISTERCLIENTDEATHOBSERVER, + SERVICE_CMD_LAST +}; +} // namespace OHOS::DistributedKv +#endif // DISTRIBUTEDDATA_IPC_INTERFACE_CODE_H \ No newline at end of file diff --git a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/include/ikvstore_data_service.h b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/include/ikvstore_data_service.h index b67e248d2ec29ac689d7ebcaa2f40d46c6eb0b54..408fbc750d108c1c8bebc0c239a7da306a0603e3 100644 --- a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/include/ikvstore_data_service.h +++ b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/include/ikvstore_data_service.h @@ -16,6 +16,7 @@ #ifndef I_KV_STORE_DATA_SERVICE_H #define I_KV_STORE_DATA_SERVICE_H +#include "distributeddata_ipc_interface_code.h" #include "iremote_broker.h" #include "ikvstore_client_death_observer.h" #include "ikvstore_observer.h" @@ -27,21 +28,6 @@ namespace OHOS::DistributedKv { class IKvStoreDataService : public IRemoteBroker { public: - enum { - GET_FEATURE_INTERFACE, - REGISTERCLIENTDEATHOBSERVER, - CLOSEKVSTORE, - CLOSEALLKVSTORE, - DELETEKVSTORE, - DELETEALLKVSTORE, - GETSINGLEKVSTORE, - GETLOCALDEVICE, - GETREMOTEDEVICES, - STARTWATCHDEVICECHANGE, - STOPWATCHDEVICECHANGE, - SERVICE_CMD_LAST, - }; - DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.DistributedKv.IKvStoreDataService"); virtual sptr GetFeatureInterface(const std::string &name) = 0; @@ -55,26 +41,17 @@ protected: class KvStoreDataServiceStub : public IRemoteStub { public: int API_EXPORT OnRemoteRequest(uint32_t code, MessageParcel &data, - MessageParcel &reply, MessageOption &option) override; + MessageParcel &reply, MessageOption &option) override; private: - int32_t NoSupport(MessageParcel &data, MessageParcel &reply); int32_t GetFeatureInterfaceOnRemote(MessageParcel &data, MessageParcel &reply); int32_t RegisterClientDeathObserverOnRemote(MessageParcel &data, MessageParcel &reply); using RequestHandler = int32_t(KvStoreDataServiceStub::*)(MessageParcel&, MessageParcel&); - static constexpr RequestHandler HANDLERS[SERVICE_CMD_LAST] = { - [GET_FEATURE_INTERFACE] = &KvStoreDataServiceStub::GetFeatureInterfaceOnRemote, - [REGISTERCLIENTDEATHOBSERVER] = &KvStoreDataServiceStub::RegisterClientDeathObserverOnRemote, - [CLOSEKVSTORE] = &KvStoreDataServiceStub::NoSupport, - [CLOSEALLKVSTORE] = &KvStoreDataServiceStub::NoSupport, - [DELETEKVSTORE] = &KvStoreDataServiceStub::NoSupport, - [DELETEALLKVSTORE] = &KvStoreDataServiceStub::NoSupport, - [GETSINGLEKVSTORE] = &KvStoreDataServiceStub::NoSupport, - [GETLOCALDEVICE] = &KvStoreDataServiceStub::NoSupport, - [GETREMOTEDEVICES] = &KvStoreDataServiceStub::NoSupport, - [STARTWATCHDEVICECHANGE] = &KvStoreDataServiceStub::NoSupport, - [STOPWATCHDEVICECHANGE] = &KvStoreDataServiceStub::NoSupport, + static constexpr RequestHandler + HANDLERS[static_cast(KvStoreDataServiceInterfaceCode::SERVICE_CMD_LAST)] = { + &KvStoreDataServiceStub::GetFeatureInterfaceOnRemote, + &KvStoreDataServiceStub::RegisterClientDeathObserverOnRemote, }; }; @@ -91,4 +68,4 @@ private: }; } // namespace OHOS::DistributedKv -#endif // I_KV_STORE_DATA_SERVICE_H +#endif // I_KV_STORE_DATA_SERVICE_H \ No newline at end of file diff --git a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/src/ikvstore_data_service.cpp b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/src/ikvstore_data_service.cpp index 5e9f0ec5367efe516d0dc7875bfce70ab5996958..72130884026245faf3ee93de6ed9a7ef7b55a499 100644 --- a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/src/ikvstore_data_service.cpp +++ b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/src/ikvstore_data_service.cpp @@ -24,7 +24,8 @@ namespace OHOS { namespace DistributedKv { -constexpr KvStoreDataServiceStub::RequestHandler KvStoreDataServiceStub::HANDLERS[SERVICE_CMD_LAST]; +constexpr KvStoreDataServiceStub::RequestHandler + KvStoreDataServiceStub::HANDLERS[static_cast(KvStoreDataServiceInterfaceCode::SERVICE_CMD_LAST)]; KvStoreDataServiceProxy::KvStoreDataServiceProxy(const sptr &impl) : IRemoteProxy(impl) { @@ -47,7 +48,8 @@ sptr KvStoreDataServiceProxy::GetFeatureInterface(const std::stri MessageParcel reply; MessageOption mo { MessageOption::TF_SYNC }; - int32_t error = Remote()->SendRequest(GET_FEATURE_INTERFACE, data, reply, mo); + int32_t error = Remote()->SendRequest( + static_cast(KvStoreDataServiceInterfaceCode::GET_FEATURE_INTERFACE), data, reply, mo); if (error != 0) { ZLOGE("SendRequest returned %{public}d", error); return nullptr; @@ -83,7 +85,8 @@ Status KvStoreDataServiceProxy::RegisterClientDeathObserver(const AppId &appId, } MessageOption mo { MessageOption::TF_SYNC }; - int32_t error = Remote()->SendRequest(REGISTERCLIENTDEATHOBSERVER, data, reply, mo); + int32_t error = Remote()->SendRequest( + static_cast(KvStoreDataServiceInterfaceCode::REGISTERCLIENTDEATHOBSERVER), data, reply, mo); if (error != 0) { ZLOGW("failed during IPC. errCode %d", error); return Status::IPC_ERROR; @@ -91,13 +94,6 @@ Status KvStoreDataServiceProxy::RegisterClientDeathObserver(const AppId &appId, return static_cast(reply.ReadInt32()); } -int32_t KvStoreDataServiceStub::NoSupport(MessageParcel &data, MessageParcel &reply) -{ - (void)data; - (void)reply; - return NOT_SUPPORT; -} - int32_t KvStoreDataServiceStub::RegisterClientDeathObserverOnRemote(MessageParcel &data, MessageParcel &reply) { AppId appId = { data.ReadString() }; @@ -135,7 +131,7 @@ int32_t KvStoreDataServiceStub::OnRemoteRequest(uint32_t code, MessageParcel &da ZLOGE("local descriptor is not equal to remote"); return -1; } - if (code >= 0 && code < SERVICE_CMD_LAST) { + if (code >= 0 && code < static_cast(KvStoreDataServiceInterfaceCode::SERVICE_CMD_LAST)) { return (this->*HANDLERS[code])(data, reply); } else { MessageOption mo { MessageOption::TF_SYNC }; diff --git a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/BUILD.gn b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/BUILD.gn index 14bb5e1760afe92df312529d5c3055004b67d4d9..feca27a0b68ef90327b58598f5eac5fa9b12610d 100644 --- a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/BUILD.gn +++ b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/BUILD.gn @@ -88,10 +88,10 @@ ohos_source_set("distributeddatafwk_src_file") { ] external_deps = [ "c_utils:utils", - "hisysevent_native:libhisysevent", - "hitrace_native:hitrace_meter", - "hitrace_native:libhitracechain", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", + "hisysevent:libhisysevent", + "hitrace:hitrace_meter", + "hitrace:libhitracechain", "huks:libhukssdk", "ipc:ipc_single", "samgr:samgr_proxy", @@ -109,7 +109,7 @@ ohos_unittest("DistributedKvDataManagerTest") { external_deps = [ "c_utils:utils", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", "ipc:ipc_single", "samgr:samgr_proxy", ] @@ -129,7 +129,7 @@ ohos_unittest("DistributedKvDataManagerEncryptTest") { external_deps = [ "c_utils:utils", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", "ipc:ipc_single", "samgr:samgr_proxy", ] @@ -150,7 +150,7 @@ ohos_unittest("LocalSubscribeStoreTest") { external_deps = [ "c_utils:utils", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", "ipc:ipc_single", "samgr:samgr_proxy", ] @@ -171,7 +171,7 @@ ohos_unittest("LocalSubscribeDeviceStoreTest") { external_deps = [ "c_utils:utils", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", "ipc:ipc_single", "samgr:samgr_proxy", ] @@ -192,7 +192,7 @@ ohos_unittest("SingleKvStoreClientQueryTest") { external_deps = [ "c_utils:utils", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", "ipc:ipc_single", "samgr:samgr_proxy", ] @@ -213,7 +213,7 @@ ohos_unittest("SingleKvStoreClientTest") { external_deps = [ "c_utils:utils", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", "ipc:ipc_single", "samgr:samgr_proxy", ] @@ -234,7 +234,7 @@ ohos_unittest("DeviceKvStoreTest") { external_deps = [ "c_utils:utils", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", "ipc:ipc_single", "samgr:samgr_proxy", ] diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/include/distributeddata_kvdb_ipc_interface_code.h b/kv_store/frameworks/innerkitsimpl/kvdb/include/distributeddata_kvdb_ipc_interface_code.h new file mode 100644 index 0000000000000000000000000000000000000000..0b071cf22d3440ae739bf2e290f2eec637669912 --- /dev/null +++ b/kv_store/frameworks/innerkitsimpl/kvdb/include/distributeddata_kvdb_ipc_interface_code.h @@ -0,0 +1,45 @@ +/* + * 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 DISTRIBUTEDDATA_KVDB_IPC_INTERFACE_CODE_H +#define DISTRIBUTEDDATA_KVDB_IPC_INTERFACE_CODE_H + +#include + +/* SAID:1301 FeatureSystem:kvdb_service */ +namespace OHOS::DistributedKv { +enum class KVDBServiceInterfaceCode : uint32_t { + TRANS_HEAD = 0, + TRANS_GET_STORE_IDS = TRANS_HEAD, + TRANS_BEFORE_CREATE, + TRANS_AFTER_CREATE, + TRANS_DELETE, + TRANS_SYNC, + TRANS_REGISTER_CALLBACK, + TRANS_UNREGISTER_CALLBACK, + TRANS_SET_SYNC_PARAM, + TRANS_GET_SYNC_PARAM, + TRANS_ENABLE_CAP, + TRANS_DISABLE_CAP, + TRANS_SET_CAP, + TRANS_ADD_SUB, + TRANS_RMV_SUB, + TRANS_SUB, + TRANS_UNSUB, + TRANS_GET_PASSWORD, + TRANS_BUTT +}; +} // namespace OHOS::DistributedKv +#endif // DISTRIBUTEDDATA_KVDB_IPC_INTERFACE_CODE_H \ No newline at end of file diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/include/kvdb_service.h b/kv_store/frameworks/innerkitsimpl/kvdb/include/kvdb_service.h index c343d06abefc3d02485e90a7f1d801d60b8ff5df..c536a468e861be6447cb3ff4403a6011629784e5 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/include/kvdb_service.h +++ b/kv_store/frameworks/innerkitsimpl/kvdb/include/kvdb_service.h @@ -63,29 +63,6 @@ public: virtual Status Unsubscribe(const AppId &appId, const StoreId &storeId, sptr observer) = 0; virtual Status GetBackupPassword( const AppId &appId, const StoreId &storeId, std::vector &password) = 0; - -protected: - enum TransId : int32_t { - TRANS_HEAD, - TRANS_GET_STORE_IDS = TRANS_HEAD, - TRANS_BEFORE_CREATE, - TRANS_AFTER_CREATE, - TRANS_DELETE, - TRANS_SYNC, - TRANS_REGISTER_CALLBACK, - TRANS_UNREGISTER_CALLBACK, - TRANS_SET_SYNC_PARAM, - TRANS_GET_SYNC_PARAM, - TRANS_ENABLE_CAP, - TRANS_DISABLE_CAP, - TRANS_SET_CAP, - TRANS_ADD_SUB, - TRANS_RMV_SUB, - TRANS_SUB, - TRANS_UNSUB, - TRANS_GET_PASSWORD, - TRANS_BUTT, - }; }; } // namespace OHOS::DistributedKv #endif // OHOS_DISTRIBUTED_DATA_FRAMEWORKS_KVDB_SERVICE_H diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/src/kvdb_service_client.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/src/kvdb_service_client.cpp index 765dbac3470632b3e9b91f7f4d06e416fbb27e9f..37e468eafceab5eb1cfb204966750fd661f1ddae 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/src/kvdb_service_client.cpp +++ b/kv_store/frameworks/innerkitsimpl/kvdb/src/kvdb_service_client.cpp @@ -15,6 +15,7 @@ #define LOG_TAG "KVDBServiceClient" #include "kvdb_service_client.h" #include +#include "distributeddata_kvdb_ipc_interface_code.h" #include "itypes_util.h" #include "kvstore_observer_client.h" #include "kvstore_service_death_notifier.h" @@ -105,7 +106,8 @@ KVDBServiceClient::KVDBServiceClient(const sptr &handle) : IRemot Status KVDBServiceClient::GetStoreIds(const AppId &appId, std::vector &storeIds) { MessageParcel reply; - int32_t status = IPC_SEND(TRANS_GET_STORE_IDS, reply, appId, StoreId(), storeIds); + int32_t status = IPC_SEND(static_cast(KVDBServiceInterfaceCode::TRANS_GET_STORE_IDS), + reply, appId, StoreId(), storeIds); if (status != SUCCESS) { ZLOGE("status:0x%{public}x, appId:%{public}s", status, appId.appId.c_str()); } @@ -116,7 +118,8 @@ Status KVDBServiceClient::GetStoreIds(const AppId &appId, std::vector & Status KVDBServiceClient::BeforeCreate(const AppId &appId, const StoreId &storeId, const Options &options) { MessageParcel reply; - int32_t status = IPC_SEND(TRANS_BEFORE_CREATE, reply, appId, storeId, options); + int32_t status = IPC_SEND(static_cast(KVDBServiceInterfaceCode::TRANS_BEFORE_CREATE), + reply, appId, storeId, options); if (status != SUCCESS) { ZLOGE("status:0x%{public}x appId:%{public}s, storeId:%{public}s", status, appId.appId.c_str(), StoreUtil::Anonymous(storeId.storeId).c_str()); @@ -128,7 +131,8 @@ Status KVDBServiceClient::AfterCreate( const AppId &appId, const StoreId &storeId, const Options &options, const std::vector &password) { MessageParcel reply; - int32_t status = IPC_SEND(TRANS_AFTER_CREATE, reply, appId, storeId, options, password); + int32_t status = IPC_SEND(static_cast(KVDBServiceInterfaceCode::TRANS_AFTER_CREATE), + reply, appId, storeId, options, password); if (status != SUCCESS) { ZLOGE("status:0x%{public}x appId:%{public}s, storeId:%{public}s, encrypt:%{public}d", status, appId.appId.c_str(), StoreUtil::Anonymous(storeId.storeId).c_str(), options.encrypt); @@ -139,7 +143,8 @@ Status KVDBServiceClient::AfterCreate( Status KVDBServiceClient::Delete(const AppId &appId, const StoreId &storeId) { MessageParcel reply; - int32_t status = IPC_SEND(TRANS_DELETE, reply, appId, storeId); + int32_t status = IPC_SEND(static_cast(KVDBServiceInterfaceCode::TRANS_DELETE), + reply, appId, storeId); if (status != SUCCESS) { ZLOGE("status:0x%{public}x appId:%{public}s, storeId:%{public}s", status, appId.appId.c_str(), StoreUtil::Anonymous(storeId.storeId).c_str()); @@ -150,8 +155,8 @@ Status KVDBServiceClient::Delete(const AppId &appId, const StoreId &storeId) Status KVDBServiceClient::Sync(const AppId &appId, const StoreId &storeId, const SyncInfo &syncInfo) { MessageParcel reply; - int32_t status = IPC_SEND(TRANS_SYNC, reply, appId, storeId, syncInfo.seqId, syncInfo.mode, syncInfo.devices, - syncInfo.delay, syncInfo.query); + int32_t status = IPC_SEND(static_cast(KVDBServiceInterfaceCode::TRANS_SYNC), reply, appId, storeId, + syncInfo.seqId, syncInfo.mode, syncInfo.devices, syncInfo.delay, syncInfo.query); if (status != SUCCESS) { ZLOGE("status:0x%{public}x, appId:%{public}s, storeId:%{public}s, sequenceId:%{public}" PRIu64, status, appId.appId.c_str(), StoreUtil::Anonymous(storeId.storeId).c_str(), syncInfo.seqId); @@ -162,7 +167,8 @@ Status KVDBServiceClient::Sync(const AppId &appId, const StoreId &storeId, const Status KVDBServiceClient::RegisterSyncCallback(const AppId &appId, sptr callback) { MessageParcel reply; - int32_t status = IPC_SEND(TRANS_REGISTER_CALLBACK, reply, appId, StoreId(), callback->AsObject().GetRefPtr()); + int32_t status = IPC_SEND(static_cast(KVDBServiceInterfaceCode::TRANS_REGISTER_CALLBACK), reply, + appId, StoreId(), callback->AsObject().GetRefPtr()); if (status != SUCCESS) { ZLOGE("status:0x%{public}x, appId:%{public}s, callback:0x%{public}x", status, appId.appId.c_str(), StoreUtil::Anonymous(callback.GetRefPtr())); @@ -173,7 +179,8 @@ Status KVDBServiceClient::RegisterSyncCallback(const AppId &appId, sptr(KVDBServiceInterfaceCode::TRANS_UNREGISTER_CALLBACK), + reply, appId, StoreId()); if (status != SUCCESS) { ZLOGE("status:0x%{public}x, appId:%{public}s", status, appId.appId.c_str()); } @@ -183,7 +190,8 @@ Status KVDBServiceClient::UnregisterSyncCallback(const AppId &appId) Status KVDBServiceClient::SetSyncParam(const AppId &appId, const StoreId &storeId, const KvSyncParam &syncParam) { MessageParcel reply; - int32_t status = IPC_SEND(TRANS_SET_SYNC_PARAM, reply, appId, storeId, syncParam.allowedDelayMs); + int32_t status = IPC_SEND(static_cast(KVDBServiceInterfaceCode::TRANS_SET_SYNC_PARAM), reply, + appId, storeId, syncParam.allowedDelayMs); if (status != SUCCESS) { ZLOGE("status:0x%{public}x, appId:%{public}s, storeId:%{public}s", status, appId.appId.c_str(), StoreUtil::Anonymous(storeId.storeId).c_str()); @@ -194,7 +202,8 @@ Status KVDBServiceClient::SetSyncParam(const AppId &appId, const StoreId &storeI Status KVDBServiceClient::GetSyncParam(const AppId &appId, const StoreId &storeId, KvSyncParam &syncParam) { MessageParcel reply; - int32_t status = IPC_SEND(TRANS_GET_SYNC_PARAM, reply, appId, storeId); + int32_t status = IPC_SEND(static_cast(KVDBServiceInterfaceCode::TRANS_GET_SYNC_PARAM), + reply, appId, storeId); if (status != SUCCESS) { ZLOGE("status:0x%{public}x, appId:%{public}s, storeId:%{public}s", status, appId.appId.c_str(), StoreUtil::Anonymous(storeId.storeId).c_str()); @@ -207,7 +216,8 @@ Status KVDBServiceClient::GetSyncParam(const AppId &appId, const StoreId &storeI Status KVDBServiceClient::EnableCapability(const AppId &appId, const StoreId &storeId) { MessageParcel reply; - int32_t status = IPC_SEND(TRANS_ENABLE_CAP, reply, appId, storeId); + int32_t status = IPC_SEND(static_cast(KVDBServiceInterfaceCode::TRANS_ENABLE_CAP), + reply, appId, storeId); if (status != SUCCESS) { ZLOGE("status:0x%{public}x, appId:%{public}s, storeId:%{public}s", status, appId.appId.c_str(), StoreUtil::Anonymous(storeId.storeId).c_str()); @@ -218,7 +228,8 @@ Status KVDBServiceClient::EnableCapability(const AppId &appId, const StoreId &st Status KVDBServiceClient::DisableCapability(const AppId &appId, const StoreId &storeId) { MessageParcel reply; - int32_t status = IPC_SEND(TRANS_DISABLE_CAP, reply, appId, storeId); + int32_t status = IPC_SEND(static_cast(KVDBServiceInterfaceCode::TRANS_DISABLE_CAP), + reply, appId, storeId); if (status != SUCCESS) { ZLOGE("status:0x%{public}x, appId:%{public}s, storeId:%{public}s", status, appId.appId.c_str(), StoreUtil::Anonymous(storeId.storeId).c_str()); @@ -230,7 +241,8 @@ Status KVDBServiceClient::SetCapability(const AppId &appId, const StoreId &store const std::vector &local, const std::vector &remote) { MessageParcel reply; - int32_t status = IPC_SEND(TRANS_SET_CAP, reply, appId, storeId, local, remote); + int32_t status = IPC_SEND(static_cast(KVDBServiceInterfaceCode::TRANS_SET_CAP), + reply, appId, storeId, local, remote); if (status != SUCCESS) { ZLOGE("status:0x%{public}x, appId:%{public}s, storeId:%{public}s", status, appId.appId.c_str(), StoreUtil::Anonymous(storeId.storeId).c_str()); @@ -241,7 +253,8 @@ Status KVDBServiceClient::SetCapability(const AppId &appId, const StoreId &store Status KVDBServiceClient::AddSubscribeInfo(const AppId &appId, const StoreId &storeId, const SyncInfo &syncInfo) { MessageParcel reply; - int32_t status = IPC_SEND(TRANS_ADD_SUB, reply, appId, storeId, syncInfo.seqId, syncInfo.devices, syncInfo.query); + int32_t status = IPC_SEND(static_cast(KVDBServiceInterfaceCode::TRANS_ADD_SUB), + reply, appId, storeId, syncInfo.seqId, syncInfo.devices, syncInfo.query); if (status != SUCCESS) { ZLOGE("status:0x%{public}x, appId:%{public}s, storeId:%{public}s, query:%{public}s", status, appId.appId.c_str(), StoreUtil::Anonymous(storeId.storeId).c_str(), @@ -253,7 +266,8 @@ Status KVDBServiceClient::AddSubscribeInfo(const AppId &appId, const StoreId &st Status KVDBServiceClient::RmvSubscribeInfo(const AppId &appId, const StoreId &storeId, const SyncInfo &syncInfo) { MessageParcel reply; - int32_t status = IPC_SEND(TRANS_RMV_SUB, reply, appId, storeId, syncInfo.seqId, syncInfo.devices, syncInfo.query); + int32_t status = IPC_SEND(static_cast(KVDBServiceInterfaceCode::TRANS_RMV_SUB), + reply, appId, storeId, syncInfo.seqId, syncInfo.devices, syncInfo.query); if (status != SUCCESS) { ZLOGE("status:0x%{public}x, appId:%{public}s, storeId:%{public}s, query:%{public}s", status, appId.appId.c_str(), StoreUtil::Anonymous(storeId.storeId).c_str(), @@ -265,7 +279,8 @@ Status KVDBServiceClient::RmvSubscribeInfo(const AppId &appId, const StoreId &st Status KVDBServiceClient::Subscribe(const AppId &appId, const StoreId &storeId, sptr observer) { MessageParcel reply; - int32_t status = IPC_SEND(TRANS_SUB, reply, appId, storeId, observer->AsObject()); + int32_t status = IPC_SEND(static_cast(KVDBServiceInterfaceCode::TRANS_SUB), + reply, appId, storeId, observer->AsObject()); if (status != SUCCESS) { ZLOGE("status:0x%{public}x, appId:%{public}s, storeId:%{public}s, observer:0x%{public}x", status, appId.appId.c_str(), StoreUtil::Anonymous(storeId.storeId).c_str(), @@ -277,7 +292,8 @@ Status KVDBServiceClient::Subscribe(const AppId &appId, const StoreId &storeId, Status KVDBServiceClient::Unsubscribe(const AppId &appId, const StoreId &storeId, sptr observer) { MessageParcel reply; - int32_t status = IPC_SEND(TRANS_UNSUB, reply, appId, storeId, observer->AsObject().GetRefPtr()); + int32_t status = IPC_SEND(static_cast(KVDBServiceInterfaceCode::TRANS_UNSUB), + reply, appId, storeId, observer->AsObject().GetRefPtr()); if (status != SUCCESS) { ZLOGE("status:0x%{public}x, appId:%{public}s, storeId:%{public}s, observer:0x%{public}x", status, appId.appId.c_str(), StoreUtil::Anonymous(storeId.storeId).c_str(), @@ -290,7 +306,8 @@ Status KVDBServiceClient::GetBackupPassword( const AppId &appId, const StoreId &storeId, std::vector &password) { MessageParcel reply; - int32_t status = IPC_SEND(TRANS_GET_PASSWORD, reply, appId, storeId); + int32_t status = IPC_SEND(static_cast(KVDBServiceInterfaceCode::TRANS_GET_PASSWORD), + reply, appId, storeId); if (status != SUCCESS) { ZLOGE("status:0x%{public}x appId:%{public}s, storeId:%{public}s", status, appId.appId.c_str(), StoreUtil::Anonymous(storeId.storeId).c_str()); diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/src/store_factory.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/src/store_factory.cpp index fda4ce8611bbdece689c93b01e9707443ab7b43f..394b27a4ddd1334d8e80b5dd3241183d5a675e14 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/src/store_factory.cpp +++ b/kv_store/frameworks/innerkitsimpl/kvdb/src/store_factory.cpp @@ -40,6 +40,9 @@ StoreFactory::StoreFactory() convertors_[SINGLE_VERSION] = new Convertor(); convertors_[MULTI_VERSION] = new Convertor(); DistributedDB::RuntimeConfig::SetThreadPool(std::make_shared()); + DistributedDB::RuntimeConfig::SetSyncActivationCheckCallback([](const ActivationCheckParam ¶m) -> bool { + return false; + }); if (DBManager::IsProcessSystemApiAdapterValid()) { return; } diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/test/BUILD.gn b/kv_store/frameworks/innerkitsimpl/kvdb/test/BUILD.gn index dfe1a37574a64b971ecc0364a5ced325e630eed5..c5a7c29d58f9709f5783d221fdf1fa7cfa01a428 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/test/BUILD.gn +++ b/kv_store/frameworks/innerkitsimpl/kvdb/test/BUILD.gn @@ -91,10 +91,10 @@ ohos_source_set("kvdb_src_file") { ] external_deps = [ "c_utils:utils", - "hisysevent_native:libhisysevent", - "hitrace_native:hitrace_meter", - "hitrace_native:libhitracechain", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", + "hisysevent:libhisysevent", + "hitrace:hitrace_meter", + "hitrace:libhitracechain", "huks:libhukssdk", "ipc:ipc_single", "samgr:samgr_proxy", @@ -112,7 +112,7 @@ ohos_unittest("SingleStoreImplTest") { external_deps = [ "c_utils:utils", - "hilog_native:libhilog", + "hilog:libhilog", "ipc:ipc_single", "safwk:system_ability_fwk", "samgr:samgr_proxy", @@ -179,7 +179,7 @@ ohos_unittest("AutoSyncTimerTest") { external_deps = [ "c_utils:utils", - "hilog_native:libhilog", + "hilog:libhilog", "ipc:ipc_single", "safwk:system_ability_fwk", "samgr:samgr_proxy", @@ -202,7 +202,7 @@ ohos_unittest("DevManagerTest") { external_deps = [ "c_utils:utils", - "hilog_native:libhilog", + "hilog:libhilog", "ipc:ipc_single", "safwk:system_ability_fwk", "samgr:samgr_proxy", @@ -225,7 +225,7 @@ ohos_unittest("SingleStoreImplGetTopTest") { external_deps = [ "c_utils:utils", - "hilog_native:libhilog", + "hilog:libhilog", "ipc:ipc_single", "safwk:system_ability_fwk", "samgr:samgr_proxy", @@ -248,7 +248,7 @@ ohos_unittest("StoreFactoryTest") { external_deps = [ "c_utils:utils", - "hilog_native:libhilog", + "hilog:libhilog", "ipc:ipc_single", "safwk:system_ability_fwk", "samgr:samgr_proxy", diff --git a/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_single_kv_store.cpp b/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_single_kv_store.cpp index 444f9947a44b825d05226a76e88c5a9972f4c175..9cd6bc9c222d6a66d30adf935f616df3a78e443b 100644 --- a/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_single_kv_store.cpp +++ b/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_single_kv_store.cpp @@ -397,7 +397,6 @@ napi_value JsSingleKVStore::StartTransaction(napi_env env, napi_callback_info in { auto ctxt = std::make_shared(); ctxt->GetCbInfo(env, info); - auto execute = [ctxt]() { auto& kvStore = reinterpret_cast(ctxt->native)->kvStore_; Status status = kvStore->StartTransaction(); diff --git a/kv_store/frameworks/libs/distributeddb/BUILD.gn b/kv_store/frameworks/libs/distributeddb/BUILD.gn index 92460ee4ba187f8c4ea6ea8b65bb3552ffadd952..ae33396bb80b78e80f79ac6c125cacd2bb13e110 100644 --- a/kv_store/frameworks/libs/distributeddb/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/BUILD.gn @@ -56,6 +56,7 @@ config("distrdb_config") { "USE_DFX_ABILITY", "SQLITE_ENABLE_DROPTABLE_CALLBACK", "OPENSSL_SUPPRESS_DEPRECATED", + "MAX_UPLOAD_COUNT=30", ] if (is_debug) { defines += [ "TRACE_SQLITE_EXECUTE" ] @@ -96,9 +97,9 @@ ohos_shared_library("distributeddb") { external_deps = [ "c_utils:utils", - "hisysevent_native:libhisysevent", - "hitrace_native:hitrace_meter", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", + "hisysevent:libhisysevent", + "hitrace:hitrace_meter", ] subsystem_name = "distributeddatamgr" diff --git a/kv_store/frameworks/libs/distributeddb/common/include/cloud/cloud_db_constant.h b/kv_store/frameworks/libs/distributeddb/common/include/cloud/cloud_db_constant.h index 902aaf18c1d1340d05fa5e610f2c60c86f5ee5cb..af35f7a4a82d86881f45867e043560fa043aad47 100644 --- a/kv_store/frameworks/libs/distributeddb/common/include/cloud/cloud_db_constant.h +++ b/kv_store/frameworks/libs/distributeddb/common/include/cloud/cloud_db_constant.h @@ -30,7 +30,6 @@ public: static constexpr const char *CURSOR_FIELD = "#_cursor"; static constexpr const char *ROW_ID_FIELD_NAME = "rowid"; static constexpr uint32_t MAX_UPLOAD_SIZE = 1024 * 512 * 3; // 1.5M - static constexpr uint32_t MAX_DOWNLOAD_RETRY_TIME = 50; // cloud data timestamp is utc ms precision // used for 100ns to ms when handle cloud data timestamp static constexpr uint32_t TEN_THOUSAND = 10000; diff --git a/kv_store/frameworks/libs/distributeddb/common/include/db_errno.h b/kv_store/frameworks/libs/distributeddb/common/include/db_errno.h index bf4f441c6de456e8634a18c90de0245ffad82dd3..8a34bde842bf0b2102e71115e61cd26c8428d2ce 100644 --- a/kv_store/frameworks/libs/distributeddb/common/include/db_errno.h +++ b/kv_store/frameworks/libs/distributeddb/common/include/db_errno.h @@ -129,6 +129,11 @@ constexpr int E_CONSTRAINT = (E_BASE + 107); // sql failed with constraint constexpr int E_CLOUD_ERROR = (E_BASE + 108); // cloud error constexpr int E_QUERY_END = (E_BASE + 110); // Indicates that query function has queried last data from cloud constexpr int E_DB_CLOSED = (E_BASE + 111); // db is closed +constexpr int E_NOT_SET = (E_BASE + 112); // asset loader is not set +constexpr int E_CLOUD_NETWORK_ERROR = (E_BASE + 113); // network error in cloud +constexpr int E_CLOUD_SYNC_UNSET = (E_BASE + 114); // not set sync option in cloud +constexpr int E_CLOUD_FULL_RECORDS = (E_BASE + 115); // cloud's record is full +constexpr int E_CLOUD_LOCK_ERROR = (E_BASE + 116); // cloud failed to get sync lock // Num 150+ is reserved for schema related errno, since it may be added regularly constexpr int E_JSON_PARSE_FAIL = (E_BASE + 150); // Parse json fail in grammatical level constexpr int E_JSON_INSERT_PATH_EXIST = (E_BASE + 151); // Path already exist before insert diff --git a/kv_store/frameworks/libs/distributeddb/communicator/src/communicator_aggregator.cpp b/kv_store/frameworks/libs/distributeddb/communicator/src/communicator_aggregator.cpp index b8c738eb7a62f7d71c5d213ed98e0ebb531e115c..0fe52b83fc47e6871813e67c0f4c54ed0acdbf70 100644 --- a/kv_store/frameworks/libs/distributeddb/communicator/src/communicator_aggregator.cpp +++ b/kv_store/frameworks/libs/distributeddb/communicator/src/communicator_aggregator.cpp @@ -401,6 +401,8 @@ void CommunicatorAggregator::SendPacketsAndDisposeTask(const SendTask &inTask, u } if (taskNeedFinalize) { TaskFinalizer(inTask, errCode); + std::lock_guard autoLock(sendRecordMutex_); + sendRecord_.erase(inTask.frameId); } } diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/include/relational/relational_store_manager.h b/kv_store/frameworks/libs/distributeddb/interfaces/include/relational/relational_store_manager.h index a43031514012647c97775e39a9c1fb1fd36fdadd..4e683a7720dac2c490782fd70c337ba560acc5e6 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/include/relational/relational_store_manager.h +++ b/kv_store/frameworks/libs/distributeddb/interfaces/include/relational/relational_store_manager.h @@ -29,6 +29,10 @@ public: // Only calculate the table name with device hash, no guarantee for the table exists DB_API static std::string GetDistributedTableName(const std::string &device, const std::string &tableName); + DB_API static std::string GetDistributedLogTableName(const std::string &tableName); + // key:colName value:real value + DB_API static std::vector CalcPrimaryKeyHash(const std::map primaryKey); + DB_API RelationalStoreManager(const std::string &appId, const std::string &userId, int32_t instanceId = 0); DB_API ~RelationalStoreManager() = default; diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/include/store_types.h b/kv_store/frameworks/libs/distributeddb/interfaces/include/store_types.h index 77d8fdd6c15d4467d0b397bf414fe8f0be2a887e..6ab481aad1e004ae4370acd6b05d4fc3004100a1 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/include/store_types.h +++ b/kv_store/frameworks/libs/distributeddb/interfaces/include/store_types.h @@ -71,6 +71,11 @@ enum DBStatus { CLOUD_ERROR, // cloud error QUERY_END, // Indicates that query function has queried last data from cloud DB_CLOSED, // db is closed + UNSET_ERROR, // something should be set not be set + CLOUD_NETWORK_ERROR, // network error in cloud + CLOUD_SYNC_UNSET, // not set sync option in cloud + CLOUD_FULL_RECORDS, // cloud's record is full + CLOUD_LOCK_ERROR, // cloud failed to get sync lock }; struct KvStoreConfig { diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_errno.cpp b/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_errno.cpp index 35fa55e2e475039fa9d3cc20839065649cea7665..cb217cade5cd6fa210979153c204f70372bf3c0a 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_errno.cpp +++ b/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_errno.cpp @@ -69,6 +69,11 @@ namespace { { -E_CONSTRAINT, CONSTRAINT }, { -E_CLOUD_ERROR, CLOUD_ERROR }, { -E_DB_CLOSED, DB_CLOSED }, + { -E_NOT_SET, UNSET_ERROR }, + { -E_CLOUD_NETWORK_ERROR, CLOUD_NETWORK_ERROR }, + { -E_CLOUD_SYNC_UNSET, CLOUD_SYNC_UNSET }, + { -E_CLOUD_FULL_RECORDS, CLOUD_FULL_RECORDS }, + { -E_CLOUD_LOCK_ERROR, CLOUD_LOCK_ERROR }, }; } diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_delegate_impl.cpp b/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_delegate_impl.cpp index 03805dfc37c03f0aee1df38fd6dccb957416e091..f7bac8f59cba6ac29ef6cf04fb35c45e57a9fe6f 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_delegate_impl.cpp +++ b/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_delegate_impl.cpp @@ -43,7 +43,6 @@ RelationalStoreDelegateImpl::~RelationalStoreDelegateImpl() DBStatus RelationalStoreDelegateImpl::RemoveDeviceDataInner(const std::string &device, ClearMode mode) { -#ifdef MANNUAL_SYNC_AND_CLEAN_CLOUD_DATA if (mode >= BUTT) { LOGE("Invalid mode for Remove device data, %d.", INVALID_ARGS); return INVALID_ARGS; @@ -61,7 +60,6 @@ DBStatus RelationalStoreDelegateImpl::RemoveDeviceDataInner(const std::string &d } return OK; } -#endif // MANNUAL_SYNC_AND_CLEAN_CLOUD_DATA return RemoveDeviceData(device, ""); } diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_manager.cpp b/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_manager.cpp index aed8a2a96695e0cc62e2198cab50bb2becc0ca72..7f27c6baf518326fbf1a0b816a40ddf7d26b757d 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_manager.cpp +++ b/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_manager.cpp @@ -19,6 +19,7 @@ #include "auto_launch.h" #include "cloud/cloud_db_constant.h" +#include "cloud/cloud_storage_utils.h" #include "relational_store_instance.h" #include "db_common.h" #include "db_dfx_adapter.h" @@ -141,6 +142,50 @@ std::string RelationalStoreManager::GetDistributedTableName(const std::string &d return DBCommon::GetDistributedTableName(device, tableName); } +DB_API std::string RelationalStoreManager::GetDistributedLogTableName(const std::string &tableName) +{ + return DBCommon::GetLogTableName(tableName); +} + +DB_API std::vector RelationalStoreManager::CalcPrimaryKeyHash(const std::map primaryKey) +{ + std::vector result; + if (primaryKey.empty()) { + LOGW("primaryKey is empty"); + return result; + } + int errCode = E_OK; + if (primaryKey.size() == 1) { + auto iter = primaryKey.begin(); + Field field = { iter->first, static_cast(iter->second.index()), true, false}; + errCode = CloudStorageUtils::CalculateHashKeyForOneField(field, primaryKey, false, result); + if (errCode != E_OK) { + // never happen + LOGE("calc hash fail when there is one primary key errCode = %d", errCode); + return result; + } + } else { + std::vector tempRes; + for (const auto &item: primaryKey) { + std::vector temp; + Field field = { item.first, static_cast(item.second.index()), true, false}; + errCode = CloudStorageUtils::CalculateHashKeyForOneField(field, primaryKey, false, temp); + if (errCode != E_OK) { + // never happen + LOGE("calc hash fail when there is more than one primary key errCode = %d", errCode); + return result; + } + tempRes.insert(tempRes.end(), temp.begin(), temp.end()); + } + errCode = DBCommon::CalcValueHash(tempRes, result); + if (errCode != E_OK) { + LOGE("calc hash fail when calc the composite primary key errCode = %d", errCode); + return result; + } + } + return result; +} + void RelationalStoreManager::SetAutoLaunchRequestCallback(const AutoLaunchRequestCallback &callback) { RuntimeContext::GetInstance()->SetAutoLaunchRequestCallback(callback, DBTypeInner::DB_RELATION); diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_sync_able_storage.h b/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_sync_able_storage.h index 387e8c327e4f2adc0b6a9e81330a217edede52b3..b6ce9ac8faabd1b3481a8bf673868cf488b4e641 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_sync_able_storage.h +++ b/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_sync_able_storage.h @@ -162,7 +162,7 @@ public: int FillCloudAssetForDownload(const std::string &tableName, VBucket &asset, bool isFullReplace) override; - int FillCloudAssetForUpload(const CloudSyncData &data) override; + int FillCloudGidAndAsset(const OpType &opType, const CloudSyncData &data) override; void SetSyncAbleEngine(std::shared_ptr syncAbleEngine); diff --git a/kv_store/frameworks/libs/distributeddb/storage/include/cloud/cloud_storage_utils.h b/kv_store/frameworks/libs/distributeddb/storage/include/cloud/cloud_storage_utils.h index 1fc38c1b49c1ecf1d3dbe17e2948dc80090e25a9..539a139b0ce51ebcced13dab030718d41638c0ed 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/include/cloud/cloud_storage_utils.h +++ b/kv_store/frameworks/libs/distributeddb/storage/include/cloud/cloud_storage_utils.h @@ -54,11 +54,16 @@ public: static void FillAssetsForDownload(Assets &assets); static int FillAssetForUpload(Asset &asset); static void FillAssetsForUpload(Assets &assets); - static void FillAssetFromVBucketBeforeDownload(VBucket &vBucket); - static void FillAssetFromVBucketDownloadFinish(VBucket &vBucket); - static void FillAssetFromVBucketAfterUpload(VBucket &vBucket); + static void PrepareToFillAssetFromVBucket(VBucket &vBucket); + static void FillAssetFromVBucketFinish(VBucket &vBucket, std::function fillAsset, + std::function fillAssets); static bool IsAsset(const Type &type); static bool IsAssets(const Type &type); + static bool IsAssetsContainDuplicateAsset(Assets &assets); + static void EraseNoChangeAsset(std::map &assetsMap); + static void MergeDownloadAsset(std::map &downloadAssets, + std::map &mergeAssets); + static std::map GenAssetsIndexMap(Assets &assets); template static int GetValueFromOneField(Type &cloudValue, T &outVal) @@ -93,6 +98,9 @@ public: outVal = *value; return E_OK; } + + static int CalculateHashKeyForOneField(const Field &field, const VBucket &vBucket, bool allowEmpty, + std::vector &hashValue); }; } #endif // CLOUD_STORAGE_UTILS_H diff --git a/kv_store/frameworks/libs/distributeddb/storage/include/icloud_sync_storage_interface.h b/kv_store/frameworks/libs/distributeddb/storage/include/icloud_sync_storage_interface.h index e7cc3b4367105bc52a68b17c75d611ee776c805c..da18258b9021f9abbe738f179c127d5dee3af014 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/include/icloud_sync_storage_interface.h +++ b/kv_store/frameworks/libs/distributeddb/storage/include/icloud_sync_storage_interface.h @@ -31,6 +31,8 @@ enum class OpType : uint8_t { // used in Cloud Force Push strategy, when SET_CLOUD_FORCE_PUSH_FLAG_ONE, upload process won't process this record SET_CLOUD_FORCE_PUSH_FLAG_ONE, SET_CLOUD_FORCE_PUSH_FLAG_ZERO, + UPDATE_TIMESTAMP, + CLEAR_GID, NOT_HANDLE }; @@ -87,7 +89,7 @@ public: virtual int FillCloudAssetForDownload(const std::string &tableName, VBucket &asset, bool isFullReplace) = 0; - virtual int FillCloudAssetForUpload(const CloudSyncData &data) = 0; + virtual int FillCloudGidAndAsset(const OpType &opType, const CloudSyncData &data) = 0; }; } diff --git a/kv_store/frameworks/libs/distributeddb/storage/include/isync_interface.h b/kv_store/frameworks/libs/distributeddb/storage/include/isync_interface.h index 893305b188d1331d9c7836318cb8df76e55031a8..9bf95083e9c101c54d3c95d4480eef19f1dc4d6a 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/include/isync_interface.h +++ b/kv_store/frameworks/libs/distributeddb/storage/include/isync_interface.h @@ -69,6 +69,8 @@ public: virtual const DBProperties &GetDbProperties() const = 0; virtual int GetSecurityOption(SecurityOption &option) const = 0; + + virtual int IsSupportSubscribe() const = 0; }; } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/storage/include/storage_proxy.h b/kv_store/frameworks/libs/distributeddb/storage/include/storage_proxy.h index b87bf3ee8958a002ec0d2d1e9982a99dc59f1010..f82fb91b5d16fe257b7d4f9d72cc1b4a07d8f33e 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/include/storage_proxy.h +++ b/kv_store/frameworks/libs/distributeddb/storage/include/storage_proxy.h @@ -43,7 +43,7 @@ public: int GetCloudWaterMark(const std::string &tableName, CloudWaterMark &cloudMark); - int PutCloudWaterMark(const std::string &tableName, CloudWaterMark &cloudMark); + int SetCloudWaterMark(const std::string &tableName, CloudWaterMark &cloudMark); int StartTransaction(TransactType type = TransactType::DEFERRED); @@ -81,7 +81,7 @@ public: int FillCloudAssetForDownload(const std::string &tableName, VBucket &asset, bool isFullReplace); - int FillCloudAssetForUpload(const CloudSyncData &data); + int FillCloudGidAndAsset(const OpType &opType, const CloudSyncData &data); protected: void Init(); diff --git a/kv_store/frameworks/libs/distributeddb/storage/include/sync_generic_interface.h b/kv_store/frameworks/libs/distributeddb/storage/include/sync_generic_interface.h index 1e3e2d52291782b37e11697307631d01795bacc8..da94c92f0281aea5822e63f6ac364d8ca4ec4c06 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/include/sync_generic_interface.h +++ b/kv_store/frameworks/libs/distributeddb/storage/include/sync_generic_interface.h @@ -144,6 +144,11 @@ public: { return {}; } + + int IsSupportSubscribe() const override + { + return -E_NOT_SUPPORT; + } }; } #endif // SYNC_GENERIC_INTERFACE_H diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/cloud/cloud_meta_data.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/cloud/cloud_meta_data.cpp index d8c6c720e705e4fc0bb5b57d17bc204f252b4aa5..e7db3f7938a6c1b448cde2a017ae154af88b6129 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/cloud/cloud_meta_data.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/cloud/cloud_meta_data.cpp @@ -55,6 +55,7 @@ int CloudMetaData::GetCloudWaterMark(TableName tableName, CloudWaterMark &cloudM } } cloudMark = cloudMetaVals_[tableName].cloudMark; + LOGD("[Meta] get cloud water mark=%s", cloudMark.c_str()); return E_OK; } @@ -97,6 +98,7 @@ int CloudMetaData::SetCloudWaterMark(TableName tableName, CloudWaterMark &cloudM } else { iter->second.cloudMark = cloudMark; } + LOGD("[Meta] set cloud water mark=%s", cloudMark.c_str()); return E_OK; } diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/cloud/cloud_storage_utils.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/cloud/cloud_storage_utils.cpp index bf84c6fa04fbe2ef4b3abbe06a55eb09ee3ed713..49863758664a1d25ab9bafe69e94c7ac559531fa 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/cloud/cloud_storage_utils.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/cloud/cloud_storage_utils.cpp @@ -12,6 +12,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include #include "cloud/cloud_db_types.h" #include "db_common.h" @@ -164,7 +165,7 @@ int CloudStorageUtils::BindAsset(int index, const VBucket &vBucket, const Field LOGE("can not get asset from vBucket when bind, %d", errCode); return errCode; } - RuntimeContext::GetInstance()->AssetToBlob(asset, val); + errCode = RuntimeContext::GetInstance()->AssetToBlob(asset, val); } else if (field.type == TYPE_INDEX) { Assets assets; errCode = GetValueFromOneField(type, assets); @@ -172,22 +173,21 @@ int CloudStorageUtils::BindAsset(int index, const VBucket &vBucket, const Field LOGE("can not get assets from vBucket when bind, %d", errCode); return errCode; } - if (assets.empty()) { - errCode = -E_NOT_FOUND; - } else { - RuntimeContext::GetInstance()->AssetsToBlob(assets, val); + if (!assets.empty()) { + errCode = RuntimeContext::GetInstance()->AssetsToBlob(assets, val); } } else { LOGE("field type is not asset or assets, %d", -E_CLOUD_ERROR); return -E_CLOUD_ERROR; } - if (errCode == E_OK) { - errCode = SQLiteUtils::BindBlobToStatement(upsertStmt, index, val); - } else { - errCode = SQLiteUtils::MapSQLiteErrno(sqlite3_bind_null(upsertStmt, index)); - } if (errCode != E_OK) { - LOGE("Bind blob to asset failed, %d", errCode); + LOGE("assets or asset to blob fail, %d", -E_CLOUD_ERROR); + return -E_CLOUD_ERROR; + } + if (val.empty()) { + errCode = SQLiteUtils::MapSQLiteErrno(sqlite3_bind_null(upsertStmt, index)); + } else { + errCode = SQLiteUtils::BindBlobToStatement(upsertStmt, index, val); } return errCode; } @@ -448,7 +448,7 @@ void CloudStorageUtils::FillAssetsForUpload(Assets &assets) } } -void CloudStorageUtils::FillAssetFromVBucketBeforeDownload(VBucket &vBucket) +void CloudStorageUtils::PrepareToFillAssetFromVBucket(VBucket &vBucket) { for (auto &item: vBucket) { if (IsAsset(item.second)) { @@ -467,40 +467,14 @@ void CloudStorageUtils::FillAssetFromVBucketBeforeDownload(VBucket &vBucket) } } -void CloudStorageUtils::FillAssetFromVBucketDownloadFinish(VBucket &vBucket) -{ - for (auto &item: vBucket) { - if (IsAsset(item.second)) { - Asset asset; - GetValueFromType(item.second, asset); - int errCode = FillAssetForDownload(asset); - if (errCode != E_OK) { - vBucket[item.first] = Nil(); - } else { - vBucket[item.first] = asset; - } - continue; - } - if (IsAssets(item.second)) { - Assets assets; - GetValueFromType(item.second, assets); - FillAssetsForDownload(assets); - if (assets.empty()) { - vBucket[item.first] = Nil(); - } else { - vBucket[item.first] = assets; - } - } - } -} - -void CloudStorageUtils::FillAssetFromVBucketAfterUpload(VBucket &vBucket) +void CloudStorageUtils::FillAssetFromVBucketFinish(VBucket &vBucket, std::function fillAsset, + std::function fillAssets) { for (auto &item: vBucket) { if (IsAsset(item.second)) { Asset asset; GetValueFromType(item.second, asset); - int errCode = FillAssetForUpload(asset); + int errCode = fillAsset(asset); if (errCode != E_OK) { vBucket[item.first] = Nil(); } else { @@ -511,7 +485,7 @@ void CloudStorageUtils::FillAssetFromVBucketAfterUpload(VBucket &vBucket) if (IsAssets(item.second)) { Assets assets; GetValueFromType(item.second, assets); - FillAssetsForUpload(assets); + fillAssets(assets); if (assets.empty()) { vBucket[item.first] = Nil(); } else { @@ -536,4 +510,87 @@ bool CloudStorageUtils::IsAssets(const Type &type) } return false; } + +int CloudStorageUtils::CalculateHashKeyForOneField(const Field &field, const VBucket &vBucket, bool allowEmpty, + std::vector &hashValue) +{ + if (allowEmpty && vBucket.find(field.colName) == vBucket.end()) { + return E_OK; // if vBucket from cloud doesn't contain primary key and allowEmpty, no need to calculate hash + } + static std::map &)>> toVecFunc = { + {TYPE_INDEX, &CloudStorageUtils::Int64ToVector}, + {TYPE_INDEX, &CloudStorageUtils::BoolToVector}, + {TYPE_INDEX, &CloudStorageUtils::DoubleToVector}, + {TYPE_INDEX, &CloudStorageUtils::TextToVector}, + {TYPE_INDEX, &CloudStorageUtils::BlobToVector}, + {TYPE_INDEX, &CloudStorageUtils::BlobToVector}, + {TYPE_INDEX, &CloudStorageUtils::BlobToVector}, + }; + auto it = toVecFunc.find(field.type); + if (it == toVecFunc.end()) { + LOGE("unknown cloud type when convert field to vector."); + return -E_CLOUD_ERROR; + } + std::vector value; + int errCode = it->second(vBucket, field, value); + if (errCode != E_OK) { + LOGE("convert cloud field fail, %d", errCode); + return errCode; + } + return DBCommon::CalcValueHash(value, hashValue); +} + +bool CloudStorageUtils::IsAssetsContainDuplicateAsset(Assets &assets) +{ + std::set set; + for (const auto &asset : assets) { + if (set.find(asset.name) != set.end()) { + return true; + } + set.insert(asset.name); + } + return false; +} + +void CloudStorageUtils::EraseNoChangeAsset(std::map &assetsMap) +{ + for (auto &items: assetsMap) { + for (auto item = items.second.begin(); item != items.second.end();) { + if (static_cast((*item).status) == AssetOpType::NO_CHANGE) { + item = items.second.erase(item); + } else { + item++; + } + } + } +} + +void CloudStorageUtils::MergeDownloadAsset(std::map &downloadAssets, + std::map &mergeAssets) +{ + for (auto &items: mergeAssets) { + auto downloadItem = downloadAssets.find(items.first); + if (downloadItem == downloadAssets.end()) { + continue; + } + std::map beCoveredAssetsMap = GenAssetsIndexMap(items.second); + for (const Asset &asset: downloadItem->second) { + auto it = beCoveredAssetsMap.find(asset.name); + if (it == beCoveredAssetsMap.end()) { + continue; + } + items.second[it->second] = asset; + } + } +} + +std::map CloudStorageUtils::GenAssetsIndexMap(Assets &assets) +{ + // key of assetsIndexMap is name of asset, the value of it is index. + std::map assetsIndexMap; + for (size_t i = 0; i < assets.size(); i++) { + assetsIndexMap[assets[i].name] = i; + } + return assetsIndexMap; +} } diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/relational_sync_able_storage.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/relational_sync_able_storage.cpp index 7612f523ee21774ec041fb427ea55d4b112038de..42bc3f4a8e8d9605d8d6ed1e5d3dc06913e32f52 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/relational_sync_able_storage.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/relational_sync_able_storage.cpp @@ -866,7 +866,7 @@ int RelationalSyncAbleStorage::GetRemoteDeviceSchema(const std::string &deviceId LOGE("Get remote device schema from meta failed. err=%d", errCode); return errCode; } - std::string remoteSchema(remoteSchemaBuff.begin(), remoteSchemaBuff.end()); + remoteSchema = std::string(remoteSchemaBuff.begin(), remoteSchemaBuff.end()); errCode = remoteDeviceSchema_.Put(deviceId, remoteSchema); } @@ -1160,11 +1160,14 @@ int RelationalSyncAbleStorage::FillCloudAssetForDownload(const std::string &tabl return errCode; } -int RelationalSyncAbleStorage::FillCloudAssetForUpload(const CloudSyncData &data) +int RelationalSyncAbleStorage::FillCloudGidAndAsset(const OpType &opType, const CloudSyncData &data) { if (storageEngine_ == nullptr) { return -E_INVALID_DB; } + if (opType == OpType::UPDATE && data.updData.assets.empty()) { + return E_OK; + } int errCode = E_OK; auto writeHandle = static_cast( storageEngine_->FindExecutor(true, OperatePerm::NORMAL_PERM, errCode, 0)); @@ -1176,8 +1179,22 @@ int RelationalSyncAbleStorage::FillCloudAssetForUpload(const CloudSyncData &data ReleaseHandle(writeHandle); return errCode; } - errCode = writeHandle->FillCloudAssetForUpload(data); + if (opType == OpType::INSERT) { + errCode = writeHandle->UpdateCloudLogGid(data); + if (errCode != E_OK) { + LOGE("Failed to fill cloud log gid, %d.", errCode); + writeHandle->Rollback(); + ReleaseHandle(writeHandle); + return errCode; + } + if (!data.insData.assets.empty()) { + errCode = writeHandle->FillCloudAssetForUpload(data.tableName, data.insData); + } + } else { + errCode = writeHandle->FillCloudAssetForUpload(data.tableName, data.updData); + } if (errCode != E_OK) { + LOGE("Failed to fill cloud asset, %d.", errCode); writeHandle->Rollback(); ReleaseHandle(writeHandle); return errCode; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store.cpp index 0340b12319fc04344d8013f337052cadded5f174..069a4176360931acb5ada6646b94ffa38003e789 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store.cpp @@ -945,8 +945,16 @@ int SQLiteRelationalStore::Sync(const std::vector &devices, SyncMod LOGE("[RelationalStore] sync with empty table"); return -E_INVALID_ARGS; } + SecurityOption option; + int errCode = storageEngine_->GetSecurityOption(option); + if (errCode != E_OK && errCode != -E_NOT_SUPPORT) { + return -E_SECURITY_OPTION_CHECK_ERROR; + } + if (errCode == E_OK && option.securityLabel == S4) { + return -E_SECURITY_OPTION_CHECK_ERROR; + } for (const auto &table: tableNames) { - int errCode = ChkSchema(table); + errCode = ChkSchema(table); if (errCode != E_OK) { LOGE("[RelationalStore] schema check failed when sync"); return errCode; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_log_table_manager.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_log_table_manager.cpp index 053ed430164e01dcad2d6bd0d29ced8dba41b418..6a449a7802d48349da98760ccc5cf5d189b36989 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_log_table_manager.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_log_table_manager.cpp @@ -45,8 +45,8 @@ int SqliteLogTableManager::CreateRelationalLogTable(sqlite3 *db, const TableInfo "wtimestamp INT NOT NULL," \ "flag INT NOT NULL," \ "hash_key BLOB NOT NULL," \ - "cloud_gid TEXT," \ - + primaryKey + ");"; + "cloud_gid TEXT," + + primaryKey + ");"; std::vector logTableSchema; logTableSchema.emplace_back(createTableSql); GetIndexSql(table, logTableSchema); diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store.cpp index bf820309d5d45b8e6fc63f6365a2d92b13c3648a..5b874ca0dcd9d28ed10cdd5668d5ff0b783d536b 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store.cpp @@ -2251,11 +2251,10 @@ int SQLiteSingleVerNaturalStore::InterceptData(std::vector & int SQLiteSingleVerNaturalStore::AddSubscribe(const std::string &subscribeId, const QueryObject &query, bool needCacheSubscribe) { - const SchemaObject &localSchema = MyProp().GetSchemaConstRef(); - if (localSchema.GetSchemaType() != SchemaType::NONE && localSchema.GetSchemaType() != SchemaType::JSON) { - // Flatbuffer schema is not support subscribe + if (IsSupportSubscribe() != E_OK) { return -E_NOT_SUPPORT; } + const SchemaObject &localSchema = MyProp().GetSchemaConstRef(); QueryObject queryInner = query; queryInner.SetSchema(localSchema); if (IsExtendedCacheDBMode() && needCacheSubscribe) { // cache auto subscribe when engine state is in CACHEDB mode @@ -2390,6 +2389,16 @@ void SQLiteSingleVerNaturalStore::Dump(int fd) SyncAbleKvDB::Dump(fd); } +int SQLiteSingleVerNaturalStore::IsSupportSubscribe() const +{ + const SchemaObject &localSchema = MyProp().GetSchemaConstRef(); + if (localSchema.GetSchemaType() != SchemaType::NONE && localSchema.GetSchemaType() != SchemaType::JSON) { + // Flatbuffer schema is not support subscribe + return -E_NOT_SUPPORT; + } + return E_OK; +} + int SQLiteSingleVerNaturalStore::RemoveDeviceDataInner(const std::string &hashDev, bool isNeedNotify) { int errCode = E_OK; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store.h index 0bb1a832eae8093425e4f63f9bf1609aa44dbe43..077afff248c80df44963bc1a632450316b6fb681 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store.h @@ -192,6 +192,8 @@ public: void Dump(int fd) override; + int IsSupportSubscribe() const override; + private: struct TransPair { int index; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_relational_storage_executor.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_relational_storage_executor.cpp index 454221389988a221bc8a510b1de28b41de1cb8ae..65bfe0588ec397a8088e4f6bcf74296f0bab76c6 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_relational_storage_executor.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_relational_storage_executor.cpp @@ -42,6 +42,7 @@ static constexpr const char* FLAG_IS_CLOUD = "FLAG & 0x02 = 0"; // see if 1th bi static constexpr const char* SET_FLAG_LOCAL = "FLAG | 0x02"; // set 1th bit of flag to one which is local static constexpr const int SET_FLAG_ZERO_MASK = 0x03; // clear 2th bit of flag static constexpr const int SET_FLAG_ONE_MASK = 0x04; // set 2th bit of flag +static constexpr const int SET_CLOUD_FLAG = 0x05; // set 1th bit of flag to 0 int PermitSelect(void *a, int b, const char *c, const char *d, const char *e, const char *f) { @@ -62,14 +63,6 @@ SQLiteSingleVerRelationalStorageExecutor::SQLiteSingleVerRelationalStorageExecut bindCloudFieldFuncMap_[TYPE_INDEX] = &CloudStorageUtils::BindBlob; bindCloudFieldFuncMap_[TYPE_INDEX] = &CloudStorageUtils::BindAsset; bindCloudFieldFuncMap_[TYPE_INDEX] = &CloudStorageUtils::BindAsset; - - toVectorFuncMap_[TYPE_INDEX] = &CloudStorageUtils::Int64ToVector; - toVectorFuncMap_[TYPE_INDEX] = &CloudStorageUtils::BoolToVector; - toVectorFuncMap_[TYPE_INDEX] = &CloudStorageUtils::DoubleToVector; - toVectorFuncMap_[TYPE_INDEX] = &CloudStorageUtils::TextToVector; - toVectorFuncMap_[TYPE_INDEX] = &CloudStorageUtils::BlobToVector; - toVectorFuncMap_[TYPE_INDEX] = &CloudStorageUtils::BlobToVector; - toVectorFuncMap_[TYPE_INDEX] = &CloudStorageUtils::BlobToVector; } @@ -538,6 +531,12 @@ int IdentifyCloudType(CloudSyncData &cloudSyncData, VBucket &data, VBucket &log, if (!data.empty()) { cloudSyncData.insData.record.push_back(data); cloudSyncData.insData.rowid.push_back(*rowid); + VBucket asset; + CloudStorageUtils::ObtainAssetFromVBucket(data, asset); + if (!asset.empty()) { + cloudSyncData.insData.timestamp.push_back(*timeStamp); + cloudSyncData.insData.assets.push_back(asset); + } } cloudSyncData.insData.extend.push_back(log); } else { @@ -930,10 +929,8 @@ int SQLiteSingleVerRelationalStorageExecutor::SaveSyncDataItems(RelationalSyncDa return saveStmt.ResetStatements(false); }); - if (errCode == -E_NOT_FOUND) { - errCode = E_OK; - } - return saveStmt.ResetStatements(true); + int ret = saveStmt.ResetStatements(true); + return errCode != E_OK ? errCode : ret; } int SQLiteSingleVerRelationalStorageExecutor::SaveSyncItems(RelationalSyncDataInserter &inserter, bool useTrans) @@ -1553,6 +1550,7 @@ int SQLiteSingleVerRelationalStorageExecutor::GetSyncCloudData(CloudSyncData &cl } Timestamp queryTime = 0; uint32_t totalSize = 0; + uint32_t stepNum = 0; do { if (isStepNext) { errCode = StepNext(isMemDb_, queryStmt, queryTime); @@ -1561,7 +1559,7 @@ int SQLiteSingleVerRelationalStorageExecutor::GetSyncCloudData(CloudSyncData &cl } } isStepNext = true; - errCode = GetCloudDataForSync(queryStmt, cloudDataResult, totalSize, maxSize); + errCode = GetCloudDataForSync(queryStmt, cloudDataResult, stepNum++, totalSize, maxSize); } while (errCode == E_OK); if (errCode != -E_UNFINISHED) { (void)token.ReleaseCloudStatement(); @@ -1570,7 +1568,7 @@ int SQLiteSingleVerRelationalStorageExecutor::GetSyncCloudData(CloudSyncData &cl } int SQLiteSingleVerRelationalStorageExecutor::GetCloudDataForSync(sqlite3_stmt *statement, - CloudSyncData &cloudDataResult, uint32_t &totalSize, const uint32_t &maxSize) + CloudSyncData &cloudDataResult, uint32_t stepNum, uint32_t &totalSize, const uint32_t &maxSize) { VBucket log; VBucket extraLog; @@ -1599,7 +1597,7 @@ int SQLiteSingleVerRelationalStorageExecutor::GetCloudDataForSync(sqlite3_stmt * } } - if (totalSize < maxSize) { + if (IsGetCloudDataContinue(stepNum, totalSize, maxSize)) { errCode = IdentifyCloudType(cloudDataResult, data, log, extraLog); } else { errCode = -E_UNFINISHED; @@ -1622,6 +1620,10 @@ int SQLiteSingleVerRelationalStorageExecutor::PutVBucketByType(VBucket &vBucket, if (errCode != E_OK) { return errCode; } + if (CloudStorageUtils::IsAssetsContainDuplicateAsset(assets)) { + LOGE("assets is contain duplicate Asset"); + return -E_CLOUD_ERROR; + } vBucket.insert_or_assign(field.colName, assets); } else { vBucket.insert_or_assign(field.colName, cloudValue); @@ -1749,7 +1751,7 @@ std::string SQLiteSingleVerRelationalStorageExecutor::GetInsertSqlForCloudSync(c } int SQLiteSingleVerRelationalStorageExecutor::GetPrimaryKeyHashValue(const VBucket &vBucket, - const TableSchema &tableSchema, std::vector &hashValue) + const TableSchema &tableSchema, std::vector &hashValue, bool allowEmpty) { int errCode = E_OK; std::map pkMap = CloudStorageUtils::GetCloudPrimaryKeyFieldMap(tableSchema); @@ -1760,12 +1762,12 @@ int SQLiteSingleVerRelationalStorageExecutor::GetPrimaryKeyHashValue(const VBuck errCode = DBCommon::CalcValueHash(value, hashValue); } else if (pkMap.size() == 1) { std::vector pkVec = CloudStorageUtils::GetCloudPrimaryKeyField(tableSchema); - errCode = CalculateHashKeyForOneField(pkVec.at(0), vBucket, hashValue); + errCode = CloudStorageUtils::CalculateHashKeyForOneField(pkVec.at(0), vBucket, allowEmpty, hashValue); } else { std::vector tempRes; for (const auto &item: pkMap) { std::vector temp; - errCode = CalculateHashKeyForOneField(item.second, vBucket, temp); + errCode = CloudStorageUtils::CalculateHashKeyForOneField(item.second, vBucket, allowEmpty, temp); if (errCode != E_OK) { LOGE("calc hash fail when there is more than one primary key. errCode = %d", errCode); return errCode; @@ -1806,7 +1808,7 @@ int SQLiteSingleVerRelationalStorageExecutor::GetQueryLogStatement(const TableSc std::vector hashValue; if (pkSet.size() > 0) { - errCode = GetPrimaryKeyHashValue(vBucket, tableSchema, hashValue); + errCode = GetPrimaryKeyHashValue(vBucket, tableSchema, hashValue, true); } if (errCode != E_OK) { LOGE("calc hash fail when get query log statement, errCode = %d", errCode); @@ -1824,23 +1826,6 @@ int SQLiteSingleVerRelationalStorageExecutor::GetQueryLogStatement(const TableSc return errCode != E_OK ? errCode : ret; } -int SQLiteSingleVerRelationalStorageExecutor::CalculateHashKeyForOneField(const Field &field, const VBucket &vBucket, - std::vector &hashValue) -{ - auto it = toVectorFuncMap_.find(field.type); - if (it == toVectorFuncMap_.end()) { - LOGE("unknown cloud type when convert field to vector."); - return -E_CLOUD_ERROR; - } - std::vector value; - int errCode = it->second(vBucket, field, value); - if (errCode != E_OK) { - LOGE("convert cloud field fail, %d", errCode); - return errCode; - } - return DBCommon::CalcValueHash(value, hashValue); -} - int SQLiteSingleVerRelationalStorageExecutor::GetQueryLogSql(const std::string &tableName, const VBucket &vBucket, std::set &pkSet, std::string &querySql) { @@ -1886,7 +1871,9 @@ int SQLiteSingleVerRelationalStorageExecutor::ExecutePutCloudData(const std::str case OpType::ONLY_UPDATE_GID: case OpType::SET_CLOUD_FORCE_PUSH_FLAG_ZERO: case OpType::SET_CLOUD_FORCE_PUSH_FLAG_ONE: - errCode = UpdateCloudGidOrFlag(vBucket, tableSchema, op); + case OpType::UPDATE_TIMESTAMP: + case OpType::CLEAR_GID: + errCode = OnlyUpdateLogTable(vBucket, tableSchema, op); break; case OpType::NOT_HANDLE: break; @@ -2166,12 +2153,14 @@ int SQLiteSingleVerRelationalStorageExecutor::PutCloudSyncData(const std::string if (ret != E_OK) { LOGE("Fail to set log trigger on, %d", ret); } - LOGD("save cloud data ok, insert count = %d, update count = %d, delete count = %d, only update gid count = %d, " - "set LCC flag zero count = %d, set LCC flag one count = %d, not handle count = %d", - statisticMap[static_cast(OpType::INSERT)], statisticMap[static_cast(OpType::UPDATE)], + LOGD("save cloud data: %d, insert cnt = %d, update cnt = %d, delete cnt = %d, only update gid cnt = %d, " + "set LCC flag zero cnt = %d, set LCC flag one cnt = %d, update timestamp cnt = %d, clear gid count = %d," + " not handle cnt = %d", + errCode, statisticMap[static_cast(OpType::INSERT)], statisticMap[static_cast(OpType::UPDATE)], statisticMap[static_cast(OpType::DELETE)], statisticMap[static_cast(OpType::ONLY_UPDATE_GID)], statisticMap[static_cast(OpType::SET_CLOUD_FORCE_PUSH_FLAG_ZERO)], statisticMap[static_cast(OpType::SET_CLOUD_FORCE_PUSH_FLAG_ONE)], + statisticMap[static_cast(OpType::UPDATE_TIMESTAMP)], statisticMap[static_cast(OpType::CLEAR_GID)], statisticMap[static_cast(OpType::NOT_HANDLE)]); return errCode == E_OK ? ret : errCode; } @@ -2186,7 +2175,7 @@ int SQLiteSingleVerRelationalStorageExecutor::InsertCloudData(const std::string LOGE("Get insert statement failed when save cloud data, %d", errCode); return errCode; } - CloudStorageUtils::FillAssetFromVBucketBeforeDownload(vBucket); + CloudStorageUtils::PrepareToFillAssetFromVBucket(vBucket); errCode = BindValueToUpsertStatement(vBucket, tableSchema.fields, insertStmt); if (errCode != E_OK) { SQLiteUtils::ResetStatement(insertStmt, true, errCode); @@ -2369,14 +2358,14 @@ int SQLiteSingleVerRelationalStorageExecutor::BindValueToInsertLogStatement(VBuc } std::string SQLiteSingleVerRelationalStorageExecutor::GetWhereConditionForDataTable(const std::string &gidStr, - const std::set &pkSet, const std::string &tableName) + const std::set &pkSet, const std::string &tableName, bool queryByPk) { std::string where = " where"; if (!gidStr.empty()) { // gid has higher priority, because primary key may be modified where += " rowid = (select data_key from " + DBCommon::GetLogTableName(tableName) + " where cloud_gid = '" + gidStr + "')"; } - if (!pkSet.empty()) { + if (!pkSet.empty() && queryByPk) { if (!gidStr.empty()) { where += " or"; } @@ -2450,7 +2439,7 @@ int SQLiteSingleVerRelationalStorageExecutor::GetUpdateDataTableStatement(const int SQLiteSingleVerRelationalStorageExecutor::UpdateCloudData(const std::string &tableName, VBucket &vBucket, const TableSchema &tableSchema) { - CloudStorageUtils::FillAssetFromVBucketBeforeDownload(vBucket); + CloudStorageUtils::PrepareToFillAssetFromVBucket(vBucket); sqlite3_stmt *updateStmt = nullptr; int errCode = GetUpdateDataTableStatement(vBucket, tableSchema, updateStmt); if (errCode != E_OK) { @@ -2488,15 +2477,21 @@ int SQLiteSingleVerRelationalStorageExecutor::GetUpdateLogRecordStatement(const updateLogSql += "flag = flag & " + std::to_string(SET_FLAG_ZERO_MASK); // clear 2th bit of flag } else if (opType == OpType::SET_CLOUD_FORCE_PUSH_FLAG_ONE) { updateLogSql += "flag = flag | " + std::to_string(SET_FLAG_ONE_MASK); // set 2th bit of flag + } else if (opType == OpType::UPDATE_TIMESTAMP) { + updateLogSql += "device = 'cloud', flag = flag & " + std::to_string(SET_CLOUD_FLAG) + + ", timestamp = ?, cloud_gid = ''"; + updateColName.push_back(CloudDbConstant::MODIFY_FIELD); + } else if (opType == OpType::CLEAR_GID) { + updateLogSql += "cloud_gid = '', flag = flag & " + std::to_string(SET_FLAG_ZERO_MASK); } else { if (opType == OpType::DELETE) { - updateLogSql += "data_key = -1, flag = 1, "; + updateLogSql += "data_key = -1, flag = 1, cloud_gid = '', "; } else { - updateLogSql += "flag = 0, "; + updateLogSql += "flag = 0, cloud_gid = ?, "; + updateColName.push_back(CloudDbConstant::GID_FIELD); } - updateLogSql += "device = 'cloud', timestamp = ?, cloud_gid = ?"; + updateLogSql += "device = 'cloud', timestamp = ?"; updateColName.push_back(CloudDbConstant::MODIFY_FIELD); - updateColName.push_back(CloudDbConstant::GID_FIELD); } std::string gidStr; @@ -2525,6 +2520,12 @@ int SQLiteSingleVerRelationalStorageExecutor::GetUpdateLogRecordStatement(const return errCode; } +static inline bool IsAllowWithPrimaryKey(OpType opType) +{ + return (opType == OpType::DELETE || opType == OpType::UPDATE_TIMESTAMP || opType == OpType::CLEAR_GID || + opType == OpType::ONLY_UPDATE_GID); +} + int SQLiteSingleVerRelationalStorageExecutor::UpdateLogRecord(const VBucket &vBucket, const TableSchema &tableSchema, OpType opType) { @@ -2536,8 +2537,8 @@ int SQLiteSingleVerRelationalStorageExecutor::UpdateLogRecord(const VBucket &vBu return errCode; } - std::map pkMap = CloudStorageUtils::GetCloudPrimaryKeyFieldMap(tableSchema); - errCode = BindValueToUpdateLogStatement(vBucket, tableSchema, updateColName, pkMap, updateLogStmt); + errCode = BindValueToUpdateLogStatement(vBucket, tableSchema, updateColName, IsAllowWithPrimaryKey(opType), + updateLogStmt); int ret = E_OK; if (errCode != E_OK) { LOGE("bind value to update log statement failed when update cloud data, %d", errCode); @@ -2556,7 +2557,7 @@ int SQLiteSingleVerRelationalStorageExecutor::UpdateLogRecord(const VBucket &vBu } int SQLiteSingleVerRelationalStorageExecutor::BindValueToUpdateLogStatement(const VBucket &vBucket, - const TableSchema &tableSchema, std::vector &colNames, std::map &pkMap, + const TableSchema &tableSchema, const std::vector &colNames, bool allowPrimaryKeyEmpty, sqlite3_stmt *updateLogStmt) { int index = 0; @@ -2564,9 +2565,17 @@ int SQLiteSingleVerRelationalStorageExecutor::BindValueToUpdateLogStatement(cons for (const auto &colName : colNames) { index++; if (colName == CloudDbConstant::GID_FIELD) { + if (vBucket.find(colName) == vBucket.end()) { + LOGE("cloud data doesn't contain gid field when bind update log stmt."); + return -E_CLOUD_ERROR; + } errCode = SQLiteUtils::BindTextToStatement(updateLogStmt, index, std::get(vBucket.at(colName))); } else if (colName == CloudDbConstant::MODIFY_FIELD) { + if (vBucket.find(colName) == vBucket.end()) { + LOGE("cloud data doesn't contain modify field when bind update log stmt."); + return -E_CLOUD_ERROR; + } errCode = SQLiteUtils::BindInt64ToStatement(updateLogStmt, index, std::get(vBucket.at(colName))); } else { LOGE("invalid col name when bind value to update log statement."); @@ -2577,12 +2586,13 @@ int SQLiteSingleVerRelationalStorageExecutor::BindValueToUpdateLogStatement(cons return errCode; } } + std::map pkMap = CloudStorageUtils::GetCloudPrimaryKeyFieldMap(tableSchema); if (pkMap.empty()) { return E_OK; } std::vector hashKey; - errCode = GetPrimaryKeyHashValue(vBucket, tableSchema, hashKey); + errCode = GetPrimaryKeyHashValue(vBucket, tableSchema, hashKey, allowPrimaryKeyEmpty); if (errCode != E_OK) { return errCode; } @@ -2598,27 +2608,18 @@ int SQLiteSingleVerRelationalStorageExecutor::GetDeleteStatementForCloudSync(con LOGE("Get gid from cloud data fail when construct delete sql, errCode = %d", errCode); return errCode; } - if (!gidStr.empty() && gidStr.find("'") != std::string::npos) { - LOGE("invalid char in cloud gid"); + if (gidStr.empty() || gidStr.find("'") != std::string::npos) { + LOGE("empty or invalid char in cloud gid"); return -E_CLOUD_ERROR; } std::string deleteSql = "delete from " + tableSchema.name; - deleteSql += GetWhereConditionForDataTable(gidStr, pkSet, tableSchema.name); + deleteSql += GetWhereConditionForDataTable(gidStr, pkSet, tableSchema.name, false); errCode = SQLiteUtils::GetStatement(dbHandle_, deleteSql, deleteStmt); if (errCode != E_OK) { - LOGE("Get delete statement failed when delete data, %d", errCode); - return errCode; + LOGE("Get delete statement failed when delete data, %d, deleteSql = %s", errCode, deleteSql.c_str()); } - - std::vector pkFields = CloudStorageUtils::GetCloudPrimaryKeyField(tableSchema); - errCode = BindValueToUpsertStatement(vBucket, pkFields, deleteStmt); - int ret = E_OK; - if (errCode != E_OK) { - LOGE("bind value to delete statement failed when delete data, %d", errCode); - SQLiteUtils::ResetStatement(deleteStmt, true, ret); - } - return errCode != E_OK ? errCode : ret; + return errCode; } int SQLiteSingleVerRelationalStorageExecutor::DeleteCloudData(const std::string &tableName, const VBucket &vBucket, @@ -2651,7 +2652,7 @@ int SQLiteSingleVerRelationalStorageExecutor::DeleteCloudData(const std::string return errCode; } -int SQLiteSingleVerRelationalStorageExecutor::UpdateCloudGidOrFlag(const VBucket &vBucket, +int SQLiteSingleVerRelationalStorageExecutor::OnlyUpdateLogTable(const VBucket &vBucket, const TableSchema &tableSchema, OpType opType) { return UpdateLogRecord(vBucket, tableSchema, opType); diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_relational_storage_executor.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_relational_storage_executor.h index b91d0e4192be8a19800b1d81203b37bb0b28fb92..cba0db783e98e709be181467ee8f5348ae17a788 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_relational_storage_executor.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_relational_storage_executor.h @@ -109,7 +109,7 @@ public: int DoCleanInner(ClearMode mode, const std::vector &tableNameList, const std::vector &tableSchemaList, std::vector &assets); - int FillCloudAssetForUpload(const CloudSyncData &data); + int FillCloudAssetForUpload(const std::string &tableName, const CloudSyncBatch &data); private: int DoCleanLogs(const std::vector &tableNameList); @@ -166,8 +166,8 @@ private: int GeneLogInfoForExistedData(sqlite3 *db, const std::string &tableName, const TableInfo &table, const std::string &calPrimaryKeyHash); - int GetCloudDataForSync(sqlite3_stmt *statement, CloudSyncData &cloudDataResult, uint32_t &totalSize, - const uint32_t &maxSize); + int GetCloudDataForSync(sqlite3_stmt *statement, CloudSyncData &cloudDataResult, uint32_t stepNum, + uint32_t &totalSize, const uint32_t &maxSize); int PutVBucketByType(VBucket &vBucket, const Field &field, Type &cloudValue); @@ -176,7 +176,8 @@ private: std::string GetInsertSqlForCloudSync(const TableSchema &tableSchema); - int GetPrimaryKeyHashValue(const VBucket &vBucket, const TableSchema &tableSchema, std::vector &hashValue); + int GetPrimaryKeyHashValue(const VBucket &vBucket, const TableSchema &tableSchema, std::vector &hashValue, + bool allowEmpty = false); int GetQueryLogStatement(const TableSchema &tableSchema, const VBucket &vBucket, const std::string &querySql, std::set &pkSet, sqlite3_stmt *&selectStmt); @@ -190,11 +191,10 @@ private: int GetQueryLogRowid(const std::string &tableName, const VBucket &vBucket, int64_t &rowId); int GetFillDownloadAssetStatement(const std::string &tableName, const VBucket &vBucket, - const std::vector &fields, bool isFullReplace, sqlite3_stmt *&statement); + const std::vector &fields, sqlite3_stmt *&statement); - int GetFillUploadAssetStatement(const std::string &tableName, const VBucket &vBucket, sqlite3_stmt *&statement); - - int CalculateHashKeyForOneField(const Field &field, const VBucket &vBucket, std::vector &hashValue); + int InitFillUploadAssetStatement(const std::string &tableName, const CloudSyncBatch &data, + const int &index, sqlite3_stmt *&statement); void GetLogInfoByStatement(sqlite3_stmt *statement, LogInfo &logInfo); @@ -215,7 +215,7 @@ private: int BindValueToInsertLogStatement(VBucket &vBucket, const TableSchema &tableSchema, sqlite3_stmt *insertLogStmt); std::string GetWhereConditionForDataTable(const std::string &gidStr, const std::set &pkSet, - const std::string &tableName); + const std::string &tableName, bool queryByPk = true); int GetUpdateSqlForCloudSync(const TableSchema &tableSchema, const VBucket &vBucket, const std::string &gidStr, const std::set &pkSet, std::string &updateSql); @@ -230,14 +230,16 @@ private: int UpdateLogRecord(const VBucket &vBucket, const TableSchema &tableSchema, OpType opType); int BindValueToUpdateLogStatement(const VBucket &vBucket, const TableSchema &tableSchema, - std::vector &colNames, std::map &pkMap, sqlite3_stmt *updateLogStmt); + const std::vector &colNames, bool allowPrimaryKeyEmpty, sqlite3_stmt *updateLogStmt); int GetDeleteStatementForCloudSync(const TableSchema &tableSchema, const std::set &pkSet, const VBucket &vBucket, sqlite3_stmt *&deleteStmt); int DeleteCloudData(const std::string &tableName, const VBucket &vBucket, const TableSchema &tableSchema); - int UpdateCloudGidOrFlag(const VBucket &vBucket, const TableSchema &tableSchema, OpType opType); + int OnlyUpdateLogTable(const VBucket &vBucket, const TableSchema &tableSchema, OpType opType); + + bool IsGetCloudDataContinue(uint32_t curNum, uint32_t curSize, uint32_t maxSize); std::string baseTblName_; TableInfo table_; // Always operating table, user table when get, device table when put. diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_relational_storage_extend_executor.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_relational_storage_extend_executor.cpp index e3924d878f69526babb2f1f87a5c84b9151a605b..db88d3d8abdf37e10ee992703b5c680084b90576 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_relational_storage_extend_executor.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_relational_storage_extend_executor.cpp @@ -26,14 +26,14 @@ int SQLiteSingleVerRelationalStorageExecutor::GetQueryInfoSql(const std::string if (assetFields.empty() && pkSet.empty()) { return GetQueryLogSql(tableName, vBucket, pkSet, querySql); } - std::string cloudGid; - int errCode = CloudStorageUtils::GetValueFromVBucket(CloudDbConstant::GID_FIELD, vBucket, cloudGid); + std::string gid; + int errCode = CloudStorageUtils::GetValueFromVBucket(CloudDbConstant::GID_FIELD, vBucket, gid); if (errCode != E_OK) { LOGE("Get cloud gid fail when query log table."); return errCode; } - if (pkSet.empty() && cloudGid.empty()) { + if (pkSet.empty() && gid.empty()) { LOGE("query log table failed because of both primary key and gid are empty."); return -E_CLOUD_ERROR; } @@ -47,7 +47,7 @@ int SQLiteSingleVerRelationalStorageExecutor::GetQueryInfoSql(const std::string } sql += " from '" + DBCommon::GetLogTableName(tableName) + "' AS a LEFT JOIN '" + tableName + "' AS b "; sql += " ON (a.data_key = b.rowid) WHERE "; - if (!cloudGid.empty()) { + if (!gid.empty()) { sql += " a.cloud_gid = ? or "; } sql += "a.hash_key = ?"; @@ -92,7 +92,7 @@ int SQLiteSingleVerRelationalStorageExecutor::GetQueryLogRowid(const std::string } int SQLiteSingleVerRelationalStorageExecutor::GetFillDownloadAssetStatement(const std::string &tableName, - const VBucket &vBucket, const std::vector &fields, bool isFullReplace, sqlite3_stmt *&statement) + const VBucket &vBucket, const std::vector &fields, sqlite3_stmt *&statement) { std::string sql = "UPDATE " + tableName + " SET "; for (const auto &field: fields) { @@ -138,11 +138,12 @@ int SQLiteSingleVerRelationalStorageExecutor::FillCloudAssetForDownload(const Ta goto END; } if (isFullReplace) { - CloudStorageUtils::FillAssetFromVBucketDownloadFinish(vBucket); + CloudStorageUtils::FillAssetFromVBucketFinish(vBucket, CloudStorageUtils::FillAssetForDownload, + CloudStorageUtils::FillAssetsForDownload); } else { - CloudStorageUtils::FillAssetFromVBucketBeforeDownload(vBucket); + CloudStorageUtils::PrepareToFillAssetFromVBucket(vBucket); } - errCode = GetFillDownloadAssetStatement(tableSchema.name, vBucket, assetsField, isFullReplace, stmt); + errCode = GetFillDownloadAssetStatement(tableSchema.name, vBucket, assetsField, stmt); if (errCode != E_OK) { goto END; } @@ -167,13 +168,13 @@ END: return errCode; } -int SQLiteSingleVerRelationalStorageExecutor::FillCloudAssetForUpload(const CloudSyncData &data) +int SQLiteSingleVerRelationalStorageExecutor::FillCloudAssetForUpload(const std::string &tableName, + const CloudSyncBatch &data) { - if (data.updData.assets.empty() || data.updData.rowid.empty() || data.updData.timestamp.empty()) { + if (data.assets.empty() || data.rowid.empty() || data.timestamp.empty()) { return -E_INVALID_ARGS; } - if (data.updData.assets.size() != data.updData.rowid.size() || - data.updData.assets.size() != data.updData.timestamp.size()) { + if (data.assets.size() != data.rowid.size() || data.assets.size() != data.timestamp.size()) { return -E_INVALID_ARGS; } int errCode = SetLogTriggerStatus(false); @@ -182,66 +183,85 @@ int SQLiteSingleVerRelationalStorageExecutor::FillCloudAssetForUpload(const Clou return errCode; } sqlite3_stmt *stmt = nullptr; - for (size_t i = 0; i < data.updData.assets.size(); ++i) { - VBucket assetData = data.updData.assets.at(i); - CloudStorageUtils::FillAssetFromVBucketAfterUpload(assetData); - errCode = GetFillUploadAssetStatement(data.tableName, assetData, stmt); - if (errCode != E_OK) { - goto END; - } - int64_t rowid = data.updData.rowid[i]; - errCode = SQLiteUtils::BindInt64ToStatement(stmt, assetData.size() + 1, rowid); - if (errCode != E_OK) { - break; - } - int64_t timeStamp = data.updData.timestamp[i]; - errCode = SQLiteUtils::BindInt64ToStatement(stmt, assetData.size() + 2, timeStamp); // 2 is index + for (size_t i = 0; i < data.assets.size(); ++i) { + errCode = InitFillUploadAssetStatement(tableName, data, i, stmt); if (errCode != E_OK) { break; } errCode = SQLiteUtils::StepWithRetry(stmt, false); - if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { - errCode = E_OK; - SQLiteUtils::ResetStatement(stmt, false, errCode); - } else { + if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { LOGE("Fill upload asset failed:%d", errCode); break; } + errCode = E_OK; + SQLiteUtils::ResetStatement(stmt, true, errCode); + stmt = nullptr; + if (errCode != E_OK) { + break; + } } - SQLiteUtils::ResetStatement(stmt, true, errCode); -END: + int ret = E_OK; + SQLiteUtils::ResetStatement(stmt, true, ret); int endCode = SetLogTriggerStatus(true); if (endCode != E_OK) { LOGE("Fail to set log trigger off, %d", endCode); + return endCode; } - return errCode; + return errCode != E_OK ? errCode : ret; } -int SQLiteSingleVerRelationalStorageExecutor::GetFillUploadAssetStatement(const std::string &tableName, - const VBucket &vBucket, sqlite3_stmt *&statement) +int SQLiteSingleVerRelationalStorageExecutor::InitFillUploadAssetStatement(const std::string &tableName, + const CloudSyncBatch &data, const int &index, sqlite3_stmt *&statement) { + VBucket vBucket = data.assets.at(index); + CloudStorageUtils::FillAssetFromVBucketFinish(vBucket, CloudStorageUtils::FillAssetForUpload, + CloudStorageUtils::FillAssetsForUpload); std::string sql = "UPDATE " + tableName + " SET "; for (const auto &item: vBucket) { sql += item.first + " = ?,"; } sql.pop_back(); - sql += " WHERE rowid = ? and (select 1 from " + DBCommon::GetLogTableName(tableName) + " WHERE timestamp = ?);"; + sql += " WHERE rowid = ? and (select 1 from " + DBCommon::GetLogTableName(tableName) + + " WHERE timestamp = ?);"; int errCode = SQLiteUtils::GetStatement(dbHandle_, sql, statement); if (errCode != E_OK) { return errCode; } - int index = 1; + int batchIndex = 1; for (const auto &item: vBucket) { Field field = { .colName = item.first, .type = static_cast(item.second.index()) }; - errCode = bindCloudFieldFuncMap_[TYPE_INDEX](index++, vBucket, field, statement); + errCode = bindCloudFieldFuncMap_[TYPE_INDEX](batchIndex++, vBucket, field, statement); if (errCode != E_OK) { - SQLiteUtils::ResetStatement(statement, true, errCode); return errCode; } } - return errCode; + int64_t rowid = data.rowid[index]; + errCode = SQLiteUtils::BindInt64ToStatement(statement, vBucket.size() + 1, rowid); + if (errCode != E_OK) { + return errCode; + } + int64_t timeStamp = data.timestamp[index]; + return SQLiteUtils::BindInt64ToStatement(statement, vBucket.size() + 2, timeStamp); // 2 is index; +} + +bool SQLiteSingleVerRelationalStorageExecutor::IsGetCloudDataContinue(uint32_t curNum, uint32_t curSize, + uint32_t maxSize) +{ + if (curNum == 0) { + return true; + } +#ifdef MAX_UPLOAD_COUNT + if (curSize < maxSize && curNum < MAX_UPLOAD_COUNT) { + return true; + } +#else + if (curSize < maxSize) { + return true; + } +#endif + return false; } } // namespace DistributedDB #endif \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/storage_proxy.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/storage_proxy.cpp index 4e5d7e4b7e102e2a7dbb406f81f5c10a7f8a863a..c8d711c1bf18f4b5256b2b9f5d830254bd5d4def 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/storage_proxy.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/storage_proxy.cpp @@ -85,7 +85,7 @@ int StorageProxy::GetCloudWaterMark(const std::string &tableName, CloudWaterMark return cloudMetaData_->GetCloudWaterMark(tableName, cloudMark); } -int StorageProxy::PutCloudWaterMark(const std::string &tableName, CloudWaterMark &cloudMark) +int StorageProxy::SetCloudWaterMark(const std::string &tableName, CloudWaterMark &cloudMark) { std::shared_lock readLock(storeMutex_); if (cloudMetaData_ == nullptr) { @@ -320,12 +320,16 @@ int StorageProxy::FillCloudAssetForDownload(const std::string &tableName, VBucke return store_->FillCloudAssetForDownload(tableName, asset, isFullReplace); } -int StorageProxy::FillCloudAssetForUpload(const CloudSyncData &data) +int StorageProxy::FillCloudGidAndAsset(const OpType &opType, const CloudSyncData &data) { std::shared_lock readLock(storeMutex_); if (store_ == nullptr) { return -E_INVALID_DB; } - return store_->FillCloudAssetForUpload(data); + if (!transactionExeFlag_.load()) { + LOGE("the transaction has not been started"); + return -E_TRANSACT_STATE; + } + return store_->FillCloudGidAndAsset(opType, data); } } diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_db_proxy.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_db_proxy.cpp index fbafb439a37b64ac4a2ee14bf5337e193ae55191..7bc80f9e430cee9369d00ee8c2e7562714739382 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_db_proxy.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_db_proxy.cpp @@ -27,7 +27,9 @@ CloudDBProxy::CloudDBProxy() int CloudDBProxy::SetCloudDB(const std::shared_ptr &cloudDB) { std::unique_lock writeLock(cloudMutex_); - iCloudDb_ = cloudDB; + if (!iCloudDb_) { + iCloudDb_ = cloudDB; + } return E_OK; } @@ -98,9 +100,6 @@ int CloudDBProxy::Query(const std::string &tableName, VBucket &extend, std::vect context->SetTableName(tableName); int errCode = InnerAction(context, cloudDb, QUERY); context->MoveOutQueryExtendAndData(extend, data); - if (errCode != E_OK && errCode != -E_QUERY_END) { - return -E_CLOUD_ERROR; - } return errCode; } @@ -178,10 +177,10 @@ int CloudDBProxy::Download(const std::string &tableName, const std::string &gid, { std::shared_lock readLock(assetLoaderMutex_); if (iAssetLoader_ == nullptr) { - LOGE("Asset loader has not been set %d", -E_INVALID_DB); - return -E_INVALID_DB; + LOGE("Asset loader has not been set %d", -E_NOT_SET); + return -E_NOT_SET; } - return iAssetLoader_->Download(tableName, gid, prefix, assets); + return iAssetLoader_->Download(tableName, gid, prefix, assets) == OK ? E_OK : -E_CLOUD_ERROR; } int CloudDBProxy::RemoveLocalAssets(const std::vector &assets) @@ -306,7 +305,7 @@ void CloudDBProxy::InnerActionTask(const std::shared_ptr &co LOGD("[CloudDBProxy] action %" PRIu8 " end res:%d", static_cast(action), static_cast(status)); if (!setResAlready) { - context->SetActionRes(status == OK ? E_OK : -E_CLOUD_ERROR); + context->SetActionRes(GetInnerErrorCode(status)); } context->FinishAndNotify(); @@ -317,6 +316,24 @@ void CloudDBProxy::InnerActionTask(const std::shared_ptr &co asyncTaskCv_.notify_all(); } +int CloudDBProxy::GetInnerErrorCode(DBStatus status) +{ + switch (status) { + case OK: + return E_OK; + case CLOUD_NETWORK_ERROR: + return -E_CLOUD_NETWORK_ERROR; + case CLOUD_SYNC_UNSET: + return -E_CLOUD_SYNC_UNSET; + case CLOUD_FULL_RECORDS: + return -E_CLOUD_FULL_RECORDS; + case CLOUD_LOCK_ERROR: + return -E_CLOUD_LOCK_ERROR; + default: + return -E_CLOUD_ERROR; + } +} + CloudDBProxy::CloudActionContext::CloudActionContext() : actionFinished_(false), actionRes_(OK), diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_db_proxy.h b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_db_proxy.h index 4173ba104ec5417655de9f1e257d7022fff4d4d8..957648cd83128a394bb8e799dd1a297ebd1ff248 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_db_proxy.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_db_proxy.h @@ -129,6 +129,8 @@ protected: void InnerActionTask(const std::shared_ptr &context, const std::shared_ptr &cloudDb, InnerActionCode action); + static int GetInnerErrorCode(DBStatus status); + mutable std::shared_mutex cloudMutex_; mutable std::shared_mutex assetLoaderMutex_; std::shared_ptr iCloudDb_; diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_force_pull_strategy.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_force_pull_strategy.cpp index 70ed70cd1aa62acd577559ae6a2e746e44578ff4..2af8c11ef85882d162e37c5e1ab0ac6d7c050967 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_force_pull_strategy.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_force_pull_strategy.cpp @@ -12,7 +12,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#ifdef MANNUAL_SYNC_AND_CLEAN_CLOUD_DATA #include "cloud_force_pull_strategy.h" #include "db_common.h" #include "db_errno.h" @@ -25,9 +24,10 @@ OpType CloudForcePullStrategy::TagSyncDataStatus(bool existInLocal, LogInfo &loc if (existInLocal) { if (!IsDelete(localInfo) && IsDelete(cloudInfo)) { return OpType::DELETE; + } else if (IsDelete(cloudInfo)) { + return OpType::UPDATE_TIMESTAMP; } else { - // When gid doestn't exist in local, it will fill gid on local also. - return OpType::UPDATE; + return IsDelete(localInfo) ? OpType::INSERT : OpType::UPDATE; } } else { if (IsDelete(cloudInfo)) { @@ -47,5 +47,4 @@ bool CloudForcePullStrategy::JudgeUpload() { return false; } -} -#endif // MANNUAL_SYNC_AND_CLEAN_CLOUD_DATA \ No newline at end of file +} \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_force_pull_strategy.h b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_force_pull_strategy.h index 34dd0997d7d045fb83f1ae232a16d0143d6cc996..79db2efdd415f7da556d84f42eea78baf46889bd 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_force_pull_strategy.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_force_pull_strategy.h @@ -12,9 +12,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#ifdef MANNUAL_SYNC_AND_CLEAN_CLOUD_DATA -#ifndef CLOUD_COVER_LOCAL_H -#define CLOUD_COVER_LOCAL_H +#ifndef CLOUD_FORCE_PULL_STRATEGY_H +#define CLOUD_FORCE_PULL_STRATEGY_H #include "cloud_sync_strategy.h" namespace DistributedDB { @@ -27,5 +26,4 @@ public: bool JudgeUpload() override; }; } -#endif // CLOUD_COVER_LOCAL_H -#endif // MANNUAL_SYNC_AND_CLEAN_CLOUD_DATA \ No newline at end of file +#endif // CLOUD_FORCE_PULL_STRATEGY_H \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_force_push_strategy.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_force_push_strategy.cpp index 40f0029ebeca3d8660a4bcd1edd08934d0868848..1fbac2f6fa57150c741166a3c8ab059c5fb54c66 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_force_push_strategy.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_force_push_strategy.cpp @@ -12,7 +12,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#ifdef MANNUAL_SYNC_AND_CLEAN_CLOUD_DATA #include "cloud_force_push_strategy.h" #include "db_common.h" #include "db_errno.h" @@ -21,10 +20,15 @@ namespace DistributedDB { const std::string cloud_device_name = "cloud"; OpType CloudForcePushStrategy::TagSyncDataStatus(bool existInLocal, LogInfo &localInfo, LogInfo &cloudInfo) { + bool isCloudDelete = IsDelete(cloudInfo); if (existInLocal) { if (localInfo.cloudGid.empty()) { - return OpType::ONLY_UPDATE_GID; + // when cloud data is deleted, we think it is different data + return isCloudDelete ? OpType::NOT_HANDLE : OpType::ONLY_UPDATE_GID; } else { + if (isCloudDelete) { + return OpType::CLEAR_GID; + } if (localInfo.device == cloud_device_name && localInfo.timestamp == cloudInfo.timestamp) { return OpType::SET_CLOUD_FORCE_PUSH_FLAG_ONE; } @@ -47,5 +51,4 @@ bool CloudForcePushStrategy::JudgeUpload() { return true; } -} -#endif // MANNUAL_SYNC_AND_CLEAN_CLOUD_DATA \ No newline at end of file +} \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_force_push_strategy.h b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_force_push_strategy.h index 94eb9ba4425c7d89276ecbdb2870c59052afee35..b7616e67e5c3fe6f7147a4ebe1c9968958c3adaa 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_force_push_strategy.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_force_push_strategy.h @@ -12,9 +12,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#ifdef MANNUAL_SYNC_AND_CLEAN_CLOUD_DATA -#ifndef LOCAL_COVER_CLOUD_H -#define LOCAL_COVER_CLOUD_H +#ifndef CLOUD_FORCE_PUSH_STRATEGY_H +#define CLOUD_FORCE_PUSH_STRATEGY_H #include "cloud_sync_strategy.h" namespace DistributedDB { @@ -27,5 +26,4 @@ public: bool JudgeUpload() override; }; } -#endif // LOCAL_COVER_CLOUD_H -#endif // MANNUAL_SYNC_AND_CLEAN_CLOUD_DATA \ No newline at end of file +#endif // CLOUD_FORCE_PUSH_STRATEGY_H \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_merge_strategy.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_merge_strategy.cpp index 15df052a88e631b3efe339903c5cc78a3020a133..9b8755fd1e59570030eb7e3fd8069ec1f9466ee0 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_merge_strategy.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_merge_strategy.cpp @@ -18,8 +18,11 @@ namespace DistributedDB { OpType CloudMergeStrategy::TagSyncDataStatus(bool existInLocal, LogInfo &localInfo, LogInfo &cloudInfo) { + bool isCloudDelete = IsDelete(cloudInfo); + bool isLocalDelete = IsDelete(localInfo); if (!existInLocal) { - if ((cloudInfo.flag & 0x1) == 1) { + // when cloud data is deleted, we think it is different data + if (isCloudDelete) { return OpType::NOT_HANDLE; } return OpType::INSERT; @@ -27,14 +30,16 @@ OpType CloudMergeStrategy::TagSyncDataStatus(bool existInLocal, LogInfo &localIn OpType type = OpType::NOT_HANDLE; if (localInfo.timestamp > cloudInfo.timestamp) { if (localInfo.cloudGid.empty()) { - type = OpType::ONLY_UPDATE_GID; + type = isCloudDelete ? OpType::NOT_HANDLE : OpType::ONLY_UPDATE_GID; + } else { + type = isCloudDelete ? OpType::CLEAR_GID : type; } return type; } - if ((cloudInfo.flag & 0x1) == 1) { - type = IsDelete(localInfo) ? OpType::NOT_HANDLE : OpType::DELETE; + if (isCloudDelete) { + type = isLocalDelete ? OpType::UPDATE_TIMESTAMP : OpType::DELETE; } else { - type = IsDelete(localInfo) ? OpType::INSERT : OpType::UPDATE; + type = isLocalDelete ? OpType::INSERT : OpType::UPDATE; } return type; } diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_strategy.h b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_strategy.h index 3b4f0bcb1bae7b63099be21c318f911a57085e91..2d0fd48b0459d75d071ccb97a2aa15d35d4e3c72 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_strategy.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_strategy.h @@ -45,7 +45,7 @@ public: return false; } - bool IsDelete(const LogInfo &info) + static bool IsDelete(const LogInfo &info) { return (info.flag & 0x1) == 1; } diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer.cpp index 87ed5afd7fdcdd4233f31c5c509cb99ffaa8c3c6..69da43a39809fcf2f68db4aedf7a15ae3fac8427 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer.cpp @@ -16,7 +16,6 @@ #include #include -#include #include "cloud/cloud_db_constant.h" #include "cloud/cloud_storage_utils.h" @@ -43,7 +42,8 @@ CloudSyncer::CloudSyncer(std::shared_ptr storageProxy) closed_(false), timerId_(0u), heartBeatCount_(0), - failedHeartBeatCount_(0) + failedHeartBeatCount_(0), + syncCallbackCount_(0) { } @@ -114,12 +114,24 @@ void CloudSyncer::Close() for (auto &info: infoList) { info.status = ProcessStatus::FINISHED; info.errCode = -E_DB_CLOSED; - ProcessNotifier notifier; + ProcessNotifier notifier(this); notifier.Init(info.table, info.devices); notifier.NotifyProcess(info, {}, true); LOGI("[CloudSyncer] finished taskId %" PRIu64 " errCode %d", info.taskId, info.errCode); } storageProxy_->Close(); + WaitAllSyncCallbackTaskFinish(); +} + +CloudSyncer::ProcessNotifier::ProcessNotifier(CloudSyncer *syncer) + : syncer_(syncer) +{ + RefObject::IncObjRef(syncer_); +} + +CloudSyncer::ProcessNotifier::~ProcessNotifier() +{ + RefObject::DecObjRef(syncer_); } void CloudSyncer::ProcessNotifier::Init(const std::vector &tableName, @@ -182,8 +194,16 @@ void CloudSyncer::ProcessNotifier::NotifyProcess(const CloudTaskInfo &taskInfo, if (!callback) { return; } - int errCode = RuntimeContext::GetInstance()->ScheduleTask([callback, currentProcess]() { + CloudSyncer *syncer = syncer_; + if (syncer == nullptr) { + return; // should not happen + } + RefObject::IncObjRef(syncer); + syncer->IncSyncCallbackTaskCount(); + int errCode = RuntimeContext::GetInstance()->ScheduleTask([callback, currentProcess, syncer]() { callback(currentProcess); + syncer->DecSyncCallbackTaskCount(); + RefObject::DecObjRef(syncer); LOGD("[ProcessNotifier] notify process finish"); }); if (errCode != E_OK) { @@ -218,7 +238,6 @@ void CloudSyncer::DoSyncIfNeed() if (closed_) { return; } - std::lock_guard lock(syncMutex_); // get taskId from queue TaskId triggerTaskId; { @@ -242,6 +261,7 @@ void CloudSyncer::DoSyncIfNeed() int CloudSyncer::DoSync(TaskId taskId) { + std::lock_guard lock(syncMutex_); CloudTaskInfo taskInfo; { std::lock_guard autoLock(queueLock_); @@ -264,27 +284,9 @@ int CloudSyncer::DoSync(TaskId taskId) return errCode; } -int CloudSyncer::DoSyncInner(const CloudTaskInfo &taskInfo, const bool &needUpload) +int CloudSyncer::DoUploadInNeed(const CloudTaskInfo &taskInfo, const bool needUpload) { int errCode = E_OK; - for (size_t i = 0; i < taskInfo.table.size(); ++i) { - LOGD("[CloudSyncer] try download table, index: %zu", i + 1); - errCode = CheckTaskIdValid(taskInfo.taskId); - if (errCode != E_OK) { - LOGE("[CloudSyncer] task is invalid, abort sync"); - return errCode; - } - { - std::lock_guard autoLock(contextLock_); - currentContext_.tableName = taskInfo.table[i]; - } - errCode = DoDownload(taskInfo.taskId); - if (errCode != E_OK) { - LOGE("[CloudSyncer] download failed %d", errCode); - return errCode; - } - } - if (needUpload) { errCode = storageProxy_->StartTransaction(); if (errCode != E_OK) { @@ -307,6 +309,11 @@ int CloudSyncer::DoSyncInner(const CloudTaskInfo &taskInfo, const bool &needUplo LOGE("[CloudSyncer] upload failed %d", errCode); break; } + errCode = SaveCloudWaterMark(taskInfo.table[i]); + if (errCode != E_OK) { + LOGE("[CloudSyncer] Can not save cloud water mark after uploading %d", errCode); + return errCode; + } } if (errCode == E_OK) { storageProxy_->Commit(); @@ -317,8 +324,43 @@ int CloudSyncer::DoSyncInner(const CloudTaskInfo &taskInfo, const bool &needUplo return errCode; } +int CloudSyncer::DoSyncInner(const CloudTaskInfo &taskInfo, const bool needUpload) +{ + int errCode = E_OK; + for (size_t i = 0; i < taskInfo.table.size(); ++i) { + LOGD("[CloudSyncer] try download table, index: %zu", i + 1); + errCode = CheckTaskIdValid(taskInfo.taskId); + if (errCode != E_OK) { + LOGE("[CloudSyncer] task is invalid, abort sync"); + return errCode; + } + { + std::lock_guard autoLock(contextLock_); + currentContext_.tableName = taskInfo.table[i]; + } + errCode = DoDownload(taskInfo.taskId); + if (errCode != E_OK) { + LOGE("[CloudSyncer] download failed %d", errCode); + return errCode; + } + if (!needUpload) { + errCode = SaveCloudWaterMark(taskInfo.table[i]); + if (errCode != E_OK) { + LOGE("[CloudSyncer] Can not save cloud water mark after downloading %d", errCode); + return errCode; + } + } + } + + return DoUploadInNeed(taskInfo, needUpload); +} + void CloudSyncer::DoFinished(TaskId taskId, int errCode, const InnerProcessInfo &processInfo) { + { + std::lock_guard autoLock(queueLock_); + taskQueue_.remove(taskId); + } std::shared_ptr notifier = nullptr; { // check current task is running or not @@ -364,26 +406,26 @@ static int GetCloudPkVals(VBucket &datum, const std::vector &pkColN std::vector &cloudPkVals) { if (!cloudPkVals.empty()) { - LOGE("Output paramater should be empty"); + LOGE("[CloudSyncer] Output paramater should be empty"); return -E_INVALID_ARGS; } if (pkColNames.size() == 1 && pkColNames[0] == CloudDbConstant::ROW_ID_FIELD_NAME) { // if data don't have primary key, then use rowID as value - cloudPkVals.emplace_back(std::move(dataKey)); + cloudPkVals.push_back(dataKey); return E_OK; } for (const auto &pkColName : pkColNames) { auto iter = datum.find(pkColName); if (iter == datum.end()) { - LOGE("Cloud data do not contain expected primary field value"); + LOGE("[CloudSyncer] Cloud data do not contain expected primary field value"); return -E_CLOUD_ERROR; } - cloudPkVals.push_back(datum[pkColName]); + cloudPkVals.push_back(iter->second); } return E_OK; } -static int SaveChangedtData(VBucket &datum, ChangedData &changedData, DataInfoWithLog &localInfo, ChangeType type) +static int SaveChangedDataByType(VBucket &datum, ChangedData &changedData, DataInfoWithLog &localInfo, ChangeType type) { int ret = E_OK; std::vector cloudPkVals; @@ -399,43 +441,41 @@ static int SaveChangedtData(VBucket &datum, ChangedData &changedData, DataInfoWi return E_OK; } -static bool shouldSaveData(const LogInfo &localLogInfo, const LogInfo &cloudLogInfo) +static bool NeedSaveData(const LogInfo &localLogInfo, const LogInfo &cloudLogInfo) { // if timeStamp, write timestamp, cloudGid are all the same, // we thought that the datum is mostly be the same between cloud and local // However, there are still slightly possibility that it may be created from different device, // So, during the strategy policy [i.e. TagSyncDataStatus], the datum was tagged as UPDATE // But we won't notify the datum - if (localLogInfo.timestamp == cloudLogInfo.timestamp && + bool isSame = localLogInfo.timestamp == cloudLogInfo.timestamp && localLogInfo.wTimestamp == cloudLogInfo.wTimestamp && - localLogInfo.cloudGid == cloudLogInfo.cloudGid) { - return false; - } - return true; + localLogInfo.cloudGid == cloudLogInfo.cloudGid; + return !isSame; } -int CloudSyncer::SaveChangedData(DownloadData &downloadData, int dataIndex, DataInfoWithLog &localInfo, - LogInfo &cloudLogInfo, ChangedData &changedData, std::vector &InsertDataNoPrimaryKeys) +int CloudSyncer::SaveChangedData(SyncParam ¶m, int dataIndex, DataInfo &dataInfo, + std::vector &InsertDataNoPrimaryKeys) { // For no primary key situation, - if (downloadData.opType[dataIndex] == OpType::INSERT && changedData.field.size() == 1 && - changedData.field[0] == CloudDbConstant::ROW_ID_FIELD_NAME) { + if (param.downloadData.opType[dataIndex] == OpType::INSERT && param.changedData.field.size() == 1 && + param.changedData.field[0] == CloudDbConstant::ROW_ID_FIELD_NAME) { InsertDataNoPrimaryKeys.push_back(dataIndex); return E_OK; } - switch (downloadData.opType[dataIndex]) { + switch (param.downloadData.opType[dataIndex]) { case OpType::INSERT: - return SaveChangedtData( - downloadData.data[dataIndex], changedData, localInfo, ChangeType::OP_INSERT); + return SaveChangedDataByType( + param.downloadData.data[dataIndex], param.changedData, dataInfo.localInfo, ChangeType::OP_INSERT); case OpType::UPDATE: - if (shouldSaveData(localInfo.logInfo, cloudLogInfo)) { - return SaveChangedtData( - downloadData.data[dataIndex], changedData, localInfo, ChangeType::OP_UPDATE); + if (NeedSaveData(dataInfo.localInfo.logInfo, dataInfo.cloudLogInfo)) { + return SaveChangedDataByType( + param.downloadData.data[dataIndex], param.changedData, dataInfo.localInfo, ChangeType::OP_UPDATE); } break; case OpType::DELETE: - return SaveChangedtData( - downloadData.data[dataIndex], changedData, localInfo, ChangeType::OP_DELETE); + return SaveChangedDataByType( + param.downloadData.data[dataIndex], param.changedData, dataInfo.localInfo, ChangeType::OP_DELETE); default: break; } @@ -458,7 +498,9 @@ static LogInfo GetCloudLogInfo(VBucket &datum) cloudLogInfo.cloudGid = std::get(datum[CloudDbConstant::GID_FIELD]); return cloudLogInfo; } - +/** + * UpdateChangedData will be used for Insert case, which we can only get rowid after we saved data in db. +*/ static void UpdateChangedData( DownloadData &downloadData, const std::vector &InsertDataNoPrimaryKeys, ChangedData &changedData) { @@ -473,28 +515,42 @@ static void UpdateChangedData( static void TagAsset(AssetOpType flag, AssetStatus status, Asset &asset, Assets &res) { - asset.flag = static_cast(flag); + if (asset.status == static_cast(AssetStatus::DELETE)) { + asset.flag = static_cast(AssetOpType::DELETE); + } else { + asset.flag = static_cast(flag); + } asset.status = static_cast(status); Timestamp timestamp; OS::GetCurrentSysTimeInMicrosecond(timestamp); - asset.timestamp = timestamp / CloudDbConstant::TEN_THOUSAND; + asset.timestamp = static_cast(timestamp / CloudDbConstant::TEN_THOUSAND); res.push_back(asset); } -static void TagAssets(AssetOpType flag, AssetStatus status, Assets &assets, Assets &res) +static void TagAssetWithNormalStatus(const bool isNormalStatus, AssetOpType flag, Asset &asset, Assets &res) +{ + if (isNormalStatus) { + TagAsset(flag, AssetStatus::NORMAL, asset, res); + return; + } + TagAsset(flag, AssetStatus::DOWNLOADING, asset, res); +} + +static void TagAssetsWithNormalStatus(const bool isNormalStatus, AssetOpType flag, Assets &assets, Assets &res) { for (Asset &asset : assets) { - TagAsset(flag, status, asset, res); + TagAssetWithNormalStatus(isNormalStatus, flag, asset, res); } } template -static bool IsDataContainField(const std::string &assetFieldName, VBucket &data) +static bool IsDataContainField(const std::string &assetFieldName, const VBucket &data) { auto assetIter = data.find(assetFieldName); if (assetIter == data.end()) { return false; } + // When type of Assets is not Nil but a vector which size is 0, we think data is not contain this field. if (assetIter->second.index() == TYPE_INDEX) { if (std::get(assetIter->second).empty()) { return false; @@ -506,8 +562,9 @@ static bool IsDataContainField(const std::string &assetFieldName, VBucket &data) return true; } -// AssetOpType and AssetStatus will be tagged, assets to be changed will be returned -static Assets TagAsset(const std::string &assetFieldName, VBucket &coveredData, VBucket &beCoveredData) +// AssetOpType and AssetStatus will be tagged, assets to be changed will be returned +static Assets TagAsset(const std::string &assetFieldName, VBucket &coveredData, VBucket &beCoveredData, + bool setNormalStatus) { Assets res = {}; bool beCoveredHasAsset = IsDataContainField(assetFieldName, beCoveredData) || @@ -515,15 +572,22 @@ static Assets TagAsset(const std::string &assetFieldName, VBucket &coveredData, bool coveredHasAsset = IsDataContainField(assetFieldName, coveredData); if (!beCoveredHasAsset) { if (!coveredHasAsset) { - LOGD("Both data do not contain certain asset field"); + LOGD("[CloudSyncer] Both data do not contain certain asset field"); return res; } - LOGD("coveredData will be regarded as insert"); - TagAsset(AssetOpType::INSERT, AssetStatus::DOWNLOADING, std::get(coveredData[assetFieldName]), res); + TagAssetWithNormalStatus( + setNormalStatus, AssetOpType::INSERT, std::get(coveredData[assetFieldName]), res); return res; } if (!coveredHasAsset) { - TagAsset(AssetOpType::DELETE, AssetStatus::DOWNLOADING, std::get(beCoveredData[assetFieldName]), res); + if (beCoveredData[assetFieldName].index() == TYPE_INDEX) { + TagAssetWithNormalStatus(setNormalStatus, AssetOpType::DELETE, + std::get(beCoveredData[assetFieldName]), res); + } + if (beCoveredData[assetFieldName].index() == TYPE_INDEX) { + TagAssetsWithNormalStatus(setNormalStatus, AssetOpType::DELETE, + std::get(beCoveredData[assetFieldName]), res); + } return res; } Asset &covered = std::get(coveredData[assetFieldName]); @@ -539,29 +603,20 @@ static Assets TagAsset(const std::string &assetFieldName, VBucket &coveredData, beCovered = beCoveredDataInAssets[0]; } if (covered.name != beCovered.name) { - TagAsset(AssetOpType::INSERT, AssetStatus::DOWNLOADING, covered, res); - TagAsset(AssetOpType::DELETE, AssetStatus::DOWNLOADING, beCovered, res); + TagAssetWithNormalStatus(setNormalStatus, AssetOpType::INSERT, covered, res); + TagAssetWithNormalStatus(setNormalStatus, AssetOpType::DELETE, beCovered, res); return res; } if (covered.hash != beCovered.hash) { - TagAsset(AssetOpType::UPDATE, AssetStatus::DOWNLOADING, covered, res); + TagAssetWithNormalStatus(setNormalStatus, AssetOpType::UPDATE, covered, res); } return res; } -static std::unordered_map GenAssetsMap(Assets &assets) -{ - std::unordered_map assetsMap; - for (size_t i = 0; i < assets.size(); i++) { - assetsMap[assets[i].name] = i; - } - return assetsMap; -} - // AssetOpType and AssetStatus will be tagged, assets to be changed will be returned // use VBucket rather than Type because we need to check whether it is empty static Assets TagAssets(const std::string &assetFieldName, VBucket &coveredData, VBucket &beCoveredData, - bool WriteToCoveredData) + bool setNormalStatus) { Assets res = {}; bool beCoveredHasAssets = IsDataContainField(assetFieldName, beCoveredData); @@ -571,57 +626,97 @@ static Assets TagAssets(const std::string &assetFieldName, VBucket &coveredData, return res; } // all the element in assets will be set to INSERT - TagAssets(AssetOpType::INSERT, AssetStatus::DOWNLOADING, std::get(coveredData[assetFieldName]), res); + TagAssetsWithNormalStatus(setNormalStatus, + AssetOpType::INSERT, std::get(coveredData[assetFieldName]), res); return res; } if (!coveredHasAssets) { // all the element in assets will be set to DELETE - TagAssets(AssetOpType::DELETE, AssetStatus::DOWNLOADING, std::get(beCoveredData[assetFieldName]), res); - if (WriteToCoveredData) { - LOGD("Write assets to be deleted from beCoveredData to CoveredData"); - coveredData[assetFieldName] = res; - } + TagAssetsWithNormalStatus(setNormalStatus, + AssetOpType::DELETE, std::get(beCoveredData[assetFieldName]), res); + coveredData[assetFieldName] = res; return res; } Assets &covered = std::get(coveredData[assetFieldName]); Assets &beCovered = std::get(beCoveredData[assetFieldName]); - std::unordered_map CoveredAssetsMap = GenAssetsMap(covered); + std::map coveredAssetsIndexMap = CloudStorageUtils::GenAssetsIndexMap(covered); for (Asset &beCoveredAsset : beCovered) { - auto it = CoveredAssetsMap.find(beCoveredAsset.name); - if (it == CoveredAssetsMap.end()) { - TagAsset(AssetOpType::DELETE, AssetStatus::DOWNLOADING, beCoveredAsset, res); - if (WriteToCoveredData) { - std::get(coveredData[assetFieldName]).push_back(beCoveredAsset); - } + auto it = coveredAssetsIndexMap.find(beCoveredAsset.name); + if (it == coveredAssetsIndexMap.end()) { + TagAssetWithNormalStatus(setNormalStatus, AssetOpType::DELETE, beCoveredAsset, res); + std::get(coveredData[assetFieldName]).push_back(beCoveredAsset); continue; } Asset &coveredAsset = covered[it->second]; if (beCoveredAsset.hash != coveredAsset.hash) { - TagAsset(AssetOpType::UPDATE, AssetStatus::DOWNLOADING, coveredAsset, res); + TagAssetWithNormalStatus(setNormalStatus, AssetOpType::UPDATE, coveredAsset, res); + } else { + res.push_back(coveredAsset); } // Erase element which has been handled, remaining element will be set to Insert - CoveredAssetsMap.erase(it); - // flag in Asset is defaultly set to NoChange, so we just continue - continue; + coveredAssetsIndexMap.erase(it); + // flag in Asset is defaultly set to NoChange, so we just go to next iteration } - for (auto &noHandledAssetKvPair : CoveredAssetsMap) { - TagAsset(AssetOpType::INSERT, AssetStatus::DOWNLOADING, covered[noHandledAssetKvPair.second], res); + for (const auto &noHandledAssetKvPair : coveredAssetsIndexMap) { + TagAssetWithNormalStatus(setNormalStatus, AssetOpType::INSERT, covered[noHandledAssetKvPair.second], res); } return res; } -bool CloudSyncer::ShouldProcessAssets() +bool CloudSyncer::IsDataContainDuplicateAsset(const std::vector &assetFields, VBucket &data) +{ + for (auto &assetField : assetFields) { + if (assetField.type == TYPE_INDEX && data[assetField.colName].index() == TYPE_INDEX) { + if (CloudStorageUtils::IsAssetsContainDuplicateAsset(std::get(data[assetField.colName]))) { + return true; + } + } + } + return false; +} + +bool CloudSyncer::IsDataContainAssets() { std::lock_guard autoLock(contextLock_); - if (currentContext_.assetFields[currentContext_.tableName].empty()) { - LOGI("Current table do not contain assets, thereby we needn't download assets"); + bool hasTable = (currentContext_.assetFields.find(currentContext_.tableName) != currentContext_.assetFields.end()); + if (!hasTable) { + LOGE("[CloudSyncer] failed to get assetFields, because tablename doesn't exit in currentContext, %d.", + -E_INTERNAL_ERROR); + } + if (hasTable && currentContext_.assetFields[currentContext_.tableName].empty()) { + LOGI("[CloudSyncer] Current table do not contain assets, thereby we needn't download assets"); return false; } return true; } -std::map CloudSyncer::TagAssetsInSingleRecord(VBucket &CoveredData, VBucket &BeCoveredData, - bool WriteToCoveredData) +void CloudSyncer::IncSyncCallbackTaskCount() +{ + std::lock_guard autoLock(syncCallbackMutex_); + syncCallbackCount_++; +} + +void CloudSyncer::DecSyncCallbackTaskCount() +{ + { + std::lock_guard autoLock(syncCallbackMutex_); + syncCallbackCount_--; + } + syncCallbackCv_.notify_all(); +} + +void CloudSyncer::WaitAllSyncCallbackTaskFinish() +{ + std::unique_lock uniqueLock(syncCallbackMutex_); + LOGD("[CloudSyncer] Begin wait all callback task finish"); + syncCallbackCv_.wait(uniqueLock, [this]() { + return syncCallbackCount_ <= 0; + }); + LOGD("[CloudSyncer] End wait all callback task finish"); +} + +std::map CloudSyncer::TagAssetsInSingleRecord(VBucket &coveredData, VBucket &beCoveredData, + bool setNormalStatus) { // Define a map to store the result std::map res = {}; @@ -632,27 +727,30 @@ std::map CloudSyncer::TagAssetsInSingleRecord(VBucket &Cove } // For every column contain asset or assets, assetFields are in context for (const Field &assetField : assetFields) { - res[assetField.colName] = TagAssetsInSingleCol(CoveredData, BeCoveredData, assetField, WriteToCoveredData); + Assets assets = TagAssetsInSingleCol(coveredData, beCoveredData, assetField, setNormalStatus); + if (!assets.empty()) { + res[assetField.colName] = assets; + } } return res; } Assets CloudSyncer::TagAssetsInSingleCol( - VBucket &CoveredData, VBucket &BeCoveredData, const Field &assetField, bool WriteToCoveredData) -{ + VBucket &coveredData, VBucket &beCoveredData, const Field &assetField, bool setNormalStatus) +{ // Define a list to store the tagged result Assets assets = {}; switch (assetField.type) { case TYPE_INDEX: { - assets = TagAssets(assetField.colName, CoveredData, BeCoveredData, WriteToCoveredData); + assets = TagAssets(assetField.colName, coveredData, beCoveredData, setNormalStatus); break; } case TYPE_INDEX: { - assets = TagAsset(assetField.colName, CoveredData, BeCoveredData); + assets = TagAsset(assetField.colName, coveredData, beCoveredData, setNormalStatus); break; } default: - LOGW("Meet an unexpected type %d", assetField.type); + LOGW("[CloudSyncer] Meet an unexpected type %d", assetField.type); break; } return assets; @@ -677,7 +775,7 @@ int CloudSyncer::FillCloudAssets( return E_OK; } -int CloudSyncer::HandleDownloadResult(const std::string &tableName, std::string gid, +int CloudSyncer::HandleDownloadResult(const std::string &tableName, const std::string &gid, std::map &DownloadResult, bool setAllNormal) { VBucket normalAssets; @@ -699,7 +797,7 @@ int CloudSyncer::HandleDownloadResult(const std::string &tableName, std::string failedAssetsList.push_back(asset); } if (static_cast(asset.status) == AssetStatus::DOWNLOADING) { - LOGW("Asset status should not be DOWNLOADING after download operation"); + LOGW("[CloudSyncer] Asset status should not be DOWNLOADING after download operation"); } } if (!normalAssetsList.empty()) { @@ -729,42 +827,58 @@ static ChangeType OpTypeToChangeType(OpType strategy) int CloudSyncer::CloudDbDownloadAssets(InnerProcessInfo &info, DownloadList &downloadList, bool willHandleResult, ChangedData &changedAssets) { - for (auto &assetsDownloadInfo : downloadList) { - std::string gid = std::get<0>(assetsDownloadInfo); - Type primaryKey = std::get<1>(assetsDownloadInfo); - OpType strategy = std::get<2>(assetsDownloadInfo); - std::map assets = std::get<3>(assetsDownloadInfo); + int downloadStatus = E_OK; + for (size_t i = 0; i < downloadList.size(); i++) { + std::string gid = std::get<0>(downloadList[i]); // 0 means gid is the first element in assetsInfo + Type primaryKey = std::get<1>(downloadList[i]); // 1 means primaryKey is the second element in assetsInfo + OpType strategy = std::get<2>(downloadList[i]); // 2 means strategy is the third element in assetsInfo + // 3 means assets info [colName, assets] is the forth element in downloadList[i] + std::map assets = std::get<3>(downloadList[i]); + std::map downloadAssets(assets); + CloudStorageUtils::EraseNoChangeAsset(downloadAssets); // Download data (include deleting) - int errorCode = cloudDB_.Download(info.tableName, gid, primaryKey, assets); - if (!willHandleResult || assets.empty()) { + if (downloadAssets.empty()) { continue; } + int errorCode = cloudDB_.Download(info.tableName, gid, primaryKey, downloadAssets); + if (errorCode == -E_NOT_SET) { + info.downLoadInfo.failCount += (downloadList.size() - i); + info.downLoadInfo.successCount -= (downloadList.size() - i); + return -E_NOT_SET; + } + changedAssets.primaryData[OpTypeToChangeType(strategy)].push_back({primaryKey}); + if (!willHandleResult) { + continue; + } + CloudStorageUtils::MergeDownloadAsset(downloadAssets, assets); // Process result of each asset if (errorCode != E_OK) { // if not OK, update process info and handle download result seperately - info.downLoadInfo.failCount++; - info.downLoadInfo.successCount--; int ret = HandleDownloadResult(info.tableName, gid, assets, false); if (ret != E_OK) { + info.downLoadInfo.failCount += (downloadList.size() - i); + info.downLoadInfo.successCount -= (downloadList.size() - i); return ret; } + downloadStatus = downloadStatus == E_OK ? errorCode : downloadStatus; + info.downLoadInfo.failCount++; + info.downLoadInfo.successCount--; continue; } - // if success, update ChangedData && Write every attribute of asset into database - // All status will be set to NORMAL(0) - changedAssets.primaryData[OpTypeToChangeType(strategy)].push_back({primaryKey}); int ret = HandleDownloadResult(info.tableName, gid, assets, true); if (ret != E_OK) { + info.downLoadInfo.failCount += (downloadList.size() - i); + info.downLoadInfo.successCount -= (downloadList.size() - i); return ret; } } - return E_OK; + return downloadStatus; } -int CloudSyncer::DownloadNotifyAssets(InnerProcessInfo &info, std::vector &pKColNames, +int CloudSyncer::DownloadAssets(InnerProcessInfo &info, const std::vector &pKColNames, ChangedData &changedAssets) { - if (!ShouldProcessAssets()) { + if (!IsDataContainAssets()) { return E_OK; } // update changed data info @@ -786,16 +900,13 @@ int CloudSyncer::DownloadNotifyAssets(InnerProcessInfo &info, std::vector CloudSyncer::GetAssetsFromVBucket(VBucket &data) return assets; } -static bool IsCompositeKey(std::vector &pKColNames) +static bool IsCompositeKey(const std::vector &pKColNames) { - if (pKColNames.empty()) { - return false; - } - if (pKColNames.size() > 1) { - return true; - } - return false; + return (pKColNames.size() > 1); } -static bool IsNoPrimaryKey(std::vector &pKColNames) +static bool IsNoPrimaryKey(const std::vector &pKColNames) { if (pKColNames.empty()) { return true; @@ -846,7 +951,7 @@ static bool IsNoPrimaryKey(std::vector &pKColNames) return false; } -static bool IsSinglePrimaryKey(std::vector &pKColNames) +static bool IsSinglePrimaryKey(const std::vector &pKColNames) { if (IsCompositeKey(pKColNames) || IsNoPrimaryKey(pKColNames)) { return false; @@ -854,133 +959,166 @@ static bool IsSinglePrimaryKey(std::vector &pKColNames) return true; } -void CloudSyncer::TagStatus(bool isExist, const TableName &tableName, size_t idx, DownloadData &downloadData, - std::vector &pKColNames, DataInfoWithLog &localInfo, LogInfo &cloudLogInfo, VBucket &localAssetInfo, - AssetDownloadList &assetsDownloadList) +static int GetSinglePk(VBucket &datum, const std::vector &pkColNames, int64_t dataKey, Type &pkVal) { - OpType strategy = - currentContext_.strategy->TagSyncDataStatus(isExist, localInfo.logInfo, cloudLogInfo); - downloadData.opType[idx] = strategy; - if (!ShouldProcessAssets()) { - return; - } - std::map assetsMap; - Type prefix; - std::vector pKVals; + std::vector pkVals; int ret = E_OK; - if (IsSinglePrimaryKey(pKColNames)) { - if (strategy == OpType::DELETE) { - ret = GetCloudPkVals(localInfo.primaryKeys, pKColNames, localInfo.logInfo.dataKey, pKVals); - } else { - ret = GetCloudPkVals(downloadData.data[idx], pKColNames, localInfo.logInfo.dataKey, pKVals); + if (IsSinglePrimaryKey(pkColNames)) { + ret = GetCloudPkVals(datum, pkColNames, dataKey, pkVals); + if (ret != E_OK) { + LOGE("[CloudSyncer] Cannot get single primary key for the datum %d", ret); + return ret; + } + pkVal = pkVals[0]; + if (pkVal.index() == TYPE_INDEX) { + LOGE("[CloudSyncer] Invalid primary key type in TagStatus, it's Nil."); + return -E_INTERNAL_ERROR; } - prefix = pKVals[0]; } - switch (strategy) + return E_OK; +} + +int CloudSyncer::TagStatus(bool isExist, SyncParam ¶m, size_t idx, DataInfo &dataInfo, VBucket &localAssetInfo) +{ + OpType strategyOpResult = OpType::NOT_HANDLE; { + std::lock_guard autoLock(contextLock_); + if (!currentContext_.strategy) { + LOGE("[CloudSyncer] strategy has not been set when tag status, %d.", -E_INTERNAL_ERROR); + return -E_INTERNAL_ERROR; + } + strategyOpResult = + currentContext_.strategy->TagSyncDataStatus(isExist, dataInfo.localInfo.logInfo, dataInfo.cloudLogInfo); + } + param.downloadData.opType[idx] = strategyOpResult; + if (!IsDataContainAssets()) { + return E_OK; + } + return TagDownloadAssets(idx, param, dataInfo, localAssetInfo); +} + +int CloudSyncer::TagDownloadAssets(size_t idx, SyncParam ¶m, DataInfo &dataInfo, VBucket &localAssetInfo) +{ + Type prefix; + int ret = E_OK; + OpType strategy = param.downloadData.opType[idx]; + std::map assetsMap; + switch (strategy) { case OpType::INSERT: case OpType::UPDATE: - assetsMap = TagAssetsInSingleRecord(downloadData.data[idx], localAssetInfo, false); - assetsDownloadList.downloadList.push_back( - std::make_tuple(cloudLogInfo.cloudGid, prefix, strategy, assetsMap)); + assetsMap = TagAssetsInSingleRecord(param.downloadData.data[idx], localAssetInfo, false); + ret = GetSinglePk(param.downloadData.data[idx], param.pkColNames, + dataInfo.localInfo.logInfo.dataKey, prefix); + if (ret != E_OK) { + LOGE("Can not get single primary key while strategy is UPDATE/INSERT in TagDownloadAssets %d", ret); + return ret; + } + param.assetsDownloadList.downloadList.push_back( + std::make_tuple(dataInfo.cloudLogInfo.cloudGid, prefix, strategy, assetsMap)); break; case OpType::DELETE: - assetsMap = TagAssetsInSingleRecord(downloadData.data[idx], localAssetInfo, false); - assetsDownloadList.completeDownloadList.push_back( - std::make_tuple(cloudLogInfo.cloudGid, prefix, strategy, assetsMap)); + assetsMap = TagAssetsInSingleRecord(param.downloadData.data[idx], localAssetInfo, false); + ret = GetSinglePk(dataInfo.localInfo.primaryKeys, param.pkColNames, + dataInfo.localInfo.logInfo.dataKey, prefix); + if (ret != E_OK) { + LOGE("Can not get single primary key while strategy is DELETE in TagDownloadAssets %d", ret); + return ret; + } + param.assetsDownloadList.completeDownloadList.push_back( + std::make_tuple(dataInfo.cloudLogInfo.cloudGid, prefix, strategy, assetsMap)); break; case OpType::NOT_HANDLE: case OpType::ONLY_UPDATE_GID: - case OpType::SET_CLOUD_FORCE_PUSH_FLAG_ZERO: {// means upload need this data + case OpType::SET_CLOUD_FORCE_PUSH_FLAG_ZERO: { // means upload need this data // Save the asset info into context - assetsMap = GetAssetsFromVBucket(downloadData.data[idx]); - if (!assetsMap.empty()) { - { - std::lock_guard autoLock(contextLock_); - if (currentContext_.assetsInfo.find(tableName) == currentContext_.assetsInfo.end()) { - currentContext_.assetsInfo[tableName] = {}; - } - currentContext_.assetsInfo[tableName][cloudLogInfo.cloudGid] = assetsMap; + assetsMap = GetAssetsFromVBucket(param.downloadData.data[idx]); + { + std::lock_guard autoLock(contextLock_); + if (currentContext_.assetsInfo.find(param.tableName) == currentContext_.assetsInfo.end()) { + currentContext_.assetsInfo[param.tableName] = {}; } + currentContext_.assetsInfo[param.tableName][dataInfo.cloudLogInfo.cloudGid] = assetsMap; } break; } default: break; } - return; + return E_OK; } -int CloudSyncer::SaveDatum(const std::string &tableName, size_t idx, DownloadData &downloadData, - AssetDownloadList &assetsDownloadList, ChangedData &changedData, std::vector &InsertDataNoPrimaryKeys) +int CloudSyncer::SaveDatum(SyncParam ¶m, size_t idx, std::vector &InsertDataNoPrimaryKeys) { - int ret = CheckDownloadDatum(downloadData.data[idx]); + int ret = CheckDownloadDatum(param.downloadData.data[idx]); if (ret != E_OK) { LOGE("[CloudSyncer] Invalid download data:%d", ret); return ret; } - ModifyCloudDataTime(downloadData.data[idx]); - DataInfoWithLog localInfo; + ModifyCloudDataTime(param.downloadData.data[idx]); + DataInfo dataInfo; VBucket localAssetInfo; bool isExist = true; - ret = storageProxy_->GetInfoByPrimaryKeyOrGid(tableName, downloadData.data[idx], localInfo, localAssetInfo); + ret = storageProxy_->GetInfoByPrimaryKeyOrGid(param.tableName, param.downloadData.data[idx], dataInfo.localInfo, + localAssetInfo); if (ret == -E_NOT_FOUND) { isExist = false; } else if (ret != E_OK) { - LOGE("[CloudSyncer] Cannot get cloud water level from cloud meta data: %d.", ret); + LOGE("[CloudSyncer] Cannot get info by primary key or gid: %d.", ret); return ret; } // Get cloudLogInfo from cloud data - LogInfo cloudLogInfo = GetCloudLogInfo(downloadData.data[idx]); + dataInfo.cloudLogInfo = GetCloudLogInfo(param.downloadData.data[idx]); // Tag datum to get opType - TagStatus(isExist, tableName, idx, downloadData, changedData.field, localInfo, cloudLogInfo, localAssetInfo, - assetsDownloadList); - ret = SaveChangedData(downloadData, idx, localInfo, cloudLogInfo, changedData, InsertDataNoPrimaryKeys); + ret = TagStatus(isExist, param, idx, dataInfo, localAssetInfo); if (ret != E_OK) { - LOGE("[CloudSyncer] Cannot save changed data: %d.", ret); + LOGE("[CloudSyncer] Cannot tag status: %d.", ret); return ret; } - return E_OK; + ret = SaveChangedData(param, idx, dataInfo, InsertDataNoPrimaryKeys); + if (ret != E_OK) { + LOGE("[CloudSyncer] Cannot save changed data: %d.", ret); + } + return ret; } -int CloudSyncer::SaveData(const TableName &tableName, DownloadData &downloadData, - Info &downloadInfo, CloudWaterMark &latestCloudWaterMark, ChangedData &changedData) +int CloudSyncer::SaveData(SyncParam ¶m) { - if (!IsChngDataEmpty(changedData)) { - // changedData.primaryData should have no member inside + if (!IsChngDataEmpty(param.changedData)) { + LOGE("[CloudSyncer] changedData.primaryData should have no member inside."); return -E_INVALID_ARGS; } // Update download btach Info - downloadInfo.batchIndex += 1; - downloadInfo.total += downloadData.data.size(); + param.info.downLoadInfo.batchIndex += 1; + param.info.downLoadInfo.total += param.downloadData.data.size(); int ret = E_OK; std::vector InsertDataNoPrimaryKeys; AssetDownloadList assetsDownloadList; - for (size_t i = 0; i < downloadData.data.size(); i++) { - ret = SaveDatum(tableName, i, downloadData, assetsDownloadList, changedData, InsertDataNoPrimaryKeys); + param.assetsDownloadList = assetsDownloadList; + for (size_t i = 0; i < param.downloadData.data.size(); i++) { + ret = SaveDatum(param, i, InsertDataNoPrimaryKeys); if (ret != E_OK) { - LOGE("Cannot save datum due to error code %d", ret); + LOGE("[CloudSyncer] Cannot save datum due to error code %d", ret); return ret; } } // Save assetsMap into current context { std::lock_guard autoLock(contextLock_); - currentContext_.assetDownloadList = assetsDownloadList; + currentContext_.assetDownloadList = param.assetsDownloadList; } // save the data to the database by batch - ret = storageProxy_->PutCloudSyncData(tableName, downloadData); + ret = storageProxy_->PutCloudSyncData(param.tableName, param.downloadData); if (ret != E_OK) { - downloadInfo.failCount += downloadData.data.size(); + param.info.downLoadInfo.failCount += param.downloadData.data.size(); LOGE("[CloudSyncer] Cannot save the data to databse with error code: %d.", ret); return ret; } - UpdateChangedData(downloadData, InsertDataNoPrimaryKeys, changedData); + UpdateChangedData(param.downloadData, InsertDataNoPrimaryKeys, param.changedData); // Update downloadInfo - downloadInfo.successCount += downloadData.data.size(); + param.info.downLoadInfo.successCount += param.downloadData.data.size(); // Get latest cloudWaterMark - VBucket &lastData = downloadData.data.back(); - latestCloudWaterMark = std::get(lastData[CloudDbConstant::CURSOR_FIELD]); + VBucket &lastData = param.downloadData.data.back(); + param.cloudWaterMark = std::get(lastData[CloudDbConstant::CURSOR_FIELD]); return E_OK; } @@ -999,12 +1137,12 @@ int CloudSyncer::PreCheck(CloudSyncer::TaskId &taskId, const TableName &tableNam } } if (currentContext_.strategy == nullptr) { - LOGE("Strategy has not been initialized"); + LOGE("[CloudSyncer] Strategy has not been initialized"); return -E_INVALID_ARGS; } ret = storageProxy_->CheckSchema(tableName); if (ret != E_OK) { - LOGE("A schema error occurred on the table to be synced, %d", ret); + LOGE("[CloudSyncer] A schema error occurred on the table to be synced, %d", ret); return ret; } return E_OK; @@ -1051,9 +1189,30 @@ int CloudSyncer::NotifyChangedData(ChangedData &&changedData) return ret; } -int CloudSyncer::SaveDataInTransaction(CloudSyncer::TaskId taskId, DownloadData &downloadData, - std::vector &pkColNames, InnerProcessInfo &info, CloudWaterMark &newCloudWaterMark, - ChangedData &changedData) +void CloudSyncer::NotifyInDownload(CloudSyncer::TaskId taskId, SyncParam ¶m) +{ + CloudTaskInfo taskInfo; + { + std::lock_guard autoLock(queueLock_); + taskInfo = cloudTaskInfos_[taskId]; + } + std::lock_guard autoLock(contextLock_); + + if (currentContext_.strategy->JudgeUpload()) { + currentContext_.notifier->NotifyProcess(taskInfo, param.info); + } else { + if (param.isLastBatch) { + param.info.tableStatus = ProcessStatus::FINISHED; + } + if (taskInfo.table.back() == param.tableName && param.isLastBatch) { + currentContext_.notifier->UpdateProcess(param.info); + } else { + currentContext_.notifier->NotifyProcess(taskInfo, param.info); + } + } +} + +int CloudSyncer::SaveDataInTransaction(CloudSyncer::TaskId taskId, SyncParam ¶m) { int ret = storageProxy_->StartTransaction(TransactType::IMMEDIATE); if (ret != E_OK) { @@ -1061,16 +1220,16 @@ int CloudSyncer::SaveDataInTransaction(CloudSyncer::TaskId taskId, DownloadData return ret; } if (!IsModeForcePush(taskId)) { - changedData.tableName = info.tableName; - changedData.field = pkColNames; - changedData.type = ChangedDataType::DATA; + param.changedData.tableName = param.info.tableName; + param.changedData.field = param.pkColNames; + param.changedData.type = ChangedDataType::DATA; } - ret = SaveData(info.tableName, downloadData, info.downLoadInfo, newCloudWaterMark, changedData); + ret = SaveData(param); if (ret != E_OK) { LOGE("[CloudSyncer] cannot save data: %d.", ret); { std::lock_guard autoLock(contextLock_); - currentContext_.notifier->UpdateProcess(info); + currentContext_.notifier->UpdateProcess(param.info); } int rollBackErrorCode = storageProxy_->Rollback(); if (rollBackErrorCode != E_OK) { @@ -1088,38 +1247,29 @@ int CloudSyncer::SaveDataInTransaction(CloudSyncer::TaskId taskId, DownloadData return E_OK; } -int CloudSyncer::SaveDataNotifyProcess(CloudSyncer::TaskId taskId, DownloadData &downloadData, - std::vector &pkColNames, InnerProcessInfo &info, CloudWaterMark &newCloudWaterMark) +int CloudSyncer::SaveDataNotifyProcess(CloudSyncer::TaskId taskId, SyncParam ¶m) { ChangedData changedData; - int ret = SaveDataInTransaction(taskId, downloadData, pkColNames, info, newCloudWaterMark, changedData); + param.changedData = changedData; + int ret = SaveDataInTransaction(taskId, param); if (ret != E_OK) { return ret; } // call OnChange to notify changedData object first time (without Assets) - ret = NotifyChangedData(std::move(changedData)); + ret = NotifyChangedData(std::move(param.changedData)); if (ret != E_OK) { - LOGE("Cannot notify changed data due to error %d", ret); + LOGE("[CloudSyncer] Cannot notify changed data due to error %d", ret); return ret; } // Begin dowloading assets ChangedData changedAssets; - ret = DownloadNotifyAssets(info, pkColNames, changedAssets); + ret = DownloadAssets(param.info, param.pkColNames, changedAssets); + (void)NotifyChangedData(std::move(changedAssets)); if (ret != E_OK) { - LOGE("Someting wrong happened during assets downloading due to error %d", ret); + LOGE("[CloudSyncer] Someting wrong happened during assets downloading due to error %d", ret); return ret; } - bool isUpdateCloudCursor = true; - { - std::lock_guard autoLock(queueLock_); - currentContext_.notifier->NotifyProcess(cloudTaskInfos_[taskId], info); - isUpdateCloudCursor = currentContext_.strategy->JudgeUpdateCursor(); - } - // use the cursor of the last datum in data set to update cloud water mark - if (isUpdateCloudCursor) { - std::lock_guard autoLock(contextLock_); - currentContext_.cloudWaterMarks[info.tableName] = newCloudWaterMark; - } + UpdateCloudWaterMark(param); return E_OK; } @@ -1141,18 +1291,15 @@ void CloudSyncer::NotifyInBatchUpload(const UploadParam &uploadParam, const Inne int CloudSyncer::DoDownload(CloudSyncer::TaskId taskId) { - TableName tableName; - int ret = GetCurrentTableName(tableName); + SyncParam param; + int ret = GetCurrentTableName(param.tableName); if (ret != E_OK) { LOGE("[CloudSyncer] Invalid table name for syncing: %d", ret); return ret; } - InnerProcessInfo info; - info.tableName = tableName; - - std::vector colNames; + param.info.tableName = param.tableName; std::vector assetFields; - ret = storageProxy_->GetPrimaryColNamesWithAssetsFields(tableName, colNames, assetFields); + ret = storageProxy_->GetPrimaryColNamesWithAssetsFields(param.tableName, param.pkColNames, assetFields); if (ret != E_OK) { LOGE("[CloudSyncer] Cannot get primary column names: %d", ret); return ret; @@ -1162,57 +1309,52 @@ int CloudSyncer::DoDownload(CloudSyncer::TaskId taskId) currentContext_.assetFields[currentContext_.tableName] = assetFields; } - CloudWaterMark cloudWaterMark; - ret = storageProxy_->GetCloudWaterMark(tableName, cloudWaterMark); + ret = storageProxy_->GetCloudWaterMark(param.tableName, param.cloudWaterMark); if (ret != E_OK) { LOGE("[CloudSyncer] Cannot get cloud water level from cloud meta data: %d.", ret); return ret; } - return DoDownloadInner(taskId, colNames, info, cloudWaterMark); + return DoDownloadInner(taskId, param); } -int CloudSyncer::DoDownloadInner(CloudSyncer::TaskId taskId, std::vector &colNames, - InnerProcessInfo &info, CloudWaterMark &cloudWaterMark) +int CloudSyncer::DoDownloadInner(CloudSyncer::TaskId taskId, SyncParam ¶m) { // Query data by batch until reaching end and not more data need to be download bool queryEnd = false; - uint32_t retryCnt = 0; - int ret = E_OK; + int ret = PreCheck(taskId, param.info.tableName); + if (ret != E_OK) { + return ret; + } while (!queryEnd) { - ret = PreCheck(taskId, info.tableName); - if (ret != E_OK) { - return ret; - } // Get cloud data after cloud water mark - info.tableStatus = ProcessStatus::PROCESSING; + param.info.tableStatus = ProcessStatus::PROCESSING; DownloadData downloadData; - ret = QueryCloudData(info.tableName, cloudWaterMark, downloadData); + param.downloadData = downloadData; + param.isLastBatch = false; + ret = QueryCloudData(param.info.tableName, param.cloudWaterMark, param.downloadData); if (ret == -E_QUERY_END) { // Won't break here since downloadData may not be null queryEnd = true; + param.isLastBatch = true; } else if (ret != E_OK) { return ret; } - if (downloadData.data.empty()) { - if (ret == E_OK && retryCnt >= CloudDbConstant::MAX_DOWNLOAD_RETRY_TIME) { - LOGE("Cloud Db send empty data but didn't return QUERY_END for too much time"); - return -E_CLOUD_ERROR; - } - if (ret == E_OK && retryCnt < CloudDbConstant::MAX_DOWNLOAD_RETRY_TIME) { - LOGW("Cloud Db return E_OK but send empty data, it should return QUERY_END, retry"); - retryCnt++; + if (param.downloadData.data.empty()) { + if (ret == E_OK) { + LOGD("[CloudSyncer] try to query cloud data use increment water mark"); + UpdateCloudWaterMark(param); continue; } - NotifyInEmptyDownload(taskId, info); + NotifyInEmptyDownload(taskId, param.info); break; } // Save data in transaction, update cloud water mark, notify process and changed data - ret = SaveDataNotifyProcess(taskId, downloadData, colNames, info, cloudWaterMark); + ret = SaveDataNotifyProcess(taskId, param); + (void)NotifyInDownload(taskId, param); if (ret != E_OK) { return ret; } - retryCnt = 0; } return E_OK; } @@ -1291,9 +1433,9 @@ int CloudSyncer::DoBatchUpload(CloudSyncData &uploadData, UploadParam &uploadPar return errCode; } // we need to fill back gid after insert data to cloud. - int ret = storageProxy_->FillCloudGid(uploadData); + int ret = storageProxy_->FillCloudGidAndAsset(OpType::INSERT, uploadData); if (ret != E_OK) { - LOGE("[CloudSyncer] Failed to fill back gid when doing upload, %d.", ret); + LOGE("[CloudSyncer] Failed to fill back when doing upload insData, %d.", ret); return ret; } innerProcessInfo.upLoadInfo.successCount += insertInfo.successCount; @@ -1305,9 +1447,9 @@ int CloudSyncer::DoBatchUpload(CloudSyncData &uploadData, UploadParam &uploadPar if (errCode != E_OK) { return errCode; } - errCode = storageProxy_->FillCloudAssetForUpload(uploadData); + errCode = storageProxy_->FillCloudGidAndAsset(OpType::UPDATE, uploadData); if (errCode != E_OK) { - LOGE("Cannot fill cloud asset during upload procedure"); + LOGE("[CloudSyncer] Failed to fill back when doing upload updData, %d.", errCode); return errCode; } innerProcessInfo.upLoadInfo.successCount += updateInfo.successCount; @@ -1340,21 +1482,7 @@ int CloudSyncer::PutWaterMarkAfterBatchUpload(const std::string &tableName, Uplo LOGE("[CloudSyncer] Cannot set local water mark while Uploading, %d.", errCode); return errCode; } - CloudWaterMark cloudWaterMark; - { - std::lock_guard autoLock(contextLock_); - auto it = currentContext_.cloudWaterMarks.find(tableName); - if (it == currentContext_.cloudWaterMarks.end()) { - LOGD("[CloudSyncer] Not found water mark just return"); - return E_OK; - } - cloudWaterMark = currentContext_.cloudWaterMarks[tableName]; - } - errCode = storageProxy_->PutCloudWaterMark(tableName, cloudWaterMark); - if (errCode != E_OK) { - LOGE("[CloudSyncer] Cannot set cloud water mark while Uploading, %d.", errCode); - } - return errCode; + return E_OK; } int CloudSyncer::DoUpload(CloudSyncer::TaskId taskId, bool lastTable) @@ -1416,7 +1544,8 @@ static AssetOpType StatusToFlag(AssetStatus status) { case AssetStatus::NORMAL: return AssetOpType::NO_CHANGE; default: - LOGW("Unexpected Situation and won't be handled, Caller should ensure that current situation won't occur"); + LOGW("[CloudSyncer] Unexpected Situation and won't be handled" + ", Caller should ensure that current situation won't occur"); return AssetOpType::NO_CHANGE; } } @@ -1424,6 +1553,7 @@ static AssetOpType StatusToFlag(AssetStatus status) { static void StatusToFlagForAsset(Asset &asset) { asset.flag = static_cast(StatusToFlag(static_cast(asset.status))); + asset.status = static_cast(AssetStatus::NORMAL); } static void StatusToFlagForAssets(Assets &assets) @@ -1447,7 +1577,7 @@ static void StatusToFlagForAssetsInRecord(const std::vector &fields, VBuc void CloudSyncer::TagUploadAssets(CloudSyncData &uploadData) { - if (!ShouldProcessAssets()) { + if (!IsDataContainAssets()) { return; } std::map> cloudAssets; @@ -1468,7 +1598,7 @@ void CloudSyncer::TagUploadAssets(CloudSyncData &uploadData) // But we need to check for safety auto gidIter = uploadData.updData.extend[i].find(CloudDbConstant::GID_FIELD); if (gidIter == uploadData.updData.extend[i].end()) { - LOGE("Datum to be upload must contain gid"); + LOGE("[CloudSyncer] Datum to be upload must contain gid"); return; } // update data must contain gid, however, we could only pull data after water mark @@ -1484,15 +1614,15 @@ void CloudSyncer::TagUploadAssets(CloudSyncData &uploadData) StatusToFlagForAssetsInRecord(assetFields, uploadData.updData.record[i]); continue; } - for (auto &it : cloudAssets[gid]) { + for (const auto &it : cloudAssets[gid]) { cloudAsset[it.first] = it.second; } (void)TagAssetsInSingleRecord(uploadData.updData.record[i], cloudAsset, true); } } -int CloudSyncer::PreProcessBatchUpload(TaskId taskId, CloudSyncData &uploadData, InnerProcessInfo &innerProcessInfo, - LocalWaterMark &localMark) +int CloudSyncer::PreProcessBatchUpload(TaskId taskId, const InnerProcessInfo &innerProcessInfo, + CloudSyncData &uploadData, LocalWaterMark &localMark) { // Precheck and calculate local water mark which would be updated if batch upload successed. int ret = CheckTaskIdValid(taskId); @@ -1515,6 +1645,24 @@ int CloudSyncer::PreProcessBatchUpload(TaskId taskId, CloudSyncData &uploadData, return ret; } +int CloudSyncer::SaveCloudWaterMark(const TableName &tableName) +{ + CloudWaterMark cloudWaterMark; + { + std::lock_guard autoLock(contextLock_); + if (currentContext_.cloudWaterMarks.find(tableName) == currentContext_.cloudWaterMarks.end()) { + LOGD("[CloudSyncer] Not found water mark just return"); + return E_OK; + } + cloudWaterMark = currentContext_.cloudWaterMarks[tableName]; + } + int errCode = storageProxy_->SetCloudWaterMark(tableName, cloudWaterMark); + if (errCode != E_OK) { + LOGE("[CloudSyncer] Cannot set cloud water mark while Uploading, %d.", errCode); + } + return errCode; +} + void CloudSyncer::SetUploadDataFlag(const TaskId taskId, CloudSyncData& uploadData) { std::lock_guard autoLock(queueLock_); @@ -1543,12 +1691,12 @@ int CloudSyncer::DoUploadInner(const std::string &tableName, UploadParam &upload InnerProcessInfo info; info.tableName = tableName; info.tableStatus = ProcessStatus::PROCESSING; - info.upLoadInfo.total = uploadParam.count; + info.upLoadInfo.total = static_cast(uploadParam.count); uint32_t batchIndex = 0; while (!CheckCloudSyncDataEmpty(uploadData)) { getDataUnfinished = (ret == -E_UNFINISHED); - ret = PreProcessBatchUpload(uploadParam.taskId, uploadData, info, uploadParam.localMark); + ret = PreProcessBatchUpload(uploadParam.taskId, info, uploadData, uploadParam.localMark); if (ret != E_OK) { goto RELEASE_EXIT; } @@ -1565,7 +1713,7 @@ int CloudSyncer::DoUploadInner(const std::string &tableName, UploadParam &upload goto RELEASE_EXIT; } - ClearCloudSyncData(uploadData); + uploadData = CloudSyncData(tableName); if (continueStmtToken == nullptr) { break; @@ -1588,26 +1736,34 @@ RELEASE_EXIT: int CloudSyncer::CheckDownloadDatum(VBucket &datum) { - if (datum.find(CloudDbConstant::GID_FIELD) == datum.end() || - datum.find(CloudDbConstant::CREATE_FIELD) == datum.end() || - datum.find(CloudDbConstant::MODIFY_FIELD) == datum.end() || - datum.find(CloudDbConstant::DELETE_FIELD) == datum.end() || - datum.find(CloudDbConstant::CURSOR_FIELD) == datum.end()) { - LOGE("Cloud data do not contain expected field"); + // type index of field in fields + std::vector> filedAndIndex = { + std::pair(CloudDbConstant::GID_FIELD, TYPE_INDEX), + std::pair(CloudDbConstant::CREATE_FIELD, TYPE_INDEX), + std::pair(CloudDbConstant::MODIFY_FIELD, TYPE_INDEX), + std::pair(CloudDbConstant::DELETE_FIELD, TYPE_INDEX), + std::pair(CloudDbConstant::CURSOR_FIELD, TYPE_INDEX) + }; + + for (size_t i = 0; i < filedAndIndex.size(); i++) { + if (datum.find(filedAndIndex[i].first) == datum.end()) { + LOGE("[CloudSyncer] Cloud data do not contain expected field: %s.", filedAndIndex[i].first.c_str()); return -E_CLOUD_ERROR; } - if (datum[CloudDbConstant::GID_FIELD].index() != TYPE_INDEX || - datum[CloudDbConstant::CREATE_FIELD].index() != TYPE_INDEX || - datum[CloudDbConstant::MODIFY_FIELD].index() != TYPE_INDEX || - datum[CloudDbConstant::DELETE_FIELD].index() != TYPE_INDEX || - datum[CloudDbConstant::CURSOR_FIELD].index() != TYPE_INDEX) { - LOGE("Cloud data do not contain expected type"); + if (datum[filedAndIndex[i].first].index() != static_cast(filedAndIndex[i].second)) { + LOGE("[CloudSyncer] Cloud data's field: %s, doesn't has expected type.", filedAndIndex[i].first.c_str()); return -E_CLOUD_ERROR; } + } + + std::lock_guard autoLock(contextLock_); + if (IsDataContainDuplicateAsset(currentContext_.assetFields[currentContext_.tableName], datum)) { + return -E_CLOUD_ERROR; + } return E_OK; } -int CloudSyncer::QueryCloudData(const std::string &tableName, const CloudWaterMark &cloudWaterMark, +int CloudSyncer::QueryCloudData(const std::string &tableName, CloudWaterMark &cloudWaterMark, DownloadData &downloadData) { VBucket extend = { @@ -1616,15 +1772,22 @@ int CloudSyncer::QueryCloudData(const std::string &tableName, const CloudWaterMa int ret = cloudDB_.Query(tableName, extend, downloadData.data); downloadData.opType.resize(downloadData.data.size()); if (ret == -E_QUERY_END) { - LOGI("[CloudSyncer] Download data from cloud database success and no more data need to be downloaded"); + LOGD("[CloudSyncer] Download data from cloud database success and no more data need to be downloaded"); return -E_QUERY_END; } - if (ret == E_OK) { - LOGI("[CloudSyncer] Download data from cloud database success but still has data to download"); - return E_OK; + if (ret == E_OK && downloadData.data.empty()) { + if (extend[CloudDbConstant::CURSOR_FIELD].index() != TYPE_INDEX) { + LOGE("[CloudSyncer] cursor type is not valid=%d", extend[CloudDbConstant::CURSOR_FIELD].index()); + return -E_CLOUD_ERROR; + } + cloudWaterMark = std::get(extend[CloudDbConstant::CURSOR_FIELD]); + LOGD("[CloudSyncer] Download data is empty, try to use other cursor=%s", cloudWaterMark.c_str()); + return ret; } - LOGE("[CloudSyncer] Download data from cloud database unsuccess %d", ret); - return -E_CLOUD_ERROR; + if (ret != E_OK) { + LOGE("[CloudSyncer] Download data from cloud database unsuccess %d", ret); + } + return ret; } int CloudSyncer::CheckParamValid(const std::vector &devices, SyncMode mode) @@ -1738,16 +1901,12 @@ int CloudSyncer::PrepareSync(TaskId taskId) return -E_DB_CLOSED; } currentContext_.currentTaskId = taskId; - currentContext_.notifier = std::make_shared(); + currentContext_.notifier = std::make_shared(this); currentContext_.strategy = StrategyFactory::BuildSyncStrategy(mode); currentContext_.notifier->Init(tableNames, devices); LOGI("[CloudSyncer] exec taskId %" PRIu64, taskId); } - // remove task id from queue std::lock_guard autoLock(queueLock_); - if (!taskQueue_.empty()) { - taskQueue_.pop_front(); - } cloudTaskInfos_[taskId].status = ProcessStatus::PROCESSING; return E_OK; } @@ -1891,14 +2050,14 @@ int CloudSyncer::CheckCloudSyncDataValid(CloudSyncData uploadData, const std::st (updRecordLen > 0 && updExtendLen > 0 && updRecordLen == updExtendLen) || (delRecordLen > 0 && delExtendLen > 0 && delRecordLen == delExtendLen)); if (!syncDataValid) { - LOGE("upload data is empty but upload count is not zero or upload table name" + LOGE("[CloudSyncer] upload data is empty but upload count is not zero or upload table name" " is not the same as table name of sync data."); return -E_INTERNAL_ERROR; } int64_t syncDataCount = static_cast(insRecordLen) + static_cast(updRecordLen) + static_cast(delRecordLen); if (syncDataCount > count) { - LOGE("Size of a batch of sync data is greater than upload data size."); + LOGE("[CloudSyncer] Size of a batch of sync data is greater than upload data size."); return -E_INTERNAL_ERROR; } @@ -1998,7 +2157,7 @@ int CloudSyncer::CleanCloudData(ClearMode mode, const std::vector & int index = 1; for (const auto &tableName: tableNameList) { LOGD("[CloudSyncer] Start clean cloud water mark. table index: %d.", index); - int ret = storageProxy_->PutCloudWaterMark(tableName, emptyString); + int ret = storageProxy_->SetCloudWaterMark(tableName, emptyString); if (ret != E_OK) { LOGE("[CloudSyncer] failed to put cloud water mark after clean cloud data, %d.", ret); return ret; @@ -2018,13 +2177,15 @@ int CloudSyncer::CleanCloudData(ClearMode mode, const std::vector & storageProxy_->Rollback(); return errCode; } - - errCode = cloudDB_.RemoveLocalAssets(assets); - if (errCode != E_OK) { - LOGE("[Storage Executor] failed to remove local assets, %d.", errCode); - storageProxy_->Rollback(); - return errCode; + if (!assets.empty() && mode == FLAG_AND_DATA) { + errCode = cloudDB_.RemoveLocalAssets(assets); + if (errCode != E_OK) { + LOGE("[Storage Executor] failed to remove local assets, %d.", errCode); + storageProxy_->Rollback(); + return errCode; + } } + storageProxy_->Commit(); return errCode; @@ -2039,4 +2200,18 @@ void CloudSyncer::ModifyCloudDataTime(VBucket &data) data[CloudDbConstant::MODIFY_FIELD] = modifyTime; data[CloudDbConstant::CREATE_FIELD] = createTime; } + +void CloudSyncer::UpdateCloudWaterMark(const SyncParam ¶m) +{ + bool isUpdateCloudCursor = true; + { + std::lock_guard autoLock(queueLock_); + isUpdateCloudCursor = currentContext_.strategy->JudgeUpdateCursor(); + } + // use the cursor of the last datum in data set to update cloud water mark + if (isUpdateCloudCursor) { + std::lock_guard autoLock(contextLock_); + currentContext_.cloudWaterMarks[param.info.tableName] = param.cloudWaterMark; + } +} } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer.h b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer.h index fc614307ffbf37e3d016561395d9365c691786e5..aaf558c58dd0d9f08bfcb3e12555ec11de4b53bd 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer.h @@ -61,14 +61,37 @@ protected: int64_t timeout; std::vector devices; }; + struct DataInfo { + DataInfoWithLog localInfo; + LogInfo cloudLogInfo; + }; struct InnerProcessInfo { std::string tableName; ProcessStatus tableStatus = ProcessStatus::PREPARED; Info downLoadInfo; Info upLoadInfo; }; + struct AssetDownloadList { + // assets in following list will fill STATUS and timestamp after calling downloading + DownloadList downloadList; + // assets in following list won't fill STATUS and timestamp after calling downloading + DownloadList completeDownloadList; + }; + struct SyncParam { + DownloadData downloadData; + ChangedData changedData; + InnerProcessInfo info; + AssetDownloadList assetsDownloadList; + CloudWaterMark cloudWaterMark; + std::vector pkColNames; + std::string tableName; + bool isLastBatch = false; + }; class ProcessNotifier { public: + explicit ProcessNotifier(CloudSyncer *syncer); + ~ProcessNotifier(); + void Init(const std::vector &tableName, const std::vector &devices); void UpdateProcess(const InnerProcessInfo &process); @@ -81,12 +104,7 @@ protected: std::mutex processMutex_; SyncProcess syncProcess_; std::vector devices_; - }; - struct AssetDownloadList { - // assets in following list will fill STATUS and timestamp after calling downloading - DownloadList downloadList; - // assets in following list won't fill STATUS and timestamp after calling downloading - DownloadList completeDownloadList; + CloudSyncer *syncer_; }; struct TaskContext { TaskId currentTaskId = 0u; @@ -113,14 +131,15 @@ protected: int DoSync(TaskId taskId); - int DoSyncInner(const CloudTaskInfo &taskInfo, const bool &needUpload); + int DoSyncInner(const CloudTaskInfo &taskInfo, const bool needUpload); + + int DoUploadInNeed(const CloudTaskInfo &taskInfo, const bool needUpload); void DoFinished(TaskId taskId, int errCode, const InnerProcessInfo &processInfo); virtual int DoDownload(TaskId taskId); - int DoDownloadInner(CloudSyncer::TaskId taskId, std::vector &colNames, - InnerProcessInfo &info, CloudWaterMark &cloudWaterMark); + int DoDownloadInner(CloudSyncer::TaskId taskId, SyncParam ¶m); void NotifyInEmptyDownload(CloudSyncer::TaskId taskId, InnerProcessInfo &info); @@ -142,8 +161,8 @@ protected: void ClearCloudSyncData(CloudSyncData &uploadData); - int PreProcessBatchUpload(TaskId taskId, CloudSyncData &uploadData, InnerProcessInfo &innerProcessInfo, - LocalWaterMark &localMark); + int PreProcessBatchUpload(TaskId taskId, const InnerProcessInfo &innerProcessInfo, + CloudSyncData &uploadData, LocalWaterMark &localMark); int PutWaterMarkAfterBatchUpload(const std::string &tableName, UploadParam &uploadParam); @@ -157,7 +176,7 @@ protected: int CheckDownloadDatum(VBucket &datum); - int QueryCloudData(const std::string &tableName, const CloudWaterMark &cloudWaterMark, DownloadData &downloadData); + int QueryCloudData(const std::string &tableName, CloudWaterMark &cloudWaterMark, DownloadData &downloadData); int CheckTaskIdValid(TaskId taskId); @@ -185,21 +204,18 @@ protected: void SetTaskFailed(TaskId taskId, int errCode); - int SaveDatum(const std::string &tableName, size_t idx, DownloadData &downloadData, - AssetDownloadList &assetsDownloadList, ChangedData &changedData, std::vector &InsertDataNoPrimaryKeys); + int SaveDatum(SyncParam ¶m, size_t idx, std::vector &InsertDataNoPrimaryKeys); - int SaveData(const TableName &tablename, DownloadData &downloadData, - Info &downloadInfo, CloudWaterMark &latestCloudWaterMark, ChangedData &changedData); + int SaveData(SyncParam ¶m); - int SaveDataInTransaction(CloudSyncer::TaskId taskId, DownloadData &downloadData, - std::vector &pkColNames, InnerProcessInfo &info, CloudWaterMark &newCloudWaterMark, - ChangedData &changedData); + void NotifyInDownload(CloudSyncer::TaskId taskId, SyncParam ¶m); - int SaveChangedData(DownloadData &downloadData, int dataIndex, DataInfoWithLog &localLogInfo, - LogInfo &cloudLogInfo, ChangedData &changedData, std::vector &InsertDataNoPrimaryKeys); + int SaveDataInTransaction(CloudSyncer::TaskId taskId, SyncParam ¶m); - int SaveDataNotifyProcess(CloudSyncer::TaskId taskId, DownloadData &downloadData, - std::vector &pkColNames, InnerProcessInfo &info, CloudWaterMark &newCloudWaterMark); + int SaveChangedData(SyncParam ¶m, int dataIndex, DataInfo &dataInfo, + std::vector &InsertDataNoPrimaryKeys); + + int SaveDataNotifyProcess(CloudSyncer::TaskId taskId, SyncParam ¶m); void NotifyInBatchUpload(const UploadParam &uploadParam, const InnerProcessInfo &innerProcessInfo, bool lastBatch); @@ -209,35 +225,48 @@ protected: std::map GetAssetsFromVBucket(VBucket &data); - std::map TagAssetsInSingleRecord(VBucket &CoveredData, VBucket &BeCoveredData, - bool WriteToCoveredData); + std::map TagAssetsInSingleRecord(VBucket &coveredData, VBucket &beCoveredData, + bool setNormalStatus); + + Assets TagAssetsInSingleCol(VBucket &coveredData, VBucket &beCoveredData, const Field &assetField, + bool setNormalStatus); - Assets TagAssetsInSingleCol(VBucket &CoveredData, VBucket &BeCoveredData, const Field &assetField, - bool WriteToCoveredData); + int TagStatus(bool isExist, SyncParam ¶m, size_t idx, DataInfo &dataInfo, VBucket &localAssetInfo); - void TagStatus(bool isExist, const TableName &tableName, size_t idx, DownloadData &downloadData, - std::vector &pKColNames, DataInfoWithLog &localInfo, LogInfo &cloudLogInfo, - VBucket &localAssetInfo, AssetDownloadList &assetsDownloadList); + int TagDownloadAssets(size_t idx, SyncParam ¶m, DataInfo &dataInfo, + VBucket &localAssetInfo); void TagUploadAssets(CloudSyncData &uploadData); int FillCloudAssets(const std::string &tableName, VBucket &normalAssets, VBucket &failedAssets); - int HandleDownloadResult(const std::string &tableName, std::string gid, + int HandleDownloadResult(const std::string &tableName, const std::string &gid, std::map &DownloadResult, bool setAllNormal); - int DownloadNotifyAssets(InnerProcessInfo &info, std::vector &pKColNames, + int DownloadAssets(InnerProcessInfo &info, const std::vector &pKColNames, ChangedData &changedAssets); int CloudDbDownloadAssets(InnerProcessInfo &info, DownloadList &downloadList, bool willHandleResult, ChangedData &changedAssets); - bool ShouldProcessAssets(); + bool IsDataContainAssets(); + + bool IsDataContainDuplicateAsset(const std::vector &assetFields, VBucket &data); + + void IncSyncCallbackTaskCount(); + + void DecSyncCallbackTaskCount(); + + void WaitAllSyncCallbackTaskFinish(); static int CheckParamValid(const std::vector &devices, SyncMode mode); void ModifyCloudDataTime(VBucket &data); + int SaveCloudWaterMark(const TableName &tableName); + + void UpdateCloudWaterMark(const SyncParam ¶m); + std::mutex queueLock_; TaskId currentTaskId_; std::list taskQueue_; @@ -261,6 +290,10 @@ protected: std::condition_variable heartbeatCv_; int32_t heartBeatCount_; std::atomic failedHeartBeatCount_; + + std::mutex syncCallbackMutex_; + std::condition_variable syncCallbackCv_; + int32_t syncCallbackCount_; }; } #endif // CLOUD_SYNCER_H diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/strategy_factory.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/strategy_factory.cpp index e0bcd54552bc71c85b8edbea79859558a177f0bf..39ef7b6f4f5c6b4b5121bf8707d4918c1db522d6 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/strategy_factory.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/strategy_factory.cpp @@ -24,12 +24,10 @@ std::shared_ptr StrategyFactory::BuildSyncStrategy(SyncMode m switch (mode) { case SyncMode::SYNC_MODE_CLOUD_MERGE: return std::make_shared(); -#ifdef MANNUAL_SYNC_AND_CLEAN_CLOUD_DATA case SyncMode::SYNC_MODE_CLOUD_FORCE_PULL: return std::make_shared(); case SyncMode::SYNC_MODE_CLOUD_FORCE_PUSH: return std::make_shared(); -#endif // MANNUAL_SYNC_AND_CLEAN_CLOUD_DATA default: LOGW("[StrategyFactory] Not support mode %d", static_cast(mode)); return std::make_shared(); diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/generic_syncer.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/generic_syncer.cpp index 6ed92a086a60dd50b8aa7ec2727315a08990440b..f9215f1ceeddf7bf96c3ea2922db17c6401c6075 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/generic_syncer.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/generic_syncer.cpp @@ -1024,6 +1024,7 @@ int GenericSyncer::CloseInner(bool isClosedOperation) int GenericSyncer::GetSyncDataSize(const std::string &device, size_t &size) const { uint64_t localWaterMark = 0; + std::shared_ptr metadata = nullptr; { std::lock_guard lock(syncerLock_); if (metadata_ == nullptr || syncInterface_ == nullptr) { @@ -1034,8 +1035,9 @@ int GenericSyncer::GetSyncDataSize(const std::string &device, size_t &size) cons return -E_BUSY; } syncInterface_->IncRefCount(); - metadata_->GetLocalWaterMark(device, localWaterMark); + metadata = metadata_; } + metadata->GetLocalWaterMark(device, localWaterMark); uint32_t expectedMtuSize = 1024u * 1024u; // 1M DataSizeSpecInfo syncDataSizeInfo = {expectedMtuSize, static_cast(MAX_TIMESTAMP)}; std::vector outData; diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/meta_data.h b/kv_store/frameworks/libs/distributeddb/syncer/src/meta_data.h index 19ec075e667e8b74f25017222059e0dc900d7fd1..f3d4a7cbf49604dbcf1e040c9fb15cca265c42a9 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/meta_data.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/meta_data.h @@ -55,7 +55,7 @@ public: void GetTimeOffset(const DeviceID &deviceId, TimeOffset &outValue); - void GetLocalWaterMark(const DeviceID &deviceId, uint64_t &outValue); + virtual void GetLocalWaterMark(const DeviceID &deviceId, uint64_t &outValue); int SaveLocalWaterMark(const DeviceID &deviceId, uint64_t inValue); diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/remote_executor.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/remote_executor.cpp index 96a2420a6353f69a3870962de423d16268ef00a9..1d5753d348ce468b272a5ec4a36651a2ec84e9f9 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/remote_executor.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/remote_executor.cpp @@ -310,6 +310,10 @@ bool RemoteExecutor::CheckParamValid(const std::string &device, uint64_t timeout LOGD("[RemoteExecutor][CheckParamValid] device is empty"); return false; } + if (device.length() > DBConstant::MAX_DEV_LENGTH) { + LOGE("[RemoteExecutor] dev is too long len=%zu", device.length()); + return false; + } ICommunicator *communicator = GetAndIncCommunicator(); if (communicator == nullptr) { return false; diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/single_ver_data_sync.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/single_ver_data_sync.cpp index 5301e977628e74488fa7c0003de3535f5caa926a..0954b3b97c7a565e0d714917d2e66cc7524687ca 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/single_ver_data_sync.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/single_ver_data_sync.cpp @@ -933,7 +933,7 @@ int SingleVerDataSync::DoAbilitySyncIfNeed(SingleVerSyncTaskContext *context, co } else { SendDataAck(context, message, -E_NEED_ABILITY_SYNC, 0); } - return -E_WAIT_NEXT_MESSAGE; + return -E_NEED_ABILITY_SYNC; } } diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/single_ver_sync_engine.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/single_ver_sync_engine.cpp index 764553de551d7af8661dd3065af1022e3fbe0ffa..28f013cdc839e1daa8c3d83b25268318d3169665 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/single_ver_sync_engine.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/single_ver_sync_engine.cpp @@ -62,6 +62,11 @@ void SingleVerSyncEngine::EnableClearRemoteStaleData(bool enable) int SingleVerSyncEngine::StartAutoSubscribeTimer() { + if (syncInterface_->IsSupportSubscribe() == -E_NOT_SUPPORT) { + LOGI("[StartAutoSubscribeTimer] no need to start subscribe timer"); + return E_OK; + } + std::lock_guard lockGuard(timerLock_); if (subscribeTimerId_ > 0) { LOGI("[SingleSyncEngine] subscribeTimerId is already set"); diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/single_ver_sync_state_machine.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/single_ver_sync_state_machine.cpp index efc27dd01a6c7f0646cb1eb8e0850ea47467b486..50e3b429a4ac0d58bfa1a7ec0de377dfca9e0f9a 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/single_ver_sync_state_machine.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/single_ver_sync_state_machine.cpp @@ -276,10 +276,14 @@ const std::vector &SingleVerSyncStateMachine::GetStateSwitchTa int SingleVerSyncStateMachine::PrepareNextSyncTask() { int errCode = StartWatchDog(); - if (errCode != E_OK) { + if (errCode != E_OK && errCode != -E_UNEXPECTED_DATA) { LOGE("[StateMachine][PrepareNextSyncTask] WatchDog start failed,err=%d", errCode); return errCode; } + if (errCode == -E_UNEXPECTED_DATA) { + LOGI("[PrepareNextSyncTask] timer already exists, reset the timer."); + (void)ResetWatchDog(); + } if (currentState_ != State::IDLE && currentState_ != State::SYNC_TASK_FINISHED) { LOGW("[StateMachine][PrepareNextSyncTask] PreSync may get an err, state=%" PRIu8 ",dev=%s", @@ -615,6 +619,7 @@ int SingleVerSyncStateMachine::AbilitySyncRecv(const Message *inMsg) // while recv last notify means ability sync finished,it is better to reset watchDog to avoid timeout. LOGI("[StateMachine][AbilitySyncRecv] ability sync finished,label=%s,dev=%s", dataSync_->GetLabel().c_str(), STR_MASK(context_->GetDeviceId())); + context_->SetRemoteSoftwareVersion(packet->GetSoftwareVersion()); currentRemoteVersionId_ = context_->GetRemoteSoftwareVersionId(); std::lock_guard lock(stateMachineLock_); (void)ResetWatchDog(); diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/sync_engine.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/sync_engine.cpp index f0fd3de90a6dc583e179001f79aa221a1a38840b..ee1c4aaa8eba8574515326aa288f98c7b794c0a3 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/sync_engine.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/sync_engine.cpp @@ -72,11 +72,13 @@ int SyncEngine::Initialize(ISyncInterface *syncInterface, const std::shared_ptr< if ((syncInterface == nullptr) || (metadata == nullptr)) { return -E_INVALID_ARGS; } + syncInterface_ = syncInterface; int errCode = StartAutoSubscribeTimer(); if (errCode != OK) { + syncInterface_ = nullptr; return errCode; } - syncInterface_ = syncInterface; + errCode = InitComunicator(syncInterface); if (errCode != E_OK) { LOGE("[SyncEngine] Init Communicator failed"); @@ -1142,6 +1144,10 @@ bool SyncEngine::CheckDeviceIdValid(const std::string &checkDeviceId, const std: if (checkDeviceId.empty()) { return false; } + if (checkDeviceId.length() > DBConstant::MAX_DEV_LENGTH) { + LOGE("[SyncEngine] dev is too long len=%zu", checkDeviceId.length()); + return false; + } return localDeviceId != checkDeviceId; } diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/sync_task_context.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/sync_task_context.cpp index 6909b163408b96d0e6f97c677cba7c119001d57f..b8fedaaa479eb4229b5365a3fa7b0773e9b9283e 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/sync_task_context.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/sync_task_context.cpp @@ -556,6 +556,7 @@ int SyncTaskContext::TimeOut(TimerId id) void SyncTaskContext::CopyTargetData(const ISyncTarget *target, const TaskParam &taskParam) { + retryTime_ = 0; mode_ = target->GetMode(); status_ = SyncOperation::OP_SYNCING; isNeedRetry_ = SyncTaskContext::NO_NEED_RETRY; diff --git a/kv_store/frameworks/libs/distributeddb/test/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/BUILD.gn index ebed30eea2a7f8b13caaf9e0c7a3b901a3718b26..617a6a043b90fe2e018d75807fea711795f9f8dd 100644 --- a/kv_store/frameworks/libs/distributeddb/test/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/BUILD.gn @@ -326,9 +326,9 @@ ohos_source_set("src_file") { ] external_deps = [ "c_utils:utils", - "hisysevent_native:libhisysevent", - "hitrace_native:hitrace_meter", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", + "hisysevent:libhisysevent", + "hitrace:hitrace_meter", ] part_name = "kv_store" } @@ -359,9 +359,9 @@ template("distributeddb_unittest") { ] external_deps = [ "c_utils:utils", - "hisysevent_native:libhisysevent", - "hitrace_native:hitrace_meter", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", + "hisysevent:libhisysevent", + "hitrace:hitrace_meter", ] } } diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/delegate_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/delegate_fuzzer/BUILD.gn index 6faa07dac8876b165151ea1a6ffcb62c007be5de..5f815d05927c4f4cad333b37f47d09247e7d1150 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/delegate_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/delegate_fuzzer/BUILD.gn @@ -101,7 +101,7 @@ ohos_fuzztest("DelegateFuzzTest") { external_deps = [ "c_utils:utils", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", ] } diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/fileoper_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/fileoper_fuzzer/BUILD.gn index b1312290c00c3c1fea6a12c6fd166784756df138..52aee2424334d968f3f855e57779691c57514bbc 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/fileoper_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/fileoper_fuzzer/BUILD.gn @@ -102,7 +102,7 @@ ohos_fuzztest("FileOperFuzzTest") { external_deps = [ "c_utils:utils", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", ] } diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/importfile_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/importfile_fuzzer/BUILD.gn index 4c9a9639e55ab0aec0cd548850eec26a14cf3a0f..eef7a91d56b039617accd6cd16ae7c4a9c557c4a 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/importfile_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/importfile_fuzzer/BUILD.gn @@ -102,7 +102,7 @@ ohos_fuzztest("ImportFileFuzzTest") { external_deps = [ "c_utils:utils", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", ] } diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/iprocesscommunicator_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/iprocesscommunicator_fuzzer/BUILD.gn index 0493b4436f1b4710af61f41530fafd42cfec39d3..c946920f7d137a17738146b381d83dd672b90c48 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/iprocesscommunicator_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/iprocesscommunicator_fuzzer/BUILD.gn @@ -101,7 +101,7 @@ ohos_fuzztest("IProcessCommunicatorFuzzTest") { external_deps = [ "c_utils:utils", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", ] } diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/kvdelegatemanager_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/kvdelegatemanager_fuzzer/BUILD.gn index 11d3cf89937bf077daece2c8253e9ed7b9655873..c7fb8f27b3bf8f9ec3f9446721617e7d04f8a99a 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/kvdelegatemanager_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/kvdelegatemanager_fuzzer/BUILD.gn @@ -102,7 +102,7 @@ ohos_fuzztest("KvDelegateManagerFuzzTest") { external_deps = [ "c_utils:utils", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", ] } diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/kvstoreresultset_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/kvstoreresultset_fuzzer/BUILD.gn index 66fd0b786077422027c7712ddc7cd3318e8c752b..20a78fd9548ab8f62b6fc4f79cd8d64348d71fd2 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/kvstoreresultset_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/kvstoreresultset_fuzzer/BUILD.gn @@ -102,7 +102,7 @@ ohos_fuzztest("KvStoreResultSetFuzzTest") { external_deps = [ "c_utils:utils", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", ] } diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/nbdelegate_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/nbdelegate_fuzzer/BUILD.gn index 00b3376662b77aa4029e8c7d4d2eba7928f7ad90..474a1d5a6815408f2b504f553fff9f229b881c82 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/nbdelegate_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/nbdelegate_fuzzer/BUILD.gn @@ -101,7 +101,7 @@ ohos_fuzztest("NbDelegateFuzzTest") { external_deps = [ "c_utils:utils", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", ] } diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/parseckeck_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/parseckeck_fuzzer/BUILD.gn index a240626ae5a3cf708943d2b148b1351ae216dc0a..9727e3b5d67d69b4af34620c307d77793657e26a 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/parseckeck_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/parseckeck_fuzzer/BUILD.gn @@ -102,7 +102,7 @@ ohos_fuzztest("ParseCkeckFuzzTest") { external_deps = [ "c_utils:utils", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", ] } diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/query_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/query_fuzzer/BUILD.gn index 3a4fbc8b176a61f93a82a231f884c3b40b9a5ed8..2824f50c8baaa7d93740a0346e101a82094488e7 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/query_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/query_fuzzer/BUILD.gn @@ -101,7 +101,7 @@ ohos_fuzztest("QueryFuzzTest") { external_deps = [ "c_utils:utils", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", ] } diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/rekey_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/rekey_fuzzer/BUILD.gn index 7c967d8481200abefff0d9c87a69fe63b70b1edc..52458c0187a730c83be11fac85f37aa10baeb61b 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/rekey_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/rekey_fuzzer/BUILD.gn @@ -102,7 +102,7 @@ ohos_fuzztest("ReKeyFuzzTest") { external_deps = [ "c_utils:utils", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", ] } diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/relationalstoredelegate_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/relationalstoredelegate_fuzzer/BUILD.gn index c261228ee6e49eb76681953d8665723136f7d897..632298e48a790ef9d183519f1cb507818539d082 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/relationalstoredelegate_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/relationalstoredelegate_fuzzer/BUILD.gn @@ -106,7 +106,7 @@ ohos_fuzztest("RelationalstoredelegateFuzzTest") { external_deps = [ "c_utils:utils", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", ] } diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/relationalstoremanager_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/relationalstoremanager_fuzzer/BUILD.gn index d4b65a80941aa71784b515aae209496ed12ece25..56af80ab891f5b0dd9668056b739ce94e0b6afdd 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/relationalstoremanager_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/relationalstoremanager_fuzzer/BUILD.gn @@ -106,7 +106,7 @@ ohos_fuzztest("RelationalstoremanagerFuzzTest") { external_deps = [ "c_utils:utils", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", ] } diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/schemadelegate_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/schemadelegate_fuzzer/BUILD.gn index 8c192846f0a7def9a472f347d85384167bcc41c2..c4a58b882ee9b05967a5f75bdecffa553726fbe7 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/schemadelegate_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/schemadelegate_fuzzer/BUILD.gn @@ -101,7 +101,7 @@ ohos_fuzztest("SchemaDelegateFuzzTest") { external_deps = [ "c_utils:utils", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", ] } diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/sync_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/sync_fuzzer/BUILD.gn index 522c4797c660653494bd5043ad696d358b673831..7ca919b4d66e28398994a87a9edd47d653c7d0a6 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/sync_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/sync_fuzzer/BUILD.gn @@ -107,7 +107,7 @@ ohos_fuzztest("SyncFuzzTest") { external_deps = [ "c_utils:utils", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", ] } diff --git a/kv_store/frameworks/libs/distributeddb/test/moduletest/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/moduletest/BUILD.gn index d16cccf7fa95561b35a155d632df9c43ab645b2a..9450059715515f842aa9e1d4cb3715c26c4f3052 100644 --- a/kv_store/frameworks/libs/distributeddb/test/moduletest/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/moduletest/BUILD.gn @@ -85,7 +85,7 @@ ohos_moduletest("DistributeddbKvTransactionTest") { ] external_deps = [ "c_utils:utils", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", ] part_name = "datamgr_service" } @@ -110,7 +110,7 @@ ohos_moduletest("DistributeddbKvTransactionPerfTest") { ] external_deps = [ "c_utils:utils", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", ] part_name = "datamgr_service" } @@ -133,7 +133,7 @@ ohos_moduletest("DistributeddbKvConcurrencyCrudTest") { ] external_deps = [ "c_utils:utils", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", ] part_name = "datamgr_service" } @@ -156,7 +156,7 @@ ohos_moduletest("DistributeddbKvBatchCrudTest") { ] external_deps = [ "c_utils:utils", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", ] part_name = "datamgr_service" } @@ -179,7 +179,7 @@ ohos_moduletest("DistributeddbKvCreateTest") { ] external_deps = [ "c_utils:utils", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", ] part_name = "datamgr_service" } @@ -202,7 +202,7 @@ ohos_moduletest("DistributeddbKvCrudTest") { ] external_deps = [ "c_utils:utils", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", ] part_name = "datamgr_service" } @@ -225,7 +225,7 @@ ohos_moduletest("DistributeddbKvObserverTest") { ] external_deps = [ "c_utils:utils", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", ] part_name = "datamgr_service" } @@ -248,7 +248,7 @@ ohos_moduletest("DistributeddbKvObserverSnapTest") { ] external_deps = [ "c_utils:utils", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", ] part_name = "datamgr_service" } @@ -270,7 +270,7 @@ ohos_moduletest("DistributeddbKvBackupTest") { ] external_deps = [ "c_utils:utils", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", ] part_name = "datamgr_service" } @@ -293,7 +293,7 @@ ohos_moduletest("DistributeddbKvRealdelTest") { ] external_deps = [ "c_utils:utils", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", ] part_name = "datamgr_service" } @@ -318,7 +318,7 @@ ohos_moduletest("DistributeddbNbCreateTest") { ] external_deps = [ "c_utils:utils", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", ] part_name = "datamgr_service" } @@ -342,7 +342,7 @@ ohos_moduletest("DistributeddbNbCrudTest") { ] external_deps = [ "c_utils:utils", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", ] part_name = "datamgr_service" } @@ -366,7 +366,7 @@ ohos_moduletest("DistributeddbNbObserverTest") { ] external_deps = [ "c_utils:utils", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", ] part_name = "datamgr_service" } @@ -392,7 +392,7 @@ ohos_moduletest("DistributeddbNbCursorTest") { ] external_deps = [ "c_utils:utils", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", ] part_name = "datamgr_service" } @@ -418,7 +418,7 @@ ohos_moduletest("DistributeddbNbBackupTest") { external_deps = [ "c_utils:utils", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", ] part_name = "datamgr_service" } @@ -443,7 +443,7 @@ ohos_moduletest("DistributeddbNbBatchCrudTest") { ] external_deps = [ "c_utils:utils", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", ] part_name = "datamgr_service" } @@ -468,7 +468,7 @@ ohos_moduletest("DistributeddbNbLocalBatchCrudTest") { ] external_deps = [ "c_utils:utils", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", ] part_name = "datamgr_service" } @@ -492,7 +492,7 @@ ohos_moduletest("DistributeddbNbSchemaDbTest") { ] external_deps = [ "c_utils:utils", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", ] part_name = "datamgr_service" } @@ -517,7 +517,7 @@ ohos_moduletest("DistributeddbNbPredicateQueryTest") { ] external_deps = [ "c_utils:utils", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", ] part_name = "datamgr_service" } @@ -542,7 +542,7 @@ ohos_moduletest("DistributeddbNbPredicateQueryExpandTest") { ] external_deps = [ "c_utils:utils", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", ] part_name = "datamgr_service" } @@ -567,7 +567,7 @@ ohos_moduletest("DistributeddbNbAutolaunchTest") { ] external_deps = [ "c_utils:utils", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", ] part_name = "datamgr_service" } @@ -592,7 +592,7 @@ ohos_moduletest("DistributedbNbDbDamageTest") { ] external_deps = [ "c_utils:utils", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", ] part_name = "datamgr_service" } @@ -617,7 +617,7 @@ ohos_moduletest("DistributeddbNbCrudPowerTest") { ] external_deps = [ "c_utils:utils", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", ] part_name = "datamgr_service" } @@ -642,7 +642,7 @@ ohos_moduletest("DistributeddbNbSchemaTest") { ] external_deps = [ "c_utils:utils", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", ] part_name = "datamgr_service" } @@ -667,7 +667,7 @@ ohos_moduletest("DistributeddbNbSchemaUpgradeTest") { ] external_deps = [ "c_utils:utils", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", ] part_name = "datamgr_service" } diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_interfaces_relational_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_interfaces_relational_sync_test.cpp index cb5caf2272e47090898dffb72b92ff07ce2a02cf..1deab89660625655529e2fdba65cec8dd9929820 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_interfaces_relational_sync_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_interfaces_relational_sync_test.cpp @@ -15,20 +15,21 @@ #ifdef RELATIONAL_STORE #include #include -#include "distributeddb_tools_unit_test.h" #include "cloud/cloud_storage_utils.h" -#include "relational_store_manager.h" +#include "cloud_db_constant.h" #include "distributeddb_data_generate_unit_test.h" +#include "distributeddb_tools_unit_test.h" +#include "process_system_api_adapter_impl.h" #include "relational_store_instance.h" +#include "relational_store_manager.h" +#include "runtime_config.h" #include "sqlite_relational_store.h" #include "sqlite_relational_utils.h" #include "store_observer.h" -#include "cloud_db_constant.h" -#include "virtual_cloud_db.h" #include "time_helper.h" -#include "runtime_config.h" -#include "virtual_cloud_data_translate.h" #include "virtual_asset_loader.h" +#include "virtual_cloud_data_translate.h" +#include "virtual_cloud_db.h" using namespace testing::ext; using namespace DistributedDB; @@ -53,6 +54,8 @@ namespace { std::shared_ptr g_virtualAssetLoader; DistributedDB::RelationalStoreManager g_mgr(APP_ID, USER_ID); RelationalStoreObserverUnitTest *g_observer = nullptr; + RelationalStoreDelegate *g_delegate = nullptr; + SyncProcess g_syncProcess; using CloudSyncStatusCallback = std::function &onProcess)>; const std::string CREATE_LOCAL_TABLE_SQL = "CREATE TABLE IF NOT EXISTS " + g_tableName1 + "(" \ @@ -161,8 +164,8 @@ namespace { EXPECT_EQ(SQLiteUtils::StepWithRetry(stmt), SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)); SQLiteUtils::ResetStatement(stmt, true, errCode); } - LOGD("insert user record worker1[primary key]:[local%d - cloud%d) , worker2[primary key]:[%d - %d)", - begin, count, begin, count); + LOGD("insert user record worker1[primary key]:[local%" PRId64 " - cloud%" PRId64 + ") , worker2[primary key]:[%" PRId64 "- %" PRId64")", begin, count, begin, count); } void UpdateUserTableRecord(sqlite3 *&db, int64_t begin, int64_t count) @@ -176,8 +179,8 @@ namespace { updateAge += ");"; ASSERT_EQ(RelationalTestUtils::ExecSql(db, updateAge), SQLITE_OK); } - LOGD("update local record worker1[primary key]:[local%d - local%d) , worker2[primary key]:[%d - %d)", - begin, count, begin, count); + LOGD("update local record worker1[primary key]:[local%" PRId64 " - local%" PRId64 + ") , worker2[primary key]:[%" PRId64 "- %" PRId64")", begin, count, begin, count); } void DeleteUserTableRecord(sqlite3 *&db, int64_t begin, int64_t count) @@ -191,8 +194,8 @@ namespace { updateAge += ");"; ASSERT_EQ(RelationalTestUtils::ExecSql(db, updateAge), SQLITE_OK); } - LOGD("delete local record worker1[primary key]:[local%d - local%d) , worker2[primary key]:[%d - %d)", - begin, count, begin, count); + LOGD("delete local record worker1[primary key]:[local%" PRId64 " - local%" PRId64 + ") , worker2[primary key]:[%" PRId64 "- %" PRId64")", begin, count, begin, count); } void InsertRecordWithoutPk2LocalAndCloud(sqlite3 *&db, int64_t begin, int64_t count, int photoSize) @@ -237,6 +240,8 @@ namespace { std::vector photo(photoSize, 'v'); std::vector record1; std::vector extend1; + std::vector record2; + std::vector extend2; Timestamp now = TimeHelper::GetSysCurrentTime(); for (int64_t i = begin; i < begin + count; ++i) { VBucket data; @@ -244,45 +249,35 @@ namespace { data.insert_or_assign("height", 166.0); // 166.0 is random double value data.insert_or_assign("married", false); data.insert_or_assign("photo", photo); + data.insert_or_assign("age", 13L); Asset asset = g_cloudAsset; asset.name = asset.name + std::to_string(i); assetIsNull ? data.insert_or_assign("assert", Nil()) : data.insert_or_assign("assert", asset); - data.insert_or_assign("age", 13L); record1.push_back(data); VBucket log; log.insert_or_assign(CloudDbConstant::CREATE_FIELD, (int64_t)now / CloudDbConstant::TEN_THOUSAND + i); log.insert_or_assign(CloudDbConstant::MODIFY_FIELD, (int64_t)now / CloudDbConstant::TEN_THOUSAND + i); log.insert_or_assign(CloudDbConstant::DELETE_FIELD, false); extend1.push_back(log); - } - ASSERT_EQ(g_virtualCloudDb->BatchInsert(g_tableName1, std::move(record1), extend1), DBStatus::OK); - std::vector record2, extend2; - now = TimeHelper::GetSysCurrentTime(); - for (int64_t i = begin; i < begin + count; ++i) { - VBucket data; + std::vector assets; data.insert_or_assign("id", i); - data.insert_or_assign("name", "Cloud" + std::to_string(i)); data.insert_or_assign("height", 180.3); // 180.3 is random double value - data.insert_or_assign("photo", photo); - std::vector assets; - Asset asset = g_cloudAsset; - for (int64_t j = i; j <= i + 1; j++) { + for (int64_t j = i; j <= i + 2; j++) { // 2 extra num asset.name = g_cloudAsset.name + std::to_string(j); assets.push_back(asset); } + data.erase("assert"); + data.erase("married"); assetIsNull ? data.insert_or_assign("asserts", Nil()) : data.insert_or_assign("asserts", assets); - data.insert_or_assign("age", 28L); record2.push_back(data); - VBucket log; - log.insert_or_assign(CloudDbConstant::CREATE_FIELD, (int64_t)now / CloudDbConstant::TEN_THOUSAND + i); - log.insert_or_assign(CloudDbConstant::MODIFY_FIELD, (int64_t)now / CloudDbConstant::TEN_THOUSAND + i); - log.insert_or_assign(CloudDbConstant::DELETE_FIELD, false); extend2.push_back(log); } + ASSERT_EQ(g_virtualCloudDb->BatchInsert(g_tableName1, std::move(record1), extend1), DBStatus::OK); ASSERT_EQ(g_virtualCloudDb->BatchInsert(g_tableName2, std::move(record2), extend2), DBStatus::OK); - LOGD("insert cloud record worker1[primary key]:[cloud%d - cloud%d) , worker2[primary key]:[%d - %d)", - begin, count, begin, count); + LOGD("insert cloud record worker1[primary key]:[cloud%" PRId64 " - cloud%" PRId64 + ") , worker2[primary key]:[%" PRId64 "- %" PRId64")", begin, count, begin, count); + std::this_thread::sleep_for(std::chrono::milliseconds(count)); } void UpdateAssetForTest(sqlite3 *&db, AssetOpType opType, int64_t cloudCount, int64_t rowid) @@ -348,6 +343,83 @@ namespace { SQLiteUtils::ResetStatement(stmt, true, errCode); } + void UpdateLocalAssetsToRepeat(sqlite3 *&db, int64_t rowid) + { + string sql = "UPDATE " + g_tables[1] + " SET asserts = ? where rowid = '" + std::to_string(rowid) + "';"; + std::vector assetsBlob; + int errCode; + Assets assets; + assets.push_back(g_localAsset); + assets.push_back(g_localAsset); + RuntimeContext::GetInstance()->AssetsToBlob(assets, assetsBlob); + sqlite3_stmt *stmt = nullptr; + ASSERT_EQ(SQLiteUtils::GetStatement(db, sql, stmt), E_OK); + if (SQLiteUtils::BindBlobToStatement(stmt, 1, assetsBlob, false) == E_OK) { + EXPECT_EQ(SQLiteUtils::StepWithRetry(stmt), SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)); + } + SQLiteUtils::ResetStatement(stmt, true, errCode); + } + + void UpdateDiffType(int64_t begin) + { + std::vector hash = {"DEC", "update_", "insert_"}; + std::vector name = { + g_cloudAsset.name + std::to_string(0), + g_cloudAsset.name + std::to_string(1), + g_cloudAsset.name + std::to_string(3) // 3 is insert id + }; + std::vector record; + std::vector extend; + Assets assets; + for (int i = 0; i < 3; i ++) { // 3 is type num + Asset asset = g_cloudAsset; + asset.name = name[i]; + asset.hash = hash[i]; + assets.push_back(asset); + } + VBucket data; + data.insert_or_assign("name", "Cloud" + std::to_string(0)); + data.insert_or_assign("id", 0L); + data.insert_or_assign("asserts", assets); + Timestamp now = TimeHelper::GetSysCurrentTime(); + VBucket log; + log.insert_or_assign(CloudDbConstant::DELETE_FIELD, false); + log.insert_or_assign(CloudDbConstant::GID_FIELD, std::to_string(begin)); + log.insert_or_assign(CloudDbConstant::CREATE_FIELD, (int64_t)now / CloudDbConstant::TEN_THOUSAND); + log.insert_or_assign(CloudDbConstant::MODIFY_FIELD, (int64_t)now / CloudDbConstant::TEN_THOUSAND); + record.push_back(data); + extend.push_back(log); + ASSERT_EQ(g_virtualCloudDb->BatchUpdate(g_tableName2, std::move(record), extend), DBStatus::OK); + } + + void CheckDiffTypeAsset(sqlite3 *&db) + { + std::vector names = { + g_cloudAsset.name + std::to_string(0), + g_cloudAsset.name + std::to_string(1), + g_cloudAsset.name + std::to_string(3) // 3 is insert id + }; + std::string sql = "SELECT asserts from " + g_tables[1] + " WHERE rowid = 0;"; + sqlite3_stmt *stmt = nullptr; + int index = 0; + ASSERT_EQ(SQLiteUtils::GetStatement(db, sql, stmt), E_OK); + while (SQLiteUtils::StepWithRetry(stmt) == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + ASSERT_EQ(sqlite3_column_type(stmt, 0), SQLITE_BLOB); + Type cloudValue; + ASSERT_EQ(SQLiteRelationalUtils::GetCloudValueByType(stmt, TYPE_INDEX, 0, cloudValue), E_OK); + std::vector assetsBlob; + Assets assets; + ASSERT_EQ(CloudStorageUtils::GetValueFromOneField(cloudValue, assetsBlob), E_OK); + ASSERT_EQ(RuntimeContext::GetInstance()->BlobToAssets(assetsBlob, assets), E_OK); + for (const Asset &asset: assets) { + ASSERT_EQ(asset.status, static_cast(AssetStatus::NORMAL)); + ASSERT_EQ(asset.name, names[index++]); + } + } + int errCode; + SQLiteUtils::ResetStatement(stmt, true, errCode); + } + void CheckFillAssetForTest10(sqlite3 *&db) { std::string sql = "SELECT assert from " + g_tables[0] + " WHERE rowid in ('27','28','29','30');"; @@ -451,6 +523,16 @@ namespace { } } + // void CheckLocalTotalNum(sqlite3 *&db, std::vector tableList, std::vector countList) + // { + // int i = 0; + // for (const auto &tableName: tableList) { + // std::string sql = "select count(*) from " + tableName + ";"; + // EXPECT_EQ(sqlite3_exec(db, sql.c_str(), QueryCountCallback, + // reinterpret_cast(countList[i]), nullptr), SQLITE_OK); + // i++; + // } + // } void CheckCleanLogNum(sqlite3 *&db, const std::vector tableList, int count) { for (const auto &tableName: tableList) { @@ -589,6 +671,7 @@ namespace { expectProcess.push_back(syncProcess); } } + void InitProcessForMannualSync1(std::vector &expectProcess) { expectProcess.clear(); @@ -626,38 +709,26 @@ namespace { expectProcess.push_back(syncProcess); } } + void InitProcessForCleanCloudData1(const uint32_t &cloudCount, const uint32_t &localCount, std::vector &expectProcess) { + // cloudCount also means data count in one batch expectProcess.clear(); std::vector infos; uint32_t index = 1; infos.push_back(TableProcessInfo{ - PROCESSING, {index, cloudCount, cloudCount, 0}, {0, 0, 0, 0} + FINISHED, {index, cloudCount, cloudCount, 0}, {0, 0, 0, 0} }); infos.push_back(TableProcessInfo{ PREPARED, {0, 0, 0, 0}, {0, 0, 0, 0} }); infos.push_back(TableProcessInfo{ - PROCESSING, {index, cloudCount, cloudCount, 0}, {0, 0, 0, 0} - }); - infos.push_back(TableProcessInfo{ - PROCESSING, {index, cloudCount, cloudCount, 0}, {0, 0, 0, 0} - }); - - infos.push_back(TableProcessInfo{ - PROCESSING, {index, cloudCount, cloudCount, 0}, {0, 0, 0, 0} - }); - infos.push_back(TableProcessInfo{ - PROCESSING, {index, cloudCount, cloudCount, 0}, {0, 0, 0, 0} - }); - - infos.push_back(TableProcessInfo{ - PROCESSING, {index, cloudCount, cloudCount, 0}, {0, 0, 0, 0} + FINISHED, {index, cloudCount, cloudCount, 0}, {0, 0, 0, 0} }); infos.push_back(TableProcessInfo{ - PROCESSING, {index, cloudCount, cloudCount, 0}, {0, 0, 0, 0} + FINISHED, {index, cloudCount, cloudCount, 0}, {0, 0, 0, 0} }); for (size_t i = 0; i < infos.size() / g_arrayHalfSub; ++i) { @@ -670,7 +741,6 @@ namespace { } } - void InitProcessForTest2(const uint32_t &cloudCount, const uint32_t &localCount, std::vector &expectProcess) { @@ -758,7 +828,6 @@ namespace { expectProcess.push_back(syncProcess); } } - void GetCallback(SyncProcess &syncProcess, CloudSyncStatusCallback &callback, std::vector &expectProcess) { @@ -932,6 +1001,16 @@ namespace { LOGD("-------------------sync end--------------"); } + void CloseDb() + { + delete g_observer; + g_virtualCloudDb = nullptr; + if (g_delegate != nullptr) { + EXPECT_EQ(g_mgr.CloseStore(g_delegate), DBStatus::OK); + g_delegate = nullptr; + } + } + class DistributedDBCloudInterfacesRelationalSyncTest : public testing::Test { public: static void SetUpTestCase(void); @@ -940,7 +1019,6 @@ namespace { void TearDown(); protected: sqlite3 *db = nullptr; - RelationalStoreDelegate *delegate = nullptr; }; @@ -968,33 +1046,28 @@ namespace { g_observer = new (std::nothrow) RelationalStoreObserverUnitTest(); ASSERT_NE(g_observer, nullptr); ASSERT_EQ(g_mgr.OpenStore(g_storePath, g_storeID, RelationalStoreDelegate::Option { .observer = g_observer }, - delegate), DBStatus::OK); - ASSERT_NE(delegate, nullptr); - ASSERT_EQ(delegate->CreateDistributedTable(g_tableName1, CLOUD_COOPERATION), DBStatus::OK); - ASSERT_EQ(delegate->CreateDistributedTable(g_tableName2, CLOUD_COOPERATION), DBStatus::OK); - ASSERT_EQ(delegate->CreateDistributedTable(g_tableName3, CLOUD_COOPERATION), DBStatus::OK); + g_delegate), DBStatus::OK); + ASSERT_NE(g_delegate, nullptr); + ASSERT_EQ(g_delegate->CreateDistributedTable(g_tableName1, CLOUD_COOPERATION), DBStatus::OK); + ASSERT_EQ(g_delegate->CreateDistributedTable(g_tableName2, CLOUD_COOPERATION), DBStatus::OK); + ASSERT_EQ(g_delegate->CreateDistributedTable(g_tableName3, CLOUD_COOPERATION), DBStatus::OK); g_virtualCloudDb = make_shared(); g_virtualAssetLoader = make_shared(); - ASSERT_EQ(delegate->SetCloudDB(g_virtualCloudDb), DBStatus::OK); - ASSERT_EQ(delegate->SetIAssetLoader(g_virtualAssetLoader), DBStatus::OK); + g_syncProcess = {}; + ASSERT_EQ(g_delegate->SetCloudDB(g_virtualCloudDb), DBStatus::OK); + ASSERT_EQ(g_delegate->SetIAssetLoader(g_virtualAssetLoader), DBStatus::OK); // sync before setting cloud db schema,it should return SCHEMA_MISMATCH Query query = Query::Select().FromTable(g_tables); CloudSyncStatusCallback callback; - ASSERT_EQ(delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, callback, g_syncWaitTime), + ASSERT_EQ(g_delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, callback, g_syncWaitTime), DBStatus::SCHEMA_MISMATCH); DataBaseSchema dataBaseSchema; GetCloudDbSchema(dataBaseSchema); - ASSERT_EQ(delegate->SetCloudDbSchema(dataBaseSchema), DBStatus::OK); + ASSERT_EQ(g_delegate->SetCloudDbSchema(dataBaseSchema), DBStatus::OK); } void DistributedDBCloudInterfacesRelationalSyncTest::TearDown(void) { - delete g_observer; - g_virtualCloudDb = nullptr; - if (delegate != nullptr) { - EXPECT_EQ(g_mgr.CloseStore(delegate), DBStatus::OK); - delegate = nullptr; - } EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK); if (DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir) != 0) { LOGE("rm test db files error."); @@ -1030,17 +1103,17 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest001, TestS Query query = Query::Select().FromTable(g_tables); std::vector expectProcess; InitProcessForTest1(cloudCount, localCount, expectProcess); - SyncProcess syncProcess; CloudSyncStatusCallback callback; - GetCallback(syncProcess, callback, expectProcess); - ASSERT_EQ(delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, callback, g_syncWaitTime), DBStatus::OK); - WaitForSyncFinish(syncProcess, g_syncWaitTime); + GetCallback(g_syncProcess, callback, expectProcess); + ASSERT_EQ(g_delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, callback, g_syncWaitTime), DBStatus::OK); + WaitForSyncFinish(g_syncProcess, g_syncWaitTime); EXPECT_TRUE(g_observer->IsAllChangedDataEq()); g_observer->ClearChangedData(); LOGD("expect download:worker1[primary key]:[cloud0 - cloud20), worker2[primary key]:[10 - 20)"); CheckDownloadResult(db, {20L, 10L}); // 20 and 10 means the num of downloads from cloud db by worker1 and worker2 LOGD("expect upload:worker1[primary key]:[local0 - local10), worker2[primary key]:[0 - 10)"); CheckCloudTotalCount({30L, 20L}); // 30 and 20 means the total num of worker1 and worker2 from the cloud db + CloseDb(); } /** @@ -1060,15 +1133,15 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest002, TestS Query query = Query::Select().FromTable(g_tables); std::vector expectProcess; InitProcessForTest2(cloudCount, localCount, expectProcess); - SyncProcess syncProcess; CloudSyncStatusCallback callback; - GetCallback(syncProcess, callback, expectProcess); - ASSERT_EQ(delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, callback, g_syncWaitTime), DBStatus::OK); - WaitForSyncFinish(syncProcess, g_syncWaitTime); + GetCallback(g_syncProcess, callback, expectProcess); + ASSERT_EQ(g_delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, callback, g_syncWaitTime), DBStatus::OK); + WaitForSyncFinish(g_syncProcess, g_syncWaitTime); LOGD("expect download:worker1[primary key]:[cloud0 - cloud10), worker2[primary key]:[0 - 10)"); CheckDownloadResult(db, {10L, 10L}); // 10 and 10 means the num of downloads from cloud db by worker1 and worker2 LOGD("expect upload:worker1[primary key]:[local0 - local20), worker2[primary key]:[10 - 20)"); CheckCloudTotalCount({30L, 20L}); // 30 and 20 means the total num of worker1 and worker2 from the cloud db + CloseDb(); } /** @@ -1087,22 +1160,21 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest003, TestS Query query = Query::Select().FromTable(g_tables); std::vector expectProcess; InitProcessForTest1(cloudCount, cloudCount, expectProcess); - SyncProcess syncProcess; CloudSyncStatusCallback callback; - GetCallback(syncProcess, callback, expectProcess); - ASSERT_EQ(delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, callback, g_syncWaitTime), DBStatus::OK); - WaitForSyncFinish(syncProcess, g_syncWaitTime); + GetCallback(g_syncProcess, callback, expectProcess); + ASSERT_EQ(g_delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, callback, g_syncWaitTime), DBStatus::OK); + WaitForSyncFinish(g_syncProcess, g_syncWaitTime); CheckDownloadResult(db, {20L, 0L}); // 20 and 0 means the num of downloads from cloud db by worker1 and worker2 CheckCloudTotalCount({40L, 20L}); // 40 and 20 means the total num of worker1 and worker2 from the cloud db int updateCount = 10; UpdateUserTableRecord(db, 5, updateCount); // 5 is start id to be updated - syncProcess = {}; + g_syncProcess = {}; InitProcessForTest1(cloudCount, updateCount, expectProcess); - GetCallback(syncProcess, callback, expectProcess); + GetCallback(g_syncProcess, callback, expectProcess); LOGD("-------------------sync after update--------------"); - ASSERT_EQ(delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, callback, g_syncWaitTime), DBStatus::OK); - WaitForSyncFinish(syncProcess, g_syncWaitTime); + ASSERT_EQ(g_delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, callback, g_syncWaitTime), DBStatus::OK); + WaitForSyncFinish(g_syncProcess, g_syncWaitTime); VBucket extend; extend[CloudDbConstant::CURSOR_FIELD] = std::to_string(0); @@ -1120,13 +1192,14 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest003, TestS int deleteCount = 3; DeleteUserTableRecord(db, 0, deleteCount); - syncProcess = {}; + g_syncProcess = {}; InitProcessForTest1(updateCount, deleteCount, expectProcess); - GetCallback(syncProcess, callback, expectProcess); - ASSERT_EQ(delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, callback, g_syncWaitTime), DBStatus::OK); - WaitForSyncFinish(syncProcess, g_syncWaitTime); + GetCallback(g_syncProcess, callback, expectProcess); + ASSERT_EQ(g_delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, callback, g_syncWaitTime), DBStatus::OK); + WaitForSyncFinish(g_syncProcess, g_syncWaitTime); CheckCloudTotalCount({37L, 17L}); // 37 and 17 means the total num of worker1 and worker2 from the cloud db + CloseDb(); } /** @@ -1148,11 +1221,11 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest004, TestS } Query query = Query::Select().FromTable(g_tables); std::vector expectProcess; - SyncProcess syncProcess; CloudSyncStatusCallback callback; - GetCallback(syncProcess, callback, expectProcess); - ASSERT_EQ(delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, callback, g_syncWaitTime), DBStatus::OK); - WaitForSyncFinish(syncProcess, 20); // 20 is wait time + GetCallback(g_syncProcess, callback, expectProcess); + ASSERT_EQ(g_delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, callback, g_syncWaitTime), DBStatus::OK); + WaitForSyncFinish(g_syncProcess, 20); // 20 is wait time + CloseDb(); } /** @@ -1165,13 +1238,13 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest004, TestS HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest005, TestSize.Level0) { Query query = Query::Select().FromTable(g_tables).OrderBy("123", true); - SyncProcess syncProcess; - ASSERT_EQ(delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, nullptr, g_syncWaitTime), + ASSERT_EQ(g_delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, nullptr, g_syncWaitTime), DBStatus::NOT_SUPPORT); query = Query::Select(); - ASSERT_EQ(delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, nullptr, g_syncWaitTime), + ASSERT_EQ(g_delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, nullptr, g_syncWaitTime), DBStatus::INVALID_ARGS); + CloseDb(); } /** @@ -1201,15 +1274,14 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest006, TestS InsertUserTableRecord(db, 0, cloudCount / g_arrayHalfSub, paddingSize, false); Query query = Query::Select().FromTable(g_tables); std::vector expectProcess; - SyncProcess syncProcess; CloudSyncStatusCallback callback; - GetCallback(syncProcess, callback, expectProcess); + GetCallback(g_syncProcess, callback, expectProcess); // Set correct cloudDbSchema (correct version) DataBaseSchema correctSchema; GetCloudDbSchema(correctSchema); - ASSERT_EQ(delegate->SetCloudDbSchema(correctSchema), DBStatus::OK); - ASSERT_EQ(delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, callback, g_syncWaitTime), DBStatus::OK); - WaitForSyncFinish(syncProcess, g_syncWaitTime); + ASSERT_EQ(g_delegate->SetCloudDbSchema(correctSchema), DBStatus::OK); + ASSERT_EQ(g_delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, callback, g_syncWaitTime), DBStatus::OK); + WaitForSyncFinish(g_syncProcess, g_syncWaitTime); EXPECT_TRUE(g_observer->IsAllChangedDataEq()); g_observer->ClearChangedData(); LOGD("expect download:worker1[primary key]:[cloud0 - cloud20), worker2[primary key]:[10 - 20)"); @@ -1219,16 +1291,17 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest006, TestS // Reset cloudDbSchema (invalid version - null) DataBaseSchema nullSchema; - ASSERT_EQ(delegate->SetCloudDbSchema(nullSchema), DBStatus::OK); - ASSERT_EQ(delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, callback, g_syncWaitTime), + ASSERT_EQ(g_delegate->SetCloudDbSchema(nullSchema), DBStatus::OK); + ASSERT_EQ(g_delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, callback, g_syncWaitTime), DBStatus::SCHEMA_MISMATCH); // Reset cloudDbSchema (invalid version - field mismatch) DataBaseSchema invalidSchema; GetInvalidCloudDbSchema(invalidSchema); - ASSERT_EQ(delegate->SetCloudDbSchema(invalidSchema), DBStatus::OK); - ASSERT_EQ(delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, callback, g_syncWaitTime), + ASSERT_EQ(g_delegate->SetCloudDbSchema(invalidSchema), DBStatus::OK); + ASSERT_EQ(g_delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, callback, g_syncWaitTime), DBStatus::SCHEMA_MISMATCH); + CloseDb(); } /** @@ -1246,15 +1319,15 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest007, TestS InsertCloudTableRecord(0, localCount / g_arrayHalfSub, paddingSize, false); Query query = Query::Select().FromTable(g_tables); std::vector expectProcess; - SyncProcess syncProcess; CloudSyncStatusCallback callback; - GetCallback(syncProcess, callback, expectProcess); - ASSERT_EQ(delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, callback, g_syncWaitTime), DBStatus::OK); - WaitForSyncFinish(syncProcess, g_syncWaitTime); + GetCallback(g_syncProcess, callback, expectProcess); + ASSERT_EQ(g_delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, callback, g_syncWaitTime), DBStatus::OK); + WaitForSyncFinish(g_syncProcess, g_syncWaitTime); CheckAssetAfterDownload(db, localCount); CheckAllAssetAfterUpload(localCount); CheckAssetsAfterDownload(db, localCount); + CloseDb(); } /* @@ -1266,9 +1339,11 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest007, TestS */ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest008, TestSize.Level0) { - ASSERT_EQ(delegate->SetCloudDB(nullptr), OK); + ASSERT_EQ(g_delegate->SetCloudDB(nullptr), OK); // it will not happen because cloudb has been set in SetUp() Query query = Query::Select().FromTable({g_tableName3}); - ASSERT_EQ(delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, nullptr, g_syncWaitTime), CLOUD_ERROR); + // clouddb has been set in SetUp() and it's not null + ASSERT_EQ(g_delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, nullptr, g_syncWaitTime), OK); + CloseDb(); } /** @@ -1287,22 +1362,22 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest009, TestS Query query = Query::Select().FromTable(g_tables); std::vector expectProcess; InitProcessForTest1(cloudCount, cloudCount, expectProcess); - SyncProcess syncProcess; CloudSyncStatusCallback callback; - GetCallback(syncProcess, callback, expectProcess); - ASSERT_EQ(delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, callback, g_syncWaitTime), DBStatus::OK); - WaitForSyncFinish(syncProcess, g_syncWaitTime); + GetCallback(g_syncProcess, callback, expectProcess); + ASSERT_EQ(g_delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, callback, g_syncWaitTime), DBStatus::OK); + WaitForSyncFinish(g_syncProcess, g_syncWaitTime); LOGD("expect download:worker1[primary key]:[cloud0 - cloud20), worker2[primary key]:none"); CheckDownloadResult(db, {20L, 0L}); // 20 and 0 means the num of downloads from cloud db by worker1 and worker2 LOGD("expect upload:worker1[primary key]:[local0 - local20), worker2[primary key]:[0 - 20)"); CheckCloudTotalCount({40L, 20L}); // 40 and 20 means the total num of worker1 and worker2 from the cloud db - syncProcess = {}; + g_syncProcess = {}; InitProcessForTest9(cloudCount, 0, expectProcess); - GetCallback(syncProcess, callback, expectProcess); + GetCallback(g_syncProcess, callback, expectProcess); LOGD("--------------the second sync-------------"); - ASSERT_EQ(delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, callback, g_syncWaitTime), DBStatus::OK); - WaitForSyncFinish(syncProcess, g_syncWaitTime); + ASSERT_EQ(g_delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, callback, g_syncWaitTime), DBStatus::OK); + WaitForSyncFinish(g_syncProcess, g_syncWaitTime); + CloseDb(); } HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest0010, TestSize.Level0) @@ -1314,11 +1389,10 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest0010, Test InsertUserTableRecord(db, 0, localCount, paddingSize, false); Query query = Query::Select().FromTable(g_tables); std::vector expectProcess; - SyncProcess syncProcess; CloudSyncStatusCallback callback; - GetCallback(syncProcess, callback, expectProcess); - ASSERT_EQ(delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, callback, g_syncWaitTime), DBStatus::OK); - WaitForSyncFinish(syncProcess, g_syncWaitTime); + GetCallback(g_syncProcess, callback, expectProcess); + ASSERT_EQ(g_delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, callback, g_syncWaitTime), DBStatus::OK); + WaitForSyncFinish(g_syncProcess, g_syncWaitTime); int rowid = 27; UpdateAssetForTest(db, AssetOpType::NO_CHANGE, cloudCount, rowid++); @@ -1332,14 +1406,15 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest0010, Test UpdateAssetsForTest(db, AssetOpType::DELETE, id++); UpdateAssetsForTest(db, AssetOpType::UPDATE, id++); - syncProcess = {}; - GetCallback(syncProcess, callback, expectProcess); + g_syncProcess = {}; + GetCallback(g_syncProcess, callback, expectProcess); LOGD("--------------the second sync-------------"); - ASSERT_EQ(delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, callback, g_syncWaitTime), DBStatus::OK); - WaitForSyncFinish(syncProcess, g_syncWaitTime); + ASSERT_EQ(g_delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, callback, g_syncWaitTime), DBStatus::OK); + WaitForSyncFinish(g_syncProcess, g_syncWaitTime); CheckFillAssetForTest10(db); CheckFillAssetsForTest10(db); + CloseDb(); } /** @@ -1367,13 +1442,14 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest011, TestS } cv.notify_all(); }; - ASSERT_EQ(delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, callback, g_syncWaitTime), DBStatus::OK); + ASSERT_EQ(g_delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, callback, g_syncWaitTime), DBStatus::OK); std::unique_lock uniqueLock(syncMutex); cv.wait(uniqueLock, [&syncFinish]() { return syncFinish; }); RuntimeContext::GetInstance()->StopTaskPool(); EXPECT_EQ(callCount, 2); // 2 is onProcess count + CloseDb(); } HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest012, TestSize.Level0) @@ -1385,33 +1461,199 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest012, TestS InsertUserTableRecord(db, 0, localCount, paddingSize, true); Query query = Query::Select().FromTable(g_tables); std::vector expectProcess; - SyncProcess syncProcess; CloudSyncStatusCallback callback; - GetCallback(syncProcess, callback, expectProcess); - ASSERT_EQ(delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, callback, g_syncWaitTime), DBStatus::OK); - WaitForSyncFinish(syncProcess, g_syncWaitTime); + GetCallback(g_syncProcess, callback, expectProcess); + ASSERT_EQ(g_delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, callback, g_syncWaitTime), DBStatus::OK); + WaitForSyncFinish(g_syncProcess, g_syncWaitTime); InsertCloudTableRecord(localCount + cloudCount, cloudCount, paddingSize, false); InsertUserTableRecord(db, localCount + cloudCount, localCount, paddingSize, true); - syncProcess = {}; - GetCallback(syncProcess, callback, expectProcess); - ASSERT_EQ(delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, callback, g_syncWaitTime), DBStatus::OK); - WaitForSyncFinish(syncProcess, g_syncWaitTime); + g_syncProcess = {}; + GetCallback(g_syncProcess, callback, expectProcess); + ASSERT_EQ(g_delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, callback, g_syncWaitTime), DBStatus::OK); + WaitForSyncFinish(g_syncProcess, g_syncWaitTime); InsertCloudTableRecord(2 * (localCount + cloudCount), cloudCount, paddingSize, false); // 2 is offset InsertUserTableRecord(db, 2 * (localCount + cloudCount), localCount, paddingSize, false); // 2 is offset - syncProcess = {}; - GetCallback(syncProcess, callback, expectProcess); - ASSERT_EQ(delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, callback, g_syncWaitTime), DBStatus::OK); - WaitForSyncFinish(syncProcess, g_syncWaitTime); + g_syncProcess = {}; + GetCallback(g_syncProcess, callback, expectProcess); + ASSERT_EQ(g_delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, callback, g_syncWaitTime), DBStatus::OK); + WaitForSyncFinish(g_syncProcess, g_syncWaitTime); InsertCloudTableRecord(3 * (localCount + cloudCount), cloudCount, paddingSize, true); // 3 is offset InsertUserTableRecord(db, 3 * (localCount + cloudCount), localCount, paddingSize, true); // 3 is offset - syncProcess = {}; - GetCallback(syncProcess, callback, expectProcess); - ASSERT_EQ(delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, callback, g_syncWaitTime), DBStatus::OK); + g_syncProcess = {}; + GetCallback(g_syncProcess, callback, expectProcess); + ASSERT_EQ(g_delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, callback, g_syncWaitTime), DBStatus::OK); + WaitForSyncFinish(g_syncProcess, g_syncWaitTime); + CloseDb(); +} + +/* + * @tc.name: CloudSyncTest013 + * @tc.desc: test increment watermark when cloud db query data size is 0 + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhuwentao + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest013, TestSize.Level0) +{ + /** + * @tc.steps: insert some data into cloud db + * @tc.expected: return ok. + */ + int64_t paddingSize = 10; + int64_t cloudCount = 10; + SyncProcess syncProcess; + InsertCloudTableRecord(0, cloudCount, paddingSize, true); + /** + * @tc.steps: try to cloud sync + * @tc.expected: return ok. + */ + Query query = Query::Select().FromTable(g_tables); + CloudSyncStatusCallback callback = [&syncProcess](const std::map &process) { + LOGI("devices size = %d", process.size()); + ASSERT_EQ(process.size(), 1u); + syncProcess = std::move(process.begin()->second); + if (syncProcess.process == FINISHED) { + g_processCondition.notify_one(); + } + }; + ASSERT_EQ(g_delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, callback, g_syncWaitTime), DBStatus::OK); WaitForSyncFinish(syncProcess, g_syncWaitTime); + uint32_t queryTimes = g_virtualCloudDb->GetQueryTimes(g_tableName1); + /** + * @tc.steps: insert some increment data into cloud db + * @tc.expected: return ok. + */ + VBucket data; + Timestamp now = TimeHelper::GetSysCurrentTime(); + data.insert_or_assign("name", "Cloud" + std::to_string(0)); + data.insert_or_assign("height", 166.0); // 166.0 is random double value + data.insert_or_assign("married", false); + data.insert_or_assign("age", 13L); + VBucket log; + log.insert_or_assign(CloudDbConstant::CREATE_FIELD, (int64_t)now / CloudDbConstant::TEN_THOUSAND); + log.insert_or_assign(CloudDbConstant::MODIFY_FIELD, (int64_t)now / CloudDbConstant::TEN_THOUSAND); + log.insert_or_assign(CloudDbConstant::DELETE_FIELD, false); + log.insert_or_assign(CloudDbConstant::CREATE_FIELD, (int64_t)now / CloudDbConstant::TEN_THOUSAND); + log.insert_or_assign(CloudDbConstant::CURSOR_FIELD, "0123"); + g_virtualCloudDb->SetIncrementData(g_tableName1, data, log); + syncProcess.process = PREPARED; + ASSERT_EQ(g_delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, callback, g_syncWaitTime), DBStatus::OK); + WaitForSyncFinish(syncProcess, g_syncWaitTime); + uint32_t lastQueryTimes = g_virtualCloudDb->GetQueryTimes(g_tableName1); + ASSERT_EQ(lastQueryTimes - queryTimes, 2u); + CloseDb(); +} + +void TestSyncForStatus(RelationalStoreDelegate *delegate, DBStatus expectStatus) +{ + std::mutex dataMutex; + std::condition_variable cv; + bool finish = false; + DBStatus res = OK; + CloudSyncStatusCallback callback = [&dataMutex, &cv, &finish, &res]( + const std::map &process) { + std::map syncProcess; + { + std::lock_guard autoLock(dataMutex); + syncProcess = process; + if (syncProcess[DEVICE_CLOUD].process == FINISHED) { + finish = true; + } + res = syncProcess[DEVICE_CLOUD].errCode; + } + cv.notify_one(); + }; + Query query = Query::Select().FromTable({g_tableName3}); + ASSERT_EQ(g_delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, callback, g_syncWaitTime), DBStatus::OK); + { + std::unique_lock uniqueLock(dataMutex); + cv.wait(uniqueLock, [&finish] { + return finish; + }); + } + EXPECT_EQ(res, expectStatus); + RuntimeContext::GetInstance()->StopTaskPool(); +} + +/* + * @tc.name: CloudSyncTest015 + * @tc.desc: Test sync with cloud error + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest015, TestSize.Level0) +{ + g_virtualCloudDb->SetActionStatus(CLOUD_NETWORK_ERROR); + TestSyncForStatus(g_delegate, CLOUD_NETWORK_ERROR); + + g_virtualCloudDb->SetActionStatus(CLOUD_SYNC_UNSET); + TestSyncForStatus(g_delegate, CLOUD_SYNC_UNSET); + + g_virtualCloudDb->SetActionStatus(CLOUD_FULL_RECORDS); + TestSyncForStatus(g_delegate, CLOUD_FULL_RECORDS); + + g_virtualCloudDb->SetActionStatus(CLOUD_LOCK_ERROR); + TestSyncForStatus(g_delegate, CLOUD_LOCK_ERROR); + + g_virtualCloudDb->SetActionStatus(DB_ERROR); + TestSyncForStatus(g_delegate, CLOUD_ERROR); + + g_virtualCloudDb->SetActionStatus(OK); + CloseDb(); +} + +/* + * @tc.name: CloudSyncTest014 + * @tc.desc: Test sync with s4 + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest014, TestSize.Level0) +{ + auto adapter = std::make_shared(); + RuntimeConfig::SetProcessSystemAPIAdapter(adapter); + + // sync failed because get security option failed + adapter->ForkGetSecurityOption([](const std::string&, SecurityOption &option) { + option.securityLabel = S0; + return DB_ERROR; + }); + Query query = Query::Select().FromTable({g_tableName3}); + EXPECT_EQ(g_delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, nullptr, g_syncWaitTime), + SECURITY_OPTION_CHECK_ERROR); + + // sync failed because get S4 + adapter->ForkGetSecurityOption([](const std::string&, SecurityOption &option) { + option.securityLabel = S4; + return NOT_SUPPORT; + }); + Query invalidQuery = Query::Select().FromTable({g_tableName3}).PrefixKey({'k'}); + EXPECT_EQ(g_delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, invalidQuery, nullptr, g_syncWaitTime), + NOT_SUPPORT); + + // sync failed because get S4 + adapter->ForkGetSecurityOption([](const std::string&, SecurityOption &option) { + option.securityLabel = S4; + return OK; + }); + EXPECT_EQ(g_delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, nullptr, g_syncWaitTime), + SECURITY_OPTION_CHECK_ERROR); + + // sync failed because S4 has been cached + adapter->ForkGetSecurityOption([](const std::string&, SecurityOption &option) { + option.securityLabel = S0; + return OK; + }); + EXPECT_EQ(g_delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, nullptr, g_syncWaitTime), + SECURITY_OPTION_CHECK_ERROR); + RuntimeConfig::SetProcessSystemAPIAdapter(nullptr); + CloseDb(); } /* @@ -1428,11 +1670,11 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, DataNotifier001, TestSi InsertRecordWithoutPk2LocalAndCloud(db, 0, localCount, paddingSize); Query query = Query::Select().FromTable({g_tableName3}); std::vector expectProcess; - SyncProcess syncProcess; CloudSyncStatusCallback callback; - GetCallback(syncProcess, callback, expectProcess); - ASSERT_EQ(delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, callback, g_syncWaitTime), DBStatus::OK); - WaitForSyncFinish(syncProcess, g_syncWaitTime); + GetCallback(g_syncProcess, callback, expectProcess); + ASSERT_EQ(g_delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, callback, g_syncWaitTime), DBStatus::OK); + WaitForSyncFinish(g_syncProcess, g_syncWaitTime); + CloseDb(); } /** @@ -1450,17 +1692,16 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncAssetTest001, InsertCloudTableRecord(0, localCount / g_arrayHalfSub, paddingSize, false); Query query = Query::Select().FromTable(g_tables); std::vector expectProcess; - SyncProcess syncProcess; CloudSyncStatusCallback callback; - GetCallback(syncProcess, callback, expectProcess); - ASSERT_EQ(delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, callback, g_syncWaitTime), DBStatus::OK); - WaitForSyncFinish(syncProcess, g_syncWaitTime); + GetCallback(g_syncProcess, callback, expectProcess); + ASSERT_EQ(g_delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, callback, g_syncWaitTime), DBStatus::OK); + WaitForSyncFinish(g_syncProcess, g_syncWaitTime); CheckAssetAfterDownload(db, localCount); CheckAllAssetAfterUpload(localCount); + CloseDb(); } -#ifdef MANNUAL_SYNC_AND_CLEAN_CLOUD_DATA /* * @tc.name: MannualNotify001 * @tc.desc: Test FLAG_ONLY mode of RemoveDeviceData @@ -1476,14 +1717,14 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, MannualNotify001, TestS Query query = Query::Select().FromTable(g_tables); std::vector expectProcess; InitProcessForMannualSync1(expectProcess); - SyncProcess syncProcess; CloudSyncStatusCallback callback; - GetCallback(syncProcess, callback, expectProcess); - ASSERT_EQ(delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_FORCE_PULL, query, callback, g_syncWaitTime), + GetCallback(g_syncProcess, callback, expectProcess); + ASSERT_EQ(g_delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_FORCE_PULL, query, callback, g_syncWaitTime), DBStatus::OK); - WaitForSyncFinish(syncProcess, g_syncWaitTime); - + WaitForSyncFinish(g_syncProcess, g_syncWaitTime); + CloseDb(); } + /* * @tc.name: CleanCloudDataTest001 * @tc.desc: Test FLAG_ONLY mode of RemoveDeviceData @@ -1501,16 +1742,16 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CleanCloudDataTest001, Query query = Query::Select().FromTable(g_tables); std::vector expectProcess; InitProcessForCleanCloudData1(cloudCount, localCount, expectProcess); - SyncProcess syncProcess; CloudSyncStatusCallback callback; - GetCallback(syncProcess, callback, expectProcess); - ASSERT_EQ(delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_FORCE_PULL, query, callback, g_syncWaitTime), + GetCallback(g_syncProcess, callback, expectProcess); + ASSERT_EQ(g_delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_FORCE_PULL, query, callback, g_syncWaitTime), DBStatus::OK); - WaitForSyncFinish(syncProcess, g_syncWaitTime); + WaitForSyncFinish(g_syncProcess, g_syncWaitTime); std::string device = ""; CheckCloudRecordNum(db, g_tables, {20, 20}); - ASSERT_EQ(delegate->RemoveDeviceData(device, FLAG_ONLY), DBStatus::OK); + ASSERT_EQ(g_delegate->RemoveDeviceData(device, FLAG_ONLY), DBStatus::OK); CheckCleanLogNum(db, g_tables, 0); + CloseDb(); } /* @@ -1530,17 +1771,281 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CleanCloudDataTest002, Query query = Query::Select().FromTable(g_tables); std::vector expectProcess; InitProcessForCleanCloudData1(cloudCount, localCount, expectProcess); - SyncProcess syncProcess; CloudSyncStatusCallback callback; - GetCallback(syncProcess, callback, expectProcess); - ASSERT_EQ(delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_FORCE_PULL, query, callback, g_syncWaitTime), + GetCallback(g_syncProcess, callback, expectProcess); + ASSERT_EQ(g_delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_FORCE_PULL, query, callback, g_syncWaitTime), DBStatus::OK); - WaitForSyncFinish(syncProcess, g_syncWaitTime); + WaitForSyncFinish(g_syncProcess, g_syncWaitTime); std::string device = ""; CheckCloudRecordNum(db, g_tables, {20, 20}); // 20 means cloud data num - ASSERT_EQ(delegate->RemoveDeviceData(device, FLAG_AND_DATA), DBStatus::OK); + ASSERT_EQ(g_delegate->RemoveDeviceData(device, FLAG_AND_DATA), DBStatus::OK); CheckCleanDataAndLogNum(db, g_tables, 0, {localCount, 0}); + CloseDb(); +} + +/* + * @tc.name: CleanCloudDataTest003 + * @tc.desc: Test FLAG_ONLY mode of RemoveDeviceData concurrently with Sync + * @tc.type: FUNC + * @tc.require: + * @tc.author: huangboxin + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CleanCloudDataTest003, TestSize.Level0) +{ + /** + * @tc.steps: step1. make data: 10 records on local and 20 records on cloud + */ + int64_t paddingSize = 10; + int localCount = 10; + int cloudCount = 20; + InsertCloudTableRecord(0, cloudCount, paddingSize, false); + InsertUserTableRecord(db, 0, localCount, paddingSize, false); + /** + * @tc.steps: step2. call Sync with cloud force pull strategy, and after that, local will has 20 records. + */ + Query query = Query::Select().FromTable(g_tables); + std::vector expectProcess; + InitProcessForCleanCloudData1(cloudCount, localCount, expectProcess); + CloudSyncStatusCallback callback; + GetCallback(g_syncProcess, callback, expectProcess); + ASSERT_EQ(g_delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_FORCE_PULL, query, callback, g_syncWaitTime), + DBStatus::OK); + WaitForSyncFinish(g_syncProcess, g_syncWaitTime); + CheckCloudRecordNum(db, g_tables, {20, 20}); // 20 means cloud data num + + /** + * @tc.steps: step3. insert 10 records into local, so local will has 20 local records and 20 cloud records. + */ + InsertUserTableRecord(db, 0, localCount, paddingSize, false); + /** + * @tc.steps: step4. call RemoveDeviceData synchronize with Sync with cloud force push strategy. + */ + g_syncProcess = {}; + std::vector expectProcess2; + InitProcessForCleanCloudData1(cloudCount, localCount, expectProcess2); + CloudSyncStatusCallback callback2; + GetCallback(g_syncProcess, callback2, expectProcess2); + std::string device = ""; + + std::thread thread1([&]() { + ASSERT_EQ(g_delegate->RemoveDeviceData(device, FLAG_AND_DATA), DBStatus::OK); + }); + std::condition_variable cv; + std::thread thread2([&]() { + ASSERT_EQ(g_delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_FORCE_PULL, query, callback2, g_syncWaitTime), + DBStatus::OK); + LOGD("-------------------sync end--------------"); + }); + thread1.join(); + thread2.join(); + WaitForSyncFinish(g_syncProcess, g_syncWaitTime); + RuntimeContext::GetInstance()->StopTaskPool(); + CheckCleanLogNum(db, g_tables, 20); + LOGD("================================== test clean cloud data 003 end ==================================="); + CloseDb(); +} + +/* + * @tc.name: CalPrimaryKeyHash001 + * @tc.desc: Test CalcPrimaryKeyHash interface when primary key is string + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhuwentao + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CalPrimaryKeyHash001, TestSize.Level0) +{ + /** + * @tc.steps: step1. local insert one data, primary key is string + * @tc.expected: OK. + */ + std::string photo(1u, 'v'); + std::string name = "Local0"; + std::map primaryKey = {{"name", name}}; + string sql = "INSERT OR REPLACE INTO " + g_tableName1 + + " (name, height, married, photo, age) VALUES ('Local" + std::to_string(0) + + "', '175.8', '0', '" + photo + "', '18');"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), SQLITE_OK); + std::vector result = RelationalStoreManager::CalcPrimaryKeyHash(primaryKey); + EXPECT_NE(result.size(), 0u); + std::string logTableName = RelationalStoreManager::GetDistributedLogTableName(g_tableName1); + /** + * @tc.steps: step1. query timestamp use hashKey + * @tc.expected: OK. + */ + std::string querysql = "select timestamp/10000 from " + logTableName + " where hash_key=?"; + sqlite3_stmt *statement = nullptr; + int errCode = SQLiteUtils::GetStatement(db, querysql, statement); + EXPECT_EQ(errCode, E_OK); + errCode = SQLiteUtils::BindBlobToStatement(statement, 1, result); // 1 means hashkey index + if (errCode != E_OK) { + SQLiteUtils::ResetStatement(statement, true, errCode); + return; + } + errCode = SQLiteUtils::StepWithRetry(statement, false); + if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + Timestamp timestamp = static_cast(sqlite3_column_int64(statement, 0)); + LOGD("get timestamp = %" PRIu64, timestamp); + errCode = E_OK; + } else if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { + errCode = -E_NOT_FOUND; + } + EXPECT_EQ(errCode, E_OK); + SQLiteUtils::ResetStatement(statement, true, errCode); + CloseDb(); +} + +/* + * @tc.name: CalPrimaryKeyHash002 + * @tc.desc: Test CalcPrimaryKeyHash interface when primary key is int + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhuwentao + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CalPrimaryKeyHash002, TestSize.Level0) +{ + /** + * @tc.steps: step1. local insert one data, primary key is int + * @tc.expected: OK. + */ + int64_t id = 1; + std::map primaryKey = {{"id", id}}; + std::string sql = "INSERT OR REPLACE INTO " + g_tableName2 + + " (id, name, height) VALUES ('" + '1' + "', 'Local" + + std::to_string(0) + "', '155.10');"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), SQLITE_OK); + std::vector result = RelationalStoreManager::CalcPrimaryKeyHash(primaryKey); + EXPECT_NE(result.size(), 0u); + std::string logTableName = RelationalStoreManager::GetDistributedLogTableName(g_tableName2); + /** + * @tc.steps: step1. query timestamp use hashKey + * @tc.expected: OK. + */ + std::string querysql = "select timestamp/10000 from " + logTableName + " where hash_key=?"; + sqlite3_stmt *statement = nullptr; + int errCode = SQLiteUtils::GetStatement(db, querysql, statement); + EXPECT_EQ(errCode, E_OK); + errCode = SQLiteUtils::BindBlobToStatement(statement, 1, result); // 1 means hashkey index + if (errCode != E_OK) { + SQLiteUtils::ResetStatement(statement, true, errCode); + return; + } + errCode = SQLiteUtils::StepWithRetry(statement, false); + if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + Timestamp timestamp = static_cast(sqlite3_column_int64(statement, 0)); + LOGD("get timestamp = %" PRIu64, timestamp); + errCode = E_OK; + } else if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { + errCode = -E_NOT_FOUND; + } + EXPECT_EQ(errCode, E_OK); + SQLiteUtils::ResetStatement(statement, true, errCode); + CloseDb(); +} + +/* + * @tc.name: CloudSyncAssetTest002 + * @tc.desc: + * @tc.type: FUNC + * @tc.require: + * @tc.author: huangboxin + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncAssetTest002, TestSize.Level0) +{ + int64_t paddingSize = 10; + int localCount = 3; + int cloudCount = 3; + InsertCloudTableRecord(0, cloudCount, paddingSize, true); + InsertUserTableRecord(db, 0, localCount, paddingSize, false); + Query query = Query::Select().FromTable(g_tables); + std::vector expectProcess; + CloudSyncStatusCallback callback; + GetCallback(g_syncProcess, callback, expectProcess); + ASSERT_EQ(g_delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_FORCE_PUSH, query, callback, g_syncWaitTime), + DBStatus::OK); + WaitForSyncFinish(g_syncProcess, g_syncWaitTime); + CloseDb(); +} + +/* + * @tc.name: CloudSyncAssetTest003 + * @tc.desc: + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncAssetTest003, TestSize.Level0) +{ + int64_t paddingSize = 10; + int localCount = 3; + int cloudCount = 3; + InsertCloudTableRecord(0, cloudCount, paddingSize, true); + InsertUserTableRecord(db, 0, localCount, paddingSize, false); + UpdateLocalAssetsToRepeat(db, 1); + Query query = Query::Select().FromTable(g_tables); + std::vector expectProcess; + CloudSyncStatusCallback callback = [](const std::map &process) { + ASSERT_EQ(process.size(), 1u); + g_syncProcess = std::move(process.begin()->second); + + if (g_syncProcess.process == FINISHED) { + g_processCondition.notify_one(); + } + }; + ASSERT_EQ(g_delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, callback, g_syncWaitTime), + DBStatus::OK); + { + std::unique_lock lock(g_processMutex); + g_processCondition.wait(lock, []() { + return g_syncProcess.process == FINISHED; + }); + ASSERT_EQ(g_syncProcess.errCode, DBStatus::CLOUD_ERROR); + } + CloseDb(); +} + +/* + * @tc.name: CloudSyncAssetTest004 + * @tc.desc: + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncAssetTest004, TestSize.Level0) +{ + int64_t paddingSize = 10; + int localCount = 3; + int cloudCount = 3; + InsertUserTableRecord(db, 0, localCount, paddingSize, false); + InsertCloudTableRecord(0, cloudCount, paddingSize, false); + Query query = Query::Select().FromTable(g_tables); + std::vector expectProcess; + CloudSyncStatusCallback callback; + GetCallback(g_syncProcess, callback, expectProcess); + ASSERT_EQ(g_delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, callback, g_syncWaitTime), + DBStatus::OK); + WaitForSyncFinish(g_syncProcess, g_syncWaitTime); + + UpdateDiffType(localCount); + g_syncProcess = {}; + CloudSyncStatusCallback callback1 = [](const std::map &process) { + ASSERT_EQ(process.size(), 1u); + g_syncProcess = std::move(process.begin()->second); + if (g_syncProcess.process == FINISHED) { + g_processCondition.notify_one(); + } + }; + + ASSERT_EQ(g_delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, callback1, g_syncWaitTime), + DBStatus::OK); + { + std::unique_lock lock(g_processMutex); + g_processCondition.wait(lock, []() { + return g_syncProcess.process == FINISHED; + }); + ASSERT_EQ(g_syncProcess.errCode, DBStatus::OK); + } + CheckDiffTypeAsset(db); + CloseDb(); } -#endif // MANNUAL_SYNC_AND_CLEAN_CLOUD_DATA } #endif // RELATIONAL_STORE diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_meta_data_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_meta_data_test.cpp index cf37722e100fb8c1d698f5edb7f9bb403ef3869b..8d34a0591d467c0fcfaa1d96a683f79c4ebb9dd3 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_meta_data_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_meta_data_test.cpp @@ -99,7 +99,7 @@ namespace { void SetAndGetWaterMark(TableName tableName, CloudWaterMark mark) { CloudWaterMark retMark; - EXPECT_EQ(g_storageProxy->PutCloudWaterMark(tableName, mark), E_OK); + EXPECT_EQ(g_storageProxy->SetCloudWaterMark(tableName, mark), E_OK); EXPECT_EQ(g_storageProxy->GetCloudWaterMark(tableName, retMark), E_OK); EXPECT_EQ(retMark, mark); } diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_save_cloud_data_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_save_cloud_data_test.cpp index 05ff36f72edc5d6949c2f6678ceb06e3ad0db5c8..0f383becb6f595f11c53b138ed873f9c4738d7db 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_save_cloud_data_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_save_cloud_data_test.cpp @@ -47,6 +47,8 @@ namespace { IRelationalStore *g_store = nullptr; RelationalStoreDelegate *g_delegate = nullptr; ICloudSyncStorageInterface *g_cloudStore = nullptr; + constexpr const int64_t BASE_MODIFY_TIME = 12345678L; + constexpr const int64_t BASE_CREATE_TIME = 12345679L; enum class PrimaryKeyType { NO_PRIMARY_KEY, @@ -80,8 +82,8 @@ namespace { void SetCloudSchema(PrimaryKeyType pkType, bool nullable) { TableSchema tableSchema; - Field field1 = { "id", TYPE_INDEX, - pkType == PrimaryKeyType::SINGLE_PRIMARY_KEY || pkType == PrimaryKeyType::COMPOSITE_PRIMARY_KEY, true }; + bool isIdPk = pkType == PrimaryKeyType::SINGLE_PRIMARY_KEY || pkType == PrimaryKeyType::COMPOSITE_PRIMARY_KEY; + Field field1 = { "id", TYPE_INDEX, isIdPk, !isIdPk }; Field field2 = { "name", TYPE_INDEX, pkType == PrimaryKeyType::COMPOSITE_PRIMARY_KEY, true }; Field field3 = { "age", TYPE_INDEX, pkType == PrimaryKeyType::COMPOSITE_PRIMARY_KEY, true }; Field field4 = { "sex", TYPE_INDEX, false, nullable }; @@ -395,7 +397,6 @@ namespace { * @tc.name: GetInfoByPrimaryKeyOrGidTest011 * @tc.desc: Test GetInfoByPrimaryKeyOrGid when table has composite primary key and gid match, * primary key mismatch - * primary key mismatch; * @tc.type: FUNC * @tc.require: * @tc.author: zhangshijie @@ -405,6 +406,53 @@ namespace { GetInfoByPrimaryKeyOrGidTest(PrimaryKeyType::COMPOSITE_PRIMARY_KEY, "abcd0", 11L, E_OK, false); } + void VbucketWithoutPrimaryDataTest(PrimaryKeyType pkType) + { + /** + * @tc.steps:step1. create db, create table. + * @tc.expected: step1. return ok. + */ + PrepareDataBase(g_tableName, pkType); + + /** + * @tc.steps:step2. call GetInfoByPrimaryKeyOrGid. + * @tc.expected: step2. return E_OK. + */ + std::shared_ptr storageProxy = GetStorageProxy(g_cloudStore); + ASSERT_NE(storageProxy, nullptr); + EXPECT_EQ(storageProxy->StartTransaction(), E_OK); + VBucket vBucket; + std::string gid = g_gid + std::to_string(0); + vBucket[CloudDbConstant::GID_FIELD] = gid; + DataInfoWithLog dataInfoWithLog; + VBucket assetInfo; + EXPECT_EQ(storageProxy->GetInfoByPrimaryKeyOrGid(g_tableName, vBucket, dataInfoWithLog, assetInfo), E_OK); + } + + /** + * @tc.name: GetInfoByPrimaryKeyOrGidTest012 + * @tc.desc: Test GetInfoByPrimaryKeyOrGid when vbucket doesn't contain pk data and gid match, + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangshijie + */ + HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest012, TestSize.Level0) + { + VbucketWithoutPrimaryDataTest(PrimaryKeyType::SINGLE_PRIMARY_KEY); + } + + /** + * @tc.name: GetInfoByPrimaryKeyOrGidTest013 + * @tc.desc: Test GetInfoByPrimaryKeyOrGid when vbucket doesn't contain pk(composite pk) data and gid match, + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangshijie + */ + HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest013, TestSize.Level0) + { + VbucketWithoutPrimaryDataTest(PrimaryKeyType::COMPOSITE_PRIMARY_KEY); + } + void ConstructDownloadData(DownloadData &downloadData, GidType gidType, bool nullable, bool vBucketContains) { for (int i = 0; i < 7; i++) { // 7 is record counts @@ -559,7 +607,7 @@ namespace { */ HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest006, TestSize.Level0) { - SaveCloudDataTest(PrimaryKeyType::SINGLE_PRIMARY_KEY, GidType::GID_EMPTY); + SaveCloudDataTest(PrimaryKeyType::SINGLE_PRIMARY_KEY, GidType::GID_EMPTY, true, true, -E_CLOUD_ERROR); } /** @@ -572,7 +620,7 @@ namespace { */ HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest007, TestSize.Level0) { - SaveCloudDataTest(PrimaryKeyType::SINGLE_PRIMARY_KEY, GidType::GID_EMPTY, true, false); + SaveCloudDataTest(PrimaryKeyType::SINGLE_PRIMARY_KEY, GidType::GID_MATCH, true, false); } /** @@ -614,35 +662,23 @@ namespace { /** * @tc.name: PutCloudSyncDataTest011 - * @tc.desc: Test save cloud data into table with SINGLE_PRIMARY_KEY primary key, gid is empty, primary key mismatch - * @tc.type: FUNC - * @tc.require: - * @tc.author: zhangshijie - */ - HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest011, TestSize.Level0) - { - SaveCloudDataTest(PrimaryKeyType::SINGLE_PRIMARY_KEY, GidType::GID_EMPTY); - } - - /** - * @tc.name: PutCloudSyncDataTest012 * @tc.desc: Test save cloud data into table with composite primary key, invalid gid * @tc.type: FUNC * @tc.require: * @tc.author: zhangshijie */ - HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest012, TestSize.Level0) + HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest011, TestSize.Level0) { SaveCloudDataTest(PrimaryKeyType::COMPOSITE_PRIMARY_KEY, GidType::GID_INVALID, true, true, -E_CLOUD_ERROR); } void ConstructMultiDownloadData(DownloadData &downloadData, GidType gidType) { - for (int i = 0; i < 5; i++) { // 5 is record counts + for (int i = 0; i < 6; i++) { // 6 is record counts VBucket vBucket; - if (i == 0) { + if (i < 1) { // UPDATE_TIMESTAMP doesn't contain pk vBucket["id"] = 1L + i; - } else { + } else if (i > 1) { vBucket["id"] = 10L + i; // 10 is id offset for cloud data } @@ -654,7 +690,11 @@ namespace { vBucket["image"] = std::vector(1, i); std::string gid; if (gidType == GidType::GID_MATCH) { - gid = g_gid + std::to_string(i); + if (i <= 1) { // first 2 exists in local + gid = g_gid + std::to_string(i); + } else { + gid = g_gid + std::to_string(10 + i); // 10 is id offset for cloud data + } } else if (gidType == GidType::GID_EMPTY) { std::string emptyGid = ""; gid = emptyGid; @@ -663,25 +703,25 @@ namespace { } vBucket[CloudDbConstant::GID_FIELD] = gid; - int64_t cTime = 12345678L + i; + int64_t cTime = BASE_CREATE_TIME + i; vBucket[CloudDbConstant::CREATE_FIELD] = cTime; - int64_t mTime = 12345679L + i; + int64_t mTime = BASE_MODIFY_TIME + i; vBucket[CloudDbConstant::MODIFY_FIELD] = mTime; downloadData.data.push_back(vBucket); } - downloadData.opType = { OpType::UPDATE, OpType::INSERT, OpType::INSERT, + downloadData.opType = { OpType::UPDATE, OpType::UPDATE_TIMESTAMP, OpType::INSERT, OpType::INSERT, OpType::INSERT, OpType::NOT_HANDLE }; } /** - * @tc.name: PutCloudSyncDataTest013 + * @tc.name: PutCloudSyncDataTest012 * @tc.desc: Test save cloud data into table with no primary key, multi cloud data * @tc.type: FUNC * @tc.require: * @tc.author: zhangshijie */ - HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest013, TestSize.Level0) + HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest012, TestSize.Level0) { /** * @tc.steps:step1. create db, create table. @@ -702,4 +742,160 @@ namespace { EXPECT_EQ(storageProxy->PutCloudSyncData(g_tableName, downloadData), E_OK); EXPECT_EQ(storageProxy->Commit(), E_OK); } + + /** + * @tc.name: PutCloudSyncDataTest013 + * @tc.desc: Test save cloud data with type = update_timestamp + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangshijie + */ + HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest013, TestSize.Level0) + { + /** + * @tc.steps:step1. create db, create table. + * @tc.expected: step1. return ok. + */ + PrepareDataBase(g_tableName, PrimaryKeyType::SINGLE_PRIMARY_KEY, true); + + std::string sql = "delete from " + g_tableName + " where id = 2"; + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + EXPECT_NE(db, nullptr); + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + /** + * @tc.steps:step2. call PutCloudSyncData + * @tc.expected: step2. return ok. + */ + std::shared_ptr storageProxy = GetStorageProxy(g_cloudStore); + ASSERT_NE(storageProxy, nullptr); + EXPECT_EQ(storageProxy->StartTransaction(TransactType::IMMEDIATE), E_OK); + + DownloadData downloadData; + ConstructMultiDownloadData(downloadData, GidType::GID_MATCH); + EXPECT_EQ(storageProxy->PutCloudSyncData(g_tableName, downloadData), E_OK); + EXPECT_EQ(storageProxy->Commit(), E_OK); + + /** + * @tc.steps:step3. verify data + * @tc.expected: step3. verify data ok. + */ + sql = "select device, timestamp, flag from " + DBCommon::GetLogTableName(g_tableName) + + " where data_key = -1 and cloud_gid = ''"; + int count = 0; + int errCode = RelationalTestUtils::ExecSql(db, sql, nullptr, [&count] (sqlite3_stmt *stmt) { + std::string device = "cloud"; + std::vector deviceVec; + (void)SQLiteUtils::GetColumnBlobValue(stmt, 0, deviceVec); // 0 is device + std::string getDevice; + DBCommon::VectorToString(deviceVec, getDevice); + EXPECT_EQ(device, getDevice); + EXPECT_EQ(sqlite3_column_int64(stmt, 1), BASE_MODIFY_TIME + 1); + EXPECT_EQ(sqlite3_column_int(stmt, 2), 1); // 2 is flag + count++; + return OK; + }); + EXPECT_EQ(errCode, E_OK); + EXPECT_EQ(count, 1); + EXPECT_EQ(sqlite3_close_v2(db), E_OK); + } + + /** + * @tc.name: PutCloudSyncDataTest014 + * @tc.desc: Test PutCloudSyncData when vbucket doesn't contain pk data and gid match, + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangshijie + */ + HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest014, TestSize.Level0) + { + /** + * @tc.steps:step1. create db, create table. + * @tc.expected: step1. return ok. + */ + PrepareDataBase(g_tableName, PrimaryKeyType::SINGLE_PRIMARY_KEY); + + /** + * @tc.steps:step2. construct data without primary key value, call PutCloudSyncData. + * @tc.expected: step2. return E_OK. + */ + std::shared_ptr storageProxy = GetStorageProxy(g_cloudStore); + ASSERT_NE(storageProxy, nullptr); + EXPECT_EQ(storageProxy->StartTransaction(TransactType::IMMEDIATE), E_OK); + + DownloadData downloadData; + VBucket vBucket; + std::string gid = g_gid + std::to_string(0); + vBucket[CloudDbConstant::GID_FIELD] = gid; + vBucket[CloudDbConstant::MODIFY_FIELD] = BASE_MODIFY_TIME; + downloadData.data.push_back(vBucket); + downloadData.opType = { OpType::DELETE }; + EXPECT_EQ(storageProxy->PutCloudSyncData(g_tableName, downloadData), E_OK); + EXPECT_EQ(storageProxy->Commit(), E_OK); + } + + /** + * @tc.name: PutCloudSyncDataTest015 + * @tc.desc: Test clear gid and ONLY_UPDATE_GID + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangshijie + */ + HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest015, TestSize.Level0) + { + /** + * @tc.steps:step1. create db, create table. + * @tc.expected: step1. return ok. + */ + PrepareDataBase(g_tableName, PrimaryKeyType::SINGLE_PRIMARY_KEY); + + /** + * @tc.steps:step2. construct data type = clear_gid, call PutCloudSyncData. + * @tc.expected: step2. return E_OK. + */ + std::shared_ptr storageProxy = GetStorageProxy(g_cloudStore); + ASSERT_NE(storageProxy, nullptr); + EXPECT_EQ(storageProxy->StartTransaction(TransactType::IMMEDIATE), E_OK); + + DownloadData downloadData; + for (int i = 0; i < 2; i++) { // 2 is record count + VBucket vBucket; + std::string gid = g_gid + std::to_string(i * 4); // 4 is data index + vBucket[CloudDbConstant::GID_FIELD] = gid; + vBucket[CloudDbConstant::MODIFY_FIELD] = BASE_MODIFY_TIME; + downloadData.data.push_back(vBucket); + } + downloadData.opType = { OpType::ONLY_UPDATE_GID, OpType::CLEAR_GID }; + EXPECT_EQ(storageProxy->PutCloudSyncData(g_tableName, downloadData), E_OK); + EXPECT_EQ(storageProxy->Commit(), E_OK); + + /** + * @tc.steps:step3. verify data + * @tc.expected: step3. verify data ok. + */ + std::string sql = "select cloud_gid, flag from " + DBCommon::GetLogTableName(g_tableName) + + " where data_key = 1 or data_key = 5"; + int count = 0; + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + EXPECT_NE(db, nullptr); + int errCode = RelationalTestUtils::ExecSql(db, sql, nullptr, [&count] (sqlite3_stmt *stmt) { + std::string gid = ""; + if (count == 0) { + gid = g_gid + "0"; + } + const unsigned char *val = sqlite3_column_text(stmt, 0); + EXPECT_TRUE(val != nullptr); + std::string getGid = reinterpret_cast(val); + LOGD("GET GID = %s", getGid.c_str()); + EXPECT_EQ(getGid, gid); + if (count == 1) { + int flag = sqlite3_column_int(stmt, 1); + EXPECT_EQ(flag & 0x04, 0); // 0x04 is binay num of b100, clear gid will clear 2th bit of flag + } + count++; + return OK; + }); + EXPECT_EQ(errCode, E_OK); + EXPECT_EQ(count, 2); // 2 is result count + EXPECT_EQ(sqlite3_close_v2(db), E_OK); + } } diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_cloud_syncable_storage_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_cloud_syncable_storage_test.cpp index 7044a4830aab27522ddfc5eb4686a5d6a6b15d1b..b41bc2c5c68823f22284b39e45467051ae9025e2 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_cloud_syncable_storage_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_cloud_syncable_storage_test.cpp @@ -105,9 +105,13 @@ void CreateAndInitUserTable(int64_t count, int64_t photoSize) std::string photo(photoSize, 'v'); std::vector assetBlob; std::vector assetsBlob; + Asset asset = g_localAsset; + int id = 0; Assets assets; - assets.push_back(g_localAsset); - assets.push_back(g_localAsset); + asset.name = g_localAsset.name + std::to_string(id++); + assets.push_back(asset); + asset.name = g_localAsset.name + std::to_string(id++); + assets.push_back(asset); int errCode; ASSERT_EQ(RuntimeContext::GetInstance()->AssetToBlob(g_localAsset, assetBlob), E_OK); ASSERT_EQ(RuntimeContext::GetInstance()->AssetsToBlob(assets, assetsBlob), E_OK); @@ -158,7 +162,7 @@ void InitLogData(int64_t insCount, int64_t updCount, int64_t delCount, int64_t e sqlite3_close(db); } -void UpdateLogGid(int64_t count) +void InitLogGid(int64_t count) { sqlite3 *db = nullptr; ASSERT_EQ(sqlite3_open(g_storePath.c_str(), &db), SQLITE_OK); @@ -212,7 +216,7 @@ void SetDbSchema(const TableSchema &tableSchema) EXPECT_EQ(g_cloudStore->SetCloudDbSchema(dataBaseSchema), E_OK); } -void InitUserAndLogForAsset(int64_t insCount, int64_t photoSize) +void InitUserDataForAssetTest(int64_t insCount, int64_t photoSize) { sqlite3 *db = nullptr; ASSERT_EQ(sqlite3_open(g_storePath.c_str(), &db), SQLITE_OK); @@ -220,7 +224,6 @@ void InitUserAndLogForAsset(int64_t insCount, int64_t photoSize) sqlite3_close(db); EXPECT_EQ(g_delegate->CreateDistributedTable(g_tableName, DistributedDB::CLOUD_COOPERATION), OK); CreateAndInitUserTable(insCount, photoSize); - UpdateLogGid(insCount); SetDbSchema(g_tableSchema); } @@ -990,7 +993,8 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetInfoByPrimaryKeyOrG { int64_t insCount = 100; int64_t photoSize = 10; - InitUserAndLogForAsset(insCount, photoSize); + InitUserDataForAssetTest(insCount, photoSize); + InitLogGid(insCount); EXPECT_EQ(g_storageProxy->StartTransaction(), E_OK); for (int i = 1; i <= insCount; i++) { @@ -1007,8 +1011,9 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetInfoByPrimaryKeyOrG Asset asset = std::get(entry1->second); EXPECT_EQ(asset.name, "Phone"); Assets assets = std::get(entry2->second); + int id = 0; for (const auto &item: assets) { - EXPECT_EQ(item.name, "Phone"); + EXPECT_EQ(item.name, "Phone" + std::to_string(id++)); } } EXPECT_EQ(g_storageProxy->Commit(), E_OK); @@ -1018,7 +1023,8 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, PutCloudSyncData001, T { int64_t insCount = 10; int64_t photoSize = 10; - InitUserAndLogForAsset(insCount, photoSize); + InitUserDataForAssetTest(insCount, photoSize); + InitLogGid(insCount); DownloadData downloadData; ConstructMultiDownloadData(insCount, downloadData); @@ -1034,7 +1040,8 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, FillCloudAsset001, Tes { int64_t insCount = 10; int64_t photoSize = 10; - InitUserAndLogForAsset(insCount, photoSize); + InitUserDataForAssetTest(insCount, photoSize); + InitLogGid(insCount); fillCloudAssetTest(insCount, AssetStatus::NORMAL, false); fillCloudAssetTest(insCount, AssetStatus::DOWNLOADING, false); fillCloudAssetTest(insCount, AssetStatus::ABNORMAL, false); @@ -1047,7 +1054,8 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, FillCloudAsset002, Tes { int64_t insCount = 10; int64_t photoSize = 10; - InitUserAndLogForAsset(insCount, photoSize); + InitUserDataForAssetTest(insCount, photoSize); + InitLogGid(insCount); sqlite3 *db = nullptr; ASSERT_EQ(sqlite3_open(g_storePath.c_str(), &db), SQLITE_OK); @@ -1060,6 +1068,8 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, FillCloudAsset002, Tes SQLiteUtils::ResetStatement(stmt, true, errCode); CloudSyncData syncData(g_tableName); + EXPECT_EQ(g_storageProxy->StartTransaction(), E_OK); + ASSERT_EQ(g_storageProxy->FillCloudGidAndAsset(OpType::UPDATE, syncData), E_OK); syncData.updData.rowid.push_back(1L); VBucket bucket1; Asset asset = g_localAsset; @@ -1073,7 +1083,8 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, FillCloudAsset002, Tes bucket1.insert_or_assign("asserts", assets); syncData.updData.assets.push_back(bucket1); syncData.updData.timestamp.push_back(timeStamp); - ASSERT_EQ(g_storageProxy->FillCloudAssetForUpload(syncData), E_OK); + ASSERT_EQ(g_storageProxy->FillCloudGidAndAsset(OpType::UPDATE, syncData), E_OK); + EXPECT_EQ(g_storageProxy->Commit(), E_OK); ASSERT_EQ(SQLiteUtils::GetStatement(db, "SELECT assert, asserts FROM " + g_tableName + " WHERE rowid = 1;", stmt), E_OK); @@ -1083,5 +1094,102 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, FillCloudAsset002, Tes SQLiteUtils::ResetStatement(stmt, true, errCode); sqlite3_close(db); } + +/** + * @tc.name: FillCloudAsset003 + * @tc.desc: The twice fill have different assert columns + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, FillCloudAsset003, TestSize.Level0) +{ + int64_t insCount = 2; + int64_t photoSize = 10; + InitUserDataForAssetTest(insCount, photoSize); + InitLogGid(insCount); + + sqlite3 *db = nullptr; + ASSERT_EQ(sqlite3_open(g_storePath.c_str(), &db), SQLITE_OK); + sqlite3_stmt *stmt = nullptr; + ASSERT_EQ(SQLiteUtils::GetStatement(db, "SELECT timestamp FROM " + DBCommon::GetLogTableName(g_tableName) + + " WHERE data_key in ('1', '2');", stmt), E_OK); + ASSERT_EQ(SQLiteUtils::StepWithRetry(stmt, false), SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)); + int64_t timeStamp1 = static_cast(sqlite3_column_int64(stmt, 0)); + int64_t timeStamp2 = static_cast(sqlite3_column_int64(stmt, 1)); + int errCode; + SQLiteUtils::ResetStatement(stmt, true, errCode); + sqlite3_close(db); + + CloudSyncData syncData(g_tableName); + syncData.updData.rowid.push_back(1L); + syncData.updData.rowid.push_back(2L); + VBucket bucket1, bucket2; + Asset asset = g_localAsset; + asset.size = "888"; + asset.status = static_cast(AssetStatus::UPDATE); + Assets assets; + assets.push_back(asset); + assets.push_back(asset); + bucket1.insert_or_assign("assert", asset); + bucket2.insert_or_assign("assert", asset); + bucket2.insert_or_assign("asserts", assets); + syncData.updData.assets.push_back(bucket1); + syncData.updData.assets.push_back(bucket2); + syncData.updData.timestamp.push_back(timeStamp1); + syncData.updData.timestamp.push_back(timeStamp2); + EXPECT_EQ(g_storageProxy->StartTransaction(), E_OK); + ASSERT_EQ(g_storageProxy->FillCloudGidAndAsset(OpType::UPDATE, syncData), E_OK); + EXPECT_EQ(g_storageProxy->Commit(), E_OK); +} + +/** + * @tc.name: FillCloudAsset004 + * @tc.desc: Test fill asset for insert type + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, FillCloudAsset004, TestSize.Level0) +{ + int64_t insCount = 2; + int64_t photoSize = 10; + InitUserDataForAssetTest(insCount, photoSize); + + sqlite3 *db = nullptr; + ASSERT_EQ(sqlite3_open(g_storePath.c_str(), &db), SQLITE_OK); + sqlite3_stmt *stmt = nullptr; + ASSERT_EQ(SQLiteUtils::GetStatement(db, "SELECT timestamp FROM " + DBCommon::GetLogTableName(g_tableName) + + " WHERE data_key in ('1', '2');", stmt), E_OK); + ASSERT_EQ(SQLiteUtils::StepWithRetry(stmt, false), SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)); + std::vector timeVector; + timeVector.push_back(static_cast(sqlite3_column_int64(stmt, 0))); + timeVector.push_back(static_cast(sqlite3_column_int64(stmt, 1))); + int errCode; + SQLiteUtils::ResetStatement(stmt, true, errCode); + sqlite3_close(db); + + CloudSyncData syncData(g_tableName); + for (int64_t i = 1; i <= insCount; ++i) { + syncData.insData.rowid.push_back(i); + VBucket bucket1; + bucket1.insert_or_assign(CloudDbConstant::GID_FIELD, std::to_string(i)); + syncData.insData.extend.push_back(bucket1); + + VBucket bucket2; + Asset asset = g_localAsset; + asset.size = "888"; + Assets assets; + assets.push_back(asset); + assets.push_back(asset); + bucket2.insert_or_assign("assert", asset); + bucket2.insert_or_assign("asserts", assets); + syncData.insData.assets.push_back(bucket2); + syncData.insData.timestamp.push_back(timeVector[i - 1]); + } + EXPECT_EQ(g_storageProxy->StartTransaction(), E_OK); + ASSERT_EQ(g_storageProxy->FillCloudGidAndAsset(OpType::INSERT, syncData), E_OK); + EXPECT_EQ(g_storageProxy->Commit(), E_OK); +} } #endif // RELATIONAL_STORE \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/cloud_syncer_test.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/cloud_syncer_test.h index 54400fce54c2bc217be982d4559d09d61260cce3..9175fdb43f4b76e27bb50f3efc0172d072985a43 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/cloud_syncer_test.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/cloud_syncer_test.h @@ -45,7 +45,7 @@ public: cloudTaskInfos_[taskId].taskId = taskId; currentContext_.currentTaskId = taskId; currentContext_.tableName = "TestTable" + std::to_string(taskId); - currentContext_.notifier = std::make_shared(); + currentContext_.notifier = std::make_shared(this); currentContext_.notifier->Init({currentContext_.tableName}, { "cloud" }); currentContext_.strategy = std::make_shared(); closed_ = false; @@ -224,9 +224,14 @@ public: } std::map TestTagAssetsInSingleRecord( - VBucket &CoveredData, VBucket &BeCoveredData, bool WriteToCoveredData = false) + VBucket &coveredData, VBucket &beCoveredData, bool WriteToCoveredData = false) { - return TagAssetsInSingleRecord(CoveredData, BeCoveredData, WriteToCoveredData); + return TagAssetsInSingleRecord(coveredData, beCoveredData, WriteToCoveredData); + } + + bool TestIsDataContainDuplicateAsset(std::vector &assetFields, VBucket &data) + { + return IsDataContainDuplicateAsset(assetFields, data); } void SetCloudWaterMarks(const TableName &tableName, const CloudWaterMark &mark) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_asset_compare_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_asset_compare_test.cpp index 921b4917e400e822f62b40695713b55d2b82c196..a07dfc008866d2a53566bba8acfd7e91d47723df 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_asset_compare_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_asset_compare_test.cpp @@ -73,6 +73,10 @@ namespace { VBucket DATA_NULL_ASSET; VBucket DATA_ASSET_IN_ASSETS; VBucket DATA_NULL_ASSETS; + VBucket DATA_ALL_NULL_ASSETS; + VBucket DATA_EMPTY_ASSETS; + VBucket DATA_UPDATE_DELTE_NOCHANGE_INSERT; + VBucket DATA_SAME_NAME_ASSETS; Asset GenAsset(std::string name, std::string hash) { @@ -102,8 +106,9 @@ namespace { a3Changed = GenAsset("truck", "truck1Changed"); a4 = GenAsset("sedan", "sedan1"); a4Changed = GenAsset("sedan", "sedan1Changed"); - a5 = GenAsset("truck", "truck1"); - a5Changed = GenAsset("truck", "truck1Changed"); + a5 = GenAsset("trucker", "truck1"); + a5Changed = GenAsset("trucker", "truck1Changed"); + DATA_EMPTY.clear(); DATA_BASELINE = GenDatum(1, "Jack", a1, Assets({a2, a3, a4})); // id is 1 DATA_EMPTY_ASSET = GenDatum(2, "PoorGuy", a1, Assets({})); // id is 2 DATA_EMPTY_ASSET.erase(FIELD_HOUSE); @@ -119,7 +124,12 @@ namespace { std::monostate nil; DATA_NULL_ASSET = GenDatum(11, "Lob3", nil, Assets({a1, a2, a3})); // id is 11 DATA_ASSET_IN_ASSETS = GenDatum(12, "Lob4", Assets({a1}), Assets({a2, a3, a4})); // id is 12 - DATA_NULL_ASSETS = GenDatum(13, "Lob5", Assets({a1}), nil); // id is 12 + DATA_NULL_ASSETS = GenDatum(13, "Lob5", Assets({a1}), nil); // id is 13 + DATA_ALL_NULL_ASSETS = GenDatum(14, "Nico", nil, nil); // id is 14 + DATA_EMPTY_ASSETS = GenDatum(15, "Lob6", a1, Assets({})); // id is 15 + DATA_EMPTY_ASSETS.erase(FIELD_CARS); + DATA_UPDATE_DELTE_NOCHANGE_INSERT = GenDatum(16, "Nico321", nil, Assets({a2Changed, a4, a5})); // id is 16 + DATA_SAME_NAME_ASSETS = GenDatum(16, "Nico156", nil, Assets({a1, a1Changed})); // id is 16 } void CreateDB() @@ -292,7 +302,7 @@ namespace { std::map expectedList; TagAsset(AssetOpType::UPDATE, AssetStatus::DOWNLOADING, a1); expectedList[FIELD_HOUSE] = { a1 }; - expectedList[FIELD_CARS] = {}; + expectedList[FIELD_CARS] = { a2, a3, a4 }; ASSERT_TRUE(CheckAssetDownloadList(FIELD_HOUSE, assetList, expectedList)); ASSERT_TRUE(CheckAssetDownloadList(FIELD_CARS, assetList, expectedList)); } @@ -311,7 +321,7 @@ namespace { std::map expectedList; TagAsset(AssetOpType::UPDATE, AssetStatus::DOWNLOADING, a3); expectedList[FIELD_HOUSE] = {}; - expectedList[FIELD_CARS] = { a3 }; + expectedList[FIELD_CARS] = { a2, a3, a4 }; ASSERT_TRUE(CheckAssetDownloadList(FIELD_HOUSE, assetList, expectedList)); ASSERT_TRUE(CheckAssetDownloadList(FIELD_CARS, assetList, expectedList)); } @@ -329,7 +339,7 @@ namespace { DATA_BASELINE, DATA_ALL_SAME); std::map expectedList; expectedList[FIELD_HOUSE] = {}; - expectedList[FIELD_CARS] = {}; + expectedList[FIELD_CARS] = { a2, a3, a4 }; ASSERT_TRUE(CheckAssetDownloadList(FIELD_HOUSE, assetList, expectedList)); ASSERT_TRUE(CheckAssetDownloadList(FIELD_CARS, assetList, expectedList)); } @@ -348,7 +358,7 @@ namespace { std::map expectedList; TagAsset(AssetOpType::DELETE, AssetStatus::DOWNLOADING, a5); expectedList[FIELD_HOUSE] = {}; - expectedList[FIELD_CARS] = { a5 }; + expectedList[FIELD_CARS] = { a2, a3, a4, a5 }; ASSERT_TRUE(CheckAssetDownloadList(FIELD_HOUSE, assetList, expectedList)); ASSERT_TRUE(CheckAssetDownloadList(FIELD_CARS, assetList, expectedList)); } @@ -368,7 +378,7 @@ namespace { TagAsset(AssetOpType::DELETE, AssetStatus::DOWNLOADING, a5); TagAsset(AssetOpType::INSERT, AssetStatus::DOWNLOADING, a4); expectedList[FIELD_HOUSE] = {}; - expectedList[FIELD_CARS] = { a5, a4 }; + expectedList[FIELD_CARS] = { a2, a3, a5, a4 }; ASSERT_TRUE(CheckAssetDownloadList(FIELD_HOUSE, assetList, expectedList)); ASSERT_TRUE(CheckAssetDownloadList(FIELD_CARS, assetList, expectedList)); } @@ -389,7 +399,7 @@ namespace { TagAsset(AssetOpType::DELETE, AssetStatus::DOWNLOADING, a5); TagAsset(AssetOpType::INSERT, AssetStatus::DOWNLOADING, a4); expectedList[FIELD_HOUSE] = {}; - expectedList[FIELD_CARS] = { a3, a5, a4 }; + expectedList[FIELD_CARS] = { a2, a3, a5, a4 }; ASSERT_TRUE(CheckAssetDownloadList(FIELD_HOUSE, assetList, expectedList)); ASSERT_TRUE(CheckAssetDownloadList(FIELD_CARS, assetList, expectedList)); } @@ -496,8 +506,10 @@ namespace { TagAsset(AssetOpType::NO_CHANGE, AssetStatus::DOWNLOADING, a2); TagAsset(AssetOpType::NO_CHANGE, AssetStatus::DOWNLOADING, a3); TagAsset(AssetOpType::NO_CHANGE, AssetStatus::DOWNLOADING, a4); - expectedList[FIELD_HOUSE] = {}; - expectedList[FIELD_CARS] = {}; + a2.status = static_cast(AssetStatus::NORMAL); + a3.status = static_cast(AssetStatus::NORMAL); + a4.status = static_cast(AssetStatus::NORMAL); + expectedList[FIELD_CARS] = {a2, a3, a4}; ASSERT_TRUE(CheckAssetDownloadList(FIELD_HOUSE, assetList, expectedList)); ASSERT_TRUE(CheckAssetDownloadList(FIELD_CARS, assetList, expectedList)); } @@ -538,7 +550,7 @@ namespace { std::map expectedList; TagAsset(AssetOpType::UPDATE, AssetStatus::DOWNLOADING, a1Changed); expectedList[FIELD_HOUSE] = { a1Changed }; - expectedList[FIELD_CARS] = {}; + expectedList[FIELD_CARS] = {a2, a3, a4}; ASSERT_TRUE(CheckAssetDownloadList(FIELD_HOUSE, assetList, expectedList)); ASSERT_TRUE(CheckAssetDownloadList(FIELD_CARS, assetList, expectedList)); } @@ -604,4 +616,217 @@ namespace { EXPECT_EQ(std::get(DATA_EMPTY[FIELD_CARS])[1].flag, static_cast(AssetOpType::DELETE)); EXPECT_EQ(std::get(DATA_EMPTY[FIELD_CARS])[2].flag, static_cast(AssetOpType::DELETE)); } + + /** + * @tc.name: AssetCmpTest020 + * @tc.desc: + * @tc.type: FUNC + * @tc.require: + * @tc.author: wanyi + */ + HWTEST_F(DistributedDBCloudAssetCompareTest, AssetCmpTest020, TestSize.Level0) + { + auto assetList = g_cloudSyncer->TestTagAssetsInSingleRecord( + DATA_ALL_NULL_ASSETS, DATA_BASELINE, true); + EXPECT_EQ(std::get(DATA_BASELINE[FIELD_HOUSE]).flag, static_cast(AssetOpType::DELETE)); + EXPECT_EQ(std::get(DATA_ALL_NULL_ASSETS[FIELD_CARS])[0].flag, + static_cast(AssetOpType::DELETE)); + EXPECT_EQ(std::get(DATA_ALL_NULL_ASSETS[FIELD_CARS])[1].flag, + static_cast(AssetOpType::DELETE)); + EXPECT_EQ(std::get(DATA_ALL_NULL_ASSETS[FIELD_CARS])[2].flag, + static_cast(AssetOpType::DELETE)); + + std::map expectedList; + TagAsset(AssetOpType::DELETE, AssetStatus::NORMAL, a1); + TagAsset(AssetOpType::DELETE, AssetStatus::NORMAL, a2); + TagAsset(AssetOpType::DELETE, AssetStatus::NORMAL, a3); + TagAsset(AssetOpType::DELETE, AssetStatus::NORMAL, a4); + expectedList[FIELD_HOUSE] = { a1 }; + expectedList[FIELD_CARS] = { a2, a3, a4 }; + ASSERT_TRUE(CheckAssetDownloadList(FIELD_HOUSE, assetList, expectedList)); + ASSERT_TRUE(CheckAssetDownloadList(FIELD_CARS, assetList, expectedList)); + } + + /** + * @tc.name: AssetCmpTest021 + * @tc.desc: + * @tc.type: FUNC + * @tc.require: + * @tc.author: wanyi + */ + HWTEST_F(DistributedDBCloudAssetCompareTest, AssetCmpTest021, TestSize.Level0) + { + auto assetList = g_cloudSyncer->TestTagAssetsInSingleRecord( + DATA_ALL_NULL_ASSETS, DATA_ALL_NULL_ASSETS, true); + ASSERT_TRUE(DATA_ALL_NULL_ASSETS[FIELD_HOUSE].index() == TYPE_INDEX); + ASSERT_TRUE(DATA_ALL_NULL_ASSETS[FIELD_CARS].index() == TYPE_INDEX); + + std::map expectedList; + expectedList[FIELD_HOUSE] = {}; + expectedList[FIELD_CARS] = {}; + ASSERT_TRUE(CheckAssetDownloadList(FIELD_HOUSE, assetList, expectedList)); + ASSERT_TRUE(CheckAssetDownloadList(FIELD_CARS, assetList, expectedList)); + } + + /** + * @tc.name: AssetCmpTest022 + * @tc.desc: + * @tc.type: FUNC + * @tc.require: + * @tc.author: wanyi + */ + HWTEST_F(DistributedDBCloudAssetCompareTest, AssetCmpTest022, TestSize.Level0) + { + auto assetList = g_cloudSyncer->TestTagAssetsInSingleRecord( + DATA_BASELINE, DATA_ALL_NULL_ASSETS, true); + EXPECT_EQ(std::get(DATA_BASELINE[FIELD_HOUSE]).flag, static_cast(AssetOpType::INSERT)); + EXPECT_EQ(std::get(DATA_BASELINE[FIELD_CARS])[0].flag, static_cast(AssetOpType::INSERT)); + EXPECT_EQ(std::get(DATA_BASELINE[FIELD_CARS])[1].flag, static_cast(AssetOpType::INSERT)); + EXPECT_EQ(std::get(DATA_BASELINE[FIELD_CARS])[2].flag, static_cast(AssetOpType::INSERT)); + + std::map expectedList; + TagAsset(AssetOpType::INSERT, AssetStatus::NORMAL, a1); + TagAsset(AssetOpType::INSERT, AssetStatus::NORMAL, a2); + TagAsset(AssetOpType::INSERT, AssetStatus::NORMAL, a3); + TagAsset(AssetOpType::INSERT, AssetStatus::NORMAL, a4); + expectedList[FIELD_HOUSE] = { a1 }; + expectedList[FIELD_CARS] = { a2, a3, a4 }; + ASSERT_TRUE(CheckAssetDownloadList(FIELD_HOUSE, assetList, expectedList)); + ASSERT_TRUE(CheckAssetDownloadList(FIELD_CARS, assetList, expectedList)); + } + + /** + * @tc.name: AssetCmpTest023 + * @tc.desc: + * @tc.type: FUNC + * @tc.require: + * @tc.author: wanyi + */ + HWTEST_F(DistributedDBCloudAssetCompareTest, AssetCmpTest023, TestSize.Level0) + { + auto assetList = g_cloudSyncer->TestTagAssetsInSingleRecord( + DATA_ASSET_SAME_NAME_BUT_CHANGE, DATA_BASELINE, true); + EXPECT_EQ(std::get(DATA_ASSET_SAME_NAME_BUT_CHANGE[FIELD_HOUSE]).flag, + static_cast(AssetOpType::UPDATE)); + EXPECT_EQ(std::get(DATA_ASSET_SAME_NAME_BUT_CHANGE[FIELD_CARS])[0].flag, + static_cast(AssetOpType::NO_CHANGE)); + EXPECT_EQ(std::get(DATA_ASSET_SAME_NAME_BUT_CHANGE[FIELD_CARS])[1].flag, + static_cast(AssetOpType::NO_CHANGE)); + EXPECT_EQ(std::get(DATA_ASSET_SAME_NAME_BUT_CHANGE[FIELD_CARS])[2].flag, + static_cast(AssetOpType::NO_CHANGE)); + } + + /** + * @tc.name: AssetCmpTest024 + * @tc.desc: + * @tc.type: FUNC + * @tc.require: + * @tc.author: wanyi + */ + HWTEST_F(DistributedDBCloudAssetCompareTest, AssetCmpTest024, TestSize.Level0) + { + auto assetList = g_cloudSyncer->TestTagAssetsInSingleRecord( + DATA_ASSETS_DIFFERENT_CHANGED_FIELD, DATA_BASELINE, true); + EXPECT_EQ(std::get(DATA_ASSETS_DIFFERENT_CHANGED_FIELD[FIELD_HOUSE]).flag, + static_cast(AssetOpType::NO_CHANGE)); + EXPECT_EQ(std::get(DATA_ASSETS_DIFFERENT_CHANGED_FIELD[FIELD_CARS])[0].flag, + static_cast(AssetOpType::NO_CHANGE)); + EXPECT_EQ(std::get(DATA_ASSETS_DIFFERENT_CHANGED_FIELD[FIELD_CARS])[1].flag, + static_cast(AssetOpType::UPDATE)); + EXPECT_EQ(std::get(DATA_ASSETS_DIFFERENT_CHANGED_FIELD[FIELD_CARS])[2].flag, + static_cast(AssetOpType::INSERT)); + EXPECT_EQ(std::get(DATA_ASSETS_DIFFERENT_CHANGED_FIELD[FIELD_CARS])[3].flag, + static_cast(AssetOpType::DELETE)); + } + + /** + * @tc.name: AssetCmpTest025 + * @tc.desc: Cloud device contain a record without assets, local device insert an assets and begin to sync. + * CloudAsset will be a record without assets. Local data will be a record with assets. + * @tc.type: FUNC + * @tc.require: + * @tc.author: wanyi + */ + HWTEST_F(DistributedDBCloudAssetCompareTest, AssetCmpTest025, TestSize.Level0) + { + auto assetList = g_cloudSyncer->TestTagAssetsInSingleRecord(DATA_BASELINE, DATA_NULL_ASSETS, true); + EXPECT_EQ(std::get(DATA_BASELINE[FIELD_HOUSE]).flag, static_cast(AssetOpType::NO_CHANGE)); + EXPECT_EQ(std::get(DATA_BASELINE[FIELD_CARS])[0].flag, static_cast(AssetOpType::INSERT)); + EXPECT_EQ(std::get(DATA_BASELINE[FIELD_CARS])[1].flag, static_cast(AssetOpType::INSERT)); + EXPECT_EQ(std::get(DATA_BASELINE[FIELD_CARS])[2].flag, static_cast(AssetOpType::INSERT)); + } + + /** + * @tc.name: AssetCmpTest026 + * @tc.desc: Cloud device contain a record without assets, local device insert an assets and begin to sync. + * CloudAsset will be a record without assets. Local data will be a record with assets. + * In this case, record do not contain certain asset column + * @tc.type: FUNC + * @tc.require: + * @tc.author: wanyi + */ + HWTEST_F(DistributedDBCloudAssetCompareTest, AssetCmpTest026, TestSize.Level0) + { + auto assetList = g_cloudSyncer->TestTagAssetsInSingleRecord(DATA_BASELINE, DATA_EMPTY_ASSETS, true); + EXPECT_EQ(std::get(DATA_BASELINE[FIELD_HOUSE]).flag, static_cast(AssetOpType::NO_CHANGE)); + EXPECT_EQ(std::get(DATA_BASELINE[FIELD_CARS])[0].flag, static_cast(AssetOpType::INSERT)); + EXPECT_EQ(std::get(DATA_BASELINE[FIELD_CARS])[1].flag, static_cast(AssetOpType::INSERT)); + EXPECT_EQ(std::get(DATA_BASELINE[FIELD_CARS])[2].flag, static_cast(AssetOpType::INSERT)); + } + + /** + * @tc.name: AssetCmpTest027 + * @tc.desc: + * @tc.type: FUNC + * @tc.require: + * @tc.author: wanyi + */ + HWTEST_F(DistributedDBCloudAssetCompareTest, AssetCmpTest027, TestSize.Level0) + { + auto assetList = g_cloudSyncer->TestTagAssetsInSingleRecord( + DATA_UPDATE_DELTE_NOCHANGE_INSERT, DATA_BASELINE, false); + EXPECT_EQ(std::get(DATA_UPDATE_DELTE_NOCHANGE_INSERT[FIELD_CARS])[0].flag, + static_cast(AssetOpType::UPDATE)); + EXPECT_EQ(std::get(DATA_UPDATE_DELTE_NOCHANGE_INSERT[FIELD_CARS])[1].flag, + static_cast(AssetOpType::NO_CHANGE)); + EXPECT_EQ(std::get(DATA_UPDATE_DELTE_NOCHANGE_INSERT[FIELD_CARS])[2].flag, + static_cast(AssetOpType::INSERT)); + EXPECT_EQ(std::get(DATA_UPDATE_DELTE_NOCHANGE_INSERT[FIELD_CARS])[3].flag, + static_cast(AssetOpType::DELETE)); + } + + /** + * @tc.name: AssetCmpTest028 + * @tc.desc: Two same name asset appears in the assets field, this situation is not allowed + * @tc.type: FUNC + * @tc.require: + * @tc.author: wanyi + */ + HWTEST_F(DistributedDBCloudAssetCompareTest, AssetCmpTest028, TestSize.Level0) + { + auto assetList = g_cloudSyncer->TestTagAssetsInSingleRecord( + DATA_ALL_NULL_ASSETS, DATA_BASELINE, true); + EXPECT_EQ(std::get(DATA_ALL_NULL_ASSETS[FIELD_CARS])[0].flag, + static_cast(AssetOpType::DELETE)); + EXPECT_EQ(std::get(DATA_ALL_NULL_ASSETS[FIELD_CARS])[1].flag, + static_cast(AssetOpType::DELETE)); + EXPECT_EQ(std::get(DATA_ALL_NULL_ASSETS[FIELD_CARS])[2].flag, + static_cast(AssetOpType::DELETE)); + } + + /** + * @tc.name: AssetCmpTest029 + * @tc.desc: Two same name asset appears in the assets field, this situation is not allowed + * @tc.type: FUNC + * @tc.require: + * @tc.author: wanyi + */ + HWTEST_F(DistributedDBCloudAssetCompareTest, AssetCmpTest029, TestSize.Level0) + { + Field field1 = { FIELD_HOUSE, TYPE_INDEX }; + Field field2 = { FIELD_CARS, TYPE_INDEX }; + std::vector assetFields = { field1, field2 }; + ASSERT_TRUE(g_cloudSyncer->TestIsDataContainDuplicateAsset(assetFields, DATA_SAME_NAME_ASSETS)); + ASSERT_TRUE(g_cloudSyncer->TestIsDataContainDuplicateAsset(assetFields, DATA_BASELINE) == false); + } } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_db_proxy_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_db_proxy_test.cpp index 02e98239bc45b0fdae44d9ed7abea5e084584033..80458c5b45b520993cf6373da1b157bc4e3394de 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_db_proxy_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_db_proxy_test.cpp @@ -20,6 +20,7 @@ #include "cloud_db_types.h" #include "cloud_db_proxy.h" #include "distributeddb_tools_unit_test.h" +#include "kv_store_errno.h" #include "mock_icloud_sync_storage_interface.h" #include "virtual_cloud_db.h" #include "virtual_cloud_syncer.h" @@ -423,4 +424,146 @@ HWTEST_F(DistributedDBCloudDBProxyTest, CloudDBProxyTest006, TestSize.Level3) cloudSyncer->Close(); RefObject::KillAndDecObjRef(cloudSyncer); } + +/** + * @tc.name: CloudDBProxyTest007 + * @tc.desc: Verify syncer close after notify finish. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBCloudDBProxyTest, CloudDBProxyTest007, TestSize.Level4) +{ + /** + * @tc.steps: step1. set cloud db to proxy + * @tc.expected: step1. E_OK + */ + auto iCloud = std::make_shared(); + auto cloudSyncer = new(std::nothrow) VirtualCloudSyncer(StorageProxy::GetCloudDb(iCloud.get())); + EXPECT_CALL(*iCloud, StartTransaction).WillRepeatedly(testing::Return(E_OK)); + EXPECT_CALL(*iCloud, Commit).WillRepeatedly(testing::Return(E_OK)); + ASSERT_NE(cloudSyncer, nullptr); + ASSERT_EQ(cloudSyncer->SetCloudDB(virtualCloudDb_), E_OK); + cloudSyncer->SetSyncAction(false, false); + /** + * @tc.steps: step2. call sync and wait sync finish + * @tc.expected: step2. notify before close finished + */ + std::atomic close = false; + int callCount = 0; + std::mutex callMutex; + std::condition_variable cv; + const auto callback = [&close, &callCount, &callMutex, &cv]( + const std::map &) { + std::this_thread::sleep_for(std::chrono::seconds(5)); // block notify 5s + { + std::lock_guard autoLock(callMutex); + callCount++; + } + cv.notify_all(); + EXPECT_EQ(close, false); + }; + EXPECT_EQ(cloudSyncer->Sync({ "cloud" }, SyncMode::SYNC_MODE_CLOUD_MERGE, { TABLE_NAME }, callback, 0), E_OK); + /** + * @tc.steps: step3. wait notify finished + */ + std::this_thread::sleep_for(std::chrono::seconds(2)); // block 2s + cloudSyncer->Close(); + close = true; + { + LOGI("begin to wait sync"); + std::unique_lock uniqueLock(callMutex); + cv.wait(uniqueLock, [&callCount]() { + return callCount > 0; + }); + LOGI("end to wait sync"); + } + RefObject::KillAndDecObjRef(cloudSyncer); +} + +/** + * @tc.name: CloudDBProxyTest008 + * @tc.desc: Verify cloud db heartbeat with diff status. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBCloudDBProxyTest, CloudDBProxyTest008, TestSize.Level0) +{ + /** + * @tc.steps: step1. set cloud db to proxy + * @tc.expected: step1. E_OK + */ + CloudDBProxy proxy; + EXPECT_EQ(proxy.SetCloudDB(virtualCloudDb_), E_OK); + /** + * @tc.steps: step2. proxy heartbeat with diff status + */ + virtualCloudDb_->SetActionStatus(CLOUD_NETWORK_ERROR); + int errCode = proxy.HeartBeat(); + EXPECT_EQ(errCode, -E_CLOUD_NETWORK_ERROR); + EXPECT_EQ(TransferDBErrno(errCode), CLOUD_NETWORK_ERROR); + + virtualCloudDb_->SetActionStatus(CLOUD_SYNC_UNSET); + errCode = proxy.HeartBeat(); + EXPECT_EQ(errCode, -E_CLOUD_SYNC_UNSET); + EXPECT_EQ(TransferDBErrno(errCode), CLOUD_SYNC_UNSET); + + virtualCloudDb_->SetActionStatus(CLOUD_FULL_RECORDS); + errCode = proxy.HeartBeat(); + EXPECT_EQ(errCode, -E_CLOUD_FULL_RECORDS); + EXPECT_EQ(TransferDBErrno(errCode), CLOUD_FULL_RECORDS); + + virtualCloudDb_->SetActionStatus(CLOUD_LOCK_ERROR); + errCode = proxy.HeartBeat(); + EXPECT_EQ(errCode, -E_CLOUD_LOCK_ERROR); + EXPECT_EQ(TransferDBErrno(errCode), CLOUD_LOCK_ERROR); + + virtualCloudDb_->SetActionStatus(DB_ERROR); + errCode = proxy.HeartBeat(); + EXPECT_EQ(errCode, -E_CLOUD_ERROR); + EXPECT_EQ(TransferDBErrno(errCode), CLOUD_ERROR); + + /** + * @tc.steps: step3. proxy close cloud db + * @tc.expected: step3. E_OK + */ + EXPECT_EQ(proxy.Close(), E_OK); +} + +/** + * @tc.name: CloudSyncQueue001 + * @tc.desc: Verify sync task count decrease after sync finished. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBCloudDBProxyTest, CloudSyncQueue001, TestSize.Level2) +{ + /** + * @tc.steps: step1. set cloud db to proxy and sleep 5s when download + * @tc.expected: step1. E_OK + */ + auto iCloud = std::make_shared(); + ASSERT_NE(iCloud, nullptr); + auto cloudSyncer = new(std::nothrow) VirtualCloudSyncer(StorageProxy::GetCloudDb(iCloud.get())); + ASSERT_NE(cloudSyncer, nullptr); + EXPECT_CALL(*iCloud, Rollback).WillRepeatedly(testing::Return(E_OK)); + EXPECT_CALL(*iCloud, Commit).WillRepeatedly(testing::Return(E_OK)); + EXPECT_CALL(*iCloud, StartTransaction).WillRepeatedly(testing::Return(E_OK)); + ASSERT_EQ(cloudSyncer->SetCloudDB(virtualCloudDb_), E_OK); + cloudSyncer->SetSyncAction(true, false); + cloudSyncer->SetDownloadFunc([cloudSyncer]() { + EXPECT_EQ(cloudSyncer->GetQueueCount(), 1u); + std::this_thread::sleep_for(std::chrono::seconds(2)); // sleep 2s + return E_OK; + }); + /** + * @tc.steps: step2. call sync and wait sync finish + */ + int callCount = 0; + EXPECT_EQ(Sync(cloudSyncer, callCount), OK); + RuntimeContext::GetInstance()->StopTaskPool(); + EXPECT_EQ(callCount, 1); +} } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_strategy_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_strategy_test.cpp index ee15854e70e349b8bd3b155ceb8b5ac0a3d2dcc0..333284221bffae991cbd61ceb7201e777c4c63f0 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_strategy_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_strategy_test.cpp @@ -140,10 +140,26 @@ HWTEST_F(DistributedDBCloudStrategyTest, TagOpTyeTest001, TestSize.Level0) * @tc.expected: step8 not handle cloud record */ cloudInfo.flag = 0x01; // it means delete + EXPECT_EQ(strategy->TagSyncDataStatus(true, localInfo, cloudInfo), OpType::UPDATE_TIMESTAMP); + /** + * @tc.steps: step9. cloud is delete and local not exist + * @tc.expected: step9 not handle cloud record + */ + EXPECT_EQ(strategy->TagSyncDataStatus(false, localInfo, cloudInfo), OpType::NOT_HANDLE); + /** + * @tc.steps: step10. cloud is old and delete, local has gid + * @tc.expected: step10 clear gid + */ + localInfo.timestamp = 3u; // mark 3 means local is new + EXPECT_EQ(strategy->TagSyncDataStatus(true, localInfo, cloudInfo), OpType::CLEAR_GID); + /** + * @tc.steps: step10. cloud is old and delete, local has not gid + * @tc.expected: step10 not handle cloud record + */ + localInfo.cloudGid = ""; EXPECT_EQ(strategy->TagSyncDataStatus(true, localInfo, cloudInfo), OpType::NOT_HANDLE); } -#ifdef MANNUAL_SYNC_AND_CLEAN_CLOUD_DATA /** * @tc.name: TagOpTyeTest002 * @tc.desc: Verify local cover cloud strategy tag operation type function. @@ -185,7 +201,13 @@ HWTEST_F(DistributedDBCloudStrategyTest, TagOpTyeTest002, TestSize.Level0) * @tc.expected: step5. ONLY UPDATE GID */ cloudInfo.flag = 0x01; // it means delete - EXPECT_EQ(strategy->TagSyncDataStatus(true, localInfo, cloudInfo), OpType::ONLY_UPDATE_GID); + EXPECT_EQ(strategy->TagSyncDataStatus(true, localInfo, cloudInfo), OpType::NOT_HANDLE); + /** + * @tc.steps: step6. local has cloud record(with gid) but cloud flag is delete + * @tc.expected: step6. CLEAR_GID + */ + localInfo.cloudGid = "gid"; + EXPECT_EQ(strategy->TagSyncDataStatus(true, localInfo, cloudInfo), OpType::CLEAR_GID); } /** @@ -243,5 +265,30 @@ HWTEST_F(DistributedDBCloudStrategyTest, TagOpTyeTest003, TestSize.Level0) localInfo.cloudGid = "gid"; EXPECT_EQ(strategy->TagSyncDataStatus(true, localInfo, cloudInfo), OpType::UPDATE); } -#endif // MANNUAL_SYNC_AND_CLEAN_CLOUD_DATA +/** + * @tc.name: TagOpTyeTest004 + * @tc.desc: Verify cloud cover local strategy tag operation type function. + * @tc.type: FUNC + * @tc.require: + * @tc.author: huangboxin + */ +HWTEST_F(DistributedDBCloudStrategyTest, TagOpTyeTest004, TestSize.Level0) +{ + /** + * @tc.steps: step1. cloud cover local strategy + */ + auto strategy = StrategyFactory::BuildSyncStrategy(SyncMode::SYNC_MODE_CLOUD_FORCE_PULL); + ASSERT_NE(strategy, nullptr); + LogInfo localInfo; + LogInfo cloudInfo; + + cloudInfo.flag = 0x01; + localInfo.flag = 0x01; + localInfo.cloudGid = ""; + EXPECT_EQ(strategy->TagSyncDataStatus(true, localInfo, cloudInfo), OpType::UPDATE_TIMESTAMP); + + cloudInfo.flag = 0x00; + localInfo.flag = 0x01; + EXPECT_EQ(strategy->TagSyncDataStatus(true, localInfo, cloudInfo), OpType::INSERT); +} } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_download_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_download_test.cpp index ae15727a87ab764c26bfaa5b93b1c60aa157530b..8fb260e2bc5ace4ec1927fdf9a1d2dbb21757b9d 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_download_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_download_test.cpp @@ -543,10 +543,10 @@ HWTEST_F(DistributedDBCloudSyncerDownloadTest, DownloadMockQueryTest005, TestSiz EXPECT_CALL(*g_idb, Query(_, _, _)) .WillRepeatedly([](const std::string &, VBucket &, std::vector &data) { data = GetRetCloudData(0); // Gen 0 data - return OK; + return QUERY_END; }); int errCode = g_cloudSyncer->CallDoDownload(taskId); - EXPECT_EQ(errCode, -E_CLOUD_ERROR); + EXPECT_EQ(errCode, E_OK); } /** diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_upload_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_upload_test.cpp index 7e29a7617cd2b265994e968311ee20135d6b29e4..dafc63b7e3312404c4370317139b867d06532ff2 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_upload_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_upload_test.cpp @@ -45,6 +45,11 @@ static void CommonExpectCall(MockICloudSyncStorageInterface *iCloud) EXPECT_CALL(*iCloud, GetCloudDataNext(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetCloudDbSchema(_)).WillRepeatedly(Return(E_OK)); } +static void BatchExpectCall(MockICloudSyncStorageInterface *iCloud) +{ + EXPECT_CALL(*iCloud, PutMetaData(_, _)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, FillCloudGid(_)).WillRepeatedly(Return(E_OK)); +} class DistributedDBCloudSyncerUploadTest : public testing::Test { public: static void SetUpTestCase(void); @@ -81,9 +86,9 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck001, TestSize.Level1 { MockICloudSyncStorageInterface *iCloud = new MockICloudSyncStorageInterface(); std::shared_ptr storageProxy = std::make_shared(iCloud); - TestCloudSyncer cloudSyncer(storageProxy); + TestCloudSyncer *cloudSyncer = new(std::nothrow) TestCloudSyncer(storageProxy); std::shared_ptr idb = std::make_shared(); - cloudSyncer.SetMockICloudDB(idb); + cloudSyncer->SetMockICloudDB(idb); TaskId taskId = 1; EXPECT_CALL(*iCloud, GetMetaData(_, _)).WillRepeatedly(Return(E_OK)); @@ -95,32 +100,34 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck001, TestSize.Level1 EXPECT_CALL(*iCloud, GetCloudTableSchema(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetCloudData(_, _, _, _)).WillRepeatedly(Return(E_OK)); - cloudSyncer.InitCloudSyncer(taskId, SYNC_MODE_PUSH_ONLY); - int errCode = cloudSyncer.CallDoUpload(taskId); + cloudSyncer->InitCloudSyncer(taskId, SYNC_MODE_PUSH_ONLY); + int errCode = cloudSyncer->CallDoUpload(taskId); EXPECT_EQ(errCode, -E_INVALID_ARGS); - cloudSyncer.InitCloudSyncer(taskId, SYNC_MODE_PULL_ONLY); - errCode = cloudSyncer.CallDoUpload(taskId); + cloudSyncer->InitCloudSyncer(taskId, SYNC_MODE_PULL_ONLY); + errCode = cloudSyncer->CallDoUpload(taskId); EXPECT_EQ(errCode, -E_INVALID_ARGS); - cloudSyncer.InitCloudSyncer(taskId, SYNC_MODE_PUSH_PULL); - errCode = cloudSyncer.CallDoUpload(taskId); + cloudSyncer->InitCloudSyncer(taskId, SYNC_MODE_PUSH_PULL); + errCode = cloudSyncer->CallDoUpload(taskId); EXPECT_EQ(errCode, -E_INVALID_ARGS); - cloudSyncer.InitCloudSyncer(taskId, SYNC_MODE_CLOUD_MERGE); - errCode = cloudSyncer.CallDoUpload(taskId); + cloudSyncer->InitCloudSyncer(taskId, SYNC_MODE_CLOUD_MERGE); + errCode = cloudSyncer->CallDoUpload(taskId); EXPECT_EQ(errCode, E_OK); - cloudSyncer.InitCloudSyncer(taskId, SYNC_MODE_CLOUD_FORCE_PUSH); - errCode = cloudSyncer.CallDoUpload(taskId); + cloudSyncer->InitCloudSyncer(taskId, SYNC_MODE_CLOUD_FORCE_PUSH); + errCode = cloudSyncer->CallDoUpload(taskId); EXPECT_EQ(errCode, E_OK); - cloudSyncer.InitCloudSyncer(taskId, SYNC_MODE_CLOUD_FORCE_PULL); - errCode = cloudSyncer.CallDoUpload(taskId); + cloudSyncer->InitCloudSyncer(taskId, SYNC_MODE_CLOUD_FORCE_PULL); + errCode = cloudSyncer->CallDoUpload(taskId); EXPECT_EQ(errCode, -E_INVALID_ARGS); - errCode = cloudSyncer.CallDoUpload(taskId); + errCode = cloudSyncer->CallDoUpload(taskId); EXPECT_EQ(errCode, -E_INVALID_ARGS); + cloudSyncer->CallClose(); + RefObject::KillAndDecObjRef(cloudSyncer); storageProxy.reset(); delete iCloud; @@ -138,9 +145,9 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck002, TestSize.Level1 { MockICloudSyncStorageInterface *iCloud = new MockICloudSyncStorageInterface(); std::shared_ptr storageProxy = std::make_shared(iCloud); - TestCloudSyncer cloudSyncer(storageProxy); + TestCloudSyncer *cloudSyncer = new(std::nothrow) TestCloudSyncer(storageProxy); std::shared_ptr idb = std::make_shared(); - cloudSyncer.SetMockICloudDB(idb); + cloudSyncer->SetMockICloudDB(idb); TaskId taskId = 2u; EXPECT_CALL(*iCloud, StartTransaction(_)).WillRepeatedly(Return(E_OK)); @@ -151,12 +158,14 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck002, TestSize.Level1 EXPECT_CALL(*iCloud, GetCloudData(_, _, _, _)).WillRepeatedly(Return(E_OK)); // 1. The water level was read successfully - cloudSyncer.InitCloudSyncer(taskId, SYNC_MODE_CLOUD_MERGE); + cloudSyncer->InitCloudSyncer(taskId, SYNC_MODE_CLOUD_MERGE); EXPECT_CALL(*iCloud, GetMetaData(_, _)).WillOnce(Return(E_OK)); EXPECT_CALL(*iCloud, ChkSchema(_)).WillRepeatedly(Return(E_OK)); - int errCode = cloudSyncer.CallDoUpload(taskId); + int errCode = cloudSyncer->CallDoUpload(taskId); EXPECT_EQ(errCode, E_OK); + cloudSyncer->CallClose(); + RefObject::KillAndDecObjRef(cloudSyncer); storageProxy.reset(); delete iCloud; @@ -173,9 +182,9 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck003, TestSize.Level1 { MockICloudSyncStorageInterface *iCloud = new MockICloudSyncStorageInterface(); std::shared_ptr storageProxy = std::make_shared(iCloud); - TestCloudSyncer cloudSyncer(storageProxy); + TestCloudSyncer *cloudSyncer = new(std::nothrow) TestCloudSyncer(storageProxy); std::shared_ptr idb = std::make_shared(); - cloudSyncer.SetMockICloudDB(idb); + cloudSyncer->SetMockICloudDB(idb); EXPECT_CALL(*iCloud, StartTransaction(_)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetUploadCount(_, _, _, _)).WillRepeatedly(Return(E_OK)); @@ -187,43 +196,13 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck003, TestSize.Level1 // 2. Failed to read water level TaskId taskId = 3u; - cloudSyncer.InitCloudSyncer(taskId, SYNC_MODE_CLOUD_MERGE); + cloudSyncer->InitCloudSyncer(taskId, SYNC_MODE_CLOUD_MERGE); EXPECT_CALL(*iCloud, GetMetaData(_, _)).WillOnce(Return(-E_INVALID_DB)); - int errCode = cloudSyncer.CallDoUpload(taskId); + int errCode = cloudSyncer->CallDoUpload(taskId); EXPECT_EQ(errCode, -E_INVALID_DB); - taskId = 4u; - cloudSyncer.InitCloudSyncer(taskId, SYNC_MODE_CLOUD_MERGE); - EXPECT_CALL(*iCloud, GetMetaData(_, _)).WillOnce(Return(-E_SECUREC_ERROR)); - errCode = cloudSyncer.CallDoUpload(taskId); - EXPECT_EQ(errCode, -E_SECUREC_ERROR); - - taskId = 5u; - cloudSyncer.InitCloudSyncer(taskId, SYNC_MODE_CLOUD_MERGE); - EXPECT_CALL(*iCloud, GetMetaData(_, _)).WillOnce(Return(-E_INVALID_ARGS)); - errCode = cloudSyncer.CallDoUpload(taskId); - EXPECT_EQ(errCode, -E_INVALID_ARGS); - - taskId = 6u; - cloudSyncer.InitCloudSyncer(taskId, SYNC_MODE_CLOUD_MERGE); - EXPECT_CALL(*iCloud, GetMetaData(_, _)).WillOnce(Return(-E_BUSY)); - errCode = cloudSyncer.CallDoUpload(taskId); - EXPECT_EQ(errCode, -E_BUSY); - - taskId = 7u; - cloudSyncer.InitCloudSyncer(taskId, SYNC_MODE_CLOUD_MERGE); - EXPECT_CALL(*iCloud, GetMetaData(_, _)).WillOnce(Return(-E_NOT_FOUND)); - errCode = cloudSyncer.CallDoUpload(taskId); - // when we coudln't find key in get meta data, read local water mark will return default value and E_OK - EXPECT_EQ(errCode, E_OK); - - // Other sqlite error, like SQLITE_ERROR - taskId = 8u; - cloudSyncer.InitCloudSyncer(taskId, SYNC_MODE_CLOUD_MERGE); - EXPECT_CALL(*iCloud, GetMetaData(_, _)).WillOnce(Return(SQLITE_ERROR)); - errCode = cloudSyncer.CallDoUpload(taskId); - EXPECT_EQ(errCode, SQLITE_ERROR); - + cloudSyncer->CallClose(); + RefObject::KillAndDecObjRef(cloudSyncer); storageProxy.reset(); delete iCloud; idb = nullptr; @@ -240,10 +219,10 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck004, TestSize.Level1 { MockICloudSyncStorageInterface *iCloud = new MockICloudSyncStorageInterface(); std::shared_ptr storageProxy = std::make_shared(iCloud); - TestCloudSyncer cloudSyncer(storageProxy); + TestCloudSyncer *cloudSyncer = new(std::nothrow) TestCloudSyncer(storageProxy); std::shared_ptr idb = std::make_shared(); - cloudSyncer.SetMockICloudDB(idb); - cloudSyncer.InitCloudSyncer(3u, SYNC_MODE_CLOUD_FORCE_PUSH); + cloudSyncer->SetMockICloudDB(idb); + cloudSyncer->InitCloudSyncer(3u, SYNC_MODE_CLOUD_FORCE_PUSH); EXPECT_CALL(*iCloud, StartTransaction(_)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, ChkSchema(_)).WillRepeatedly(Return(E_OK)); @@ -253,36 +232,12 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck004, TestSize.Level1 // 1. Failed to get total data count EXPECT_CALL(*iCloud, GetUploadCount(_, _, _, _)).WillOnce(Return(-E_INVALID_DB)); - int errCode = cloudSyncer.CallDoUpload(3u); + int errCode = cloudSyncer->CallDoUpload(3u); EXPECT_EQ(errCode, -E_INVALID_DB); - cloudSyncer.InitCloudSyncer(4u, SYNC_MODE_CLOUD_FORCE_PUSH); - EXPECT_CALL(*iCloud, GetUploadCount(_, _, _, _)).WillOnce(Return(-E_BUSY)); - errCode = cloudSyncer.CallDoUpload(4u); - EXPECT_EQ(errCode, -E_BUSY); - - cloudSyncer.InitCloudSyncer(5u, SYNC_MODE_CLOUD_FORCE_PUSH); - - EXPECT_CALL(*iCloud, GetUploadCount(_, _, _, _)).WillOnce(Return(-E_OUT_OF_MEMORY)); - errCode = cloudSyncer.CallDoUpload(5u); - EXPECT_EQ(errCode, -E_OUT_OF_MEMORY); - - cloudSyncer.InitCloudSyncer(6u, SYNC_MODE_CLOUD_FORCE_PUSH); - EXPECT_CALL(*iCloud, GetUploadCount(_, _, _, _)).WillOnce(Return(-E_INTERNAL_ERROR)); - errCode = cloudSyncer.CallDoUpload(6u); - EXPECT_EQ(errCode, -E_INTERNAL_ERROR); - - cloudSyncer.InitCloudSyncer(7u, SYNC_MODE_CLOUD_FORCE_PUSH); - EXPECT_CALL(*iCloud, GetUploadCount(_, _, _, _)).WillOnce(Return(-E_INVALID_QUERY_FORMAT)); - errCode = cloudSyncer.CallDoUpload(7u); - EXPECT_EQ(errCode, -E_INVALID_QUERY_FORMAT); - - cloudSyncer.InitCloudSyncer(9u, SYNC_MODE_CLOUD_FORCE_PUSH); - EXPECT_CALL(*iCloud, GetUploadCount(_, _, _, _)).WillOnce(Return(SQLITE_ERROR)); - errCode = cloudSyncer.CallDoUpload(9u); - EXPECT_EQ(errCode, SQLITE_ERROR); - RuntimeContext::GetInstance()->StopTaskPool(); + cloudSyncer->CallClose(); + RefObject::KillAndDecObjRef(cloudSyncer); storageProxy.reset(); delete iCloud; idb = nullptr; @@ -299,10 +254,10 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck005, TestSize.Level1 { MockICloudSyncStorageInterface *iCloud = new MockICloudSyncStorageInterface(); std::shared_ptr storageProxy = std::make_shared(iCloud); - TestCloudSyncer cloudSyncer(storageProxy); + TestCloudSyncer *cloudSyncer = new(std::nothrow) TestCloudSyncer(storageProxy); std::shared_ptr idb = std::make_shared(); - cloudSyncer.SetMockICloudDB(idb); - cloudSyncer.InitCloudSyncer(3u, SYNC_MODE_CLOUD_FORCE_PUSH); + cloudSyncer->SetMockICloudDB(idb); + cloudSyncer->InitCloudSyncer(3u, SYNC_MODE_CLOUD_FORCE_PUSH); EXPECT_CALL(*iCloud, StartTransaction(_)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, ChkSchema(_)).WillRepeatedly(Return(E_OK)); @@ -313,23 +268,25 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck005, TestSize.Level1 EXPECT_CALL(*iCloud, GetCloudData(_, _, _, _)).WillRepeatedly(Return(E_OK)); // 2. get total upload count ok - cloudSyncer.InitCloudSyncer(10u, SYNC_MODE_CLOUD_FORCE_PUSH); + cloudSyncer->InitCloudSyncer(10u, SYNC_MODE_CLOUD_FORCE_PUSH); EXPECT_CALL(*iCloud, GetUploadCount(_, _, _, _)).WillOnce(Return(E_OK)); - int errCode = cloudSyncer.CallDoUpload(10u); + int errCode = cloudSyncer->CallDoUpload(10u); EXPECT_EQ(errCode, E_OK); // 3. get total upload count ok, which is 0 - cloudSyncer.InitCloudSyncer(11u, SYNC_MODE_CLOUD_FORCE_PUSH); + cloudSyncer->InitCloudSyncer(11u, SYNC_MODE_CLOUD_FORCE_PUSH); EXPECT_CALL(*iCloud, GetUploadCount(_, _, _, _)) .WillOnce([](const std::string &, const Timestamp &, const bool, int64_t & count) { count = 0; return E_OK; }); - errCode = cloudSyncer.CallDoUpload(11u); + errCode = cloudSyncer->CallDoUpload(11u); EXPECT_EQ(errCode, E_OK); RuntimeContext::GetInstance()->StopTaskPool(); + cloudSyncer->CallClose(); + RefObject::KillAndDecObjRef(cloudSyncer); storageProxy.reset(); delete iCloud; idb = nullptr; @@ -346,11 +303,11 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck006, TestSize.Level1 { MockICloudSyncStorageInterface *iCloud = new MockICloudSyncStorageInterface(); std::shared_ptr storageProxy = std::make_shared(iCloud); - TestCloudSyncer cloudSyncer(storageProxy); + TestCloudSyncer *cloudSyncer = new(std::nothrow) TestCloudSyncer(storageProxy); std::shared_ptr idb = std::make_shared(); - cloudSyncer.SetMockICloudDB(idb); + cloudSyncer->SetMockICloudDB(idb); TaskId taskId = 4u; - cloudSyncer.InitCloudSyncer(taskId, SYNC_MODE_CLOUD_FORCE_PUSH); + cloudSyncer->InitCloudSyncer(taskId, SYNC_MODE_CLOUD_FORCE_PUSH); EXPECT_CALL(*idb, BatchInsert(_, _, _)).WillRepeatedly(Return(OK)); @@ -370,7 +327,7 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck006, TestSize.Level1 EXPECT_CALL(*iCloud, PutMetaData(_, _)).WillRepeatedly(Return(E_OK)); VBucket tmp = {pair(CloudDbConstant::MODIFY_FIELD, 1)}; - CloudSyncData uploadData(cloudSyncer.GetCurrentContextTableName()); + CloudSyncData uploadData(cloudSyncer->GetCurrentContextTableName()); // batch_1 CloudSyncData quantity > total count uploadData.insData.record = std::vector(1001, tmp); @@ -380,11 +337,12 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck006, TestSize.Level1 cloudDataResult = uploadData; return E_OK; }); - int errCode = cloudSyncer.CallDoUpload(taskId); + int errCode = cloudSyncer->CallDoUpload(taskId); EXPECT_EQ(errCode, -E_INTERNAL_ERROR); RuntimeContext::GetInstance()->StopTaskPool(); - + cloudSyncer->CallClose(); + RefObject::KillAndDecObjRef(cloudSyncer); storageProxy.reset(); delete iCloud; idb = nullptr; @@ -401,15 +359,14 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck007, TestSize.Level1 { MockICloudSyncStorageInterface *iCloud = new MockICloudSyncStorageInterface(); std::shared_ptr storageProxy = std::make_shared(iCloud); - TestCloudSyncer cloudSyncer(storageProxy); + TestCloudSyncer *cloudSyncer = new(std::nothrow) TestCloudSyncer(storageProxy); std::shared_ptr idb = std::make_shared(); - cloudSyncer.SetMockICloudDB(idb); - cloudSyncer.InitCloudSyncer(4u, SYNC_MODE_CLOUD_FORCE_PUSH); + cloudSyncer->SetMockICloudDB(idb); + cloudSyncer->InitCloudSyncer(4u, SYNC_MODE_CLOUD_FORCE_PUSH); CommonExpectCall(iCloud); + BatchExpectCall(iCloud); EXPECT_CALL(*idb, BatchInsert(_, _, _)).WillRepeatedly(Return(OK)); - EXPECT_CALL(*iCloud, PutMetaData(_, _)).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*iCloud, FillCloudGid(_)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetUploadCount(_, _, _, _)) .WillRepeatedly([](const std::string &, const Timestamp &, const bool, int64_t & count) { count = 1000; @@ -417,16 +374,15 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck007, TestSize.Level1 }); // Batch_n CloudSyncData quantity > total count - cloudSyncer.InitCloudSyncer(5u, SYNC_MODE_CLOUD_FORCE_PUSH); - CloudSyncData uploadData2(cloudSyncer.GetCurrentContextTableName()); + cloudSyncer->InitCloudSyncer(5u, SYNC_MODE_CLOUD_FORCE_PUSH); + CloudSyncData uploadData2(cloudSyncer->GetCurrentContextTableName()); VBucket tmp = {pair(CloudDbConstant::MODIFY_FIELD, 1)}; uploadData2.insData.record = std::vector(1000, tmp); uploadData2.insData.extend = std::vector(1000, tmp); SyncTimeRange syncTimeRange = { .beginTime = 1u }; - Query query1 = Query::Select(); - QueryObject queryObject(query1); - queryObject.SetTableName(cloudSyncer.GetCurrentContextTableName()); + QueryObject queryObject(Query::Select()); + queryObject.SetTableName(cloudSyncer->GetCurrentContextTableName()); auto token = new (std::nothrow) SQLiteSingleVerRelationalContinueToken(syncTimeRange, queryObject); ContinueToken conStmtToken = static_cast(token); delete token; @@ -438,7 +394,7 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck007, TestSize.Level1 return -E_UNFINISHED; }); - CloudSyncData uploadData3(cloudSyncer.GetCurrentContextTableName()); + CloudSyncData uploadData3(cloudSyncer->GetCurrentContextTableName()); uploadData3.insData.record = std::vector(1001, tmp); uploadData3.insData.extend = std::vector(1001, tmp); EXPECT_CALL(*iCloud, GetCloudDataNext(_, _)).WillOnce( @@ -446,11 +402,12 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck007, TestSize.Level1 cloudDataResult = uploadData3; return E_OK; }); - int errCode = cloudSyncer.CallDoUpload(5u); + int errCode = cloudSyncer->CallDoUpload(5u); EXPECT_EQ(errCode, -E_INTERNAL_ERROR); RuntimeContext::GetInstance()->StopTaskPool(); - + cloudSyncer->CallClose(); + RefObject::KillAndDecObjRef(cloudSyncer); storageProxy.reset(); delete iCloud; idb = nullptr; @@ -467,11 +424,11 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck008, TestSize.Level1 { MockICloudSyncStorageInterface *iCloud = new MockICloudSyncStorageInterface(); std::shared_ptr storageProxy = std::make_shared(iCloud); - TestCloudSyncer cloudSyncer(storageProxy); + TestCloudSyncer *cloudSyncer = new(std::nothrow) TestCloudSyncer(storageProxy); std::shared_ptr idb = std::make_shared(); - cloudSyncer.SetMockICloudDB(idb); + cloudSyncer->SetMockICloudDB(idb); TaskId taskId = 4u; - cloudSyncer.InitCloudSyncer(taskId, SYNC_MODE_CLOUD_FORCE_PUSH); + cloudSyncer->InitCloudSyncer(taskId, SYNC_MODE_CLOUD_FORCE_PUSH); EXPECT_CALL(*idb, BatchInsert(_, _, _)).WillRepeatedly(Return(OK)); @@ -493,8 +450,8 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck008, TestSize.Level1 // empty CloudSyncData taskId = 6u; - CloudSyncData uploadData2(cloudSyncer.GetCurrentContextTableName()); - cloudSyncer.InitCloudSyncer(taskId, SYNC_MODE_CLOUD_FORCE_PUSH); + CloudSyncData uploadData2(cloudSyncer->GetCurrentContextTableName()); + cloudSyncer->InitCloudSyncer(taskId, SYNC_MODE_CLOUD_FORCE_PUSH); uploadData2.insData.record = std::vector(100); uploadData2.insData.extend = std::vector(100); EXPECT_CALL(*iCloud, GetCloudData(_, _, _, _)) @@ -504,11 +461,12 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck008, TestSize.Level1 return -E_UNFINISHED; }); - int errCode = cloudSyncer.CallDoUpload(taskId); + int errCode = cloudSyncer->CallDoUpload(taskId); EXPECT_EQ(errCode, -E_INTERNAL_ERROR); RuntimeContext::GetInstance()->StopTaskPool(); - + cloudSyncer->CallClose(); + RefObject::KillAndDecObjRef(cloudSyncer); storageProxy.reset(); delete iCloud; idb = nullptr; @@ -526,12 +484,12 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck009, TestSize.Level1 // ClouSyncData format is ok MockICloudSyncStorageInterface *iCloud = new MockICloudSyncStorageInterface(); std::shared_ptr storageProxy = std::make_shared(iCloud); - TestCloudSyncer cloudSyncer(storageProxy); + TestCloudSyncer *cloudSyncer = new(std::nothrow) TestCloudSyncer(storageProxy); std::shared_ptr idb = std::make_shared(); - cloudSyncer.SetMockICloudDB(idb); + cloudSyncer->SetMockICloudDB(idb); TaskId taskId = 5u; - cloudSyncer.InitCloudSyncer(taskId, SYNC_MODE_CLOUD_FORCE_PUSH); + cloudSyncer->InitCloudSyncer(taskId, SYNC_MODE_CLOUD_FORCE_PUSH); VBucket tmp = {pair(CloudDbConstant::MODIFY_FIELD, 1)}; CommonExpectCall(iCloud); EXPECT_CALL(*iCloud, PutMetaData(_, _)).WillRepeatedly(Return(E_OK)); @@ -545,7 +503,7 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck009, TestSize.Level1 return E_OK; }); - CloudSyncData uploadData(cloudSyncer.GetCurrentContextTableName()); + CloudSyncData uploadData(cloudSyncer->GetCurrentContextTableName()); uploadData.insData.record = std::vector(1000, tmp); uploadData.insData.extend = std::vector(1000, tmp); EXPECT_CALL(*iCloud, GetCloudData(_, _, _, _)) @@ -554,11 +512,11 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck009, TestSize.Level1 cloudDataResult = uploadData; return E_OK; }); - int errCode = cloudSyncer.CallDoUpload(taskId); + int errCode = cloudSyncer->CallDoUpload(taskId); EXPECT_EQ(errCode, E_OK); // CloudSyncData format error: record does not match extend length - cloudSyncer.CallClearCloudSyncData(uploadData); + cloudSyncer->CallClearCloudSyncData(uploadData); uploadData.insData.record = std::vector(1000, tmp); uploadData.insData.extend = std::vector(999, tmp); EXPECT_CALL(*iCloud, GetCloudData(_, _, _, _)) @@ -567,11 +525,12 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck009, TestSize.Level1 cloudDataResult = uploadData; return E_OK; }); - errCode = cloudSyncer.CallDoUpload(taskId); + errCode = cloudSyncer->CallDoUpload(taskId); EXPECT_EQ(errCode, -E_INTERNAL_ERROR); RuntimeContext::GetInstance()->StopTaskPool(); - + cloudSyncer->CallClose(); + RefObject::KillAndDecObjRef(cloudSyncer); storageProxy.reset(); delete iCloud; idb = nullptr; @@ -589,12 +548,12 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck017, TestSize.Level1 // ClouSyncData format is ok MockICloudSyncStorageInterface *iCloud = new MockICloudSyncStorageInterface(); std::shared_ptr storageProxy = std::make_shared(iCloud); - TestCloudSyncer cloudSyncer(storageProxy); + TestCloudSyncer *cloudSyncer = new(std::nothrow) TestCloudSyncer(storageProxy); std::shared_ptr idb = std::make_shared(); - cloudSyncer.SetMockICloudDB(idb); + cloudSyncer->SetMockICloudDB(idb); TaskId taskId = 5u; - cloudSyncer.InitCloudSyncer(taskId, SYNC_MODE_CLOUD_FORCE_PUSH); + cloudSyncer->InitCloudSyncer(taskId, SYNC_MODE_CLOUD_FORCE_PUSH); VBucket tmp = {pair(CloudDbConstant::MODIFY_FIELD, 1)}; CommonExpectCall(iCloud); EXPECT_CALL(*iCloud, PutMetaData(_, _)).WillRepeatedly(Return(E_OK)); @@ -609,7 +568,7 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck017, TestSize.Level1 }); // CloudSyncData format error: tableName is different from the table name corresponding to Task - CloudSyncData uploadData2(cloudSyncer.GetCurrentContextTableName() + "abc"); + CloudSyncData uploadData2(cloudSyncer->GetCurrentContextTableName() + "abc"); uploadData2.insData.record = std::vector(1000, tmp); uploadData2.insData.extend = std::vector(1000, tmp); EXPECT_CALL(*iCloud, GetCloudData(_, _, _, _)) @@ -618,11 +577,12 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck017, TestSize.Level1 cloudDataResult = uploadData2; return E_OK; }); - int errCode = cloudSyncer.CallDoUpload(taskId); + int errCode = cloudSyncer->CallDoUpload(taskId); EXPECT_EQ(errCode, -E_INTERNAL_ERROR); RuntimeContext::GetInstance()->StopTaskPool(); - + cloudSyncer->CallClose(); + RefObject::KillAndDecObjRef(cloudSyncer); storageProxy.reset(); delete iCloud; idb = nullptr; @@ -639,14 +599,14 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck010, TestSize.Level1 // insert has data, update has data, delete has data (check whether it is running normally and info count) MockICloudSyncStorageInterface *iCloud = new MockICloudSyncStorageInterface(); std::shared_ptr storageProxy = std::make_shared(iCloud); - TestCloudSyncer cloudSyncer(storageProxy); + TestCloudSyncer *cloudSyncer = new(std::nothrow) TestCloudSyncer(storageProxy); std::shared_ptr idb = std::make_shared(); - cloudSyncer.SetMockICloudDB(idb); + cloudSyncer->SetMockICloudDB(idb); TaskId taskId = 6u; - cloudSyncer.InitCloudSyncer(taskId, SYNC_MODE_CLOUD_FORCE_PUSH); - CloudSyncData uploadData(cloudSyncer.GetCurrentContextTableName()); - cloudSyncer.initFullCloudSyncData(uploadData, 1000); + cloudSyncer->InitCloudSyncer(taskId, SYNC_MODE_CLOUD_FORCE_PUSH); + CloudSyncData uploadData(cloudSyncer->GetCurrentContextTableName()); + cloudSyncer->initFullCloudSyncData(uploadData, 1000); EXPECT_CALL(*iCloud, GetCloudData(_, _, _, _)) .WillOnce([&uploadData](const TableSchema &, const Timestamp &, @@ -673,13 +633,15 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck010, TestSize.Level1 EXPECT_CALL(*iCloud, GetCloudTableSchema(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, FillCloudGid(_)).WillRepeatedly(Return(E_OK)); - int errCode = cloudSyncer.CallDoUpload(taskId); + int errCode = cloudSyncer->CallDoUpload(taskId); EXPECT_EQ(errCode, E_OK); std::this_thread::sleep_for(std::chrono::seconds(1)); - EXPECT_EQ(cloudSyncer.GetUploadSuccessCount(taskId), 3000); - EXPECT_EQ(cloudSyncer.GetUploadFailCount(taskId), 0); + EXPECT_EQ(cloudSyncer->GetUploadSuccessCount(taskId), 3000); + EXPECT_EQ(cloudSyncer->GetUploadFailCount(taskId), 0); RuntimeContext::GetInstance()->StopTaskPool(); + cloudSyncer->CallClose(); + RefObject::KillAndDecObjRef(cloudSyncer); storageProxy.reset(); delete iCloud; idb = nullptr; @@ -696,11 +658,11 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck011, TestSize.Level1 { MockICloudSyncStorageInterface *iCloud = new MockICloudSyncStorageInterface(); std::shared_ptr storageProxy = std::make_shared(iCloud); - TestCloudSyncer cloudSyncer(storageProxy); + TestCloudSyncer *cloudSyncer = new(std::nothrow) TestCloudSyncer(storageProxy); std::shared_ptr idb = std::make_shared(); - cloudSyncer.SetMockICloudDB(idb); + cloudSyncer->SetMockICloudDB(idb); VBucket tmp = {pair(CloudDbConstant::MODIFY_FIELD, 1)}; - cloudSyncer.InitCloudSyncer(6u, SYNC_MODE_CLOUD_FORCE_PUSH); + cloudSyncer->InitCloudSyncer(6u, SYNC_MODE_CLOUD_FORCE_PUSH); EXPECT_CALL(*iCloud, StartTransaction(_)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, ChkSchema(_)).WillRepeatedly(Return(E_OK)); @@ -722,7 +684,7 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck011, TestSize.Level1 EXPECT_CALL(*iCloud, FillCloudGid(_)).WillRepeatedly(Return(E_OK)); // insert has no data, update and delete have data - CloudSyncData uploadData2(cloudSyncer.GetCurrentContextTableName()); + CloudSyncData uploadData2(cloudSyncer->GetCurrentContextTableName()); uploadData2.updData.record = std::vector(1000, tmp); uploadData2.updData.extend = std::vector(1000, tmp); uploadData2.delData.record = std::vector(1000, tmp); @@ -733,14 +695,15 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck011, TestSize.Level1 cloudDataResult = uploadData2; return E_OK; }); - int errCode = cloudSyncer.CallDoUpload(6u); + int errCode = cloudSyncer->CallDoUpload(6u); std::this_thread::sleep_for(std::chrono::seconds(1)); EXPECT_EQ(errCode, E_OK); - EXPECT_EQ(cloudSyncer.GetUploadSuccessCount(6u), 2000); - EXPECT_EQ(cloudSyncer.GetUploadFailCount(6u), 0); + EXPECT_EQ(cloudSyncer->GetUploadSuccessCount(6u), 2000); + EXPECT_EQ(cloudSyncer->GetUploadFailCount(6u), 0); RuntimeContext::GetInstance()->StopTaskPool(); - + cloudSyncer->CallClose(); + RefObject::KillAndDecObjRef(cloudSyncer); storageProxy.reset(); delete iCloud; idb = nullptr; @@ -757,11 +720,11 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck012, TestSize.Level1 { MockICloudSyncStorageInterface *iCloud = new MockICloudSyncStorageInterface(); std::shared_ptr storageProxy = std::make_shared(iCloud); - TestCloudSyncer cloudSyncer(storageProxy); + TestCloudSyncer *cloudSyncer = new(std::nothrow) TestCloudSyncer(storageProxy); std::shared_ptr idb = std::make_shared(); - cloudSyncer.SetMockICloudDB(idb); + cloudSyncer->SetMockICloudDB(idb); VBucket tmp = {pair(CloudDbConstant::MODIFY_FIELD, 1)}; - cloudSyncer.InitCloudSyncer(6u, SYNC_MODE_CLOUD_FORCE_PUSH); + cloudSyncer->InitCloudSyncer(6u, SYNC_MODE_CLOUD_FORCE_PUSH); EXPECT_CALL(*iCloud, StartTransaction(_)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, ChkSchema(_)).WillRepeatedly(Return(E_OK)); @@ -783,7 +746,7 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck012, TestSize.Level1 EXPECT_CALL(*iCloud, FillCloudGid(_)).WillRepeatedly(Return(E_OK)); // insert has data, update has no data, delete has data - CloudSyncData uploadData3(cloudSyncer.GetCurrentContextTableName()); + CloudSyncData uploadData3(cloudSyncer->GetCurrentContextTableName()); uploadData3.insData.record = std::vector(1000, tmp); uploadData3.insData.extend = std::vector(1000, tmp); uploadData3.delData.record = std::vector(1000, tmp); @@ -794,14 +757,15 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck012, TestSize.Level1 cloudDataResult = uploadData3; return E_OK; }); - int errCode = cloudSyncer.CallDoUpload(6u); + int errCode = cloudSyncer->CallDoUpload(6u); std::this_thread::sleep_for(std::chrono::seconds(1)); EXPECT_EQ(errCode, E_OK); - EXPECT_EQ(cloudSyncer.GetUploadSuccessCount(6u), 2000); - EXPECT_EQ(cloudSyncer.GetUploadFailCount(6u), 0); + EXPECT_EQ(cloudSyncer->GetUploadSuccessCount(6u), 2000); + EXPECT_EQ(cloudSyncer->GetUploadFailCount(6u), 0); RuntimeContext::GetInstance()->StopTaskPool(); - + cloudSyncer->CallClose(); + RefObject::KillAndDecObjRef(cloudSyncer); storageProxy.reset(); delete iCloud; idb = nullptr; @@ -819,18 +783,16 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck013, TestSize.Level1 // batch api all success. MockICloudSyncStorageInterface *iCloud = new MockICloudSyncStorageInterface(); std::shared_ptr storageProxy = std::make_shared(iCloud); - TestCloudSyncer cloudSyncer(storageProxy); + TestCloudSyncer *cloudSyncer = new(std::nothrow) TestCloudSyncer(storageProxy); std::shared_ptr idb = std::make_shared(); - cloudSyncer.SetMockICloudDB(idb); - TaskId taskId = 7u; - cloudSyncer.InitCloudSyncer(taskId, SYNC_MODE_CLOUD_FORCE_PUSH); + cloudSyncer->SetMockICloudDB(idb); + cloudSyncer->InitCloudSyncer(7u, SYNC_MODE_CLOUD_FORCE_PUSH); // taskId is 7u CommonExpectCall(iCloud); - EXPECT_CALL(*iCloud, PutMetaData(_, _)).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*iCloud, FillCloudGid(_)).WillRepeatedly(Return(E_OK)); + BatchExpectCall(iCloud); - CloudSyncData uploadData(cloudSyncer.GetCurrentContextTableName()); - cloudSyncer.initFullCloudSyncData(uploadData, 1000); + CloudSyncData uploadData(cloudSyncer->GetCurrentContextTableName()); + cloudSyncer->initFullCloudSyncData(uploadData, 1000); EXPECT_CALL(*iCloud, GetCloudData(_, _, _, _)) .WillRepeatedly([&uploadData](const TableSchema &, const Timestamp &, ContinueToken &continueStmtToken, CloudSyncData &cloudDataResult) { @@ -858,14 +820,15 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck013, TestSize.Level1 extend = uploadData.delData.extend; return OK; }); - int errCode = cloudSyncer.CallDoUpload(taskId); + int errCode = cloudSyncer->CallDoUpload(7u); // taskId is 7u EXPECT_EQ(errCode, E_OK); - cloudSyncer.CallNotify(); + cloudSyncer->CallNotify(); std::this_thread::sleep_for(std::chrono::seconds(1)); - EXPECT_EQ(cloudSyncer.GetUploadSuccessCount(taskId), 3000); - EXPECT_EQ(cloudSyncer.GetUploadFailCount(taskId), 0); - + EXPECT_EQ(cloudSyncer->GetUploadSuccessCount(7u), 3000); // taskId is 7u + EXPECT_EQ(cloudSyncer->GetUploadFailCount(7u), 0); // taskId is 7u + cloudSyncer->CallClose(); + RefObject::KillAndDecObjRef(cloudSyncer); RuntimeContext::GetInstance()->StopTaskPool(); storageProxy.reset(); delete iCloud; @@ -882,9 +845,9 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck014, TestSize.Level1 { MockICloudSyncStorageInterface *iCloud = new MockICloudSyncStorageInterface(); std::shared_ptr storageProxy = std::make_shared(iCloud); - TestCloudSyncer cloudSyncer2(storageProxy); + TestCloudSyncer *cloudSyncer2 = new(std::nothrow) TestCloudSyncer(storageProxy); std::shared_ptr idb2 = std::make_shared(); - cloudSyncer2.SetMockICloudDB(idb2); + cloudSyncer2->SetMockICloudDB(idb2); TaskId taskId = 8u; CommonExpectCall(iCloud); @@ -892,9 +855,9 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck014, TestSize.Level1 EXPECT_CALL(*iCloud, FillCloudGid(_)).WillRepeatedly(Return(E_OK)); // batch api partially success - cloudSyncer2.InitCloudSyncer(taskId, SYNC_MODE_CLOUD_FORCE_PUSH); - CloudSyncData uploadData2(cloudSyncer2.GetCurrentContextTableName()); - cloudSyncer2.initFullCloudSyncData(uploadData2, 1000); + cloudSyncer2->InitCloudSyncer(taskId, SYNC_MODE_CLOUD_FORCE_PUSH); + CloudSyncData uploadData2(cloudSyncer2->GetCurrentContextTableName()); + cloudSyncer2->initFullCloudSyncData(uploadData2, 1000); EXPECT_CALL(*iCloud, GetCloudData(_, _, _, _)).WillRepeatedly( [&uploadData2](const TableSchema &, const Timestamp &, ContinueToken &, CloudSyncData &cloudDataResult) { cloudDataResult = uploadData2; return E_OK; @@ -915,14 +878,16 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck014, TestSize.Level1 extend = uploadData2.updData.extend; return DB_ERROR; }); - int errCode = cloudSyncer2.CallDoUpload(taskId); + int errCode = cloudSyncer2->CallDoUpload(taskId); EXPECT_EQ(errCode, -E_CLOUD_ERROR); - cloudSyncer2.CallNotify(); + cloudSyncer2->CallNotify(); std::this_thread::sleep_for(std::chrono::seconds(1)); - EXPECT_EQ(cloudSyncer2.GetUploadSuccessCount(taskId), 1000); - EXPECT_EQ(cloudSyncer2.GetUploadFailCount(taskId), 2000); + EXPECT_EQ(cloudSyncer2->GetUploadSuccessCount(taskId), 1000); + EXPECT_EQ(cloudSyncer2->GetUploadFailCount(taskId), 2000); RuntimeContext::GetInstance()->StopTaskPool(); + cloudSyncer2->CallClose(); + RefObject::KillAndDecObjRef(cloudSyncer2); storageProxy.reset(); delete iCloud; idb2 = nullptr; @@ -939,20 +904,19 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck015, TestSize.Level1 { MockICloudSyncStorageInterface *iCloud = new MockICloudSyncStorageInterface(); std::shared_ptr storageProxy = std::make_shared(iCloud); - TestCloudSyncer cloudSyncer3(storageProxy); + TestCloudSyncer *cloudSyncer3 = new(std::nothrow) TestCloudSyncer(storageProxy); std::shared_ptr idb3 = std::make_shared(); - cloudSyncer3.SetMockICloudDB(idb3); + cloudSyncer3->SetMockICloudDB(idb3); CommonExpectCall(iCloud); - EXPECT_CALL(*iCloud, PutMetaData(_, _)).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*iCloud, FillCloudGid(_)).WillRepeatedly(Return(E_OK)); + BatchExpectCall(iCloud); // BatchInsert failed, BatchUpdate ok, BatchDelete ok - cloudSyncer3.InitCloudSyncer(9u, SYNC_MODE_CLOUD_FORCE_PUSH); - CloudSyncData uploadData3(cloudSyncer3.GetCurrentContextTableName()); - cloudSyncer3.initFullCloudSyncData(uploadData3, 1000); + cloudSyncer3->InitCloudSyncer(9u, SYNC_MODE_CLOUD_FORCE_PUSH); + CloudSyncData uploadData3(cloudSyncer3->GetCurrentContextTableName()); + cloudSyncer3->initFullCloudSyncData(uploadData3, 1000); EXPECT_CALL(*iCloud, GetCloudData(_, _, _, _)) - .WillRepeatedly([&uploadData3](const TableSchema &, const Timestamp &, ContinueToken &, + .WillRepeatedly([&uploadData3](const TableSchema &, const Timestamp &, ContinueToken &, CloudSyncData &cloudDataResult) { cloudDataResult = uploadData3; return E_OK; @@ -977,16 +941,17 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck015, TestSize.Level1 std::vector &&record, std::vector &extend) { record = uploadData3.updData.record; extend = uploadData3.delData.extend; - return OK; + return OK; }); - int errCode = cloudSyncer3.CallDoUpload(9u); - cloudSyncer3.CallNotify(); + EXPECT_EQ(cloudSyncer3->CallDoUpload(9u), -E_CLOUD_ERROR); + cloudSyncer3->CallNotify(); RuntimeContext::GetInstance()->StopTaskPool(); - EXPECT_EQ(errCode, -E_CLOUD_ERROR); - EXPECT_EQ(cloudSyncer3.GetUploadSuccessCount(9u), 0); - EXPECT_EQ(cloudSyncer3.GetUploadFailCount(9u), 3000); + EXPECT_EQ(cloudSyncer3->GetUploadSuccessCount(9u), 0); + EXPECT_EQ(cloudSyncer3->GetUploadFailCount(9u), 3000); + cloudSyncer3->CallClose(); + RefObject::KillAndDecObjRef(cloudSyncer3); storageProxy.reset(); delete iCloud; idb3 = nullptr; @@ -1025,11 +990,11 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck016, TestSize.Level1 // update water level successful MockICloudSyncStorageInterface *iCloud = new MockICloudSyncStorageInterface(); std::shared_ptr storageProxy = std::make_shared(iCloud); - TestCloudSyncer cloudSyncer(storageProxy); + TestCloudSyncer *cloudSyncer = new(std::nothrow) TestCloudSyncer(storageProxy); std::shared_ptr idb = std::make_shared(); - cloudSyncer.SetMockICloudDB(idb); - cloudSyncer.InitCloudSyncer(8u, SYNC_MODE_CLOUD_MERGE); - cloudSyncer.SetCloudWaterMarks(TABLE_NAME_1, CLOUD_WATER_MARK); + cloudSyncer->SetMockICloudDB(idb); + cloudSyncer->InitCloudSyncer(8u, SYNC_MODE_CLOUD_MERGE); + cloudSyncer->SetCloudWaterMarks(TABLE_NAME_1, CLOUD_WATER_MARK); CommonExpectCall(iCloud); // CheckSchema @@ -1039,8 +1004,8 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck016, TestSize.Level1 return E_OK; }); VBucket tmp = {pair(CloudDbConstant::MODIFY_FIELD, 1)}; - CloudSyncData uploadData(cloudSyncer.GetCurrentContextTableName()); - cloudSyncer.initFullCloudSyncData(uploadData, 1000); + CloudSyncData uploadData(cloudSyncer->GetCurrentContextTableName()); + cloudSyncer->initFullCloudSyncData(uploadData, 1000); EXPECT_CALL(*iCloud, FillCloudGid(_)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetCloudData(_, _, _, _)) @@ -1050,14 +1015,15 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck016, TestSize.Level1 return E_OK; }); ExpectCallForTestCase016(idb, uploadData); - EXPECT_EQ(cloudSyncer.CallDoUpload(8u), E_OK); + EXPECT_EQ(cloudSyncer->CallDoUpload(8u), E_OK); EXPECT_CALL(*iCloud, PutMetaData(_, _)).WillOnce(Return(-E_INVALID_DB)); - EXPECT_EQ(cloudSyncer.CallDoUpload(8u), -E_INVALID_DB); + EXPECT_EQ(cloudSyncer->CallDoUpload(8u), -E_INVALID_DB); EXPECT_CALL(*iCloud, PutMetaData(_, _)).WillOnce(Return(-E_INVALID_ARGS)); - EXPECT_EQ(cloudSyncer.CallDoUpload(8u), -E_INVALID_ARGS); + EXPECT_EQ(cloudSyncer->CallDoUpload(8u), -E_INVALID_ARGS); RuntimeContext::GetInstance()->StopTaskPool(); - + cloudSyncer->CallClose(); + RefObject::KillAndDecObjRef(cloudSyncer); storageProxy.reset(); delete iCloud; idb = nullptr; @@ -1087,24 +1053,24 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck018, TestSize.Level1 auto *iCloud = new(std::nothrow) MockICloudSyncStorageInterface(); ASSERT_NE(iCloud, nullptr); std::shared_ptr storageProxy = std::make_shared(iCloud); - TestCloudSyncer cloudSyncer(storageProxy); + TestCloudSyncer *cloudSyncer = new(std::nothrow) TestCloudSyncer(storageProxy); auto idb = std::make_shared(); - cloudSyncer.SetMockICloudDB(idb); - cloudSyncer.InitCloudSyncer(5u, SYNC_MODE_CLOUD_FORCE_PUSH); + cloudSyncer->SetMockICloudDB(idb); + cloudSyncer->InitCloudSyncer(5u, SYNC_MODE_CLOUD_FORCE_PUSH); CommonExpectCall(iCloud); MockCall(iCloud, idb); // Batch_n CloudSyncData quantity > total count VBucket tmp = {pair(CloudDbConstant::MODIFY_FIELD, 1)}; - cloudSyncer.InitCloudSyncer(5u, SYNC_MODE_CLOUD_FORCE_PUSH); - CloudSyncData uploadData2(cloudSyncer.GetCurrentContextTableName()); + cloudSyncer->InitCloudSyncer(5u, SYNC_MODE_CLOUD_FORCE_PUSH); + CloudSyncData uploadData2(cloudSyncer->GetCurrentContextTableName()); uploadData2.insData.record = std::vector(1000, tmp); uploadData2.insData.extend = std::vector(1000, tmp); SyncTimeRange syncTimeRange = { .beginTime = 1u }; QueryObject queryObject(Query::Select()); - queryObject.SetTableName(cloudSyncer.GetCurrentContextTableName()); + queryObject.SetTableName(cloudSyncer->GetCurrentContextTableName()); auto token = new (std::nothrow) SQLiteSingleVerRelationalContinueToken(syncTimeRange, queryObject); auto conStmtToken = static_cast(token); delete token; @@ -1116,7 +1082,7 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck018, TestSize.Level1 return -E_UNFINISHED; }); - CloudSyncData uploadData3(cloudSyncer.GetCurrentContextTableName()); + CloudSyncData uploadData3(cloudSyncer->GetCurrentContextTableName()); uploadData3.insData.extend = std::vector(2001, tmp); uploadData3.insData.record = std::vector(2001, tmp); EXPECT_CALL(*iCloud, GetCloudDataNext(_, _)).WillOnce( @@ -1125,15 +1091,16 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck018, TestSize.Level1 return E_OK; }); std::atomic callCount = 0; - cloudSyncer.SetCurrentCloudTaskInfos({"TABLE"}, [&callCount](const std::map &) { + cloudSyncer->SetCurrentCloudTaskInfos({"TABLE"}, [&callCount](const std::map &) { callCount++; }); - int errCode = cloudSyncer.CallDoUpload(5u, true); + int errCode = cloudSyncer->CallDoUpload(5u, true); EXPECT_EQ(errCode, -E_INTERNAL_ERROR); RuntimeContext::GetInstance()->StopTaskPool(); EXPECT_EQ(callCount, 1); - + cloudSyncer->CallClose(); + RefObject::KillAndDecObjRef(cloudSyncer); storageProxy.reset(); delete iCloud; idb = nullptr; @@ -1163,27 +1130,32 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadNotifyCheck001, TestSize.Leve { MockICloudSyncStorageInterface *iCloud = new MockICloudSyncStorageInterface(); std::shared_ptr storageProxy = std::make_shared(iCloud); - TestCloudSyncer cloudSyncer(storageProxy); + TestCloudSyncer *cloudSyncer = new(std::nothrow) TestCloudSyncer(storageProxy); std::shared_ptr idb = std::make_shared(); - cloudSyncer.SetMockICloudDB(idb); + cloudSyncer->SetMockICloudDB(idb); TaskId taskId = 17u; - cloudSyncer.InitCloudSyncer(taskId, SYNC_MODE_CLOUD_FORCE_PUSH); + cloudSyncer->InitCloudSyncer(taskId, SYNC_MODE_CLOUD_FORCE_PUSH); std::string tableName2 = "TestTable2" + std::to_string(taskId); - std::vector tables = {cloudSyncer.GetCurrentContextTableName(), tableName2}; + std::vector tables = {cloudSyncer->GetCurrentContextTableName(), tableName2}; SyncProcess res; TableProcessInfo tbProcessInfo; - res.tableProcess[cloudSyncer.GetCurrentContextTableName()] = tbProcessInfo; + res.tableProcess[cloudSyncer->GetCurrentContextTableName()] = tbProcessInfo; res.tableProcess[tableName2] = tbProcessInfo; - cloudSyncer.SetCurrentCloudTaskInfos(tables, [&res]( + std::mutex mutex; + cloudSyncer->SetCurrentCloudTaskInfos(tables, [&res, &mutex]( const std::map &process) { + std::lock_guard autoLock(mutex); + if (process.empty()) { + return; + } res = process.begin()->second; }); CommonExpectCall(iCloud); MockMethod(idb, iCloud); - CloudSyncData uploadData(cloudSyncer.GetCurrentContextTableName()); - cloudSyncer.initFullCloudSyncData(uploadData, 1000); // each size 1000 + CloudSyncData uploadData(cloudSyncer->GetCurrentContextTableName()); + cloudSyncer->initFullCloudSyncData(uploadData, 1000); // each size 1000 CloudSyncData uploadData2(tableName2); - cloudSyncer.initFullCloudSyncData(uploadData2, 1000); // each size 1000 + cloudSyncer->initFullCloudSyncData(uploadData2, 1000); // each size 1000 EXPECT_CALL(*iCloud, GetCloudData(_, _, _, _)) .WillOnce([&uploadData](const TableSchema &, const Timestamp &, @@ -1195,12 +1167,14 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadNotifyCheck001, TestSize.Leve cloudDataResult = uploadData2; return E_OK;}); - EXPECT_EQ(cloudSyncer.CallDoSyncInner(cloudSyncer.GetCurrentCloudTaskInfos(), true), E_OK); - EXPECT_EQ(res.tableProcess[cloudSyncer.GetCurrentContextTableName()].process, PROCESSING); - cloudSyncer.CallNotify(); + EXPECT_EQ(cloudSyncer->CallDoSyncInner(cloudSyncer->GetCurrentCloudTaskInfos(), true), E_OK); + EXPECT_EQ(res.tableProcess[cloudSyncer->GetCurrentContextTableName()].process, PROCESSING); + cloudSyncer->CallNotify(); RuntimeContext::GetInstance()->StopTaskPool(); - EXPECT_EQ(res.tableProcess[cloudSyncer.GetCurrentContextTableName()].process, FINISHED); + EXPECT_EQ(res.tableProcess[cloudSyncer->GetCurrentContextTableName()].process, FINISHED); EXPECT_EQ(res.tableProcess[tableName2].process, FINISHED); + cloudSyncer->CallClose(); + RefObject::KillAndDecObjRef(cloudSyncer); storageProxy.reset(); delete iCloud; idb = nullptr; @@ -1217,22 +1191,25 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadNotifyCheck002, TestSize.Leve { MockICloudSyncStorageInterface *iCloud = new MockICloudSyncStorageInterface(); std::shared_ptr storageProxy = std::make_shared(iCloud); - TestCloudSyncer cloudSyncer(storageProxy); + TestCloudSyncer *cloudSyncer = new(std::nothrow) TestCloudSyncer(storageProxy); std::shared_ptr idb = std::make_shared(); - cloudSyncer.SetMockICloudDB(idb); + cloudSyncer->SetMockICloudDB(idb); TaskId taskId = 17u; - cloudSyncer.InitCloudSyncer(taskId, SYNC_MODE_CLOUD_FORCE_PUSH); + cloudSyncer->InitCloudSyncer(taskId, SYNC_MODE_CLOUD_FORCE_PUSH); std::string tableName2 = "TestTable2" + std::to_string(taskId); - std::vector tables = { - cloudSyncer.GetCurrentContextTableName(), tableName2 - }; + std::vector tables = {cloudSyncer->GetCurrentContextTableName(), tableName2}; SyncProcess res; TableProcessInfo tbProcessInfo; - res.tableProcess[cloudSyncer.GetCurrentContextTableName()] = tbProcessInfo; + res.tableProcess[cloudSyncer->GetCurrentContextTableName()] = tbProcessInfo; res.tableProcess[tableName2] = tbProcessInfo; - cloudSyncer.SetCurrentCloudTaskInfos(tables, [&res]( + std::mutex mutex; + cloudSyncer->SetCurrentCloudTaskInfos(tables, [&res, &mutex]( const std::map &process) { + std::lock_guard autoLock(mutex); + if (process.empty()) { + return; + } res = process.begin()->second; }); CommonExpectCall(iCloud); @@ -1244,10 +1221,9 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadNotifyCheck002, TestSize.Leve EXPECT_CALL(*iCloud, GetUploadCount(_, _, _, _)) .WillRepeatedly([](const std::string &, const Timestamp &, const bool, int64_t & count) { count = 3000; // total count is 3000 - return E_OK; - }); - CloudSyncData uploadData(cloudSyncer.GetCurrentContextTableName()); - cloudSyncer.initFullCloudSyncData(uploadData, 1000); // each size 1000 + return E_OK;}); + CloudSyncData uploadData(cloudSyncer->GetCurrentContextTableName()); + cloudSyncer->initFullCloudSyncData(uploadData, 1000); // each size 1000 EXPECT_CALL(*iCloud, GetCloudData(_, _, _, _)) .WillOnce([&uploadData](const TableSchema &, const Timestamp &, @@ -1255,11 +1231,13 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadNotifyCheck002, TestSize.Leve cloudDataResult = uploadData; return E_OK;}); - EXPECT_EQ(cloudSyncer.CallDoSyncInner(cloudSyncer.GetCurrentCloudTaskInfos(), true), -E_CLOUD_ERROR); - cloudSyncer.CallNotify(); + EXPECT_EQ(cloudSyncer->CallDoSyncInner(cloudSyncer->GetCurrentCloudTaskInfos(), true), -E_CLOUD_ERROR); + cloudSyncer->CallNotify(); RuntimeContext::GetInstance()->StopTaskPool(); - EXPECT_EQ(res.tableProcess[cloudSyncer.GetCurrentContextTableName()].process, PROCESSING); + EXPECT_EQ(res.tableProcess[cloudSyncer->GetCurrentContextTableName()].process, PROCESSING); EXPECT_EQ(res.tableProcess[tableName2].process, PROCESSING); + cloudSyncer->CallClose(); + RefObject::KillAndDecObjRef(cloudSyncer); storageProxy.reset(); delete iCloud; idb = nullptr; @@ -1276,22 +1254,27 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadNotifyCheck003, TestSize.Leve { MockICloudSyncStorageInterface *iCloud = new MockICloudSyncStorageInterface(); std::shared_ptr storageProxy = std::make_shared(iCloud); - TestCloudSyncer cloudSyncer(storageProxy); + TestCloudSyncer *cloudSyncer = new(std::nothrow) TestCloudSyncer(storageProxy); std::shared_ptr idb = std::make_shared(); - cloudSyncer.SetMockICloudDB(idb); + cloudSyncer->SetMockICloudDB(idb); TaskId taskId = 19u; - cloudSyncer.InitCloudSyncer(taskId, SYNC_MODE_CLOUD_FORCE_PUSH); + cloudSyncer->InitCloudSyncer(taskId, SYNC_MODE_CLOUD_FORCE_PUSH); std::string tableName2 = "TestTable2" + std::to_string(taskId); std::vector tables = { - cloudSyncer.GetCurrentContextTableName(), tableName2 + cloudSyncer->GetCurrentContextTableName(), tableName2 }; SyncProcess res; TableProcessInfo tbProcessInfo; - res.tableProcess[cloudSyncer.GetCurrentContextTableName()] = tbProcessInfo; + res.tableProcess[cloudSyncer->GetCurrentContextTableName()] = tbProcessInfo; res.tableProcess[tableName2] = tbProcessInfo; - cloudSyncer.SetCurrentCloudTaskInfos(tables, [&res]( + std::mutex mutex; + cloudSyncer->SetCurrentCloudTaskInfos(tables, [&res, &mutex]( const std::map &process) { + std::lock_guard autoLock(mutex); + if (process.empty()) { + return; + } res = process.begin()->second; }); CommonExpectCall(iCloud); @@ -1306,11 +1289,13 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadNotifyCheck003, TestSize.Leve return E_OK; }); // test when count == 0 - EXPECT_EQ(cloudSyncer.CallDoSyncInner(cloudSyncer.GetCurrentCloudTaskInfos(), true), E_OK); - cloudSyncer.CallNotify(); + EXPECT_EQ(cloudSyncer->CallDoSyncInner(cloudSyncer->GetCurrentCloudTaskInfos(), true), E_OK); + cloudSyncer->CallNotify(); RuntimeContext::GetInstance()->StopTaskPool(); - EXPECT_EQ(res.tableProcess[cloudSyncer.GetCurrentContextTableName()].process, FINISHED); + EXPECT_EQ(res.tableProcess[cloudSyncer->GetCurrentContextTableName()].process, FINISHED); EXPECT_EQ(res.tableProcess[tableName2].process, FINISHED); + cloudSyncer->CallClose(); + RefObject::KillAndDecObjRef(cloudSyncer); storageProxy.reset(); delete iCloud; idb = nullptr; diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/mock_icloud_sync_storage_interface.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/mock_icloud_sync_storage_interface.h index aed113e826d2bcc1a5258dfb4867f5abdde0a00a..2c182d39b9469a04388c130e594334ed38503c31 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/mock_icloud_sync_storage_interface.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/mock_icloud_sync_storage_interface.h @@ -41,7 +41,7 @@ public: MOCK_METHOD3(CleanCloudData, int(ClearMode mode, const std::vector &tableNameList, std::vector &assets)); MOCK_METHOD3(FillCloudAssetForDownload, int(const std::string &, VBucket &, bool)); - MOCK_METHOD1(FillCloudAssetForUpload, int(const CloudSyncData &)); + MOCK_METHOD2(FillCloudGidAndAsset, int(const OpType &, const CloudSyncData &)); }; } diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/virtual_cloud_db.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/virtual_cloud_db.cpp index f7166ab829e80cf1bfaf80fbfb0ecfcb03b63069..5afb7d11fd73e7637c4791b379424f33f8bb3a54 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/virtual_cloud_db.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/virtual_cloud_db.cpp @@ -87,6 +87,9 @@ DBStatus VirtualCloudDb::BatchDelete(const std::string &tableName, std::vector &data) { + if (actionStatus_ != OK) { + return actionStatus_; + } if (cloudError_) { return DB_ERROR; } if (blockTimeMs_ != 0) { std::this_thread::sleep_for(std::chrono::milliseconds(blockTimeMs_)); } + if (queryTimes_.find(tableName) == queryTimes_.end()) { + queryTimes_.try_emplace(tableName, 0); + } + queryTimes_[tableName]++; std::lock_guard autoLock(cloudDataMutex_); if (cloudData_.find(tableName) == cloudData_.end()) { return QUERY_END; } - LOGD("extend size: %zu type: %zu expect: %zu", extend.size(), extend[g_cursorField].index(), - TYPE_INDEX); std::string cursor = std::get(extend[g_cursorField]); - cursor = cursor.empty() ? "0" : cursor; - for (auto &tableData : cloudData_[tableName]) { + bool isIncreCursor = (cursor.substr(0, increPrefix_.size()) == increPrefix_); + LOGD("extend size: %zu type: %zu expect: %zu, cursor: %s", extend.size(), extend[g_cursorField].index(), + TYPE_INDEX, cursor.c_str()); + if (isIncreCursor) { + GetCloudData(cursor, isIncreCursor, incrementCloudData_[tableName], data); + } else { + cursor = cursor.empty() ? "0" : cursor; + GetCloudData(cursor, isIncreCursor, cloudData_[tableName], data); + } + if (!isIncreCursor && data.empty() && isSetCrementCloudData_) { + extend[g_cursorField] = increPrefix_; + return OK; + } + return (data.empty() || data.size() < static_cast(queryLimit_)) ? QUERY_END : OK; +} + +void VirtualCloudDb::GetCloudData(const std::string &cursor, bool isIncreCursor, std::vector allData, + std::vector &data) +{ + for (auto &tableData : allData) { std::string srcCursor = std::get(tableData.extend[g_cursorField]); - if (std::stol(srcCursor) > std::stol(cursor)) { + if ((!isIncreCursor && std::stol(srcCursor) > std::stol(cursor)) || isIncreCursor) { VBucket bucket = tableData.record; for (const auto &ex: tableData.extend) { bucket.insert(ex); @@ -158,10 +184,9 @@ DBStatus VirtualCloudDb::Query(const std::string &tableName, VBucket &extend, st data.push_back(std::move(bucket)); } if (data.size() >= static_cast(queryLimit_)) { - return OK; + return; } } - return (data.empty() || data.size() < static_cast(queryLimit_)) ? QUERY_END : OK; } DBStatus VirtualCloudDb::InnerUpdate(const std::string &tableName, std::vector &&record, @@ -250,4 +275,29 @@ void VirtualCloudDb::SetHeartbeatError(bool heartbeatError) { heartbeatError_ = heartbeatError; } + +void VirtualCloudDb::SetIncrementData(const std::string &tableName, const VBucket &record, const VBucket &extend) +{ + std::lock_guard autoLock(cloudDataMutex_); + isSetCrementCloudData_ = true; + auto iter = incrementCloudData_.find(tableName); + if (iter == incrementCloudData_.end()) { + return; + } + CloudData data = {record, extend}; + iter->second.push_back(data); +} + +uint32_t VirtualCloudDb::GetQueryTimes(const std::string &tableName) +{ + if (queryTimes_.find(tableName) == queryTimes_.end()) { + return 0; + } + return queryTimes_[tableName]; +} + +void VirtualCloudDb::SetActionStatus(DBStatus status) +{ + actionStatus_ = status; +} } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/virtual_cloud_db.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/virtual_cloud_db.h index e536e7f22824aab98fc2763bb3e8b66e0149cfdb..4b7054c5a34565ebbabde7373ca4606a7256d10e 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/virtual_cloud_db.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/virtual_cloud_db.h @@ -53,6 +53,12 @@ public: bool GetLockStatus(); void SetHeartbeatError(bool heartbeatError); + + void SetIncrementData(const std::string &tableName, const VBucket &record, const VBucket &extend); + + uint32_t GetQueryTimes(const std::string &tableName); + + void SetActionStatus(DBStatus status); private: struct CloudData { VBucket record; @@ -64,6 +70,9 @@ private: DBStatus UpdateCloudData(const std::string &tableName, CloudData &&cloudData); + void GetCloudData(const std::string &cursor, bool isIncreCursor, std::vector allData, + std::vector &data); + std::atomic cloudError_ = false; std::atomic heartbeatError_ = false; std::atomic lockStatus_ = false; @@ -74,6 +83,11 @@ private: std::atomic heartbeatCount_ = 0; std::mutex cloudDataMutex_; std::map> cloudData_; + std::map> incrementCloudData_; + bool isSetCrementCloudData_ = false; + std::string increPrefix_ = "increPrefix_"; + std::map queryTimes_; + DBStatus actionStatus_ = OK; }; } #endif // VIRTUAL_CLOUD_DB_H diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/virtual_cloud_syncer.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/virtual_cloud_syncer.cpp index 0aa8627dbadb227fa02b6b8f9cae5148a9369efb..15afa3aad2e12256562efcc389fe5e76d354a1d5 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/virtual_cloud_syncer.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/virtual_cloud_syncer.cpp @@ -68,4 +68,10 @@ void VirtualCloudSyncer::Notify(bool notifyIfError) std::lock_guard autoLock(contextLock_); currentContext_.notifier->NotifyProcess(taskInfo, {}, notifyIfError); } + +size_t VirtualCloudSyncer::GetQueueCount() +{ + std::lock_guard autoLock(queueLock_); + return taskQueue_.size(); +} } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/virtual_cloud_syncer.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/virtual_cloud_syncer.h index 73df6a8642f60ccb16a49f774901eeee172ec6ce..ad35668a30f68789dd00516e5340968595801720 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/virtual_cloud_syncer.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/virtual_cloud_syncer.h @@ -31,6 +31,8 @@ public: void SetDownloadFunc(const std::function &); void Notify(bool notifyIfError = false); + + size_t GetQueueCount(); private: std::function downloadFunc_; std::atomic doDownload_; diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_mock_sync_module_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_mock_sync_module_test.cpp index 86c18e5166e6202849b08b73323e5e9910ad8567..c35cd16e9f80852dfd7f9f0856ac99530fd21a32 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_mock_sync_module_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_mock_sync_module_test.cpp @@ -380,7 +380,6 @@ void TimeSync001() delete storage; delete communicator; } -} class DistributedDBMockSyncModuleTest : public testing::Test { public: @@ -796,6 +795,31 @@ HWTEST_F(DistributedDBMockSyncModuleTest, DataSyncCheck003, TestSize.Level1) } #endif +/** + * @tc.name: DataSyncCheck004 + * @tc.desc: Test dataSync do ability sync. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBMockSyncModuleTest, DataSyncCheck004, TestSize.Level1) +{ + MockSingleVerDataSync dataSync; + auto *message = new (std::nothrow) DistributedDB::Message(); + ASSERT_TRUE(message != nullptr); + message->SetMessageType(TYPE_NOTIFY); + auto *context = new (std::nothrow) SingleVerKvSyncTaskContext(); + ASSERT_NE(context, nullptr); + auto *communicator = new (std::nothrow) VirtualCommunicator("DEVICE", nullptr); + ASSERT_NE(communicator, nullptr); + dataSync.SetCommunicatorHandle(communicator); + EXPECT_EQ(dataSync.CallDoAbilitySyncIfNeed(context, message, false), -E_NEED_ABILITY_SYNC); + delete message; + RefObject::KillAndDecObjRef(context); + dataSync.SetCommunicatorHandle(nullptr); + RefObject::KillAndDecObjRef(communicator); +} + /** * @tc.name: AutoLaunchCheck001 * @tc.desc: Test autoLaunch close connection. @@ -1741,6 +1765,45 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncTaskContextCheck005, TestSize.Leve EXPECT_EQ(context->GetQuerySyncId(), ""); RefObject::KillAndDecObjRef(context); } + +/** + * @tc.name: SyncTaskContextCheck006 + * @tc.desc: test context call get query id async. + * @tc.type: FUNC + * @tc.require: AR000CCPOM + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBMockSyncModuleTest, SyncTaskContextCheck006, TestSize.Level1) +{ + /** + * @tc.steps: step1. prepare context + */ + auto context = new (std::nothrow) SingleVerRelationalSyncTaskContext(); + ASSERT_NE(context, nullptr); + VirtualCommunicator communicator("device", nullptr); + VirtualSingleVerSyncDBInterface dbSyncInterface; + SingleVerSyncStateMachine stateMachine; + std::shared_ptr metadata = std::make_shared(); + ASSERT_EQ(metadata->Initialize(&dbSyncInterface), E_OK); + (void)stateMachine.Initialize(context, &dbSyncInterface, metadata, &communicator); + (void)context->Initialize("device", &dbSyncInterface, metadata, &communicator); + /** + * @tc.steps: step2. add sync target into context + */ + auto target = new (std::nothrow) SingleVerSyncTarget(); + ASSERT_NE(target, nullptr); + target->SetTaskType(ISyncTarget::RESPONSE); + EXPECT_EQ(context->AddSyncTarget(target), E_OK); + /** + * @tc.steps: step3. move to next target + * @tc.expected: retry time will be reset to zero + */ + context->SetRetryTime(AUTO_RETRY_TIMES); + context->MoveToNextTarget(); + EXPECT_EQ(context->GetRetryTime(), 0); + context->Clear(); + RefObject::KillAndDecObjRef(context); +} #ifdef RUN_AS_ROOT /** * @tc.name: TimeChangeListenerTest001 @@ -1946,6 +2009,31 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncerCheck006, TestSize.Level1) delete syncDBInterface; } +/** + * @tc.name: SyncerCheck007 + * @tc.desc: Test syncer get sync data size without syncer lock. + * @tc.type: FUNC + * @tc.require: AR000CCPOM + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBMockSyncModuleTest, SyncerCheck007, TestSize.Level1) +{ + MockSingleVerKVSyncer syncer; + auto mockMeta = std::make_shared(); + auto metadata = std::static_pointer_cast(mockMeta); + EXPECT_CALL(*mockMeta, GetLocalWaterMark).WillRepeatedly([&syncer](const DeviceID &, uint64_t &) { + syncer.TestSyncerLock(); + }); + syncer.SetMetadata(metadata); + auto syncDBInterface = new VirtualSingleVerSyncDBInterface(); + ASSERT_NE(syncDBInterface, nullptr); + syncer.Init(nullptr, syncDBInterface, true); + size_t size = 0u; + EXPECT_EQ(syncer.GetSyncDataSize("device", size), E_OK); + syncer.SetMetadata(nullptr); + delete syncDBInterface; +} + /** * @tc.name: SessionId001 * @tc.desc: Test syncer call set sync retry before init. @@ -2018,4 +2106,23 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SingleVerDataSyncUtils001, TestSize.Le SingleVerDataSyncUtils::TransSendDataItemToLocal(&context, "", data); EXPECT_NE(data[0]->GetTimestamp(), data[1]->GetTimestamp()); SingleVerKvEntry::Release(data); +} + +/** + * @tc.name: SyncTimerResetTest001 + * @tc.desc: Test it will retrurn ok when sync with a timer already exists. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangshijie + */ +HWTEST_F(DistributedDBMockSyncModuleTest, SyncTimerResetTest001, TestSize.Level1) { + MockSingleVerStateMachine stateMachine; + MockSyncTaskContext syncTaskContext; + MockCommunicator communicator; + VirtualSingleVerSyncDBInterface dbSyncInterface; + Init(stateMachine, syncTaskContext, communicator, dbSyncInterface); + + EXPECT_EQ(stateMachine.CallStartWatchDog(), E_OK); + EXPECT_EQ(stateMachine.CallPrepareNextSyncTask(), E_OK); +} } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_relational_ver_p2p_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_relational_ver_p2p_sync_test.cpp index d7b40533eb0ad09cdcea40a6605779abf18334fc..96f00bbea43b73ac2118beeee868a259e0c6e953 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_relational_ver_p2p_sync_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_relational_ver_p2p_sync_test.cpp @@ -2117,6 +2117,26 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RemoteQuery011, TestSize.Level1) EXPECT_EQ(result, nullptr); } +/** +* @tc.name: remote query 012 +* @tc.desc: Test rdb remote query with invalid dev +* @tc.type: FUNC +* @tc.require: AR000GK58G +* @tc.author: zhangqiquan +*/ +HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RemoteQuery012, TestSize.Level1) +{ + std::map dataMap; + std::string invalidDev = std::string(DBConstant::MAX_DEV_LENGTH + 1, '0'); + PrepareEnvironment(dataMap, {g_deviceB}); + ASSERT_NE(g_rdbDelegatePtr, nullptr); + RemoteCondition condition; + condition.sql = "SELECT * FROM " + g_tableName; + std::shared_ptr result = nullptr; + EXPECT_EQ(g_rdbDelegatePtr->RemoteQuery(invalidDev, condition, DBConstant::MIN_TIMEOUT, result), INVALID_ARGS); + EXPECT_EQ(result, nullptr); +} + /** * @tc.name: RelationalPemissionTest001 * @tc.desc: deviceB PermissionCheck not pass test, SYNC_MODE_PUSH_ONLY diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_simple_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_simple_sync_test.cpp index 4faed0f4388824b02b9017eee81ba0888a3d149c..20c4d463e3e1473ba882810c611c5f0cec384319 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_simple_sync_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_simple_sync_test.cpp @@ -745,8 +745,10 @@ HWTEST_F(DistributedDBSingleVerP2PSimpleSyncTest, NormalSync010, TestSize.Level1 { DBStatus status = OK; std::vector devices; + std::string invalidDev = std::string(DBConstant::MAX_DEV_LENGTH + 1, '0'); devices.push_back(DEVICE_A); devices.push_back(g_deviceB->GetDeviceId()); + devices.push_back(invalidDev); std::map result; status = g_tool.SyncTest(g_kvDelegatePtr, devices, SYNC_MODE_PUSH_ONLY, result); @@ -754,6 +756,7 @@ HWTEST_F(DistributedDBSingleVerP2PSimpleSyncTest, NormalSync010, TestSize.Level1 ASSERT_EQ(result.size(), devices.size()); EXPECT_EQ(result[DEVICE_A], INVALID_ARGS); + EXPECT_EQ(result[invalidDev], INVALID_ARGS); EXPECT_EQ(result[DEVICE_B], OK); } diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_meta_data.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_meta_data.h index c1e83d6e1650e6722ce9d712d6e85e7b6cd6f0f9..b9a29d0de497cbd9f8375c998c6831cb824d8b37 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_meta_data.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_meta_data.h @@ -24,6 +24,8 @@ public: MOCK_METHOD3(SetLastQueryTime, int(const std::string &, const std::string &, const Timestamp &)); MOCK_METHOD3(GetLastQueryTime, int(const std::string &, const std::string &, Timestamp &)); + + MOCK_METHOD2(GetLocalWaterMark, void(const DeviceID &, uint64_t &)); }; } // namespace DistributedDB #endif // #define MOCK_META_DATA_H \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_single_ver_data_sync.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_single_ver_data_sync.h index 550ece3dbb93050b87c596a432cc3cd425a6c0a2..c8d28c519067a9e17d094424611af92a989228f2 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_single_ver_data_sync.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_single_ver_data_sync.h @@ -42,6 +42,16 @@ public: return SingleVerDataSync::RemoveDeviceDataIfNeed(context); } + int CallDoAbilitySyncIfNeed(SingleVerSyncTaskContext *context, const Message *message, bool isControlMsg) + { + return SingleVerDataSync::DoAbilitySyncIfNeed(context, message, isControlMsg); + } + + void SetCommunicatorHandle(ICommunicator *communicator) + { + communicateHandle_ = communicator; + } + MOCK_METHOD1(RemoveDeviceDataIfNeed, int(SingleVerSyncTaskContext *)); }; } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_single_ver_kv_syncer.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_single_ver_kv_syncer.h index a479a092fbf38738778dce9323f2cb23c032d676..4bb7d46e7be858e898a7c72d3905f697293228a4 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_single_ver_kv_syncer.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_single_ver_kv_syncer.h @@ -47,6 +47,13 @@ public: { metadata_ = metadata; } + + void TestSyncerLock() + { + LOGD("begin get lock"); + std::lock_guard autoLock(syncerLock_); + LOGD("get lock success"); + } }; } #endif // MOCK_SINGLE_VER_KV_SYNCER_H diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_single_ver_state_machine.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_single_ver_state_machine.h index 9b7fbb37030b23cfe038134862349d2a57c125f0..8598c3b512fdede3b5d41fe8ac3911d2ff679406 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_single_ver_state_machine.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_single_ver_state_machine.h @@ -57,6 +57,16 @@ public: SyncStateMachine::SwitchMachineState(event); } + int CallPrepareNextSyncTask() + { + return SingleVerSyncStateMachine::PrepareNextSyncTask(); + } + + int CallStartWatchDog() + { + return SingleVerSyncStateMachine::StartWatchDog(); + } + uint8_t GetCurrentState() { return currentState_; diff --git a/kv_store/interfaces/innerkits/distributeddata/BUILD.gn b/kv_store/interfaces/innerkits/distributeddata/BUILD.gn index 9b6da14b983fd39960db719f3b761dde5e886eac..9d75c7cc01abbd1dd0c5d511e007adcffabf4154 100644 --- a/kv_store/interfaces/innerkits/distributeddata/BUILD.gn +++ b/kv_store/interfaces/innerkits/distributeddata/BUILD.gn @@ -91,10 +91,10 @@ deps_config = [ "//foundation/distributeddatamgr/kv_store/frameworks/libs/distri external_deps_config = [ "c_utils:utils", "device_manager:devicemanagersdk", - "hisysevent_native:libhisysevent", - "hitrace_native:hitrace_meter", - "hitrace_native:libhitracechain", - "hiviewdfx_hilog_native:libhilog", + "hisysevent:libhisysevent", + "hitrace:hitrace_meter", + "hitrace:libhitracechain", + "hilog:libhilog", "huks:libhukssdk", "ipc:ipc_single", "samgr:samgr_proxy", diff --git a/kv_store/interfaces/jskits/distributeddata/BUILD.gn b/kv_store/interfaces/jskits/distributeddata/BUILD.gn index e046791e63cfa7e8f8ee883ab48f6ecac09658b9..3957fda70186ad0cac6393c95c0d0fe692404c5b 100644 --- a/kv_store/interfaces/jskits/distributeddata/BUILD.gn +++ b/kv_store/interfaces/jskits/distributeddata/BUILD.gn @@ -75,7 +75,7 @@ ohos_shared_library("distributeddata") { "ability_runtime:napi_base_context", "c_utils:utils", "common_event_service:cesfwk_innerkits", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", "ipc:ipc_single", "napi:ace_napi", ] diff --git a/kv_store/interfaces/jskits/distributedkvstore/BUILD.gn b/kv_store/interfaces/jskits/distributedkvstore/BUILD.gn index 832daa84039b5b54a9445d4503a121cb92b14ba0..0f871bf673e986378f441dc0424e601f67262cf0 100644 --- a/kv_store/interfaces/jskits/distributedkvstore/BUILD.gn +++ b/kv_store/interfaces/jskits/distributedkvstore/BUILD.gn @@ -75,7 +75,7 @@ ohos_shared_library("distributedkvstore") { "ability_runtime:napi_base_context", "c_utils:utils", "common_event_service:cesfwk_innerkits", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", "ipc:ipc_single", "napi:ace_napi", ] diff --git a/kv_store/test/distributedtest/single_kvstore_client/BUILD.gn b/kv_store/test/distributedtest/single_kvstore_client/BUILD.gn index 7ce4568d3d6487a0bb93e6d6b5eb160a761b578c..56479110cb7f6132ad256954e3bd80218d2e7b27 100644 --- a/kv_store/test/distributedtest/single_kvstore_client/BUILD.gn +++ b/kv_store/test/distributedtest/single_kvstore_client/BUILD.gn @@ -92,10 +92,10 @@ ohos_distributedtest("DistributedTest") { external_deps = [ "c_utils:utils", "device_manager:devicemanagersdk", - "hisysevent_native:libhisysevent", - "hitrace_native:hitrace_meter", - "hitrace_native:libhitracechain", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", + "hisysevent:libhisysevent", + "hitrace:hitrace_meter", + "hitrace:libhitracechain", "huks:libhukssdk", "ipc:ipc_core", "samgr:samgr_proxy", @@ -120,10 +120,10 @@ ohos_distributedtest("DistributedTestAgent") { external_deps = [ "c_utils:utils", "device_manager:devicemanagersdk", - "hisysevent_native:libhisysevent", - "hitrace_native:hitrace_meter", - "hitrace_native:libhitracechain", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", + "hisysevent:libhisysevent", + "hitrace:hitrace_meter", + "hitrace:libhitracechain", "huks:libhukssdk", "ipc:ipc_core", "samgr:samgr_proxy", diff --git a/kv_store/test/fuzztest/blob_fuzzer/BUILD.gn b/kv_store/test/fuzztest/blob_fuzzer/BUILD.gn index edc1b818f7e0de17db896b8ceb1c4b159cf58f52..80279776e8c1346218dc2ad04f597356b95aa20a 100644 --- a/kv_store/test/fuzztest/blob_fuzzer/BUILD.gn +++ b/kv_store/test/fuzztest/blob_fuzzer/BUILD.gn @@ -45,7 +45,7 @@ ohos_fuzztest("BlobFuzzTest") { external_deps = [ "c_utils:utils", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", ] } diff --git a/kv_store/test/fuzztest/devicekvstore_fuzzer/BUILD.gn b/kv_store/test/fuzztest/devicekvstore_fuzzer/BUILD.gn index b1fbfb4bb3ce47205de28fe7aa082964efe33747..b6e3d4bb0b8a9afdd4841d634dce54c2f261944b 100644 --- a/kv_store/test/fuzztest/devicekvstore_fuzzer/BUILD.gn +++ b/kv_store/test/fuzztest/devicekvstore_fuzzer/BUILD.gn @@ -35,7 +35,7 @@ ohos_fuzztest("DeviceKvStoreFuzzTest") { external_deps = [ "c_utils:utils", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", "kv_store:distributeddata_inner", ] } diff --git a/kv_store/test/fuzztest/distributedkvdatamanager_fuzzer/BUILD.gn b/kv_store/test/fuzztest/distributedkvdatamanager_fuzzer/BUILD.gn index 2f838ded424b70f8bf192229025c00f763aa7243..4d286a2d30a6867314c96f9310d637d0815d9bd9 100644 --- a/kv_store/test/fuzztest/distributedkvdatamanager_fuzzer/BUILD.gn +++ b/kv_store/test/fuzztest/distributedkvdatamanager_fuzzer/BUILD.gn @@ -40,7 +40,7 @@ ohos_fuzztest("DistributedKvDataManagerFuzzTest") { external_deps = [ "c_utils:utils", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", "kv_store:distributeddata_inner", ] } diff --git a/kv_store/test/fuzztest/singlekvstore_fuzzer/BUILD.gn b/kv_store/test/fuzztest/singlekvstore_fuzzer/BUILD.gn index b5f62a24cd62aab63f95692c0d4658cfed6de057..d767c8b1766a7b362ac8f09c1e3213cbf9c15ba6 100644 --- a/kv_store/test/fuzztest/singlekvstore_fuzzer/BUILD.gn +++ b/kv_store/test/fuzztest/singlekvstore_fuzzer/BUILD.gn @@ -41,7 +41,7 @@ ohos_fuzztest("SingleKvStoreFuzzTest") { external_deps = [ "c_utils:utils", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", "kv_store:distributeddata_inner", ] } diff --git a/kv_store/test/fuzztest/typesutil_fuzzer/BUILD.gn b/kv_store/test/fuzztest/typesutil_fuzzer/BUILD.gn index 77818a65f3add11f07fb806f915094957937228e..f60d24c019cb51eb7b487c26d8574794fe86c3e1 100644 --- a/kv_store/test/fuzztest/typesutil_fuzzer/BUILD.gn +++ b/kv_store/test/fuzztest/typesutil_fuzzer/BUILD.gn @@ -48,7 +48,7 @@ ohos_fuzztest("TypesUtilFuzzTest") { external_deps = [ "c_utils:utils", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", "ipc:ipc_single", "kv_store:distributeddata_inner", ] diff --git a/mock/napi/native_common.h b/mock/napi/native_common.h index 188c3c0c612990eb8b561172f3eae7042ec1a896..06d4d094ce07ae5ca9ef011da2770846bb0c501c 100644 --- a/mock/napi/native_common.h +++ b/mock/napi/native_common.h @@ -18,7 +18,7 @@ #define DEPRECATED __attribute__((__deprecated__)) #ifndef NAPI_VERSION -#define NAPI_VERSION 2 +#define NAPI_VERSION 8 #endif #define NAPI_RETVAL_NOTHING diff --git a/mock/napi/src/js_native_api.h b/mock/napi/src/js_native_api.h index 5daa20f90400962b3ed18f0afc425fdb0e9f0366..c474debe5f03376511e7b6d0ced130b203d9718d 100644 --- a/mock/napi/src/js_native_api.h +++ b/mock/napi/src/js_native_api.h @@ -69,6 +69,9 @@ NAPI_EXTERN napi_status napi_create_array_with_length(napi_env env, NAPI_EXTERN napi_status napi_create_double(napi_env env, double value, napi_value* result); +NAPI_EXTERN napi_status napi_create_double(napi_env env, + double value, + napi_value* result); NAPI_EXTERN napi_status napi_create_int32(napi_env env, int32_t value, napi_value* result); diff --git a/mock/src/mock_js_napi.cpp b/mock/src/mock_js_napi.cpp index be4d6188f38cd5b25cd463c6d4569e46ea2f615d..9b6e0a78a811c1d023e170bcac35aa227bb2309c 100644 --- a/mock/src/mock_js_napi.cpp +++ b/mock/src/mock_js_napi.cpp @@ -58,6 +58,7 @@ napi_status napi_create_typedarray(napi_env env, napi_typedarray_type type, size napi_status napi_create_int32(napi_env env, int32_t value, napi_value *result) { return napi_ok; } napi_status napi_create_int64(napi_env env, int64_t value, napi_value *result) { return napi_ok; } napi_status napi_create_double(napi_env env, double value, napi_value *result) { return napi_ok; } +napi_status napi_create_date(napi_env env, double value, napi_value *result) { return napi_ok; } napi_status napi_get_boolean(napi_env env, bool value, napi_value *result) { return napi_ok; } napi_status napi_define_class(napi_env env, const char *utf8name, size_t length, napi_callback constructor, void *callback_data, size_t property_count, const napi_property_descriptor *properties, diff --git a/relational_store/CMakeLists.txt b/relational_store/CMakeLists.txt index 9abf12e4e94aa4964e3c7969935324371fc6d09a..964f741a960dd0c3d68f236c43fb043e95e75893 100644 --- a/relational_store/CMakeLists.txt +++ b/relational_store/CMakeLists.txt @@ -12,8 +12,9 @@ set(MOCK_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../mock) set(KV_STORE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../kv_store) add_definitions(-DNAPI_EXPERIMENTAL) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/js/napi/common/src relational_store_src) -aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/js/napi/dataability/src relational_store_src) -aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/js/napi/rdb/src relational_store_src) +#aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/js/napi/dataability/src relational_store_src) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/js/napi/relationalstore/src relational_store_src) +#aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/js/napi/rdb/src relational_store_src) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/native/appdatafwk/src relational_store_src) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/native/dataability/src relational_store_src) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/native/rdb/src relational_store_src) @@ -30,8 +31,9 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}/interfaces/inner_api/rdb_data_ab include_directories(${CMAKE_CURRENT_SOURCE_DIR}/interfaces/inner_api/rdb_data_share_adapter/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/common/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/js/napi/common/include) -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/js/napi/dataability/include) -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/js/napi/rdb/include) +#include_directories(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/js/napi/dataability/include) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/js/napi/relationalstore/include) +#include_directories(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/js/napi/rdb/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/native/dataability/src) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/native/rdb/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/native/rdb_device_manager_adapter/include) diff --git a/relational_store/bundle.json b/relational_store/bundle.json index 020d453bf60748bad6f56d19483445ad1b382c6b..cb43a48b6227edfb78f6f807e05f606bc4540ff2 100644 --- a/relational_store/bundle.json +++ b/relational_store/bundle.json @@ -53,9 +53,8 @@ "common_event_service", "c_utils", "device_manager", - "hilog_native", - "hitrace_native", - "hiviewdfx_hilog_native", + "hilog", + "hitrace", "huks", "ipc", "napi", diff --git a/relational_store/frameworks/js/napi/cloud_data/BUILD.gn b/relational_store/frameworks/js/napi/cloud_data/BUILD.gn index 0991ef48479617ff3958dcd22e1c9a73703084cf..2aaac109e732b9e8f5c66570da7e3d05eddb74d1 100644 --- a/relational_store/frameworks/js/napi/cloud_data/BUILD.gn +++ b/relational_store/frameworks/js/napi/cloud_data/BUILD.gn @@ -49,9 +49,8 @@ ohos_shared_library("clouddata") { "ability_runtime:abilitykit_native", "ability_runtime:napi_base_context", "c_utils:utils", - "hilog_native:libhilog", - "hitrace_native:hitrace_meter", - "hiviewdfx_hilog_native:libhilog", + "hilog:libhilog", + "hitrace:hitrace_meter", "ipc:ipc_core", "napi:ace_napi", "samgr:samgr_proxy", diff --git a/relational_store/frameworks/js/napi/common/include/js_utils.h b/relational_store/frameworks/js/napi/common/include/js_utils.h index 5f07852511fa194459bca4ceef793be552263b67..0f2f3d86fd9164c2ab3491fab8c438479234874f 100644 --- a/relational_store/frameworks/js/napi/common/include/js_utils.h +++ b/relational_store/frameworks/js/napi/common/include/js_utils.h @@ -113,9 +113,27 @@ napi_value Convert2JSValue(napi_env env, const T &value); template napi_value Convert2JSValue(napi_env env, const std::vector &value); +template +napi_value Convert2JSValue(napi_env env, const std::map &value); + template napi_value Convert2JSValue(napi_env env, const std::variant &value); +template +std::string ToString(const T &key); + +template +std::enable_if_t, std::string> ConvertMapKey(const K &key) +{ + return ToString(key); +} + +template +std::enable_if_t, const std::string &> ConvertMapKey(const K &key) +{ + return key; +} + template int32_t GetCPPValue(napi_env env, napi_value jsValue, T &value) { @@ -179,6 +197,25 @@ int32_t JSUtils::Convert2Value(napi_env env, napi_value jsValue, std::vector return napi_ok; } +template +napi_value JSUtils::Convert2JSValue(napi_env env, const std::map &value) +{ + napi_value jsValue; + napi_status status = napi_create_object(env, &jsValue); + if (status != napi_ok) { + return nullptr; + } + + for (const auto &[key, val] : value) { + const std::string &name = ConvertMapKey(key); + status = napi_set_named_property(env, jsValue, name.c_str(), Convert2JSValue(env, val)); + if (status != napi_ok) { + return nullptr; + } + } + return jsValue; +} + template int32_t JSUtils::Convert2Value(napi_env env, napi_value jsValue, std::variant &value) { diff --git a/relational_store/frameworks/js/napi/common/include/js_uv_queue.h b/relational_store/frameworks/js/napi/common/include/js_uv_queue.h new file mode 100644 index 0000000000000000000000000000000000000000..f9fb07c8262bec2c0b7ca712120bf5e71544606a --- /dev/null +++ b/relational_store/frameworks/js/napi/common/include/js_uv_queue.h @@ -0,0 +1,63 @@ +/* + * 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 DISTRIBUTEDDATAMGR_APPDATAMGR_UV_QUEUE_H +#define DISTRIBUTEDDATAMGR_APPDATAMGR_UV_QUEUE_H +#include +#include "napi/native_api.h" +#include "napi/native_common.h" +#include "napi/native_node_api.h" +#include "uv.h" + +namespace OHOS::AppDataMgrJsKit { +class UvQueue final { +public: + using ArgsGenerator = std::function; + using CallbackGetter = std::function; + struct UvCallback { + napi_ref callback_ = nullptr; + bool repeat_ = false; + CallbackGetter getter_; + UvCallback(napi_ref callback, bool repeat = false) : callback_(callback), repeat_(repeat) {} + UvCallback(CallbackGetter getter) : getter_(std::move(getter)) {} + bool IsNull() + { + return (callback_ == nullptr && getter_ == nullptr); + } + }; + + explicit UvQueue(napi_env env); + ~UvQueue(); + + napi_env GetEnv(); + void AsyncCall(UvCallback callback, ArgsGenerator genArgs = ArgsGenerator()); +private: + struct UvEntry { + napi_env env; + napi_ref callback; + bool repeat = false; + CallbackGetter getter; + ArgsGenerator args; + ~UvEntry() + { + if (callback != nullptr && !repeat) { + napi_delete_reference(env, callback); + } + } + }; + napi_env env_ = nullptr; + uv_loop_s* loop_ = nullptr; +}; +} // namespace OHOS::AppDataMgrJsKit +#endif // DISTRIBUTEDDATAMGR_APPDATAMGR_UV_QUEUE_H diff --git a/relational_store/frameworks/js/napi/common/src/js_uv_queue.cpp b/relational_store/frameworks/js/napi/common/src/js_uv_queue.cpp new file mode 100644 index 0000000000000000000000000000000000000000..100f80e385e9c03019e5ca47e852c270efeec610 --- /dev/null +++ b/relational_store/frameworks/js/napi/common/src/js_uv_queue.cpp @@ -0,0 +1,96 @@ +/* + * 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 +#include "js_uv_queue.h" +#include "logger.h" + +namespace OHOS::AppDataMgrJsKit { +using namespace OHOS::Rdb; +constexpr size_t ARGC_MAX = 6; +UvQueue::UvQueue(napi_env env) + : env_(env) +{ + if (env != nullptr) { + napi_get_uv_event_loop(env, &loop_); + } +} + +UvQueue::~UvQueue() +{ + LOG_DEBUG("no memory leak for queue-callback"); + env_ = nullptr; +} + +void UvQueue::AsyncCall(UvCallback callback, ArgsGenerator genArgs) +{ + if (loop_ == nullptr || callback.IsNull()) { + LOG_ERROR("loop_ or callback is nullptr"); + return; + } + + uv_work_t* work = new (std::nothrow) uv_work_t; + if (work == nullptr) { + LOG_ERROR("no memory for uv_work_t"); + return; + } + work->data = new (std::nothrow) + UvEntry{ env_, callback.callback_, callback.repeat_, std::move(callback.getter_), std::move(genArgs) }; + uv_queue_work( + loop_, work, [](uv_work_t* work) {}, + [](uv_work_t* work, int uvstatus) { + std::shared_ptr entry(static_cast(work->data), [work](UvEntry *data) { + delete data; + delete work; + }); + napi_handle_scope scope = nullptr; + napi_open_handle_scope(entry->env, &scope); + napi_value method = nullptr; + if (entry->callback != nullptr) { + napi_get_reference_value(entry->env, entry->callback, &method); + } else { + method = entry->getter(entry->env); + } + if (method == nullptr) { + LOG_ERROR("the callback is invalid, maybe is cleared!"); + if (scope != nullptr) { + napi_close_handle_scope(entry->env, scope); + } + return; + } + int argc = 0; + napi_value argv[ARGC_MAX] = { nullptr }; + if (entry->args) { + argc = ARGC_MAX; + entry->args(entry->env, argc, argv); + } + LOG_DEBUG("queue uv_after_work_cb"); + napi_value global = nullptr; + napi_get_global(entry->env, &global); + napi_value result; + napi_status status = napi_call_function(entry->env, global, method, argc, argv, &result); + if (status != napi_ok) { + LOG_ERROR("notify data change failed status:%{public}d.", status); + } + if (scope != nullptr) { + napi_close_handle_scope(entry->env, scope); + } + }); +} + +napi_env UvQueue::GetEnv() +{ + return env_; +} +} // namespace OHOS::AppDataMgrJsKit diff --git a/relational_store/frameworks/js/napi/dataability/BUILD.gn b/relational_store/frameworks/js/napi/dataability/BUILD.gn index 7678a06272ccebbf43087e37d4a5785e2c46af6f..7d79cc09cc1ce6735852fa37655fe99138cf614b 100644 --- a/relational_store/frameworks/js/napi/dataability/BUILD.gn +++ b/relational_store/frameworks/js/napi/dataability/BUILD.gn @@ -43,7 +43,7 @@ ohos_shared_library("dataability") { ] external_deps = [ - "hilog_native:libhilog", + "hilog:libhilog", "napi:ace_napi", ] diff --git a/relational_store/frameworks/js/napi/rdb/BUILD.gn b/relational_store/frameworks/js/napi/rdb/BUILD.gn index 78d972566af367b587641b6b4919096ee5d8c2c7..6a810946cb027fc194db915441d0087259c54bf6 100644 --- a/relational_store/frameworks/js/napi/rdb/BUILD.gn +++ b/relational_store/frameworks/js/napi/rdb/BUILD.gn @@ -87,8 +87,8 @@ ohos_shared_library("napi_rdb") { "ability_runtime:napi_base_context", "c_utils:utils", "common_event_service:cesfwk_innerkits", - "hilog_native:libhilog", - "hitrace_native:hitrace_meter", + "hilog:libhilog", + "hitrace:hitrace_meter", "napi:ace_napi", ] } @@ -149,8 +149,8 @@ ohos_shared_library("rdb") { "ability_runtime:abilitykit_native", "ability_runtime:napi_base_context", "c_utils:utils", - "hilog_native:libhilog", - "hitrace_native:hitrace_meter", + "hilog:libhilog", + "hitrace:hitrace_meter", "napi:ace_napi", ] } diff --git a/relational_store/frameworks/js/napi/rdb/include/napi_rdb_error.h b/relational_store/frameworks/js/napi/rdb/include/napi_rdb_error.h index 12a500ae25fc04d2648c76b8437d7a803410525a..19578ca77967a15a80689c6e87322f9ef20e34aa 100644 --- a/relational_store/frameworks/js/napi/rdb/include/napi_rdb_error.h +++ b/relational_store/frameworks/js/napi/rdb/include/napi_rdb_error.h @@ -15,8 +15,6 @@ #ifndef RDB_JS_NAPI_ERROR_H #define RDB_JS_NAPI_ERROR_H -#include - #include "logger.h" namespace OHOS { diff --git a/relational_store/frameworks/js/napi/relationalstore/BUILD.gn b/relational_store/frameworks/js/napi/relationalstore/BUILD.gn index 29ba7dee72c32b148228b92be11663fe39e7069a..62be81b2161213dc5f6991d69b9041876aa67726 100644 --- a/relational_store/frameworks/js/napi/relationalstore/BUILD.gn +++ b/relational_store/frameworks/js/napi/relationalstore/BUILD.gn @@ -23,6 +23,7 @@ ohos_copy("relational_store_declaration") { sources = [ "../common/src/js_utils.cpp", + "../common/src/js_uv_queue.cpp", "src/entry_point.cpp", "src/napi_async_call.cpp", "src/napi_rdb_const_properties.cpp", @@ -62,8 +63,8 @@ if (is_ohos) { "ability_runtime:napi_base_context", "c_utils:utils", "common_event_service:cesfwk_innerkits", - "hilog_native:libhilog", - "hitrace_native:hitrace_meter", + "hilog:libhilog", + "hitrace:hitrace_meter", "napi:ace_napi", ] diff --git a/relational_store/frameworks/js/napi/relationalstore/include/napi_async_call.h b/relational_store/frameworks/js/napi/relationalstore/include/napi_async_call.h index 621d193ef2ffff857ebddba31fa1520f491ee46f..f6c73cb34de16b313b25e1a1f9dd0ff01565805e 100644 --- a/relational_store/frameworks/js/napi/relationalstore/include/napi_async_call.h +++ b/relational_store/frameworks/js/napi/relationalstore/include/napi_async_call.h @@ -34,6 +34,7 @@ using ExecuteAction = std::function; class Context { public: void SetAction(napi_env env, napi_callback_info info, InputAction input, ExecuteAction exec, OutputAction output); + void SetAll(napi_env env, napi_callback_info info, InputAction input, ExecuteAction exec, OutputAction output); void SetError(std::shared_ptr error); virtual ~Context(); diff --git a/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_error.h b/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_error.h index f0678c744f2d42686eee86fd9ea3b5381a2e3796..8777074ec1a09ae709794e95fa0492ba4210abde 100644 --- a/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_error.h +++ b/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_error.h @@ -16,6 +16,7 @@ #define RDB_JS_NAPI_ERROR_H #include +#include #include "logger.h" #include "rdb_errno.h" diff --git a/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_js_utils.h b/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_js_utils.h index 97a3cbbf76a476d49ed0e54a713071a7b00db1f6..5f25014de6f98eec87783d6a3f614673ab144b2b 100644 --- a/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_js_utils.h +++ b/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_js_utils.h @@ -27,7 +27,9 @@ namespace OHOS::AppDataMgrJsKit { namespace JSUtils { using Asset = OHOS::NativeRdb::AssetValue; using RowEntity = OHOS::NativeRdb::RowEntity; +using Date = OHOS::DistributedRdb::Date; using JSChangeInfo = OHOS::RelationalStoreJsKit::NapiRdbStoreObserver::JSChangeInfo; +using PRIKey = OHOS::DistributedRdb::RdbStoreObserver::PrimaryKey; template<> int32_t Convert2Value(napi_env env, napi_value input, Asset &output); @@ -50,6 +52,10 @@ template<> napi_value Convert2JSValue(napi_env env, const DistributedRdb::Details &details); template<> napi_value Convert2JSValue(napi_env env, const JSChangeInfo &value); +template<> +napi_value Convert2JSValue(napi_env env, const Date &date); +template<> +std::string ToString(const PRIKey &key); }; // namespace JSUtils } // namespace OHOS::AppDataMgrJsKit #endif // RDB_JSKIT_NAPI_RDB_JS_UTILS_H diff --git a/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_store.h b/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_store.h index fcadeea4a4d03dda78f0b9adffe46fccb07bd5b1..7a02f05223afc387e33644c6d876c83f68fa6309 100644 --- a/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_store.h +++ b/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_store.h @@ -19,6 +19,7 @@ #include #include +#include "js_uv_queue.h" #include "napi/native_api.h" #include "napi/native_common.h" #include "napi/native_node_api.h" @@ -70,6 +71,7 @@ private: static napi_value ObtainDistributedTableName(napi_env env, napi_callback_info info); static napi_value Sync(napi_env env, napi_callback_info info); static napi_value CloudSync(napi_env env, napi_callback_info info); + static napi_value GetModifyTime(napi_env env, napi_callback_info info); static napi_value OnEvent(napi_env env, napi_callback_info info); static napi_value OffEvent(napi_env env, napi_callback_info info); @@ -89,6 +91,7 @@ private: std::mutex mutex_; bool isSystemAppCalled_ = false; + std::shared_ptr queue_; std::list> observers_[DistributedRdb::SUBSCRIBE_MODE_MAX]; }; } // namespace RelationalStoreJsKit diff --git a/relational_store/frameworks/js/napi/relationalstore/src/napi_async_call.cpp b/relational_store/frameworks/js/napi/relationalstore/src/napi_async_call.cpp index 513925a08f18927978732dc529bff1e736c500b3..2ceff6f6319a4cab7cf807f3b6a0f841bbe03740 100644 --- a/relational_store/frameworks/js/napi/relationalstore/src/napi_async_call.cpp +++ b/relational_store/frameworks/js/napi/relationalstore/src/napi_async_call.cpp @@ -49,6 +49,25 @@ void Context::SetAction( napi_create_reference(env, self, 1, &self_); } +void Context::SetAll( + napi_env env, napi_callback_info info, InputAction input, ExecuteAction exec, OutputAction output) +{ + env_ = env; + size_t argc = MAX_INPUT_COUNT; + napi_value self = nullptr; + napi_value argv[MAX_INPUT_COUNT] = { nullptr }; + NAPI_CALL_RETURN_VOID(env, napi_get_cb_info(env, info, &argc, argv, &self, nullptr)); + + // int -->input_(env, argc, argv, self) + input(env, argc, argv, self); + + // if input return is not ok, then napi_throw_error context error + RDB_NAPI_ASSERT_BASE(env, error == nullptr, error, NAPI_RETVAL_NOTHING); + output_ = std::move(output); + exec_ = std::move(exec); + napi_create_reference(env, self, 1, &self_); +} + void Context::SetError(std::shared_ptr err) { error = err; diff --git a/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_js_utils.cpp b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_js_utils.cpp index 91011b8547db60c29e88ab7bb58a463d0de25afe..56e9cf5efd0d2c6c7fdea35c25ab7011a9a93b3b 100644 --- a/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_js_utils.cpp +++ b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_js_utils.cpp @@ -205,5 +205,34 @@ napi_value Convert2JSValue(napi_env env, const JSChangeInfo &value) ADD_JS_PROPERTY(env, object, value, deleted); return object; } + +template<> +napi_value Convert2JSValue(napi_env env, const Date &date) +{ + napi_value jsValue; + napi_status status = napi_create_date(env, date, &jsValue); + if (status != napi_ok) { + return nullptr; + } + return jsValue; +} + +template<> +std::string ToString(const PRIKey &key) +{ + auto strVal = std::get_if(&key); + if (strVal != nullptr) { + return *strVal; + } + auto intVal = std::get_if(&key); + if (intVal != nullptr) { + return std::to_string(*intVal); + } + auto dbVal = std::get_if(&key); + if (dbVal != nullptr) { + return std::to_string(static_cast(*dbVal)); + } + return {}; +} }; // namespace JSUtils } // namespace OHOS::AppDataMgrJsKit \ No newline at end of file diff --git a/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_store.cpp b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_store.cpp index 29710b4c2bd2e32ef51cd6aa8d28930b5d93066a..b304a6b5136fe5589fa082a9b9084bf45b3ef3fa 100644 --- a/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_store.cpp +++ b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_store.cpp @@ -77,14 +77,17 @@ struct RdbStoreContext : public Context { std::string aliasName; std::string pathName; std::string srcName; + std::string columnName; int32_t enumArg; int32_t distributedType; int32_t syncMode; DistributedRdb::DistributedConfig distributedConfig; + napi_ref asyncHolder = nullptr; NativeRdb::ConflictResolution conflictResolution; DistributedRdb::SyncResult syncResult; - napi_value cloudSyncCallback = nullptr; std::shared_ptr rdbPredicates = nullptr; + std::vector keys; + std::map modifyTime; RdbStoreContext() : predicatesProxy(nullptr), int64Output(0), intOutput(0), enumArg(-1), @@ -158,6 +161,7 @@ void RdbStoreProxy::Init(napi_env env, napi_value exports) DECLARE_NAPI_FUNCTION("obtainDistributedTableName", ObtainDistributedTableName), DECLARE_NAPI_FUNCTION("sync", Sync), DECLARE_NAPI_FUNCTION("cloudSync", CloudSync), + DECLARE_NAPI_FUNCTION("getModifyTime", GetModifyTime), DECLARE_NAPI_FUNCTION("on", OnEvent), DECLARE_NAPI_FUNCTION("off", OffEvent), #endif @@ -217,6 +221,7 @@ napi_value RdbStoreProxy::NewInstance(napi_env env, std::shared_ptrqueue_ = std::make_shared(env); proxy->rdbStore_ = std::move(value); proxy->isSystemAppCalled_ = isSystemAppCalled; return instance; @@ -251,6 +256,20 @@ int ParseTableName(const napi_env &env, const napi_value &arg, std::shared_ptr context) +{ + context->columnName = JSUtils::Convert2String(env, arg); + CHECK_RETURN_SET(!context->columnName.empty(), std::make_shared("columnName", "not string")); + return OK; +} + +int ParsePrimaryKey(const napi_env &env, const napi_value &arg, std::shared_ptr context) +{ + JSUtils::Convert2Value(env, arg, context->keys); + CHECK_RETURN_SET(!context->keys.empty(), std::make_shared("PRIKey", "not number or string")); + return OK; +} + int ParseDevice(const napi_env &env, const napi_value &arg, std::shared_ptr context) { context->device = JSUtils::Convert2String(env, arg); @@ -323,7 +342,7 @@ int ParseCloudSyncCallback(const napi_env &env, const napi_value &arg, std::shar napi_valuetype valueType = napi_undefined; napi_typeof(env, arg, &valueType); CHECK_RETURN_SET(valueType == napi_function, std::make_shared("a callback type")); - context->cloudSyncCallback = arg; + napi_create_reference(env, arg, 1, &context->asyncHolder); LOG_DEBUG("ParseCloudSyncCallback end"); return OK; @@ -1156,7 +1175,7 @@ napi_value RdbStoreProxy::CloudSync(napi_env env, napi_callback_info info) LOG_DEBUG("RdbStoreProxy::CloudSync start"); auto context = std::make_shared(); auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) { - CHECK_RETURN_SET_E(argc == 2 || argc == 3, std::make_shared("2 - 4")); + CHECK_RETURN_SET_E(argc > 1 && argc < 5, std::make_shared("2 - 4")); CHECK_RETURN(OK == ParserThis(env, self, context)); CHECK_RETURN(OK == ParseCloudSyncModeArg(env, argv[0], context)); uint32_t index = 1; @@ -1166,7 +1185,16 @@ napi_value RdbStoreProxy::CloudSync(napi_env env, napi_callback_info info) CHECK_RETURN(OK == ParseTablesName(env, argv[index], context)); index++; } - CHECK_RETURN(OK == ParseCloudSyncCallback(env, argv[index], context)); + CHECK_RETURN(OK == ParseCloudSyncCallback(env, argv[index++], context)); + CHECK_RETURN_SET_E(index == argc - 1 || index == argc, std::make_shared("2 - 4")); + if (index == argc - 1) { + napi_valuetype valueType = napi_undefined; + napi_typeof(env, argv[index], &valueType); + if (valueType == napi_function) { + LOG_INFO("asyncCall set callback"); + NAPI_CALL_RETURN_VOID(env, napi_create_reference(env, argv[index], 1, &context->callback_)); + } + } }; auto exec = [context]() -> int { LOG_DEBUG("RdbStoreProxy::CloudSync Async"); @@ -1175,18 +1203,57 @@ napi_value RdbStoreProxy::CloudSync(napi_env env, napi_callback_info info) option.mode = static_cast(context->syncMode); option.isBlock = false; - return obj->rdbStore_->Sync(option, context->tablesNames, [context](const Details &details) { - auto callback = std::make_shared(context->env_, context->cloudSyncCallback); - callback->OnSyncCompelete(details); - }); + context->execCode_ = obj->rdbStore_->Sync(option, context->tablesNames, + [queue = obj->queue_, callback = context->asyncHolder](const Details &details) { + if (queue == nullptr || callback == nullptr) { + return; + } + bool repeat = !details.empty() && details.begin()->second.progress != DistributedRdb::SYNC_FINISH; + queue->AsyncCall({ callback, repeat }, [details](napi_env env, int &argc, napi_value *argv) -> void { + argc = 1; + argv[0] = details.empty() ? nullptr : JSUtils::Convert2JSValue(env, details.begin()->second); + }); + }); + return OK; }; auto output = [context](napi_env env, napi_value &result) { LOG_DEBUG("RdbStoreProxy::CloudSync output"); + if (context->execCode_ != E_OK && context->asyncHolder != nullptr) { + napi_delete_reference(env, context->asyncHolder); + } napi_status status = napi_get_undefined(env, &result); CHECK_RETURN_SET_E(status == napi_ok, std::make_shared(E_ERROR)); }; + context->SetAll(env, info, input, exec, output); + + CHECK_RETURN_NULL(context->error == nullptr || context->error->GetCode() == OK); + return AsyncCall::Call(env, context); +} + +napi_value RdbStoreProxy::GetModifyTime(napi_env env, napi_callback_info info) +{ + LOG_DEBUG("RdbStoreProxy::GetModifyTime start"); + auto context = std::make_shared(); + auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) { + CHECK_RETURN_SET_E(argc == 3, std::make_shared("3 - 4")); + CHECK_RETURN(OK == ParserThis(env, self, context)); + CHECK_RETURN(OK == ParseTableName(env, argv[0], context)); + CHECK_RETURN(OK == ParseColumnName(env, argv[1], context)); + CHECK_RETURN(OK == ParsePrimaryKey(env, argv[2], context)); + }; + auto exec = [context]() -> int { + LOG_DEBUG("RdbStoreProxy::GetModifyTime Async"); + auto *obj = reinterpret_cast(context->boundObj); + context->modifyTime = obj->rdbStore_->GetModifyTime(context->tableName, context->columnName, context->keys); + return context->modifyTime.empty() ? E_ERROR : E_OK; + }; + auto output = [context](napi_env env, napi_value &result) { + LOG_DEBUG("RdbStoreProxy::GetModifyTime output"); + result = JSUtils::Convert2JSValue(env, context->modifyTime); + CHECK_RETURN_SET_E(result != nullptr, std::make_shared(E_ERROR)); + }; context->SetAction(env, info, input, exec, output); CHECK_RETURN_NULL(context->error == nullptr || context->error->GetCode() == OK); diff --git a/relational_store/frameworks/js/napi/relationalstore/src/napi_result_set.cpp b/relational_store/frameworks/js/napi/relationalstore/src/napi_result_set.cpp index 951de5c0720ae69aa99be00d75b2b3048d09bf39..05ba2c8e80cd8cb739b7696d7b3c4323d9aff454 100644 --- a/relational_store/frameworks/js/napi/relationalstore/src/napi_result_set.cpp +++ b/relational_store/frameworks/js/napi/relationalstore/src/napi_result_set.cpp @@ -457,6 +457,10 @@ napi_value ResultSetProxy::GetAsset(napi_env env, napi_callback_info info) Asset result; int errCode = resultSetProxy->resultSet_->GetAsset(columnIndex, result); + if (errCode == E_NULL_OBJECT) { + LOG_DEBUG("getAsset col %{public}d is null ", columnIndex); + return JSUtils::Convert2JSValue(env, std::monostate()); + } RDB_NAPI_ASSERT(env, errCode == E_OK, std::make_shared(errCode)); return JSUtils::Convert2JSValue(env, result); @@ -471,6 +475,10 @@ napi_value ResultSetProxy::GetAssets(napi_env env, napi_callback_info info) Assets result; int errCode = resultSetProxy->resultSet_->GetAssets(columnIndex, result); + if (errCode == E_NULL_OBJECT) { + LOG_DEBUG("getAssets col %{public}d is null ", columnIndex); + return JSUtils::Convert2JSValue(env, std::monostate()); + } RDB_NAPI_ASSERT(env, errCode == E_OK, std::make_shared(errCode)); return JSUtils::Convert2JSValue(env, result); diff --git a/relational_store/frameworks/native/appdatafwk/src/general_endian.cpp b/relational_store/frameworks/native/appdatafwk/src/general_endian.cpp new file mode 100644 index 0000000000000000000000000000000000000000..295c2c09032f234e93c1ce97008daf1c3a03c89c --- /dev/null +++ b/relational_store/frameworks/native/appdatafwk/src/general_endian.cpp @@ -0,0 +1,39 @@ +/* +* 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 "multi_platform_endian.h" +#include + +#if defined(WINDOWS_PLATFORM) +namespace OHOS { +uint16_t Endian::LeToH(uint16_t value) +{ + return le16toh(value); +} +uint16_t Endian::HToLe(uint16_t value) +{ + return htole16(value); +} + +uint32_t Endian::LeToH(uint32_t value) +{ + return le32toh(value); +} +uint32_t Endian::HToLe(uint32_t value) +{ + return htole32(value); +} +} +#endif diff --git a/relational_store/frameworks/native/cloud_data/include/icloud_service.h b/relational_store/frameworks/native/cloud_data/include/icloud_service.h index a21def4f50c48b9c94c8e38e23636e4a54f6231b..fe6c3e546e2d3afe1953f2f97e55eef6ff8c8ccc 100644 --- a/relational_store/frameworks/native/cloud_data/include/icloud_service.h +++ b/relational_store/frameworks/native/cloud_data/include/icloud_service.h @@ -18,6 +18,7 @@ #include "cloud_service.h" #include "iremote_broker.h" +#include "distributeddata_relational_store_ipc_interface_code.h" namespace OHOS::CloudData { class ICloudService : public CloudService, public IRemoteBroker { @@ -27,8 +28,6 @@ public: class IKvStoreDataService : public IRemoteBroker { public: - enum { GET_FEATURE_INTERFACE = 0 }; - virtual sptr GetFeatureInterface(const std::string &name) = 0; DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.DistributedKv.IKvStoreDataService"); 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 43bf0dd30ff9ce765888ba54f6826a9fbb7c474e..b138cbdebbf6888b90023225163c17986e022157 100644 --- a/relational_store/frameworks/native/cloud_data/src/cloud_manager.cpp +++ b/relational_store/frameworks/native/cloud_data/src/cloud_manager.cpp @@ -24,6 +24,7 @@ namespace OHOS::CloudData { using namespace OHOS::Rdb; +using namespace OHOS::DistributedRdb::RelationalStore; class DataMgrService : public IRemoteProxy { public: @@ -120,7 +121,8 @@ sptr DataMgrService::GetFeatureInterface(const std::string &name) MessageParcel reply; MessageOption mo{ MessageOption::TF_SYNC }; - int32_t error = Remote()->SendRequest(GET_FEATURE_INTERFACE, data, reply, mo); + int32_t error = Remote()->SendRequest( + static_cast(CloudKvStoreInterfaceCode::GET_FEATURE_INTERFACE), data, reply, mo); if (error != 0) { LOG_ERROR("SendRequest returned %{public}d", error); return nullptr; diff --git a/relational_store/frameworks/native/dataability/src/ishared_result_set_proxy.cpp b/relational_store/frameworks/native/dataability/src/ishared_result_set_proxy.cpp index 6ede53ae6c18532f8c25fa1891068f022e982f08..aa11c7b294d2a0762bcb8e39d288c3fd83b6ecf7 100644 --- a/relational_store/frameworks/native/dataability/src/ishared_result_set_proxy.cpp +++ b/relational_store/frameworks/native/dataability/src/ishared_result_set_proxy.cpp @@ -23,6 +23,8 @@ namespace OHOS::NativeRdb { using namespace OHOS::Rdb; +using ResultSetCode = OHOS::DistributedRdb::RelationalStore::IResultSetInterfaceCode; + std::function( MessageParcel &parcel)> ISharedResultSet::consumerCreator_ = ISharedResultSetProxy::CreateProxy; BrokerDelegator ISharedResultSetProxy::delegator_; @@ -55,7 +57,8 @@ int ISharedResultSetProxy::GetAllColumnNames(std::vector &columnNam request.WriteInterfaceToken(GetDescriptor()); MessageParcel reply; MessageOption msgOption; - int errCode = Remote()->SendRequest(FUNC_GET_ALL_COLUMN_NAMES, request, reply, msgOption); + int errCode = Remote()->SendRequest( + static_cast(ResultSetCode::FUNC_GET_ALL_COLUMN_NAMES), request, reply, msgOption); if (errCode != 0) { LOG_ERROR("GetAllColumnNames IPC Error %{public}x", errCode); return -errCode; @@ -83,7 +86,8 @@ int ISharedResultSetProxy::GetRowCount(int &count) request.WriteInterfaceToken(GetDescriptor()); MessageParcel reply; MessageOption msgOption; - int errCode = Remote()->SendRequest(FUNC_GET_ROW_COUNT, request, reply, msgOption); + int errCode = Remote()->SendRequest( + static_cast(ResultSetCode::FUNC_GET_ROW_COUNT), request, reply, msgOption); if (errCode != 0) { LOG_ERROR("GetRowCount IPC Error %{public}x", errCode); return -errCode; @@ -108,7 +112,7 @@ bool ISharedResultSetProxy::OnGo(int oldRowIndex, int newRowIndex) request.WriteInt32(newRowIndex); MessageParcel reply; MessageOption msgOption; - int errCode = Remote()->SendRequest(FUNC_ON_GO, request, reply, msgOption); + int errCode = Remote()->SendRequest(static_cast(ResultSetCode::FUNC_ON_GO), request, reply, msgOption); if (errCode != 0) { LOG_ERROR("OnGo IPC Error %{public}x", errCode); return -errCode; @@ -124,7 +128,7 @@ int ISharedResultSetProxy::Close() request.WriteInterfaceToken(GetDescriptor()); MessageParcel reply; MessageOption msgOption; - int errCode = Remote()->SendRequest(FUNC_CLOSE, request, reply, msgOption); + int errCode = Remote()->SendRequest(static_cast(ResultSetCode::FUNC_CLOSE), request, reply, msgOption); if (errCode != 0) { LOG_ERROR("Close IPC Error %{public}x", errCode); return -errCode; diff --git a/relational_store/frameworks/native/dataability/src/ishared_result_set_stub.cpp b/relational_store/frameworks/native/dataability/src/ishared_result_set_stub.cpp index ac0e92dddfb3f19fe4013caeb888de49fd1b314d..39e78db2ca71beadf831ba733211cdcc58d5803c 100644 --- a/relational_store/frameworks/native/dataability/src/ishared_result_set_stub.cpp +++ b/relational_store/frameworks/native/dataability/src/ishared_result_set_stub.cpp @@ -25,7 +25,7 @@ using namespace OHOS::Rdb; std::function(std::shared_ptr, MessageParcel &)> ISharedResultSet::providerCreator_ = ISharedResultSetStub::CreateStub; -constexpr ISharedResultSetStub::Handler ISharedResultSetStub::handlers[ISharedResultSet::FUNC_BUTT]; +constexpr ISharedResultSetStub::Handler ISharedResultSetStub::handlers[static_cast(ResultSetCode::FUNC_BUTT)]; sptr ISharedResultSetStub::CreateStub(std::shared_ptr result, OHOS::MessageParcel &parcel) @@ -71,7 +71,7 @@ int ISharedResultSetStub::OnRemoteRequest(uint32_t code, OHOS::MessageParcel &da return INVALID_FD; } - if (code >= FUNC_BUTT) { + if (code >= static_cast(ResultSetCode::FUNC_BUTT)) { LOG_ERROR("OnRemoteRequest method code(%{public}d) out of range", code); return IPCObjectStub::OnRemoteRequest(code, data, reply, option); } diff --git a/relational_store/frameworks/native/dataability/src/ishared_result_set_stub.h b/relational_store/frameworks/native/dataability/src/ishared_result_set_stub.h index 2f0dda82f692544647b7fbb47f8a9d177a2b9251..a7be30c748f1f5407140d657cbac2dda232788ca 100644 --- a/relational_store/frameworks/native/dataability/src/ishared_result_set_stub.h +++ b/relational_store/frameworks/native/dataability/src/ishared_result_set_stub.h @@ -21,6 +21,8 @@ #include "ishared_result_set.h" #include "iremote_stub.h" namespace OHOS::NativeRdb { +using ResultSetCode = OHOS::DistributedRdb::RelationalStore::IResultSetInterfaceCode; + class ISharedResultSetStub : public IRemoteStub { public: explicit ISharedResultSetStub(std::shared_ptr resultSet); @@ -55,7 +57,7 @@ private: SafeBlockQueue> runnables_; bool isRunning_ = true; std::thread thread_; - static constexpr Handler handlers[FUNC_BUTT] { + static constexpr Handler handlers[static_cast(ResultSetCode::FUNC_BUTT)] { &ISharedResultSetStub::HandleGetRowCountRequest, &ISharedResultSetStub::HandleGetAllColumnNamesRequest, &ISharedResultSetStub::HandleOnGoRequest, diff --git a/relational_store/frameworks/native/rdb/include/irdb_service.h b/relational_store/frameworks/native/rdb/include/irdb_service.h index 4ab698779ae9c7780870429e43a7879e4dd4ee73..35b30c87ac9893a9a3d2e9d9c35575a849d7bb8f 100644 --- a/relational_store/frameworks/native/rdb/include/irdb_service.h +++ b/relational_store/frameworks/native/rdb/include/irdb_service.h @@ -20,6 +20,8 @@ #include "iremote_broker.h" #include "rdb_service.h" +#include "distributeddata_relational_store_ipc_interface_code.h" + namespace OHOS::DistributedRdb { class IRdbService : public RdbService, public IRemoteBroker { public: @@ -28,11 +30,6 @@ public: class IKvStoreDataService : public IRemoteBroker { public: - enum { - GET_FEATURE_INTERFACE = 0, - REGISTER_DEATH_OBSERVER, - }; - DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.DistributedKv.IKvStoreDataService"); virtual sptr GetFeatureInterface(const std::string &name) = 0; virtual int32_t RegisterDeathObserver(const std::string &bundleName, sptr observer) = 0; diff --git a/relational_store/frameworks/native/rdb/include/rdb_notifier_stub.h b/relational_store/frameworks/native/rdb/include/rdb_notifier_stub.h index f9e35df60d129a49115c721275b4d80fea305eb0..35663b0ba0b2757193b295e362e829deb5b8302f 100644 --- a/relational_store/frameworks/native/rdb/include/rdb_notifier_stub.h +++ b/relational_store/frameworks/native/rdb/include/rdb_notifier_stub.h @@ -19,6 +19,8 @@ #include #include namespace OHOS::DistributedRdb { +using NotifierIFCode = RelationalStore::IRdbNotifierInterfaceCode; + class RdbNotifierStubBroker : public IRdbNotifier, public IRemoteBroker { public: DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.DistributedRdb.IRdbNotifier"); @@ -42,9 +44,9 @@ private: bool CheckInterfaceToken(MessageParcel& data); using RequestHandle = int32_t (RdbNotifierStub::*)(MessageParcel&, MessageParcel&); - static constexpr RequestHandle HANDLES[RDB_NOTIFIER_CMD_MAX] = { - [RDB_NOTIFIER_CMD_SYNC_COMPLETE] = &RdbNotifierStub::OnCompleteInner, - [RDB_NOTIFIER_CMD_DATA_CHANGE] = &RdbNotifierStub::OnChangeInner, + static constexpr RequestHandle HANDLES[static_cast(NotifierIFCode::RDB_NOTIFIER_CMD_MAX)] = { + [static_cast(NotifierIFCode::RDB_NOTIFIER_CMD_SYNC_COMPLETE)] = &RdbNotifierStub::OnCompleteInner, + [static_cast(NotifierIFCode::RDB_NOTIFIER_CMD_DATA_CHANGE)] = &RdbNotifierStub::OnChangeInner, }; SyncCompleteHandler completeNotifier_; 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 73929f4ee25b934f1d676e90be36e15663bb1947..9513c3882d7508f5050f5f918e512642032bdbd9 100644 --- a/relational_store/frameworks/native/rdb/include/rdb_store_impl.h +++ b/relational_store/frameworks/native/rdb/include/rdb_store_impl.h @@ -91,6 +91,7 @@ public: std::string GetFileType(); std::shared_ptr QueryByStep(const std::string &sql, const std::vector &selectionArgs) override; + std::shared_ptr QueryByStep(const std::string &sql, std::vector &&args) override; std::shared_ptr QueryByStep( const AbsRdbPredicates &predicates, const std::vector columns) override; std::shared_ptr Query( @@ -118,6 +119,9 @@ public: // user must use UDID bool DropDeviceData(const std::vector& devices, const DropOption& option) override; + std::map GetModifyTime( + const std::string &table, const std::string &columnName, std::vector &keys) override; + private: int InnerOpen(); int InnerInsert(int64_t &outRowId, const std::string &table, ValuesBucket values, @@ -134,6 +138,9 @@ private: void DoCloudSync(const std::string &table); int InnerBackup(const std::string databasePath, const std::vector destEncryptKey = std::vector()); + std::map GetModifyTimeByRowId( + const std::string &logTable, std::vector &keys); + std::string GetSqlArgs(size_t size); const RdbStoreConfig rdbStoreConfig; SqliteConnectionPool *connectionPool; diff --git a/relational_store/frameworks/native/rdb/include/sqlite_connection.h b/relational_store/frameworks/native/rdb/include/sqlite_connection.h index ec242bf2aa61a2e4a2375e82b7893907519206b2..945f5ee139287608b8b49718496c15df67da5ca1 100644 --- a/relational_store/frameworks/native/rdb/include/sqlite_connection.h +++ b/relational_store/frameworks/native/rdb/include/sqlite_connection.h @@ -47,6 +47,8 @@ public: const std::vector &bindArgs = std::vector()); std::shared_ptr BeginStepQuery(int &errCode, const std::string &sql, const std::vector &selectionArgs) const; + std::shared_ptr BeginStepQuery(int &errCode, const std::string &sql, + const std::vector &args) const; int DesFinalize(); int EndStepQuery(); void SetInTransaction(bool transaction); diff --git a/relational_store/frameworks/native/rdb/include/step_result_set.h b/relational_store/frameworks/native/rdb/include/step_result_set.h index 1193712853aa35a100d29402c59605b4ebd7f06a..c7c4c2071efd7599179b63c1de24abec5df0f5f6 100644 --- a/relational_store/frameworks/native/rdb/include/step_result_set.h +++ b/relational_store/frameworks/native/rdb/include/step_result_set.h @@ -31,6 +31,8 @@ class StepResultSet : public AbsResultSet { public: StepResultSet(std::shared_ptr rdb, SqliteConnectionPool *connectionPool, const std::string &sql, const std::vector &selectionArgs); + StepResultSet(std::shared_ptr rdb, SqliteConnectionPool *pool, const std::string &sql, + std::vector &&args); ~StepResultSet() override; int GetAllColumnNames(std::vector &columnNames) override; @@ -66,6 +68,7 @@ private: SqliteConnectionPool *connectionPool_; std::string sql; std::vector selectionArgs; + std::vector args_; // Whether reach the end of this result set or not bool isAfterLast; // The value indicates the row count of the result set diff --git a/relational_store/frameworks/native/rdb/mock/include/rdb_store_impl.h b/relational_store/frameworks/native/rdb/mock/include/rdb_store_impl.h index 6da70afbefb7aef6fe01105b8bdf13cbd5d8df48..1d41bac95dcd1d08ea5ea6ae75835e559aacdb10 100644 --- a/relational_store/frameworks/native/rdb/mock/include/rdb_store_impl.h +++ b/relational_store/frameworks/native/rdb/mock/include/rdb_store_impl.h @@ -83,6 +83,7 @@ public: std::string GetFileType(); std::shared_ptr QueryByStep(const std::string &sql, const std::vector &selectionArgs) override; + std::shared_ptr QueryByStep(const std::string &sql, std::vector &&args) override; std::shared_ptr Query( const AbsRdbPredicates &predicates, const std::vector columns) override; int Count(int64_t &outValue, const AbsRdbPredicates &predicates) override; diff --git a/relational_store/frameworks/native/rdb/mock/include/sqlite_connection.h b/relational_store/frameworks/native/rdb/mock/include/sqlite_connection.h index 284464f7f14c471bac77a915f20fa94668bb08af..9f2f368bf676f9153fe2a8fa32f89a5617b34869 100644 --- a/relational_store/frameworks/native/rdb/mock/include/sqlite_connection.h +++ b/relational_store/frameworks/native/rdb/mock/include/sqlite_connection.h @@ -45,6 +45,8 @@ public: const std::vector &bindArgs = std::vector()); std::shared_ptr BeginStepQuery(int &errCode, const std::string &sql, const std::vector &selectionArgs) const; + std::shared_ptr BeginStepQuery(int &errCode, const std::string &sql, + const std::vector &args) const; int DesFinalize(); int EndStepQuery(); void SetInTransaction(bool transaction); @@ -73,7 +75,8 @@ private: int SetBusyTimeout(int timeout); int RegDefaultFunctions(sqlite3 *dbHandle); static void MergeAssets(sqlite3_context *ctx, int argc, sqlite3_value **argv); - static void CompAssets(std::map &oldAssets, std::map &newAssets); + static void CompAssets(std::map &oldAssets, std::map &newAssets); static void MergeAsset(ValueObject::Asset &oldAsset, ValueObject::Asset &newAsset); int SetCustomFunctions(const RdbStoreConfig &config); int SetCustomScalarFunction(const std::string &functionName, int argc, ScalarFunction *function); diff --git a/relational_store/frameworks/native/rdb/mock/include/step_result_set.h b/relational_store/frameworks/native/rdb/mock/include/step_result_set.h index 1193712853aa35a100d29402c59605b4ebd7f06a..c7c4c2071efd7599179b63c1de24abec5df0f5f6 100644 --- a/relational_store/frameworks/native/rdb/mock/include/step_result_set.h +++ b/relational_store/frameworks/native/rdb/mock/include/step_result_set.h @@ -31,6 +31,8 @@ class StepResultSet : public AbsResultSet { public: StepResultSet(std::shared_ptr rdb, SqliteConnectionPool *connectionPool, const std::string &sql, const std::vector &selectionArgs); + StepResultSet(std::shared_ptr rdb, SqliteConnectionPool *pool, const std::string &sql, + std::vector &&args); ~StepResultSet() override; int GetAllColumnNames(std::vector &columnNames) override; @@ -66,6 +68,7 @@ private: SqliteConnectionPool *connectionPool_; std::string sql; std::vector selectionArgs; + std::vector args_; // Whether reach the end of this result set or not bool isAfterLast; // The value indicates the row count of the result set diff --git a/relational_store/frameworks/native/rdb/src/abs_shared_result_set.cpp b/relational_store/frameworks/native/rdb/src/abs_shared_result_set.cpp index 88568f6148705fc513f05b17073c553f44a63d86..3f96739f035861fd9f9562a4f2680fd7f13c99f5 100644 --- a/relational_store/frameworks/native/rdb/src/abs_shared_result_set.cpp +++ b/relational_store/frameworks/native/rdb/src/abs_shared_result_set.cpp @@ -173,22 +173,22 @@ int AbsSharedResultSet::GetBlob(int columnIndex, std::vector &value) } return E_OK; } else if (type == AppDataFwk::SharedBlock::CELL_UNIT_TYPE_INTEGER) { - LOG_ERROR("AbsSharedResultSet::GetDouble AppDataFwk::SharedBlock::CELL_UNIT_TYPE_INTEGER!"); + LOG_ERROR("AbsSharedResultSet::GetBlob AppDataFwk::SharedBlock::CELL_UNIT_TYPE_INTEGER!"); return E_OK; } else if (type == AppDataFwk::SharedBlock::CELL_UNIT_TYPE_NULL) { - LOG_ERROR("AbsSharedResultSet::GetDouble AppDataFwk::SharedBlock::CELL_UNIT_TYPE_NULL!"); + LOG_ERROR("AbsSharedResultSet::GetBlob AppDataFwk::SharedBlock::CELL_UNIT_TYPE_NULL!"); return E_OK; } else if (type == AppDataFwk::SharedBlock::CELL_UNIT_TYPE_FLOAT) { - LOG_ERROR("AbsSharedResultSet::GetDouble AppDataFwk::SharedBlock::CELL_UNIT_TYPE_FLOAT!"); + LOG_ERROR("AbsSharedResultSet::GetBlob AppDataFwk::SharedBlock::CELL_UNIT_TYPE_FLOAT!"); return E_OK; } else if (type == AppDataFwk::SharedBlock::CELL_UNIT_TYPE_ASSET) { - LOG_ERROR("AbsSharedResultSet::GetDouble AppDataFwk::SharedBlock::CELL_UNIT_TYPE_ASSET!"); - return E_OK; + LOG_ERROR("AbsSharedResultSet::GetBlob AppDataFwk::SharedBlock::CELL_UNIT_TYPE_ASSET!"); + return E_INVALID_OBJECT_TYPE; } else if (type == AppDataFwk::SharedBlock::CELL_UNIT_TYPE_ASSETS) { - LOG_ERROR("AbsSharedResultSet::GetDouble AppDataFwk::SharedBlock::CELL_UNIT_TYPE_ASSETS!"); - return E_OK; + LOG_ERROR("AbsSharedResultSet::GetBlob AppDataFwk::SharedBlock::CELL_UNIT_TYPE_ASSETS!"); + return E_INVALID_OBJECT_TYPE; } else { - LOG_ERROR("AbsSharedResultSet::GetDouble AppDataFwk::SharedBlock::nothing !"); + LOG_ERROR("AbsSharedResultSet::GetBlob AppDataFwk::SharedBlock::nothing !"); return E_INVALID_OBJECT_TYPE; } } @@ -230,9 +230,11 @@ int AbsSharedResultSet::GetString(int columnIndex, std::string &value) } else if (type == AppDataFwk::SharedBlock::CELL_UNIT_TYPE_BLOB) { return E_OK; } else if (type == AppDataFwk::SharedBlock::CELL_UNIT_TYPE_ASSET) { - return E_OK; + LOG_ERROR("AbsSharedResultSet::GetString AppDataFwk::SharedBlock::CELL_UNIT_TYPE_ASSET !"); + return E_INVALID_OBJECT_TYPE; } else if (type == AppDataFwk::SharedBlock::CELL_UNIT_TYPE_ASSETS) { - return E_OK; + LOG_ERROR("AbsSharedResultSet::GetString AppDataFwk::SharedBlock::CELL_UNIT_TYPE_ASSETS !"); + return E_INVALID_OBJECT_TYPE; } else { LOG_ERROR("AbsSharedResultSet::GetString is failed!"); return E_ERROR; @@ -288,11 +290,11 @@ int AbsSharedResultSet::GetLong(int columnIndex, int64_t &value) value = 0L; return E_OK; } else if (type == AppDataFwk::SharedBlock::CELL_UNIT_TYPE_ASSET) { - value = 0L; - return E_OK; + LOG_ERROR("AbsSharedResultSet::GetLong AppDataFwk::SharedBlock::CELL_UNIT_TYPE_ASSET !"); + return E_INVALID_OBJECT_TYPE; } else if (type == AppDataFwk::SharedBlock::CELL_UNIT_TYPE_ASSETS) { - value = 0L; - return E_OK; + LOG_ERROR("AbsSharedResultSet::GetLong AppDataFwk::SharedBlock::CELL_UNIT_TYPE_ASSETS !"); + return E_INVALID_OBJECT_TYPE; } else { LOG_ERROR("AbsSharedResultSet::GetLong Nothing !"); return E_INVALID_OBJECT_TYPE; @@ -333,12 +335,10 @@ int AbsSharedResultSet::GetDouble(int columnIndex, double &value) return E_OK; } else if (type == AppDataFwk::SharedBlock::CELL_UNIT_TYPE_ASSET) { LOG_ERROR("AbsSharedResultSet::GetDouble AppDataFwk::SharedBlock::CELL_UNIT_TYPE_ASSET!"); - value = 0.0; - return E_OK; + return E_INVALID_OBJECT_TYPE; } else if (type == AppDataFwk::SharedBlock::CELL_UNIT_TYPE_ASSETS) { LOG_ERROR("AbsSharedResultSet::GetDouble AppDataFwk::SharedBlock::CELL_UNIT_TYPE_ASSETS!"); - value = 0.0; - return E_OK; + return E_INVALID_OBJECT_TYPE; } else { LOG_ERROR("AbsSharedResultSet::GetDouble AppDataFwk::SharedBlock::nothing !"); value = 0.0; @@ -360,8 +360,14 @@ int AbsSharedResultSet::GetAsset(int32_t col, ValueObject::Asset &value) return E_ERROR; } + if (cellUnit->type == AppDataFwk::SharedBlock::CELL_UNIT_TYPE_NULL) { + LOG_ERROR("GetAsset the type of cell is null !"); + return E_NULL_OBJECT; + } + if (cellUnit->type != AppDataFwk::SharedBlock::CELL_UNIT_TYPE_ASSET) { - LOG_ERROR("GetAsset AppDataFwk::SharedBlock::nothing !"); + LOG_ERROR("GetAssets the type of cell is not assets, type is %{public}d, col is %{public}d!", cellUnit->type, + col); return E_INVALID_OBJECT_TYPE; } @@ -387,8 +393,14 @@ int AbsSharedResultSet::GetAssets(int32_t col, ValueObject::Assets &value) return E_ERROR; } + if (cellUnit->type == AppDataFwk::SharedBlock::CELL_UNIT_TYPE_NULL) { + LOG_ERROR("GetAssets the type of cell is null !"); + return E_NULL_OBJECT; + } + if (cellUnit->type != AppDataFwk::SharedBlock::CELL_UNIT_TYPE_ASSETS) { - LOG_ERROR("GetAssets AppDataFwk::SharedBlock::nothing !"); + LOG_ERROR("GetAssets the type of cell is not assets, type is %{public}d, col is %{public}d!", cellUnit->type, + col); return E_INVALID_OBJECT_TYPE; } 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 752fc71dd936141f3a7e22fee195dc804a91761b..563b218565054031e075c46334a7f3a3c2e1742d 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_manager_impl.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_manager_impl.cpp @@ -30,6 +30,7 @@ namespace OHOS::DistributedRdb { using namespace OHOS::Rdb; using RdbServiceProxy = DistributedRdb::RdbServiceProxy; using namespace OHOS::NativeRdb; +using namespace OHOS::DistributedRdb::RelationalStore; class DeathStub : public IRemoteBroker { public: @@ -188,7 +189,8 @@ sptr RdbStoreDataServiceProxy::GetFeatureInterface(const std::str MessageParcel reply; MessageOption mo { MessageOption::TF_SYNC }; - int32_t error = Remote()->SendRequest(GET_FEATURE_INTERFACE, data, reply, mo); + int32_t error = Remote()->SendRequest( + static_cast(KvStoreInterfaceCode::GET_FEATURE_INTERFACE), data, reply, mo); if (error != 0) { LOG_ERROR("SendRequest returned %{public}d", error); return nullptr; @@ -217,7 +219,8 @@ int32_t RdbStoreDataServiceProxy::RegisterDeathObserver(const std::string &bundl MessageParcel reply; MessageOption mo { MessageOption::TF_SYNC }; - int32_t error = Remote()->SendRequest(REGISTER_DEATH_OBSERVER, data, reply, mo); + int32_t error = Remote()->SendRequest( + static_cast(KvStoreInterfaceCode::REGISTER_DEATH_OBSERVER), data, reply, mo); if (error != 0) { LOG_ERROR("SendRequest returned %{public}d", error); return E_ERROR; diff --git a/relational_store/frameworks/native/rdb/src/rdb_notifier_stub.cpp b/relational_store/frameworks/native/rdb/src/rdb_notifier_stub.cpp index e5b79ed8e3685f54a5c2ea3ca42a11a9b059b167..c559c541760fcd5b2e5f5e21d5c5633eac873e51 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_notifier_stub.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_notifier_stub.cpp @@ -53,7 +53,7 @@ int RdbNotifierStub::OnRemoteRequest(uint32_t code, MessageParcel &data, Message return RDB_ERROR; } - if (code >= 0 && code < RDB_NOTIFIER_CMD_MAX) { + if (code >= 0 && code < static_cast(NotifierIFCode::RDB_NOTIFIER_CMD_MAX)) { return (this->*HANDLES[code])(data, reply); } 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 a89ae9aaf84b4e4258e1432357a15e0bcb88abec..6856f87d95c758e0c66c0041440970932ea1fe10 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_service_proxy.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_service_proxy.cpp @@ -22,6 +22,7 @@ namespace OHOS::DistributedRdb { using namespace OHOS::Rdb; using SqliteUtils = OHOS::NativeRdb::SqliteUtils; +using RdbServiceCode = OHOS::DistributedRdb::RelationalStore::RdbServiceInterfaceCode; #define IPC_SEND(code, reply, ...) \ ({ \ @@ -83,7 +84,7 @@ void RdbServiceProxy::OnDataChange(const Origin &origin, const PrimaryFields &pr std::string RdbServiceProxy::ObtainDistributedTableName(const std::string &device, const std::string &table) { MessageParcel reply; - int32_t status = IPC_SEND(RDB_SERVICE_CMD_OBTAIN_TABLE, reply, device, table); + int32_t status = IPC_SEND(static_cast(RdbServiceCode::RDB_SERVICE_CMD_OBTAIN_TABLE), reply, device, table); if (status != RDB_OK) { LOG_ERROR("status:%{public}d, device:%{public}.6s, table:%{public}s", status, SqliteUtils::Anonymous(device).c_str(), SqliteUtils::Anonymous(table).c_str()); @@ -118,7 +119,8 @@ int32_t RdbServiceProxy::InitNotifier(const RdbSyncerParam ¶m) int32_t RdbServiceProxy::InitNotifier(const RdbSyncerParam ¶m, sptr notifier) { MessageParcel reply; - int32_t status = IPC_SEND(RDB_SERVICE_CMD_INIT_NOTIFIER, reply, param, notifier); + int32_t status = IPC_SEND( + static_cast(RdbServiceCode::RDB_SERVICE_CMD_INIT_NOTIFIER), reply, param, notifier); if (status != RDB_OK) { LOG_ERROR("status:%{public}d, bundleName:%{public}s", status, param.bundleName_.c_str()); } @@ -140,7 +142,7 @@ std::pair RdbServiceProxy::DoSync(const RdbSyncerParam& param, std::pair result{RDB_ERROR, {}}; MessageParcel reply; auto &[status, details] = result; - status = IPC_SEND(RDB_SERVICE_CMD_SYNC, reply, param, option, predicates); + status = IPC_SEND(static_cast(RdbServiceCode::RDB_SERVICE_CMD_SYNC), reply, param, option, predicates); if (status != RDB_OK) { LOG_ERROR("status:%{public}d, bundleName:%{public}s, storeName:%{public}s", status, param.bundleName_.c_str(), SqliteUtils::Anonymous(param.storeName_).c_str()); @@ -174,7 +176,8 @@ int32_t RdbServiceProxy::DoSync(const RdbSyncerParam ¶m, const Option &optio int32_t RdbServiceProxy::DoAsync(const RdbSyncerParam ¶m, const Option &option, const PredicatesMemo &predicates) { MessageParcel reply; - int32_t status = IPC_SEND(RDB_SERVICE_CMD_ASYNC, reply, param, option, predicates); + int32_t status = IPC_SEND( + static_cast(RdbServiceCode::RDB_SERVICE_CMD_ASYNC), reply, param, option, predicates); if (status != RDB_OK) { LOG_ERROR("status:%{public}d, bundleName:%{public}s, storeName:%{public}s, seqNum:%{public}u", status, param.bundleName_.c_str(), SqliteUtils::Anonymous(param.storeName_).c_str(), option.seqNum); @@ -208,7 +211,8 @@ int32_t RdbServiceProxy::SetDistributedTables(const RdbSyncerParam& param, const int32_t type) { MessageParcel reply; - int32_t status = IPC_SEND(RDB_SERVICE_CMD_SET_DIST_TABLE, reply, param, tables, type); + int32_t status = IPC_SEND( + static_cast(RdbServiceCode::RDB_SERVICE_CMD_SET_DIST_TABLE), reply, param, tables, type); if (status != RDB_OK) { LOG_ERROR("status:%{public}d, bundleName:%{public}s, storeName:%{public}s, type:%{public}d", status, param.bundleName_.c_str(), SqliteUtils::Anonymous(param.storeName_).c_str(), type); @@ -264,7 +268,8 @@ int32_t RdbServiceProxy::Subscribe(const RdbSyncerParam ¶m, const SubscribeO int32_t RdbServiceProxy::DoSubscribe(const RdbSyncerParam ¶m, const SubscribeOption &option) { MessageParcel reply; - int32_t status = IPC_SEND(RDB_SERVICE_CMD_SUBSCRIBE, reply, param, option); + int32_t status = IPC_SEND( + static_cast(RdbServiceCode::RDB_SERVICE_CMD_SUBSCRIBE), reply, param, option); if (status != RDB_OK) { LOG_ERROR("status:%{public}d, bundleName:%{public}s, storeName:%{public}s", status, param.bundleName_.c_str(), SqliteUtils::Anonymous(param.storeName_).c_str()); @@ -290,7 +295,7 @@ int32_t RdbServiceProxy::UnSubscribe(const RdbSyncerParam ¶m, const Subscrib int32_t RdbServiceProxy::DoUnSubscribe(const RdbSyncerParam ¶m) { MessageParcel reply; - int32_t status = IPC_SEND(RDB_SERVICE_CMD_UNSUBSCRIBE, reply, param); + int32_t status = IPC_SEND(static_cast(RdbServiceCode::RDB_SERVICE_CMD_UNSUBSCRIBE), reply, param); if (status != RDB_OK) { LOG_ERROR("status:%{public}d, bundleName:%{public}s, storeName:%{public}s", status, param.bundleName_.c_str(), SqliteUtils::Anonymous(param.storeName_).c_str()); @@ -302,7 +307,8 @@ int32_t RdbServiceProxy::RemoteQuery(const RdbSyncerParam& param, const std::str const std::vector& selectionArgs, sptr& resultSet) { MessageParcel reply; - int32_t status = IPC_SEND(RDB_SERVICE_CMD_REMOTE_QUERY, reply, param, device, sql, selectionArgs); + int32_t status = IPC_SEND( + static_cast(RdbServiceCode::RDB_SERVICE_CMD_REMOTE_QUERY), reply, param, device, sql, selectionArgs); if (status != RDB_OK) { LOG_ERROR("status:%{public}d, bundleName:%{public}s, storeName:%{public}s, device:%{public}.6s", status, param.bundleName_.c_str(), SqliteUtils::Anonymous(param.storeName_).c_str(), device.c_str()); @@ -338,7 +344,7 @@ void RdbServiceProxy::ImportObservers(ObserverMap &observers) int32_t RdbServiceProxy::GetSchema(const RdbSyncerParam ¶m) { MessageParcel reply; - int32_t status = IPC_SEND(RDB_SERVICE_CMD_GET_SCHEMA, reply, param); + int32_t status = IPC_SEND(static_cast(RdbServiceCode::RDB_SERVICE_CMD_GET_SCHEMA), reply, param); if (status != RDB_OK) { LOG_ERROR("status:%{public}d, bundleName:%{public}s, storeName:%{public}s", status, param.bundleName_.c_str(), SqliteUtils::Anonymous(param.storeName_).c_str()); 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 b24e27694f434f0488b950d587a68bacc2a1ff1c..bf73df715da9d44d1b2ae9d393b70c53b4566a4d 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_store_impl.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_store_impl.cpp @@ -21,6 +21,7 @@ #include "logger.h" #include "rdb_errno.h" +#include "rdb_store.h" #include "rdb_trace.h" #include "rdb_sql_utils.h" #include "sqlite_global_config.h" @@ -36,6 +37,7 @@ #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM) #include "iresult_set.h" +#include "raw_data_parser.h" #include "rdb_device_manager_adapter.h" #include "rdb_manager_impl.h" #include "relational_store_manager.h" @@ -107,6 +109,102 @@ void RdbStoreImpl::GetSchema(const RdbStoreConfig &config) }); } } + +std::map RdbStoreImpl::GetModifyTime( + const std::string &table, const std::string &columnName, std::vector &keys) +{ + if (table.empty() || columnName.empty() || keys.empty()) { + LOG_ERROR("invalid para."); + return {}; + } + + auto logTable = DistributedDB::RelationalStoreManager::GetDistributedLogTableName(table); + if (columnName == "rowid") { + return GetModifyTimeByRowId(logTable, keys); + } + std::vector hashKeys; + hashKeys.reserve(keys.size()); + std::map, PRIKey> keyMap; + std::map tmp; + for (const auto &key : keys) { + DistributedDB::Type value; + RawDataParser::Convert(key, value); + tmp[columnName] = value; + auto hashKey = DistributedDB::RelationalStoreManager::CalcPrimaryKeyHash(tmp); + if (hashKey.empty()) { + LOG_DEBUG("hash key fail"); + continue; + } + hashKeys.emplace_back(ValueObject(hashKey)); + keyMap[hashKey] = key; + } + + std::string sql; + sql.append("select hash_key, timestamp/10000 from "); + sql.append(logTable); + sql.append(" where hash_key in ("); + sql.append(GetSqlArgs(hashKeys.size())); + sql.append(")"); + auto resultSet = QueryByStep(sql, std::move(hashKeys)); + int count = 0; + if (resultSet == nullptr || resultSet->GetRowCount(count) != E_OK || count <= 0) { + LOG_ERROR("get resultSet err."); + return {}; + } + std::map result; + for (int i = 0; i < count; i++) { + resultSet->GoToRow(i); + std::vector hashKey; + int64_t timeStamp; + resultSet->GetBlob(0, hashKey); + resultSet->GetLong(1, timeStamp); + result[keyMap[hashKey]] = Date(timeStamp); + } + return result; +} + +std::map RdbStoreImpl::GetModifyTimeByRowId( + const std::string &logTable, std::vector &keys) +{ + std::string sql; + sql.append("select data_key, timestamp/10000 from "); + sql.append(logTable); + sql.append(" where data_key in ("); + sql.append(GetSqlArgs(keys.size())); + sql.append(")"); + std::vector args; + args.reserve(keys.size()); + for (auto &key : keys) { + ValueObject::Type value; + RawDataParser::Convert(key, value); + args.emplace_back(ValueObject(value)); + } + auto resultSet = QueryByStep(sql, std::move(args)); + int count = 0; + if (resultSet == nullptr || resultSet->GetRowCount(count) != E_OK || count <= 0) { + LOG_ERROR("get resultSet err."); + return {}; + } + std::map result; + for (int i = 0; i < count; i++) { + resultSet->GoToRow(i); + int rowId; + int64_t timeStamp; + resultSet->GetInt(0, rowId); + resultSet->GetLong(1, timeStamp); + result[rowId] = Date(timeStamp); + } + return result; +} + +std::string RdbStoreImpl::GetSqlArgs(size_t size) +{ + std::string args((size << 1) - 1, '?'); + for (size_t i = 1; i < size; ++i) { + args[(i << 1) - 1] = ','; + } + return args; +} #endif RdbStoreImpl::RdbStoreImpl(const RdbStoreConfig &config, int &errCode) @@ -268,7 +366,8 @@ int RdbStoreImpl::InnerInsert(int64_t &outRowId, const std::string &table, for (auto &[key, val] : values.values_) { sql << split; sql << key; // columnName - if (val.GetType() == ValueObject::TYPE_ASSETS && conflictResolution == ConflictResolution::ON_CONFLICT_REPLACE) { + if (val.GetType() == ValueObject::TYPE_ASSETS && + conflictResolution == ConflictResolution::ON_CONFLICT_REPLACE) { return E_INVALID_ARGS; } if (val.GetType() == ValueObject::TYPE_ASSET || val.GetType() == ValueObject::TYPE_ASSETS) { @@ -608,6 +707,7 @@ int RdbStoreImpl::GetDataBasePath(const std::string &databasePath, std::string & if (ISFILE(databasePath)) { backupFilePath = ExtractFilePath(path) + databasePath; } else { + // 2 represents two characters starting from the len - 2 position if (!PathToRealPath(ExtractFilePath(databasePath), backupFilePath) || databasePath.back() == '/' || databasePath.substr(databasePath.length() - 2, 2) == "\\") { LOG_ERROR("Invalid databasePath."); @@ -1184,6 +1284,11 @@ std::shared_ptr RdbStoreImpl::QueryByStep(const std::string &sql, return std::make_shared(shared_from_this(), connectionPool, sql, selectionArgs); } +std::shared_ptr RdbStoreImpl::QueryByStep(const std::string &sql, std::vector &&args) +{ + return std::make_shared(shared_from_this(), connectionPool, sql, std::move(args)); +} + #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM) int RdbStoreImpl::SetDistributedTables(const std::vector &tables, int32_t type, const DistributedRdb::DistributedConfig &distributedConfig) 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 ec8ca65518ab8422063aad76886d8daae976a805..88ebca6aa527560af13f339c423e9f77596abe4e 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_types_util.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_types_util.cpp @@ -159,12 +159,11 @@ bool Unmarshalling(PrimaryKeys &output, MessageParcel &data) template<> bool Marshalling(const Origin &input, MessageParcel &data) { - return Marshal(data, input.origin, input.id, input.store); + return Marshal(data, input.origin, input.dataType, input.id, input.store); } - template<> bool Unmarshalling(Origin &output, MessageParcel &data) { - return Unmarshal(data, output.origin, output.id, output.store); + return Unmarshal(data, output.origin, output.dataType, output.id, output.store); } } diff --git a/relational_store/frameworks/native/rdb/src/sqlite_connection.cpp b/relational_store/frameworks/native/rdb/src/sqlite_connection.cpp index fbdec8079361c328fbb1b8f5b810150e0feaed5d..6f948b7bdb3093f74fdce8696f0fd6fc4f003560 100644 --- a/relational_store/frameworks/native/rdb/src/sqlite_connection.cpp +++ b/relational_store/frameworks/native/rdb/src/sqlite_connection.cpp @@ -374,6 +374,7 @@ int SqliteConnection::RegDefaultFunctions(sqlite3 *dbHandle) if (dbHandle == nullptr) { return SQLITE_OK; } + // The number of parameters is 2 return sqlite3_create_function_v2(dbHandle, "merge_assets", 2, SQLITE_UTF8 | SQLITE_DETERMINISTIC, nullptr, &MergeAssets, nullptr, nullptr, nullptr); } @@ -706,6 +707,20 @@ std::shared_ptr SqliteConnection::BeginStepQuery( return stepStatement; } +std::shared_ptr SqliteConnection::BeginStepQuery(int &errCode, const std::string &sql, + const std::vector &args) const +{ + errCode = stepStatement->Prepare(dbHandle, sql); + if (errCode != E_OK) { + return nullptr; + } + errCode = stepStatement->BindArguments(args); + if (errCode != E_OK) { + return nullptr; + } + return stepStatement; +} + int SqliteConnection::DesFinalize() { int errCode = 0; @@ -895,6 +910,7 @@ int SqliteConnection::LimitWalSize() void SqliteConnection::MergeAssets(sqlite3_context *ctx, int argc, sqlite3_value **argv) { LOG_DEBUG("merge assets begin"); + // 2 is the number of parameters if (ctx == nullptr || argc != 2 || argv == nullptr) { LOG_ERROR("Parameter does not meet restrictions."); return; @@ -919,12 +935,13 @@ void SqliteConnection::MergeAssets(sqlite3_context *ctx, int argc, sqlite3_value sqlite3_result_blob(ctx, blob.data(), blob.size(), SQLITE_TRANSIENT); } -void SqliteConnection::CompAssets(std::map &assets, std::map &newAssets) +void SqliteConnection::CompAssets(std::map &assets, std::map &newAssets) { using Status = ValueObject::Asset::Status; auto oldIt = assets.begin(); auto newIt = newAssets.begin(); - for (; oldIt != assets.end() && newIt != newAssets.end(); ) { + for (; oldIt != assets.end() && newIt != newAssets.end();) { if (oldIt->first == newIt->first) { if (newIt->second.status == Status::STATUS_DELETE) { oldIt->second.status = Status::STATUS_DELETE; @@ -969,7 +986,8 @@ void SqliteConnection::MergeAsset(ValueObject::Asset &oldAsset, ValueObject::Ass oldAsset.path = newAsset.path; oldAsset.status = Status ::STATUS_UPDATE; } - default:; + default: + return; } } } // namespace NativeRdb diff --git a/relational_store/frameworks/native/rdb/src/step_result_set.cpp b/relational_store/frameworks/native/rdb/src/step_result_set.cpp index bea159a0dc289794eee73c16eb4102a3dd2266d3..97cfff2033b07ac4c737b0eeb945c3039a33c56a 100644 --- a/relational_store/frameworks/native/rdb/src/step_result_set.cpp +++ b/relational_store/frameworks/native/rdb/src/step_result_set.cpp @@ -31,7 +31,17 @@ using namespace OHOS::Rdb; StepResultSet::StepResultSet(std::shared_ptr rdb, SqliteConnectionPool *connectionPool, const std::string &sql, const std::vector &selectionArgs) - : rdb(rdb), connectionPool_(connectionPool), sql(sql), selectionArgs(selectionArgs), isAfterLast(false), + : rdb(rdb), connectionPool_(connectionPool), sql(sql), isAfterLast(false), + rowCount(INIT_POS), sqliteStatement(nullptr), connection_(connectionPool_->AcquireConnection(true)) +{ + for (auto arg : selectionArgs) { + args_.push_back(ValueObject(std::move(arg))); + } +} + +StepResultSet::StepResultSet(std::shared_ptr rdb, SqliteConnectionPool *pool, + const std::string &sql, std::vector &&args) + : rdb(rdb), connectionPool_(pool), sql(sql), args_(std::move(args)), isAfterLast(false), rowCount(INIT_POS), sqliteStatement(nullptr), connection_(connectionPool_->AcquireConnection(true)) { } @@ -256,7 +266,7 @@ int StepResultSet::PrepareStep() } int errCode; - sqliteStatement = connection_->BeginStepQuery(errCode, sql, selectionArgs); + sqliteStatement = connection_->BeginStepQuery(errCode, sql, args_); if (sqliteStatement == nullptr) { connection_->EndStepQuery(); LOG_ERROR("BeginStepQuery ret is %{public}d", errCode); diff --git a/relational_store/interfaces/inner_api/appdatafwk/BUILD.gn b/relational_store/interfaces/inner_api/appdatafwk/BUILD.gn index df0cead5bfb5b7fff0642105f34cec3ff71e62c3..97b2755ac5217d1b5d8a822cd2e267d7eca1b64d 100644 --- a/relational_store/interfaces/inner_api/appdatafwk/BUILD.gn +++ b/relational_store/interfaces/inner_api/appdatafwk/BUILD.gn @@ -107,7 +107,7 @@ ohos_shared_library("native_appdatafwk") { external_deps = [ "c_utils:utils", - "hilog_native:libhilog", + "hilog:libhilog", "ipc:ipc_single", ] diff --git a/relational_store/interfaces/inner_api/dataability/BUILD.gn b/relational_store/interfaces/inner_api/dataability/BUILD.gn index c3768e761ab692b6a682b0cca9edbb39667ed934..510d7bc71f9b87c2db7f3f46bd8775f3fa877815 100644 --- a/relational_store/interfaces/inner_api/dataability/BUILD.gn +++ b/relational_store/interfaces/inner_api/dataability/BUILD.gn @@ -52,7 +52,7 @@ ohos_shared_library("native_dataability") { external_deps = [ "c_utils:utils", - "hilog_native:libhilog", + "hilog:libhilog", "ipc:ipc_single", ] diff --git a/relational_store/interfaces/inner_api/dataability/include/ishared_result_set.h b/relational_store/interfaces/inner_api/dataability/include/ishared_result_set.h index aaa80e1b04d2c23fdb3c390d074908f21a9436b0..23e3941c97b08308cef0acbbdee26ba7004b90ac 100644 --- a/relational_store/interfaces/inner_api/dataability/include/ishared_result_set.h +++ b/relational_store/interfaces/inner_api/dataability/include/ishared_result_set.h @@ -18,6 +18,7 @@ #include #include "iremote_broker.h" #include "abs_shared_result_set.h" +#include "distributeddata_relational_store_ipc_interface_code.h" namespace OHOS::NativeRdb { class API_EXPORT ISharedResultSet : public AbsSharedResultSet, public IRemoteBroker { public: @@ -25,38 +26,7 @@ public: API_EXPORT static std::shared_ptr ReadFromParcel(MessageParcel &parcel); API_EXPORT static sptr WriteToParcel( std::shared_ptr resultSet, MessageParcel &parcel); - -protected: - enum { - FUNC_GET_ROW_COUNT, - FUNC_GET_ALL_COLUMN_NAMES, - FUNC_ON_GO, - FUNC_CLOSE, - FUNC_GET_BLOB, - FUNC_GET_STRING, - FUNC_GET_INT, - FUNC_GET_LONG, - FUNC_GET_DOUBLE, - FUNC_IS_COLUMN_NULL, - FUNC_GO_TO, - FUNC_GO_TO_ROW, - FUNC_GO_TO_FISTR_ROW, - FUNC_GO_TO_LAST_ROW, - FUNC_GO_TO_NEXT_ROW, - FUNC_GO_TO_PREV_ROW, - FUNC_IS_AT_FIRST_ROW, - FUNC_IS_AT_LAST_ROW, - FUNC_IS_STARTED_ROW, - FUNC_IS_ENDED_ROW, - FUNC_IS_CLOSED, - FUNC_GET_COLUMN_COUNT, - FUNC_GET_COLUMN_INDEX, - FUNC_GET_COLUMN_NAME, - FUNC_GET_COLUMN_TYPE, - FUNC_GET_ROW_INDEX, - FUNC_BUTT - }; - + private: static std::function(MessageParcel &parcel)> consumerCreator_; static std::function(std::shared_ptr, MessageParcel &)> providerCreator_; diff --git a/relational_store/interfaces/inner_api/rdb/BUILD.gn b/relational_store/interfaces/inner_api/rdb/BUILD.gn index 42fab011ca12098a67c11b5f5321c09b9199143b..cae6ea396d882d64a7cfdf8c681770e559aee898 100644 --- a/relational_store/interfaces/inner_api/rdb/BUILD.gn +++ b/relational_store/interfaces/inner_api/rdb/BUILD.gn @@ -123,8 +123,8 @@ if (is_ohos) { external_deps = [ "c_utils:utils", "device_manager:devicemanagersdk", - "hilog_native:libhilog", - "hitrace_native:hitrace_meter", + "hilog:libhilog", + "hitrace:hitrace_meter", "huks:libhukssdk", "ipc:ipc_core", "samgr:samgr_proxy", @@ -172,8 +172,8 @@ if (is_ohos) { external_deps = [ "c_utils:utils", "device_manager:devicemanagersdk", - "hilog_native:libhilog", - "hitrace_native:hitrace_meter", + "hilog:libhilog", + "hitrace:hitrace_meter", "huks:libhukssdk", "ipc:ipc_core", "samgr:samgr_proxy", diff --git a/relational_store/interfaces/inner_api/rdb/include/distributeddata_relational_store_ipc_interface_code.h b/relational_store/interfaces/inner_api/rdb/include/distributeddata_relational_store_ipc_interface_code.h new file mode 100644 index 0000000000000000000000000000000000000000..69ca73e6d018107a8f35bd2a86325bcd86ad0732 --- /dev/null +++ b/relational_store/interfaces/inner_api/rdb/include/distributeddata_relational_store_ipc_interface_code.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* SAID:1301 */ +/* FeatureSystem: rdb_service */ +#ifndef DISTRIBUTEDDATA_RELATIONAL_STORE_IPC_INTERFACE_H +#define DISTRIBUTEDDATA_RELATIONAL_STORE_IPC_INTERFACE_H + +namespace OHOS::DistributedRdb { +namespace RelationalStore { +enum class IRdbNotifierInterfaceCode { + RDB_NOTIFIER_CMD_SYNC_COMPLETE = 0, + RDB_NOTIFIER_CMD_DATA_CHANGE, + RDB_NOTIFIER_CMD_MAX +}; + +enum class IResultSetInterfaceCode { + FUNC_GET_ROW_COUNT, + FUNC_GET_ALL_COLUMN_NAMES, + FUNC_ON_GO, + FUNC_CLOSE, + FUNC_GET_BLOB, + FUNC_GET_STRING, + FUNC_GET_INT, + FUNC_GET_LONG, + FUNC_GET_DOUBLE, + FUNC_IS_COLUMN_NULL, + FUNC_GO_TO, + FUNC_GO_TO_ROW, + FUNC_GO_TO_FISTR_ROW, + FUNC_GO_TO_LAST_ROW, + FUNC_GO_TO_NEXT_ROW, + FUNC_GO_TO_PREV_ROW, + FUNC_IS_AT_FIRST_ROW, + FUNC_IS_AT_LAST_ROW, + FUNC_IS_STARTED_ROW, + FUNC_IS_ENDED_ROW, + FUNC_IS_CLOSED, + FUNC_GET_COLUMN_COUNT, + FUNC_GET_COLUMN_INDEX, + FUNC_GET_COLUMN_NAME, + FUNC_GET_COLUMN_TYPE, + FUNC_GET_ROW_INDEX, + FUNC_BUTT, +}; + +enum class KvStoreInterfaceCode { + GET_FEATURE_INTERFACE = 0, + REGISTER_DEATH_OBSERVER, +}; + +enum class CloudKvStoreInterfaceCode { + GET_FEATURE_INTERFACE = 0 +}; + +enum class RdbServiceInterfaceCode { + RDB_SERVICE_CMD_OBTAIN_TABLE, + RDB_SERVICE_CMD_INIT_NOTIFIER, + RDB_SERVICE_CMD_SET_DIST_TABLE, + RDB_SERVICE_CMD_SYNC, + RDB_SERVICE_CMD_ASYNC, + RDB_SERVICE_CMD_SUBSCRIBE, + RDB_SERVICE_CMD_UNSUBSCRIBE, + RDB_SERVICE_CMD_REMOTE_QUERY, + RDB_SERVICE_CMD_GET_SCHEMA, + RDB_SERVICE_CMD_MAX +}; +} // namespace RelationalStore +} // namespace OHOS::DistributedRdb + +#endif // DISTRIBUTEDDATA_RELATIONAL_STORE_IPC_INTERFACE_H \ No newline at end of file diff --git a/relational_store/interfaces/inner_api/rdb/include/rdb_errno.h b/relational_store/interfaces/inner_api/rdb/include/rdb_errno.h index 19e5906443919065d10f726f92699625cfda2637..51aa2c500ed298645bb64818d624cfa41f8637ae 100644 --- a/relational_store/interfaces/inner_api/rdb/include/rdb_errno.h +++ b/relational_store/interfaces/inner_api/rdb/include/rdb_errno.h @@ -278,6 +278,11 @@ static constexpr int E_WAL_SIZE_OVER_LIMIT = (E_BASE + 47); * @brief The error when the connection count is used up. */ static constexpr int E_CON_OVER_LIMIT = (E_BASE + 48); + +/** +* @brief The error when the sharedblock unit is null. +*/ +static constexpr int E_NULL_OBJECT = (E_BASE + 49); } // namespace NativeRdb } // namespace OHOS diff --git a/relational_store/interfaces/inner_api/rdb/include/rdb_notifier.h b/relational_store/interfaces/inner_api/rdb/include/rdb_notifier.h index e61872a357b3f904695e3977c031b405db97a088..11d5e0b925e6e678b0bed8d38ec90689b3238980 100644 --- a/relational_store/interfaces/inner_api/rdb/include/rdb_notifier.h +++ b/relational_store/interfaces/inner_api/rdb/include/rdb_notifier.h @@ -16,16 +16,12 @@ #ifndef DISTRIBUTED_RDB_RDB_NOTIFIER_H #define DISTRIBUTED_RDB_RDB_NOTIFIER_H #include "rdb_types.h" +#include "distributeddata_relational_store_ipc_interface_code.h" namespace OHOS::DistributedRdb { class IRdbNotifier { public: using ChangeInfo = RdbStoreObserver::ChangeInfo; using PrimaryFields = std::map; - enum Code : int32_t { - RDB_NOTIFIER_CMD_SYNC_COMPLETE, - RDB_NOTIFIER_CMD_DATA_CHANGE, - RDB_NOTIFIER_CMD_MAX - }; virtual int32_t OnComplete(uint32_t seqNum, Details &&result) = 0; virtual int32_t OnChange(const Origin &origin, const PrimaryFields &primaries, ChangeInfo &&changeInfo) = 0; 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 b126c156ec77326edf530505ba00ee4975670945..891da413defe33a3eced7cc7b4f64381f54ea21b 100644 --- a/relational_store/interfaces/inner_api/rdb/include/rdb_service.h +++ b/relational_store/interfaces/inner_api/rdb/include/rdb_service.h @@ -21,6 +21,7 @@ #include "rdb_types.h" #include "rdb_notifier.h" +#include "distributeddata_relational_store_ipc_interface_code.h" namespace OHOS { template @@ -29,19 +30,6 @@ class IRemoteObject; namespace DistributedRdb { class RdbService { public: - enum { - RDB_SERVICE_CMD_OBTAIN_TABLE, - RDB_SERVICE_CMD_INIT_NOTIFIER, - RDB_SERVICE_CMD_SET_DIST_TABLE, - RDB_SERVICE_CMD_SYNC, - RDB_SERVICE_CMD_ASYNC, - RDB_SERVICE_CMD_SUBSCRIBE, - RDB_SERVICE_CMD_UNSUBSCRIBE, - RDB_SERVICE_CMD_REMOTE_QUERY, - RDB_SERVICE_CMD_GET_SCHEMA, - RDB_SERVICE_CMD_MAX - }; - struct Option { int32_t mode; uint32_t seqNum = 0; diff --git a/relational_store/interfaces/inner_api/rdb/include/rdb_store.h b/relational_store/interfaces/inner_api/rdb/include/rdb_store.h index b420aec9d3bffe682fd258e6fa679aa557533dfa..fe99849a3000e370720b5074f87a68cc65fdc911 100644 --- a/relational_store/interfaces/inner_api/rdb/include/rdb_store.h +++ b/relational_store/interfaces/inner_api/rdb/include/rdb_store.h @@ -69,6 +69,12 @@ public: * @brief Use RdbStoreObserver replace DistributedRdb::RdbStoreObserver namespace. */ using RdbStoreObserver = DistributedRdb::RdbStoreObserver; + using PRIKey = RdbStoreObserver::PrimaryKey; + + /** + * @brief Use Date replace DistributedRdb::Date namespace. + */ + using Date = DistributedRdb::Date; /** * @brief Destructor. @@ -413,6 +419,26 @@ public: * @param option Indicates the drop option. */ virtual bool DropDeviceData(const std::vector& devices, const DropOption& option) = 0; + + /** + * @brief Get the the specified column modify time. + * + * @param table Indicates the specified table. + * @param columnName Indicates the column. + * @param PRIKey Indicates the primary key. + * + * @return Returns the specified column modify time. + */ + virtual std::map GetModifyTime( + const std::string &table, const std::string &columnName, std::vector &keys) = 0; + + /** + * @brief Queries data in the database based on SQL statement. + * + * @param sql Indicates the SQL statement to execute. + * @param args Indicates the selection arguments. + */ + virtual std::shared_ptr QueryByStep(const std::string &sql, std::vector &&args) = 0; }; } // namespace OHOS::NativeRdb #endif 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 62e024893e2a7083c5f7fc47e1bab27568723cb1..44ecbdfe503387e3733f1400bfb578c1231bd572 100644 --- a/relational_store/interfaces/inner_api/rdb/include/rdb_types.h +++ b/relational_store/interfaces/inner_api/rdb/include/rdb_types.h @@ -82,10 +82,10 @@ enum Progress { }; struct Statistic { - int32_t total; - int32_t success; - int32_t failed; - int32_t untreated; + uint32_t total; + uint32_t success; + uint32_t failed; + uint32_t untreated; }; struct TableDetail { @@ -142,6 +142,16 @@ struct PredicatesMemo { std::vector operations_; }; +struct Date { + Date() {} + Date(int64_t date) : date(date) {} + operator double() const + { + return static_cast(date); + } + int64_t date; +}; + enum SubscribeMode { REMOTE, CLOUD, @@ -183,7 +193,7 @@ public: CHG_TYPE_DELETE, CHG_TYPE_BUTT }; - using PrimaryKey = std::variant; + using PrimaryKey = std::variant; using ChangeInfo = std::map[CHG_TYPE_BUTT]>; using PrimaryFields = std::map; virtual void OnChange(const std::vector &devices) = 0; // networkid diff --git a/relational_store/interfaces/inner_api/rdb/mock/include/rdb_store.h b/relational_store/interfaces/inner_api/rdb/mock/include/rdb_store.h index 37c7e30610b846785d9de4fb6fa3e7fd90c9fdbc..71d0bf32a43fc118d258a9a978deb39d6e739eaf 100644 --- a/relational_store/interfaces/inner_api/rdb/mock/include/rdb_store.h +++ b/relational_store/interfaces/inner_api/rdb/mock/include/rdb_store.h @@ -37,7 +37,8 @@ public: virtual int BatchInsert(int64_t &outInsertNum, const std::string &table, const std::vector &initialBatchValues) = 0; virtual int Replace(int64_t &outRowId, const std::string &table, const ValuesBucket &initialValues) = 0; - virtual int InsertWithConflictResolution(int64_t &outRowId, const std::string &table, const ValuesBucket &initialValues, + virtual int InsertWithConflictResolution( + int64_t &outRowId, const std::string &table, const ValuesBucket &initialValues, ConflictResolution conflictResolution = ConflictResolution::ON_CONFLICT_NONE) = 0; virtual int Update(int &changedRows, const std::string &table, const ValuesBucket &values, const std::string &whereClause = "", @@ -82,6 +83,7 @@ public: virtual bool IsReadOnly() const = 0; virtual bool IsMemoryRdb() const = 0; virtual int Restore(const std::string backupPath, const std::vector &newKey = std::vector()) = 0; + virtual std::shared_ptr QueryByStep(const std::string &sql, std::vector &&args) = 0; }; } // namespace OHOS::NativeRdb #endif diff --git a/relational_store/interfaces/inner_api/rdb_bms_adapter/BUILD.gn b/relational_store/interfaces/inner_api/rdb_bms_adapter/BUILD.gn index f3b822d134948290769f93e96747e0ecb3e35b85..93e2b904ee29bee6faec71861bdc58ffc24c4f6c 100644 --- a/relational_store/interfaces/inner_api/rdb_bms_adapter/BUILD.gn +++ b/relational_store/interfaces/inner_api/rdb_bms_adapter/BUILD.gn @@ -55,7 +55,7 @@ ohos_shared_library("rdb_bms_adapter") { "bundle_framework:appexecfwk_base", "bundle_framework:appexecfwk_core", "c_utils:utils", - "hilog_native:libhilog", + "hilog:libhilog", "resource_management:global_resmgr", ] diff --git a/relational_store/interfaces/inner_api/rdb_bms_adapter/include/data_properties.h b/relational_store/interfaces/inner_api/rdb_bms_adapter/include/data_properties.h index 6416a42ae21f7fa93528065ef6f8fbee598b5995..32eea4fad2376ba9b774fa46f68d0353502e021d 100644 --- a/relational_store/interfaces/inner_api/rdb_bms_adapter/include/data_properties.h +++ b/relational_store/interfaces/inner_api/rdb_bms_adapter/include/data_properties.h @@ -17,7 +17,6 @@ #define DATA_PROPERTIES_H #include "serializable.h" - namespace OHOS::RdbBMSAdapter { struct API_EXPORT DataProperties : public Serializable { virtual ~DataProperties() = default; diff --git a/relational_store/interfaces/inner_api/rdb_data_share_adapter/BUILD.gn b/relational_store/interfaces/inner_api/rdb_data_share_adapter/BUILD.gn index eed23df4d7b639dd8cf2fc1338c2db6321de004a..75849e9a882c01fc4a3207ae1163514c60dbfc6e 100644 --- a/relational_store/interfaces/inner_api/rdb_data_share_adapter/BUILD.gn +++ b/relational_store/interfaces/inner_api/rdb_data_share_adapter/BUILD.gn @@ -52,7 +52,7 @@ ohos_shared_library("rdb_data_share_adapter") { external_deps = [ "c_utils:utils", - "hilog_native:libhilog", + "hilog:libhilog", ] public_configs = [ ":rdb_data_share_adapter_public_config" ] diff --git a/relational_store/interfaces/ndk/BUILD.gn b/relational_store/interfaces/ndk/BUILD.gn index 9fa6476e584b0343ce3a092bd8e11bef9b0fb3c4..4326da78c248c63b9b922b1cc7173b65adf7503c 100644 --- a/relational_store/interfaces/ndk/BUILD.gn +++ b/relational_store/interfaces/ndk/BUILD.gn @@ -29,11 +29,18 @@ ohos_ndk_headers("native_rdb_ndk_header") { ohos_ndk_library("libnative_rdb_ndk") { output_name = "native_rdb_ndk" - output_extension = "so" - ndk_description_file = "./libnative_rdb.ndk.json" system_capability = "SystemCapability.DistributedDataManager.RelationalStore.Core" + ndk_description_file = "./libnative_rdb.ndk.json" min_compact_version = "10" + system_capability_headers = [ + "$ndk_headers_out_dir/database/rdb/oh_cursor.h", + "$ndk_headers_out_dir/database/rdb/oh_predicates.h", + "$ndk_headers_out_dir/database/rdb/oh_value_object.h", + "$ndk_headers_out_dir/database/rdb/oh_values_bucket.h", + "$ndk_headers_out_dir/database/rdb/relational_store.h", + "$ndk_headers_out_dir/database/rdb/relational_store_error_code.h", + ] } ohos_shared_library("native_rdb_ndk") { @@ -56,9 +63,10 @@ ohos_shared_library("native_rdb_ndk") { external_deps = [ "c_utils:utils", - "hilog_native:libhilog", + "hilog:libhilog", ] + relative_install_dir = "ndk" part_name = "relational_store" subsystem_name = "distributeddatamgr" } diff --git a/relational_store/test/js/clouddata/unittest/src/CloudSyncConfigCallback.js b/relational_store/test/js/clouddata/unittest/src/CloudSyncConfigCallback.js index 33e3653ea368bb7f47ff9153e8fe5b41186f178e..d3bcf18ccba514e836ea0cf925e9e62c7481cd32 100644 --- a/relational_store/test/js/clouddata/unittest/src/CloudSyncConfigCallback.js +++ b/relational_store/test/js/clouddata/unittest/src/CloudSyncConfigCallback.js @@ -17,7 +17,7 @@ import {describe, beforeAll, beforeEach, afterEach, afterAll, it, expect} from 'deccjsunit/index' import cloudData from '@ohos.data.cloudData'; -describe('CloudConfigTest', function () { +describe('CloudConfigCallbackTest', function () { /** * @tc.name EnabledCloudInvalidArgsCallbackTest * @tc.desc Test Js Api EnabledCloud with invalid args diff --git a/relational_store/test/js/clouddata/unittest/src/CloudSyncConfigPromise.js b/relational_store/test/js/clouddata/unittest/src/CloudSyncConfigPromise.js index 4e64a9e9cc2195080a7235d95802c8f353884214..8c9e034ac690a5fad047f7cfabe586a8505e8280 100644 --- a/relational_store/test/js/clouddata/unittest/src/CloudSyncConfigPromise.js +++ b/relational_store/test/js/clouddata/unittest/src/CloudSyncConfigPromise.js @@ -17,7 +17,7 @@ import {describe, beforeAll, beforeEach, afterEach, afterAll, it, expect} from 'deccjsunit/index' import cloudData from '@ohos.data.cloudData'; -describe('CloudConfigTest', function () { +describe('CloudConfigPromiseTest', function () { /** * @tc.name EnabledCloudInvalidArgsTest * @tc.desc Test Js Api EnabledCloud with invalid args diff --git a/relational_store/test/js/rdb/unittest/src/RdbstoreStoreExcuteSqlJsunit.test.js b/relational_store/test/js/rdb/unittest/src/RdbstoreStoreExcuteSqlJsunit.test.js index 09b9b0440b434faced2b71ac0ce5d155d93244dc..2fef3b4bfc72f919f9e1a3653b6a8d585357e85f 100644 --- a/relational_store/test/js/rdb/unittest/src/RdbstoreStoreExcuteSqlJsunit.test.js +++ b/relational_store/test/js/rdb/unittest/src/RdbstoreStoreExcuteSqlJsunit.test.js @@ -24,7 +24,7 @@ const STORE_CONFIG = { } var rdbStore = undefined; -describe('rdbStoreInsertTest', function () { +describe('rdbStoreExcuteSqlTest', function () { beforeAll(async function () { console.info(TAG + 'beforeAll') rdbStore = await dataRdb.getRdbStore(STORE_CONFIG, 1); diff --git a/relational_store/test/js/rdb/unittest/src/RdbstoreTransactionJsunit.test.js b/relational_store/test/js/rdb/unittest/src/RdbstoreTransactionJsunit.test.js index 3e4e4c8b69cd32aeb3b36df47c4ed7abd3f0eeaf..977d795ce7bb794b84b6daa4a8b602f64c5818a1 100644 --- a/relational_store/test/js/rdb/unittest/src/RdbstoreTransactionJsunit.test.js +++ b/relational_store/test/js/rdb/unittest/src/RdbstoreTransactionJsunit.test.js @@ -26,7 +26,7 @@ const STORE_CONFIG = { var rdbStore = undefined; -describe('rdbStoreInsertTest', function () { +describe('rdbStoreTransactionTest', function () { beforeAll(async function () { console.info(TAG + 'beforeAll') rdbStore = await dataRdb.getRdbStore(STORE_CONFIG, 1); diff --git a/relational_store/test/js/relationalstore/unittest/src/RdbStoreAssetResultSetJsunit.test.js b/relational_store/test/js/relationalstore/unittest/src/RdbStoreAssetResultSetJsunit.test.js index 1a12808b198e5b3825d2c173b375824edad2c67b..e30ef45ca668a21fc707cd7a344135f6c5e90c97 100644 --- a/relational_store/test/js/relationalstore/unittest/src/RdbStoreAssetResultSetJsunit.test.js +++ b/relational_store/test/js/relationalstore/unittest/src/RdbStoreAssetResultSetJsunit.test.js @@ -64,7 +64,7 @@ const asset4 = { } var rdbStore = undefined; -describe('rdbResultSetTest', function () { +describe('rdbAssetResultSetTest', function () { beforeAll(async function () { console.info(TAG + 'beforeAll') rdbStore = await data_relationalStore.getRdbStore(context, STORE_CONFIG); @@ -106,6 +106,7 @@ describe('rdbResultSetTest', function () { await rdbStore.insert("test", valuesBucket) valuesBucket = { "data1": asset1, + "data3": new Array(), } await rdbStore.insert("test", valuesBucket) console.log(TAG + "createTest data end"); @@ -213,16 +214,17 @@ describe('rdbResultSetTest', function () { expect(true).assertEqual(resultSet.goToNextRow()) const id = resultSet.getLong(resultSet.getColumnIndex("id")) const data2 = resultSet.getAsset(resultSet.getColumnIndex("data2")) - expect(null).assertFail(); - } catch (e) { - expect(e.code == 14800000).assertTrue() - } finally { + console.log(TAG + "id=" + id + ", data2=" + data2); + expect(data2).assertEqual(null); + resultSet.close(); expect(true).assertEqual(resultSet.isClosed) - resultSet = null - done(); - console.log(TAG + "************* testGetAsset0003 end *************"); + } catch (e) { + expect(null).assertFail(); } + resultSet = null + done(); + console.log(TAG + "************* testGetAsset0003 end *************"); }) /** @@ -511,16 +513,17 @@ describe('rdbResultSetTest', function () { expect(true).assertEqual(resultSet.goToNextRow()) const id = resultSet.getLong(resultSet.getColumnIndex("id")) const data3 = resultSet.getAssets(resultSet.getColumnIndex("data3")) - expect(null).assertFail(); - } catch (e) { - expect(e.code == 14800000).assertTrue() - } finally { + console.log(TAG + "id=" + id + ", data3=" + data3); + expect(data3.length).assertEqual(0); + resultSet.close(); expect(true).assertEqual(resultSet.isClosed) - resultSet = null - done(); - console.log(TAG + "************* testGetAsset0003 end *************"); + } catch (e) { + expect(null).assertFail(); } + resultSet = null + done(); + console.log(TAG + "************* testGetAssets0003 end *************"); }) /** diff --git a/relational_store/test/js/relationalstore/unittest/src/RdbstoreStoreExcuteSqlJsunit.test.js b/relational_store/test/js/relationalstore/unittest/src/RdbstoreStoreExcuteSqlJsunit.test.js index aa28d45e1d6ea18e77841c50dd0f26980ab2e1e2..45494e59240f6622c1fb41b2fb53b1ab842b84fb 100644 --- a/relational_store/test/js/relationalstore/unittest/src/RdbstoreStoreExcuteSqlJsunit.test.js +++ b/relational_store/test/js/relationalstore/unittest/src/RdbstoreStoreExcuteSqlJsunit.test.js @@ -27,7 +27,7 @@ const STORE_CONFIG = { } var rdbStore = undefined; -describe('rdbStoreInsertTest', function () { +describe('rdbStoreExcuteSqlTest', function () { beforeAll(async function () { console.info(TAG + 'beforeAll') rdbStore = await data_relationalStore.getRdbStore(context, STORE_CONFIG); diff --git a/relational_store/test/js/relationalstore/unittest/src/RdbstoreTransactionJsunit.test.js b/relational_store/test/js/relationalstore/unittest/src/RdbstoreTransactionJsunit.test.js index 96b97fc0b628f519d9014e4562661bb38d06f873..416448a27bfe5dde7e500940a41d87cf71b1829d 100644 --- a/relational_store/test/js/relationalstore/unittest/src/RdbstoreTransactionJsunit.test.js +++ b/relational_store/test/js/relationalstore/unittest/src/RdbstoreTransactionJsunit.test.js @@ -29,7 +29,7 @@ const STORE_CONFIG = { var rdbStore = undefined; -describe('rdbStoreInsertTest', function () { +describe('rdbStoreTransactionTest', function () { beforeAll(async function () { console.info(TAG + 'beforeAll') rdbStore = await data_relationalStore.getRdbStore(context, STORE_CONFIG); diff --git a/relational_store/test/js/relationalstore/unittest/src/RdbstoreUpdateJsunit.test.js b/relational_store/test/js/relationalstore/unittest/src/RdbstoreUpdateJsunit.test.js index 864ab835b860e8a6dc7c47c873b808775b1f8819..e76939e25ae9e044b979c25b93950725823766ba 100644 --- a/relational_store/test/js/relationalstore/unittest/src/RdbstoreUpdateJsunit.test.js +++ b/relational_store/test/js/relationalstore/unittest/src/RdbstoreUpdateJsunit.test.js @@ -778,7 +778,7 @@ describe('rdbStoreUpdateTest', function () { await predicates.equalTo("age", "19") let updatePromise = rdbStore.update(valueBucket, predicates, data_relationalStore.ConflictResolution.ON_CONFLICT_ROLLBACK); updatePromise.then(async (ret) => { - aexpect(null).assertFail(); + expect(null).assertFail(); await console.log(TAG + "update done: " + ret); }).catch((err) => { expect(null).assertFail(); diff --git a/relational_store/test/native/dataability/BUILD.gn b/relational_store/test/native/dataability/BUILD.gn index 7926c60326ca0f7cd2656a6cd281d7abb27999c4..77b788c236669dabe54941e4ab15618237c7f098 100644 --- a/relational_store/test/native/dataability/BUILD.gn +++ b/relational_store/test/native/dataability/BUILD.gn @@ -35,7 +35,7 @@ ohos_unittest("NativeDataAbilityTest") { external_deps = [ "c_utils:utils", - "hilog_native:libhilog", + "hilog:libhilog", "relational_store:native_dataability", "relational_store:native_rdb", ] diff --git a/relational_store/test/native/rdb/BUILD.gn b/relational_store/test/native/rdb/BUILD.gn index 9543b509a7239ee1483eda8ea9b0bd6638614f60..811f11d0d53e4e82558478504fbe1095e09248b8 100644 --- a/relational_store/test/native/rdb/BUILD.gn +++ b/relational_store/test/native/rdb/BUILD.gn @@ -72,7 +72,7 @@ ohos_unittest("NativeRdbTest") { external_deps = [ "c_utils:utils", - "hilog_native:libhilog", + "hilog:libhilog", "huks:libhukssdk", "ipc:ipc_core", ] diff --git a/relational_store/test/native/rdb/distributedtest/rdb_store_impl_test/BUILD.gn b/relational_store/test/native/rdb/distributedtest/rdb_store_impl_test/BUILD.gn index 1759e451a910208dba33964f547dcaa0048e718d..2c8c284dc7f548b4aa1f749709a96bd702831a2e 100644 --- a/relational_store/test/native/rdb/distributedtest/rdb_store_impl_test/BUILD.gn +++ b/relational_store/test/native/rdb/distributedtest/rdb_store_impl_test/BUILD.gn @@ -46,7 +46,7 @@ ohos_distributedtest("DistributedTest") { external_deps = [ "c_utils:utils", "device_manager:devicemanagersdk", - "hilog_native:libhilog", + "hilog:libhilog", "ipc:ipc_core", "relational_store:native_rdb", ] @@ -67,7 +67,7 @@ ohos_distributedtest("DistributedTestAgent") { external_deps = [ "c_utils:utils", "device_manager:devicemanagersdk", - "hilog_native:libhilog", + "hilog:libhilog", "ipc:ipc_core", "relational_store:native_rdb", ] diff --git a/relational_store/test/native/rdb/fuzztest/rdbimpl_fuzzer/BUILD.gn b/relational_store/test/native/rdb/fuzztest/rdbimpl_fuzzer/BUILD.gn index e806d5d166292a8676d1902dd8ff015006f0f7b2..ab97a101c695b54e0311973c5e250501294b4fb5 100644 --- a/relational_store/test/native/rdb/fuzztest/rdbimpl_fuzzer/BUILD.gn +++ b/relational_store/test/native/rdb/fuzztest/rdbimpl_fuzzer/BUILD.gn @@ -61,7 +61,7 @@ ohos_fuzztest("RdbImplFuzzTest") { external_deps = [ "c_utils:utils", - "hilog_native:libhilog", + "hilog:libhilog", "ipc:ipc_core", ] } diff --git a/relational_store/test/native/rdb/fuzztest/rdbstore_fuzzer/BUILD.gn b/relational_store/test/native/rdb/fuzztest/rdbstore_fuzzer/BUILD.gn index 0e2743a974e5727add8a26a0ef1e166773d2df51..bd277be08a5a692bce08b402b9b645cf880bf7f6 100644 --- a/relational_store/test/native/rdb/fuzztest/rdbstore_fuzzer/BUILD.gn +++ b/relational_store/test/native/rdb/fuzztest/rdbstore_fuzzer/BUILD.gn @@ -35,7 +35,7 @@ ohos_fuzztest("RdbStoreFuzzTest") { sources = [ "rdbstore_fuzzer.cpp" ] external_deps = [ - "hilog_native:libhilog", + "hilog:libhilog", "relational_store:native_rdb", ] } diff --git a/relational_store/test/native/rdb_data_ability_adapter/BUILD.gn b/relational_store/test/native/rdb_data_ability_adapter/BUILD.gn index df213be11310675dc1a16dfe6ee929b2ebe3468d..9b0ceb9d88a4b12095af7d591318d2d24992f650 100644 --- a/relational_store/test/native/rdb_data_ability_adapter/BUILD.gn +++ b/relational_store/test/native/rdb_data_ability_adapter/BUILD.gn @@ -37,7 +37,7 @@ ohos_unittest("NativeDataAbilityAdapterTest") { external_deps = [ "c_utils:utils", - "hilog_native:libhilog", + "hilog:libhilog", "relational_store:native_dataability", "relational_store:native_rdb", "relational_store:rdb_data_ability_adapter", diff --git a/relational_store/test/native/rdb_data_share_adapter/BUILD.gn b/relational_store/test/native/rdb_data_share_adapter/BUILD.gn index a9d8934f6e4c803717983f6406b357aabfb5ab21..68cacefd21827f43e1629779c4430c79637864b9 100644 --- a/relational_store/test/native/rdb_data_share_adapter/BUILD.gn +++ b/relational_store/test/native/rdb_data_share_adapter/BUILD.gn @@ -51,7 +51,7 @@ ohos_unittest("RdbDataShareAdapterTest") { external_deps = [ "c_utils:utils", - "hilog_native:libhilog", + "hilog:libhilog", "relational_store:native_rdb", "relational_store:rdb_data_share_adapter", ] diff --git a/relational_store/test/ndk/BUILD.gn b/relational_store/test/ndk/BUILD.gn index a2ac85a7c5adb1af09f3d613e602ad4d3e44b4f2..47d3a71eb97ad36484a684be62b65c8859744a45 100644 --- a/relational_store/test/ndk/BUILD.gn +++ b/relational_store/test/ndk/BUILD.gn @@ -24,6 +24,8 @@ config("module_private_config") { "${relational_store_innerapi_path}/rdb/include", "${relational_store_innerapi_path}/appdatafwk/include", "${relational_store_base_path}/interfaces/ndk/src", + "${relational_store_common_path}/include", + "${relational_store_native_path}/rdb/include", ] } @@ -31,6 +33,11 @@ ohos_unittest("NativeRdbNdkTest") { module_out_path = module_output_path sources = [ + "${relational_store_base_path}/interfaces/ndk/src/relational_cursor.cpp", + "${relational_store_base_path}/interfaces/ndk/src/relational_predicates.cpp", + "${relational_store_base_path}/interfaces/ndk/src/relational_store.cpp", + "${relational_store_base_path}/interfaces/ndk/src/relational_value_object.cpp", + "${relational_store_base_path}/interfaces/ndk/src/relational_values_bucket.cpp", "unittest/rdb_cursor_test.cpp", "unittest/rdb_predicates_test.cpp", "unittest/rdb_store_test.cpp", @@ -39,11 +46,14 @@ ohos_unittest("NativeRdbNdkTest") { configs = [ ":module_private_config" ] external_deps = [ - "hilog_native:libhilog", - "relational_store:native_rdb_ndk", + "c_utils:utils", + "hilog:libhilog", ] - deps = [ "//third_party/googletest:gtest_main" ] + deps = [ + "${relational_store_innerapi_path}/rdb:native_rdb", + "//third_party/googletest:gtest_main", + ] } ############################################################################### diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 3e66eac8884c3a604c9ffaff16f2ac767bb5fd52..c535ed67da97078577b786844435754d42553f33 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -37,7 +37,7 @@ aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/../preferences/test/native/unit #aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/../relational_store/test/native/dataability/unittest localTestSrc) #aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/../relational_store/test/native/rdb/unittest localTestSrc) #aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/../relational_store/test/native/rdb_data_share_adapter/unittest localTestSrc) -aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/../udmf/framework/innerkitsimpl/test/unittest remoteTestSrc) +#aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/../udmf/framework/innerkitsimpl/test/unittest remoteTestSrc) set(links secure mock relational_store data_share preferences jsoncpp crypto distributeddb data_object app adapter svcFwk kvdb service udmf) diff --git a/test/include/CMakeLists.txt b/test/include/CMakeLists.txt index 37066cd5a2d74091aa647ae8383db99ed696f27c..37e1580cbad09425e080404c75508e716e34a5d0 100644 --- a/test/include/CMakeLists.txt +++ b/test/include/CMakeLists.txt @@ -64,6 +64,7 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../data_share/interfaces/inner_a include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../data_share/interfaces/inner_api/provider/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../data_share/frameworks/native/common/include) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../udmf) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../udmf/framework/common) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../udmf/interfaces/innerkits/client) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../udmf/interfaces/innerkits/common) diff --git a/udmf b/udmf deleted file mode 160000 index 5edbfe95a814f28c6659b68d3267072e195cdc5c..0000000000000000000000000000000000000000 --- a/udmf +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 5edbfe95a814f28c6659b68d3267072e195cdc5c diff --git a/udmf/BUILD.gn b/udmf/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..8cc737b8aa63c5c8c23e582029495d609312c687 --- /dev/null +++ b/udmf/BUILD.gn @@ -0,0 +1,39 @@ +# Copyright (c) 2022-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. + +import("//build/ohos.gni") + +group("udmf_packages") { + if (is_standard_system) { + deps = [ + "interfaces/innerkits:udmf_client", + "interfaces/jskits:udmf_data_napi", + "interfaces/jskits:udmf_napi", + ] + } +} + +group("unittest") { + testonly = true + + deps = [ + "framework/innerkitsimpl/test/unittest:unittest", + "framework/jskitsimpl/unittest:unittest", + ] +} + +group("fuzztest") { + testonly = true + + deps = [ "framework/innerkitsimpl/test/fuzztest:fuzztest" ] +} diff --git a/udmf/CMakeLists.txt b/udmf/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..416e22bbfca5fc7fd97b94c99c433cf946753d4d --- /dev/null +++ b/udmf/CMakeLists.txt @@ -0,0 +1,42 @@ +cmake_minimum_required(VERSION 3.10.2) +project(udmf) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++1y -fno-rtti -fvisibility=default -D_GNU_SOURCE") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdata-sections -fPIC -fpic -ffunction-sections -D_GLIBC_MOCK") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wl,--no-as-needed -ldl") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wformat=0") + +set(MOCK_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../mock) +set(KV_STORE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../kv_store) +add_definitions(-DNAPI_EXPERIMENTAL) + +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/framework/common udmf_src) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/framework/innerkitsimpl/client udmf_src) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/framework/innerkitsimpl/common udmf_src) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/framework/innerkitsimpl/data udmf_src) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/framework/jskitsimpl/common udmf_src) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/framework/jskitsimpl/data udmf_src) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/framework/service udmf_src) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/interfaces/jskits/module udmf_src) + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/framework/common) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/framework/service) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/interfaces/innerkits/client) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/interfaces/innerkits/common) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/interfaces/innerkits/data) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/interfaces/jskits/common) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/interfaces/jskits/data) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../kv_store/common) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../kv_store/innerkitsimpl/distributeddatafwk/include) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../kv_store/innerkitsimpl/distributeddatafwk/src) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../kv_store/innerkits/distributeddata/include) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../utils_native/base/include) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../utils_native/safwk/native/include) + +include(${MOCK_DIR}/include/CMakeLists.txt OPTIONAL) +include(${KV_STORE_DIR}/interfaces/CMakeLists.txt OPTIONAL) + +set(links secure mock distributeddb kvdb) +add_library(udmf SHARED ${udmf_src}) +target_link_libraries(udmf ${links}) \ No newline at end of file diff --git a/udmf/CODEOWNERS b/udmf/CODEOWNERS new file mode 100644 index 0000000000000000000000000000000000000000..df88964efef9d3dce49f19b89c6619b634b1162b --- /dev/null +++ b/udmf/CODEOWNERS @@ -0,0 +1,15 @@ +# 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. + +# any change to framework/service/distributeddata_udmf_ipc_interface_code.h needs to be reviewed by @leonchan5 +framework/service/distributeddata_udmf_ipc_interface_code.h @leonchan5 \ No newline at end of file diff --git a/udmf/LICENSE b/udmf/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..4947287f7b5ccb5d1e8b7b2d3aa5d89f322c160d --- /dev/null +++ b/udmf/LICENSE @@ -0,0 +1,177 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS \ No newline at end of file diff --git a/udmf/OAT.xml b/udmf/OAT.xml new file mode 100644 index 0000000000000000000000000000000000000000..118a8533ff0f1296413581bf08936f2d13f5210b --- /dev/null +++ b/udmf/OAT.xml @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + diff --git a/udmf/README_zh.md b/udmf/README_zh.md new file mode 100644 index 0000000000000000000000000000000000000000..4b8036d809aaccf5373aa020bdfc704bc0b2c646 --- /dev/null +++ b/udmf/README_zh.md @@ -0,0 +1,106 @@ +# 统一数据管理框架 + +## 简介 +从数据管理角度出发,随着OpenHarmony中数据跨应用、跨设备流转场景和需求的不断增加,流转过程中会存在数据协同通道繁杂、数据协同标准不一致、数据协同安全策略不一致、应用适配复杂度高、开发工作量增多等诸多痛点问题。统一数据管理框架(Unified Data Management Framework, UDMF)旨在定义数据跨应用、跨设备以及跨平台过程中的各项标准,提供统一的OpenHarmony数据语言和标准化的数据接入与读取通路。 + +## 架构介绍 +UDMF提供统一的OpenHarmony数据语言和标准化的数据接入与读取通路。 + +**统一的OpenHarmony数据语言:** 构建OpenHarmony数据跨应用、跨设备交互的标准定义,降低应用/业务数据交互成本,促进数据生态建设。 + +**标准化的数据接入与读取通路:** 提供安全、标准化的数据通路,降低业务跨应用、跨设备数据交互的成本。 + +UDMF的整体架构如图1所示,业务层对外提供标准化的数据定义和数据接入与读取的业务接口。统一数据管理框架层提供标准化数据定义和数据接入与读取的具体实现,同时负责管理数据的生命周期、安全性、权限和存储。存储模块层负责数据的具体保存,可以使用分布式KVDB、分布式数据对象和分布式RDB进行数据存储。 + +**图1** UDMF架构图 + +![架构图](figures/udmf_architecture.png) + +### 标准化数据定义 + +UDMF提供了标准化的数据定义,统一定义了以下几种不同的数据类型。 + +**基础数据类型:** File、Text等,能够进行跨应用、跨设备以及跨平台流转。File、Text数据类型可见图2和图3,它们具有继承关系和层次结构,衍生出多种具体子类。 + +**图2** UDMF File数据类型示意图 + +![架构图](figures/udmf_type_File.png) + +**图3** UDMF Text数据类型示意图 + +![架构图](figures/udmf_type_Text.png) + +**系统相关数据类型(System Defined Type, SDT):** 与具体的平台/操作系统绑定,如Form(UI卡片信息)、AppItem(App描述信息)、PixelMap(缩略图格式)等,该类数据可以实现系统/平台内的跨应用、跨设备流转,如图4所示。 + +**图4** UDMF SDT数据类型示意图 + +![架构图](figures/udmf_type_SDT.png) + +**应用自定义数据类型(App Defined Type, ADT):** 单个应用自定义的数据,该类数据可以实现应用内的跨平台与跨设备流转,如图5所示为例,应用可自定义MyFile类型文件格式在应用生态内部使用。 + +**图5** UDMF ADT数据类型示意图 + +![架构图](figures/udmf_type_ADT.png) + +### 标准化数据通路 + +UDMF定义了标准化的数据接入与读取通路,为各种业务场景(如跨应用跨设备数据拖拽)提供了跨应用、跨设备的数据接入与读取通路,通路中的数据URI定义为udmf://intension/bundleName/groupName/guid,其中各组成部分的含义分别为: +**udmf:** 协议名,表示使用UDMF提供的数据通路。 +**intension:** 通道分类,对应不同的业务场景(如数据拖拽)。 +**bundleName:** 数据来源应用的包名称。 +**groupName:** 分组名称,支持批量数据分组管理。 +**guid:** 系统生成的数据id,全局唯一。 + +## 约束限制 + +- UDMF中每条数据记录大小不超过2MB。 +- UDMF支持批量数据记录的分组管理,每个分组整体大小不超过4MB。 + +## 目录 + +UDMF代码仓的目录结构和对应目录的功能描述如下: + +```undefined +foundation/distributeddatamgr/udmf # udmf统一数据管理部件 +├── frameworks # udmf的核心逻辑 +│ ├── common # 公共工具 +│ ├── innerkitsimpl # nativie接口具体实现 +│ │ ├── client # native客户端 +│ │ ├── common # native接口公共工具类 +│ │ ├── data # 数据结构定义 +│ │ └── test # 测试目录 +│ ├── jskitsimpl # js接口具体实现 +│ │ ├── common # js接口公共工具类 +│ │ |── data # 统一数据公共接口实现 +| | └── unittest # js单元测试目录 +│ ├── manager # 数据管理核心类 +| | ├── lifecycle # 生命周期管理 +| | ├── permission # 权限管理 +│ │ ├── preprocess # 预处理 +│ │ └── store # 存储策略 +│ └── service # 服务模块 +├── interfaces # udmf对外接口声明 +│ ├── innerkits # nativie接口声明 +│ │ ├── client # client接口声明 +│ │ ├── common # 公共工具类声明 +│ │ └── data # 数据结构声明 +│ └── jskits # napi接口声明 +│ ├── common # napi工具类声明 +│ ├── data # napi数据封装声明 +│ └── module # 统一数据模块注册 +├── service # udmf服务框架代码 +│ ├── include # 服务端声明 +│ ├── src # 服务端具体实现 +| └── test # 测试目录 +├── BUILD.gn # 编译配置文件 +├── bundle.json # 模块配置文件 +├── LICENSE # License文件 +├── OAT.xml # OAT扫描策略 +├── README_zh.md # Readme中文介绍 +└── udmf.gni # 编译配置头文件 +``` +## 相关仓 + +- [分布式数据管理子系统](https://gitee.com/openharmony/docs/blob/master/zh-cn/readme/%E5%88%86%E5%B8%83%E5%BC%8F%E6%95%B0%E6%8D%AE%E7%AE%A1%E7%90%86%E5%AD%90%E7%B3%BB%E7%BB%9F.md) + +- [**distributeddatamgr\_kv_store**](https://gitee.com/openharmony/distributeddatamgr_kv_store/blob/master/README_zh.md) \ No newline at end of file diff --git a/udmf/bundle.json b/udmf/bundle.json new file mode 100644 index 0000000000000000000000000000000000000000..6e27f3c85ca9cdc5f87c46f7560193926dda4ca7 --- /dev/null +++ b/udmf/bundle.json @@ -0,0 +1,121 @@ +{ + "name": "@ohos/udmf", + "description": "Provide unified data management service for 3rd party app", + "version": "4.0", + "license": "Apache License 2.0", + "publishAs": "code-segment", + "segment": { + "destPath": "foundation/distributeddatamgr/udmf" + }, + "dirs": {}, + "scripts": {}, + "component": { + "name": "udmf", + "subsystem": "distributeddatamgr", + "syscap": [ + "SystemCapability.DistributedDataManager.UDMF.Core" + ], + "features": [ + ], + "adapted_system_type": [ + "standard" + ], + "rom": "1000KB", + "ram": "636KB", + "deps": { + "components": [ + "ability_base", + "ability_runtime", + "access_token", + "bundle_framework", + "c_utils", + "hilog", + "hitrace", + "ipc", + "kv_store", + "napi", + "samgr" + ], + "third_party": [ + "bounds_checking_function", + "googletest" + ] + }, + "build": { + "sub_component": [ + "//foundation/distributeddatamgr/udmf:udmf_packages" + ], + "inner_kits": [ + { + "name": "//foundation/distributeddatamgr/udmf/interfaces/innerkits:udmf_client", + "header": { + "header_files": [ + "udmf_client.h" + ], + "header_base":"//foundation/distributeddatamgr/udmf/interfaces/innerkits/client" + } + }, + { + "name": "//foundation/distributeddatamgr/udmf/interfaces/innerkits:udmf_client", + "header": { + "header_files": [ + "error_code.h", + "unified_key.h", + "unified_meta.h", + "unified_types.h", + "visibility.h" + ], + "header_base":"//foundation/distributeddatamgr/udmf/interfaces/innerkits/common" + } + }, + { + "name": "//foundation/distributeddatamgr/udmf/interfaces/innerkits:udmf_client", + "header": { + "header_files": [ + "application_defined_record.h", + "audio.h", + "file.h", + "folder.h", + "html.h", + "image.h", + "link.h", + "plain_text.h", + "system_defined_appitem.h", + "system_defined_form.h", + "system_defined_pixelmap.h", + "system_defined_record.h", + "text.h", + "unified_data.h", + "unified_record.h", + "video.h" + ], + "header_base":"//foundation/distributeddatamgr/udmf/interfaces/innerkits/data" + } + }, + { + "name": "//foundation/distributeddatamgr/udmf/interfaces/jskits:udmf_data_napi", + "header": { + "header_files": [ + "unified_data_napi.h", + "summary_napi.h" + ], + "header_base":"//foundation/distributeddatamgr/udmf/interfaces/jskits/data" + } + }, + { + "name": "//foundation/distributeddatamgr/udmf/interfaces/jskits:udmf_data_napi", + "header": { + "header_files": [ + "napi_queue.h" + ], + "header_base":"//foundation/distributeddatamgr/udmf/interfaces/jskits/common" + } + } + ], + "test": [ + "//foundation/distributeddatamgr/udmf:unittest", + "//foundation/distributeddatamgr/udmf:fuzztest" + ] + } + } +} diff --git a/udmf/figures/udmf_architecture.png b/udmf/figures/udmf_architecture.png new file mode 100644 index 0000000000000000000000000000000000000000..78281a43dc5debb18f4fec9aee9b1f6816fca429 Binary files /dev/null and b/udmf/figures/udmf_architecture.png differ diff --git a/udmf/figures/udmf_type_ADT.png b/udmf/figures/udmf_type_ADT.png new file mode 100644 index 0000000000000000000000000000000000000000..2eb1e7b94080b6d611b1ed7abaceda31b04442e7 Binary files /dev/null and b/udmf/figures/udmf_type_ADT.png differ diff --git a/udmf/figures/udmf_type_File.png b/udmf/figures/udmf_type_File.png new file mode 100644 index 0000000000000000000000000000000000000000..80bbec073de7e4e75da239a8a073453545260cc1 Binary files /dev/null and b/udmf/figures/udmf_type_File.png differ diff --git a/udmf/figures/udmf_type_SDT.png b/udmf/figures/udmf_type_SDT.png new file mode 100644 index 0000000000000000000000000000000000000000..026ce5bd7ae68f4dbabdcf5bac63e721454e17f5 Binary files /dev/null and b/udmf/figures/udmf_type_SDT.png differ diff --git a/udmf/figures/udmf_type_Text.png b/udmf/figures/udmf_type_Text.png new file mode 100644 index 0000000000000000000000000000000000000000..d12a2390dce2d08417e7024d15ee431dde66756b Binary files /dev/null and b/udmf/figures/udmf_type_Text.png differ diff --git a/udmf/framework/common/endian_converter.h b/udmf/framework/common/endian_converter.h new file mode 100644 index 0000000000000000000000000000000000000000..5101b9d921ae257657d587b453fa586f3bf18896 --- /dev/null +++ b/udmf/framework/common/endian_converter.h @@ -0,0 +1,123 @@ +/* +* 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 UDMF_ENDIAN_CONVERTER_H +#define UDMF_ENDIAN_CONVERTER_H + +#include +#include + +namespace OHOS { +namespace UDMF { +static inline int8_t HostToNet(int8_t value) +{ + return value; +} +static inline int16_t HostToNet(int16_t value) +{ + return htole16(value); +} + +static inline int16_t NetToHost(int16_t value) +{ + return le16toh(value); +} + +static inline int32_t HostToNet(int32_t value) +{ + return htole32(value); +} + +static inline int8_t NetToHost(int8_t value) +{ + return le32toh(value); +} + +static inline int32_t NetToHost(int32_t value) +{ + return le32toh(value); +} + +static inline int64_t HostToNet(int64_t value) +{ + return htole64(value); +} + +static inline int64_t NetToHost(int64_t value) +{ + return le64toh(value); +} + +static inline uint8_t HostToNet(uint8_t value) +{ + return value; +} +static inline uint16_t HostToNet(uint16_t value) +{ + return htole16(value); +} + +static inline uint16_t NetToHost(uint16_t value) +{ + return le16toh(value); +} + +static inline uint32_t HostToNet(uint32_t value) +{ + return htole32(value); +} + +static inline uint8_t NetToHost(uint8_t value) +{ + return le32toh(value); +} + +static inline uint32_t NetToHost(uint32_t value) +{ + return le32toh(value); +} + +static inline uint64_t HostToNet(uint64_t value) +{ + return htole64(value); +} + +static inline uint64_t NetToHost(uint64_t value) +{ + return le64toh(value); +} + +static inline float HostToNet(float value) +{ + return htole32(*reinterpret_cast(&value)); +} + +static inline float NetToHost(float value) +{ + return le32toh(*reinterpret_cast(&value)); +} + +static inline double HostToNet(double value) +{ + return htole64(*reinterpret_cast(&value)); +} + +static inline double NetToHost(double value) +{ + return le64toh(*reinterpret_cast(&value)); +} +} // namespace UDMF +} // namespace OHOS +#endif // UDMF_ENDIAN_CONVERTER_H diff --git a/udmf/framework/common/logger.h b/udmf/framework/common/logger.h new file mode 100644 index 0000000000000000000000000000000000000000..370b3834a598295040732dd960797a093f53e395 --- /dev/null +++ b/udmf/framework/common/logger.h @@ -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. + */ + +#ifndef UDMF_LOGGER_H +#define UDMF_LOGGER_H +#include + +#include "hilog/log.h" + +namespace OHOS { +namespace UDMF { +// param of log interface, such as UDMF_LABEL. +enum UdmfSubModule { + UDMF_FRAMEWORK = 0, // for framework core module + UDMF_KITS_INNER, // for udmf innerkits module + UDMF_KITS_NAPI, // for udmf napi kits module + UDMF_CLIENT, // for udmf client module + UDMF_SERVICE, // for udmf service module + UDMF_TEST, // for udmf test module +}; + +// 0xD001600: subsystem:distributeddatamgr module:udmf, 8 bits reserved. +static inline OHOS::HiviewDFX::HiLogLabel LogLabel() +{ + return { LOG_CORE, 0xD001656, "UDMF" }; +} + +// In order to improve performance, do not check the module range. +// Besides, make sure module is less than UDMF_SERVICE. +#define LOG_FATAL(module, fmt, ...) \ + do { \ + using HiLog = OHOS::HiviewDFX::HiLog; \ + auto lable = LogLabel(); \ + if (!HiLogIsLoggable(lable.domain, lable.tag, LogLevel::LOG_FATAL)) { \ + break; \ + } \ + HiLog::Fatal(lable, "%{public}d: %{public}s " fmt " ", __LINE__, __FUNCTION__, ##__VA_ARGS__); \ + } while (0) + +#define LOG_ERROR(module, fmt, ...) \ + do { \ + using HiLog = OHOS::HiviewDFX::HiLog; \ + auto lable = LogLabel(); \ + if (!HiLogIsLoggable(lable.domain, lable.tag, LogLevel::LOG_ERROR)) { \ + break; \ + } \ + HiLog::Error(lable, "%{public}d: %{public}s " fmt " ", __LINE__, __FUNCTION__, ##__VA_ARGS__); \ + } while (0) + +#define LOG_WARN(module, fmt, ...) \ + do { \ + using HiLog = OHOS::HiviewDFX::HiLog; \ + auto lable = LogLabel(); \ + if (!HiLogIsLoggable(lable.domain, lable.tag, LogLevel::LOG_WARN)) { \ + break; \ + } \ + HiLog::Warn(lable, "%{public}d: %{public}s " fmt " ", __LINE__, __FUNCTION__, ##__VA_ARGS__); \ + } while (0) + +#define LOG_INFO(module, fmt, ...) \ + do { \ + using HiLog = OHOS::HiviewDFX::HiLog; \ + auto lable = LogLabel(); \ + if (!HiLogIsLoggable(lable.domain, lable.tag, LogLevel::LOG_INFO)) { \ + break; \ + } \ + HiLog::Info(lable, "%{public}d: %{public}s " fmt " ", __LINE__, __FUNCTION__, ##__VA_ARGS__); \ + } while (0) + +#define LOG_DEBUG(module, fmt, ...) \ + do { \ + using HiLog = OHOS::HiviewDFX::HiLog; \ + auto lable = LogLabel(); \ + if (!HiLogIsLoggable(lable.domain, lable.tag, LogLevel::LOG_DEBUG)) { \ + break; \ + } \ + HiLog::Debug(lable, "%{public}d: %{public}s " fmt " ", __LINE__, __FUNCTION__, ##__VA_ARGS__); \ + } while (0) +} // namespace UDMF +} // namespace OHOS +#endif // UDMF_LOGGER_H diff --git a/udmf/framework/common/tlv_object.h b/udmf/framework/common/tlv_object.h new file mode 100644 index 0000000000000000000000000000000000000000..cca092be1c00b7798db417a5510981257dc63935 --- /dev/null +++ b/udmf/framework/common/tlv_object.h @@ -0,0 +1,478 @@ +/* + * 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 UDMF_TLV_OBJECT_H +#define UDMF_TLV_OBJECT_H + +#include "securec.h" +#include "error_code.h" +#include "unified_meta.h" +#include "unified_types.h" +#include "endian_converter.h" + +namespace OHOS { +namespace UDMF { +enum TAG : uint16_t { + TAG_INT32 = 0x0000, + TAG_INT64, + TAG_UINT32, + TAG_UINT64, + TAG_BOOL, + TAG_DOUBLE, + TAG_STRING, + TAG_VECTOR, + TAG_MAP, + TAG_BUTT, +}; + +#pragma pack(1) +struct TLVHead { + uint16_t tag; + uint32_t len; + std::uint8_t value[0]; +}; +#pragma pack() + +class TLVObject { +public: + TLVObject() = default; + ~TLVObject() = default; + explicit TLVObject(std::vector &buffer) + { + total_ += buffer.size(); + buffer_ = &buffer; + cursor_ = 0; + } + + void UpdateSize() + { + buffer_->resize(total_); + } + + std::vector GetBuffer() + { + return *buffer_; + } + + void Count(const uint32_t value) + { + total_ += sizeof(value) + sizeof(TLVHead); + } + + void Count(const uint64_t value) + { + total_ += sizeof(value) + sizeof(TLVHead); + } + + void Count(const int32_t value) + { + total_ += sizeof(value) + sizeof(TLVHead); + } + + void Count(const int64_t value) + { + total_ += sizeof(value) + sizeof(TLVHead); + } + + void Count(const float value) + { + total_ += sizeof(value) + sizeof(TLVHead); + } + + void Count(const double value) + { + total_ += sizeof(value) + sizeof(TLVHead); + } + + void Count(const std::string &value) + { + total_ += value.size() + sizeof(TLVHead); + } + + void Count(const std::vector &value) + { + std::size_t expectSize = sizeof(TLVHead); + expectSize += value.size(); + total_ += expectSize; + } + + void Count(const UDVariant &value) + { + total_ += sizeof(TLVHead); + auto int32Value = std::get_if(&value); + if (int32Value != nullptr) { + Count(std::get(value)); + return; + } + auto int64Value = std::get_if(&value); + if (int64Value != nullptr) { + Count(std::get(value)); + return; + } + auto boolValue = std::get_if(&value); + if (boolValue != nullptr) { + Count(std::get(value)); + return; + } + auto doubleValue = std::get_if(&value); + if (doubleValue != nullptr) { + Count(std::get(value)); + return; + } + auto strValue = std::get_if(&value); + if (strValue != nullptr) { + Count(std::get(value)); + return; + } + auto vecValue = std::get_if>(&value); + if (vecValue != nullptr) { + Count(std::get>(value)); + return; + } + total_ += sizeof(TLVHead); + } + + void Count(const UDDetails &value) + { + for (auto &item : value) { + Count(item.first); + Count(item.second); + } + total_ += sizeof(TLVHead); + } + + void Count(const UnifiedKey &value) + { + Count(value.key); + Count(value.intention); + Count(value.bundleName); + Count(value.groupId); + } + + void Count(const Privilege &value) + { + Count(value.tokenId); + Count(value.readPermission); + Count(value.writePermission); + } + + template + bool WriteBasic(uint16_t type, const T &value) + { + if (!HasExpectBuffer(sizeof(TLVHead) + sizeof(value))) { + return false; + } + auto *tlvHead = reinterpret_cast(buffer_->data() + cursor_); + tlvHead->tag = HostToNet(type); + tlvHead->len = HostToNet((uint32_t)sizeof(value)); + auto valueBuff = HostToNet(value); + auto ret = memcpy_s(tlvHead->value, sizeof(value), &valueBuff, sizeof(value)); + if (ret != EOK) { + return false; + } + cursor_ += sizeof(TLVHead) + sizeof(value); + return true; + } + + template + bool ReadBasic(T &value) + { + TLVHead head {}; + if (!ReadHead(head)) { + return false; + } + if (head.len == 0) { + return false; + } + if (!HasExpectBuffer(head.len)) { + return false; + } + auto ret = memcpy_s(&value, sizeof(T), buffer_->data() + cursor_, sizeof(T)); + if (ret != EOK) { + return false; + } + value = NetToHost(value); + cursor_ += sizeof(T); + return true; + } + + bool WriteString(const std::string &value) + { + if (!HasExpectBuffer(sizeof(TLVHead) + value.size())) { + return false; + } + auto *tlvHead = reinterpret_cast(buffer_->data() + cursor_); + tlvHead->tag = HostToNet(TAG_STRING); + tlvHead->len = HostToNet((uint32_t)value.size()); + if (!value.empty()) { + auto err = memcpy_s(tlvHead->value, value.size(), value.c_str(), value.size()); + if (err != EOK) { + return false; + } + } + cursor_ += sizeof(TLVHead) + value.size(); + return true; + } + + bool ReadString(std::string &value) + { + TLVHead head {}; + if (!ReadHead(head)) { + return false; + } + if (!HasExpectBuffer(head.len)) { + return false; + } + value.append(reinterpret_cast(buffer_->data() + cursor_), head.len); + cursor_ += head.len; + return true; + } + + bool WriteVector(const std::vector &value) + { + if (!HasExpectBuffer(sizeof(TLVHead) + value.size())) { + return false; + } + WriteHead(TAG_VECTOR, cursor_, value.size()); + cursor_ += sizeof(TLVHead); + + if (!value.empty()) { + auto err = memcpy_s(buffer_->data() + cursor_, buffer_->size() - cursor_, value.data(), value.size()); + if (err != EOK) { + return false; + } + } + cursor_ += value.size(); + return true; + } + + bool ReadVector(std::vector &value) + { + TLVHead head {}; + if (!ReadHead(head)) { + return false; + } + if (!HasExpectBuffer(head.len)) { + return false; + } + std::vector buff(buffer_->data() + cursor_, buffer_->data() + cursor_ + head.len); + value = std::move(buff); + cursor_ += head.len; + return true; + } + + bool WriteVariant(const UDVariant &value) + { + if (!HasExpectBuffer(sizeof(TLVHead))) { + return false; + } + auto tagCursor = cursor_; + cursor_ += sizeof(TLVHead); + auto valueCursor = cursor_; + TAG tag = TAG::TAG_BUTT; + auto int32Value = std::get_if(&value); + if (int32Value != nullptr) { + if (!WriteBasic(TAG_INT32, std::get(value))) { + return false; + } + tag = TAG::TAG_INT32; + } + auto int64Value = std::get_if(&value); + if (int64Value != nullptr) { + if (!WriteBasic(TAG_INT64, std::get(value))) { + return false; + } + tag = TAG::TAG_INT64; + } + auto boolValue = std::get_if(&value); + if (boolValue != nullptr) { + if (!WriteBasic(TAG_BOOL, std::get(value))) { + return false; + } + tag = TAG::TAG_BOOL; + } + auto doubleValue = std::get_if(&value); + if (doubleValue != nullptr) { + if (!WriteBasic(TAG_DOUBLE, std::get(value))) { + return false; + } + tag = TAG::TAG_DOUBLE; + } + auto stringValue = std::get_if(&value); + if (stringValue != nullptr) { + if (!WriteString(std::get(value))) { + return false; + } + tag = TAG::TAG_STRING; + } + auto vectorValue = std::get_if>(&value); + if (vectorValue != nullptr) { + if (!WriteVector(std::get>(value))) { + return false; + } + tag = TAG::TAG_VECTOR; + } + WriteHead(tag, tagCursor, cursor_ - valueCursor); + return true; + } + + bool ReadVariant(UDVariant &value) + { + TLVHead head {}; + if (!ReadHead(head)) { + return false; + } + if (!HasExpectBuffer(head.len)) { + return false; + } + switch (head.tag) { + case static_cast(TAG::TAG_INT32): { + int32_t int32Value; + if (!ReadBasic(int32Value)) { + return false; + } + value.emplace(int32Value); + break; + } + case static_cast(TAG::TAG_INT64): { + int64_t int64Value; + if (!ReadBasic(int64Value)) { + return false; + } + value.emplace(int64Value); + break; + } + case static_cast(TAG::TAG_BOOL): { + bool boolValue; + if (!ReadBasic(boolValue)) { + return false; + } + value.emplace(boolValue); + break; + } + case static_cast(TAG::TAG_DOUBLE): { + double doubleValue; + if (!ReadBasic(doubleValue)) { + return false; + } + value.emplace(doubleValue); + break; + } + case static_cast(TAG::TAG_STRING): { + std::string stringValue; + if (!ReadString(stringValue)) { + return false; + } + value.emplace(stringValue); + break; + } + case static_cast(TAG::TAG_VECTOR): { + std::vector vectorValue; + if (!ReadVector(vectorValue)) { + return false; + } + value.emplace>(vectorValue); + break; + } + default: { + return false; + } + } + return true; + } + + bool WriteMap(const UDDetails &value) + { + if (!HasExpectBuffer(sizeof(TLVHead))) { + return false; + } + + auto tagCursor = cursor_; + cursor_ += sizeof(TLVHead); + auto valueCursor = cursor_; + + for (const auto &item : value) { + if (!WriteString(item.first)) { + return false; + } + if (!WriteVariant(item.second)) { + return false; + } + } + + WriteHead(TAG_MAP, tagCursor, cursor_ - valueCursor); + return true; + } + + bool ReadMap(UDDetails &value) + { + TLVHead head {}; + if (!ReadHead(head)) { + return false; + } + if (!HasExpectBuffer(head.len)) { + return false; + } + auto mapEnd = cursor_ + head.len; + while (cursor_ < mapEnd) { + std::string itemKey; + if (!ReadString(itemKey)) { + return false; + } + UDVariant itemValue; + if (!ReadVariant(itemValue)) { + return false; + } + value.emplace(itemKey, itemValue); + } + return true; + } + +private: + inline bool ReadHead(TLVHead &head) + { + if (!HasExpectBuffer(sizeof(TLVHead))) { + return false; + } + const auto *pHead = reinterpret_cast(buffer_->data() + cursor_); + if (!HasExpectBuffer(NetToHost(pHead->len)) && + !HasExpectBuffer(NetToHost(pHead->len) + sizeof(TLVHead))) { + return false; + } + head.tag = NetToHost(pHead->tag); + head.len = NetToHost(pHead->len); + cursor_ += sizeof(TLVHead); + return true; + } + + inline void WriteHead(uint16_t type, size_t tagCursor, uint32_t len) + { + auto *tlvHead = reinterpret_cast(buffer_->data() + tagCursor); + tlvHead->tag = HostToNet(type); + tlvHead->len = HostToNet(len); + } + + inline bool HasExpectBuffer(const uint32_t expectLen) const + { + return buffer_->size() >= cursor_ && buffer_->size() - cursor_ >= expectLen; + } + + std::size_t total_ = 0; + std::size_t cursor_ = 0; + std::vector *buffer_; +}; +} // namespace UDMF +} // namespace OHOS +#endif // UDMF_TLV_OBJECT_H \ No newline at end of file diff --git a/udmf/framework/common/tlv_util.cpp b/udmf/framework/common/tlv_util.cpp new file mode 100644 index 0000000000000000000000000000000000000000..235d141737988bb21617b00fa7c213f36186f32c --- /dev/null +++ b/udmf/framework/common/tlv_util.cpp @@ -0,0 +1,1463 @@ +/* + * 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 "tlv_util.h" + +namespace OHOS { +namespace TLVUtil { +template<> +bool CountBufferSize(const std::shared_ptr &input, TLVObject &data) +{ + data.Count(input->GetType()); + data.Count(input->GetUid()); + auto type = input->GetType(); + switch (type) { + case UDType::TEXT: { + auto text = static_cast(input.get()); + if (text == nullptr) { + return false; + } + data.Count(text->GetDetails()); + break; + } + case UDType::PLAIN_TEXT: { + auto plainText = static_cast(input.get()); + if (plainText == nullptr) { + return false; + } + data.Count(plainText->GetContent()); + data.Count(plainText->GetAbstract()); + auto text = static_cast<Text *>(input.get()); + if (text == nullptr) { + return false; + } + data.Count(text->GetDetails()); + break; + } + case UDType::HTML: { + auto html = static_cast<Html *>(input.get()); + if (html == nullptr) { + return false; + } + data.Count(html->GetHtmlContent()); + data.Count(html->GetPlainContent()); + auto text = static_cast<Text *>(input.get()); + if (text == nullptr) { + return false; + } + data.Count(text->GetDetails()); + break; + } + case UDType::HYPERLINK: { + auto link = static_cast<Link *>(input.get()); + if (link == nullptr) { + return false; + } + data.Count(link->GetUrl()); + data.Count(link->GetDescription()); + auto text = static_cast<Text *>(input.get()); + if (text == nullptr) { + return false; + } + data.Count(text->GetDetails()); + break; + } + case UDType::FILE: { + auto file = static_cast<File *>(input.get()); + if (file == nullptr) { + return false; + } + data.Count(file->GetUri()); + data.Count(file->GetRemoteUri()); + data.Count(file->GetDetails()); + break; + } + case UDType::IMAGE: { + auto image = static_cast<Image *>(input.get()); + if (image == nullptr) { + return false; + } + data.Count(image->GetUri()); + data.Count(image->GetRemoteUri()); + auto file = static_cast<File *>(input.get()); + if (file == nullptr) { + return false; + } + data.Count(file->GetDetails()); + break; + } + case UDType::VIDEO: { + auto video = static_cast<Video *>(input.get()); + if (video == nullptr) { + return false; + } + data.Count(video->GetUri()); + data.Count(video->GetRemoteUri()); + auto file = static_cast<File *>(input.get()); + if (file == nullptr) { + return false; + } + data.Count(file->GetDetails()); + break; + } + case UDType::AUDIO: { + auto audio = static_cast<Audio *>(input.get()); + if (audio == nullptr) { + return false; + } + data.Count(audio->GetUri()); + data.Count(audio->GetRemoteUri()); + auto file = static_cast<File *>(input.get()); + if (file == nullptr) { + return false; + } + data.Count(file->GetDetails()); + break; + } + case UDType::FOLDER: { + auto folder = static_cast<Folder *>(input.get()); + if (folder == nullptr) { + return false; + } + data.Count(folder->GetUri()); + data.Count(folder->GetRemoteUri()); + auto file = static_cast<File *>(input.get()); + if (file == nullptr) { + return false; + } + data.Count(file->GetDetails()); + break; + } + case UDType::SYSTEM_DEFINED_RECORD: { + auto sdRecord = static_cast<SystemDefinedRecord *>(input.get()); + if (sdRecord == nullptr) { + return false; + } + data.Count(sdRecord->GetDetails()); + break; + } + case UDType::SYSTEM_DEFINED_FORM: { + auto form = static_cast<SystemDefinedForm *>(input.get()); + if (form == nullptr) { + return false; + } + data.Count(form->GetFormId()); + data.Count(form->GetFormName()); + data.Count(form->GetBundleName()); + data.Count(form->GetAbilityName()); + data.Count(form->GetModule()); + auto sdRecord = static_cast<SystemDefinedRecord *>(input.get()); + if (sdRecord == nullptr) { + return false; + } + data.Count(sdRecord->GetDetails()); + break; + } + case UDType::SYSTEM_DEFINED_APP_ITEM: { + auto appItem = static_cast<SystemDefinedAppItem *>(input.get()); + if (appItem == nullptr) { + return false; + } + data.Count(appItem->GetAppId()); + data.Count(appItem->GetAppName()); + data.Count(appItem->GetAppIconId()); + data.Count(appItem->GetAppLabelId()); + data.Count(appItem->GetBundleName()); + data.Count(appItem->GetAbilityName()); + auto sdRecord = static_cast<SystemDefinedRecord *>(input.get()); + if (sdRecord == nullptr) { + return false; + } + data.Count(sdRecord->GetDetails()); + break; + } + case UDType::SYSTEM_DEFINED_PIXEL_MAP: { + auto pixelMap = static_cast<SystemDefinedPixelMap *>(input.get()); + if (pixelMap == nullptr) { + return false; + } + data.Count(pixelMap->GetRawData()); + auto sdRecord = static_cast<SystemDefinedRecord *>(input.get()); + if (sdRecord == nullptr) { + return false; + } + data.Count(sdRecord->GetDetails()); + break; + } + case UDType::APPLICATION_DEFINED_RECORD: { + auto record = static_cast<ApplicationDefinedRecord *>(input.get()); + if (record == nullptr) { + return false; + } + data.Count(record->GetApplicationDefinedType()); + data.Count(record->GetRawData()); + break; + } + default: { + return false; + } + } + return true; +} + +template<> +bool CountBufferSize(const Runtime &input, TLVObject &data) +{ + data.Count(input.key); + data.Count(input.isPrivate); + uint32_t size = static_cast<uint32_t>(input.privileges.size()); + data.Count(size); + for (uint32_t i = 0; i < size; ++i) { + data.Count(input.privileges[i]); + } + data.Count(static_cast<int64_t>(input.createTime)); + data.Count(static_cast<int64_t>(input.lastModifiedTime)); + data.Count(input.sourcePackage); + data.Count(static_cast<int32_t>(input.dataStatus)); + data.Count(input.dataVersion); + data.Count(input.createPackage); + data.Count(input.deviceId); + return true; +} + +template<> +bool CountBufferSize(const UnifiedData &input, TLVObject &data) +{ + int32_t size = input.GetRecords().size(); + data.Count(size); + for (auto record : input.GetRecords()) { + if (!CountBufferSize(record, data)) { + return false; + } + } + return true; +} + +template<> +bool CountBufferSize(const std::vector<UnifiedData> &input, TLVObject &data) +{ + int32_t size = input.size(); + data.Count(size); + for (auto unifiedData : input) { + if (!CountBufferSize(unifiedData, data)) { + return false; + } + } + return true; +} + +template<typename T> +bool Writing(const T &input, TLVObject &data); + +template<typename T> +bool Reading(T &output, TLVObject &data); + +template<> +bool Writing(const int32_t &input, TLVObject &data) +{ + return data.WriteBasic(TAG_INT32, input); +} + +template<> +bool Reading(int32_t &output, TLVObject &data) +{ + return data.ReadBasic(output); +} + +template<> +bool Writing(const int64_t &input, TLVObject &data) +{ + return data.WriteBasic(TAG_INT64, input); +} + +template<> +bool Reading(int64_t &output, TLVObject &data) +{ + return data.ReadBasic(output); +} + +template<> +bool Reading(uint32_t &output, TLVObject &data) +{ + return data.ReadBasic(output); +} + +template<> +bool Writing(const uint32_t &input, TLVObject &data) +{ + return data.WriteBasic(TAG_UINT32, input); +} + +template<> +bool Reading(uint64_t &output, TLVObject &data) +{ + return data.ReadBasic(output); +} + +template<> +bool Writing(const uint64_t &input, TLVObject &data) +{ + return data.WriteBasic(TAG_UINT64, input); +} + +template<> +bool Writing(const bool &input, TLVObject &data) +{ + return data.WriteBasic(TAG_BOOL, input); +} + +template<> +bool Reading(bool &output, TLVObject &data) +{ + return data.ReadBasic(output); +} + +template<> +bool Writing(const std::string &input, TLVObject &data) +{ + return data.WriteString(input); +} + +template<> +bool Reading(std::string &output, TLVObject &data) +{ + return data.ReadString(output); +} + +template<> +bool Writing(const std::vector<uint8_t> &input, TLVObject &data) +{ + return data.WriteVector(input); +} + +template<> +bool Reading(std::vector<uint8_t> &output, TLVObject &data) +{ + return data.ReadVector(output); +} + +template<> +bool Writing(const UDVariant &input, TLVObject &data) +{ + return data.WriteVariant(input); +} + +template<> +bool Reading(UDVariant &output, TLVObject &data) +{ + return data.ReadVariant(output); +} + +template<> +bool Writing(const UDDetails &input, TLVObject &data) +{ + return data.WriteMap(input); +} + +template<> +bool Reading(UDDetails &output, TLVObject &data) +{ + return data.ReadMap(output); +} + +template<> +bool Writing(const UDType &input, TLVObject &data) +{ + int32_t type = input; + return Writing(type, data); +} + +template<> +bool Reading(UDType &output, TLVObject &data) +{ + int32_t type; + if (!Reading(type, data)) { + return false; + } + if (type < UDType::TEXT || type >= UDType::UD_BUTT) { + return false; + } + output = static_cast<UDType>(type); + return true; +} + +template<> +bool Writing(const Text &input, TLVObject &data) +{ + return Writing(input.GetDetails(), data); +} + +template<> +bool Reading(Text &output, TLVObject &data) +{ + UDDetails details; + if (!Reading(details, data)) { + return false; + } + output.SetDetails(details); + return true; +} + +template<> +bool Writing(const PlainText &input, TLVObject &data) +{ + if (!Writing(input.GetContent(), data)) { + return false; + } + if (!Writing(input.GetAbstract(), data)) { + return false; + } + return true; +} + +template<> +bool Reading(PlainText &output, TLVObject &data) +{ + std::string content; + std::string abstract; + UDDetails details; + if (!Reading(content, data)) { + return false; + } + if (!Reading(abstract, data)) { + return false; + } + if (!Reading(details, data)) { + return false; + } + output.SetContent(content); + output.SetAbstract(abstract); + output.SetDetails(details); + return true; +} + +template<> +bool Writing(const Html &input, TLVObject &data) +{ + if (!Writing(input.GetHtmlContent(), data)) { + return false; + } + if (!Writing(input.GetPlainContent(), data)) { + return false; + } + return true; +} + +template<> +bool Reading(Html &output, TLVObject &data) +{ + std::string htmlContent; + std::string plainContent; + UDDetails details; + if (!Reading(htmlContent, data)) { + return false; + } + if (!Reading(plainContent, data)) { + return false; + } + if (!Reading(details, data)) { + return false; + } + output.SetHtmlContent(htmlContent); + output.SetPlainContent(plainContent); + output.SetDetails(details); + return true; +} + +template<> +bool Writing(const Link &input, TLVObject &data) +{ + if (!Writing(input.GetUrl(), data)) { + return false; + } + if (!Writing(input.GetDescription(), data)) { + return false; + } + return true; +} + +template<> +bool Reading(Link &output, TLVObject &data) +{ + std::string url; + std::string description; + UDDetails details; + if (!Reading(url, data)) { + return false; + } + if (!Reading(description, data)) { + return false; + } + if (!Reading(details, data)) { + return false; + } + output.SetUrl(url); + output.SetDescription(description); + output.SetDetails(details); + return true; +} + +template<> +bool Writing(const File &input, TLVObject &data) +{ + if (!Writing(input.GetUri(), data)) { + return false; + } + if (!Writing(input.GetRemoteUri(), data)) { + return false; + } + if (!Writing(input.GetDetails(), data)) { + return false; + } + return true; +} + +template<> +bool Reading(File &output, TLVObject &data) +{ + std::string uri; + std::string remoteUri; + UDDetails details; + if (!Reading(uri, data)) { + return false; + } + if (!Reading(remoteUri, data)) { + return false; + } + if (!Reading(details, data)) { + return false; + } + output.SetUri(uri); + output.SetRemoteUri(remoteUri); + output.SetDetails(details); + return true; +} + +template<> +bool Writing(const Image &input, TLVObject &data) +{ + return true; +} + +template<> +bool Reading(Image &output, TLVObject &data) +{ + std::string uri; + std::string remoteUri; + UDDetails details; + if (!Reading(uri, data)) { + return false; + } + if (!Reading(remoteUri, data)) { + return false; + } + if (!Reading(details, data)) { + return false; + } + output.SetUri(uri); + output.SetRemoteUri(remoteUri); + output.SetDetails(details); + return true; +} + +template<> +bool Writing(const Video &input, TLVObject &data) +{ + return true; +} + +template<> +bool Reading(Video &output, TLVObject &data) +{ + std::string uri; + std::string remoteUri; + UDDetails details; + if (!Reading(uri, data)) { + return false; + } + if (!Reading(remoteUri, data)) { + return false; + } + if (!Reading(details, data)) { + return false; + } + output.SetUri(uri); + output.SetRemoteUri(remoteUri); + output.SetDetails(details); + return true; +} + +template<> +bool Writing(const Audio &input, TLVObject &data) +{ + return true; +} + +template<> +bool Reading(Audio &output, TLVObject &data) +{ + std::string uri; + std::string remoteUri; + UDDetails details; + if (!Reading(uri, data)) { + return false; + } + if (!Reading(remoteUri, data)) { + return false; + } + if (!Reading(details, data)) { + return false; + } + output.SetUri(uri); + output.SetRemoteUri(remoteUri); + output.SetDetails(details); + return true; +} + +template<> +bool Writing(const Folder &input, TLVObject &data) +{ + return true; +} + +template<> +bool Reading(Folder &output, TLVObject &data) +{ + std::string uri; + std::string remoteUri; + UDDetails details; + if (!Reading(uri, data)) { + return false; + } + if (!Reading(remoteUri, data)) { + return false; + } + if (!Reading(details, data)) { + return false; + } + output.SetUri(uri); + output.SetRemoteUri(remoteUri); + output.SetDetails(details); + return true; +} + +template<> +bool Writing(const SystemDefinedRecord &input, TLVObject &data) +{ + if (!Writing(input.GetDetails(), data)) { + return false; + } + return true; +} + +template<> +bool Reading(SystemDefinedRecord &output, TLVObject &data) +{ + UDDetails details; + if (!Reading(details, data)) { + return false; + } + output.SetDetails(details); + return true; +} + +template<> +bool Writing(const SystemDefinedForm &input, TLVObject &data) +{ + if (!Writing(input.GetFormId(), data)) { + return false; + } + if (!Writing(input.GetFormName(), data)) { + return false; + } + if (!Writing(input.GetBundleName(), data)) { + return false; + } + if (!Writing(input.GetAbilityName(), data)) { + return false; + } + if (!Writing(input.GetModule(), data)) { + return false; + } + return true; +} + +template<> +bool Reading(SystemDefinedForm &output, TLVObject &data) +{ + int32_t formId; + std::string formName; + std::string bundleName; + std::string abilityName; + std::string module; + UDDetails details; + if (!Reading(formId, data)) { + return false; + } + if (!Reading(formName, data)) { + return false; + } + if (!Reading(bundleName, data)) { + return false; + } + if (!Reading(abilityName, data)) { + return false; + } + if (!Reading(module, data)) { + return false; + } + if (!Reading(details, data)) { + return false; + } + output.SetFormId(formId); + output.SetFormName(formName); + output.SetBundleName(bundleName); + output.SetAbilityName(abilityName); + output.SetModule(module); + output.SetDetails(details); + return true; +} + +template<> +bool Writing(const SystemDefinedAppItem &input, TLVObject &data) +{ + if (!Writing(input.GetAppId(), data)) { + return false; + } + if (!Writing(input.GetAppName(), data)) { + return false; + } + if (!Writing(input.GetAppIconId(), data)) { + return false; + } + if (!Writing(input.GetAppLabelId(), data)) { + return false; + } + if (!Writing(input.GetBundleName(), data)) { + return false; + } + if (!Writing(input.GetAbilityName(), data)) { + return false; + } + return true; +} + +template<> +bool Reading(SystemDefinedAppItem &output, TLVObject &data) +{ + std::string appId; + std::string appName; + std::string appIconId; + std::string appLabelId; + std::string bundleName; + std::string abilityName; + UDDetails details; + if (!Reading(appId, data)) { + return false; + } + if (!Reading(appName, data)) { + return false; + } + if (!Reading(appIconId, data)) { + return false; + } + if (!Reading(appLabelId, data)) { + return false; + } + if (!Reading(bundleName, data)) { + return false; + } + if (!Reading(abilityName, data)) { + return false; + } + if (!Reading(details, data)) { + return false; + } + output.SetAppId(appId); + output.SetAppName(appName); + output.SetAppIconId(appIconId); + output.SetAppLabelId(appLabelId); + output.SetBundleName(bundleName); + output.SetAbilityName(abilityName); + output.SetDetails(details); + return true; +} + +template<> +bool Writing(const SystemDefinedPixelMap &input, TLVObject &data) +{ + if (!Writing(input.GetRawData(), data)) { + return false; + } + return true; +} + +template<> +bool Reading(SystemDefinedPixelMap &output, TLVObject &data) +{ + std::vector<uint8_t> rawData; + UDDetails details; + if (!Reading(rawData, data)) { + return false; + } + if (!Reading(details, data)) { + return false; + } + output.SetRawData(rawData); + output.SetDetails(details); + return true; +} + +template<> +bool Writing(const ApplicationDefinedRecord &input, TLVObject &data) +{ + if (!Writing(input.GetApplicationDefinedType(), data)) { + return false; + } + if (!Writing(input.GetRawData(), data)) { + return false; + } + return true; +} + +template<> +bool Reading(ApplicationDefinedRecord &output, TLVObject &data) +{ + std::string type; + std::vector<uint8_t> rawData; + if (!Reading(type, data)) { + return false; + } + if (!Reading(rawData, data)) { + return false; + } + output.SetApplicationDefinedType(type); + output.SetRawData(rawData); + return true; +} + +template<> +bool Writing(const std::shared_ptr<UnifiedRecord> &input, TLVObject &data) +{ + if (data.GetBuffer().size() == 0) { + if (!CountBufferSize(input, data)) { + return false; + } + data.UpdateSize(); + } + + if (!Writing(input->GetType(), data)) { + return false; + } + if (!Writing(input->GetUid(), data)) { + return false; + } + auto type = input->GetType(); + switch (type) { + case UDType::TEXT: { + auto text = static_cast<Text *>(input.get()); + if (text == nullptr) { + return false; + } + return Writing(*text, data); + } + case UDType::PLAIN_TEXT: { + auto plainText = static_cast<PlainText *>(input.get()); + if (plainText == nullptr) { + return false; + } + if (!Writing(*plainText, data)) { + return false; + } + auto text = static_cast<Text *>(input.get()); + if (text == nullptr) { + return false; + } + return Writing(*text, data); + } + case UDType::HTML: { + auto html = static_cast<Html *>(input.get()); + if (html == nullptr) { + return false; + } + if (!Writing(*html, data)) { + return false; + } + auto text = static_cast<Text *>(input.get()); + if (text == nullptr) { + return false; + } + return Writing(*text, data); + } + case UDType::HYPERLINK: { + auto link = static_cast<Link *>(input.get()); + if (link == nullptr) { + return false; + } + if (!Writing(*link, data)) { + return false; + } + auto text = static_cast<Text *>(input.get()); + if (text == nullptr) { + return false; + } + return Writing(*text, data); + } + case UDType::FILE: { + auto file = static_cast<File *>(input.get()); + if (file == nullptr) { + return false; + } + return Writing(*file, data); + } + case UDType::IMAGE: { + auto image = static_cast<Image *>(input.get()); + if (image == nullptr) { + return false; + } + if (!Writing(*image, data)) { + return false; + } + auto file = static_cast<File *>(input.get()); + if (file == nullptr) { + return false; + } + return Writing(*file, data); + } + case UDType::VIDEO: { + auto video = static_cast<Video *>(input.get()); + if (video == nullptr) { + return false; + } + if (!Writing(*video, data)) { + return false; + } + auto file = static_cast<File *>(input.get()); + if (file == nullptr) { + return false; + } + return Writing(*file, data); + } + case UDType::AUDIO: { + auto audio = static_cast<Audio *>(input.get()); + if (audio == nullptr) { + return false; + } + if (!Writing(*audio, data)) { + return false; + } + auto file = static_cast<File *>(input.get()); + if (file == nullptr) { + return false; + } + return Writing(*file, data); + } + case UDType::FOLDER: { + auto folder = static_cast<Folder *>(input.get()); + if (folder == nullptr) { + return false; + } + if (!Writing(*folder, data)) { + return false; + } + auto file = static_cast<File *>(input.get()); + if (file == nullptr) { + return false; + } + return Writing(*file, data); + } + case UDType::SYSTEM_DEFINED_RECORD: { + auto sdRecord = static_cast<SystemDefinedRecord *>(input.get()); + if (sdRecord == nullptr) { + return false; + } + return Writing(*sdRecord, data); + } + case UDType::SYSTEM_DEFINED_FORM: { + auto form = static_cast<SystemDefinedForm *>(input.get()); + if (form == nullptr) { + return false; + } + if (!Writing(*form, data)) { + return false; + } + auto sdRecord = static_cast<SystemDefinedRecord *>(input.get()); + if (sdRecord == nullptr) { + return false; + } + return Writing(*sdRecord, data); + } + case UDType::SYSTEM_DEFINED_APP_ITEM: { + auto appItem = static_cast<SystemDefinedAppItem *>(input.get()); + if (appItem == nullptr) { + return false; + } + if (!Writing(*appItem, data)) { + return false; + } + auto sdRecord = static_cast<SystemDefinedRecord *>(input.get()); + if (sdRecord == nullptr) { + return false; + } + return Writing(*sdRecord, data); + } + case UDType::SYSTEM_DEFINED_PIXEL_MAP: { + auto pixelMap = static_cast<SystemDefinedPixelMap *>(input.get()); + if (pixelMap == nullptr) { + return false; + } + if (!Writing(*pixelMap, data)) { + return false; + } + auto sdRecord = static_cast<SystemDefinedRecord *>(input.get()); + if (sdRecord == nullptr) { + return false; + } + return Writing(*sdRecord, data); + } + case UDType::APPLICATION_DEFINED_RECORD: { + auto record = static_cast<ApplicationDefinedRecord *>(input.get()); + if (record == nullptr) { + return false; + } + return Writing(*record, data); + } + default: { + return false; + } + } +} + +template<> +bool Reading(std::shared_ptr<UnifiedRecord> &output, TLVObject &data) +{ + UDType type ; + if (!Reading(type, data)) { + return false; + } + std::string uid; + if (!Reading(uid, data)) { + return false; + } + switch (type) { + case UDType::TEXT: { + std::shared_ptr<Text> text = std::make_shared<Text>(); + if (!Reading(*text, data)) { + return false; + } + output = text; + break; + } + case UDType::PLAIN_TEXT: { + std::shared_ptr<PlainText> plainText = std::make_shared<PlainText>(); + if (!Reading(*plainText, data)) { + return false; + } + output = plainText; + break; + } + case UDType::HTML: { + std::shared_ptr<Html> html = std::make_shared<Html>(); + if (!Reading(*html, data)) { + return false; + } + output = html; + break; + } + case UDType::HYPERLINK: { + std::shared_ptr<Link> link = std::make_shared<Link>(); + if (!Reading(*link, data)) { + return false; + } + output = link; + break; + } + case UDType::FILE: { + std::shared_ptr<File> file = std::make_shared<File>(); + if (!Reading(*file, data)) { + return false; + } + output = file; + break; + } + case UDType::IMAGE: { + std::shared_ptr<Image> image = std::make_shared<Image>(); + if (!Reading(*image, data)) { + return false; + } + output = image; + break; + } + case UDType::VIDEO: { + std::shared_ptr<Video> video = std::make_shared<Video>(); + if (!Reading(*video, data)) { + return false; + } + output = video; + break; + } + case UDType::AUDIO: { + std::shared_ptr<Audio> audio = std::make_shared<Audio>(); + if (!Reading(*audio, data)) { + return false; + } + output = audio; + break; + } + case UDType::FOLDER: { + std::shared_ptr<Folder> folder = std::make_shared<Folder>(); + if (!Reading(*folder, data)) { + return false; + } + output = folder; + break; + } + case UDType::SYSTEM_DEFINED_RECORD: { + std::shared_ptr<SystemDefinedRecord> sdRecord = std::make_shared<SystemDefinedRecord>(); + if (!Reading(*sdRecord, data)) { + return false; + } + output = sdRecord; + break; + } + case UDType::SYSTEM_DEFINED_FORM: { + std::shared_ptr<SystemDefinedForm> form = std::make_shared<SystemDefinedForm>(); + if (!Reading(*form, data)) { + return false; + } + output = form; + break; + } + case UDType::SYSTEM_DEFINED_APP_ITEM: { + std::shared_ptr<SystemDefinedAppItem> appItem = std::make_shared<SystemDefinedAppItem>(); + if (!Reading(*appItem, data)) { + return false; + } + output = appItem; + break; + } + case UDType::SYSTEM_DEFINED_PIXEL_MAP: { + std::shared_ptr<SystemDefinedPixelMap> pixelMap = std::make_shared<SystemDefinedPixelMap>(); + if (!Reading(*pixelMap, data)) { + return false; + } + output = pixelMap; + break; + } + case UDType::APPLICATION_DEFINED_RECORD: { + std::shared_ptr<ApplicationDefinedRecord> record = std::make_shared<ApplicationDefinedRecord>(); + if (!Reading(*record, data)) { + return false; + } + output = record; + break; + } + default: { + return false; + } + } + output->SetUid(uid); + output->SetType(type); + return true; +} + +template<> +bool Writing(const UnifiedData &input, TLVObject &data) +{ + if (data.GetBuffer().size() == 0) { + if (!CountBufferSize(input, data)) { + return false; + } + data.UpdateSize(); + } + + int32_t size = input.GetRecords().size(); + if (!Writing(size, data)) { + return false; + } + + for (auto record : input.GetRecords()) { + if (!Writing(record, data)) { + return false; + } + } + return true; +} + +template<> +bool Reading(UnifiedData &output, TLVObject &data) +{ + int32_t size; + if (!Reading(size, data)) { + return false; + } + while (size-- > 0) { + std::shared_ptr<UnifiedRecord> record; + if (!Reading(record, data)) { + return false; + } + output.AddRecord(record); + } + return true; +} + +template<> +bool Writing(const std::vector<UnifiedData> &input, TLVObject &data) +{ + if (!CountBufferSize(input, data)) { + return false; + } + data.UpdateSize(); + + int32_t size = input.size(); + if (!Writing(size, data)) { + return false; + } + + for (auto unifiedData : input) { + if (!Writing(unifiedData, data)) { + return false; + } + } + return true; +} + +template<> +bool Reading(std::vector<UnifiedData> &output, TLVObject &data) +{ + int32_t size; + if (!Reading(size, data)) { + return false; + } + while (size-- > 0) { + UnifiedData unifiedData; + if (!Reading(unifiedData, data)) { + return false; + } + output.push_back(unifiedData); + } + return true; +} + +template<> +bool Writing(const UnifiedKey &input, TLVObject &data) +{ + if (!Writing(input.key, data)) { + return false; + } + if (!Writing(input.intention, data)) { + return false; + } + if (!Writing(input.bundleName, data)) { + return false; + } + if (!Writing(input.groupId, data)) { + return false; + } + return true; +} + +template<> +bool Reading(UnifiedKey &output, TLVObject &data) +{ + std::string key; + std::string intention; + std::string bundleName; + std::string groupId; + if (!Reading(key, data)) { + return false; + } + if (!Reading(intention, data)) { + return false; + } + if (!Reading(bundleName, data)) { + return false; + } + if (!Reading(groupId, data)) { + return false; + } + output.key = key; + output.intention = intention; + output.bundleName = bundleName; + output.groupId = groupId; + return true; +} + +template<> +bool Writing(const Privilege &input, TLVObject &data) +{ + if (!Writing(input.tokenId, data)) { + return false; + } + if (!Writing(input.readPermission, data)) { + return false; + } + if (!Writing(input.writePermission, data)) { + return false; + } + return true; +} + +template<> +bool Reading(Privilege &output, TLVObject &data) +{ + uint32_t tokenId; + std::string readPermission; + std::string writePermission; + if (!Reading(tokenId, data)) { + return false; + } + if (!Reading(readPermission, data)) { + return false; + } + if (!Reading(writePermission, data)) { + return false; + } + output.tokenId = tokenId; + output.readPermission = readPermission; + output.writePermission = writePermission; + return true; +} + +template<> +bool Writing(const DataStatus &input, TLVObject &data) +{ + int32_t status = input; + return Writing(status, data); +} + +template<> +bool Reading(DataStatus &output, TLVObject &data) +{ + int32_t status; + if (!Reading(status, data)) { + return false; + } + if (status < DataStatus::WORKING || status >= DataStatus::FADE) { + return false; + } + output = static_cast<DataStatus>(status); + return true; +} + +template<> +bool Writing(const Runtime &input, TLVObject &data) +{ + (void)CountBufferSize(input, data); + data.UpdateSize(); + if (!Writing(input.key, data)) { + return false; + } + if (!Writing(input.isPrivate, data)) { + return false; + } + uint32_t size = static_cast<uint32_t>(input.privileges.size()); + if (!Writing(size, data)) { + return false; + } + for (uint32_t i = 0; i < size; ++i) { + if (!Writing(input.privileges[i], data)) { + return false; + } + } + if (!Writing(static_cast<int64_t>(input.createTime), data)) { + return false; + } + if (!Writing(input.sourcePackage, data)) { + return false; + } + if (!Writing(input.dataStatus, data)) { + return false; + } + if (!Writing(input.dataVersion, data)) { + return false; + } + if (!Writing(static_cast<int64_t>(input.lastModifiedTime), data)) { + return false; + } + if (!Writing(input.createPackage, data)) { + return false; + } + if (!Writing(input.deviceId, data)) { + return false; + } + return true; +} + +template<> +bool Reading(Runtime &output, TLVObject &data) +{ + UnifiedKey key; + bool isPrivate; + uint32_t size; + std::vector<Privilege> privileges; + int64_t createTime; + std::string sourcePackage; + DataStatus dataStatus; + int32_t dataVersion; + int64_t lastModifiedTime; + std::string createPackage; + std::string deviceId; + if (!Reading(key, data)) { + return false; + } + if (!Reading(isPrivate, data)) { + return false; + } + if (!Reading(size, data)) { + return false; + } + for (uint32_t i = 0; i < size; ++i) { + Privilege privilege; + if (!Reading(privilege, data)) { + return false; + } + privileges.emplace_back(privilege); + } + if (!Reading(createTime, data)) { + return false; + } + if (!Reading(sourcePackage, data)) { + return false; + } + if (!Reading(dataStatus, data)) { + return false; + } + if (!Reading(dataVersion, data)) { + return false; + } + if (!Reading(lastModifiedTime, data)) { + return false; + } + if (!Reading(createPackage, data)) { + return false; + } + if (!Reading(deviceId, data)) { + return false; + } + output.key = key; + output.isPrivate = isPrivate; + output.privileges = privileges; + output.createTime = createTime; + output.sourcePackage = sourcePackage; + output.dataStatus = dataStatus; + output.dataVersion = dataVersion; + output.lastModifiedTime = lastModifiedTime; + output.createPackage = createPackage; + output.deviceId = deviceId; + return true; +} +} // namespace TLVUtil +} // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/common/tlv_util.h b/udmf/framework/common/tlv_util.h new file mode 100644 index 0000000000000000000000000000000000000000..e3d330b0a9ab1c2c09e591a9b14a11a7f0ea69d9 --- /dev/null +++ b/udmf/framework/common/tlv_util.h @@ -0,0 +1,223 @@ +/* + * 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 UDMF_TLV_UTIL_H +#define UDMF_TLV_UTIL_H + +#include <type_traits> + +#include "application_defined_record.h" +#include "audio.h" +#include "file.h" +#include "folder.h" +#include "html.h" +#include "image.h" +#include "link.h" +#include "plain_text.h" +#include "system_defined_appitem.h" +#include "system_defined_form.h" +#include "system_defined_pixelmap.h" +#include "system_defined_record.h" +#include "text.h" +#include "tlv_object.h" +#include "unified_data.h" +#include "unified_key.h" +#include "unified_meta.h" +#include "unified_record.h" +#include "unified_types.h" +#include "video.h" + +namespace OHOS { +namespace TLVUtil { +using namespace OHOS::UDMF; +template<typename T> +bool CountBufferSize(const T &input, TLVObject &data); + +template<> +bool CountBufferSize(const std::shared_ptr<UnifiedRecord> &input, TLVObject &data); + +template<> +bool CountBufferSize(const Runtime &input, TLVObject &data); + +template<> +bool CountBufferSize(const UnifiedData &input, TLVObject &data); + +template<> +bool CountBufferSize(const std::vector<UnifiedData> &input, TLVObject &data); + +template<typename T> +bool Writing(const T &input, TLVObject &data); +template<typename T> +bool Reading(T &output, TLVObject &data); + +template<> +bool Writing(const int32_t &input, TLVObject &data); +template<> +bool Reading(int32_t &output, TLVObject &data); + +template<> +bool Writing(const int64_t &input, TLVObject &data); +template<> +bool Reading(int64_t &output, TLVObject &data); + +template<> +bool Writing(const bool &input, TLVObject &data); +template<> +bool Reading(bool &output, TLVObject &data); + +template<> +bool Reading(uint32_t &output, TLVObject &data); + +template<> +bool Writing(const uint32_t &input, TLVObject &data); + +template<> +bool Reading(uint64_t &output, TLVObject &data); + +template<> +bool Writing(const uint64_t &input, TLVObject &data); + +template<> +bool Writing(const std::string &input, TLVObject &data); +template<> +bool Reading(std::string &output, TLVObject &data); + +template<> +bool Writing(const std::vector<uint8_t> &input, TLVObject &data); +template<> +bool Reading(std::vector<uint8_t> &output, TLVObject &data); + +template<> +bool Writing(const UDVariant &input, TLVObject &data); +template<> +bool Reading(UDVariant &output, TLVObject &data); + +template<> +bool Writing(const UDDetails &input, TLVObject &data); +template<> +bool Reading(UDDetails &output, TLVObject &data); + +template<> +bool Writing(const UDType &input, TLVObject &data); +template<> +bool Reading(UDType &output, TLVObject &data); + +template<> +bool Writing(const Text &input, TLVObject &data); +template<> +bool Reading(Text &output, TLVObject &data); + +template<> +bool Writing(const PlainText &input, TLVObject &data); +template<> +bool Reading(PlainText &output, TLVObject &data); + +template<> +bool Writing(const Html &input, TLVObject &data); +template<> +bool Reading(Html &output, TLVObject &data); + +template<> +bool Writing(const Link &input, TLVObject &data); +template<> +bool Reading(Link &output, TLVObject &data); + +template<> +bool Writing(const File &input, TLVObject &data); +template<> +bool Reading(File &output, TLVObject &data); + +template<> +bool Writing(const Image &input, TLVObject &data); +template<> +bool Reading(Image &output, TLVObject &data); + +template<> +bool Writing(const Video &input, TLVObject &data); +template<> +bool Reading(Video &output, TLVObject &data); + +template<> +bool Writing(const Audio &input, TLVObject &data); +template<> +bool Reading(Audio &output, TLVObject &data); + +template<> +bool Writing(const Folder &input, TLVObject &data); +template<> +bool Reading(Folder &output, TLVObject &data); + +template<> +bool Writing(const SystemDefinedRecord &input, TLVObject &data); +template<> +bool Reading(SystemDefinedRecord &output, TLVObject &data); + +template<> +bool Writing(const SystemDefinedForm &input, TLVObject &data); +template<> +bool Reading(SystemDefinedForm &output, TLVObject &data); + +template<> +bool Writing(const SystemDefinedAppItem &input, TLVObject &data); +template<> +bool Reading(SystemDefinedAppItem &output, TLVObject &data); + +template<> +bool Writing(const SystemDefinedPixelMap &input, TLVObject &data); +template<> +bool Reading(SystemDefinedPixelMap &output, TLVObject &data); + +template<> +bool Writing(const ApplicationDefinedRecord &input, TLVObject &data); +template<> +bool Reading(ApplicationDefinedRecord &output, TLVObject &data); + +template<> +bool Writing(const std::shared_ptr<UnifiedRecord> &input, TLVObject &data); +template<> +bool Reading(std::shared_ptr<UnifiedRecord> &output, TLVObject &data); + +template<> +bool Writing(const UnifiedData &input, TLVObject &data); +template<> +bool Reading(UnifiedData &output, TLVObject &data); + +template<> +bool Writing(const std::vector<UnifiedData> &input, TLVObject &data); +template<> +bool Reading(std::vector<UnifiedData> &output, TLVObject &data); + +template<> +bool Writing(const UnifiedKey &input, TLVObject &data); +template<> +bool Reading(UnifiedKey &output, TLVObject &data); + +template<> +bool Writing(const Privilege &input, TLVObject &data); +template<> +bool Reading(Privilege &output, TLVObject &data); + +template<> +bool Writing(const DataStatus &input, TLVObject &data); +template<> +bool Reading(DataStatus &output, TLVObject &data); + +template<> +bool Writing(const Runtime &input, TLVObject &data); +template<> +bool Reading(Runtime &output, TLVObject &data); +} // namespace TLVUtil +} // namespace OHOS +#endif // UDMF_TLV_UTIL_H \ No newline at end of file diff --git a/udmf/framework/common/udmf_types_util.cpp b/udmf/framework/common/udmf_types_util.cpp new file mode 100644 index 0000000000000000000000000000000000000000..261eb14300ce7e51d0e2f590392f2d9feab80222 --- /dev/null +++ b/udmf/framework/common/udmf_types_util.cpp @@ -0,0 +1,198 @@ +/* + * 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 "udmf_types_util.h" + +#include <string> + +#include "logger.h" +#include "tlv_util.h" + +namespace OHOS { +namespace ITypesUtil { +using namespace UDMF; +template<> +bool Marshalling(const UnifiedData &input, MessageParcel &parcel) +{ + std::vector<uint8_t> dataBytes; + auto recordTlv = TLVObject(dataBytes); + if (!TLVUtil::Writing(input, recordTlv)) { + LOG_ERROR(UDMF_SERVICE, "TLV writing failed!"); + return false; + } + if (!parcel.WriteInt32(static_cast<int32_t>(dataBytes.size())) + || !parcel.WriteRawData(dataBytes.data(), dataBytes.size())) { + LOG_ERROR(UDMF_SERVICE, "Marshall unified data failed!"); + return false; + } + return true; +} + +template<> +bool Unmarshalling(UnifiedData &output, MessageParcel &parcel) +{ + auto size = parcel.ReadInt32(); + if (size == 0) { + LOG_ERROR(UDMF_SERVICE, "UnifiedData is empty!"); + return false; + } + const uint8_t *rawData = reinterpret_cast<const uint8_t *>(parcel.ReadRawData(size)); + if (rawData == nullptr) { + LOG_ERROR(UDMF_SERVICE, "RawData is null!"); + return false; + } + std::vector<uint8_t> dataBytes(rawData, rawData + size); + auto recordTlv = TLVObject(dataBytes); + if (!TLVUtil::Reading(output, recordTlv)) { + LOG_ERROR(UDMF_SERVICE, "Unmarshall unified data failed!"); + return false; + } + return true; +} + +template<> +bool Marshalling(const std::vector<UnifiedData> &input, MessageParcel &parcel) +{ + std::vector<uint8_t> dataSetBytes; + auto recordTlv = TLVObject(dataSetBytes); + if (!TLVUtil::Writing(input, recordTlv)) { + LOG_ERROR(UDMF_SERVICE, "TLV writing failed!"); + return false; + } + if (!parcel.WriteInt32(static_cast<int32_t>(dataSetBytes.size())) + || !parcel.WriteRawData(dataSetBytes.data(), dataSetBytes.size())) { + LOG_ERROR(UDMF_SERVICE, "Marshall unified data set failed!"); + return false; + } + return true; +} + +template<> +bool Unmarshalling(std::vector<UnifiedData> &output, MessageParcel &parcel) +{ + auto size = parcel.ReadInt32(); + if (size == 0) { + LOG_ERROR(UDMF_SERVICE, "UnifiedDataSet is empty!"); + return false; + } + const uint8_t *rawData = reinterpret_cast<const uint8_t *>(parcel.ReadRawData(size)); + if (rawData == nullptr) { + LOG_ERROR(UDMF_SERVICE, "RawData is null!"); + return false; + } + std::vector<uint8_t> dataSetBytes(rawData, rawData + size); + auto recordTlv = TLVObject(dataSetBytes); + if (!TLVUtil::Reading(output, recordTlv)) { + LOG_ERROR(UDMF_SERVICE, "Unmarshall unified data set failed!"); + return false; + } + return true; +} + +template<> +bool Marshalling(const Summary &input, MessageParcel &parcel) +{ + return ITypesUtil::Marshal(parcel, input.summary, input.totalSize); +} + +template<> +bool Unmarshalling(Summary &output, MessageParcel &parcel) +{ + return ITypesUtil::Unmarshal(parcel, output.summary, output.totalSize); +} + +template<> +bool Marshalling(const Privilege &input, MessageParcel &parcel) +{ + return ITypesUtil::Marshal(parcel, input.tokenId, input.readPermission, input.writePermission); +} + +template<> +bool Unmarshalling(Privilege &output, MessageParcel &parcel) +{ + return ITypesUtil::Unmarshal(parcel, output.tokenId, output.readPermission, output.writePermission); +} + +template<> +bool Marshalling(const CustomOption &input, MessageParcel &parcel) +{ + return ITypesUtil::Marshal(parcel, input.intention); +} + +template<> +bool Unmarshalling(CustomOption &output, MessageParcel &parcel) +{ + return ITypesUtil::Unmarshal(parcel, output.intention); +} + +template<> +bool Marshalling(const QueryOption &input, MessageParcel &parcel) +{ + return ITypesUtil::Marshal(parcel, input.key, input.intention); +} + +template<> +bool Unmarshalling(QueryOption &output, MessageParcel &parcel) +{ + return ITypesUtil::Unmarshal(parcel, output.key, output.intention); +} + +template<> +bool Marshalling(const UDType &input, MessageParcel &parcel) +{ + int32_t type = input; + return ITypesUtil::Marshal(parcel, type); +} + +template<> +bool Unmarshalling(UDType &output, MessageParcel &parcel) +{ + int32_t type; + if (!ITypesUtil::Unmarshal(parcel, type)) { + LOG_ERROR(UDMF_FRAMEWORK, "Unmarshal UDType failed!"); + return false; + } + if (type < TEXT || type >= UD_BUTT) { + LOG_ERROR(UDMF_FRAMEWORK, "invalid UDType!"); + return false; + } + output = static_cast<UDType>(type); + return true; +} + +template<> +bool Marshalling(const Intention &input, MessageParcel &parcel) +{ + int32_t intention = input; + return ITypesUtil::Marshal(parcel, intention); +} + +template<> +bool Unmarshalling(Intention &output, MessageParcel &parcel) +{ + int32_t intention; + if (!ITypesUtil::Unmarshal(parcel, intention)) { + LOG_ERROR(UDMF_FRAMEWORK, "Unmarshal Intention failed!"); + return false; + } + if (intention < UD_INTENTION_BASE || intention > UD_INTENTION_BUTT) { + LOG_ERROR(UDMF_FRAMEWORK, "invalid Intention!"); + return false; + } + output = static_cast<Intention>(intention); + return true; +} +} // namespace ITypesUtil +} // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/common/udmf_types_util.h b/udmf/framework/common/udmf_types_util.h new file mode 100644 index 0000000000000000000000000000000000000000..53f181ccf912e910254f6d8e717b1ce4bc2ef408 --- /dev/null +++ b/udmf/framework/common/udmf_types_util.h @@ -0,0 +1,76 @@ +/* + * 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 UDMF_TYPES_UTIL_H +#define UDMF_TYPES_UTIL_H + +#include "itypes_util.h" + +#include "unified_data.h" +#include "unified_meta.h" +#include "unified_types.h" + +namespace OHOS { +namespace ITypesUtil { +using UnifiedData = UDMF::UnifiedData; +using Summary = UDMF::Summary; +using Privilege = UDMF::Privilege; +using CustomOption = UDMF::CustomOption; +using QueryOption = UDMF::QueryOption; +using UDType = UDMF::UDType; +using Intention = UDMF::Intention; + +template<> +bool Marshalling(const UnifiedData &input, MessageParcel &parcel); +template<> +bool Unmarshalling(UnifiedData &output, MessageParcel &parcel); + +template<> +bool Marshalling(const std::vector<UnifiedData> &input, MessageParcel &parcel); +template<> +bool Unmarshalling(std::vector<UnifiedData> &output, MessageParcel &parcel); + +template<> +bool Marshalling(const Summary &input, MessageParcel &parcel); +template<> +bool Unmarshalling(Summary &output, MessageParcel &parcel); + +template<> +bool Marshalling(const Privilege &input, MessageParcel &parcel); +template<> +bool Unmarshalling(Privilege &output, MessageParcel &parcel); + +template<> +bool Marshalling(const CustomOption &input, MessageParcel &parcel); +template<> +bool Unmarshalling(CustomOption &output, MessageParcel &parcel); + +template<> +bool Marshalling(const QueryOption &input, MessageParcel &parcel); +template<> +bool Unmarshalling(QueryOption &output, MessageParcel &parcel); + +template<> +bool Marshalling(const UDType &input, MessageParcel &parcel); +template<> +bool Unmarshalling(UDType &output, MessageParcel &parcel); + +template<> +bool Marshalling(const Intention &input, MessageParcel &parcel); +template<> +bool Unmarshalling(Intention &output, MessageParcel &parcel); +} // namespace ITypesUtil +} // namespace OHOS +#endif // UDMF_TYPES_UTIL_H \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/client/udmf_client.cpp b/udmf/framework/innerkitsimpl/client/udmf_client.cpp new file mode 100644 index 0000000000000000000000000000000000000000..91dab5cfed6443003ee6794576f5586eb670bb36 --- /dev/null +++ b/udmf/framework/innerkitsimpl/client/udmf_client.cpp @@ -0,0 +1,162 @@ +/* + * 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 "udmf_client.h" + +#include "dds_trace.h" + +#include "error_code.h" +#include "logger.h" +#include "udmf_service_client.h" + +namespace OHOS { +namespace UDMF { +const std::string TAG = "UdmfClient::"; +using namespace OHOS::DistributedDataDfx; +UdmfClient &UdmfClient::GetInstance() +{ + static auto instance_ = new UdmfClient(); + return *instance_; +} + +Status UdmfClient::SetData(CustomOption &option, UnifiedData &unifiedData, std::string &key) +{ + DdsTrace trace( + std::string(TAG) + std::string(__FUNCTION__), TraceSwitch::BYTRACE_ON | TraceSwitch::TRACE_CHAIN_ON); + auto service = UdmfServiceClient::GetInstance(); + if (service == nullptr) { + LOG_ERROR(UDMF_CLIENT, "Service unavailable"); + return E_IPC; + } + int32_t ret = service->SetData(option, unifiedData, key); + if (ret != E_OK) { + LOG_ERROR(UDMF_CLIENT, "failed! ret = %{public}d", ret); + } + return static_cast<Status>(ret); +} + +Status UdmfClient::GetData(const QueryOption &query, UnifiedData &unifiedData) +{ + DdsTrace trace( + std::string(TAG) + std::string(__FUNCTION__), TraceSwitch::BYTRACE_ON | TraceSwitch::TRACE_CHAIN_ON); + auto service = UdmfServiceClient::GetInstance(); + if (service == nullptr) { + LOG_ERROR(UDMF_CLIENT, "Service unavailable"); + return E_IPC; + } + int32_t ret = service->GetData(query, unifiedData); + if (ret != E_OK) { + LOG_ERROR(UDMF_CLIENT, "failed! ret = %{public}d", ret); + } + return static_cast<Status>(ret); +} + +Status UdmfClient::GetBatchData(const QueryOption &query, std::vector<UnifiedData> &unifiedDataSet) +{ + DdsTrace trace( + std::string(TAG) + std::string(__FUNCTION__), TraceSwitch::BYTRACE_ON | TraceSwitch::TRACE_CHAIN_ON); + auto service = UdmfServiceClient::GetInstance(); + if (service == nullptr) { + LOG_ERROR(UDMF_CLIENT, "Service unavailable"); + return E_IPC; + } + int32_t ret = service->GetBatchData(query, unifiedDataSet); + if (ret != E_OK) { + LOG_ERROR(UDMF_CLIENT, "failed! ret = %{public}d", ret); + } + return static_cast<Status>(ret); +} + +Status UdmfClient::UpdateData(const QueryOption &query, UnifiedData &unifiedData) +{ + DdsTrace trace( + std::string(TAG) + std::string(__FUNCTION__), TraceSwitch::BYTRACE_ON | TraceSwitch::TRACE_CHAIN_ON); + auto service = UdmfServiceClient::GetInstance(); + if (service == nullptr) { + LOG_ERROR(UDMF_CLIENT, "Service unavailable"); + return E_IPC; + } + int32_t ret = service->UpdateData(query, unifiedData); + if (ret != E_OK) { + LOG_ERROR(UDMF_CLIENT, "failed! ret = %{public}d", ret); + } + return static_cast<Status>(ret); +} + +Status UdmfClient::DeleteData(const QueryOption &query, std::vector<UnifiedData> &unifiedDataSet) +{ + DdsTrace trace( + std::string(TAG) + std::string(__FUNCTION__), TraceSwitch::BYTRACE_ON | TraceSwitch::TRACE_CHAIN_ON); + auto service = UdmfServiceClient::GetInstance(); + if (service == nullptr) { + LOG_ERROR(UDMF_CLIENT, "Service unavailable"); + return E_IPC; + } + int32_t ret = service->DeleteData(query, unifiedDataSet); + if (ret != E_OK) { + LOG_ERROR(UDMF_CLIENT, "failed! ret = %{public}d", ret); + } + return static_cast<Status>(ret); +} + +Status UdmfClient::GetSummary(const QueryOption &query, Summary &summary) +{ + DdsTrace trace( + std::string(TAG) + std::string(__FUNCTION__), TraceSwitch::BYTRACE_ON | TraceSwitch::TRACE_CHAIN_ON); + auto service = UdmfServiceClient::GetInstance(); + if (service == nullptr) { + LOG_ERROR(UDMF_CLIENT, "Service unavailable"); + return E_IPC; + } + int32_t ret = service->GetSummary(query, summary); + if (ret != E_OK) { + LOG_ERROR(UDMF_CLIENT, "failed! ret = %{public}d", ret); + } + return static_cast<Status>(ret); +} + +Status UdmfClient::AddPrivilege(const QueryOption &query, Privilege &privilege) +{ + DdsTrace trace( + std::string(TAG) + std::string(__FUNCTION__), TraceSwitch::BYTRACE_ON | TraceSwitch::TRACE_CHAIN_ON); + auto service = UdmfServiceClient::GetInstance(); + if (service == nullptr) { + LOG_ERROR(UDMF_CLIENT, "Service unavailable"); + return E_IPC; + } + int32_t ret = service->AddPrivilege(query, privilege); + if (ret != E_OK) { + LOG_ERROR(UDMF_CLIENT, "failed! ret = %{public}d", ret); + } + return static_cast<Status>(ret); +} + +Status UdmfClient::Sync(const QueryOption &query, const std::vector<std::string> &devices) +{ + DdsTrace trace( + std::string(TAG) + std::string(__FUNCTION__), TraceSwitch::BYTRACE_ON | TraceSwitch::TRACE_CHAIN_ON); + auto service = UdmfServiceClient::GetInstance(); + if (service == nullptr) { + LOG_ERROR(UDMF_CLIENT, "Service unavailable"); + return E_IPC; + } + int32_t ret = service->Sync(query, devices); + if (ret != E_OK) { + LOG_ERROR(UDMF_CLIENT, "failed! ret = %{public}d", ret); + } + return static_cast<Status>(ret); +} +} // namespace UDMF +} // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/common/unified_key.cpp b/udmf/framework/innerkitsimpl/common/unified_key.cpp new file mode 100644 index 0000000000000000000000000000000000000000..03abf4bd6904dd6cd018bbe223bbd2d46d5a2ecc --- /dev/null +++ b/udmf/framework/innerkitsimpl/common/unified_key.cpp @@ -0,0 +1,152 @@ +/* + * 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 "unified_key.h" + +#include "logger.h" + +namespace OHOS { +namespace UDMF { +static std::bitset<MAX_BIT_SIZE> g_ruleIntention; +static std::bitset<MAX_BIT_SIZE> g_ruleBundleName; +static std::bitset<MAX_BIT_SIZE> g_ruleGroupId; +static const std::string UNIFIED_KEY_SCHEMA = "udmf://"; +static const std::string ALPHA_AGGREGATE = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; +static const std::string DIGIT_AGGREGATE = "0123456789"; +static const std::string SYMBOL_AGGREGATE = ":;<=>?@[\\]_`"; +UnifiedKey::UnifiedKey(std::string key) +{ + this->key = std::move(key); +} + +UnifiedKey::UnifiedKey(std::string intention, std::string bundle, std::string groupId) +{ + this->intention = std::move(intention); + this->bundleName = std::move(bundle); + this->groupId = std::move(groupId); +} + +std::string UnifiedKey::GetUnifiedKey() +{ + if (!this->key.empty()) { + return this->key; + } + if (this->intention.empty() || this->groupId.empty()) { + return ""; + } + // Uri-compliant structure, example: udmf://drag/com.ohos.test/012345679abc + this->key = UNIFIED_KEY_SCHEMA + this->intention + "/" + this->bundleName + "/" + this->groupId; + return this->key; +} + +bool UnifiedKey::IsValid() +{ + if (this->key.empty()) { + LOG_DEBUG(UDMF_FRAMEWORK, "empty key"); + return false; + } + PreliminaryWork(); + + std::string data = this->key; // schema/intention/groupId + std::string separator = "://"; + size_t pos = data.find(separator); + if (pos == std::string::npos) { + return false; + } + std::string schema = data.substr(0, pos + separator.size()); // schema + if (UNIFIED_KEY_SCHEMA != schema) { + LOG_DEBUG(UDMF_FRAMEWORK, "wrong schema"); + return false; + } + + data = data.substr(pos + separator.size()); // intention/bundleName/groupId + pos = data.find('/'); // intention + if (pos == std::string::npos) { + return false; + } + std::string intentionTmp = data.substr(0, pos); + if (!CheckCharacter(intentionTmp, g_ruleIntention)) { + return false; + } + this->intention = intentionTmp; + + data = data.substr(pos + 1); + pos = data.find('/'); // bundleName + if (pos == std::string::npos) { + return false; + } + std::string bundle = data.substr(0, pos); + if (!CheckCharacter(bundle, g_ruleBundleName)) { + LOG_DEBUG(UDMF_FRAMEWORK, "wrong bundle"); + return false; + } + this->bundleName = bundle; + + data = data.substr(pos + 1); // groupId + if (data.empty()) { + return false; + } + if (!CheckCharacter(data, g_ruleGroupId)) { + LOG_DEBUG(UDMF_FRAMEWORK, "wrong groupId"); + return false; + } + this->groupId = data; + return true; +} + +bool UnifiedKey::CheckCharacter(std::string data, std::bitset<MAX_BIT_SIZE> rule) +{ + if (data.empty()) { + LOG_DEBUG(UDMF_FRAMEWORK, "empty key"); + return false; + } + size_t dataLen = data.size(); + for (size_t i = 0; i < dataLen; ++i) { + if (static_cast<int>(data[i]) >= 0 && static_cast<int>(data[i]) < 128) { // 128:ASCII Max Number + bool isLegal = rule.test(data[i]); + if (!isLegal) { + return false; + } + } + } + return true; +} + +void UnifiedKey::PreliminaryWork() +{ + // All intentions are composed of uppercase and lowercase letters and underscores. + if (g_ruleIntention.none()) { + std::string intentionTmp = ALPHA_AGGREGATE + "_"; + for (char i : intentionTmp) { + g_ruleIntention.set(i); + } + } + // All bundle name are composed of uppercase and lowercase letters and dots. + if (g_ruleBundleName.none()) { + std::string bundleAggregate = ALPHA_AGGREGATE + DIGIT_AGGREGATE + "._"; + for (char i : bundleAggregate) { + g_ruleBundleName.set(i); + } + } + // Characters of groupId are taken from Ascii codes 48 to 122. + if (g_ruleGroupId.none()) { + std::string idAggregate = DIGIT_AGGREGATE + ALPHA_AGGREGATE + SYMBOL_AGGREGATE; + for (char i : idAggregate) { + g_ruleGroupId.set(i); + } + } +} +} // namespace UDMF +} // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/common/unified_meta.cpp b/udmf/framework/innerkitsimpl/common/unified_meta.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6bad218c5444fa15e35a8992da1cc018135608a2 --- /dev/null +++ b/udmf/framework/innerkitsimpl/common/unified_meta.cpp @@ -0,0 +1,108 @@ +/* + * 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 "unified_meta.h" + +#include "unified_key.h" + +namespace OHOS { +namespace UDMF { +bool UnifiedDataUtils::IsValidType(int32_t value) +{ + return value >= TEXT && value < UD_BUTT; +} + +bool UnifiedDataUtils::IsValidIntention(int32_t value) +{ + return value > UD_INTENTION_BASE && value < UD_INTENTION_BUTT; +} + +size_t UnifiedDataUtils::GetVariantSize(UDVariant &variant) +{ + auto int32Value = std::get_if<int32_t>(&variant); + if (int32Value != nullptr) { + return sizeof(std::get<int32_t>(variant)); + } + auto int64Value = std::get_if<int64_t>(&variant); + if (int64Value != nullptr) { + return sizeof(std::get<int64_t>(variant)); + } + auto boolValue = std::get_if<bool>(&variant); + if (boolValue != nullptr) { + return sizeof(std::get<bool>(variant)); + } + auto doubleValue = std::get_if<double>(&variant); + if (doubleValue != nullptr) { + return sizeof(std::get<double>(variant)); + } + auto strValue = std::get_if<std::string>(&variant); + if (strValue != nullptr) { + return std::get<std::string>(variant).size(); + } + auto vecValue = std::get_if<std::vector<uint8_t>>(&variant); + if (vecValue != nullptr) { + return std::get<std::vector<uint8_t>>(variant).size(); + } + return 0; +} + +size_t UnifiedDataUtils::GetDetailsSize(UDDetails &details) +{ + size_t total = 0; + for (std::pair<std::string, UDVariant> prop : details) { + total += prop.first.size(); + total += GetVariantSize(prop.second); + } + return total; +} + +bool UnifiedDataUtils::IsPersist(const Intention &intention) +{ + return intention >= UD_INTENTION_DATA_HUB && intention < UD_INTENTION_BUTT; +} + +bool UnifiedDataUtils::IsPersist(const std::string &intention) +{ + return IsPersist(GetIntentionByString(intention)); +} + +Intention UnifiedDataUtils::GetIntentionByString(const std::string &intention) +{ + for (const auto &it : UD_INTENTION_MAP) { + if (it.second == intention) { + return static_cast<Intention>(it.first); + } + } + return UD_INTENTION_BUTT; +} + +bool UnifiedDataUtils::IsValidOptions(const std::string &key, std::string &intention) +{ + UnifiedKey unifiedKey(key); + auto isValidKey = unifiedKey.IsValid(); + if (key.empty() && IsPersist(intention)) { + return true; + } + if (intention.empty() && isValidKey && IsPersist(unifiedKey.intention)) { + return true; + } + if (isValidKey && unifiedKey.intention == intention && IsPersist(intention)) { + intention = ""; + return true; + } + return false; +} +} // namespace UDMF +} // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/data/application_defined_record.cpp b/udmf/framework/innerkitsimpl/data/application_defined_record.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cc6c8c0427d2a970c62fed6141f2c5acddaa3836 --- /dev/null +++ b/udmf/framework/innerkitsimpl/data/application_defined_record.cpp @@ -0,0 +1,61 @@ +/* + * 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 "application_defined_record.h" + +namespace OHOS { +namespace UDMF { +ApplicationDefinedRecord::ApplicationDefinedRecord() : UnifiedRecord(APPLICATION_DEFINED_RECORD) +{ +} + +ApplicationDefinedRecord::ApplicationDefinedRecord(std::string type) : UnifiedRecord(APPLICATION_DEFINED_RECORD) +{ + this->applicationDefinedType = std::move(type); +} + +ApplicationDefinedRecord::ApplicationDefinedRecord(std::string type, std::vector<uint8_t> &data) + : UnifiedRecord(APPLICATION_DEFINED_RECORD) +{ + this->applicationDefinedType = std::move(type); + this->rawData_ = std::move(data); +} + +int64_t ApplicationDefinedRecord::GetSize() +{ + return rawData_.size(); +} + +std::string ApplicationDefinedRecord::GetApplicationDefinedType() const +{ + return this->applicationDefinedType; +} + +void ApplicationDefinedRecord::SetApplicationDefinedType(const std::string &type) +{ + this->applicationDefinedType = type; +} + +std::vector<uint8_t> ApplicationDefinedRecord::GetRawData() const +{ + return this->rawData_; +} + +void ApplicationDefinedRecord::SetRawData(const std::vector<uint8_t> &rawData) +{ + this->rawData_ = rawData; +} +} // namespace UDMF +} // namespace OHOS diff --git a/udmf/framework/innerkitsimpl/data/audio.cpp b/udmf/framework/innerkitsimpl/data/audio.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9f6a1baeaf3987e523af632f310054f454bdb834 --- /dev/null +++ b/udmf/framework/innerkitsimpl/data/audio.cpp @@ -0,0 +1,29 @@ +/* + * 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 "audio.h" + +namespace OHOS { +namespace UDMF { +Audio::Audio() : Audio("") +{ +} + +Audio::Audio(const std::string &uri) : File(uri) +{ + this->dataType_ = AUDIO; +} +} // namespace UDMF +} // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/data/file.cpp b/udmf/framework/innerkitsimpl/data/file.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0502b503bb3fec4b18043f277d2485f8675f3ef5 --- /dev/null +++ b/udmf/framework/innerkitsimpl/data/file.cpp @@ -0,0 +1,64 @@ +/* + * 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 "file.h" + +namespace OHOS { +namespace UDMF { +File::File() : UnifiedRecord(FILE) +{ +} + +File::File(const std::string &uri) : UnifiedRecord(FILE) +{ + this->oriUri_ = uri; +} + +int64_t File::GetSize() +{ + return this->oriUri_.size() + this->remoteUri_.size(); +} + +std::string File::GetUri() const +{ + return this->oriUri_; +} + +void File::SetUri(const std::string &uri) +{ + this->oriUri_ = uri; +} + +std::string File::GetRemoteUri() const +{ + return this->remoteUri_; +} + +void File::SetRemoteUri(const std::string &uri) +{ + this->remoteUri_ = uri; +} + +void File::SetDetails(UDDetails &variantMap) +{ + this->details_ = variantMap; +} + +UDDetails File::GetDetails() const +{ + return this->details_; +} +} // namespace UDMF +} // namespace OHOS diff --git a/udmf/framework/innerkitsimpl/data/folder.cpp b/udmf/framework/innerkitsimpl/data/folder.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6961eb665a1a16d7fe9fef81ff46c2680e14fd0e --- /dev/null +++ b/udmf/framework/innerkitsimpl/data/folder.cpp @@ -0,0 +1,29 @@ +/* + * 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 "folder.h" + +namespace OHOS { +namespace UDMF { +Folder::Folder() : Folder("") +{ +} + +Folder::Folder(const std::string &uri) : File(uri) +{ + this->dataType_ = FOLDER; +} +} // namespace UDMF +} // namespace OHOS diff --git a/udmf/framework/innerkitsimpl/data/html.cpp b/udmf/framework/innerkitsimpl/data/html.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8bc129be7d6776536a7f98e832744836af7be393 --- /dev/null +++ b/udmf/framework/innerkitsimpl/data/html.cpp @@ -0,0 +1,66 @@ +/* + * 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 "html.h" + +namespace OHOS { +namespace UDMF { +Html::Html() +{ + this->dataType_ = HTML; +} + +Html::Html(const std::string &htmlContent, const std::string &plainContent) +{ + if (plainContent.length() >= MAX_TEXT_LEN || htmlContent.length() >= MAX_TEXT_LEN) { + return; + } + this->dataType_ = HTML; + this->htmlContent_ = htmlContent; + this->plainContent_ = plainContent; +} + +int64_t Html::GetSize() +{ + return UnifiedDataUtils::GetDetailsSize(this->details_) + this->htmlContent_.size() + this->plainContent_.size(); +} + +std::string Html::GetHtmlContent() const +{ + return this->htmlContent_; +} + +void Html::SetHtmlContent(const std::string &htmlContent) +{ + if (htmlContent.length() >= MAX_TEXT_LEN) { + return; + } + this->htmlContent_ = htmlContent; +} + +std::string Html::GetPlainContent() const +{ + return this->plainContent_; +} + +void Html::SetPlainContent(const std::string &plainContent) +{ + if (plainContent.length() >= MAX_TEXT_LEN) { + return; + } + this->plainContent_ = plainContent; +} +} // namespace UDMF +} // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/data/image.cpp b/udmf/framework/innerkitsimpl/data/image.cpp new file mode 100644 index 0000000000000000000000000000000000000000..dce12163424f3757632eb5ac85a000133a71278c --- /dev/null +++ b/udmf/framework/innerkitsimpl/data/image.cpp @@ -0,0 +1,29 @@ +/* + * 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 "image.h" + +namespace OHOS { +namespace UDMF { +Image::Image() : Image("") +{ +} + +Image::Image(const std::string &uri) : File(uri) +{ + this->dataType_ = IMAGE; +} +} // namespace UDMF +} // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/data/link.cpp b/udmf/framework/innerkitsimpl/data/link.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6ab4f99455299c3c5bb6721b4956f94aaf292156 --- /dev/null +++ b/udmf/framework/innerkitsimpl/data/link.cpp @@ -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. + */ + +#include "link.h" + +namespace OHOS { +namespace UDMF { +Link::Link() : Link("", "") +{ +} + +Link::Link(const std::string &url) : Link(url, "") +{ +} + +Link::Link(const std::string &url, const std::string &description) +{ + if (url.length() >= MAX_TEXT_LEN || description.length() >= MAX_TEXT_LEN) { + return; + } + this->dataType_ = HYPERLINK; + this->url_ = url; + this->description_ = description; +} + +int64_t Link::GetSize() +{ + return UnifiedDataUtils::GetDetailsSize(this->details_) + this->url_.size() + this->description_.size(); +} + +std::string Link::GetUrl() const +{ + return this->url_; +} + +void Link::SetUrl(const std::string &url) +{ + if (url.length() >= MAX_TEXT_LEN) { + return; + } + this->url_ = url; +} + +std::string Link::GetDescription() const +{ + return this->description_; +} + +void Link::SetDescription(const std::string &description) +{ + if (description.length() >= MAX_TEXT_LEN) { + return; + } + this->description_ = description; +} +} // namespace UDMF +} // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/data/plain_text.cpp b/udmf/framework/innerkitsimpl/data/plain_text.cpp new file mode 100644 index 0000000000000000000000000000000000000000..99167635b0b7ec54393942deda216852f8656db5 --- /dev/null +++ b/udmf/framework/innerkitsimpl/data/plain_text.cpp @@ -0,0 +1,65 @@ +/* + * 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 "plain_text.h" + +namespace OHOS { +namespace UDMF { +PlainText::PlainText() : PlainText("", "") +{ +} + +PlainText::PlainText(const std::string &content, const std::string &abstract) +{ + if (content.length() >= MAX_TEXT_LEN) { + return; + } + this->dataType_ = PLAIN_TEXT; + this->content_ = content; + this->abstract_ = abstract; +} + +int64_t PlainText::GetSize() +{ + return UnifiedDataUtils::GetDetailsSize(this->details_) + this->content_.size() + this->abstract_.size(); +} + +std::string PlainText::GetContent() const +{ + return this->content_; +} + +void PlainText::SetContent(const std::string &text) +{ + if (text.length() >= MAX_TEXT_LEN) { + return; + } + this->content_ = text; +} + +std::string PlainText::GetAbstract() const +{ + return this->abstract_; +} + +void PlainText::SetAbstract(const std::string &abstract) +{ + if (abstract.length() >= MAX_TEXT_LEN) { + return; + } + this->abstract_ = abstract; +} +} // namespace UDMF +} // namespace OHOS diff --git a/udmf/framework/innerkitsimpl/data/system_defined_appitem.cpp b/udmf/framework/innerkitsimpl/data/system_defined_appitem.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d9f18a3fbc1fcf7c608272459e743123cc041567 --- /dev/null +++ b/udmf/framework/innerkitsimpl/data/system_defined_appitem.cpp @@ -0,0 +1,91 @@ +/* + * 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 "system_defined_appitem.h" + +namespace OHOS { +namespace UDMF { +SystemDefinedAppItem::SystemDefinedAppItem() +{ + this->dataType_ = SYSTEM_DEFINED_APP_ITEM; +} + +int64_t SystemDefinedAppItem::GetSize() +{ + return UnifiedDataUtils::GetDetailsSize(this->details_) + this->appId_.size() + this->appName_.size() + + this->appIconId_.size() + this->appLabelId_.size() + this->bundleName_.size() + this->abilityName_.size(); +} + +std::string SystemDefinedAppItem::GetAppId() const +{ + return this->appId_; +} + +void SystemDefinedAppItem::SetAppId(const std::string &appId) +{ + this->appId_ = appId; +} + +std::string SystemDefinedAppItem::GetAppName() const +{ + return this->appName_; +} + +void SystemDefinedAppItem::SetAppName(const std::string &appName) +{ + this->appName_ = appName; +} + +std::string SystemDefinedAppItem::GetAppIconId() const +{ + return this->appIconId_; +} + +void SystemDefinedAppItem::SetAppIconId(const std::string &appIconId) +{ + this->appIconId_ = appIconId; +} + +std::string SystemDefinedAppItem::GetAppLabelId() const +{ + return this->appLabelId_; +} + +void SystemDefinedAppItem::SetAppLabelId(const std::string &appLabelId) +{ + this->appLabelId_ = appLabelId; +} + +std::string SystemDefinedAppItem::GetBundleName() const +{ + return this->bundleName_; +} + +void SystemDefinedAppItem::SetBundleName(const std::string &bundleName) +{ + this->bundleName_ = bundleName; +} + +std::string SystemDefinedAppItem::GetAbilityName() const +{ + return this->abilityName_; +} + +void SystemDefinedAppItem::SetAbilityName(const std::string &abilityName) +{ + this->abilityName_ = abilityName; +} +} // namespace UDMF +} // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/data/system_defined_form.cpp b/udmf/framework/innerkitsimpl/data/system_defined_form.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7714a3296e0da81595c726ffe4b138b8b438a5fd --- /dev/null +++ b/udmf/framework/innerkitsimpl/data/system_defined_form.cpp @@ -0,0 +1,81 @@ +/* + * 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 "system_defined_form.h" + +namespace OHOS { +namespace UDMF { +SystemDefinedForm::SystemDefinedForm() +{ + this->dataType_ = SYSTEM_DEFINED_FORM; +} + +int64_t SystemDefinedForm::GetSize() +{ + return UnifiedDataUtils::GetDetailsSize(this->details_) + sizeof(formId_) + this->formName_.size() + + this->bundleName_.size() + this->abilityName_.size() + this->module_.size(); +} + +int32_t SystemDefinedForm::GetFormId() const +{ + return this->formId_; +} + +void SystemDefinedForm::SetFormId(const int32_t &formId) +{ + this->formId_ = formId; +} + +std::string SystemDefinedForm::GetFormName() const +{ + return this->formName_; +} + +void SystemDefinedForm::SetFormName(const std::string &formName) +{ + this->formName_ = formName; +} + +std::string SystemDefinedForm::GetBundleName() const +{ + return this->bundleName_; +} + +void SystemDefinedForm::SetBundleName(const std::string &bundleName) +{ + this->bundleName_ = bundleName; +} + +std::string SystemDefinedForm::GetAbilityName() const +{ + return this->abilityName_; +} + +void SystemDefinedForm::SetAbilityName(const std::string &abilityName) +{ + this->abilityName_ = abilityName; +} + +std::string SystemDefinedForm::GetModule() const +{ + return this->module_; +} + +void SystemDefinedForm::SetModule(const std::string &module) +{ + this->module_ = module; +} +} // namespace UDMF +} // namespace OHOS diff --git a/udmf/framework/innerkitsimpl/data/system_defined_pixelmap.cpp b/udmf/framework/innerkitsimpl/data/system_defined_pixelmap.cpp new file mode 100644 index 0000000000000000000000000000000000000000..85660988aae48fc7082271020981468a96f4c86f --- /dev/null +++ b/udmf/framework/innerkitsimpl/data/system_defined_pixelmap.cpp @@ -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. + */ + +#include "system_defined_pixelmap.h" + +namespace OHOS { +namespace UDMF { +SystemDefinedPixelMap::SystemDefinedPixelMap() +{ + this->dataType_ = SYSTEM_DEFINED_PIXEL_MAP; +} + +SystemDefinedPixelMap::SystemDefinedPixelMap(std::vector<uint8_t> &data) +{ + this->dataType_ = SYSTEM_DEFINED_PIXEL_MAP; + this->rawData_ = std::move(data); +} + +int64_t SystemDefinedPixelMap::GetSize() +{ + return UnifiedDataUtils::GetDetailsSize(this->details_) + rawData_.size(); +} + +std::vector<uint8_t> SystemDefinedPixelMap::GetRawData() const +{ + return this->rawData_; +} + +void SystemDefinedPixelMap::SetRawData(const std::vector<uint8_t> &rawData) +{ + this->rawData_ = rawData; +} +} // namespace UDMF +} // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/data/system_defined_record.cpp b/udmf/framework/innerkitsimpl/data/system_defined_record.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fe125ea68bca645ca35abe6891daa553bf757103 --- /dev/null +++ b/udmf/framework/innerkitsimpl/data/system_defined_record.cpp @@ -0,0 +1,58 @@ +/* + * 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 "system_defined_record.h" + +namespace OHOS { +namespace UDMF { +SystemDefinedRecord::SystemDefinedRecord() : UnifiedRecord(SYSTEM_DEFINED_RECORD) +{ +} + +int64_t SystemDefinedRecord::GetSize() +{ + return UnifiedDataUtils::GetDetailsSize(this->details_); +} + +void SystemDefinedRecord::AddProperty(const std::string &property, UDVariant &value) +{ + auto it = details_.find(property); + if (it == details_.end()) { + details_.insert(std::make_pair(property, value)); + } else { + details_[property] = value; + } +} + +UDVariant SystemDefinedRecord::GetPropertyByName(const std::string &property) const +{ + auto it = details_.find(property); + if (it == details_.end()) { + return nullptr; + } + return it->second; +} + +void SystemDefinedRecord::SetDetails(UDDetails &details) +{ + this->details_ = details; +} + +UDDetails SystemDefinedRecord::GetDetails() const +{ + return this->details_; +} +} // namespace UDMF +} // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/data/text.cpp b/udmf/framework/innerkitsimpl/data/text.cpp new file mode 100644 index 0000000000000000000000000000000000000000..29aafc8eea8daf7b88bfcbcc7e52e1fbebef5921 --- /dev/null +++ b/udmf/framework/innerkitsimpl/data/text.cpp @@ -0,0 +1,44 @@ +/* + * 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 "text.h" + +namespace OHOS { +namespace UDMF { +Text::Text() : UnifiedRecord(TEXT) +{ +} + +Text::Text(UDDetails &variantMap) : UnifiedRecord(TEXT) +{ + this->details_ = variantMap; +} + +int64_t Text::GetSize() +{ + return UnifiedDataUtils::GetDetailsSize(this->details_); +} + +void Text::SetDetails(UDDetails &variantMap) +{ + this->details_ = variantMap; +} + +UDDetails Text::GetDetails() const +{ + return this->details_; +} +} // namespace UDMF +} // namespace OHOS diff --git a/udmf/framework/innerkitsimpl/data/unified_data.cpp b/udmf/framework/innerkitsimpl/data/unified_data.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7062a7e0ff50ff93fa37258ed2bc89fca204e64b --- /dev/null +++ b/udmf/framework/innerkitsimpl/data/unified_data.cpp @@ -0,0 +1,84 @@ +/* + * 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 "unified_data.h" + +namespace OHOS { +namespace UDMF { +int64_t UnifiedData::GetSize() +{ + int64_t totalSize = 0; + for (const auto &record : this->records_) { + totalSize += record->GetSize(); + } + return totalSize; +} + +std::string UnifiedData::GetGroupId() const +{ + return this->runtime_->key.groupId; +} + +std::shared_ptr<Runtime> UnifiedData::GetRuntime() const +{ + return this->runtime_; +} + +void UnifiedData::SetRuntime(Runtime &runtime) +{ + this->runtime_ = std::make_shared<Runtime>(runtime); +} + +void UnifiedData::AddRecord(const std::shared_ptr<UnifiedRecord> &record) +{ + if (record == nullptr) { + return; + } + this->records_.push_back(record); +} + +std::shared_ptr<UnifiedRecord> UnifiedData::GetRecordAt(std::size_t index) +{ + if (records_.size() > index) { + return records_[index]; + } + return nullptr; +} + +void UnifiedData::SetRecords(std::vector<std::shared_ptr<UnifiedRecord>> records) +{ + this->records_ = std::move(records); +} + +std::vector<std::shared_ptr<UnifiedRecord>> UnifiedData::GetRecords() const +{ + return this->records_; +} + +std::vector<UDType> UnifiedData::GetUDTypes() +{ + std::vector<UDType> typeSet; + for (const std::shared_ptr<UnifiedRecord> &record : records_) { + typeSet.push_back(record->GetType()); + } + return typeSet; +} + +bool UnifiedData::IsEmpty() const +{ + return records_.empty(); +} +} // namespace UDMF +} // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/data/unified_record.cpp b/udmf/framework/innerkitsimpl/data/unified_record.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a6d7eb08953329fb38f63cc283ea08135b6d4cb2 --- /dev/null +++ b/udmf/framework/innerkitsimpl/data/unified_record.cpp @@ -0,0 +1,58 @@ +/* + * 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 "unified_record.h" + +namespace OHOS { +namespace UDMF { +UnifiedRecord::UnifiedRecord() +{ + dataType_ = UD_BUTT; +} + +UnifiedRecord::UnifiedRecord(UDType type) +{ + if (type < TEXT || type > UD_BUTT) { + dataType_ = UD_BUTT; + } + dataType_ = type; +} + +UDType UnifiedRecord::GetType() const +{ + return this->dataType_; +} + +void UnifiedRecord::SetType(const UDType &type) +{ + this->dataType_ = type; +} + +int64_t UnifiedRecord::GetSize() +{ + return 0; +} + +std::string UnifiedRecord::GetUid() const +{ + return this->uid_; +} + +void UnifiedRecord::SetUid(const std::string &id) +{ + this->uid_ = id; +} +} // namespace UDMF +} // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/data/video.cpp b/udmf/framework/innerkitsimpl/data/video.cpp new file mode 100644 index 0000000000000000000000000000000000000000..db247ebccd3046f856d41a8a2817ebab005ca4a1 --- /dev/null +++ b/udmf/framework/innerkitsimpl/data/video.cpp @@ -0,0 +1,29 @@ +/* + * 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 "video.h" + +namespace OHOS { +namespace UDMF { +Video::Video() : Video("") +{ +} + +Video::Video(const std::string &uri) : File(uri) +{ + this->dataType_ = VIDEO; +} +} // namespace UDMF +} // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/test/fuzztest/BUILD.gn b/udmf/framework/innerkitsimpl/test/fuzztest/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..f0423470665d7a64c778aac4bf56d5f3512a79aa --- /dev/null +++ b/udmf/framework/innerkitsimpl/test/fuzztest/BUILD.gn @@ -0,0 +1,21 @@ +# 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. + +import("//build/ohos.gni") + +######################################################################################### +group("fuzztest") { + testonly = true + + deps = [ "udmfclient_fuzzer:fuzztest" ] +} diff --git a/udmf/framework/innerkitsimpl/test/fuzztest/udmfclient_fuzzer/BUILD.gn b/udmf/framework/innerkitsimpl/test/fuzztest/udmfclient_fuzzer/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..0d066a760420e1b95cb12dce98823f1f8077c093 --- /dev/null +++ b/udmf/framework/innerkitsimpl/test/fuzztest/udmfclient_fuzzer/BUILD.gn @@ -0,0 +1,67 @@ +# 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. +import("//build/config/features.gni") + +#####################hydra-fuzz################### +import("//build/test.gni") +import("//foundation/distributeddatamgr/udmf/udmf.gni") + +##############################fuzztest########################################## +ohos_fuzztest("UdmfClientFuzzTest") { + module_out_path = "udmf/innerkitsImpl" + + include_dirs = [ + "${udmf_interfaces_path}/innerkits/client", + "${udmf_interfaces_path}/innerkits/common", + "${udmf_interfaces_path}/innerkits/data", + "${udmf_framework_path}/common", + "${udmf_framework_path}/service", + ] + + fuzz_config_file = + "${udmf_framework_path}/innerkitsimpl/test/fuzztest/udmfclient_fuzzer" + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + sources = [ "udmf_client_fuzzer.cpp" ] + + deps = [ "${udmf_interfaces_path}/innerkits:udmf_client" ] + + external_deps = [ + "access_token:libaccesstoken_sdk", + "access_token:libnativetoken", + "access_token:libtoken_setproc", + "bundle_framework:appexecfwk_core", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:distributeddata_inner", + "samgr:samgr_proxy", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":UdmfClientFuzzTest", + ] +} +############################################################################### diff --git a/udmf/framework/innerkitsimpl/test/fuzztest/udmfclient_fuzzer/corpus/init b/udmf/framework/innerkitsimpl/test/fuzztest/udmfclient_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..2b595da0c26af63ffb2d5f4132c086b2e5986fce --- /dev/null +++ b/udmf/framework/innerkitsimpl/test/fuzztest/udmfclient_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/test/fuzztest/udmfclient_fuzzer/project.xml b/udmf/framework/innerkitsimpl/test/fuzztest/udmfclient_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..4fdbc407f205680885fa42663163b5c987f123a6 --- /dev/null +++ b/udmf/framework/innerkitsimpl/test/fuzztest/udmfclient_fuzzer/project.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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. +--> +<fuzz_config> + <fuzztest> + <!-- maximum length of a test input --> + <max_len>1000</max_len> + <!-- maximum total time in seconds to run the fuzzer --> + <max_total_time>300</max_total_time> + <!-- memory usage limit in Mb --> + <rss_limit_mb>4096</rss_limit_mb> + </fuzztest> +</fuzz_config> diff --git a/udmf/framework/innerkitsimpl/test/fuzztest/udmfclient_fuzzer/udmf_client_fuzzer.cpp b/udmf/framework/innerkitsimpl/test/fuzztest/udmfclient_fuzzer/udmf_client_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..179454fd1b0119402a5556b4c9968b6ea2bf2a0e --- /dev/null +++ b/udmf/framework/innerkitsimpl/test/fuzztest/udmfclient_fuzzer/udmf_client_fuzzer.cpp @@ -0,0 +1,658 @@ +/* + * 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 "udmf_client_fuzzer.h" + +#include <unistd.h> + +#include "accesstoken_kit.h" +#include "nativetoken_kit.h" +#include "token_setproc.h" + +#include "udmf_client.h" +#include "text.h" +#include "plain_text.h" +#include "html.h" +#include "link.h" +#include "file.h" +#include "image.h" +#include "video.h" +#include "system_defined_record.h" +#include "system_defined_form.h" +#include "system_defined_appitem.h" +#include "system_defined_pixelmap.h" + +using namespace OHOS; +using namespace OHOS::Security::AccessToken; +using namespace OHOS::UDMF; + +namespace OHOS { +void AllocHapToken() +{ + HapInfoParams info = { + .userID = 100, + .bundleName = "ohos.test.demo", + .instIndex = 0, + .appIDDesc = "ohos.test.demo" + }; + + HapPolicyParams policy = { + .apl = APL_NORMAL, + .domain = "test.domain", + .permList = { + { + .permissionName = "ohos.permission.test", + .bundleName = "ohos.test.demo", + .grantMode = 1, + .availableLevel = APL_NORMAL, + .label = "label", + .labelId = 1, + .description = "test", + .descriptionId = 1 + } + }, + .permStateList = { + { + .permissionName = "ohos.permission.test", + .isGeneral = true, + .resDeviceID = {"local"}, + .grantStatus = {PermissionState::PERMISSION_GRANTED}, + .grantFlags = {1} + } + } + }; + auto tokenID = AccessTokenKit::AllocHapToken(info, policy); + SetSelfTokenID(tokenID.tokenIDEx); +} + +void SetUpTestCase() +{ + AllocHapToken(); +} + +void TearDown() +{ +} + +void SetNativeToken() +{ + NativeTokenInfoParams infoInstance = { + .dcapsNum = 0, + .permsNum = 0, + .aclsNum = 0, + .dcaps = nullptr, + .perms = nullptr, + .acls = nullptr, + .processName = "msdp_sa", + .aplStr = "system_core", + }; + auto tokenId = GetAccessTokenId(&infoInstance); + SetSelfTokenID(tokenId); + AccessTokenKit::ReloadNativeTokenInfo(); +} + +void SetHapToken() +{ + auto tokenId = AccessTokenKit::GetHapTokenID(100, "ohos.test.demo", 0); + SetSelfTokenID(tokenId); +} + +void SetDataTextFuzz(const uint8_t *data, size_t size) +{ + std::string skey(data, data + size); + std::string svalue(data, data + size); + UnifiedData unifiedData; + CustomOption option = {.intention = Intention::UD_INTENTION_BUTT}; + Text text; + UDDetails details; + details.insert({skey, svalue}); + text.SetDetails(details); + std::shared_ptr<UnifiedRecord> record = std::make_shared<Text>(text); + unifiedData.AddRecord(record); + std::string key; + UdmfClient::GetInstance().SetData(option, unifiedData, key); + + SetNativeToken(); + + QueryOption option2 = {.key = key}; + Privilege privilege; + privilege.readPermission = "readPermission"; + privilege.writePermission = "writePermission"; + UdmfClient::GetInstance().AddPrivilege(option2, privilege); + + SetHapToken(); + + UnifiedData data2; + UdmfClient::GetInstance().GetData(option2, data2); +} + +void SetDataPlainTextFuzz(const uint8_t *data, size_t size) +{ + std::string skey(data, data + size); + std::string svalue(data, data + size); + CustomOption option1 = {.intention = Intention::UD_INTENTION_DRAG}; + UnifiedData data1; + PlainText plainText1; + UDDetails details1; + details1.insert({skey, svalue}); + plainText1.SetDetails(details1); + plainText1.SetContent(svalue + "content"); + plainText1.SetAbstract(svalue + "abstract"); + plainText1.GetContent(); + plainText1.GetAbstract(); + std::shared_ptr<UnifiedRecord> record1 = std::make_shared<PlainText>(plainText1); + data1.AddRecord(record1); + std::string key; + UdmfClient::GetInstance().SetData(option1, data1, key); + + SetNativeToken(); + + QueryOption option2 = {.key = key}; + Privilege privilege; + privilege.readPermission = "readPermission"; + privilege.writePermission = "writePermission"; + UdmfClient::GetInstance().AddPrivilege(option2, privilege); + + SetHapToken(); + + UnifiedData data2; + UdmfClient::GetInstance().GetData(option2, data2); +} + +void SetDataHtmlFuzz(const uint8_t *data, size_t size) +{ + std::string skey(data, data + size); + std::string svalue(data, data + size); + CustomOption option1 = {.intention = Intention::UD_INTENTION_DRAG}; + UnifiedData data1; + std::string key; + Html html1; + UDDetails details1; + details1.insert({skey, svalue}); + html1.SetDetails(details1); + html1.SetHtmlContent(svalue + "htmlcontent"); + html1.SetPlainContent(svalue + "plainContent"); + html1.GetHtmlContent(); + html1.GetPlainContent(); + std::shared_ptr<UnifiedRecord> record1 = std::make_shared<Html>(html1); + data1.AddRecord(record1); + UdmfClient::GetInstance().SetData(option1, data1, key); + + SetNativeToken(); + + QueryOption option2 = {.key = key}; + Privilege privilege; + privilege.readPermission = "readPermission"; + privilege.writePermission = "writePermission"; + UdmfClient::GetInstance().AddPrivilege(option2, privilege); + + SetHapToken(); + + UnifiedData data2; + UdmfClient::GetInstance().GetData(option2, data2); +} + +void SetDataLinkFuzz(const uint8_t *data, size_t size) +{ + std::string skey(data, data + size); + std::string svalue(data, data + size); + CustomOption option1 = {.intention = Intention::UD_INTENTION_DRAG}; + UnifiedData data1; + std::string key; + Link link1; + UDDetails details1; + details1.insert({skey, svalue}); + link1.SetDetails(details1); + link1.SetUrl(svalue + "url"); + link1.SetDescription(svalue + "description"); + link1.GetUrl(); + link1.GetDescription(); + std::shared_ptr<UnifiedRecord> record1 = std::make_shared<Link>(link1); + data1.AddRecord(record1); + UdmfClient::GetInstance().SetData(option1, data1, key); + + SetNativeToken(); + + QueryOption option2 = {.key = key}; + Privilege privilege; + privilege.readPermission = "readPermission"; + privilege.writePermission = "writePermission"; + UdmfClient::GetInstance().AddPrivilege(option2, privilege); + + SetHapToken(); + + UnifiedData data2; + UdmfClient::GetInstance().GetData(option2, data2); +} + +void SetDataFileFuzz(const uint8_t *data, size_t size) +{ + std::string svalue(data, data + size); + CustomOption option1 = {.intention = Intention::UD_INTENTION_DRAG}; + UnifiedData data1; + std::string key; + File file1; + file1.SetUri(svalue + "uri"); + file1.SetRemoteUri(svalue + "remoteUri"); + file1.GetUri(); + file1.GetRemoteUri(); + file1.GetSize(); + std::shared_ptr<UnifiedRecord> record1 = std::make_shared<File>(file1); + data1.AddRecord(record1); + UdmfClient::GetInstance().SetData(option1, data1, key); + + SetNativeToken(); + + QueryOption option2 = {.key = key}; + Privilege privilege; + privilege.readPermission = "readPermission"; + privilege.writePermission = "writePermission"; + UdmfClient::GetInstance().AddPrivilege(option2, privilege); + + SetHapToken(); + + UnifiedData data2; + UdmfClient::GetInstance().GetData(option2, data2); +} + +void SetDataImageFuzz(const uint8_t *data, size_t size) +{ + std::string svalue(data, data + size); + CustomOption option1 = {.intention = Intention::UD_INTENTION_DRAG}; + UnifiedData data1; + std::string key; + Image image1; + image1.SetUri(svalue + "uri"); + image1.SetRemoteUri(svalue + "remoteUri"); + std::shared_ptr<UnifiedRecord> record1 = std::make_shared<Image>(image1); + data1.AddRecord(record1); + UdmfClient::GetInstance().SetData(option1, data1, key); + + SetNativeToken(); + + QueryOption option2 = {.key = key}; + Privilege privilege; + privilege.readPermission = "readPermission"; + privilege.writePermission = "writePermission"; + UdmfClient::GetInstance().AddPrivilege(option2, privilege); + + SetHapToken(); + + UnifiedData data2; + UdmfClient::GetInstance().GetData(option2, data2); +} + +void SetDataVideoFuzz(const uint8_t *data, size_t size) +{ + std::string svalue(data, data + size); + CustomOption option1 = {.intention = Intention::UD_INTENTION_DRAG}; + UnifiedData data1; + std::string key; + Video video1; + video1.SetUri(svalue + "uri"); + video1.SetRemoteUri(svalue + "remoteUri"); + std::shared_ptr<UnifiedRecord> record1 = std::make_shared<Video>(video1); + data1.AddRecord(record1); + UdmfClient::GetInstance().SetData(option1, data1, key); + + SetNativeToken(); + + QueryOption option2 = {.key = key}; + Privilege privilege; + privilege.readPermission = "readPermission"; + privilege.writePermission = "writePermission"; + UdmfClient::GetInstance().AddPrivilege(option2, privilege); + + SetHapToken(); + + UnifiedData data2; + UdmfClient::GetInstance().GetData(option2, data2); +} + +void SetDataSystemDefinedRecordFuzz(const uint8_t *data, size_t size) +{ + std::string skey(data, data + size); + std::string svalue(data, data + size); + CustomOption option1 = {.intention = Intention::UD_INTENTION_DRAG}; + UnifiedData data1; + std::string key; + SystemDefinedRecord systemDefinedRecord1; + UDDetails details1; + details1.insert({skey, svalue}); + systemDefinedRecord1.SetDetails(details1); + std::shared_ptr<UnifiedRecord> record1 = std::make_shared<SystemDefinedRecord>(systemDefinedRecord1); + data1.AddRecord(record1); + UdmfClient::GetInstance().SetData(option1, data1, key); + + SetNativeToken(); + + QueryOption option2 = {.key = key}; + Privilege privilege; + privilege.readPermission = "readPermission"; + privilege.writePermission = "writePermission"; + UdmfClient::GetInstance().AddPrivilege(option2, privilege); + + SetHapToken(); + + UnifiedData data2; + UdmfClient::GetInstance().GetData(option2, data2); +} + +void SetDataSystemDefinedFormFuzz(const uint8_t *data, size_t size) +{ + std::string skey(data, data + size); + std::string svalue(data, data + size); + CustomOption option1 = {.intention = Intention::UD_INTENTION_DRAG}; + UnifiedData data1; + std::string key; + SystemDefinedForm systemDefinedForm1; + UDDetails details1; + details1.insert({skey, svalue}); + systemDefinedForm1.SetDetails(details1); + auto formId = 123; + systemDefinedForm1.SetFormId(formId); + systemDefinedForm1.SetFormName(svalue + "formName"); + systemDefinedForm1.SetModule(svalue + "module"); + systemDefinedForm1.SetAbilityName(svalue + "abilityName"); + systemDefinedForm1.SetBundleName(svalue + "bundleName"); + systemDefinedForm1.GetFormId(); + systemDefinedForm1.GetFormName(); + systemDefinedForm1.GetBundleName(); + systemDefinedForm1.GetAbilityName(); + systemDefinedForm1.GetModule(); + std::shared_ptr<UnifiedRecord> record1 = std::make_shared<SystemDefinedForm>(systemDefinedForm1); + data1.AddRecord(record1); + UdmfClient::GetInstance().SetData(option1, data1, key); + + SetNativeToken(); + + QueryOption option2 = {.key = key}; + Privilege privilege; + privilege.readPermission = "readPermission"; + privilege.writePermission = "writePermission"; + UdmfClient::GetInstance().AddPrivilege(option2, privilege); + + SetHapToken(); + + UnifiedData data2; + UdmfClient::GetInstance().GetData(option2, data2); +} + +void SetDataSystemDefinedAppItemFuzz(const uint8_t *data, size_t size) +{ + std::string skey(data, data + size); + std::string svalue(data, data + size); + CustomOption option1 = {.intention = Intention::UD_INTENTION_DRAG}; + UnifiedData data1; + std::string key; + SystemDefinedAppItem systemDefinedAppItem1; + UDDetails details1; + details1.insert({skey, svalue}); + systemDefinedAppItem1.SetDetails(details1); + systemDefinedAppItem1.SetAppId(svalue + "appId"); + systemDefinedAppItem1.SetAppName(svalue + "appName"); + systemDefinedAppItem1.SetAppIconId(svalue + "appIconId"); + systemDefinedAppItem1.SetAppLabelId(svalue + "appLabelId"); + systemDefinedAppItem1.SetBundleName(svalue + "bundleName"); + systemDefinedAppItem1.SetAbilityName(svalue + "abilityName"); + systemDefinedAppItem1.GetAppId(); + systemDefinedAppItem1.GetAppName(); + systemDefinedAppItem1.GetBundleName(); + systemDefinedAppItem1.GetAbilityName(); + systemDefinedAppItem1.GetAppIconId(); + systemDefinedAppItem1.GetAppLabelId(); + std::shared_ptr<UnifiedRecord> record1 = std::make_shared<SystemDefinedAppItem>(systemDefinedAppItem1); + data1.AddRecord(record1); + UdmfClient::GetInstance().SetData(option1, data1, key); + + SetNativeToken(); + + QueryOption option2 = {.key = key}; + Privilege privilege; + privilege.readPermission = "readPermission"; + privilege.writePermission = "writePermission"; + UdmfClient::GetInstance().AddPrivilege(option2, privilege); + + SetHapToken(); + + UnifiedData data2; + UdmfClient::GetInstance().GetData(option2, data2); +} + +void SetDataSystemDefinedPixelMapFuzz(const uint8_t *data, size_t size) +{ + std::string skey(data, data + size); + std::string svalue(data, data + size); + CustomOption option1 = {.intention = Intention::UD_INTENTION_DRAG}; + UnifiedData data1; + std::string key; + SystemDefinedPixelMap systemDefinedPixelMap1; + UDDetails details1; + details1.insert({skey, svalue}); + systemDefinedPixelMap1.SetDetails(details1); + std::vector<uint8_t> rawData1 = {1, 2, 3, 4, 5}; + systemDefinedPixelMap1.SetRawData(rawData1); + std::shared_ptr<UnifiedRecord> record1 = std::make_shared<SystemDefinedPixelMap>(systemDefinedPixelMap1); + data1.AddRecord(record1); + UdmfClient::GetInstance().SetData(option1, data1, key); + + SetNativeToken(); + + QueryOption option2 = {.key = key}; + Privilege privilege; + privilege.readPermission = "readPermission"; + privilege.writePermission = "writePermission"; + UdmfClient::GetInstance().AddPrivilege(option2, privilege); + + SetHapToken(); + + UnifiedData data2; + UdmfClient::GetInstance().GetData(option2, data2); +} + +void GetSummaryFuzz(const uint8_t *data, size_t size) +{ + std::string skey(data, data + size); + std::string svalue(data, data + size); + CustomOption option1 = {.intention = Intention::UD_INTENTION_DRAG}; + UnifiedData UData; + std::string key; + + UDDetails details; + details.insert({skey, svalue}); + + Text text; + text.SetDetails(details); + std::shared_ptr<UnifiedRecord> record1 = std::make_shared<Text>(text); + UData.AddRecord(record1); + + PlainText plainText; + plainText.SetDetails(details); + plainText.SetContent(svalue + "content"); + plainText.SetAbstract(svalue + "abstract"); + std::shared_ptr<UnifiedRecord> record2 = std::make_shared<PlainText>(plainText); + UData.AddRecord(record2); + + File file; + file.SetUri(svalue + "uri"); + file.SetRemoteUri(svalue + "remoteUri"); + std::shared_ptr<UnifiedRecord> record3 = std::make_shared<File>(file); + UData.AddRecord(record3); + + Image image; + image.SetUri(svalue + "uri"); + image.SetRemoteUri(svalue + "remoteUri"); + std::shared_ptr<UnifiedRecord> record4 = std::make_shared<Image>(image); + UData.AddRecord(record4); + + SystemDefinedRecord systemDefinedRecord; + systemDefinedRecord.SetDetails(details); + std::shared_ptr<UnifiedRecord> record5 = std::make_shared<SystemDefinedRecord>(systemDefinedRecord); + UData.AddRecord(record5); + + SystemDefinedForm systemDefinedForm; + systemDefinedForm.SetDetails(details); + auto formId = 123; + systemDefinedForm.SetFormId(formId); + systemDefinedForm.SetFormName(svalue + "formName"); + systemDefinedForm.SetModule(svalue + "module"); + systemDefinedForm.SetAbilityName(svalue + "abilityName"); + systemDefinedForm.SetBundleName(svalue + "bundleName"); + std::shared_ptr<UnifiedRecord> record6 = std::make_shared<SystemDefinedForm>(systemDefinedForm); + UData.AddRecord(record6); + + UdmfClient::GetInstance().SetData(option1, UData, key); + + QueryOption option2 = {.key = key}; + Summary summary; + UdmfClient::GetInstance().GetSummary(option2, summary); + UnifiedData data2; + UdmfClient::GetInstance().GetData(option2, data2); +} + +void GetBatchDataByKeyFuzz(const uint8_t *data, size_t size) +{ + std::string skey(data, data + size); + CustomOption option1 = { .intention = UD_INTENTION_DATA_HUB }; + UnifiedData data1; + std::string key; + PlainText plainText(skey, skey); + std::shared_ptr<UnifiedRecord> record1 = std::make_shared<PlainText>(plainText); + data1.AddRecord(record1); + UdmfClient::GetInstance().SetData(option1, data1, key); + + SetHapToken(); + QueryOption option2 = { .key = key }; + std::vector<UnifiedData> dataSet2; + UdmfClient::GetInstance().GetBatchData(option2, dataSet2); + + SetHapToken(); + QueryOption option3 = { .key = skey }; + std::vector<UnifiedData> dataSet3; + UdmfClient::GetInstance().GetBatchData(option3, dataSet3); +} + +void GetBatchDataByIntentionFuzz(const uint8_t *data, size_t size) +{ + std::string skey(data, data + size); + CustomOption option1 = { .intention = UD_INTENTION_DATA_HUB }; + UnifiedData data1; + std::string key; + PlainText plainText(skey, skey); + std::shared_ptr<UnifiedRecord> record1 = std::make_shared<PlainText>(plainText); + data1.AddRecord(record1); + UdmfClient::GetInstance().SetData(option1, data1, key); + + SetHapToken(); + Intention intention = UnifiedDataUtils::GetIntentionByString(skey); + QueryOption option2 = { .intention = intention }; + std::vector<UnifiedData> dataSet; + UdmfClient::GetInstance().GetBatchData(option2, dataSet); +} + +void DeleteDataByKeyFuzz(const uint8_t *data, size_t size) +{ + std::string skey(data, data + size); + CustomOption option1 = { .intention = UD_INTENTION_DATA_HUB }; + UnifiedData data1; + std::string key; + PlainText plainText(skey, skey); + std::shared_ptr<UnifiedRecord> record1 = std::make_shared<PlainText>(plainText); + data1.AddRecord(record1); + UdmfClient::GetInstance().SetData(option1, data1, key); + + SetHapToken(); + QueryOption option2 = { .key = key }; + std::vector<UnifiedData> dataSet2; + UdmfClient::GetInstance().DeleteData(option2, dataSet2); + + SetHapToken(); + QueryOption option3 = { .key = skey }; + std::vector<UnifiedData> dataSet3; + UdmfClient::GetInstance().DeleteData(option3, dataSet3); +} + +void DeleteDataByIntentionFuzz(const uint8_t *data, size_t size) +{ + std::string skey(data, data + size); + CustomOption option1 = { .intention = UD_INTENTION_DATA_HUB }; + UnifiedData data1; + std::string key; + PlainText plainText(skey, skey); + std::shared_ptr<UnifiedRecord> record1 = std::make_shared<PlainText>(plainText); + data1.AddRecord(record1); + UdmfClient::GetInstance().SetData(option1, data1, key); + + SetHapToken(); + Intention intention = UnifiedDataUtils::GetIntentionByString(skey); + QueryOption option2 = { .intention = intention }; + std::vector<UnifiedData> dataSet; + UdmfClient::GetInstance().DeleteData(option2, dataSet); +} + +void UpdateDataFuzz(const uint8_t *data, size_t size) +{ + std::string skey(data, data + size); + CustomOption option1 = { .intention = UD_INTENTION_DATA_HUB }; + UnifiedData data1; + std::string key; + PlainText plainText(skey, skey); + std::shared_ptr<UnifiedRecord> record1 = std::make_shared<PlainText>(plainText); + data1.AddRecord(record1); + UdmfClient::GetInstance().SetData(option1, data1, key); + + SetHapToken(); + UnifiedData data2; + PlainText plainText2(skey + "2", skey + "2"); + record1 = std::make_shared<PlainText>(plainText2); + data2.AddRecord(record1); + QueryOption option2 = { .key = key }; + UdmfClient::GetInstance().UpdateData(option2, data2); + + SetHapToken(); + UnifiedData data3; + PlainText plainText3(skey + "3", skey + "3"); + record1 = std::make_shared<PlainText>(plainText3); + data3.AddRecord(record1); + QueryOption option3 = { .key = skey }; + UdmfClient::GetInstance().UpdateData(option3, data3); +} +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + /* Run your code on data */ + OHOS::SetUpTestCase(); + OHOS::SetDataFileFuzz(data, size); + OHOS::SetDataHtmlFuzz(data, size); + OHOS::SetDataImageFuzz(data, size); + OHOS::SetDataLinkFuzz(data, size); + OHOS::SetDataPlainTextFuzz(data, size); + OHOS::SetDataSystemDefinedAppItemFuzz(data, size); + OHOS::SetDataSystemDefinedFormFuzz(data, size); + OHOS::SetDataSystemDefinedPixelMapFuzz(data, size); + OHOS::SetDataSystemDefinedRecordFuzz(data, size); + OHOS::SetDataTextFuzz(data, size); + OHOS::SetDataVideoFuzz(data, size); + OHOS::GetSummaryFuzz(data, size); + OHOS::GetBatchDataByKeyFuzz(data, size); + OHOS::GetBatchDataByIntentionFuzz(data, size); + OHOS::DeleteDataByKeyFuzz(data, size); + OHOS::DeleteDataByIntentionFuzz(data, size); + OHOS::UpdateDataFuzz(data, size); + OHOS::TearDown(); + return 0; +} \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/test/fuzztest/udmfclient_fuzzer/udmf_client_fuzzer.h b/udmf/framework/innerkitsimpl/test/fuzztest/udmfclient_fuzzer/udmf_client_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..a535292cf4ef03a8d17b8376b4adcedb856d1be6 --- /dev/null +++ b/udmf/framework/innerkitsimpl/test/fuzztest/udmfclient_fuzzer/udmf_client_fuzzer.h @@ -0,0 +1,21 @@ +/* + * 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 UDMF_UDMF_CLIENT_FUZZER_H +#define UDMF_UDMF_CLIENT_FUZZER_H + +#define FUZZ_PROJECT_NAME "udmfclient_fuzzer" + +#endif // UDMF_UDMF_CLIENT_FUZZER_H diff --git a/udmf/framework/innerkitsimpl/test/unittest/BUILD.gn b/udmf/framework/innerkitsimpl/test/unittest/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..fae602a03a471b6aa7cdf14a59a039f2fbc30a84 --- /dev/null +++ b/udmf/framework/innerkitsimpl/test/unittest/BUILD.gn @@ -0,0 +1,61 @@ +# 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. +import("//build/test.gni") +import("//foundation/distributeddatamgr/udmf/udmf.gni") + +module_output_path = "udmf/innerkitsImpl" + +############################################################################### +config("module_private_config") { + include_dirs = [ + "${udmf_interfaces_path}/innerkits/client", + "${udmf_interfaces_path}/innerkits/common", + "${udmf_interfaces_path}/innerkits/data", + "${udmf_framework_path}/common", + "${udmf_framework_path}/service", + ] +} + +common_deps = [ "${udmf_interfaces_path}/innerkits:udmf_client" ] + +common_external_deps = [ + "access_token:libaccesstoken_sdk", + "access_token:libnativetoken", + "access_token:libtoken_setproc", + "bundle_framework:appexecfwk_core", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:distributeddata_inner", + "samgr:samgr_proxy", +] + +ohos_unittest("UdmfClientTest") { + module_out_path = module_output_path + + sources = [ "udmf_client_test.cpp" ] + + configs = [ ":module_private_config" ] + + deps = common_deps + + external_deps = common_external_deps +} + +############################################################################### +group("unittest") { + testonly = true + + deps = [ ":UdmfClientTest" ] +} +############################################################################### diff --git a/udmf/framework/innerkitsimpl/test/unittest/udmf_client_test.cpp b/udmf/framework/innerkitsimpl/test/unittest/udmf_client_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ceb0b5cabcaed529b8d22c2aeb1014a6202286b6 --- /dev/null +++ b/udmf/framework/innerkitsimpl/test/unittest/udmf_client_test.cpp @@ -0,0 +1,1755 @@ +/* + * 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 <gtest/gtest.h> + +#include <unistd.h> + +#include "token_setproc.h" +#include "accesstoken_kit.h" +#include "nativetoken_kit.h" + +#include "framework/common/logger.h" +#include "udmf_client.h" +#include "application_defined_record.h" +#include "audio.h" +#include "file.h" +#include "folder.h" +#include "html.h" +#include "image.h" +#include "link.h" +#include "plain_text.h" +#include "system_defined_appitem.h" +#include "system_defined_form.h" +#include "system_defined_pixelmap.h" +#include "system_defined_record.h" +#include "text.h" +#include "video.h" + +using namespace testing::ext; +using namespace OHOS::Security::AccessToken; +using namespace OHOS::UDMF; +using namespace OHOS; +namespace OHOS::Test { +class UdmfClientTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; + + void SetNativeToken(); + static void AllocHapToken1(); + static void AllocHapToken2(); + void SetHapToken1(); + void SetHapToken2(); + + void AddPrivilege(QueryOption &option); + void CompareDetails(const UDDetails &details); + void GetEmptyData(QueryOption &option); + + static constexpr int USER_ID = 100; + static constexpr int INST_INDEX = 0; +}; + +void UdmfClientTest::SetUpTestCase() +{ + AllocHapToken1(); + AllocHapToken2(); +} + +void UdmfClientTest::TearDownTestCase() +{ + auto tokenId = AccessTokenKit::GetHapTokenID(USER_ID, "ohos.test.demo1", INST_INDEX); + AccessTokenKit::DeleteToken(tokenId); + tokenId = AccessTokenKit::GetHapTokenID(USER_ID, "ohos.test.demo2", INST_INDEX); + AccessTokenKit::DeleteToken(tokenId); +} + +void UdmfClientTest::SetUp() +{ + SetHapToken1(); +} + +void UdmfClientTest::TearDown() +{ +} + +void UdmfClientTest::SetNativeToken() +{ + auto tokenId = AccessTokenKit::GetNativeTokenId("msdp_sa"); + SetSelfTokenID(tokenId); +} + +void UdmfClientTest::AllocHapToken1() +{ + HapInfoParams info = { + .userID = USER_ID, + .bundleName = "ohos.test.demo1", + .instIndex = INST_INDEX, + .appIDDesc = "ohos.test.demo1" + }; + + HapPolicyParams policy = { + .apl = APL_NORMAL, + .domain = "test.domain", + .permList = { + { + .permissionName = "ohos.permission.test", + .bundleName = "ohos.test.demo1", + .grantMode = 1, + .availableLevel = APL_NORMAL, + .label = "label", + .labelId = 1, + .description = "test1", + .descriptionId = 1 + } + }, + .permStateList = { + { + .permissionName = "ohos.permission.test", + .isGeneral = true, + .resDeviceID = { "local" }, + .grantStatus = { PermissionState::PERMISSION_GRANTED }, + .grantFlags = { 1 } + } + } + }; + auto tokenID = AccessTokenKit::AllocHapToken(info, policy); + SetSelfTokenID(tokenID.tokenIDEx); +} + +void UdmfClientTest::AllocHapToken2() +{ + HapInfoParams info = { + .userID = USER_ID, + .bundleName = "ohos.test.demo2", + .instIndex = INST_INDEX, + .appIDDesc = "ohos.test.demo2" + }; + + HapPolicyParams policy = { + .apl = APL_NORMAL, + .domain = "test.domain", + .permList = { + { + .permissionName = "ohos.permission.test", + .bundleName = "ohos.test.demo2", + .grantMode = 1, + .availableLevel = APL_NORMAL, + .label = "label", + .labelId = 1, + .description = "test2", + .descriptionId = 1 + } + }, + .permStateList = { + { + .permissionName = "ohos.permission.test", + .isGeneral = true, + .resDeviceID = { "local" }, + .grantStatus = { PermissionState::PERMISSION_GRANTED }, + .grantFlags = { 1 } + } + } + }; + auto tokenID = AccessTokenKit::AllocHapToken(info, policy); + SetSelfTokenID(tokenID.tokenIDEx); +} + +void UdmfClientTest::SetHapToken1() +{ + auto tokenId = AccessTokenKit::GetHapTokenID(USER_ID, "ohos.test.demo1", INST_INDEX); + SetSelfTokenID(tokenId); +} + +void UdmfClientTest::SetHapToken2() +{ + auto tokenId = AccessTokenKit::GetHapTokenID(USER_ID, "ohos.test.demo2", INST_INDEX); + SetSelfTokenID(tokenId); +} + +void UdmfClientTest::AddPrivilege(QueryOption &option) +{ + Privilege privilege; + privilege.tokenId = AccessTokenKit::GetHapTokenID(USER_ID, "ohos.test.demo2", INST_INDEX); + privilege.readPermission = "readPermission"; + privilege.writePermission = "writePermission"; + SetNativeToken(); + auto status = UdmfClient::GetInstance().AddPrivilege(option, privilege); + ASSERT_EQ(status, E_OK); +} + +void UdmfClientTest::CompareDetails(const UDDetails &details) +{ + for (const auto &detail : details) { + auto key = detail.first; + EXPECT_EQ(key, "udmf_key"); + auto value = detail.second; + auto str = std::get<std::string>(value); + EXPECT_EQ(str, "udmf_value"); + } +} + +void UdmfClientTest::GetEmptyData(QueryOption &option) +{ + UnifiedData data; + auto status = UdmfClient::GetInstance().GetData(option, data); + EXPECT_EQ(status, E_OK); + EXPECT_TRUE(data.IsEmpty()); +} + +/** +* @tc.name: SetData001 +* @tc.desc: Set data with invalid params +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientTest, SetData001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SetData001 begin."); + + CustomOption option = { .intention = Intention::UD_INTENTION_DRAG }; + UnifiedData data; + std::string key; + auto status = UdmfClient::GetInstance().SetData(option, data, key); + EXPECT_EQ(status, E_INVALID_PARAMETERS); + + option = { .intention = Intention::UD_INTENTION_BUTT }; + Text text; + UDDetails details; + details.insert({ "udmf_key", "udmf_value" }); + text.SetDetails(details); + std::shared_ptr<UnifiedRecord> record = std::make_shared<Text>(text); + data.AddRecord(record); + status = UdmfClient::GetInstance().SetData(option, data, key); + EXPECT_EQ(status, E_INVALID_PARAMETERS); + + option = {}; + status = UdmfClient::GetInstance().SetData(option, data, key); + EXPECT_EQ(status, E_INVALID_PARAMETERS); + + option = { .intention = Intention::UD_INTENTION_BASE }; + status = UdmfClient::GetInstance().SetData(option, data, key); + EXPECT_EQ(status, E_INVALID_PARAMETERS); + LOG_INFO(UDMF_TEST, "SetData001 end."); +} + +/** +* @tc.name: SetData002 +* @tc.desc: Set Text record with valid params and get data +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientTest, SetData002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SetData002 begin."); + + CustomOption option1 = { .intention = Intention::UD_INTENTION_DRAG }; + UnifiedData data1; + Text text1; + UDDetails details1; + details1.insert({ "udmf_key", "udmf_value" }); + text1.SetDetails(details1); + std::shared_ptr<UnifiedRecord> record1 = std::make_shared<Text>(text1); + data1.AddRecord(record1); + std::string key; + auto status = UdmfClient::GetInstance().SetData(option1, data1, key); + ASSERT_EQ(status, E_OK); + + QueryOption option2 = { .key = key }; + AddPrivilege(option2); + SetHapToken2(); + UnifiedData data2; + status = UdmfClient::GetInstance().GetData(option2, data2); + ASSERT_EQ(status, E_OK); + + std::shared_ptr<UnifiedRecord> record2 = data2.GetRecordAt(0); + ASSERT_NE(record2, nullptr); + auto type = record2->GetType(); + EXPECT_EQ(type, UDType::TEXT); + + auto text2 = static_cast<Text *>(record2.get()); + ASSERT_NE(text2, nullptr); + CompareDetails(text2->GetDetails()); + + GetEmptyData(option2); + + LOG_INFO(UDMF_TEST, "SetData002 end."); +} + +/** +* @tc.name: SetData003 +* @tc.desc: Set PlainText record with valid params and get data +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientTest, SetData003, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SetData003 begin."); + + CustomOption option1 = { .intention = Intention::UD_INTENTION_DRAG }; + UnifiedData data1; + PlainText plainText1; + UDDetails details1; + details1.insert({ "udmf_key", "udmf_value" }); + plainText1.SetDetails(details1); + plainText1.SetContent("content"); + plainText1.SetAbstract("abstract"); + std::shared_ptr<UnifiedRecord> record1 = std::make_shared<PlainText>(plainText1); + data1.AddRecord(record1); + std::string key; + auto status = UdmfClient::GetInstance().SetData(option1, data1, key); + ASSERT_EQ(status, E_OK); + + QueryOption option2 = { .key = key }; + AddPrivilege(option2); + SetHapToken2(); + UnifiedData data2; + status = UdmfClient::GetInstance().GetData(option2, data2); + ASSERT_EQ(status, E_OK); + + std::shared_ptr<UnifiedRecord> record2 = data2.GetRecordAt(0); + ASSERT_NE(record2, nullptr); + auto type = record2->GetType(); + ASSERT_EQ(type, UDType::PLAIN_TEXT); + + auto text2 = static_cast<Text *>(record2.get()); + ASSERT_NE(text2, nullptr); + CompareDetails(text2->GetDetails()); + + auto plainText2 = static_cast<PlainText *>(record2.get()); + ASSERT_NE(plainText2, nullptr); + EXPECT_EQ(plainText1.GetContent(), plainText2->GetContent()); + EXPECT_EQ(plainText1.GetAbstract(), plainText2->GetAbstract()); + + GetEmptyData(option2); + + LOG_INFO(UDMF_TEST, "SetData003 end."); +} + +/** +* @tc.name: SetData004 +* @tc.desc: Set Html record with valid params and get data +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientTest, SetData004, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SetData004 begin."); + + CustomOption option1 = { .intention = Intention::UD_INTENTION_DRAG }; + UnifiedData data1; + std::string key; + Html html1; + UDDetails details1; + details1.insert({ "udmf_key", "udmf_value" }); + html1.SetDetails(details1); + html1.SetHtmlContent("htmlcontent"); + html1.SetPlainContent("plainContent"); + std::shared_ptr<UnifiedRecord> record1 = std::make_shared<Html>(html1); + data1.AddRecord(record1); + auto status = UdmfClient::GetInstance().SetData(option1, data1, key); + ASSERT_EQ(status, E_OK); + + QueryOption option2 = { .key = key }; + AddPrivilege(option2); + SetHapToken2(); + UnifiedData data2; + status = UdmfClient::GetInstance().GetData(option2, data2); + ASSERT_EQ(status, E_OK); + + std::shared_ptr<UnifiedRecord> record2 = data2.GetRecordAt(0); + ASSERT_NE(record2, nullptr); + auto type = record2->GetType(); + ASSERT_EQ(type, UDType::HTML); + + auto text2 = static_cast<Text *>(record2.get()); + ASSERT_NE(text2, nullptr); + CompareDetails(text2->GetDetails()); + + auto html2 = static_cast<Html *>(record2.get()); + ASSERT_NE(html2, nullptr); + EXPECT_EQ(html1.GetHtmlContent(), html2->GetHtmlContent()); + EXPECT_EQ(html1.GetPlainContent(), html2->GetPlainContent()); + + GetEmptyData(option2); + + LOG_INFO(UDMF_TEST, "SetData004 end."); +} + +/** +* @tc.name: SetData005 +* @tc.desc: Set Link record with valid params and get data +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientTest, SetData005, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SetData005 begin."); + + CustomOption option1 = { .intention = Intention::UD_INTENTION_DRAG }; + UnifiedData data1; + std::string key; + Link link1; + UDDetails details1; + details1.insert({ "udmf_key", "udmf_value" }); + link1.SetDetails(details1); + link1.SetUrl("url"); + link1.SetDescription("description"); + std::shared_ptr<UnifiedRecord> record1 = std::make_shared<Link>(link1); + data1.AddRecord(record1); + auto status = UdmfClient::GetInstance().SetData(option1, data1, key); + ASSERT_EQ(status, E_OK); + + QueryOption option2 = { .key = key }; + AddPrivilege(option2); + SetHapToken2(); + UnifiedData data2; + status = UdmfClient::GetInstance().GetData(option2, data2); + ASSERT_EQ(status, E_OK); + + std::shared_ptr<UnifiedRecord> record2 = data2.GetRecordAt(0); + ASSERT_NE(record2, nullptr); + auto type = record2->GetType(); + ASSERT_EQ(type, UDType::HYPERLINK); + + auto text2 = static_cast<Text *>(record2.get()); + ASSERT_NE(text2, nullptr); + CompareDetails(text2->GetDetails()); + + auto link2 = static_cast<Link *>(record2.get()); + ASSERT_NE(link2, nullptr); + EXPECT_EQ(link1.GetUrl(), link2->GetUrl()); + EXPECT_EQ(link1.GetDescription(), link2->GetDescription()); + + GetEmptyData(option2); + + LOG_INFO(UDMF_TEST, "SetData005 end."); +} + +/** +* @tc.name: SetData006 +* @tc.desc: Set File record with valid params and get data +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientTest, SetData006, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SetData006 begin."); + + CustomOption option1 = { .intention = Intention::UD_INTENTION_DRAG }; + UnifiedData data1; + std::string key; + File file1; + file1.SetRemoteUri("remoteUri"); + UDDetails details1; + details1.insert({ "udmf_key", "udmf_value" }); + file1.SetDetails(details1); + std::shared_ptr<UnifiedRecord> record1 = std::make_shared<File>(file1); + data1.AddRecord(record1); + auto status = UdmfClient::GetInstance().SetData(option1, data1, key); + ASSERT_EQ(status, E_OK); + + QueryOption option2 = { .key = key }; + AddPrivilege(option2); + SetHapToken2(); + UnifiedData data2; + status = UdmfClient::GetInstance().GetData(option2, data2); + ASSERT_EQ(status, E_OK); + + std::shared_ptr<UnifiedRecord> record2 = data2.GetRecordAt(0); + ASSERT_NE(record2, nullptr); + auto type = record2->GetType(); + ASSERT_EQ(type, UDType::FILE); + + auto file2 = static_cast<File *>(record2.get()); + ASSERT_NE(file2, nullptr); + EXPECT_EQ(file1.GetRemoteUri(), file2->GetRemoteUri()); + CompareDetails(file2->GetDetails()); + + GetEmptyData(option2); + + LOG_INFO(UDMF_TEST, "SetData006 end."); +} + +/** +* @tc.name: SetData007 +* @tc.desc: Set Image record with valid params and get data +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientTest, SetData007, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SetData007 begin."); + + CustomOption option1 = { .intention = Intention::UD_INTENTION_DRAG }; + UnifiedData data1; + std::string key; + Image image1; + UDDetails details1; + details1.insert({ "udmf_key", "udmf_value" }); + image1.SetDetails(details1); + image1.SetRemoteUri("remoteUri"); + std::shared_ptr<UnifiedRecord> record1 = std::make_shared<Image>(image1); + data1.AddRecord(record1); + auto status = UdmfClient::GetInstance().SetData(option1, data1, key); + ASSERT_EQ(status, E_OK); + + QueryOption option2 = { .key = key }; + AddPrivilege(option2); + SetHapToken2(); + UnifiedData data2; + status = UdmfClient::GetInstance().GetData(option2, data2); + ASSERT_EQ(status, E_OK); + + std::shared_ptr<UnifiedRecord> record2 = data2.GetRecordAt(0); + ASSERT_NE(record2, nullptr); + auto type = record2->GetType(); + ASSERT_EQ(type, UDType::IMAGE); + + auto file2 = static_cast<File *>(record2.get()); + ASSERT_NE(file2, nullptr); + CompareDetails(file2->GetDetails()); + + auto image2 = static_cast<Image *>(record2.get()); + ASSERT_NE(image2, nullptr); + EXPECT_EQ(image1.GetRemoteUri(), image2->GetRemoteUri()); + + GetEmptyData(option2); + + LOG_INFO(UDMF_TEST, "SetData007 end."); +} + +/** +* @tc.name: SetData008 +* @tc.desc: Set Video record with valid params and get data +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientTest, SetData008, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SetData008 begin."); + + CustomOption option1 = { .intention = Intention::UD_INTENTION_DRAG }; + UnifiedData data1; + std::string key; + Video video1; + UDDetails details1; + details1.insert({ "udmf_key", "udmf_value" }); + video1.SetDetails(details1); + video1.SetRemoteUri("remoteUri"); + std::shared_ptr<UnifiedRecord> record1 = std::make_shared<Video>(video1); + data1.AddRecord(record1); + auto status = UdmfClient::GetInstance().SetData(option1, data1, key); + ASSERT_EQ(status, E_OK); + + QueryOption option2 = { .key = key }; + AddPrivilege(option2); + SetHapToken2(); + UnifiedData data2; + status = UdmfClient::GetInstance().GetData(option2, data2); + ASSERT_EQ(status, E_OK); + + std::shared_ptr<UnifiedRecord> record2 = data2.GetRecordAt(0); + ASSERT_NE(record2, nullptr); + auto type = record2->GetType(); + EXPECT_EQ(type, UDType::VIDEO); + + auto file2 = static_cast<File *>(record2.get()); + ASSERT_NE(file2, nullptr); + CompareDetails(file2->GetDetails()); + + auto video2 = static_cast<Video *>(record2.get()); + ASSERT_NE(video2, nullptr); + EXPECT_EQ(video1.GetRemoteUri(), video2->GetRemoteUri()); + + GetEmptyData(option2); + + LOG_INFO(UDMF_TEST, "SetData008 end."); +} + +/** +* @tc.name: SetData009 +* @tc.desc: Set Audio record with valid params and get data +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientTest, SetData009, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SetData009 begin."); + + CustomOption option1 = { .intention = Intention::UD_INTENTION_DRAG }; + UnifiedData data1; + std::string key; + Audio audio1; + UDDetails details1; + details1.insert({ "udmf_key", "udmf_value" }); + audio1.SetDetails(details1); + audio1.SetRemoteUri("remoteUri"); + std::shared_ptr<UnifiedRecord> record1 = std::make_shared<Audio>(audio1); + data1.AddRecord(record1); + auto status = UdmfClient::GetInstance().SetData(option1, data1, key); + ASSERT_EQ(status, E_OK); + + QueryOption option2 = { .key = key }; + AddPrivilege(option2); + SetHapToken2(); + UnifiedData data2; + status = UdmfClient::GetInstance().GetData(option2, data2); + ASSERT_EQ(status, E_OK); + + std::shared_ptr<UnifiedRecord> record2 = data2.GetRecordAt(0); + ASSERT_NE(record2, nullptr); + auto type = record2->GetType(); + EXPECT_EQ(type, UDType::AUDIO); + + auto file2 = static_cast<File *>(record2.get()); + ASSERT_NE(file2, nullptr); + CompareDetails(file2->GetDetails()); + + auto audio2 = static_cast<Audio *>(record2.get()); + ASSERT_NE(audio2, nullptr); + EXPECT_EQ(audio1.GetRemoteUri(), audio2->GetRemoteUri()); + + GetEmptyData(option2); + + LOG_INFO(UDMF_TEST, "SetData009 end."); +} + +/** +* @tc.name: SetData010 +* @tc.desc: Set Folder record with valid params and get data +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientTest, SetData010, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SetData010 begin."); + + CustomOption option1 = { .intention = Intention::UD_INTENTION_DRAG }; + UnifiedData data1; + std::string key; + Folder folder1; + UDDetails details1; + details1.insert({ "udmf_key", "udmf_value" }); + folder1.SetDetails(details1); + folder1.SetRemoteUri("remoteUri"); + std::shared_ptr<UnifiedRecord> record1 = std::make_shared<Folder>(folder1); + data1.AddRecord(record1); + auto status = UdmfClient::GetInstance().SetData(option1, data1, key); + ASSERT_EQ(status, E_OK); + + QueryOption option2 = { .key = key }; + AddPrivilege(option2); + SetHapToken2(); + UnifiedData data2; + status = UdmfClient::GetInstance().GetData(option2, data2); + ASSERT_EQ(status, E_OK); + + std::shared_ptr<UnifiedRecord> record2 = data2.GetRecordAt(0); + ASSERT_NE(record2, nullptr); + auto type = record2->GetType(); + EXPECT_EQ(type, UDType::FOLDER); + + auto file2 = static_cast<File *>(record2.get()); + ASSERT_NE(file2, nullptr); + CompareDetails(file2->GetDetails()); + + auto folder2 = static_cast<Folder *>(record2.get()); + ASSERT_NE(folder2, nullptr); + EXPECT_EQ(folder1.GetRemoteUri(), folder2->GetRemoteUri()); + + GetEmptyData(option2); + + LOG_INFO(UDMF_TEST, "SetData010 end."); +} + +/** +* @tc.name: SetData011 +* @tc.desc: Set SystemDefined record with valid params and get data +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientTest, SetData011, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SetData011 begin."); + + CustomOption option1 = { .intention = Intention::UD_INTENTION_DRAG }; + UnifiedData data1; + std::string key; + SystemDefinedRecord systemDefinedRecord1; + UDDetails details1; + details1.insert({ "udmf_key", "udmf_value" }); + systemDefinedRecord1.SetDetails(details1); + std::shared_ptr<UnifiedRecord> record1 = std::make_shared<SystemDefinedRecord>(systemDefinedRecord1); + data1.AddRecord(record1); + auto status = UdmfClient::GetInstance().SetData(option1, data1, key); + ASSERT_EQ(status, E_OK); + + QueryOption option2 = { .key = key }; + AddPrivilege(option2); + SetHapToken2(); + UnifiedData data2; + status = UdmfClient::GetInstance().GetData(option2, data2); + ASSERT_EQ(status, E_OK); + + std::shared_ptr<UnifiedRecord> record2 = data2.GetRecordAt(0); + ASSERT_NE(record2, nullptr); + auto type = record2->GetType(); + ASSERT_EQ(type, UDType::SYSTEM_DEFINED_RECORD); + + auto systemDefinedRecord2 = static_cast<SystemDefinedRecord *>(record2.get()); + ASSERT_NE(systemDefinedRecord2, nullptr); + CompareDetails(systemDefinedRecord2->GetDetails()); + + GetEmptyData(option2); + + LOG_INFO(UDMF_TEST, "SetData011 end."); +} + +/** +* @tc.name: SetData012 +* @tc.desc: Set Form record with valid params and get data +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientTest, SetData012, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SetData012 begin."); + + CustomOption option1 = { .intention = Intention::UD_INTENTION_DRAG }; + UnifiedData data1; + std::string key; + SystemDefinedForm systemDefinedForm1; + UDDetails details1; + details1.insert({ "udmf_key", "udmf_value" }); + systemDefinedForm1.SetDetails(details1); + systemDefinedForm1.SetFormId(123); + systemDefinedForm1.SetFormName("formName"); + systemDefinedForm1.SetModule("module"); + systemDefinedForm1.SetAbilityName("abilityName"); + systemDefinedForm1.SetBundleName("bundleName"); + std::shared_ptr<UnifiedRecord> record1 = std::make_shared<SystemDefinedForm>(systemDefinedForm1); + data1.AddRecord(record1); + auto status = UdmfClient::GetInstance().SetData(option1, data1, key); + ASSERT_EQ(status, E_OK); + + QueryOption option2 = { .key = key }; + AddPrivilege(option2); + SetHapToken2(); + UnifiedData data2; + status = UdmfClient::GetInstance().GetData(option2, data2); + ASSERT_EQ(status, E_OK); + + std::shared_ptr<UnifiedRecord> record2 = data2.GetRecordAt(0); + ASSERT_NE(record2, nullptr); + auto type = record2->GetType(); + ASSERT_EQ(type, UDType::SYSTEM_DEFINED_FORM); + + auto systemDefinedRecord2 = static_cast<SystemDefinedRecord *>(record2.get()); + ASSERT_NE(systemDefinedRecord2, nullptr); + CompareDetails(systemDefinedRecord2->GetDetails()); + + auto systemDefinedForm2 = static_cast<SystemDefinedForm *>(record2.get()); + ASSERT_NE(systemDefinedForm2, nullptr); + EXPECT_EQ(systemDefinedForm1.GetFormId(), systemDefinedForm2->GetFormId()); + EXPECT_EQ(systemDefinedForm1.GetFormName(), systemDefinedForm2->GetFormName()); + EXPECT_EQ(systemDefinedForm1.GetBundleName(), systemDefinedForm2->GetBundleName()); + EXPECT_EQ(systemDefinedForm1.GetAbilityName(), systemDefinedForm2->GetAbilityName()); + EXPECT_EQ(systemDefinedForm1.GetModule(), systemDefinedForm2->GetModule()); + + GetEmptyData(option2); + + LOG_INFO(UDMF_TEST, "SetData012 end."); +} + +/** +* @tc.name: SetData013 +* @tc.desc: Set AppItem record with valid params and get data +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientTest, SetData013, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SetData013 begin."); + + CustomOption option1 = { .intention = Intention::UD_INTENTION_DRAG }; + UnifiedData data1; + std::string key; + SystemDefinedAppItem systemDefinedAppItem1; + UDDetails details1; + details1.insert({ "udmf_key", "udmf_value" }); + systemDefinedAppItem1.SetDetails(details1); + systemDefinedAppItem1.SetAppId("appId"); + systemDefinedAppItem1.SetAppName("appName"); + systemDefinedAppItem1.SetAppIconId("appIconId"); + systemDefinedAppItem1.SetAppLabelId("appLabelId"); + systemDefinedAppItem1.SetBundleName("bundleName"); + systemDefinedAppItem1.SetAbilityName("abilityName"); + std::shared_ptr<UnifiedRecord> record1 = std::make_shared<SystemDefinedAppItem>(systemDefinedAppItem1); + data1.AddRecord(record1); + auto status = UdmfClient::GetInstance().SetData(option1, data1, key); + ASSERT_EQ(status, E_OK); + + QueryOption option2 = { .key = key }; + AddPrivilege(option2); + SetHapToken2(); + UnifiedData data2; + status = UdmfClient::GetInstance().GetData(option2, data2); + ASSERT_EQ(status, E_OK); + + std::shared_ptr<UnifiedRecord> record2 = data2.GetRecordAt(0); + ASSERT_NE(record2, nullptr); + auto type = record2->GetType(); + ASSERT_EQ(type, UDType::SYSTEM_DEFINED_APP_ITEM); + + auto systemDefinedRecord2 = static_cast<SystemDefinedRecord *>(record2.get()); + ASSERT_NE(systemDefinedRecord2, nullptr); + CompareDetails(systemDefinedRecord2->GetDetails()); + + auto systemDefinedAppItem2 = static_cast<SystemDefinedAppItem *>(record2.get()); + ASSERT_NE(systemDefinedAppItem2, nullptr); + EXPECT_EQ(systemDefinedAppItem1.GetAppId(), systemDefinedAppItem2->GetAppId()); + EXPECT_EQ(systemDefinedAppItem1.GetAppName(), systemDefinedAppItem2->GetAppName()); + EXPECT_EQ(systemDefinedAppItem1.GetBundleName(), systemDefinedAppItem2->GetBundleName()); + EXPECT_EQ(systemDefinedAppItem1.GetAbilityName(), systemDefinedAppItem2->GetAbilityName()); + EXPECT_EQ(systemDefinedAppItem1.GetAppIconId(), systemDefinedAppItem2->GetAppIconId()); + EXPECT_EQ(systemDefinedAppItem1.GetAppLabelId(), systemDefinedAppItem2->GetAppLabelId()); + + GetEmptyData(option2); + + LOG_INFO(UDMF_TEST, "SetData013 end."); +} + +/** +* @tc.name: SetData014 +* @tc.desc: Set PixelMap record with valid params and get data +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientTest, SetData014, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SetData014 begin."); + + CustomOption option1 = { .intention = Intention::UD_INTENTION_DRAG }; + UnifiedData data1; + std::string key; + SystemDefinedPixelMap systemDefinedPixelMap1; + UDDetails details1; + details1.insert({ "udmf_key", "udmf_value" }); + systemDefinedPixelMap1.SetDetails(details1); + std::vector<uint8_t> rawData1 = { 1, 2, 3, 4, 5 }; + systemDefinedPixelMap1.SetRawData(rawData1); + std::shared_ptr<UnifiedRecord> record1 = std::make_shared<SystemDefinedPixelMap>(systemDefinedPixelMap1); + data1.AddRecord(record1); + auto status = UdmfClient::GetInstance().SetData(option1, data1, key); + ASSERT_EQ(status, E_OK); + + QueryOption option2 = { .key = key }; + AddPrivilege(option2); + SetHapToken2(); + UnifiedData data2; + status = UdmfClient::GetInstance().GetData(option2, data2); + ASSERT_EQ(status, E_OK); + + std::shared_ptr<UnifiedRecord> record2 = data2.GetRecordAt(0); + ASSERT_NE(record2, nullptr); + auto type = record2->GetType(); + ASSERT_EQ(type, UDType::SYSTEM_DEFINED_PIXEL_MAP); + + auto systemDefinedRecord2 = static_cast<SystemDefinedRecord *>(record2.get()); + ASSERT_NE(systemDefinedRecord2, nullptr); + CompareDetails(systemDefinedRecord2->GetDetails()); + + auto systemDefinedPixelMap2 = static_cast<SystemDefinedPixelMap *>(record2.get()); + ASSERT_NE(systemDefinedPixelMap2, nullptr); + auto rawData2 = systemDefinedPixelMap2->GetRawData(); + EXPECT_EQ(rawData1.size(), rawData2.size()); + for (uint32_t i = 0; i < rawData1.size(); ++i) { + EXPECT_EQ(rawData1[i], rawData2[i]); + } + + GetEmptyData(option2); + + LOG_INFO(UDMF_TEST, "SetData014 end."); +} + +/** +* @tc.name: SetData015 +* @tc.desc: Set Application Defined record with valid params and get data +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientTest, SetData015, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SetData015 begin."); + + CustomOption option1 = { .intention = Intention::UD_INTENTION_DRAG }; + UnifiedData data1; + std::string key; + ApplicationDefinedRecord applicationDefinedRecord1; + applicationDefinedRecord1.SetApplicationDefinedType("applicationDefinedType"); + std::vector<uint8_t> rawData1 = { 1, 2, 3, 4, 5 }; + applicationDefinedRecord1.SetRawData(rawData1); + std::shared_ptr<UnifiedRecord> record1 = std::make_shared<ApplicationDefinedRecord>(applicationDefinedRecord1); + data1.AddRecord(record1); + auto status = UdmfClient::GetInstance().SetData(option1, data1, key); + ASSERT_EQ(status, E_OK); + + QueryOption option2 = { .key = key }; + AddPrivilege(option2); + SetHapToken2(); + UnifiedData data2; + status = UdmfClient::GetInstance().GetData(option2, data2); + ASSERT_EQ(status, E_OK); + + std::shared_ptr<UnifiedRecord> record2 = data2.GetRecordAt(0); + ASSERT_NE(record2, nullptr); + auto type = record2->GetType(); + ASSERT_EQ(type, UDType::APPLICATION_DEFINED_RECORD); + + auto applicationDefinedRecord2 = static_cast<ApplicationDefinedRecord *>(record2.get()); + ASSERT_NE(applicationDefinedRecord2, nullptr); + EXPECT_EQ(applicationDefinedRecord1.GetApplicationDefinedType(), + applicationDefinedRecord2->GetApplicationDefinedType()); + auto rawData2 = applicationDefinedRecord2->GetRawData(); + EXPECT_EQ(rawData1.size(), rawData2.size()); + for (uint32_t i = 0; i < rawData1.size(); ++i) { + EXPECT_EQ(rawData1[i], rawData2[i]); + } + + GetEmptyData(option2); + + LOG_INFO(UDMF_TEST, "SetData015 end."); +} + +/** +* @tc.name: SetData016 +* @tc.desc: Set multiple record with valid params and get data +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientTest, SetData016, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SetData016 begin."); + + CustomOption customOption = {.intention = Intention::UD_INTENTION_DRAG}; + std::string key; + UnifiedData inputData; + std::vector<std::shared_ptr<UnifiedRecord>> inputRecords = { + std::make_shared<Text>(), + std::make_shared<PlainText>(), + std::make_shared<File>(), + std::make_shared<Image>(), + std::make_shared<SystemDefinedRecord>(), + std::make_shared<SystemDefinedForm>(), + std::make_shared<ApplicationDefinedRecord>() + }; + inputData.SetRecords(inputRecords); + + auto status = UdmfClient::GetInstance().SetData(customOption, inputData, key); + ASSERT_EQ(status, E_OK); + + QueryOption queryOption = { .key = key }; + UnifiedData outputData; + status = UdmfClient::GetInstance().GetData(queryOption, outputData); + ASSERT_EQ(status, E_OK); + auto outputRecords = outputData.GetRecords(); + ASSERT_EQ(inputRecords.size(), outputRecords.size()); + for (size_t i = 0; i < outputRecords.size(); ++i) { + ASSERT_EQ(outputRecords[i]->GetType(), inputRecords[i]->GetType()); + } + + LOG_INFO(UDMF_TEST, "SetData016 end."); +} + +/** +* @tc.name: SetData017 +* @tc.desc: Set 512 records with valid params and get data +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientTest, SetData017, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SetData017 begin."); + + CustomOption customOption = {.intention = Intention::UD_INTENTION_DRAG}; + std::string key; + UnifiedData inputData; + std::vector<std::shared_ptr<UnifiedRecord>> inputRecords; + for (int32_t i = 0; i < 512; ++i) { + inputRecords.emplace_back(std::make_shared<Text>()); + } + inputData.SetRecords(inputRecords); + + auto status = UdmfClient::GetInstance().SetData(customOption, inputData, key); + ASSERT_EQ(status, E_OK); + + QueryOption queryOption = { .key = key }; + UnifiedData outputData; + status = UdmfClient::GetInstance().GetData(queryOption, outputData); + ASSERT_EQ(status, E_OK); + auto outputRecords = outputData.GetRecords(); + ASSERT_EQ(inputRecords.size(), outputRecords.size()); + + LOG_INFO(UDMF_TEST, "SetData017 end."); +} + +/** +* @tc.name: SetData018 +* @tc.desc: Set one 2MB record of data with valid params and get data +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientTest, SetData018, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SetData018 begin."); + + CustomOption customOption = { .intention = Intention::UD_INTENTION_DRAG }; + UnifiedData inputData; + std::string key; + UDDetails details; + std::string value; + int64_t maxSize = 512 * 1024; + for (int64_t i = 0; i < maxSize; ++i) { + value += "11"; + } + details.insert({ value, value }); + Text text; + text.SetDetails(details); + std::shared_ptr<UnifiedRecord> record = std::make_shared<Text>(text); + inputData.AddRecord(record); + + auto status = UdmfClient::GetInstance().SetData(customOption, inputData, key); + ASSERT_EQ(status, E_OK); + + QueryOption queryOption = { .key = key }; + UnifiedData outputData; + status = UdmfClient::GetInstance().GetData(queryOption, outputData); + ASSERT_EQ(status, E_OK); + + LOG_INFO(UDMF_TEST, "SetData018 end."); +} + +/** +* @tc.name: SetData019 +* @tc.desc: Set one over 4MB record of data with valid params and get data +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientTest, SetData019, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SetData019 begin."); + + CustomOption customOption = { .intention = Intention::UD_INTENTION_DRAG }; + UnifiedData inputData; + std::string key; + UDDetails details; + std::string value; + int64_t maxSize = 512 * 1024; + for (int64_t i = 0; i < maxSize; ++i) { + value += "1111"; + } + details.insert({ value, value }); + details.insert({ "udmf_key", "udmf_value" }); + Text text; + text.SetDetails(details); + std::shared_ptr<UnifiedRecord> record = std::make_shared<Text>(text); + inputData.AddRecord(record); + + auto status = UdmfClient::GetInstance().SetData(customOption, inputData, key); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + + LOG_INFO(UDMF_TEST, "SetData019 end."); +} + +/** +* @tc.name: SetData020 +* @tc.desc: Set two 2MB record of data with valid params and get data +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientTest, SetData020, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SetData020 begin."); + + CustomOption customOption = { .intention = Intention::UD_INTENTION_DRAG }; + UnifiedData inputData; + std::string key; + UDDetails details; + std::string value; + int64_t maxSize = 512 * 1024; + for (int64_t i = 0; i < maxSize; ++i) { + value += "11"; + } + details.insert({ value, value }); + Text text; + text.SetDetails(details); + std::shared_ptr<UnifiedRecord> record = std::make_shared<Text>(text); + for (int i = 0; i < 2; ++i) { + inputData.AddRecord(record); + } + auto status = UdmfClient::GetInstance().SetData(customOption, inputData, key); + ASSERT_EQ(status, E_OK); + + QueryOption queryOption = { .key = key }; + UnifiedData outputData; + status = UdmfClient::GetInstance().GetData(queryOption, outputData); + ASSERT_EQ(status, E_OK); + + LOG_INFO(UDMF_TEST, "SetData020 end."); +} + +/** +* @tc.name: GetData001 +* @tc.desc: Get data with invalid key +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientTest, GetData001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetData001 begin."); + + QueryOption option; + UnifiedData data; + auto status = UdmfClient::GetInstance().GetData(option, data); + EXPECT_EQ(status, E_INVALID_PARAMETERS); + + option.key = "udmf"; + status = UdmfClient::GetInstance().GetData(option, data); + EXPECT_EQ(status, E_INVALID_PARAMETERS); + + option.key = "odmf://"; + status = UdmfClient::GetInstance().GetData(option, data); + EXPECT_EQ(status, E_INVALID_PARAMETERS); + + option.key = "udmf://drag"; + status = UdmfClient::GetInstance().GetData(option, data); + EXPECT_EQ(status, E_INVALID_PARAMETERS); + + option.key = "udmf://123/bundle/group"; + status = UdmfClient::GetInstance().GetData(option, data); + EXPECT_EQ(status, E_INVALID_PARAMETERS); + + option.key = "udmf://drag/bundle"; + status = UdmfClient::GetInstance().GetData(option, data); + EXPECT_EQ(status, E_INVALID_PARAMETERS); + + option.key = "udmf://drag/bundle***/group"; + status = UdmfClient::GetInstance().GetData(option, data); + EXPECT_EQ(status, E_INVALID_PARAMETERS); + + option.key = "udmf://drag/bundle/"; + status = UdmfClient::GetInstance().GetData(option, data); + EXPECT_EQ(status, E_INVALID_PARAMETERS); + + option.key = "udmf://drag/bundle/group###"; + status = UdmfClient::GetInstance().GetData(option, data); + EXPECT_EQ(status, E_INVALID_PARAMETERS); + + LOG_INFO(UDMF_TEST, "GetData001 end."); +} + +/** +* @tc.name: GetSummary001 +* @tc.desc: Get summary data +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientTest, GetSummary001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetSummary001 begin."); + + CustomOption option1 = { .intention = Intention::UD_INTENTION_DRAG }; + UnifiedData data; + std::string key; + + UDDetails details; + details.insert({ "udmf_key", "udmf_value" }); + + Text text; + text.SetDetails(details); + std::shared_ptr<UnifiedRecord> record1 = std::make_shared<Text>(text); + data.AddRecord(record1); + + PlainText plainText; + plainText.SetDetails(details); + plainText.SetContent("content"); + plainText.SetAbstract("abstract"); + std::shared_ptr<UnifiedRecord> record2 = std::make_shared<PlainText>(plainText); + data.AddRecord(record2); + + File file; + file.SetDetails(details); + file.SetUri("uri"); + file.SetRemoteUri("remoteUri"); + std::shared_ptr<UnifiedRecord> record3 = std::make_shared<File>(file); + data.AddRecord(record3); + + Image image; + file.SetDetails(details); + image.SetUri("uri"); + image.SetRemoteUri("remoteUri"); + std::shared_ptr<UnifiedRecord> record4 = std::make_shared<Image>(image); + data.AddRecord(record4); + + SystemDefinedRecord systemDefinedRecord; + systemDefinedRecord.SetDetails(details); + std::shared_ptr<UnifiedRecord> record5 = std::make_shared<SystemDefinedRecord>(systemDefinedRecord); + data.AddRecord(record5); + + SystemDefinedForm systemDefinedForm; + systemDefinedForm.SetDetails(details); + systemDefinedForm.SetFormId(123); + systemDefinedForm.SetFormName("formName"); + systemDefinedForm.SetModule("module"); + systemDefinedForm.SetAbilityName("abilityName"); + systemDefinedForm.SetBundleName("bundleName"); + std::shared_ptr<UnifiedRecord> record6 = std::make_shared<SystemDefinedForm>(systemDefinedForm); + data.AddRecord(record6); + + ApplicationDefinedRecord applicationDefinedRecord; + applicationDefinedRecord.SetApplicationDefinedType("applicationDefinedType"); + std::vector<uint8_t> rawData = { 1, 2, 3, 4, 5 }; + applicationDefinedRecord.SetRawData(rawData); + std::shared_ptr<UnifiedRecord> record7 = std::make_shared<ApplicationDefinedRecord>(applicationDefinedRecord); + data.AddRecord(record7); + + auto status = UdmfClient::GetInstance().SetData(option1, data, key); + ASSERT_EQ(status, E_OK); + + QueryOption option2 = { .key = key }; + Summary summary; + status = UdmfClient::GetInstance().GetSummary(option2, summary); + + auto size = record1->GetSize(); + size += record2->GetSize(); + size += record3->GetSize(); + size += record4->GetSize(); + size += record5->GetSize(); + size += record6->GetSize(); + size += record7->GetSize(); + + ASSERT_EQ(status, E_OK); + ASSERT_EQ(summary.totalSize, size); + ASSERT_EQ(summary.summary["Text"], record1->GetSize()); + ASSERT_EQ(summary.summary["Text.PlainText"], record2->GetSize()); + ASSERT_EQ(summary.summary["File"], record3->GetSize()); + ASSERT_EQ(summary.summary["File.Media.Image"], record4->GetSize()); + ASSERT_EQ(summary.summary["SystemDefinedType"], record5->GetSize()); + ASSERT_EQ(summary.summary["SystemDefinedType.Form"], record6->GetSize()); + ASSERT_EQ(summary.summary["ApplicationDefinedType"], record7->GetSize()); + + LOG_INFO(UDMF_TEST, "GetSummary001 end."); +} + + +/** +* @tc.name: GetSummary002 +* @tc.desc: Get summary with invalid key +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientTest, GetSummary002, TestSize.Level1) +{ + LOG_INFO(UDMF_FRAMEWORK, "GetSummary002 begin."); + + QueryOption option; + Summary summary; + auto status = UdmfClient::GetInstance().GetSummary(option, summary); + EXPECT_EQ(status, E_INVALID_PARAMETERS); + + option.key = "udmf"; + status = UdmfClient::GetInstance().GetSummary(option, summary); + EXPECT_EQ(status, E_INVALID_PARAMETERS); + + option.key = "odmf://"; + status = UdmfClient::GetInstance().GetSummary(option, summary); + EXPECT_EQ(status, E_INVALID_PARAMETERS); + + option.key = "udmf://drag"; + status = UdmfClient::GetInstance().GetSummary(option, summary); + EXPECT_EQ(status, E_INVALID_PARAMETERS); + + option.key = "udmf://123/bundle/group"; + status = UdmfClient::GetInstance().GetSummary(option, summary); + EXPECT_EQ(status, E_INVALID_PARAMETERS); + + option.key = "udmf://drag/bundle"; + status = UdmfClient::GetInstance().GetSummary(option, summary); + EXPECT_EQ(status, E_INVALID_PARAMETERS); + + option.key = "udmf://drag/bundle***/group"; + status = UdmfClient::GetInstance().GetSummary(option, summary); + EXPECT_EQ(status, E_INVALID_PARAMETERS); + + option.key = "udmf://drag/bundle/"; + status = UdmfClient::GetInstance().GetSummary(option, summary); + EXPECT_EQ(status, E_INVALID_PARAMETERS); + + option.key = "udmf://drag/bundle/group###"; + status = UdmfClient::GetInstance().GetSummary(option, summary); + EXPECT_EQ(status, E_INVALID_PARAMETERS); + + LOG_INFO(UDMF_FRAMEWORK, "GetSummary002 end."); +} + +/** +* @tc.name: AddPrivilege001 +* @tc.desc: Add privilege with valid params +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientTest, AddPrivilege001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "AddPrivilege001 begin."); + + CustomOption option1 = { .intention = Intention::UD_INTENTION_DRAG }; + UnifiedData data; + Text text; + UDDetails details; + details.insert({ "udmf_key", "udmf_value" }); + text.SetDetails(details); + std::shared_ptr<UnifiedRecord> record = std::make_shared<Text>(text); + data.AddRecord(record); + std::string key; + auto status = UdmfClient::GetInstance().SetData(option1, data, key); + ASSERT_EQ(status, E_OK); + + QueryOption option2 = { .key = key }; + Privilege privilege; + SetHapToken2(); + privilege.tokenId = AccessTokenKit::GetHapTokenID(100, "ohos.test.demo2", 0); + privilege.readPermission = "readPermission"; + privilege.writePermission = "writePermission"; + SetNativeToken(); + status = UdmfClient::GetInstance().AddPrivilege(option2, privilege); + ASSERT_EQ(status, E_OK); + + LOG_INFO(UDMF_TEST, "AddPrivilege001 end."); +} + +/** +* @tc.name: AddPrivilege002 +* @tc.desc: Add Privilege with invalid params +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientTest, AddPrivilege002, TestSize.Level1) +{ + LOG_INFO(UDMF_FRAMEWORK, "AddPrivilege002 begin."); + + QueryOption option; + Privilege privilege; + auto status = UdmfClient::GetInstance().AddPrivilege(option, privilege); + EXPECT_EQ(status, E_INVALID_PARAMETERS); + + option.key = "udmf"; + status = UdmfClient::GetInstance().AddPrivilege(option, privilege); + EXPECT_EQ(status, E_INVALID_PARAMETERS); + + option.key = "odmf://"; + status = UdmfClient::GetInstance().AddPrivilege(option, privilege); + EXPECT_EQ(status, E_INVALID_PARAMETERS); + + option.key = "udmf://drag"; + status = UdmfClient::GetInstance().AddPrivilege(option, privilege); + EXPECT_EQ(status, E_INVALID_PARAMETERS); + + option.key = "udmf://123/bundle/group"; + status = UdmfClient::GetInstance().AddPrivilege(option, privilege); + EXPECT_EQ(status, E_INVALID_PARAMETERS); + + option.key = "udmf://drag/bundle"; + status = UdmfClient::GetInstance().AddPrivilege(option, privilege); + EXPECT_EQ(status, E_INVALID_PARAMETERS); + + option.key = "udmf://drag/bundle***/group"; + status = UdmfClient::GetInstance().AddPrivilege(option, privilege); + EXPECT_EQ(status, E_INVALID_PARAMETERS); + + option.key = "udmf://drag/bundle/"; + status = UdmfClient::GetInstance().AddPrivilege(option, privilege); + EXPECT_EQ(status, E_INVALID_PARAMETERS); + + option.key = "udmf://drag/bundle/group###"; + status = UdmfClient::GetInstance().AddPrivilege(option, privilege); + EXPECT_EQ(status, E_INVALID_PARAMETERS); + + LOG_INFO(UDMF_FRAMEWORK, "AddPrivilege002 end."); +} + +/** +* @tc.name: GetSelfData001 +* @tc.desc: Set File record with valid params and no add privilege and get data by self +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientTest, GetSelfData001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetSelfData001 begin."); + + CustomOption option1 = { .intention = Intention::UD_INTENTION_DRAG }; + UnifiedData data1; + std::string key; + File file1; + file1.SetRemoteUri("remoteUri"); + UDDetails details1; + details1.insert({ "udmf_key", "udmf_value" }); + file1.SetDetails(details1); + std::shared_ptr<UnifiedRecord> record1 = std::make_shared<File>(file1); + data1.AddRecord(record1); + auto status = UdmfClient::GetInstance().SetData(option1, data1, key); + ASSERT_EQ(status, E_OK); + + QueryOption option2 = { .key = key }; + UnifiedData data2; + status = UdmfClient::GetInstance().GetData(option2, data2); + ASSERT_EQ(status, E_OK); + + std::shared_ptr<UnifiedRecord> record2 = data2.GetRecordAt(0); + ASSERT_NE(record2, nullptr); + auto type = record2->GetType(); + ASSERT_EQ(type, UDType::FILE); + + auto file2 = static_cast<File *>(record2.get()); + ASSERT_NE(file2, nullptr); + EXPECT_EQ(file1.GetRemoteUri(), file2->GetRemoteUri()); + CompareDetails(file2->GetDetails()); + + GetEmptyData(option2); + + LOG_INFO(UDMF_TEST, "GetSelfData001 end."); +} + +/** +* @tc.name: GetSelfData002 +* @tc.desc: Set File record with valid params and add privilege and get data by self +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientTest, GetSelfData002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetSelfData002 begin."); + + CustomOption option1 = { .intention = Intention::UD_INTENTION_DRAG }; + UnifiedData data1; + std::string key; + File file1; + file1.SetRemoteUri("remoteUri"); + UDDetails details1; + details1.insert({ "udmf_key", "udmf_value" }); + file1.SetDetails(details1); + std::shared_ptr<UnifiedRecord> record1 = std::make_shared<File>(file1); + data1.AddRecord(record1); + auto status = UdmfClient::GetInstance().SetData(option1, data1, key); + ASSERT_EQ(status, E_OK); + + QueryOption option2 = { .key = key }; + AddPrivilege(option2); + SetHapToken1(); + UnifiedData data2; + status = UdmfClient::GetInstance().GetData(option2, data2); + ASSERT_EQ(status, E_OK); + + std::shared_ptr<UnifiedRecord> record2 = data2.GetRecordAt(0); + ASSERT_NE(record2, nullptr); + auto type = record2->GetType(); + ASSERT_EQ(type, UDType::FILE); + + auto file2 = static_cast<File *>(record2.get()); + ASSERT_NE(file2, nullptr); + EXPECT_EQ(file1.GetRemoteUri(), file2->GetRemoteUri()); + CompareDetails(file2->GetDetails()); + + GetEmptyData(option2); + + LOG_INFO(UDMF_TEST, "GetSelfData002 end."); +} + +/** +* @tc.name: SetData021 +* @tc.desc: Set datas with intention ${UD_INTENTION_DATA_HUB} and manually check db is cleared before set or not +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientTest, SetData021, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SetData021 begin."); + QueryOption query = { .intention = Intention::UD_INTENTION_DATA_HUB }; + std::vector<UnifiedData> unifiedDataSet; + auto status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + unifiedDataSet.clear(); + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + ASSERT_TRUE(unifiedDataSet.empty()); + + CustomOption customOption = { .intention = Intention::UD_INTENTION_DATA_HUB }; + UnifiedData data1; + PlainText plainText1; + plainText1.SetContent("content1"); + std::shared_ptr<UnifiedRecord> record1 = std::make_shared<PlainText>(plainText1); + data1.AddRecord(record1); + std::string key; + status = UdmfClient::GetInstance().SetData(customOption, data1, key); + ASSERT_EQ(status, E_OK); + + UnifiedData data2; + PlainText plainText2; + plainText1.SetContent("content2"); + std::shared_ptr<UnifiedRecord> record2 = std::make_shared<PlainText>(plainText1); + data2.AddRecord(record2); + status = UdmfClient::GetInstance().SetData(customOption, data2, key); + ASSERT_EQ(status, E_OK); + + SetHapToken2(); + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + auto size = static_cast<int32_t>(unifiedDataSet.size()); + ASSERT_EQ(size, 2); + LOG_INFO(UDMF_TEST, "SetData021 end."); +} + +/** +* @tc.name: UpdateData001 +* @tc.desc: Update data with invalid params +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientTest, UpdateData001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "UpdateData001 begin."); + + UnifiedData data; + QueryOption queryOption = { .key = "" }; + auto status = UdmfClient::GetInstance().UpdateData(queryOption, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + + queryOption = { .key = "udmf://drag/ohos.test.demo1/abcde" }; + status = UdmfClient::GetInstance().UpdateData(queryOption, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + + CustomOption customOption = { .intention = Intention::UD_INTENTION_DATA_HUB }; + UnifiedData data1; + PlainText plainText1; + plainText1.SetContent("content1"); + std::shared_ptr<UnifiedRecord> record1 = std::make_shared<PlainText>(plainText1); + data1.AddRecord(record1); + std::string key; + status = UdmfClient::GetInstance().SetData(customOption, data1, key); + ASSERT_EQ(status, E_OK); + + queryOption = { .key = key }; + SetHapToken2(); + status = UdmfClient::GetInstance().UpdateData(queryOption, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + LOG_INFO(UDMF_TEST, "UpdateData001 end."); +} + +/** +* @tc.name: UpdateData002 +* @tc.desc: Update data with valid params +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientTest, UpdateData002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "UpdateData002 begin."); + + UnifiedData data; + PlainText plainText; + plainText.SetContent("content"); + std::shared_ptr<UnifiedRecord> record = std::make_shared<PlainText>(plainText); + data.AddRecord(record); + + CustomOption customOption = { .intention = Intention::UD_INTENTION_DATA_HUB }; + UnifiedData data1; + PlainText plainText1; + plainText1.SetContent("content1"); + std::shared_ptr<UnifiedRecord> record1 = std::make_shared<PlainText>(plainText1); + data1.AddRecord(record1); + std::string key; + auto status = UdmfClient::GetInstance().SetData(customOption, data1, key); + + ASSERT_EQ(status, E_OK); + QueryOption queryOption = { .key = key }; + SetHapToken2(); + status = UdmfClient::GetInstance().UpdateData(queryOption, data); + ASSERT_EQ(status, E_OK); + + std::vector<UnifiedData> dataSet; + status = UdmfClient::GetInstance().GetBatchData(queryOption, dataSet); + std::shared_ptr<UnifiedRecord> record2 = dataSet[0].GetRecordAt(0); + ASSERT_NE(record2, nullptr); + auto type = record2->GetType(); + ASSERT_EQ(type, UDType::PLAIN_TEXT); + auto plainText2 = static_cast<PlainText *>(record2.get()); + ASSERT_EQ(plainText2->GetContent(), "content"); + + LOG_INFO(UDMF_TEST, "UpdateData002 end."); +} + +/** +* @tc.name: QueryData001 +* @tc.desc: Query data with invalid params +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientTest, QueryData001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "QueryData001 begin."); + std::vector<UnifiedData> unifiedDataSet; + QueryOption queryOption = {}; + auto status = UdmfClient::GetInstance().GetBatchData(queryOption, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + + queryOption = { .key = "udmf://drag/ohos.test.demo1/abcde" }; + status = UdmfClient::GetInstance().GetBatchData(queryOption, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + + queryOption = { .intention = UD_INTENTION_DRAG }; + status = UdmfClient::GetInstance().GetBatchData(queryOption, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + + queryOption = { .key = "udmf://DataHub/ohos.test.demo1/abcde", .intention = UD_INTENTION_DRAG }; + status = UdmfClient::GetInstance().GetBatchData(queryOption, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + + queryOption = { .key = "udmf://drag/ohos.test.demo1/abcde", .intention = UD_INTENTION_DATA_HUB }; + status = UdmfClient::GetInstance().GetBatchData(queryOption, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + LOG_INFO(UDMF_TEST, "QueryData001 end."); +} + +/** +* @tc.name: QueryData002 +* @tc.desc: Query data with valid params +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientTest, QueryData002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "QueryData002 begin."); + + QueryOption query = { .intention = Intention::UD_INTENTION_DATA_HUB }; + std::vector<UnifiedData> unifiedDataSet; + auto status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + unifiedDataSet.clear(); + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + ASSERT_TRUE(unifiedDataSet.empty()); + + CustomOption customOption = { .intention = Intention::UD_INTENTION_DATA_HUB }; + UnifiedData data; + PlainText plainText; + plainText.SetContent("content1"); + std::shared_ptr<UnifiedRecord> record = std::make_shared<PlainText>(plainText); + data.AddRecord(record); + std::string key; + status = UdmfClient::GetInstance().SetData(customOption, data, key); + ASSERT_EQ(status, E_OK); + + query = { .key = key }; + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + auto size = static_cast<int32_t>(unifiedDataSet.size()); + ASSERT_EQ(size, 1); + std::shared_ptr<UnifiedRecord> record2 = unifiedDataSet[0].GetRecordAt(0); + ASSERT_NE(record2, nullptr); + auto type = record2->GetType(); + ASSERT_EQ(type, UDType::PLAIN_TEXT); + auto plainText2 = static_cast<PlainText *>(record2.get()); + ASSERT_EQ(plainText2->GetContent(), "content1"); + + UnifiedData data2; + plainText.SetContent("content2"); + record = std::make_shared<PlainText>(plainText); + data2.AddRecord(record); + status = UdmfClient::GetInstance().SetData(customOption, data2, key); + ASSERT_EQ(status, E_OK); + + unifiedDataSet.clear(); + query = { .key = key, .intention = UD_INTENTION_DATA_HUB }; + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + size = static_cast<int32_t>(unifiedDataSet.size()); + ASSERT_EQ(size, 1); + record2 = unifiedDataSet[0].GetRecordAt(0); + ASSERT_NE(record2, nullptr); + type = record2->GetType(); + ASSERT_EQ(type, UDType::PLAIN_TEXT); + plainText2 = static_cast<PlainText *>(record2.get()); + ASSERT_EQ(plainText2->GetContent(), "content2"); + + unifiedDataSet.clear(); + query = { .intention = UD_INTENTION_DATA_HUB }; + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + size = static_cast<int32_t>(unifiedDataSet.size()); + ASSERT_EQ(size, 2); + + LOG_INFO(UDMF_TEST, "QueryData002 end."); +} + +/** +* @tc.name: DeleteData001 +* @tc.desc: Delete data with invalid params +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientTest, DeleteData001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "DeleteData001 begin."); + std::vector<UnifiedData> unifiedDataSet; + QueryOption queryOption = {}; + auto status = UdmfClient::GetInstance().DeleteData(queryOption, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + + queryOption = { .key = "udmf://drag/ohos.test.demo1/abcde" }; + status = UdmfClient::GetInstance().DeleteData(queryOption, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + + queryOption = { .intention = UD_INTENTION_DRAG }; + status = UdmfClient::GetInstance().DeleteData(queryOption, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + + queryOption = { .key = "udmf://DataHub/ohos.test.demo1/abcde", .intention = UD_INTENTION_DRAG }; + status = UdmfClient::GetInstance().DeleteData(queryOption, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + + queryOption = { .key = "udmf://drag/ohos.test.demo1/abcde", .intention = UD_INTENTION_DATA_HUB }; + status = UdmfClient::GetInstance().DeleteData(queryOption, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + LOG_INFO(UDMF_TEST, "DeleteData001 end."); +} + +/** +* @tc.name: DeleteData002 +* @tc.desc: Delete data with valid params +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientTest, DeleteData002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "DeleteData002 begin."); + + CustomOption customOption = { .intention = UD_INTENTION_DATA_HUB }; + UnifiedData data; + PlainText plainText; + plainText.SetContent("content1"); + std::shared_ptr<UnifiedRecord> record = std::make_shared<PlainText>(plainText); + data.AddRecord(record); + std::string key; + auto status = UdmfClient::GetInstance().SetData(customOption, data, key); + ASSERT_EQ(status, E_OK); + status = UdmfClient::GetInstance().SetData(customOption, data, key); + ASSERT_EQ(status, E_OK); + status = UdmfClient::GetInstance().SetData(customOption, data, key); + ASSERT_EQ(status, E_OK); + + QueryOption queryOption = { .key = key }; + SetHapToken2(); + + std::vector<UnifiedData> unifiedDataSet; + status = UdmfClient::GetInstance().DeleteData(queryOption, unifiedDataSet); + ASSERT_EQ(status, E_OK); + + unifiedDataSet.clear(); + status = UdmfClient::GetInstance().GetBatchData(queryOption, unifiedDataSet); + ASSERT_TRUE(unifiedDataSet.empty()); + + queryOption = { .intention = UD_INTENTION_DATA_HUB }; + unifiedDataSet.clear(); + status = UdmfClient::GetInstance().GetBatchData(queryOption, unifiedDataSet); + ASSERT_TRUE(!unifiedDataSet.empty()); + + status = UdmfClient::GetInstance().DeleteData(queryOption, unifiedDataSet); + ASSERT_EQ(status, E_OK); + + unifiedDataSet.clear(); + status = UdmfClient::GetInstance().GetBatchData(queryOption, unifiedDataSet); + ASSERT_TRUE(unifiedDataSet.empty()); + LOG_INFO(UDMF_TEST, "DeleteData002 end."); +} +} // OHOS::Test \ No newline at end of file diff --git a/udmf/framework/jskitsimpl/common/napi_data_utils.cpp b/udmf/framework/jskitsimpl/common/napi_data_utils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8ec95699daf0360df5bea19987cab2a179315517 --- /dev/null +++ b/udmf/framework/jskitsimpl/common/napi_data_utils.cpp @@ -0,0 +1,443 @@ +/* + * 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 "napi_data_utils.h" + +#include "napi_queue.h" + +namespace OHOS { +namespace UDMF { +constexpr int32_t STR_MAX_LENGTH = 4096; +constexpr size_t STR_TAIL_LENGTH = 1; + +/* napi_value <-> bool */ +napi_status NapiDataUtils::GetValue(napi_env env, napi_value in, bool &out) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "napi_value <- bool"); + return napi_get_value_bool(env, in, &out); +} + +napi_status NapiDataUtils::SetValue(napi_env env, const bool &in, napi_value &out) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "napi_value -> bool"); + return napi_get_boolean(env, in, &out); +} + +/* napi_value <-> int32_t */ +napi_status NapiDataUtils::GetValue(napi_env env, napi_value in, int32_t &out) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "napi_value -> int32_t"); + return napi_get_value_int32(env, in, &out); +} + +napi_status NapiDataUtils::SetValue(napi_env env, const int32_t &in, napi_value &out) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "napi_value <- int32_t"); + return napi_create_int32(env, in, &out); +} + +/* napi_value <-> int64_t */ +napi_status NapiDataUtils::GetValue(napi_env env, napi_value in, int64_t &out) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "napi_value -> int64_t"); + return napi_get_value_int64(env, in, &out); +} + +napi_status NapiDataUtils::SetValue(napi_env env, const int64_t &in, napi_value &out) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "napi_value <- int64_t"); + return napi_create_int64(env, in, &out); +} + +/* napi_value <-> float */ +napi_status NapiDataUtils::GetValue(napi_env env, napi_value in, float &out) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "napi_value -> float"); + double tmp; + napi_status status = napi_get_value_double(env, in, &tmp); + out = tmp; + return status; +} + +napi_status NapiDataUtils::SetValue(napi_env env, const float &in, napi_value &out) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "napi_value <- float"); + double tmp = in; + return napi_create_double(env, tmp, &out); +} + +/* napi_value <-> double */ +napi_status NapiDataUtils::GetValue(napi_env env, napi_value in, double &out) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "napi_value -> double"); + return napi_get_value_double(env, in, &out); +} + +napi_status NapiDataUtils::SetValue(napi_env env, const double &in, napi_value &out) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "napi_value <- double"); + return napi_create_double(env, in, &out); +} + +/* napi_value <-> std::string */ +napi_status NapiDataUtils::GetValue(napi_env env, napi_value in, std::string &out) +{ + size_t maxLen = STR_MAX_LENGTH; + napi_status status = napi_get_value_string_utf8(env, in, NULL, 0, &maxLen); + if (maxLen == 0) { + GET_AND_THROW_LAST_ERROR(env); + return status; + } + char *buf = new (std::nothrow) char[maxLen + STR_TAIL_LENGTH]; + if (buf != nullptr) { + size_t len = 0; + status = napi_get_value_string_utf8(env, in, buf, maxLen + STR_TAIL_LENGTH, &len); + if (status != napi_ok) { + GET_AND_THROW_LAST_ERROR(env); + } + buf[len] = 0; + out = std::string(buf); + delete[] buf; + } else { + status = napi_generic_failure; + } + return status; +} + +napi_status NapiDataUtils::SetValue(napi_env env, const std::string &in, napi_value &out) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "napi_value <- std::string %{public}d", (int)in.length()); + return napi_create_string_utf8(env, in.c_str(), in.size(), &out); +} + +/* napi_value <-> std::vector<std::string> */ +napi_status NapiDataUtils::GetValue(napi_env env, napi_value in, std::vector<std::string> &out) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "napi_value -> std::vector<std::string>"); + bool isArray = false; + napi_is_array(env, in, &isArray); + LOG_ERROR_RETURN(isArray, "not an array", napi_invalid_arg); + + uint32_t length = 0; + napi_status status = napi_get_array_length(env, in, &length); + LOG_ERROR_RETURN((status == napi_ok) && (length > 0), "get_array failed!", napi_invalid_arg); + for (uint32_t i = 0; i < length; ++i) { + napi_value item = nullptr; + status = napi_get_element(env, in, i, &item); + LOG_ERROR_RETURN((item != nullptr) && (status == napi_ok), "no element", napi_invalid_arg); + std::string value; + status = GetValue(env, item, value); + LOG_ERROR_RETURN(status == napi_ok, "not a string", napi_invalid_arg); + out.push_back(value); + } + return status; +} + +napi_status NapiDataUtils::SetValue(napi_env env, const std::vector<std::string> &in, napi_value &out) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "napi_value <- std::vector<std::string>"); + napi_status status = napi_create_array_with_length(env, in.size(), &out); + LOG_ERROR_RETURN(status == napi_ok, "create array failed!", status); + int index = 0; + for (auto &item : in) { + napi_value element = nullptr; + SetValue(env, item, element); + status = napi_set_element(env, out, index++, element); + LOG_ERROR_RETURN((status == napi_ok), "napi_set_element failed!", status); + } + return status; +} + +/* napi_value <-> std::vector<uint8_t> */ +napi_status NapiDataUtils::GetValue(napi_env env, napi_value in, std::vector<uint8_t> &out) +{ + out.clear(); + LOG_DEBUG(UDMF_KITS_NAPI, "napi_value -> std::vector<uint8_t> "); + napi_typedarray_type type = napi_biguint64_array; + size_t length = 0; + napi_value buffer = nullptr; + size_t offset = 0; + void *data = nullptr; + napi_status status = napi_get_typedarray_info(env, in, &type, &length, &data, &buffer, &offset); + LOG_DEBUG(UDMF_KITS_NAPI, "array type=%{public}d length=%{public}d offset=%{public}d status=%{public}d", + (int)type, (int)length, (int)offset, status); + LOG_ERROR_RETURN(status == napi_ok, "napi_get_typedarray_info failed!", napi_invalid_arg); + LOG_ERROR_RETURN(type == napi_uint8_array, "is not Uint8Array!", napi_invalid_arg); + LOG_ERROR_RETURN((length > 0) && (data != nullptr), "invalid data!", napi_invalid_arg); + out.assign(reinterpret_cast<uint8_t *>(data), reinterpret_cast<uint8_t *>(data) + length); + return status; +} + +napi_status NapiDataUtils::SetValue(napi_env env, const std::vector<uint8_t> &in, napi_value &out) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "napi_value <- std::vector<uint8_t> "); + LOG_ERROR_RETURN(in.size() > 0, "invalid std::vector<uint8_t>", napi_invalid_arg); + void *data = nullptr; + napi_value buffer = nullptr; + napi_status status = napi_create_arraybuffer(env, in.size(), &data, &buffer); + LOG_ERROR_RETURN((status == napi_ok), "create array buffer failed!", status); + + if (memcpy_s(data, in.size(), in.data(), in.size()) != EOK) { + LOG_ERROR(UDMF_KITS_NAPI, "memcpy_s not EOK"); + return napi_invalid_arg; + } + status = napi_create_typedarray(env, napi_uint8_array, in.size(), buffer, 0, &out); + LOG_ERROR_RETURN((status == napi_ok), "napi_value <- std::vector<uint8_t> invalid value", status); + return status; +} + +/* napi_value <-> std::map<std::string, int32_t> */ +napi_status NapiDataUtils::GetValue(napi_env env, napi_value in, std::map<std::string, int32_t> &out) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "napi_value -> std::map<std::string, int32_t> "); + (void)(env); + (void)(in); + (void)(out); + LOG_ERROR_RETURN(false, "std::map<std::string, uint32_t> from napi_value, unsupported!", napi_invalid_arg); + return napi_invalid_arg; +} + +napi_status NapiDataUtils::SetValue(napi_env env, const std::map<std::string, int32_t> &in, napi_value &out) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "napi_value <- std::map<std::string, int32_t> "); + napi_status status = napi_create_array_with_length(env, in.size(), &out); + LOG_ERROR_RETURN((status == napi_ok), "invalid object", status); + int index = 0; + for (const auto &[key, value] : in) { + napi_value element = nullptr; + napi_create_array_with_length(env, TUPLE_SIZE, &element); + napi_value jsKey = nullptr; + napi_create_string_utf8(env, key.c_str(), key.size(), &jsKey); + napi_set_element(env, element, TUPLE_KEY, jsKey); + napi_value jsValue = nullptr; + napi_create_int32(env, static_cast<int32_t>(value), &jsValue); + napi_set_element(env, element, TUPLE_VALUE, jsValue); + napi_set_element(env, out, index++, element); + } + return status; +} + +/* napi_value <-> std::map<std::string, int64_t> */ +napi_status NapiDataUtils::GetValue(napi_env env, napi_value in, std::map<std::string, int64_t> &out) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "napi_value -> std::map<std::string, int64_t> "); + (void)(env); + (void)(in); + (void)(out); + LOG_ERROR_RETURN(false, "std::map<std::string, int64_t> from napi_value, unsupported!", napi_invalid_arg); + return napi_invalid_arg; +} + +napi_status NapiDataUtils::SetValue(napi_env env, const std::map<std::string, int64_t> &in, napi_value &out) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "napi_value <- std::map<std::string, int64_t> "); + napi_status status = napi_create_array_with_length(env, in.size(), &out); + LOG_ERROR_RETURN((status == napi_ok), "invalid object", status); + int index = 0; + for (const auto &[key, value] : in) { + napi_value element = nullptr; + napi_create_array_with_length(env, TUPLE_SIZE, &element); + napi_value jsKey = nullptr; + napi_create_string_utf8(env, key.c_str(), key.size(), &jsKey); + napi_set_element(env, element, TUPLE_KEY, jsKey); + napi_value jsValue = nullptr; + napi_create_int64(env, static_cast<int64_t>(value), &jsValue); + napi_set_element(env, element, TUPLE_VALUE, jsValue); + napi_set_element(env, out, index++, element); + } + return status; +} + +/* napi_value <-> UDVariant */ +napi_status NapiDataUtils::GetValue(napi_env env, napi_value in, UDVariant &out) +{ + napi_valuetype type = napi_undefined; + napi_status status = napi_typeof(env, in, &type); + LOG_ERROR_RETURN((status == napi_ok), "invalid type", status); + switch (type) { + case napi_boolean: { + bool vBool = false; + status = GetValue(env, in, vBool); + out = vBool; + break; + } + case napi_number: { + double vNum = 0.0f; + status = GetValue(env, in, vNum); + out = vNum; + break; + } + case napi_string: { + std::string vString; + status = GetValue(env, in, vString); + out = vString; + break; + } + case napi_object: { + std::vector<uint8_t> vct; + status = GetValue(env, in, vct); + out = vct; + break; + } + default: + LOG_ERROR(UDMF_KITS_NAPI, + "napi_value <- UDVariant not [Uint8Array | string | boolean | number] type=%{public}d", type); + status = napi_invalid_arg; + break; + } + return status; +} + +napi_status NapiDataUtils::SetValue(napi_env env, const UDVariant &in, napi_value &out) +{ + auto strValue = std::get_if<std::string>(&in); + if (strValue != nullptr) { + return SetValue(env, *strValue, out); + } + auto intValue = std::get_if<int32_t>(&in); + if (intValue != nullptr) { + return SetValue(env, *intValue, out); + } + auto pUint8 = std::get_if<std::vector<uint8_t>>(&in); + if (pUint8 != nullptr) { + return SetValue(env, *pUint8, out); + } + auto boolValue = std::get_if<bool>(&in); + if (boolValue != nullptr) { + return SetValue(env, *boolValue, out); + } + auto dblValue = std::get_if<double>(&in); + if (dblValue != nullptr) { + return SetValue(env, *dblValue, out); + } + + LOG_ERROR(UDMF_KITS_NAPI, "napi_value <- UDVariant INVALID value type"); + return napi_invalid_arg; +} + +/* napi_value <-> UDDetails */ +napi_status NapiDataUtils::GetValue(napi_env env, napi_value in, UDDetails &out) +{ + if (!IsTypeForNapiValue(env, in, napi_object)) { + return napi_invalid_arg; + } + napi_value jsProNameList = nullptr; + uint32_t jsProCount = 0; + + NAPI_CALL_BASE(env, napi_get_property_names(env, in, &jsProNameList), napi_invalid_arg); + NAPI_CALL_BASE(env, napi_get_array_length(env, jsProNameList, &jsProCount), napi_invalid_arg); + + napi_value jsProName = nullptr; + napi_value jsProValue = nullptr; + for (uint32_t index = 0; index < jsProCount; index++) { + NAPI_CALL_BASE(env, napi_get_element(env, jsProNameList, index, &jsProName), napi_invalid_arg); + if (!IsTypeForNapiValue(env, jsProName, napi_string)) { + return napi_invalid_arg; + } + std::string strProName; + GetValue(env, jsProName, strProName); + + NAPI_CALL_BASE(env, napi_get_named_property(env, in, strProName.c_str(), &jsProValue), napi_invalid_arg); + UDVariant natValue; + GetValue(env, jsProValue, natValue); + out[strProName] = natValue; + } + return napi_ok; +} + +napi_status NapiDataUtils::SetValue(napi_env env, const UDDetails &in, napi_value &out) +{ + NAPI_CALL_BASE(env, napi_create_object(env, &out), napi_invalid_arg); + for (std::pair<std::string, UDVariant> prop : in) { + napi_value jsProValue = nullptr; + SetValue(env, prop.second, jsProValue); + NAPI_CALL_BASE(env, napi_set_named_property(env, out, prop.first.c_str(), jsProValue), napi_invalid_arg); + } + return napi_ok; +} + +bool NapiDataUtils::IsTypeForNapiValue(napi_env env, napi_value param, napi_valuetype expectType) +{ + napi_valuetype valueType = napi_undefined; + + if (param == nullptr) { + return false; + } + + if (napi_typeof(env, param, &valueType) != napi_ok) { + return false; + } + + return valueType == expectType; +} + +bool NapiDataUtils::IsNull(napi_env env, napi_value value) +{ + napi_valuetype type = napi_undefined; + napi_status status = napi_typeof(env, value, &type); + if (status == napi_ok && (type == napi_undefined || type == napi_null)) { + return true; + } + if (type == napi_string) { + size_t len; + status = napi_get_value_string_utf8(env, value, NULL, 0, &len); + return len == 0; + } + return false; +} + +napi_value NapiDataUtils::DefineClass(napi_env env, const std::string &name, + const napi_property_descriptor *properties, size_t count, napi_callback newcb) +{ + // base64("data.udmf") as rootPropName, i.e. global.<root> + const std::string rootPropName = "ZGF0YS51ZG1m"; + napi_value root = nullptr; + bool hasRoot = false; + napi_value global = nullptr; + napi_get_global(env, &global); + napi_has_named_property(env, global, rootPropName.c_str(), &hasRoot); + if (hasRoot) { + napi_get_named_property(env, global, rootPropName.c_str(), &root); + } else { + napi_create_object(env, &root); + napi_set_named_property(env, global, rootPropName.c_str(), root); + } + + std::string propName = "constructor_of_" + name; + napi_value constructor = nullptr; + bool hasProp = false; + napi_has_named_property(env, root, propName.c_str(), &hasProp); + if (hasProp) { + napi_get_named_property(env, root, propName.c_str(), &constructor); + if (constructor != nullptr) { + LOG_DEBUG(UDMF_KITS_NAPI, "got data.distributeddata.%{public}s as constructor", propName.c_str()); + return constructor; + } + hasProp = false; // no constructor. + } + + NAPI_CALL_BASE(env, + napi_define_class(env, name.c_str(), name.size(), newcb, nullptr, count, properties, &constructor), + nullptr); + NAPI_ASSERT(env, constructor != nullptr, "napi_define_class failed!"); + + if (!hasProp) { + napi_set_named_property(env, root, propName.c_str(), constructor); + LOG_DEBUG(UDMF_KITS_NAPI, "save constructor to data.distributeddata.%{public}s", propName.c_str()); + } + return constructor; +} +} // namespace UDMF +} // namespace OHOS diff --git a/udmf/framework/jskitsimpl/common/napi_error_utils.cpp b/udmf/framework/jskitsimpl/common/napi_error_utils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6b43b7e3572ef536273ec82954a6f7226d3ed915 --- /dev/null +++ b/udmf/framework/jskitsimpl/common/napi_error_utils.cpp @@ -0,0 +1,94 @@ +/* + * 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 "napi_error_utils.h" + +#include <algorithm> + +namespace OHOS { +namespace UDMF { +using NapiErrorCode = OHOS::UDMF::NapiErrorCode; + +static const NapiErrorCode JS_ERROR_CODE_MSGS[] = { + { Status::E_NO_PERMISSION, 201, "Permission denied!" }, + { Status::E_INVALID_PARAMETERS, 401, "Parameter error." }, +}; + +const std::optional<NapiErrorCode> GetErrorCode(int32_t errorCode) +{ + auto napiErrorCode = NapiErrorCode{ 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]), napiErrorCode, + [](const NapiErrorCode &napiErrorCode1, const NapiErrorCode &napiErrorCode2) { + return napiErrorCode1.status < napiErrorCode2.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(Status error, int32_t &errCode, std::string &errMessage) +{ + auto errormsg = GetErrorCode(error); + if (errormsg.has_value()) { + auto napiError = errormsg.value(); + errCode = napiError.jsCode; + errMessage = napiError.message; + } else { + // unmatched status return unified error code + errCode = -1; + errMessage = ""; + } + LOG_DEBUG(UDMF_KITS_NAPI, "GenerateNapiError errCode is %{public}d", errCode); + if (errCode == 0) { + return Status::E_OK; + } + return error; +} + +void ThrowNapiError(napi_env env, int32_t status, const std::string &errMessage, bool isParamsCheck) +{ + LOG_INFO(UDMF_KITS_NAPI, "ThrowNapiError message: %{public}s", errMessage.c_str()); + if (status == Status::E_OK) { + return; + } + auto errorMsg = GetErrorCode(status); + NapiErrorCode napiError; + if (errorMsg.has_value()) { + napiError = errorMsg.value(); + } else { + napiError.jsCode = -1; + napiError.message = ""; + } + + std::string message(napiError.message); + if (isParamsCheck) { + auto paramsCheckError = 401; + napiError.jsCode = paramsCheckError; + 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 UDMF +} // namespace OHOS diff --git a/udmf/framework/jskitsimpl/common/napi_queue.cpp b/udmf/framework/jskitsimpl/common/napi_queue.cpp new file mode 100644 index 0000000000000000000000000000000000000000..63b63ce34dfbbf6ad1c595214554340e96dbb915 --- /dev/null +++ b/udmf/framework/jskitsimpl/common/napi_queue.cpp @@ -0,0 +1,175 @@ +/* + * 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 "napi_queue.h" + +#include "logger.h" + +namespace OHOS { +namespace UDMF { +ContextBase::~ContextBase() +{ + LOG_DEBUG(UDMF_KITS_NAPI, "no memory leak after callback or promise[resolved/rejected]"); + if (env != nullptr) { + if (work != nullptr) { + napi_delete_async_work(env, work); + } + if (callbackRef != nullptr) { + napi_delete_reference(env, callbackRef); + } + napi_delete_reference(env, selfRef); + 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 :: <callback> + 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; + LOG_DEBUG(UDMF_KITS_NAPI, "async callback, no promise"); + } else { + LOG_DEBUG(UDMF_KITS_NAPI, "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<ContextBase> ctxt, const std::string &name, + NapiAsyncExecute execute, NapiAsyncComplete complete) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "NapiQueue::AsyncWork name = %{public}s", name.c_str()); + ctxt->execute = std::move(execute); + ctxt->complete = std::move(complete); + LOG_DEBUG(UDMF_KITS_NAPI, "NapiQueue::AsyncWork move func finish"); + napi_value promise = nullptr; + if (ctxt->callbackRef == nullptr) { + LOG_DEBUG(UDMF_KITS_NAPI, "NapiQueue::AsyncWork has promise"); + napi_create_promise(ctxt->env, &ctxt->deferred, &promise); + LOG_DEBUG(UDMF_KITS_NAPI, "create deferred promise"); + } else { + LOG_DEBUG(UDMF_KITS_NAPI, "NapiQueue::AsyncWork no promise"); + napi_get_undefined(ctxt->env, &promise); + } + napi_value resource = nullptr; + LOG_DEBUG(UDMF_KITS_NAPI, "NapiQueue::AsyncWork create string start"); + napi_create_string_utf8(ctxt->env, name.c_str(), NAPI_AUTO_LENGTH, &resource); + LOG_DEBUG(UDMF_KITS_NAPI, "NapiQueue::AsyncWork create string finish"); + napi_create_async_work(ctxt->env, nullptr, resource, + [](napi_env env, void *data) { + LOG_DEBUG(UDMF_KITS_NAPI, "NapiQueue::AsyncWork start execute"); + ASSERT_VOID(data != nullptr, "no data"); + auto ctxt = reinterpret_cast<ContextBase *>(data); + LOG_DEBUG(UDMF_KITS_NAPI, "napi_async_execute_callback ctxt->status = %{public}d", ctxt->status); + if (ctxt->execute && ctxt->status == napi_ok) { + LOG_DEBUG(UDMF_KITS_NAPI, "NapiQueue::AsyncWork do user design execute"); + ctxt->execute(); + } + LOG_DEBUG(UDMF_KITS_NAPI, "NapiQueue::AsyncWork finish execute"); + }, + [](napi_env env, napi_status status, void *data) { + LOG_DEBUG(UDMF_KITS_NAPI, "NapiQueue::AsyncWork start output"); + ASSERT_VOID(data != nullptr, "no data"); + auto ctxt = reinterpret_cast<ContextBase *>(data); + LOG_DEBUG(UDMF_KITS_NAPI, "napi_async_complete_callback status = %{public}d, ctxt->status = %{public}d", + status, ctxt->status); + if ((status != napi_ok) && (ctxt->status == napi_ok)) { + LOG_DEBUG(UDMF_KITS_NAPI, "NapiQueue::AsyncWork check status"); + ctxt->status = status; + } + if ((ctxt->complete) && (status == napi_ok) && (ctxt->status == napi_ok)) { + LOG_DEBUG(UDMF_KITS_NAPI, "NapiQueue::AsyncWork do user design output"); + ctxt->complete(ctxt->output); + } + GenerateOutput(ctxt); + LOG_DEBUG(UDMF_KITS_NAPI, "NapiQueue::AsyncWork finish output"); + }, + reinterpret_cast<void *>(ctxt.get()), &ctxt->work); + napi_queue_async_work(ctxt->env, ctxt->work); + ctxt->hold = ctxt; // save crossing-thread ctxt. + return promise; +} + +void NapiQueue::GenerateOutput(ContextBase *ctxt) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "GenerateOutput start"); + napi_value result[RESULT_ALL] = { nullptr }; + LOG_DEBUG(UDMF_KITS_NAPI, "GenerateOutput ctxt->status = %{public}d", ctxt->status); + if (ctxt->status == napi_ok) { + napi_get_undefined(ctxt->env, &result[RESULT_ERROR]); + if (ctxt->output == nullptr) { + napi_get_undefined(ctxt->env, &ctxt->output); + } + result[RESULT_DATA] = ctxt->output; + } else { + napi_value code = nullptr; + napi_value message = nullptr; + if (ctxt->jsCode != 0 && ctxt->jsCode != -1) { + napi_create_string_utf8(ctxt->env, std::to_string(ctxt->jsCode).c_str(), NAPI_AUTO_LENGTH, &code); + } + if (ctxt->jsCode == -1) { + std::string jsCode; + napi_create_string_utf8(ctxt->env, jsCode.c_str(), NAPI_AUTO_LENGTH, &code); + } + napi_create_string_utf8(ctxt->env, ctxt->error.c_str(), NAPI_AUTO_LENGTH, &message); + napi_create_error(ctxt->env, code, message, &result[RESULT_ERROR]); + napi_get_undefined(ctxt->env, &result[RESULT_DATA]); + } + if (ctxt->deferred != nullptr) { + LOG_DEBUG(UDMF_KITS_NAPI, "GenerateOutput deferred branch"); + if (ctxt->status == napi_ok) { + LOG_DEBUG(UDMF_KITS_NAPI, "deferred promise resolved"); + napi_resolve_deferred(ctxt->env, ctxt->deferred, result[RESULT_DATA]); + } else { + LOG_DEBUG(UDMF_KITS_NAPI, "deferred promise rejected"); + napi_reject_deferred(ctxt->env, ctxt->deferred, result[RESULT_ERROR]); + } + } else { + napi_value callback = nullptr; + napi_get_reference_value(ctxt->env, ctxt->callbackRef, &callback); + napi_value callbackResult = nullptr; + LOG_INFO(UDMF_KITS_NAPI, "GenerateOutput call callback function"); + LOG_DEBUG(UDMF_KITS_NAPI, "call callback function"); + napi_call_function(ctxt->env, nullptr, callback, RESULT_ALL, result, &callbackResult); + } + ctxt->hold.reset(); // release ctxt. + LOG_DEBUG(UDMF_KITS_NAPI, "GenerateOutput stop"); +} +} // namespace UDMF +} // namespace OHOS diff --git a/udmf/framework/jskitsimpl/data/application_defined_record_napi.cpp b/udmf/framework/jskitsimpl/data/application_defined_record_napi.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bf52d0963c3351239cfe03ff854d7fec573e8a1c --- /dev/null +++ b/udmf/framework/jskitsimpl/data/application_defined_record_napi.cpp @@ -0,0 +1,143 @@ +/* + * 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 "application_defined_record_napi.h" + +#include "application_defined_record.h" +#include "napi_data_utils.h" +#include "napi_error_utils.h" +#include "napi_queue.h" +#include "unified_record_napi.h" + +namespace OHOS { +namespace UDMF { +napi_value ApplicationDefinedRecordNapi::Constructor(napi_env env) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "ApplicationDefinedRecordNapi"); + napi_property_descriptor properties[] = { + /* ApplicationDefinedRecord extends UnifiedRecord */ + DECLARE_NAPI_FUNCTION("getType", UnifiedRecordNapi::GetType), + /* ApplicationDefinedRecord properties */ + DECLARE_NAPI_GETTER_SETTER("applicationDefinedType", GetApplicationDefinedType, SetApplicationDefinedType), + DECLARE_NAPI_GETTER_SETTER("rawData", GetRawData, SetRawData), + }; + size_t count = sizeof(properties) / sizeof(properties[0]); + return NapiDataUtils::DefineClass( + env, "ApplicationDefinedRecord", properties, count, ApplicationDefinedRecordNapi::New); +} + +napi_value ApplicationDefinedRecordNapi::New(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "ApplicationDefinedRecordNapi"); + auto ctxt = std::make_shared<ContextBase>(); + ctxt->GetCbInfoSync(env, info); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + + auto *record = new (std::nothrow) ApplicationDefinedRecordNapi(); + ASSERT_ERR(ctxt->env, record != nullptr, Status::E_UNKNOWN, "no memory for application defined record!"); + record->value_ = std::make_shared<ApplicationDefinedRecord>(); + ASSERT_CALL(ctxt->env, napi_wrap(env, ctxt->self, record, Destructor, nullptr, nullptr), record); + return ctxt->self; +} + +void ApplicationDefinedRecordNapi::NewInstance(napi_env env, std::shared_ptr<UnifiedRecord> in, napi_value &out) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "ApplicationDefinedRecordNapi"); + ASSERT_CALL_VOID(env, napi_new_instance(env, Constructor(env), 0, nullptr, &out)); + auto *record = new (std::nothrow) ApplicationDefinedRecordNapi(); + ASSERT_ERR_VOID(env, record != nullptr, Status::E_UNKNOWN, "no memory for application defined record!"); + record->value_ = std::static_pointer_cast<ApplicationDefinedRecord>(in); + ASSERT_CALL_DELETE(env, napi_wrap(env, out, record, Destructor, nullptr, nullptr), record); +} + +void ApplicationDefinedRecordNapi::Destructor(napi_env env, void *data, void *hint) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "ApplicationDefinedRecordNapi finalize."); + auto *record = static_cast<ApplicationDefinedRecordNapi *>(data); + ASSERT_VOID(record != nullptr, "finalize null!"); + delete record; +} + +ApplicationDefinedRecordNapi *ApplicationDefinedRecordNapi::GetApplicationDefinedRecord( + napi_env env, napi_callback_info info, std::shared_ptr<ContextBase> ctxt) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "ApplicationDefinedRecordNapi"); + ctxt->GetCbInfoSync(env, info); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + return static_cast<ApplicationDefinedRecordNapi *>(ctxt->native); +} + +napi_value ApplicationDefinedRecordNapi::GetApplicationDefinedType(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "ApplicationDefinedRecordNapi"); + auto ctxt = std::make_shared<ContextBase>(); + auto record = GetApplicationDefinedRecord(env, info, ctxt); + ASSERT_ERR( + ctxt->env, (record != nullptr && record->value_ != nullptr), Status::E_INVALID_PARAMETERS, "invalid object!"); + ctxt->status = NapiDataUtils::SetValue(env, record->value_->GetApplicationDefinedType(), ctxt->output); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "set type failed!"); + return ctxt->output; +} + +napi_value ApplicationDefinedRecordNapi::SetApplicationDefinedType(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "ApplicationDefinedRecordNapi"); + auto ctxt = std::make_shared<ContextBase>(); + std::string type; + auto input = [env, ctxt, &type](size_t argc, napi_value *argv) { + ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + ctxt->status = NapiDataUtils::GetValue(env, argv[0], type); + ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + }; + ctxt->GetCbInfoSync(env, info, input); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + auto record = static_cast<ApplicationDefinedRecordNapi *>(ctxt->native); + ASSERT_ERR( + ctxt->env, (record != nullptr && record->value_ != nullptr), Status::E_INVALID_PARAMETERS, "invalid object!"); + record->value_->SetApplicationDefinedType(type); + return nullptr; +} + +napi_value ApplicationDefinedRecordNapi::GetRawData(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "ApplicationDefinedRecordNapi"); + auto ctxt = std::make_shared<ContextBase>(); + auto record = GetApplicationDefinedRecord(env, info, ctxt); + ASSERT_ERR( + ctxt->env, (record != nullptr && record->value_ != nullptr), Status::E_INVALID_PARAMETERS, "invalid object!"); + ctxt->status = NapiDataUtils::SetValue(env, record->value_->GetRawData(), ctxt->output); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "set rawData failed!"); + return ctxt->output; +} + +napi_value ApplicationDefinedRecordNapi::SetRawData(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "ApplicationDefinedRecordNapi"); + auto ctxt = std::make_shared<ContextBase>(); + std::vector<uint8_t> rawData; + auto input = [env, ctxt, &rawData](size_t argc, napi_value *argv) { + ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + ctxt->status = NapiDataUtils::GetValue(env, argv[0], rawData); + ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + }; + ctxt->GetCbInfoSync(env, info, input); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + auto record = static_cast<ApplicationDefinedRecordNapi *>(ctxt->native); + ASSERT_ERR( + ctxt->env, (record != nullptr && record->value_ != nullptr), Status::E_INVALID_PARAMETERS, "invalid object!"); + record->value_->SetRawData(rawData); + return nullptr; +} +} // namespace UDMF +} // namespace OHOS diff --git a/udmf/framework/jskitsimpl/data/audio_napi.cpp b/udmf/framework/jskitsimpl/data/audio_napi.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bc85616833072253769c5d8d6e35daa868d754a5 --- /dev/null +++ b/udmf/framework/jskitsimpl/data/audio_napi.cpp @@ -0,0 +1,114 @@ +/* +* 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 "audio_napi.h" + +#include "audio.h" +#include "file_napi.h" +#include "napi_data_utils.h" +#include "napi_error_utils.h" +#include "napi_queue.h" +#include "unified_record_napi.h" + +namespace OHOS { +namespace UDMF { +napi_value AudioNapi::Constructor(napi_env env) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "AudioNapi"); + napi_property_descriptor properties[] = { + /* Audio extends UnifiedRecord */ + DECLARE_NAPI_FUNCTION("getType", UnifiedRecordNapi::GetType), + /* Audio extends File */ + DECLARE_NAPI_GETTER_SETTER("details", FileNapi::GetDetails, FileNapi::SetDetails), + DECLARE_NAPI_GETTER_SETTER("uri", FileNapi::GetUri, FileNapi::SetUri), + /* Audio properties */ + DECLARE_NAPI_GETTER_SETTER("audioUri", GetAudioUri, SetAudioUri), + }; + size_t count = sizeof(properties) / sizeof(properties[0]); + return NapiDataUtils::DefineClass(env, "Audio", properties, count, AudioNapi::New); +} + +napi_value AudioNapi::New(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "AudioNapi"); + auto ctxt = std::make_shared<ContextBase>(); + ctxt->GetCbInfoSync(env, info); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + + auto *audio = new (std::nothrow) AudioNapi(); + ASSERT_ERR(ctxt->env, audio != nullptr, Status::E_UNKNOWN, "no memory for audio!"); + audio->value_ = std::make_shared<Audio>(); + ASSERT_CALL(env, napi_wrap(env, ctxt->self, audio, Destructor, nullptr, nullptr), audio); + return ctxt->self; +} + +void AudioNapi::NewInstance(napi_env env, std::shared_ptr<UnifiedRecord> in, napi_value &out) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "AudioNapi"); + ASSERT_CALL_VOID(env, napi_new_instance(env, Constructor(env), 0, nullptr, &out)); + auto *audio = new (std::nothrow) AudioNapi(); + ASSERT_ERR_VOID(env, audio != nullptr, Status::E_UNKNOWN, "no memory for audio!"); + audio->value_ = std::static_pointer_cast<Audio>(in); + ASSERT_CALL_DELETE(env, napi_wrap(env, out, audio, Destructor, nullptr, nullptr), audio); +} + +void AudioNapi::Destructor(napi_env env, void *data, void *hint) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "AudioNapi finalize."); + auto *audio = static_cast<AudioNapi *>(data); + ASSERT_VOID(audio != nullptr, "finalize null!"); + delete audio; +} + +AudioNapi *AudioNapi::GetAudio(napi_env env, napi_callback_info info, std::shared_ptr<ContextBase> ctxt) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "AudioNapi"); + ctxt->GetCbInfoSync(env, info); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + return static_cast<AudioNapi *>(ctxt->native); +} + +napi_value AudioNapi::GetAudioUri(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "AudioNapi"); + auto ctxt = std::make_shared<ContextBase>(); + auto audio = GetAudio(env, info, ctxt); + ASSERT_ERR( + ctxt->env, (audio != nullptr && audio->value_ != nullptr), Status::E_INVALID_PARAMETERS, "invalid object!"); + ctxt->status = NapiDataUtils::SetValue(env, audio->value_->GetUri(), ctxt->output); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "set audio uri failed!"); + return ctxt->output; +} + +napi_value AudioNapi::SetAudioUri(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "AudioNapi"); + auto ctxt = std::make_shared<ContextBase>(); + std::string uri; + auto input = [env, ctxt, &uri](size_t argc, napi_value *argv) { + ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + ctxt->status = NapiDataUtils::GetValue(env, argv[0], uri); + ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + }; + ctxt->GetCbInfoSync(env, info, input); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + auto audio = static_cast<AudioNapi *>(ctxt->native); + ASSERT_ERR( + ctxt->env, (audio != nullptr && audio->value_ != nullptr), Status::E_INVALID_PARAMETERS, "invalid object!"); + audio->value_->SetUri(uri); + return nullptr; +} +} // namespace UDMF +} // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/jskitsimpl/data/file_napi.cpp b/udmf/framework/jskitsimpl/data/file_napi.cpp new file mode 100644 index 0000000000000000000000000000000000000000..933663f280b034d90ba67cd71c1da9087874c853 --- /dev/null +++ b/udmf/framework/jskitsimpl/data/file_napi.cpp @@ -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. + */ + +#include "file_napi.h" + +#include "file.h" +#include "napi_data_utils.h" +#include "napi_error_utils.h" +#include "napi_queue.h" +#include "unified_record_napi.h" + +namespace OHOS { +namespace UDMF { +napi_value FileNapi::Constructor(napi_env env) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "FileNapi"); + napi_property_descriptor properties[] = { + /* File extends UnifiedRecord */ + DECLARE_NAPI_FUNCTION("getType", UnifiedRecordNapi::GetType), + /* File properties */ + DECLARE_NAPI_GETTER_SETTER("details", GetDetails, SetDetails), + DECLARE_NAPI_GETTER_SETTER("uri", GetUri, SetUri), + }; + size_t count = sizeof(properties) / sizeof(properties[0]); + return NapiDataUtils::DefineClass(env, "File", properties, count, FileNapi::New); +} + +napi_value FileNapi::New(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "FileNapi"); + auto ctxt = std::make_shared<ContextBase>(); + ctxt->GetCbInfoSync(env, info); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + + auto *file = new (std::nothrow) FileNapi(); + ASSERT_ERR(ctxt->env, file != nullptr, Status::E_UNKNOWN, "no memory for file!"); + file->value_ = std::make_shared<File>(); + ASSERT_CALL(env, napi_wrap(env, ctxt->self, file, Destructor, nullptr, nullptr), file); + return ctxt->self; +} + +void FileNapi::NewInstance(napi_env env, std::shared_ptr<UnifiedRecord> in, napi_value &out) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "FileNapi"); + ASSERT_CALL_VOID(env, napi_new_instance(env, Constructor(env), 0, nullptr, &out)); + auto *file = new (std::nothrow) FileNapi(); + ASSERT_ERR_VOID(env, file != nullptr, Status::E_UNKNOWN, "no memory for file!"); + file->value_ = std::static_pointer_cast<File>(in); + ASSERT_CALL_DELETE(env, napi_wrap(env, out, file, Destructor, nullptr, nullptr), file); +} + +void FileNapi::Destructor(napi_env env, void *data, void *hint) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "FileNapi finalize."); + auto *file = static_cast<FileNapi *>(data); + ASSERT_VOID(file != nullptr, "finalize null!"); + delete file; +} + +FileNapi *FileNapi::GetFile(napi_env env, napi_callback_info info, std::shared_ptr<ContextBase> ctxt) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "FileNapi"); + ctxt->GetCbInfoSync(env, info); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + return static_cast<FileNapi *>(ctxt->native); +} + +napi_value FileNapi::GetDetails(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "FileNapi"); + auto ctxt = std::make_shared<ContextBase>(); + auto file = GetFile(env, info, ctxt); + ASSERT_ERR( + ctxt->env, (file != nullptr && file->value_ != nullptr), Status::E_INVALID_PARAMETERS, "invalid object!"); + ctxt->status = NapiDataUtils::SetValue(env, file->value_->GetDetails(), ctxt->output); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "set details failed!"); + return ctxt->output; +} + +napi_value FileNapi::SetDetails(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "FileNapi"); + auto ctxt = std::make_shared<ContextBase>(); + UDDetails details; + auto input = [env, ctxt, &details](size_t argc, napi_value *argv) { + ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + ctxt->status = NapiDataUtils::GetValue(env, argv[0], details); + ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + }; + ctxt->GetCbInfoSync(env, info, input); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + auto file = static_cast<FileNapi *>(ctxt->native); + ASSERT_ERR( + ctxt->env, (file != nullptr && file->value_ != nullptr), Status::E_INVALID_PARAMETERS, "invalid object!"); + file->value_->SetDetails(details); + return nullptr; +} + +napi_value FileNapi::GetUri(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "FileNapi"); + auto ctxt = std::make_shared<ContextBase>(); + auto file = GetFile(env, info, ctxt); + ASSERT_ERR( + ctxt->env, (file != nullptr && file->value_ != nullptr), Status::E_INVALID_PARAMETERS, "invalid object!"); + ctxt->status = NapiDataUtils::SetValue(env, file->value_->GetUri(), ctxt->output); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "set uri failed!"); + return ctxt->output; +} + +napi_value FileNapi::SetUri(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "FileNapi"); + auto ctxt = std::make_shared<ContextBase>(); + std::string uri; + auto input = [env, ctxt, &uri](size_t argc, napi_value *argv) { + ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + ctxt->status = NapiDataUtils::GetValue(env, argv[0], uri); + ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + }; + ctxt->GetCbInfoSync(env, info, input); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + auto file = static_cast<FileNapi *>(ctxt->native); + ASSERT_ERR( + ctxt->env, (file != nullptr && file->value_ != nullptr), Status::E_INVALID_PARAMETERS, "invalid object!"); + file->value_->SetUri(uri); + return nullptr; +} +} // namespace UDMF +} // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/jskitsimpl/data/folder_napi.cpp b/udmf/framework/jskitsimpl/data/folder_napi.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f9d87e06597d0dda1fcb4973d351d1c1c7940139 --- /dev/null +++ b/udmf/framework/jskitsimpl/data/folder_napi.cpp @@ -0,0 +1,113 @@ +/* + * 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 "folder_napi.h" + +#include "file_napi.h" +#include "folder.h" +#include "napi_data_utils.h" +#include "napi_error_utils.h" +#include "napi_queue.h" +#include "unified_record_napi.h" + +namespace OHOS { +namespace UDMF { +napi_value FolderNapi::Constructor(napi_env env) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "FolderNapi"); + napi_property_descriptor properties[] = { + /* Folder extends UnifiedRecord */ + DECLARE_NAPI_FUNCTION("getType", UnifiedRecordNapi::GetType), + /* Folder extends File */ + DECLARE_NAPI_GETTER_SETTER("details", FileNapi::GetDetails, FileNapi::SetDetails), + DECLARE_NAPI_GETTER_SETTER("uri", FileNapi::GetUri, FileNapi::SetUri), + /* Folder properties */ + DECLARE_NAPI_GETTER_SETTER("folderUri", GetFolderUri, SetFolderUri), + }; + size_t count = sizeof(properties) / sizeof(properties[0]); + return NapiDataUtils::DefineClass(env, "Folder", properties, count, FolderNapi::New); +} + +napi_value FolderNapi::New(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "FolderNapi"); + auto ctxt = std::make_shared<ContextBase>(); + ctxt->GetCbInfoSync(env, info); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + + auto *folder = new (std::nothrow) FolderNapi(); + ASSERT_ERR(ctxt->env, folder != nullptr, Status::E_UNKNOWN, "no memory for folder!"); + folder->value_ = std::make_shared<Folder>(); + ASSERT_CALL(env, napi_wrap(env, ctxt->self, folder, Destructor, nullptr, nullptr), folder); + return ctxt->self; +} + +void FolderNapi::NewInstance(napi_env env, std::shared_ptr<UnifiedRecord> in, napi_value &out) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "FolderNapi"); + ASSERT_CALL_VOID(env, napi_new_instance(env, Constructor(env), 0, nullptr, &out)); + auto *folder = new (std::nothrow) FolderNapi(); + ASSERT_ERR_VOID(env, folder != nullptr, Status::E_UNKNOWN, "no memory for folder!"); + folder->value_ = std::static_pointer_cast<Folder>(in); + ASSERT_CALL_DELETE(env, napi_wrap(env, out, folder, Destructor, nullptr, nullptr), folder); +} + +void FolderNapi::Destructor(napi_env env, void *data, void *hint) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "FolderNapi finalize."); + auto *folder = static_cast<FolderNapi *>(data); + ASSERT_VOID(folder != nullptr, "finalize null!"); + delete folder; +} + +FolderNapi *FolderNapi::GetFolder(napi_env env, napi_callback_info info, std::shared_ptr<ContextBase> ctxt) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "FolderNapi"); + ctxt->GetCbInfoSync(env, info); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + return static_cast<FolderNapi *>(ctxt->native); +} + +napi_value FolderNapi::GetFolderUri(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "FolderNapi"); + auto ctxt = std::make_shared<ContextBase>(); + auto folder = GetFolder(env, info, ctxt); + ASSERT_ERR( + ctxt->env, (folder != nullptr && folder->value_ != nullptr), Status::E_INVALID_PARAMETERS, "invalid object!"); + ctxt->status = NapiDataUtils::SetValue(env, folder->value_->GetUri(), ctxt->output); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "set folder uri failed!"); + return ctxt->output; +} + +napi_value FolderNapi::SetFolderUri(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "FolderNapi"); + auto ctxt = std::make_shared<ContextBase>(); + std::string uri; + auto input = [env, ctxt, &uri](size_t argc, napi_value *argv) { + ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + ctxt->status = NapiDataUtils::GetValue(env, argv[0], uri); + ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + }; + ctxt->GetCbInfoSync(env, info, input); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + auto folder = static_cast<FolderNapi *>(ctxt->native); + ASSERT_ERR( + ctxt->env, (folder != nullptr && folder->value_ != nullptr), Status::E_INVALID_PARAMETERS, "invalid object!"); + folder->value_->SetUri(uri); + return nullptr; +} +} // namespace UDMF +} // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/jskitsimpl/data/html_napi.cpp b/udmf/framework/jskitsimpl/data/html_napi.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7b2282b3c6c8aba991e7425541bfe89828fa1ab9 --- /dev/null +++ b/udmf/framework/jskitsimpl/data/html_napi.cpp @@ -0,0 +1,145 @@ +/* + * 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 "html_napi.h" + +#include "html.h" +#include "napi_data_utils.h" +#include "napi_error_utils.h" +#include "napi_queue.h" +#include "text_napi.h" +#include "unified_record_napi.h" + +namespace OHOS { +namespace UDMF { +napi_value HtmlNapi::Constructor(napi_env env) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "HtmlNapi"); + napi_property_descriptor properties[] = { + /* Html extends UnifiedRecord */ + DECLARE_NAPI_FUNCTION("getType", UnifiedRecordNapi::GetType), + /* Html extends Text */ + DECLARE_NAPI_GETTER_SETTER("details", TextNapi::GetDetails, TextNapi::SetDetails), + /* Html properties */ + DECLARE_NAPI_GETTER_SETTER("htmlContent", GetHtmlContent, SetHtmlContent), + DECLARE_NAPI_GETTER_SETTER("plainContent", GetPlainContent, SetPlainContent), + }; + size_t count = sizeof(properties) / sizeof(properties[0]); + return NapiDataUtils::DefineClass(env, "HTML", properties, count, HtmlNapi::New); +} + +napi_value HtmlNapi::New(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "HtmlNapi"); + auto ctxt = std::make_shared<ContextBase>(); + ctxt->GetCbInfoSync(env, info); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + + auto *html = new (std::nothrow) HtmlNapi(); + ASSERT_ERR(ctxt->env, html != nullptr, Status::E_UNKNOWN, "no memory for html!"); + html->value_ = std::make_shared<Html>(); + ASSERT_CALL(env, napi_wrap(env, ctxt->self, html, Destructor, nullptr, nullptr), html); + return ctxt->self; +} + +void HtmlNapi::NewInstance(napi_env env, std::shared_ptr<UnifiedRecord> in, napi_value &out) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "HtmlNapi"); + ASSERT_CALL_VOID(env, napi_new_instance(env, Constructor(env), 0, nullptr, &out)); + auto *html = new (std::nothrow) HtmlNapi(); + ASSERT_ERR_VOID(env, html != nullptr, Status::E_UNKNOWN, "no memory for html!"); + html->value_ = std::static_pointer_cast<Html>(in); + ASSERT_CALL_DELETE(env, napi_wrap(env, out, html, Destructor, nullptr, nullptr), html); +} + +void HtmlNapi::Destructor(napi_env env, void *data, void *hint) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "HtmlNapi finalize."); + auto *html = static_cast<HtmlNapi *>(data); + ASSERT_VOID(html != nullptr, "finalize null!"); + delete html; +} + +HtmlNapi *HtmlNapi::GetHtml(napi_env env, napi_callback_info info, std::shared_ptr<ContextBase> ctxt) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "HtmlNapi"); + ctxt->GetCbInfoSync(env, info); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + return static_cast<HtmlNapi *>(ctxt->native); +} + +napi_value HtmlNapi::GetPlainContent(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "HtmlNapi"); + auto ctxt = std::make_shared<ContextBase>(); + auto html = GetHtml(env, info, ctxt); + ASSERT_ERR( + ctxt->env, (html != nullptr && html->value_ != nullptr), Status::E_INVALID_PARAMETERS, "invalid object!"); + ctxt->status = NapiDataUtils::SetValue(env, html->value_->GetPlainContent(), ctxt->output); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "set plain content failed!"); + return ctxt->output; +} + +napi_value HtmlNapi::SetPlainContent(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "HtmlNapi"); + auto ctxt = std::make_shared<ContextBase>(); + std::string plainContent; + auto input = [env, ctxt, &plainContent](size_t argc, napi_value *argv) { + ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + ctxt->status = NapiDataUtils::GetValue(env, argv[0], plainContent); + ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + }; + ctxt->GetCbInfoSync(env, info, input); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + auto html = static_cast<HtmlNapi *>(ctxt->native); + ASSERT_ERR( + ctxt->env, (html != nullptr && html->value_ != nullptr), Status::E_INVALID_PARAMETERS, "invalid object!"); + html->value_->SetPlainContent(plainContent); + return nullptr; +} + +napi_value HtmlNapi::GetHtmlContent(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "HtmlNapi"); + auto ctxt = std::make_shared<ContextBase>(); + auto html = GetHtml(env, info, ctxt); + ASSERT_ERR( + ctxt->env, (html != nullptr && html->value_ != nullptr), Status::E_INVALID_PARAMETERS, "invalid object!"); + ctxt->status = NapiDataUtils::SetValue(env, html->value_->GetHtmlContent(), ctxt->output); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "set html failed!"); + return ctxt->output; +} + +napi_value HtmlNapi::SetHtmlContent(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "HtmlNapi"); + auto ctxt = std::make_shared<ContextBase>(); + std::string htmlContent; + auto input = [env, ctxt, &htmlContent](size_t argc, napi_value *argv) { + ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + ctxt->status = NapiDataUtils::GetValue(env, argv[0], htmlContent); + ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + }; + ctxt->GetCbInfoSync(env, info, input); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + auto html = static_cast<HtmlNapi *>(ctxt->native); + ASSERT_ERR( + ctxt->env, (html != nullptr && html->value_ != nullptr), Status::E_INVALID_PARAMETERS, "invalid object!"); + html->value_->SetHtmlContent(htmlContent); + return nullptr; +} +} // namespace UDMF +} // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/jskitsimpl/data/image_napi.cpp b/udmf/framework/jskitsimpl/data/image_napi.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ba6c9234dfca80e4f2abfcab64f08df369e350ac --- /dev/null +++ b/udmf/framework/jskitsimpl/data/image_napi.cpp @@ -0,0 +1,114 @@ +/* + * 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 "image_napi.h" + +#include "file_napi.h" +#include "image.h" +#include "napi_data_utils.h" +#include "napi_error_utils.h" +#include "napi_queue.h" +#include "unified_record_napi.h" + +namespace OHOS { +namespace UDMF { +napi_value ImageNapi::Constructor(napi_env env) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "ImageNapi"); + napi_property_descriptor properties[] = { + /* Image extends UnifiedRecord */ + DECLARE_NAPI_FUNCTION("getType", UnifiedRecordNapi::GetType), + /* Image extends File */ + DECLARE_NAPI_GETTER_SETTER("details", FileNapi::GetDetails, FileNapi::SetDetails), + DECLARE_NAPI_GETTER_SETTER("uri", FileNapi::GetUri, FileNapi::SetUri), + /* Image properties */ + DECLARE_NAPI_GETTER_SETTER("imageUri", GetImageUri, SetImageUri), + }; + size_t count = sizeof(properties) / sizeof(properties[0]); + return NapiDataUtils::DefineClass(env, "Image", properties, count, ImageNapi::New); +} + +napi_value ImageNapi::New(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "ImageNapi"); + auto ctxt = std::make_shared<ContextBase>(); + ctxt->GetCbInfoSync(env, info); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + + auto *image = new (std::nothrow) ImageNapi(); + ASSERT_ERR(ctxt->env, image != nullptr, Status::E_UNKNOWN, "no memory for image!"); + image->value_ = std::make_shared<Image>(); + ASSERT_CALL(env, napi_wrap(env, ctxt->self, image, Destructor, nullptr, nullptr), image); + return ctxt->self; +} + +void ImageNapi::NewInstance(napi_env env, std::shared_ptr<UnifiedRecord> in, napi_value &out) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "ImageNapi"); + ASSERT_CALL_VOID(env, napi_new_instance(env, Constructor(env), 0, nullptr, &out)); + auto *image = new (std::nothrow) ImageNapi(); + ASSERT_ERR_VOID(env, image != nullptr, Status::E_UNKNOWN, "no memory for image!"); + image->value_ = std::static_pointer_cast<Image>(in); + ASSERT_CALL_DELETE(env, napi_wrap(env, out, image, Destructor, nullptr, nullptr), image); +} + +void ImageNapi::Destructor(napi_env env, void *data, void *hint) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "ImageNapi finalize."); + auto *image = static_cast<ImageNapi *>(data); + ASSERT_VOID(image != nullptr, "finalize null!"); + delete image; +} + +ImageNapi *ImageNapi::GetImage(napi_env env, napi_callback_info info, std::shared_ptr<ContextBase> ctxt) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "ImageNapi"); + ctxt->GetCbInfoSync(env, info); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + return static_cast<ImageNapi *>(ctxt->native); +} + +napi_value ImageNapi::GetImageUri(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "ImageNapi"); + auto ctxt = std::make_shared<ContextBase>(); + auto image = GetImage(env, info, ctxt); + ASSERT_ERR( + ctxt->env, (image != nullptr && image->value_ != nullptr), Status::E_INVALID_PARAMETERS, "invalid object!"); + ctxt->status = NapiDataUtils::SetValue(env, image->value_->GetUri(), ctxt->output); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "set image uri failed!"); + return ctxt->output; +} + +napi_value ImageNapi::SetImageUri(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "ImageNapi"); + auto ctxt = std::make_shared<ContextBase>(); + std::string uri; + auto input = [env, ctxt, &uri](size_t argc, napi_value *argv) { + ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + ctxt->status = NapiDataUtils::GetValue(env, argv[0], uri); + ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + }; + ctxt->GetCbInfoSync(env, info, input); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + auto image = static_cast<ImageNapi *>(ctxt->native); + ASSERT_ERR( + ctxt->env, (image != nullptr && image->value_ != nullptr), Status::E_INVALID_PARAMETERS, "invalid object!"); + image->value_->SetUri(uri); + return nullptr; +} +} // namespace UDMF +} // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/jskitsimpl/data/link_napi.cpp b/udmf/framework/jskitsimpl/data/link_napi.cpp new file mode 100644 index 0000000000000000000000000000000000000000..40206fb085e35ce32b22518da81204e025c6f218 --- /dev/null +++ b/udmf/framework/jskitsimpl/data/link_napi.cpp @@ -0,0 +1,146 @@ +/* + * 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 "link_napi.h" + +#include "link.h" +#include "napi_data_utils.h" +#include "napi_error_utils.h" +#include "napi_queue.h" +#include "text_napi.h" +#include "unified_record_napi.h" + +namespace OHOS { +namespace UDMF { +napi_value LinkNapi::Constructor(napi_env env) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "LinkNapi"); + napi_property_descriptor properties[] = { + /* Link extends UnifiedRecord */ + DECLARE_NAPI_FUNCTION("getType", UnifiedRecordNapi::GetType), + /* Link extends Text */ + DECLARE_NAPI_GETTER_SETTER("details", TextNapi::GetDetails, TextNapi::SetDetails), + /* Link properties */ + DECLARE_NAPI_GETTER_SETTER("url", GetUrl, SetUrl), + DECLARE_NAPI_GETTER_SETTER("description", GetDescription, SetDescription), + }; + size_t count = sizeof(properties) / sizeof(properties[0]); + return NapiDataUtils::DefineClass(env, "Hyperlink", properties, count, LinkNapi::New); +} + +napi_value LinkNapi::New(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "LinkNapi"); + auto ctxt = std::make_shared<ContextBase>(); + + ctxt->GetCbInfoSync(env, info); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + + auto *link = new (std::nothrow) LinkNapi(); + ASSERT_ERR(ctxt->env, link != nullptr, Status::E_UNKNOWN, "no memory for link!"); + link->value_ = std::make_shared<Link>(); + ASSERT_CALL(env, napi_wrap(env, ctxt->self, link, Destructor, nullptr, nullptr), link); + return ctxt->self; +} + +void LinkNapi::NewInstance(napi_env env, std::shared_ptr<UnifiedRecord> in, napi_value &out) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "LinkNapi"); + ASSERT_CALL_VOID(env, napi_new_instance(env, Constructor(env), 0, nullptr, &out)); + auto *link = new (std::nothrow) LinkNapi(); + ASSERT_ERR_VOID(env, link != nullptr, Status::E_UNKNOWN, "no memory for link!"); + link->value_ = std::static_pointer_cast<Link>(in); + ASSERT_CALL_DELETE(env, napi_wrap(env, out, link, Destructor, nullptr, nullptr), link); +} + +void LinkNapi::Destructor(napi_env env, void *data, void *hint) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "LinkNapi finalize."); + auto *link = static_cast<LinkNapi *>(data); + ASSERT_VOID(link != nullptr, "finalize null!"); + delete link; +} + +LinkNapi *LinkNapi::GetLink(napi_env env, napi_callback_info info, std::shared_ptr<ContextBase> ctxt) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "LinkNapi"); + ctxt->GetCbInfoSync(env, info); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + return static_cast<LinkNapi *>(ctxt->native); +} + +napi_value LinkNapi::GetUrl(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "LinkNapi"); + auto ctxt = std::make_shared<ContextBase>(); + auto link = GetLink(env, info, ctxt); + ASSERT_ERR( + ctxt->env, (link != nullptr && link->value_ != nullptr), Status::E_INVALID_PARAMETERS, "invalid object!"); + ctxt->status = NapiDataUtils::SetValue(env, link->value_->GetUrl(), ctxt->output); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "set url failed!"); + return ctxt->output; +} + +napi_value LinkNapi::SetUrl(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "LinkNapi"); + auto ctxt = std::make_shared<ContextBase>(); + std::string url; + auto input = [env, ctxt, &url](size_t argc, napi_value *argv) { + ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + ctxt->status = NapiDataUtils::GetValue(env, argv[0], url); + ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + }; + ctxt->GetCbInfoSync(env, info, input); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + auto link = static_cast<LinkNapi *>(ctxt->native); + ASSERT_ERR( + ctxt->env, (link != nullptr && link->value_ != nullptr), Status::E_INVALID_PARAMETERS, "invalid object!"); + link->value_->SetUrl(url); + return nullptr; +} + +napi_value LinkNapi::GetDescription(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "LinkNapi"); + auto ctxt = std::make_shared<ContextBase>(); + auto link = GetLink(env, info, ctxt); + ASSERT_ERR( + ctxt->env, (link != nullptr && link->value_ != nullptr), Status::E_INVALID_PARAMETERS, "invalid object!"); + ctxt->status = NapiDataUtils::SetValue(env, link->value_->GetDescription(), ctxt->output); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "set description failed!"); + return ctxt->output; +} + +napi_value LinkNapi::SetDescription(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "LinkNapi"); + auto ctxt = std::make_shared<ContextBase>(); + std::string description; + auto input = [env, ctxt, &description](size_t argc, napi_value *argv) { + ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + ctxt->status = NapiDataUtils::GetValue(env, argv[0], description); + ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + }; + ctxt->GetCbInfoSync(env, info, input); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + auto link = static_cast<LinkNapi *>(ctxt->native); + ASSERT_ERR( + ctxt->env, (link != nullptr && link->value_ != nullptr), Status::E_INVALID_PARAMETERS, "invalid object!"); + link->value_->SetDescription(description); + return nullptr; +} +} // namespace UDMF +} // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/jskitsimpl/data/plain_text_napi.cpp b/udmf/framework/jskitsimpl/data/plain_text_napi.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d87ee77a2146a0a9ebac7edddbc4577b8f88483d --- /dev/null +++ b/udmf/framework/jskitsimpl/data/plain_text_napi.cpp @@ -0,0 +1,145 @@ +/* + * 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 "plain_text_napi.h" + +#include "napi_data_utils.h" +#include "napi_error_utils.h" +#include "napi_queue.h" +#include "plain_text.h" +#include "text_napi.h" +#include "unified_record_napi.h" + +namespace OHOS { +namespace UDMF { +napi_value PlainTextNapi::Constructor(napi_env env) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "PlainTextNapi"); + napi_property_descriptor properties[] = { + /* PlainText extends UnifiedRecord */ + DECLARE_NAPI_FUNCTION("getType", UnifiedRecordNapi::GetType), + /* PlainText extends Text */ + DECLARE_NAPI_GETTER_SETTER("details", TextNapi::GetDetails, TextNapi::SetDetails), + /* PlainText properties */ + DECLARE_NAPI_GETTER_SETTER("textContent", GetContent, SetContent), + DECLARE_NAPI_GETTER_SETTER("abstract", GetAbstract, SetAbstract), + }; + size_t count = sizeof(properties) / sizeof(properties[0]); + return NapiDataUtils::DefineClass(env, "PlainText", properties, count, PlainTextNapi::New); +} + +napi_value PlainTextNapi::New(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "PlainTextNapi"); + auto ctxt = std::make_shared<ContextBase>(); + ctxt->GetCbInfoSync(env, info); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + + auto *plainText = new (std::nothrow) PlainTextNapi(); + ASSERT_ERR(ctxt->env, plainText != nullptr, Status::E_UNKNOWN, "no memory for plain text!"); + plainText->value_ = std::make_shared<PlainText>(); + ASSERT_CALL(env, napi_wrap(env, ctxt->self, plainText, Destructor, nullptr, nullptr), plainText); + return ctxt->self; +} + +void PlainTextNapi::NewInstance(napi_env env, std::shared_ptr<UnifiedRecord> in, napi_value &out) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "PlainTextNapi"); + ASSERT_CALL_VOID(env, napi_new_instance(env, Constructor(env), 0, nullptr, &out)); + auto *plainText = new (std::nothrow) PlainTextNapi(); + ASSERT_ERR_VOID(env, plainText != nullptr, Status::E_UNKNOWN, "no memory for plain text!"); + plainText->value_ = std::static_pointer_cast<PlainText>(in); + ASSERT_CALL_DELETE(env, napi_wrap(env, out, plainText, Destructor, nullptr, nullptr), plainText); +} + +void PlainTextNapi::Destructor(napi_env env, void *data, void *hint) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "PlainTextNapi finalize."); + auto *plainText = static_cast<PlainTextNapi *>(data); + ASSERT_VOID(plainText != nullptr, "finalize null!"); + delete plainText; +} + +PlainTextNapi *PlainTextNapi::GetPlainText(napi_env env, napi_callback_info info, std::shared_ptr<ContextBase> ctxt) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "PlainTextNapi"); + ctxt->GetCbInfoSync(env, info); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + return static_cast<PlainTextNapi *>(ctxt->native); +} + +napi_value PlainTextNapi::GetContent(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "PlainTextNapi"); + auto ctxt = std::make_shared<ContextBase>(); + auto plainText = GetPlainText(env, info, ctxt); + ASSERT_ERR(ctxt->env, (plainText != nullptr && plainText->value_ != nullptr), Status::E_INVALID_PARAMETERS, + "invalid object!"); + ctxt->status = NapiDataUtils::SetValue(env, plainText->value_->GetContent(), ctxt->output); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "set text content failed!"); + return ctxt->output; +} + +napi_value PlainTextNapi::SetContent(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "PlainTextNapi"); + auto ctxt = std::make_shared<ContextBase>(); + std::string content; + auto input = [env, ctxt, &content](size_t argc, napi_value *argv) { + ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + ctxt->status = NapiDataUtils::GetValue(env, argv[0], content); + ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + }; + ctxt->GetCbInfoSync(env, info, input); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + auto plainText = static_cast<PlainTextNapi *>(ctxt->native); + ASSERT_ERR(ctxt->env, (plainText != nullptr && plainText->value_ != nullptr), Status::E_INVALID_PARAMETERS, + "invalid object!"); + plainText->value_->SetContent(content); + return nullptr; +} + +napi_value PlainTextNapi::GetAbstract(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "PlainTextNapi"); + auto ctxt = std::make_shared<ContextBase>(); + auto plainText = GetPlainText(env, info, ctxt); + ASSERT_ERR(ctxt->env, (plainText != nullptr && plainText->value_ != nullptr), Status::E_INVALID_PARAMETERS, + "invalid object!"); + ctxt->status = NapiDataUtils::SetValue(env, plainText->value_->GetAbstract(), ctxt->output); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "set abstract failed!"); + return ctxt->output; +} + +napi_value PlainTextNapi::SetAbstract(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "PlainTextNapi"); + auto ctxt = std::make_shared<ContextBase>(); + std::string abstract; + auto input = [env, ctxt, &abstract](size_t argc, napi_value *argv) { + ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + ctxt->status = NapiDataUtils::GetValue(env, argv[0], abstract); + ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + }; + ctxt->GetCbInfoSync(env, info, input); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + auto plainText = static_cast<PlainTextNapi *>(ctxt->native); + ASSERT_ERR(ctxt->env, (plainText != nullptr && plainText->value_ != nullptr), Status::E_INVALID_PARAMETERS, + "invalid object!"); + plainText->value_->SetAbstract(abstract); + return nullptr; +} +} // namespace UDMF +} // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/jskitsimpl/data/summary_napi.cpp b/udmf/framework/jskitsimpl/data/summary_napi.cpp new file mode 100644 index 0000000000000000000000000000000000000000..00a3795c9f7d6e74369d9a853f32f2b821da7f88 --- /dev/null +++ b/udmf/framework/jskitsimpl/data/summary_napi.cpp @@ -0,0 +1,100 @@ +/* + * 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 "summary_napi.h" + +#include "napi_data_utils.h" +#include "napi_error_utils.h" +#include "napi_queue.h" +#include "unified_types.h" + +namespace OHOS { +namespace UDMF { +napi_value SummaryNapi::Constructor(napi_env env) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "SummaryNapi"); + napi_property_descriptor properties[] = { + DECLARE_NAPI_GETTER_SETTER("summary", GetSummary, nullptr), + DECLARE_NAPI_GETTER_SETTER("totalSize", GetTotal, nullptr), + }; + size_t count = sizeof(properties) / sizeof(properties[0]); + return NapiDataUtils::DefineClass(env, "Summary", properties, count, SummaryNapi::New); +} + +napi_value SummaryNapi::New(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "SummaryNapi"); + auto ctxt = std::make_shared<ContextBase>(); + ctxt->GetCbInfoSync(env, info); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + + auto *summary = new (std::nothrow) SummaryNapi(); + ASSERT_ERR(ctxt->env, summary != nullptr, Status::E_UNKNOWN, "no memory for summary!"); + summary->value_ = std::make_shared<Summary>(); + ASSERT_CALL(env, napi_wrap(env, ctxt->self, summary, Destructor, nullptr, nullptr), summary); + return ctxt->self; +} + +void SummaryNapi::Destructor(napi_env env, void *data, void *hint) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "SummaryNapi finalize."); + auto *summary = static_cast<SummaryNapi *>(data); + ASSERT_VOID(summary != nullptr, "finalize null!"); + delete summary; +} + +void SummaryNapi::NewInstance(napi_env env, std::shared_ptr<Summary> in, napi_value &out) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "SummaryNapi"); + ASSERT_CALL_VOID(env, napi_new_instance(env, Constructor(env), 0, nullptr, &out)); + auto *summary = new (std::nothrow) SummaryNapi(); + ASSERT_ERR_VOID(env, summary != nullptr, Status::E_UNKNOWN, "no memory for summary!"); + summary->value_ = in; + ASSERT_CALL_DELETE(env, napi_wrap(env, out, summary, Destructor, nullptr, nullptr), summary); +} + +SummaryNapi *SummaryNapi::GetDataSummary(napi_env env, napi_callback_info info, std::shared_ptr<ContextBase> ctxt) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "SummaryNapi"); + ctxt->GetCbInfoSync(env, info); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + return static_cast<SummaryNapi *>(ctxt->native); +} + +napi_value SummaryNapi::GetSummary(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "SummaryNapi"); + auto ctxt = std::make_shared<ContextBase>(); + auto summary = GetDataSummary(env, info, ctxt); + ASSERT_ERR(ctxt->env, (summary != nullptr && summary->value_ != nullptr), Status::E_INVALID_PARAMETERS, + "invalid object!"); + ctxt->status = NapiDataUtils::SetValue(env, summary->value_->summary, ctxt->output); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "set summery failed!"); + return ctxt->output; +} + +napi_value SummaryNapi::GetTotal(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "SummaryNapi"); + auto ctxt = std::make_shared<ContextBase>(); + auto summary = GetDataSummary(env, info, ctxt); + ASSERT_ERR(ctxt->env, (summary != nullptr && summary->value_ != nullptr), Status::E_INVALID_PARAMETERS, + "invalid object!"); + ctxt->status = NapiDataUtils::SetValue(env, summary->value_->totalSize, ctxt->output); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "set total failed!"); + return ctxt->output; +} +} // namespace UDMF +} // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/jskitsimpl/data/system_defined_appitem_napi.cpp b/udmf/framework/jskitsimpl/data/system_defined_appitem_napi.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6a9bfe37c31dd53712f4127159739111fd4778a1 --- /dev/null +++ b/udmf/framework/jskitsimpl/data/system_defined_appitem_napi.cpp @@ -0,0 +1,274 @@ +/* + * 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 "system_defined_appitem_napi.h" + +#include "napi_data_utils.h" +#include "napi_error_utils.h" +#include "napi_queue.h" +#include "system_defined_appitem.h" +#include "system_defined_record_napi.h" +#include "unified_record_napi.h" + +namespace OHOS { +namespace UDMF { +napi_value SystemDefinedAppItemNapi::Constructor(napi_env env) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "SystemDefinedAppItemNapi"); + napi_property_descriptor properties[] = { + /* SystemDefinedAppItem extends UnifiedRecord */ + DECLARE_NAPI_FUNCTION("getType", UnifiedRecordNapi::GetType), + /* SystemDefinedAppItem extends SystemDefinedRecord */ + DECLARE_NAPI_GETTER_SETTER("details", SystemDefinedRecordNapi::GetDetails, SystemDefinedRecordNapi::SetDetails), + /* SystemDefinedAppItem properties */ + DECLARE_NAPI_GETTER_SETTER("appId", GetAppId, SetAppId), + DECLARE_NAPI_GETTER_SETTER("appName", GetAppName, SetAppName), + DECLARE_NAPI_GETTER_SETTER("appIconId", GetAppIconId, SetAppIconId), + DECLARE_NAPI_GETTER_SETTER("appLabelId", GetAppLabelId, SetAppLabelId), + DECLARE_NAPI_GETTER_SETTER("bundleName", GetBundleName, SetBundleName), + DECLARE_NAPI_GETTER_SETTER("abilityName", GetAbilityName, SetAbilityName), + }; + size_t count = sizeof(properties) / sizeof(properties[0]); + return NapiDataUtils::DefineClass(env, "SDAppItem", properties, count, SystemDefinedAppItemNapi::New); +} + +napi_value SystemDefinedAppItemNapi::New(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "SystemDefinedAppItemNapi"); + auto ctxt = std::make_shared<ContextBase>(); + ctxt->GetCbInfoSync(env, info); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + + auto *sdAppItem = new (std::nothrow) SystemDefinedAppItemNapi(); + ASSERT_ERR(ctxt->env, sdAppItem != nullptr, Status::E_UNKNOWN, "no memory for system defined appitem!"); + sdAppItem->value_ = std::make_shared<SystemDefinedAppItem>(); + ASSERT_CALL(env, napi_wrap(env, ctxt->self, sdAppItem, Destructor, nullptr, nullptr), sdAppItem); + return ctxt->self; +} + +void SystemDefinedAppItemNapi::NewInstance(napi_env env, std::shared_ptr<UnifiedRecord> in, napi_value &out) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "SystemDefinedAppItemNapi"); + ASSERT_CALL_VOID(env, napi_new_instance(env, Constructor(env), 0, nullptr, &out)); + auto *sdAppItem = new (std::nothrow) SystemDefinedAppItemNapi(); + ASSERT_ERR_VOID(env, sdAppItem != nullptr, Status::E_UNKNOWN, "no memory for system defined appitem!"); + sdAppItem->value_ = std::static_pointer_cast<SystemDefinedAppItem>(in); + ASSERT_CALL_DELETE(env, napi_wrap(env, out, sdAppItem, Destructor, nullptr, nullptr), sdAppItem); +} + +void SystemDefinedAppItemNapi::Destructor(napi_env env, void *data, void *hint) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "SystemDefinedAppItemNapi finalize."); + auto *sdAppItem = static_cast<SystemDefinedAppItemNapi *>(data); + ASSERT_VOID(sdAppItem != nullptr, "finalize null!"); + delete sdAppItem; +} + +SystemDefinedAppItemNapi *SystemDefinedAppItemNapi::GetSystemDefinedAppItem( + napi_env env, napi_callback_info info, std::shared_ptr<ContextBase> ctxt) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "SystemDefinedAppItemNapi"); + ctxt->GetCbInfoSync(env, info); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + return static_cast<SystemDefinedAppItemNapi *>(ctxt->native); +} + +napi_value SystemDefinedAppItemNapi::GetAppId(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "SystemDefinedAppItemNapi"); + auto ctxt = std::make_shared<ContextBase>(); + auto sdAppItem = GetSystemDefinedAppItem(env, info, ctxt); + ASSERT_ERR(ctxt->env, (sdAppItem != nullptr && sdAppItem->value_ != nullptr), Status::E_INVALID_PARAMETERS, + "invalid object!"); + ctxt->status = NapiDataUtils::SetValue(env, sdAppItem->value_->GetAppId(), ctxt->output); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "set app id failed!"); + return ctxt->output; +} + +napi_value SystemDefinedAppItemNapi::SetAppId(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "SystemDefinedAppItemNapi"); + auto ctxt = std::make_shared<ContextBase>(); + std::string appId; + auto input = [env, ctxt, &appId](size_t argc, napi_value *argv) { + ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + ctxt->status = NapiDataUtils::GetValue(env, argv[0], appId); + ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + }; + ctxt->GetCbInfoSync(env, info, input); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + auto sdAppItem = static_cast<SystemDefinedAppItemNapi *>(ctxt->native); + ASSERT_ERR(ctxt->env, (sdAppItem != nullptr && sdAppItem->value_ != nullptr), Status::E_INVALID_PARAMETERS, + "invalid object!"); + sdAppItem->value_->SetAppId(appId); + return nullptr; +} + +napi_value SystemDefinedAppItemNapi::GetAppName(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "SystemDefinedAppItemNapi"); + auto ctxt = std::make_shared<ContextBase>(); + auto sdAppItem = GetSystemDefinedAppItem(env, info, ctxt); + ASSERT_ERR(ctxt->env, (sdAppItem != nullptr && sdAppItem->value_ != nullptr), Status::E_INVALID_PARAMETERS, + "invalid object!"); + ctxt->status = NapiDataUtils::SetValue(env, sdAppItem->value_->GetAppName(), ctxt->output); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "set app name failed!"); + return ctxt->output; +} + +napi_value SystemDefinedAppItemNapi::SetAppName(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "SystemDefinedAppItemNapi"); + auto ctxt = std::make_shared<ContextBase>(); + std::string appName; + auto input = [env, ctxt, &appName](size_t argc, napi_value *argv) { + ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + ctxt->status = NapiDataUtils::GetValue(env, argv[0], appName); + ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + }; + ctxt->GetCbInfoSync(env, info, input); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + auto sdAppItem = static_cast<SystemDefinedAppItemNapi *>(ctxt->native); + ASSERT_ERR(ctxt->env, (sdAppItem != nullptr && sdAppItem->value_ != nullptr), Status::E_INVALID_PARAMETERS, + "invalid object!"); + sdAppItem->value_->SetAppName(appName); + return nullptr; +} + +napi_value SystemDefinedAppItemNapi::GetAppIconId(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "SystemDefinedAppItemNapi"); + auto ctxt = std::make_shared<ContextBase>(); + auto sdAppItem = GetSystemDefinedAppItem(env, info, ctxt); + ASSERT_ERR(ctxt->env, (sdAppItem != nullptr && sdAppItem->value_ != nullptr), Status::E_INVALID_PARAMETERS, + "invalid object!"); + ctxt->status = NapiDataUtils::SetValue(env, sdAppItem->value_->GetAppIconId(), ctxt->output); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "set app icon id failed!"); + return ctxt->output; +} + +napi_value SystemDefinedAppItemNapi::SetAppIconId(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "SystemDefinedAppItemNapi"); + auto ctxt = std::make_shared<ContextBase>(); + std::string appIconId; + auto input = [env, ctxt, &appIconId](size_t argc, napi_value *argv) { + ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + ctxt->status = NapiDataUtils::GetValue(env, argv[0], appIconId); + ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + }; + ctxt->GetCbInfoSync(env, info, input); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + auto sdAppItem = static_cast<SystemDefinedAppItemNapi *>(ctxt->native); + ASSERT_ERR(ctxt->env, (sdAppItem != nullptr && sdAppItem->value_ != nullptr), Status::E_INVALID_PARAMETERS, + "invalid object!"); + sdAppItem->value_->SetAppIconId(appIconId); + return nullptr; +} + +napi_value SystemDefinedAppItemNapi::GetAppLabelId(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "SystemDefinedAppItemNapi"); + auto ctxt = std::make_shared<ContextBase>(); + auto sdAppItem = GetSystemDefinedAppItem(env, info, ctxt); + ASSERT_ERR(ctxt->env, (sdAppItem != nullptr && sdAppItem->value_ != nullptr), Status::E_INVALID_PARAMETERS, + "invalid object!"); + ctxt->status = NapiDataUtils::SetValue(env, sdAppItem->value_->GetAppLabelId(), ctxt->output); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "set app label id failed!"); + return ctxt->output; +} + +napi_value SystemDefinedAppItemNapi::SetAppLabelId(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "SystemDefinedAppItemNapi"); + auto ctxt = std::make_shared<ContextBase>(); + std::string appLabelId; + auto input = [env, ctxt, &appLabelId](size_t argc, napi_value *argv) { + ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + ctxt->status = NapiDataUtils::GetValue(env, argv[0], appLabelId); + ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + }; + ctxt->GetCbInfoSync(env, info, input); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + auto sdAppItem = static_cast<SystemDefinedAppItemNapi *>(ctxt->native); + ASSERT_ERR(ctxt->env, (sdAppItem != nullptr && sdAppItem->value_ != nullptr), Status::E_INVALID_PARAMETERS, + "invalid object!"); + sdAppItem->value_->SetAppLabelId(appLabelId); + return nullptr; +} + +napi_value SystemDefinedAppItemNapi::GetBundleName(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "SystemDefinedAppItemNapi"); + auto ctxt = std::make_shared<ContextBase>(); + auto sdAppItem = GetSystemDefinedAppItem(env, info, ctxt); + ASSERT_ERR(ctxt->env, (sdAppItem != nullptr && sdAppItem->value_ != nullptr), Status::E_INVALID_PARAMETERS, + "invalid object!"); + ctxt->status = NapiDataUtils::SetValue(env, sdAppItem->value_->GetBundleName(), ctxt->output); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "set bundle name failed!"); + return ctxt->output; +} + +napi_value SystemDefinedAppItemNapi::SetBundleName(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "SystemDefinedAppItemNapi"); + auto ctxt = std::make_shared<ContextBase>(); + std::string bundleName; + auto input = [env, ctxt, &bundleName](size_t argc, napi_value *argv) { + ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + ctxt->status = NapiDataUtils::GetValue(env, argv[0], bundleName); + ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + }; + ctxt->GetCbInfoSync(env, info, input); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + auto sdAppItem = static_cast<SystemDefinedAppItemNapi *>(ctxt->native); + ASSERT_ERR(ctxt->env, (sdAppItem != nullptr && sdAppItem->value_ != nullptr), Status::E_INVALID_PARAMETERS, + "invalid object!"); + sdAppItem->value_->SetBundleName(bundleName); + return nullptr; +} + +napi_value SystemDefinedAppItemNapi::GetAbilityName(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "SystemDefinedAppItemNapi"); + auto ctxt = std::make_shared<ContextBase>(); + auto sdAppItem = GetSystemDefinedAppItem(env, info, ctxt); + ASSERT_ERR(ctxt->env, (sdAppItem != nullptr && sdAppItem->value_ != nullptr), Status::E_INVALID_PARAMETERS, + "invalid object!"); + ctxt->status = NapiDataUtils::SetValue(env, sdAppItem->value_->GetAbilityName(), ctxt->output); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "set ability name failed!"); + return ctxt->output; +} + +napi_value SystemDefinedAppItemNapi::SetAbilityName(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "SystemDefinedAppItemNapi"); + auto ctxt = std::make_shared<ContextBase>(); + std::string abilityName; + auto input = [env, ctxt, &abilityName](size_t argc, napi_value *argv) { + ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + ctxt->status = NapiDataUtils::GetValue(env, argv[0], abilityName); + ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + }; + ctxt->GetCbInfoSync(env, info, input); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + auto sdAppItem = static_cast<SystemDefinedAppItemNapi *>(ctxt->native); + ASSERT_ERR(ctxt->env, (sdAppItem != nullptr && sdAppItem->value_ != nullptr), Status::E_INVALID_PARAMETERS, + "invalid object!"); + sdAppItem->value_->SetAbilityName(abilityName); + return nullptr; +} +} // namespace UDMF +} // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/jskitsimpl/data/system_defined_form_napi.cpp b/udmf/framework/jskitsimpl/data/system_defined_form_napi.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4425d3a9068e23d5341506c284423039ec6c425a --- /dev/null +++ b/udmf/framework/jskitsimpl/data/system_defined_form_napi.cpp @@ -0,0 +1,242 @@ +/* + * 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 "system_defined_form_napi.h" + +#include "napi_data_utils.h" +#include "napi_error_utils.h" +#include "napi_queue.h" +#include "system_defined_form.h" +#include "system_defined_record_napi.h" +#include "unified_record_napi.h" + +namespace OHOS { +namespace UDMF { +napi_value SystemDefinedFormNapi::Constructor(napi_env env) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "SystemDefinedFormNapi"); + napi_property_descriptor properties[] = { + /* SystemDefinedForm extends UnifiedRecord */ + DECLARE_NAPI_FUNCTION("getType", UnifiedRecordNapi::GetType), + /* SystemDefinedForm extends SystemDefinedRecord */ + DECLARE_NAPI_GETTER_SETTER("details", SystemDefinedRecordNapi::GetDetails, SystemDefinedRecordNapi::SetDetails), + /* SystemDefinedForm properties */ + DECLARE_NAPI_GETTER_SETTER("formId", GetFormId, SetFormId), + DECLARE_NAPI_GETTER_SETTER("formName", GetFormName, SetFormName), + DECLARE_NAPI_GETTER_SETTER("bundleName", GetBundleName, SetBundleName), + DECLARE_NAPI_GETTER_SETTER("abilityName", GetAbilityName, SetAbilityName), + DECLARE_NAPI_GETTER_SETTER("module", GetModule, SetModule), + }; + size_t count = sizeof(properties) / sizeof(properties[0]); + return NapiDataUtils::DefineClass(env, "SDForm", properties, count, SystemDefinedFormNapi::New); +} + +napi_value SystemDefinedFormNapi::New(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "SystemDefinedFormNapi"); + auto ctxt = std::make_shared<ContextBase>(); + ctxt->GetCbInfoSync(env, info); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + + auto *sdForm = new (std::nothrow) SystemDefinedFormNapi(); + ASSERT_ERR(ctxt->env, sdForm != nullptr, Status::E_UNKNOWN, "no memory for system defined form!"); + sdForm->value_ = std::make_shared<SystemDefinedForm>(); + ASSERT_CALL(env, napi_wrap(env, ctxt->self, sdForm, Destructor, nullptr, nullptr), sdForm); + return ctxt->self; +} + +void SystemDefinedFormNapi::NewInstance(napi_env env, std::shared_ptr<UnifiedRecord> in, napi_value &out) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "SystemDefinedFormNapi"); + ASSERT_CALL_VOID(env, napi_new_instance(env, Constructor(env), 0, nullptr, &out)); + auto *sdForm = new (std::nothrow) SystemDefinedFormNapi(); + ASSERT_ERR_VOID(env, sdForm != nullptr, Status::E_UNKNOWN, "no memory for system defined form!"); + sdForm->value_ = std::static_pointer_cast<SystemDefinedForm>(in); + ASSERT_CALL_DELETE(env, napi_wrap(env, out, sdForm, Destructor, nullptr, nullptr), sdForm); +} + +void SystemDefinedFormNapi::Destructor(napi_env env, void *data, void *hint) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "SystemDefinedFormNapi finalize."); + auto *sdForm = static_cast<SystemDefinedFormNapi *>(data); + ASSERT_VOID(sdForm != nullptr, "finalize null!"); + delete sdForm; +} + +SystemDefinedFormNapi *SystemDefinedFormNapi::GetSystemDefinedForm( + napi_env env, napi_callback_info info, std::shared_ptr<ContextBase> ctxt) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "SystemDefinedFormNapi"); + ctxt->GetCbInfoSync(env, info); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + return static_cast<SystemDefinedFormNapi *>(ctxt->native); +} + +napi_value SystemDefinedFormNapi::GetFormId(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "SystemDefinedFormNapi"); + auto ctxt = std::make_shared<ContextBase>(); + auto sdForm = GetSystemDefinedForm(env, info, ctxt); + ASSERT_ERR( + ctxt->env, (sdForm != nullptr && sdForm->value_ != nullptr), Status::E_INVALID_PARAMETERS, "invalid object!"); + ctxt->status = NapiDataUtils::SetValue(env, sdForm->value_->GetFormId(), ctxt->output); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "set form id failed!"); + return ctxt->output; +} + +napi_value SystemDefinedFormNapi::SetFormId(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "SystemDefinedFormNapi"); + auto ctxt = std::make_shared<ContextBase>(); + int32_t formId = 0; + auto input = [env, ctxt, &formId](size_t argc, napi_value *argv) { + ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + ctxt->status = NapiDataUtils::GetValue(env, argv[0], formId); + ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + }; + ctxt->GetCbInfoSync(env, info, input); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + auto sdForm = static_cast<SystemDefinedFormNapi *>(ctxt->native); + ASSERT_ERR( + ctxt->env, (sdForm != nullptr && sdForm->value_ != nullptr), Status::E_INVALID_PARAMETERS, "invalid object!"); + sdForm->value_->SetFormId(formId); + return nullptr; +} + +napi_value SystemDefinedFormNapi::GetFormName(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "SystemDefinedFormNapi"); + auto ctxt = std::make_shared<ContextBase>(); + auto sdForm = GetSystemDefinedForm(env, info, ctxt); + ASSERT_ERR( + ctxt->env, (sdForm != nullptr && sdForm->value_ != nullptr), Status::E_INVALID_PARAMETERS, "invalid object!"); + ctxt->status = NapiDataUtils::SetValue(env, sdForm->value_->GetFormName(), ctxt->output); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "set form name failed!"); + return ctxt->output; +} + +napi_value SystemDefinedFormNapi::SetFormName(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "SystemDefinedFormNapi"); + auto ctxt = std::make_shared<ContextBase>(); + std::string formName; + auto input = [env, ctxt, &formName](size_t argc, napi_value *argv) { + ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + ctxt->status = NapiDataUtils::GetValue(env, argv[0], formName); + ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + }; + ctxt->GetCbInfoSync(env, info, input); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + auto sdForm = static_cast<SystemDefinedFormNapi *>(ctxt->native); + ASSERT_ERR( + ctxt->env, (sdForm != nullptr && sdForm->value_ != nullptr), Status::E_INVALID_PARAMETERS, "invalid object!"); + sdForm->value_->SetFormName(formName); + return nullptr; +} + +napi_value SystemDefinedFormNapi::GetBundleName(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "SystemDefinedFormNapi"); + auto ctxt = std::make_shared<ContextBase>(); + auto sdForm = GetSystemDefinedForm(env, info, ctxt); + ASSERT_ERR( + ctxt->env, (sdForm != nullptr && sdForm->value_ != nullptr), Status::E_INVALID_PARAMETERS, "invalid object!"); + ctxt->status = NapiDataUtils::SetValue(env, sdForm->value_->GetBundleName(), ctxt->output); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "set bundle name failed!"); + return ctxt->output; +} + +napi_value SystemDefinedFormNapi::SetBundleName(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "SystemDefinedFormNapi"); + auto ctxt = std::make_shared<ContextBase>(); + std::string bundleName; + auto input = [env, ctxt, &bundleName](size_t argc, napi_value *argv) { + ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + ctxt->status = NapiDataUtils::GetValue(env, argv[0], bundleName); + ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + }; + ctxt->GetCbInfoSync(env, info, input); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + auto sdForm = static_cast<SystemDefinedFormNapi *>(ctxt->native); + ASSERT_ERR( + ctxt->env, (sdForm != nullptr && sdForm->value_ != nullptr), Status::E_INVALID_PARAMETERS, "invalid object!"); + sdForm->value_->SetBundleName(bundleName); + return nullptr; +} + +napi_value SystemDefinedFormNapi::GetAbilityName(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "SystemDefinedFormNapi"); + auto ctxt = std::make_shared<ContextBase>(); + auto sdForm = GetSystemDefinedForm(env, info, ctxt); + ASSERT_ERR( + ctxt->env, (sdForm != nullptr && sdForm->value_ != nullptr), Status::E_INVALID_PARAMETERS, "invalid object!"); + ctxt->status = NapiDataUtils::SetValue(env, sdForm->value_->GetAbilityName(), ctxt->output); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "set ability name failed!"); + return ctxt->output; +} + +napi_value SystemDefinedFormNapi::SetAbilityName(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "SystemDefinedFormNapi"); + auto ctxt = std::make_shared<ContextBase>(); + std::string abilityName; + auto input = [env, ctxt, &abilityName](size_t argc, napi_value *argv) { + ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + ctxt->status = NapiDataUtils::GetValue(env, argv[0], abilityName); + ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + }; + ctxt->GetCbInfoSync(env, info, input); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + auto sdForm = static_cast<SystemDefinedFormNapi *>(ctxt->native); + ASSERT_ERR( + ctxt->env, (sdForm != nullptr && sdForm->value_ != nullptr), Status::E_INVALID_PARAMETERS, "invalid object!"); + sdForm->value_->SetAbilityName(abilityName); + return nullptr; +} + +napi_value SystemDefinedFormNapi::GetModule(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "SystemDefinedFormNapi"); + auto ctxt = std::make_shared<ContextBase>(); + auto sdForm = GetSystemDefinedForm(env, info, ctxt); + ASSERT_ERR( + ctxt->env, (sdForm != nullptr && sdForm->value_ != nullptr), Status::E_INVALID_PARAMETERS, "invalid object!"); + ctxt->status = NapiDataUtils::SetValue(env, sdForm->value_->GetModule(), ctxt->output); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "set module failed!"); + return ctxt->output; +} + +napi_value SystemDefinedFormNapi::SetModule(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "SystemDefinedFormNapi"); + auto ctxt = std::make_shared<ContextBase>(); + std::string module; + auto input = [env, ctxt, &module](size_t argc, napi_value *argv) { + ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + ctxt->status = NapiDataUtils::GetValue(env, argv[0], module); + ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + }; + ctxt->GetCbInfoSync(env, info, input); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + auto sdForm = static_cast<SystemDefinedFormNapi *>(ctxt->native); + ASSERT_ERR( + ctxt->env, (sdForm != nullptr && sdForm->value_ != nullptr), Status::E_INVALID_PARAMETERS, "invalid object!"); + sdForm->value_->SetModule(module); + return nullptr; +} +} // namespace UDMF +} // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/jskitsimpl/data/system_defined_pixelmap_napi.cpp b/udmf/framework/jskitsimpl/data/system_defined_pixelmap_napi.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e46eaa4b60a53735f34467a3dd03aece65edea2c --- /dev/null +++ b/udmf/framework/jskitsimpl/data/system_defined_pixelmap_napi.cpp @@ -0,0 +1,114 @@ +/* + * 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 "system_defined_pixelmap_napi.h" + +#include "system_defined_pixelmap.h" +#include "napi_data_utils.h" +#include "napi_error_utils.h" +#include "napi_queue.h" +#include "unified_record_napi.h" +#include "system_defined_record_napi.h" + +namespace OHOS { +namespace UDMF { +napi_value SystemDefinedPixelMapNapi::Constructor(napi_env env) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "SystemDefinedPixelMapNapi"); + napi_property_descriptor properties[] = { + /* SystemDefinedPixelMap extends UnifiedRecord */ + DECLARE_NAPI_FUNCTION("getType", UnifiedRecordNapi::GetType), + /* SystemDefinedPixelMap extends SystemDefinedRecord */ + DECLARE_NAPI_GETTER_SETTER("details", SystemDefinedRecordNapi::GetDetails, SystemDefinedRecordNapi::SetDetails), + /* SystemDefinedPixelMap properties */ + DECLARE_NAPI_GETTER_SETTER("rawData", GetRawData, SetRawData), + }; + size_t count = sizeof(properties) / sizeof(properties[0]); + return NapiDataUtils::DefineClass(env, "SystemDefinedPixelMap", properties, count, SystemDefinedPixelMapNapi::New); +} + +napi_value SystemDefinedPixelMapNapi::New(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "SystemDefinedPixelMapNapi"); + auto ctxt = std::make_shared<ContextBase>(); + ctxt->GetCbInfoSync(env, info); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + + auto *sdPixelMap = new (std::nothrow) SystemDefinedPixelMapNapi(); + ASSERT_ERR(ctxt->env, sdPixelMap != nullptr, Status::E_UNKNOWN, "no memory for system defined pixel map!"); + sdPixelMap->value_ = std::make_shared<SystemDefinedPixelMap>(); + ASSERT_CALL(env, napi_wrap(env, ctxt->self, sdPixelMap, Destructor, nullptr, nullptr), sdPixelMap); + return ctxt->self; +} + +void SystemDefinedPixelMapNapi::NewInstance(napi_env env, std::shared_ptr<UnifiedRecord> in, napi_value &out) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "SystemDefinedPixelMapNapi"); + ASSERT_CALL_VOID(env, napi_new_instance(env, Constructor(env), 0, nullptr, &out)); + auto *sdPixelMap = new (std::nothrow) SystemDefinedPixelMapNapi(); + ASSERT_ERR_VOID(env, sdPixelMap != nullptr, Status::E_UNKNOWN, "no memory for system defined pixel map!"); + sdPixelMap->value_ = std::static_pointer_cast<SystemDefinedPixelMap>(in); + ASSERT_CALL_DELETE(env, napi_wrap(env, out, sdPixelMap, Destructor, nullptr, nullptr), sdPixelMap); +} + +void SystemDefinedPixelMapNapi::Destructor(napi_env env, void *data, void *hint) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "SystemDefinedPixelMapNapi finalize."); + auto *sdPixelMap = static_cast<SystemDefinedPixelMapNapi *>(data); + ASSERT_VOID(sdPixelMap != nullptr, "finalize null!"); + delete sdPixelMap; +} + +SystemDefinedPixelMapNapi *SystemDefinedPixelMapNapi::GetSystemDefinedPixelMap( + napi_env env, napi_callback_info info, std::shared_ptr<ContextBase> ctxt) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "SystemDefinedPixelMapNapi"); + ctxt->GetCbInfoSync(env, info); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + return static_cast<SystemDefinedPixelMapNapi *>(ctxt->native); +} + +napi_value SystemDefinedPixelMapNapi::GetRawData(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "SystemDefinedPixelMapNapi"); + auto ctxt = std::make_shared<ContextBase>(); + auto sdPixelMap = GetSystemDefinedPixelMap(env, info, ctxt); + ASSERT_ERR(ctxt->env, (sdPixelMap != nullptr && sdPixelMap->value_ != nullptr), Status::E_INVALID_PARAMETERS, + "invalid object!"); + ctxt->status = NapiDataUtils::SetValue(env, sdPixelMap->value_->GetRawData(), ctxt->output); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "set raw data failed!"); + return ctxt->output; +} + +napi_value SystemDefinedPixelMapNapi::SetRawData(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "SystemDefinedPixelMapNapi"); + auto ctxt = std::make_shared<ContextBase>(); + std::vector<uint8_t> pixelMap; + auto input = [env, ctxt, &pixelMap](size_t argc, napi_value *argv) { + ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + ctxt->status = NapiDataUtils::GetValue(env, argv[0], pixelMap); + ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + }; + ctxt->GetCbInfoSync(env, info, input); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + auto sdPixelMap = static_cast<SystemDefinedPixelMapNapi *>(ctxt->native); + ASSERT_ERR(ctxt->env, (sdPixelMap != nullptr && sdPixelMap->value_ != nullptr), Status::E_INVALID_PARAMETERS, + "invalid object!"); + sdPixelMap->value_->SetRawData(pixelMap); + return nullptr; +} +} // namespace UDMF +} // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/jskitsimpl/data/system_defined_record_napi.cpp b/udmf/framework/jskitsimpl/data/system_defined_record_napi.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ddbf7363a583dd07e5a6102881ee9a1f46e528ee --- /dev/null +++ b/udmf/framework/jskitsimpl/data/system_defined_record_napi.cpp @@ -0,0 +1,113 @@ +/* + * 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 "system_defined_record_napi.h" + +#include "system_defined_record.h" +#include "napi_data_utils.h" +#include "napi_error_utils.h" +#include "napi_queue.h" +#include "unified_record_napi.h" + +namespace OHOS { +namespace UDMF { +napi_value SystemDefinedRecordNapi::Constructor(napi_env env) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "SystemDefinedRecordNapi"); + napi_property_descriptor properties[] = { + /* SystemDefinedRecord extends UnifiedRecord */ + DECLARE_NAPI_FUNCTION("getType", UnifiedRecordNapi::GetType), + /* SystemDefinedRecord properties */ + DECLARE_NAPI_GETTER_SETTER("details", GetDetails, SetDetails), + }; + size_t count = sizeof(properties) / sizeof(properties[0]); + return NapiDataUtils::DefineClass(env, "SystemDefinedRecord", properties, count, SystemDefinedRecordNapi::New); +} + +napi_value SystemDefinedRecordNapi::New(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "SystemDefinedRecordNapi"); + auto ctxt = std::make_shared<ContextBase>(); + ctxt->GetCbInfoSync(env, info); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + + auto *sdRecord = new (std::nothrow) SystemDefinedRecordNapi(); + ASSERT_ERR(ctxt->env, sdRecord != nullptr, Status::E_UNKNOWN, "no memory for system defined record!"); + sdRecord->value_ = std::make_shared<SystemDefinedRecord>(); + ASSERT_CALL(env, napi_wrap(env, ctxt->self, sdRecord, Destructor, nullptr, nullptr), sdRecord); + return ctxt->self; +} + +void SystemDefinedRecordNapi::NewInstance(napi_env env, std::shared_ptr<UnifiedRecord> in, napi_value &out) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "SystemDefinedRecordNapi"); + ASSERT_CALL_VOID(env, napi_new_instance(env, Constructor(env), 0, nullptr, &out)); + auto *sdRecord = new (std::nothrow) SystemDefinedRecordNapi(); + ASSERT_ERR_VOID(env, sdRecord != nullptr, Status::E_UNKNOWN, "no memory for system defined record!"); + sdRecord->value_ = std::static_pointer_cast<SystemDefinedRecord>(in); + ASSERT_CALL_DELETE(env, napi_wrap(env, out, sdRecord, Destructor, nullptr, nullptr), sdRecord); +} + +void SystemDefinedRecordNapi::Destructor(napi_env env, void *data, void *hint) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "SystemDefinedRecordNapi finalize."); + auto *sdRecord = static_cast<SystemDefinedRecordNapi *>(data); + ASSERT_VOID(sdRecord != nullptr, "finalize null!"); + delete sdRecord; +} + +SystemDefinedRecordNapi *SystemDefinedRecordNapi::GetSystemDefinedRecord( + napi_env env, napi_callback_info info, std::shared_ptr<ContextBase> ctxt) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "SystemDefinedRecordNapi"); + ctxt->GetCbInfoSync(env, info); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + return static_cast<SystemDefinedRecordNapi *>(ctxt->native); +} + +napi_value SystemDefinedRecordNapi::GetDetails(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "SystemDefinedRecordNapi"); + auto ctxt = std::make_shared<ContextBase>(); + auto sdRecord = GetSystemDefinedRecord(env, info, ctxt); + ASSERT_ERR(ctxt->env, (sdRecord != nullptr && sdRecord->value_ != nullptr), Status::E_INVALID_PARAMETERS, + "invalid object!"); + ctxt->status = NapiDataUtils::SetValue(env, sdRecord->value_->GetDetails(), ctxt->output); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "set details failed!"); + return ctxt->output; +} + +napi_value SystemDefinedRecordNapi::SetDetails(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "SystemDefinedRecordNapi"); + auto ctxt = std::make_shared<ContextBase>(); + + UDDetails details; + auto input = [env, ctxt, &details](size_t argc, napi_value *argv) { + ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + ctxt->status = NapiDataUtils::GetValue(env, argv[0], details); + ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + }; + ctxt->GetCbInfoSync(env, info, input); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + auto sdRecord = static_cast<SystemDefinedRecordNapi *>(ctxt->native); + ASSERT_ERR( + ctxt->env, (sdRecord != nullptr && sdRecord->value_ != nullptr), Status::E_INVALID_PARAMETERS, + "invalid object!"); + sdRecord->value_->SetDetails(details); + return nullptr; +} +} // namespace UDMF +} // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/jskitsimpl/data/text_napi.cpp b/udmf/framework/jskitsimpl/data/text_napi.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9cae4d94a550f8a16e58e2a69fbe897803d95ea1 --- /dev/null +++ b/udmf/framework/jskitsimpl/data/text_napi.cpp @@ -0,0 +1,109 @@ +/* + * 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 "text_napi.h" + +#include "text.h" +#include "napi_data_utils.h" +#include "napi_error_utils.h" +#include "napi_queue.h" +#include "unified_record_napi.h" + +namespace OHOS { +namespace UDMF { +napi_value TextNapi::Constructor(napi_env env) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "TextNapi"); + napi_property_descriptor properties[] = { + /* Text extends UnifiedRecord */ + DECLARE_NAPI_FUNCTION("getType", UnifiedRecordNapi::GetType), + /* Text properties */ + DECLARE_NAPI_GETTER_SETTER("details", GetDetails, SetDetails), + }; + size_t count = sizeof(properties) / sizeof(properties[0]); + return NapiDataUtils::DefineClass(env, "Text", properties, count, TextNapi::New); +} + +napi_value TextNapi::New(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "TextNapi"); + auto ctxt = std::make_shared<ContextBase>(); + ctxt->GetCbInfoSync(env, info); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + + auto *text = new (std::nothrow) TextNapi(); + ASSERT_ERR(ctxt->env, text != nullptr, Status::E_UNKNOWN, "no memory for text!"); + text->value_ = std::make_shared<Text>(); + ASSERT_CALL(ctxt->env, napi_wrap(env, ctxt->self, text, Destructor, nullptr, nullptr), text); + return ctxt->self; +} + +void TextNapi::NewInstance(napi_env env, std::shared_ptr<UnifiedRecord> in, napi_value &out) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "TextNapi"); + ASSERT_CALL_VOID(env, napi_new_instance(env, Constructor(env), 0, nullptr, &out)); + auto *text = new (std::nothrow) TextNapi(); + ASSERT_ERR_VOID(env, text != nullptr, Status::E_UNKNOWN, "no memory for text!"); + text->value_ = std::static_pointer_cast<Text>(in); + ASSERT_CALL_DELETE(env, napi_wrap(env, out, text, Destructor, nullptr, nullptr), text); +} + +void TextNapi::Destructor(napi_env env, void *data, void *hint) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "TextNapi finalize."); + auto *text = static_cast<TextNapi *>(data); + ASSERT_VOID(text != nullptr, "finalize null!"); + delete text; +} + +TextNapi *TextNapi::GetText(napi_env env, napi_callback_info info, std::shared_ptr<ContextBase> ctxt) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "TextNapi"); + ctxt->GetCbInfoSync(env, info); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + return static_cast<TextNapi *>(ctxt->native); +} + +napi_value TextNapi::GetDetails(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "TextNapi"); + auto ctxt = std::make_shared<ContextBase>(); + auto text = GetText(env, info, ctxt); + ASSERT_ERR( + ctxt->env, (text != nullptr && text->value_ != nullptr), Status::E_INVALID_PARAMETERS, "invalid object!"); + ctxt->status = NapiDataUtils::SetValue(env, text->value_->GetDetails(), ctxt->output); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "set details failed!"); + return ctxt->output; +} + +napi_value TextNapi::SetDetails(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "TextNapi"); + auto ctxt = std::make_shared<ContextBase>(); + UDDetails details; + auto input = [env, ctxt, &details](size_t argc, napi_value *argv) { + ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + ctxt->status = NapiDataUtils::GetValue(env, argv[0], details); + ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + }; + ctxt->GetCbInfoSync(env, info, input); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + auto text = static_cast<TextNapi *>(ctxt->native); + ASSERT_ERR( + ctxt->env, (text != nullptr && text->value_ != nullptr), Status::E_INVALID_PARAMETERS, "invalid object!"); + text->value_->SetDetails(details); + return nullptr; +} +} // namespace UDMF +} // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/jskitsimpl/data/udmf_napi.cpp b/udmf/framework/jskitsimpl/data/udmf_napi.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d437acc305e11d513a8043be9ef55cfc7a3b0475 --- /dev/null +++ b/udmf/framework/jskitsimpl/data/udmf_napi.cpp @@ -0,0 +1,300 @@ +/* + * 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 "udmf_napi.h" + +#include "napi_data_utils.h" +#include "napi_error_utils.h" +#include "napi_queue.h" +#include "udmf_client.h" +#include "unified_data_napi.h" +#include "unified_meta.h" + +namespace OHOS { +namespace UDMF { +napi_value UDMFNapi::UDMFInit(napi_env env, napi_value exports) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "UDMFNapi"); + napi_value unifiedDataType = CreateUnifiedDataType(env); + napi_value intention = CreateIntention(env); + napi_property_descriptor desc[] = { + DECLARE_NAPI_PROPERTY("UnifiedDataType", unifiedDataType), + DECLARE_NAPI_PROPERTY("Intention", intention), + DECLARE_NAPI_FUNCTION("insertData", InsertData), + DECLARE_NAPI_FUNCTION("updateData", UpdateData), + DECLARE_NAPI_FUNCTION("queryData", QueryData), + DECLARE_NAPI_FUNCTION("deleteData", DeleteData), + }; + + NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc)); + return exports; +} + +napi_value UDMFNapi::CreateUnifiedDataType(napi_env env) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "UDMFNapi"); + napi_value unifiedDataType = nullptr; + napi_create_object(env, &unifiedDataType); + SetNamedProperty(env, unifiedDataType, JS_UD_TYPE_NAME_MAP.at(TEXT), UD_TYPE_MAP.at(TEXT)); + SetNamedProperty(env, unifiedDataType, JS_UD_TYPE_NAME_MAP.at(PLAIN_TEXT), UD_TYPE_MAP.at(PLAIN_TEXT)); + SetNamedProperty(env, unifiedDataType, JS_UD_TYPE_NAME_MAP.at(HTML), UD_TYPE_MAP.at(HTML)); + SetNamedProperty(env, unifiedDataType, JS_UD_TYPE_NAME_MAP.at(HYPERLINK), UD_TYPE_MAP.at(HYPERLINK)); + SetNamedProperty(env, unifiedDataType, JS_UD_TYPE_NAME_MAP.at(FILE), UD_TYPE_MAP.at(FILE)); + SetNamedProperty(env, unifiedDataType, JS_UD_TYPE_NAME_MAP.at(IMAGE), UD_TYPE_MAP.at(IMAGE)); + SetNamedProperty(env, unifiedDataType, JS_UD_TYPE_NAME_MAP.at(VIDEO), UD_TYPE_MAP.at(VIDEO)); + SetNamedProperty(env, unifiedDataType, JS_UD_TYPE_NAME_MAP.at(AUDIO), UD_TYPE_MAP.at(AUDIO)); + SetNamedProperty(env, unifiedDataType, JS_UD_TYPE_NAME_MAP.at(FOLDER), UD_TYPE_MAP.at(FOLDER)); + SetNamedProperty( + env, unifiedDataType, JS_UD_TYPE_NAME_MAP.at(SYSTEM_DEFINED_RECORD), UD_TYPE_MAP.at(SYSTEM_DEFINED_RECORD)); + SetNamedProperty( + env, unifiedDataType, JS_UD_TYPE_NAME_MAP.at(SYSTEM_DEFINED_FORM), UD_TYPE_MAP.at(SYSTEM_DEFINED_FORM)); + SetNamedProperty(env, unifiedDataType, JS_UD_TYPE_NAME_MAP.at(SYSTEM_DEFINED_APP_ITEM), + UD_TYPE_MAP.at(SYSTEM_DEFINED_APP_ITEM)); + SetNamedProperty(env, unifiedDataType, JS_UD_TYPE_NAME_MAP.at(SYSTEM_DEFINED_PIXEL_MAP), + UD_TYPE_MAP.at(SYSTEM_DEFINED_PIXEL_MAP)); + SetNamedProperty(env, unifiedDataType, JS_UD_TYPE_NAME_MAP.at(APPLICATION_DEFINED_RECORD), + UD_TYPE_MAP.at(APPLICATION_DEFINED_RECORD)); + napi_object_freeze(env, unifiedDataType); + return unifiedDataType; +} + +napi_value UDMFNapi::CreateIntention(napi_env env) +{ + napi_value intention = nullptr; + napi_create_object(env, &intention); + SetNamedProperty(env, intention, JS_UD_INTENTION_NAME_MAP.at(UD_INTENTION_DATA_HUB), + UD_INTENTION_MAP.at(UD_INTENTION_DATA_HUB)); + napi_object_freeze(env, intention); + return intention; +} + +napi_status UDMFNapi::SetNamedProperty(napi_env env, napi_value &obj, const std::string &name, const std::string &value) +{ + napi_value property = nullptr; + napi_status status = NapiDataUtils::SetValue(env, value, property); + ASSERT(status == napi_ok, "string 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; +} + +napi_value UDMFNapi::InsertData(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "InsertData is called!"); + struct InsertContext : public ContextBase { + std::string key; + Intention intention; + std::shared_ptr<UnifiedData> unifiedData; + }; + std::string intention; + auto unifiedDataNapi = new (std::nothrow) UnifiedDataNapi(); + auto ctxt = std::make_shared<InsertContext>(); + auto input = [env, ctxt, &intention, &unifiedDataNapi](size_t argc, napi_value *argv) { + // require 2 arguments <options, unifiedData> + ASSERT_BUSINESS_ERR(ctxt, argc >= 2, E_INVALID_PARAMETERS, "invalid arguments!"); + ctxt->status = GetNamedProperty(env, argv[0], "intention", intention); + ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok && UnifiedDataUtils::IsPersist(intention), + E_INVALID_PARAMETERS, "invalid arg[0], i.e. invalid intention!"); + ctxt->status = napi_unwrap(env, argv[1], reinterpret_cast<void **>(&unifiedDataNapi)); + ASSERT_BUSINESS_ERR( + ctxt, ctxt->status == napi_ok, E_INVALID_PARAMETERS, "invalid arg[1], i.e. invalid unifiedData!"); + }; + ctxt->GetCbInfo(env, info, input); + ASSERT_NULL(!ctxt->isThrowError, "Insert Exit"); + ctxt->unifiedData = unifiedDataNapi->value_; + ctxt->intention = UnifiedDataUtils::GetIntentionByString(intention); + auto execute = [ctxt]() { + CustomOption option = { .intention = ctxt->intention }; + auto status = UdmfClient::GetInstance().SetData(option, *(ctxt->unifiedData), ctxt->key); + ASSERT_WITH_ERRCODE(ctxt, status == E_OK, status, "InsertData failed!"); + }; + + auto output = [env, ctxt](napi_value &result) { + ctxt->status = NapiDataUtils::SetValue(env, ctxt->key, result); + ASSERT_WITH_ERRCODE(ctxt, ctxt->status == napi_ok, E_ERROR, "output failed!"); + }; + return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute, output); +} + +napi_value UDMFNapi::UpdateData(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "UpdateData is called!"); + struct UpdateContext : public ContextBase { + std::string key; + std::shared_ptr<UnifiedData> unifiedData; + }; + std::string key; + auto unifiedDataNapi = new (std::nothrow) UnifiedDataNapi(); + auto ctxt = std::make_shared<UpdateContext>(); + auto input = [env, ctxt, &unifiedDataNapi](size_t argc, napi_value *argv) { + // require 2 arguments <options, unifiedData> + ASSERT_BUSINESS_ERR(ctxt, argc >= 2, E_INVALID_PARAMETERS, "invalid arguments!"); + ctxt->status = GetNamedProperty(env, argv[0], "key", ctxt->key); + UnifiedKey key(ctxt->key); + ASSERT_BUSINESS_ERR(ctxt, + ctxt->status == napi_ok && key.IsValid() && UnifiedDataUtils::IsPersist(key.intention), + E_INVALID_PARAMETERS, "invalid arg[0], i.e. invalid key!"); + ctxt->status = napi_unwrap(env, argv[1], reinterpret_cast<void **>(&unifiedDataNapi)); + ASSERT_BUSINESS_ERR( + ctxt, ctxt->status == napi_ok, E_INVALID_PARAMETERS, "invalid arg[1], i.e. invalid unifiedData!"); + }; + ctxt->GetCbInfo(env, info, input); + ASSERT_NULL(!ctxt->isThrowError, "Update Exit"); + ctxt->unifiedData = unifiedDataNapi->value_; + auto execute = [ctxt]() { + QueryOption option = { .key = ctxt->key }; + auto status = UdmfClient::GetInstance().UpdateData(option, *(ctxt->unifiedData)); + ASSERT_WITH_ERRCODE(ctxt, status == E_OK, status, "UpdateData failed!"); + }; + return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute); +} + +napi_value UDMFNapi::QueryData(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "QueryData is called!"); + struct QueryContext : public ContextBase { + std::string key; + Intention intention; + std::vector<UnifiedData> unifiedDataSet; + }; + std::string intention; + auto ctxt = std::make_shared<QueryContext>(); + auto input = [env, ctxt, &intention](size_t argc, napi_value *argv) { + // require 1 arguments <options> + ASSERT_BUSINESS_ERR(ctxt, argc >= 1, E_INVALID_PARAMETERS, "invalid arguments!"); + napi_status keyStatus; + napi_status intentionStatus; + auto options = argv[0]; + keyStatus = GetNamedProperty(env, options, "key", ctxt->key); + intentionStatus = GetNamedProperty(env, options, "intention", intention); + ASSERT_BUSINESS_ERR(ctxt, + (keyStatus == napi_ok || intentionStatus == napi_ok) + && UnifiedDataUtils::IsValidOptions(ctxt->key, intention), + E_INVALID_PARAMETERS, "invalid arg[0], i.e. invalid options!"); + }; + ctxt->GetCbInfo(env, info, input); + ASSERT_NULL(!ctxt->isThrowError, "Query Exit"); + ctxt->intention = UnifiedDataUtils::GetIntentionByString(intention); + auto execute = [env, ctxt]() { + QueryOption option = { + .key = ctxt->key, + .intention = ctxt->intention, + }; + auto status = UdmfClient::GetInstance().GetBatchData(option, ctxt->unifiedDataSet); + LOG_DEBUG(UDMF_SERVICE, "GetBatchData : status = %{public}d!", status); + ASSERT_WITH_ERRCODE(ctxt, status == E_OK, status, "QueryData failed!"); + }; + auto output = [env, ctxt](napi_value &result) { + ASSERT_WITH_ERRCODE(ctxt, !ctxt->unifiedDataSet.empty(), E_ERROR, "unifiedDataSet is empty!"); + ctxt->status = napi_create_array_with_length(env, ctxt->unifiedDataSet.size(), &ctxt->output); + ASSERT_WITH_ERRCODE(ctxt, ctxt->status == napi_ok, E_ERROR, "napi_create_array_with_length failed!"); + int index = 0; + for (const UnifiedData &data : ctxt->unifiedDataSet) { + std::shared_ptr<UnifiedData> unifiedData = std::make_shared<UnifiedData>(); + unifiedData->SetRecords(data.GetRecords()); + napi_value dataNapi = nullptr; + UnifiedDataNapi::NewInstance(env, unifiedData, dataNapi); + ctxt->status = napi_set_element(env, ctxt->output, index++, dataNapi); + ASSERT_WITH_ERRCODE(ctxt, ctxt->status == napi_ok, E_ERROR, "napi_set_element failed!"); + } + result = ctxt->output; + }; + return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute, output); +} + +napi_value UDMFNapi::DeleteData(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "DeleteData is called!"); + struct DeleteContext : public ContextBase { + std::string key; + Intention intention; + std::vector<UnifiedData> unifiedDataSet; + }; + std::string intention; + auto ctxt = std::make_shared<DeleteContext>(); + auto input = [env, ctxt, &intention](size_t argc, napi_value *argv) { + // require 1 arguments <options> + ASSERT_BUSINESS_ERR(ctxt, argc >= 1, E_INVALID_PARAMETERS, "invalid arguments!"); + napi_status keyStatus; + napi_status intentionStatus; + napi_value options = argv[0]; + keyStatus = GetNamedProperty(env, options, "key", ctxt->key); + intentionStatus = GetNamedProperty(env, options, "intention", intention); + ASSERT_BUSINESS_ERR(ctxt, + (keyStatus == napi_ok || intentionStatus == napi_ok) + && UnifiedDataUtils::IsValidOptions(ctxt->key, intention), + E_INVALID_PARAMETERS, "invalid arg[0], i.e. invalid options!"); + }; + ctxt->GetCbInfo(env, info, input); + ASSERT_NULL(!ctxt->isThrowError, "Delete Exit"); + ctxt->intention = UnifiedDataUtils::GetIntentionByString(intention); + auto execute = [env, ctxt]() { + QueryOption option = { + .key = ctxt->key, + .intention = ctxt->intention, + }; + auto status = UdmfClient::GetInstance().DeleteData(option, ctxt->unifiedDataSet); + ASSERT_WITH_ERRCODE(ctxt, status == E_OK, status, "DeleteData failed!"); + }; + + auto output = [env, ctxt](napi_value &result) { + ASSERT_WITH_ERRCODE(ctxt, !ctxt->unifiedDataSet.empty(), E_ERROR, "unifiedDataSet is empty!"); + ctxt->status = napi_create_array_with_length(env, ctxt->unifiedDataSet.size(), &ctxt->output); + ASSERT_WITH_ERRCODE(ctxt, ctxt->status == napi_ok, E_ERROR, "napi_create_array_with_length failed!"); + int index = 0; + for (const UnifiedData &data : ctxt->unifiedDataSet) { + std::shared_ptr<UnifiedData> unifiedData = std::make_shared<UnifiedData>(); + unifiedData->SetRecords(data.GetRecords()); + napi_value dataNapi = nullptr; + UnifiedDataNapi::NewInstance(env, unifiedData, dataNapi); + ctxt->status = napi_set_element(env, ctxt->output, index++, dataNapi); + ASSERT_WITH_ERRCODE(ctxt, ctxt->status == napi_ok, E_ERROR, "napi_set_element failed!"); + } + result = ctxt->output; + }; + return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute, output); +} + +napi_status UDMFNapi::GetNamedProperty(napi_env env, napi_value &obj, const std::string &key, std::string &value) +{ + bool hasKey = false; + napi_status status = napi_has_named_property(env, obj, key.c_str(), &hasKey); + if (status != napi_ok) { + LOG_ERROR(UDMF_KITS_NAPI, "napi_has_named_property failed, name = %{public}s", key.c_str()); + return napi_generic_failure; + } + if (!hasKey) { + LOG_ERROR(UDMF_KITS_NAPI, "The property name is non-existent, name: %{public}s", key.c_str()); + return napi_generic_failure; + } + napi_value napiValue = nullptr; + status = napi_get_named_property(env, obj, key.c_str(), &napiValue); + if (status != napi_ok || napiValue == nullptr) { + LOG_ERROR(UDMF_KITS_NAPI, "napi_get_named_property failed, name = %{public}s", key.c_str()); + return napi_generic_failure; + } + if (NapiDataUtils::IsNull(env, napiValue)) { + LOG_ERROR(UDMF_KITS_NAPI, "The property value is null, name = %{public}s", key.c_str()); + return napi_generic_failure; + } + status = NapiDataUtils::GetValue(env, napiValue, value); + if (status != napi_ok) { + LOG_ERROR(UDMF_KITS_NAPI, "NapiDataUtils::GetValue failed, name = %{public}s", key.c_str()); + return status; + } + LOG_DEBUG(UDMF_KITS_NAPI, "Param parse successful, Options.%{public}s = %{public}s", key.c_str(), value.c_str()); + return status; +} +} // namespace UDMF +} // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/jskitsimpl/data/unified_data_napi.cpp b/udmf/framework/jskitsimpl/data/unified_data_napi.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c6ad9771d683ccd9e4d7e67030849bed7fe6b002 --- /dev/null +++ b/udmf/framework/jskitsimpl/data/unified_data_napi.cpp @@ -0,0 +1,216 @@ +/* + * 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 "unified_data_napi.h" + +#include "application_defined_record_napi.h" +#include "audio_napi.h" +#include "file_napi.h" +#include "folder_napi.h" +#include "html_napi.h" +#include "image_napi.h" +#include "link_napi.h" +#include "napi_data_utils.h" +#include "napi_error_utils.h" +#include "napi_queue.h" +#include "plain_text_napi.h" +#include "system_defined_appitem_napi.h" +#include "system_defined_form_napi.h" +#include "system_defined_pixelmap_napi.h" +#include "system_defined_record_napi.h" +#include "text_napi.h" +#include "unified_data.h" +#include "unified_record_napi.h" +#include "video_napi.h" + +namespace OHOS { +namespace UDMF { +napi_value UnifiedDataNapi::Constructor(napi_env env) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "UnifiedDataNapi"); + napi_property_descriptor properties[] = { + /* UnifiedData properties */ + DECLARE_NAPI_FUNCTION("addRecord", AddRecord), + DECLARE_NAPI_FUNCTION("getRecords", GetRecords), + }; + size_t count = sizeof(properties) / sizeof(properties[0]); + return NapiDataUtils::DefineClass(env, "UnifiedData", properties, count, UnifiedDataNapi::New); +} + +napi_value UnifiedDataNapi::New(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "UnifiedDataNapi"); + UnifiedRecordNapi *uRecord = nullptr; + auto ctxt = std::make_shared<ContextBase>(); + auto input = [env, info, ctxt, &uRecord](size_t argc, napi_value *argv) { + // required 1 arguments :: <UnifiedRecord*> + ASSERT_BUSINESS_ERR(ctxt, argc <= 1, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + if (argc == 1) { + ctxt->status = napi_unwrap(env, *argv, reinterpret_cast<void **>(&uRecord)); + ASSERT_BUSINESS_ERR(ctxt, (ctxt->status == napi_ok && uRecord != nullptr && uRecord->value_ != nullptr), + Status::E_INVALID_PARAMETERS, "invalid object!"); + ctxt->status = UnifiedDataUtils::IsValidType(uRecord->value_->GetType()) ? napi_ok : napi_invalid_arg; + ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid type!"); + } + }; + + // Parsing input parameters + ctxt->GetCbInfoSync(env, info, input); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + auto *uData = new (std::nothrow) UnifiedDataNapi(); + ASSERT_ERR(ctxt->env, uData != nullptr, Status::E_UNKNOWN, "no memory for unified data!"); + uData->value_ = std::make_shared<UnifiedData>(); + if (uRecord) { + uData->value_->AddRecord(uRecord->value_); + } + ASSERT_CALL(env, napi_wrap(env, ctxt->self, uData, Destructor, nullptr, nullptr), uData); + return ctxt->self; +} + +void UnifiedDataNapi::Destructor(napi_env env, void *data, void *hint) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "UnifiedDataNapi finalize."); + auto *uData = static_cast<UnifiedDataNapi *>(data); + ASSERT_VOID(uData != nullptr, "finalize null!"); + delete uData; +} + +void UnifiedDataNapi::NewInstance(napi_env env, std::shared_ptr<UnifiedData> in, napi_value &out) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "UnifiedDataNapi"); + ASSERT_CALL_VOID(env, napi_new_instance(env, Constructor(env), 0, nullptr, &out)); + auto *unifiedData = new (std::nothrow) UnifiedDataNapi(); + ASSERT_ERR_VOID(env, unifiedData != nullptr, Status::E_UNKNOWN, "no memory for unified data!"); + unifiedData->value_ = in; + ASSERT_CALL_DELETE(env, napi_wrap(env, out, unifiedData, Destructor, nullptr, nullptr), unifiedData); +} + +UnifiedDataNapi *UnifiedDataNapi::GetUnifiedData(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "UnifiedDataNapi"); + auto ctxt = std::make_shared<ContextBase>(); + ctxt->GetCbInfoSync(env, info); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + return static_cast<UnifiedDataNapi *>(ctxt->native); +} + +napi_value UnifiedDataNapi::AddRecord(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "UnifiedDataNapi"); + UnifiedRecordNapi *uRecord = nullptr; + auto ctxt = std::make_shared<ContextBase>(); + auto input = [env, info, ctxt, &uRecord](size_t argc, napi_value *argv) { + ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + ctxt->status = napi_unwrap(env, *argv, reinterpret_cast<void **>(&uRecord)); + ASSERT_BUSINESS_ERR(ctxt, (ctxt->status == napi_ok && uRecord != nullptr && uRecord->value_ != nullptr), + Status::E_INVALID_PARAMETERS, "invalid object!"); + ctxt->status = UnifiedDataUtils::IsValidType(uRecord->value_->GetType()) ? napi_ok : napi_invalid_arg; + ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid type!"); + }; + ctxt->GetCbInfoSync(env, info, input); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + auto *uData = static_cast<UnifiedDataNapi *>(ctxt->native); + ASSERT_ERR( + ctxt->env, (uData != nullptr && uData->value_ != nullptr), Status::E_INVALID_PARAMETERS, "invalid object!"); + uData->value_->AddRecord(uRecord->value_); + return nullptr; +} + +napi_value UnifiedDataNapi::GetRecords(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "UnifiedDataNapi"); + auto ctxt = std::make_shared<ContextBase>(); + auto uData = GetUnifiedData(env, info); + ASSERT_ERR( + ctxt->env, (uData != nullptr && uData->value_ != nullptr), Status::E_INVALID_PARAMETERS, "invalid object!"); + std::vector<std::shared_ptr<UnifiedRecord>> records = uData->value_->GetRecords(); + napi_status status = napi_create_array_with_length(env, records.size(), &ctxt->output); + ASSERT_ERR(ctxt->env, status == napi_ok, Status::E_ERROR, "init array failed!"); + int index = 0; + for (const std::shared_ptr<UnifiedRecord> &recordPtr : records) { + napi_value recordNapi = nullptr; + GetRecord(env, recordPtr, recordNapi); + ctxt->status = napi_set_element(env, ctxt->output, index++, recordNapi); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_ERROR, "set element failed!"); + } + return ctxt->output; +} + +void UnifiedDataNapi::GetRecord(napi_env env, std::shared_ptr<UnifiedRecord> in, napi_value &out) +{ + switch (in->GetType()) { + case TEXT: { + TextNapi::NewInstance(env, in, out); + break; + } + case PLAIN_TEXT: { + PlainTextNapi::NewInstance(env, in, out); + break; + } + case HTML: { + HtmlNapi::NewInstance(env, in, out); + break; + } + case HYPERLINK: { + LinkNapi::NewInstance(env, in, out); + break; + } + case FILE: { + FileNapi::NewInstance(env, in, out); + break; + } + case IMAGE: { + ImageNapi::NewInstance(env, in, out); + break; + } + case VIDEO: { + VideoNapi::NewInstance(env, in, out); + break; + } + case AUDIO: { + AudioNapi::NewInstance(env, in, out); + break; + } + case FOLDER: { + FolderNapi::NewInstance(env, in, out); + break; + } + case SYSTEM_DEFINED_RECORD: { + SystemDefinedRecordNapi::NewInstance(env, in, out); + break; + } + case SYSTEM_DEFINED_APP_ITEM: { + SystemDefinedAppItemNapi::NewInstance(env, in, out); + break; + } + case SYSTEM_DEFINED_FORM: { + SystemDefinedFormNapi::NewInstance(env, in, out); + break; + } + case SYSTEM_DEFINED_PIXEL_MAP: { + SystemDefinedPixelMapNapi::NewInstance(env, in, out); + break; + } + case APPLICATION_DEFINED_RECORD: { + ApplicationDefinedRecordNapi::NewInstance(env, in, out); + break; + } + default: + LOG_INFO(UDMF_KITS_NAPI, "GetRecord default"); + break; + } +} +} // namespace UDMF +} // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/jskitsimpl/data/unified_record_napi.cpp b/udmf/framework/jskitsimpl/data/unified_record_napi.cpp new file mode 100644 index 0000000000000000000000000000000000000000..35192f568dfa8d20b9c44b0fce2a08752c450d69 --- /dev/null +++ b/udmf/framework/jskitsimpl/data/unified_record_napi.cpp @@ -0,0 +1,79 @@ +/* + * 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 "unified_record_napi.h" + +#include "napi_data_utils.h" +#include "napi_error_utils.h" +#include "napi_queue.h" +#include "unified_record.h" + +namespace OHOS { +namespace UDMF { +napi_value UnifiedRecordNapi::Constructor(napi_env env) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "UnifiedRecordNapi"); + napi_property_descriptor properties[] = { + /* UnifiedRecord properties */ + DECLARE_NAPI_FUNCTION("getType", GetType), + }; + size_t count = sizeof(properties) / sizeof(properties[0]); + return NapiDataUtils::DefineClass(env, "UnifiedRecord", properties, count, UnifiedRecordNapi::New); +} + +napi_value UnifiedRecordNapi::New(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "UnifiedRecordNapi"); + auto ctxt = std::make_shared<ContextBase>(); + ctxt->GetCbInfoSync(env, info); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + + auto *udRecord = new (std::nothrow) UnifiedRecordNapi(); + ASSERT_ERR(ctxt->env, udRecord != nullptr, Status::E_UNKNOWN, "no memory for unified record!"); + udRecord->value_ = std::make_shared<UnifiedRecord>(); + ASSERT_CALL(env, napi_wrap(env, ctxt->self, udRecord, Destructor, nullptr, nullptr), udRecord); + return ctxt->self; +} + +void UnifiedRecordNapi::Destructor(napi_env env, void *data, void *hint) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "UnifiedRecordNapi finalize."); + auto *uRecord = static_cast<UnifiedRecordNapi *>(data); + ASSERT_VOID(uRecord != nullptr, "finalize null!"); + delete uRecord; +} + +UnifiedRecordNapi *UnifiedRecordNapi::GetUnifiedRecord( + napi_env env, napi_callback_info info, std::shared_ptr<ContextBase> ctxt) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "UnifiedRecordNapi"); + ctxt->GetCbInfoSync(env, info); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + return static_cast<UnifiedRecordNapi *>(ctxt->native); +} + +napi_value UnifiedRecordNapi::GetType(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "UnifiedRecordNapi"); + auto ctxt = std::make_shared<ContextBase>(); + auto uRecord = GetUnifiedRecord(env, info, ctxt); + ASSERT_ERR(ctxt->env, (uRecord != nullptr && uRecord->value_ != nullptr), Status::E_INVALID_PARAMETERS, + "invalid object!"); + ctxt->status = NapiDataUtils::SetValue(env, UD_TYPE_MAP.at(uRecord->value_->GetType()), ctxt->output); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "set type failed!"); + return ctxt->output; +} +} // namespace UDMF +} // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/jskitsimpl/data/video_napi.cpp b/udmf/framework/jskitsimpl/data/video_napi.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a9df4142d932b52ba14b5bae275f5bae77fcfcde --- /dev/null +++ b/udmf/framework/jskitsimpl/data/video_napi.cpp @@ -0,0 +1,114 @@ +/* + * 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 "video_napi.h" + +#include "file_napi.h" +#include "napi_data_utils.h" +#include "napi_error_utils.h" +#include "napi_queue.h" +#include "unified_record_napi.h" +#include "video.h" + +namespace OHOS { +namespace UDMF { +napi_value VideoNapi::Constructor(napi_env env) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "VideoNapi"); + napi_property_descriptor properties[] = { + /* Video extends UnifiedRecord */ + DECLARE_NAPI_FUNCTION("getType", UnifiedRecordNapi::GetType), + /* Video extends File */ + DECLARE_NAPI_GETTER_SETTER("details", FileNapi::GetDetails, FileNapi::SetDetails), + DECLARE_NAPI_GETTER_SETTER("uri", FileNapi::GetUri, FileNapi::SetUri), + /* Video properties */ + DECLARE_NAPI_GETTER_SETTER("videoUri", GetVideoUri, SetVideoUri), + }; + size_t count = sizeof(properties) / sizeof(properties[0]); + return NapiDataUtils::DefineClass(env, "Video", properties, count, VideoNapi::New); +} + +napi_value VideoNapi::New(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "VideoNapi"); + auto ctxt = std::make_shared<ContextBase>(); + ctxt->GetCbInfoSync(env, info); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + + auto *video = new (std::nothrow) VideoNapi(); + ASSERT_ERR(ctxt->env, video != nullptr, Status::E_UNKNOWN, "no memory for video!"); + video->value_ = std::make_shared<Video>(); + ASSERT_CALL(env, napi_wrap(env, ctxt->self, video, Destructor, nullptr, nullptr), video); + return ctxt->self; +} + +void VideoNapi::NewInstance(napi_env env, std::shared_ptr<UnifiedRecord> in, napi_value &out) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "VideoNapi"); + ASSERT_CALL_VOID(env, napi_new_instance(env, Constructor(env), 0, nullptr, &out)); + auto *video = new (std::nothrow) VideoNapi(); + ASSERT_ERR_VOID(env, video != nullptr, Status::E_UNKNOWN, "no memory for video!"); + video->value_ = std::static_pointer_cast<Video>(in); + ASSERT_CALL_DELETE(env, napi_wrap(env, out, video, Destructor, nullptr, nullptr), video); +} + +void VideoNapi::Destructor(napi_env env, void *data, void *hint) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "VideoNapi finalize."); + auto *video = static_cast<VideoNapi *>(data); + ASSERT_VOID(video != nullptr, "finalize null!"); + delete video; +} + +VideoNapi *VideoNapi::GetVideo(napi_env env, napi_callback_info info, std::shared_ptr<ContextBase> ctxt) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "VideoNapi"); + ctxt->GetCbInfoSync(env, info); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + return static_cast<VideoNapi *>(ctxt->native); +} + +napi_value VideoNapi::GetVideoUri(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "VideoNapi"); + auto ctxt = std::make_shared<ContextBase>(); + auto video = GetVideo(env, info, ctxt); + ASSERT_ERR( + ctxt->env, (video != nullptr && video->value_ != nullptr), Status::E_INVALID_PARAMETERS, "invalid object!"); + ctxt->status = NapiDataUtils::SetValue(env, video->value_->GetUri(), ctxt->output); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "set video uri failed!"); + return ctxt->output; +} + +napi_value VideoNapi::SetVideoUri(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "VideoNapi"); + auto ctxt = std::make_shared<ContextBase>(); + std::string uri; + auto input = [env, ctxt, &uri](size_t argc, napi_value *argv) { + ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + ctxt->status = NapiDataUtils::GetValue(env, argv[0], uri); + ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + }; + ctxt->GetCbInfoSync(env, info, input); + ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + auto video = static_cast<VideoNapi *>(ctxt->native); + ASSERT_ERR( + ctxt->env, (video != nullptr && video->value_ != nullptr), Status::E_INVALID_PARAMETERS, "invalid object!"); + video->value_->SetUri(uri); + return nullptr; +} +} // namespace UDMF +} // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/jskitsimpl/unittest/BUILD.gn b/udmf/framework/jskitsimpl/unittest/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..75bf5b1128706c64bafffdb9a724e7aba1ff3af7 --- /dev/null +++ b/udmf/framework/jskitsimpl/unittest/BUILD.gn @@ -0,0 +1,30 @@ +# 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. + +import("//build/test.gni") +import("//foundation/distributeddatamgr/udmf/udmf.gni") + +module_output_path = "udmf/jskitsimpl" + +ohos_js_unittest("UDMFJsTest") { + module_out_path = module_output_path + + hap_profile = "./config.json" + + certificate_profile = "${developer_test_path}/signature/openharmony_sx.p7b" +} + +group("unittest") { + testonly = true + deps = [ ":UDMFJsTest" ] +} diff --git a/udmf/framework/jskitsimpl/unittest/UdmfCallbackJsTest.js b/udmf/framework/jskitsimpl/unittest/UdmfCallbackJsTest.js new file mode 100644 index 0000000000000000000000000000000000000000..50ac19dca99e007866391002da665cf6f19a7d24 --- /dev/null +++ b/udmf/framework/jskitsimpl/unittest/UdmfCallbackJsTest.js @@ -0,0 +1,344 @@ +/* + * 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. + */ + +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from 'deccjsunit/index'; +import UDMF from '@ohos.data.UDMF'; + +const TEXT_CONTEXT_01 = 'TextContent01'; +const TEXT_CONTEXT_02 = 'TextContent02'; +const ERROR_PARAMETER = '401'; + +describe('UdmfCallbackJSTest', function () { + + let gPlainText1 = new UDMF.PlainText(); + gPlainText1.textContent = TEXT_CONTEXT_01; + let gPlainText2 = new UDMF.PlainText(); + gPlainText2.textContent = TEXT_CONTEXT_02; + + const optionsValid = { intention: 'DataHub', }; + const optionsInValidIntention = { intention: 'Drag', }; + const optionsInValidKey = { key: 'udmf://drag/com.test.demo/123456789', }; + const optionsInValidAll = { intention: 'DataHub', key: 'udmf://drag/com.test.demo/123456789' }; + const unifiedData01 = new UDMF.UnifiedData(gPlainText1); + const unifiedData02 = new UDMF.UnifiedData(gPlainText2); + const unifiedDataInvalid = new UDMF.UnifiedData(); + + /** + * @tc.name UdmfInsertCallbackInvalidOptionsTest + * @tc.desc Test Js Api insertData with invalid options + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('UdmfInsertCallbackInvalidOptionsTest', 0, async function (done) { + const TAG = 'UdmfInsertCallbackInvalidOptionsTest:'; + console.info(TAG, 'start'); + try { + UDMF.insertData(optionsInValidIntention, unifiedData01, (err, data) => { + console.info(TAG, 'Unreachable code!'); + expect(null).assertFail(); + done(); + }); + } catch (e) { + console.error(TAG, `get e. code is ${e.code},message is ${e.message} `); + expect(e.code === ERROR_PARAMETER).assertTrue(); + done(); + } + console.info(TAG, 'end'); + }); + + /** + * @tc.name UdmfInsertCallbackInvalidDataTest + * @tc.desc Test Js Api insertData with invalid UnifiedData + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('UdmfInsertCallbackInvalidDataTest', 0, async function (done) { + const TAG = 'UdmfInsertCallbackInvalidDataTest:'; + console.info(TAG, 'start'); + try { + UDMF.insertData(optionsValid, unifiedDataInvalid, (err, data) => { + expect(data).assertUndefined(); + console.error(TAG, `get fail. code is ${err.code},message is ${err.message} `); + expect(err.code === ERROR_PARAMETER).assertTrue(); + done(); + }); + } catch (e) { + console.error(TAG, 'Unreachable code!'); + expect(null).assertFail(); + done(); + } + console.info(TAG, 'end'); + }); + + /** + * @tc.name UdmfInsertCallbackSucTest + * @tc.desc Test Js Api insertData successful + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('UdmfInsertCallbackSucTest', 0, async function (done) { + const TAG = 'UdmfInsertCallbackSucTest:'; + console.info(TAG, 'start'); + try { + UDMF.insertData(optionsValid, unifiedData01, (err, data) => { + expect(err).assertUndefined(); + console.info(TAG, `insert success. The key: ${data}`); + let options = { key: data }; + console.info(TAG, `query start. The options: ${JSON.stringify(options)}`); + UDMF.queryData(options, (err, data) => { + expect(err).assertUndefined(); + console.info(TAG, 'query success.'); + console.info(TAG, `data.length = ${data.length}.`); + expect(data.length).assertEqual(1); + let records = data[0].getRecords(); + console.info(TAG, `records.length = ${records.length}.`); + console.info(TAG, `records[0].getType() = ${records[0].getType()}.`); + console.info(TAG, `records[0].textContent = ${records[0].textContent}.`); + expect(records.length).assertEqual(1); + expect(records[0].getType()).assertEqual(UDMF.UnifiedDataType.PLAIN_TEXT); + expect(records[0].textContent).assertEqual(TEXT_CONTEXT_01); + done(); + }); + }); + } catch (e) { + console.error(TAG, 'Unreachable code!'); + expect(null).assertFail(); + done(); + } + console.info(TAG, 'end'); + }); + + /** + * @tc.name UdmfUpdateCallbackInvalidOptionsTest + * @tc.desc Test Js Api updateData with invalid options + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('UdmfUpdateCallbackInvalidOptionsTest', 0, async function (done) { + const TAG = 'UdmfUpdateCallbackInvalidOptionsTest:'; + console.info(TAG, 'start'); + try { + UDMF.updateData(optionsInValidKey, unifiedData01, (err) => { + console.error(TAG, 'Unreachable code!'); + expect(null).assertFail(); + }); + done(); + } catch (e) { + console.error(TAG, `get e. code is ${e.code},message is ${e.message} `); + expect(e.code === ERROR_PARAMETER).assertTrue(); + done(); + } + console.info(TAG, 'end'); + }); + + /** + * @tc.name UdmfUpdateCallbackInvalidDataTest + * @tc.desc Test Js Api updateData with invalid UnifiedData + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('UdmfUpdateCallbackInvalidDataTest', 0, async function (done) { + const TAG = 'UdmfUpdateCallbackInvalidDataTest:'; + console.info(TAG, 'start'); + try { + UDMF.insertData(optionsValid, unifiedData01, (err, data) => { + expect(err).assertUndefined(); + console.info(TAG, `insert success. The key: ${data}`); + let options = { key: data }; + console.info(TAG, `update start. The options: ${JSON.stringify(options)}`); + UDMF.updateData(options, unifiedDataInvalid, (err) => { + console.error(TAG, `get fail. code is ${err.code},message is ${err.message} `); + expect(err.code === ERROR_PARAMETER).assertTrue(); + done(); + }); + }); + } catch (e) { + console.error(TAG, 'Unreachable code!'); + expect(null).assertFail(); + done(); + } + console.info(TAG, 'end'); + }); + + /** + * @tc.name UdmfUpdateCallbackSucTest + * @tc.desc Test Js Api updateData successful + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('UdmfUpdateCallbackSucTest', 0, async function (done) { + const TAG = 'UdmfUpdateCallbackSucTest:'; + console.info(TAG, 'start'); + try { + UDMF.insertData(optionsValid, unifiedData01, (err, data) => { + expect(err).assertUndefined(); + console.info(TAG, `insert success. The key: ${data}`); + let options = { key: data }; + console.info(TAG, `update start. The options: ${JSON.stringify(options)}`); + UDMF.updateData(options, unifiedData02, (err) => { + expect(err).assertUndefined(); + console.info(TAG, 'update success.'); + UDMF.queryData(options, (err, data) => { + expect(err).assertUndefined(); + console.info(TAG, 'query success.'); + expect(data.length).assertEqual(1); + let records = data[0].getRecords(); + expect(records.length).assertEqual(1); + expect(records[0].getType()).assertEqual(UDMF.UnifiedDataType.PLAIN_TEXT); + expect(records[0].textContent).assertEqual(TEXT_CONTEXT_02); + done(); + }); + }); + }); + + } catch (e) { + console.error(TAG, 'Unreachable code!'); + expect(null).assertFail(); + done(); + } + console.info(TAG, 'end'); + }); + + + /** + * @tc.name UdmfQueryCallbackInvalidOptionsTest + * @tc.desc Test Js Api queryData with invalid options + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('UdmfQueryCallbackInvalidOptionsTest', 0, async function (done) { + const TAG = 'UdmfQueryCallbackInvalidOptionsTest:'; + console.info(TAG, 'start'); + try { + UDMF.queryData(optionsInValidAll, (err, data) => { + console.error(TAG, 'Unreachable code!'); + expect(null).assertFail(); + done(); + }); + } catch (e) { + console.error(TAG, `get e. code is ${e.code},message is ${e.message} `); + expect(e.code === ERROR_PARAMETER).assertTrue(); + done(); + } + console.info(TAG, 'end'); + }); + + /** + * @tc.name UdmfQueryCallbackSucTest + * @tc.desc Test Js Api queryData successful + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('UdmfQueryCallbackSucTest', 0, async function (done) { + const TAG = 'UdmfQueryCallbackSucTest:'; + console.info(TAG, 'start'); + try { + UDMF.deleteData(optionsValid, (err, data) => { + expect(err).assertUndefined(); + console.info(TAG, 'delete success.'); + UDMF.queryData(optionsValid, (err, data) => { + console.info(TAG, 'query has no data.'); + expect(data).assertUndefined(); + UDMF.insertData(optionsValid, unifiedData01, (err, data) => { + expect(err).assertUndefined(); + console.info(TAG, `insert success. The key: ${data}`); + UDMF.insertData(optionsValid, unifiedData02, (err, data) => { + expect(err).assertUndefined(); + console.info(TAG, `insert success. The key: ${data}`); + UDMF.queryData(optionsValid, function (err, data) { + expect(err).assertUndefined(); + console.info(TAG, `query success.`); + expect(data.length).assertEqual(2); + done(); + }); + }); + }); + }); + }); + } catch (e) { + console.error(TAG, 'Unreachable code!'); + expect(null).assertFail(); + done(); + } + console.info(TAG, 'end'); + }); + + + /** + * @tc.name UdmfDeleteCallbackInvalidOptionsTest + * @tc.desc Test Js Api deleteData with invalid options + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('UdmfDeleteCallbackInvalidOptionsTest', 0, async function (done) { + const TAG = 'UdmfDeleteCallbackInvalidOptionsTest:'; + console.info(TAG, 'start'); + try { + UDMF.deleteData(optionsInValidAll, (err, data) => { + console.error(TAG, 'Unreachable code!'); + expect(null).assertFail(); + done(); + }); + } catch (e) { + console.error(TAG, `get e. code is ${e.code},message is ${e.message} `); + expect(e.code === ERROR_PARAMETER).assertTrue(); + done(); + } + console.info(TAG, 'end'); + }); + + /** + * @tc.name UdmfDeleteCallbackSucTest + * @tc.desc Test Js Api deleteData successful + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('UdmfDeleteCallbackSucTest', 0, async function (done) { + const TAG = 'UdmfDeleteCallbackSucTest:'; + console.info(TAG, 'start'); + try { + UDMF.insertData(optionsValid, unifiedData01, (err, data) => { + expect(err).assertUndefined(); + console.info(TAG, `insert success. The key: ${data}`); + let options = { key: data }; + console.info(TAG, `query start. The options: ${JSON.stringify(options)}`); + UDMF.queryData(options, (err, data) => { + expect(err).assertUndefined(); + console.info(TAG, 'query success.'); + expect(data.length).assertEqual(1); + UDMF.deleteData(options, (err, data) => { + expect(err).assertUndefined(); + console.info(TAG, 'delete success.'); + expect(data.length).assertEqual(1); + let records = data[0].getRecords(); + expect(records.length).assertEqual(1); + expect(records[0].getType()).assertEqual(UDMF.UnifiedDataType.PLAIN_TEXT); + expect(records[0].textContent).assertEqual(TEXT_CONTEXT_01); + UDMF.queryData(options, (err, data) => { + expect(data).assertUndefined(); + console.info(TAG, 'query has no data.'); + done(); + }); + }); + }); + }); + } catch (e) { + console.error(TAG, 'Unreachable code!'); + expect(null).assertFail(); + done(); + } + console.info(TAG, 'end'); + }); +}); \ No newline at end of file diff --git a/udmf/framework/jskitsimpl/unittest/UdmfJsTest.js b/udmf/framework/jskitsimpl/unittest/UdmfJsTest.js new file mode 100644 index 0000000000000000000000000000000000000000..2a88a7b61b46e367943c7e20c139063ccd9b23b4 --- /dev/null +++ b/udmf/framework/jskitsimpl/unittest/UdmfJsTest.js @@ -0,0 +1,416 @@ +/* + * 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. + */ + +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from 'deccjsunit/index'; +import UDMF from '@ohos.data.UDMF'; + +const TEST_BUNDLE_NAME = 'MyBundleName'; +const KEY_TEST_ELEMENT = 'TestKey'; +const VALUE_TEST_ELEMENT = 'TestValue'; +const TEST_ID = 123456; +const TEST_ABILITY_NAME = 'MyAbilityName'; +const TEST_MODULE = 'MyModule'; + +let U8_ARRAY = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); + +describe('UdmfJSTest', function () { + + /** + * @tc.name UdmfTextTest + * @tc.desc Test Js Api Text testcase + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('UdmfTextTest', 0, function () { + console.info('UdmfTextTest start'); + let text = new UDMF.Text(); + text.details = { + Key: 'text' + KEY_TEST_ELEMENT, + Value: 'text' + VALUE_TEST_ELEMENT, + }; + let unifiedData = new UDMF.UnifiedData(text); + let records = unifiedData.getRecords(); + expect(records.length).assertEqual(1); + expect(records[0].details.Key).assertEqual('text' + KEY_TEST_ELEMENT); + expect(records[0].details.Value).assertEqual('text' + VALUE_TEST_ELEMENT); + console.info('UdmfTextTest end'); + }); + + /** + * @tc.name UdmfPlainTextTest + * @tc.desc Test Js Api PlainText testcase + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('UdmfPlainTextTest', 0, function () { + console.info('UdmfPlainTextTest start'); + let plainText = new UDMF.PlainText(); + plainText.details = { + Key: 'text' + KEY_TEST_ELEMENT, + Value: 'text' + VALUE_TEST_ELEMENT, + }; + plainText.textContent = 'textContent'; + plainText.abstract = 'abstract'; + let unifiedData = new UDMF.UnifiedData(plainText); + let records = unifiedData.getRecords(); + expect(records.length).assertEqual(1); + expect(records[0].details.Key).assertEqual('text' + KEY_TEST_ELEMENT); + expect(records[0].details.Value).assertEqual('text' + VALUE_TEST_ELEMENT); + expect(records[0].textContent).assertEqual('textContent'); + expect(records[0].abstract).assertEqual('abstract'); + console.info('UdmfPlainTextTest end'); + }); + + /** + * @tc.name UdmfHyperlinkTest + * @tc.desc Test Js Api Hyperlink testcase + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('UdmfHyperlinkTest', 0, function () { + console.info('UdmfHyperlinkTest start'); + let link = new UDMF.Hyperlink(); + link.details = { + Key: 'link' + KEY_TEST_ELEMENT, + Value: 'link' + VALUE_TEST_ELEMENT, + }; + link.url = 'url'; + link.description = 'description'; + let unifiedData = new UDMF.UnifiedData(link); + let records = unifiedData.getRecords(); + expect(records.length).assertEqual(1); + expect(records[0].details.Key).assertEqual('link' + KEY_TEST_ELEMENT); + expect(records[0].details.Value).assertEqual('link' + VALUE_TEST_ELEMENT); + expect(records[0].url).assertEqual('url'); + expect(records[0].description).assertEqual('description'); + console.info('UdmfHyperlinkTest end'); + }); + + /** + * @tc.name UdmfHtmlTest + * @tc.desc Test Js Api HTML testcase + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('UdmfHtmlTest', 0, function () { + console.info('UdmfHtmlTest start'); + let html = new UDMF.HTML(); + html.details = { + Key: 'html' + KEY_TEST_ELEMENT, + Value: 'html' + VALUE_TEST_ELEMENT, + }; + html.htmlContent = 'htmlContent'; + html.plainContent = 'plainContent'; + let unifiedData = new UDMF.UnifiedData(html); + let records = unifiedData.getRecords(); + expect(records.length).assertEqual(1); + expect(records[0].details.Key).assertEqual('html' + KEY_TEST_ELEMENT); + expect(records[0].details.Value).assertEqual('html' + VALUE_TEST_ELEMENT); + expect(records[0].htmlContent).assertEqual('htmlContent'); + expect(records[0].plainContent).assertEqual('plainContent'); + console.info('UdmfHtmlTest end'); + }); + + /** + * @tc.name UdmfFileTest + * @tc.desc Test Js Api File testcase + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('UdmfFileTest', 0, function () { + console.info('UdmfFileTest start'); + let file = new UDMF.File(); + file.details = { + Key: 'file' + KEY_TEST_ELEMENT, + Value: 'file' + VALUE_TEST_ELEMENT, + }; + file.uri = 'uri'; + let unifiedData = new UDMF.UnifiedData(file); + let records = unifiedData.getRecords(); + expect(records.length).assertEqual(1); + expect(records[0].details.Key).assertEqual('file' + KEY_TEST_ELEMENT); + expect(records[0].details.Value).assertEqual('file' + VALUE_TEST_ELEMENT); + expect(records[0].uri).assertEqual('uri'); + console.info('UdmfFileTest end'); + }); + + /** + * @tc.name UdmfFolderTest + * @tc.desc Test Js Api Folder testcase + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('UdmfFolderTest', 0, function () { + console.info('UdmfFolderTest start'); + let folder = new UDMF.Folder(); + folder.details = { + Key: 'folder' + KEY_TEST_ELEMENT, + Value: 'folder' + VALUE_TEST_ELEMENT, + }; + folder.uri = 'folderUri'; + let unifiedData = new UDMF.UnifiedData(folder); + let records = unifiedData.getRecords(); + expect(records.length).assertEqual(1); + expect(records[0].details.Key).assertEqual('folder' + KEY_TEST_ELEMENT); + expect(records[0].details.Value).assertEqual('folder' + VALUE_TEST_ELEMENT); + expect(records[0].uri).assertEqual('folderUri'); + console.info('UdmfFolderTest end'); + }); + + /** + * @tc.name UdmfImageTest + * @tc.desc Test Js Api Image testcase + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('UdmfImageTest', 0, function () { + console.info('UdmfImageTest start'); + let image = new UDMF.Image(); + image.details = { + Key: 'image' + KEY_TEST_ELEMENT, + Value: 'image' + VALUE_TEST_ELEMENT, + }; + image.imageUri = 'imageUri'; + let unifiedData = new UDMF.UnifiedData(image); + let records = unifiedData.getRecords(); + expect(records.length).assertEqual(1); + expect(records[0].details.Key).assertEqual('image' + KEY_TEST_ELEMENT); + expect(records[0].details.Value).assertEqual('image' + VALUE_TEST_ELEMENT); + expect(records[0].imageUri).assertEqual('imageUri'); + console.info('UdmfImageTest end'); + }); + + /** + * @tc.name UdmfVideoTest + * @tc.desc Test Js Api Video testcase + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('UdmfVideoTest', 0, function () { + console.info('UdmfVideoTest start'); + let video = new UDMF.Video(); + video.details = { + Key: 'video' + KEY_TEST_ELEMENT, + Value: 'video' + VALUE_TEST_ELEMENT, + }; + video.videoUri = 'videoUri'; + let unifiedData = new UDMF.UnifiedData(video); + let records = unifiedData.getRecords(); + expect(records.length).assertEqual(1); + expect(records[0].details.Key).assertEqual('video' + KEY_TEST_ELEMENT); + expect(records[0].details.Value).assertEqual('video' + VALUE_TEST_ELEMENT); + expect(records[0].videoUri).assertEqual('videoUri'); + console.info('UdmfVideoTest end'); + }); + + /** + * @tc.name UdmfSystemDefinedRecordTest + * @tc.desc Test Js Api SystemDefinedRecord testcase + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('UdmfSystemDefinedRecordTest', 0, function () { + console.info('UdmfSystemDefinedRecordTest start'); + let systemDefinedRecord = new UDMF.SystemDefinedRecord(); + systemDefinedRecord.details = { + recordKey1: 'systemDefinedRecord' + KEY_TEST_ELEMENT, + recordKey2: 1, + recordKey3: U8_ARRAY, + }; + let unifiedData = new UDMF.UnifiedData(systemDefinedRecord); + let records = unifiedData.getRecords(); + expect(records.length).assertEqual(1); + expect(records[0].details.recordKey1).assertEqual('systemDefinedRecord' + KEY_TEST_ELEMENT); + expect(records[0].details.recordKey2).assertEqual(1); + for (let i = 0; i < U8_ARRAY.length; i++) { + expect(records[0].details.recordKey3[i]).assertEqual(U8_ARRAY[i]); + } + console.info('UdmfSystemDefinedRecordTest end'); + }); + + /** + * @tc.name UdmfSystemDefinedPixelMapTest + * @tc.desc Test Js Api SystemDefinedPixelMap testcase + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('UdmfSystemDefinedPixelMapTest', 0, function () { + console.info('UdmfSystemDefinedPixelMapTest start'); + let systemDefinedPixelMap = new UDMF.SystemDefinedPixelMap(); + systemDefinedPixelMap.details = { + recordKey1: 'systemDefinedPixelMap' + KEY_TEST_ELEMENT, + recordKey2: 1, + recordKey3: U8_ARRAY, + }; + systemDefinedPixelMap.rawData = U8_ARRAY; + let unifiedData = new UDMF.UnifiedData(systemDefinedPixelMap); + let records = unifiedData.getRecords(); + expect(records.length).assertEqual(1); + expect(records[0].details.recordKey1).assertEqual('systemDefinedPixelMap' + KEY_TEST_ELEMENT); + expect(records[0].details.recordKey2).assertEqual(1); + for (let i = 0; i < U8_ARRAY.length; i++) { + expect(records[0].details.recordKey3[i]).assertEqual(U8_ARRAY[i]); + } + for (let i = 0; i < U8_ARRAY.length; i++) { + expect(records[0].rawData[i]).assertEqual(U8_ARRAY[i]); + } + console.info('UdmfSystemDefinedPixelMapTest end'); + }); + + /** + * @tc.name UdmfSystemDefinedFormTest + * @tc.desc Test Js Api SystemDefinedForm testcase + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('UdmfSystemDefinedFormTest', 0, function () { + console.info('UdmfSystemDefinedFormTest start'); + let form = new UDMF.SystemDefinedForm(); + form.formId = TEST_ID; + form.formName = 'MyFormName'; + form.bundleName = TEST_BUNDLE_NAME; + form.abilityName = TEST_ABILITY_NAME; + form.module = TEST_MODULE; + form.details = { + formKey1: 1, + formKey2: 'form' + VALUE_TEST_ELEMENT, + formKey3: U8_ARRAY, + }; + let unifiedData = new UDMF.UnifiedData(form); + let records = unifiedData.getRecords(); + expect(records.length).assertEqual(1); + expect(records[0].details.formKey1).assertEqual(1); + expect(records[0].details.formKey2).assertEqual('form' + VALUE_TEST_ELEMENT); + for (let i = 0; i < U8_ARRAY.length; i++) { + expect(records[0].details.formKey3[i]).assertEqual(U8_ARRAY[i]); + } + expect(records[0].formId).assertEqual(TEST_ID); + expect(records[0].formName).assertEqual('MyFormName'); + expect(records[0].bundleName).assertEqual(TEST_BUNDLE_NAME); + expect(records[0].abilityName).assertEqual(TEST_ABILITY_NAME); + expect(records[0].module).assertEqual(TEST_MODULE); + console.info('UdmfSystemDefinedFormTest end'); + }); + + /** + * @tc.name UdmfSystemDefinedAppItemTest + * @tc.desc Test Js Api SystemDefinedAppItem testcase + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('UdmfSystemDefinedAppItemTest', 0, function () { + console.info('UdmfSystemDefinedAppItemTest start'); + let appItem = new UDMF.SystemDefinedAppItem(); + appItem.appId = 'MyAppId'; + appItem.appName = 'MyAppName'; + appItem.abilityName = TEST_ABILITY_NAME; + appItem.bundleName = TEST_BUNDLE_NAME; + appItem.appIconId = 'MyAppIconId'; + appItem.appLabelId = 'MyAppLabelId'; + appItem.details = { + appItemKey1: 1, + appItemKey2: 'appItem' + VALUE_TEST_ELEMENT, + appItemKey3: U8_ARRAY, + }; + let unifiedData = new UDMF.UnifiedData(appItem); + let records = unifiedData.getRecords(); + expect(records.length).assertEqual(1); + expect(records[0].details.appItemKey1).assertEqual(1); + expect(records[0].details.appItemKey2).assertEqual('appItem' + VALUE_TEST_ELEMENT); + for (let i = 0; i < U8_ARRAY.length; i++) { + expect(records[0].details.appItemKey3[i]).assertEqual(U8_ARRAY[i]); + } + expect(records[0].appId).assertEqual('MyAppId'); + expect(records[0].appName).assertEqual('MyAppName'); + expect(records[0].abilityName).assertEqual(TEST_ABILITY_NAME); + expect(records[0].bundleName).assertEqual(TEST_BUNDLE_NAME); + expect(records[0].appIconId).assertEqual('MyAppIconId'); + expect(records[0].appLabelId).assertEqual('MyAppLabelId'); + console.info('UdmfSystemDefinedAppItemTest end'); + }); + + /** + * @tc.name UdmfSystemDefinedFormTest + * @tc.desc Test Js Api ApplicationDefinedRecord testcase + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('UdmfApplicationDefinedRecord', 0, function () { + console.info('UdmfApplicationDefinedRecord start'); + let applicationDefinedRecord = new UDMF.ApplicationDefinedRecord(); + applicationDefinedRecord.applicationDefinedType = 'applicationDefinedType'; + applicationDefinedRecord.rawData = U8_ARRAY; + let unifiedData = new UDMF.UnifiedData(applicationDefinedRecord); + let records = unifiedData.getRecords(); + expect(records.length).assertEqual(1); + expect(records[0].applicationDefinedType).assertEqual('applicationDefinedType'); + for (let i = 0; i < U8_ARRAY.length; i++) { + expect(records[0].rawData[i]).assertEqual(U8_ARRAY[i]); + } + console.info('UdmfApplicationDefinedRecord end'); + }); + + /** + * @tc.name UdmfAllRecordsTest + * @tc.desc Test Js AllRecords testcase + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('UdmfAllRecordsTest', 0, function () { + console.info('UdmfAllRecordsTest start'); + let text = new UDMF.Text(); + let unifiedDatas = new UDMF.UnifiedData(text); + let plainText = new UDMF.PlainText(); + unifiedDatas.addRecord(plainText); + let link = new UDMF.Hyperlink(); + unifiedDatas.addRecord(link); + let html = new UDMF.HTML(); + unifiedDatas.addRecord(html); + let file = new UDMF.File(); + unifiedDatas.addRecord(file); + let folder = new UDMF.Folder(); + unifiedDatas.addRecord(folder); + let image = new UDMF.Image(); + unifiedDatas.addRecord(image); + let video = new UDMF.Video(); + unifiedDatas.addRecord(video); + let systemDefinedRecord = new UDMF.SystemDefinedRecord(); + unifiedDatas.addRecord(systemDefinedRecord); + let systemDefinedPixelMap = new UDMF.SystemDefinedPixelMap(); + unifiedDatas.addRecord(systemDefinedPixelMap); + let form = new UDMF.SystemDefinedForm(); + unifiedDatas.addRecord(form); + let appItem = new UDMF.SystemDefinedAppItem(); + unifiedDatas.addRecord(appItem); + let applicationDefinedRecord = new UDMF.ApplicationDefinedRecord(); + unifiedDatas.addRecord(applicationDefinedRecord); + let records = unifiedDatas.getRecords(); + expect(records.length).assertEqual(13); + expect(records[0].getType()).assertEqual(UDMF.UnifiedDataType.TEXT); + expect(records[1].getType()).assertEqual(UDMF.UnifiedDataType.PLAIN_TEXT); + expect(records[2].getType()).assertEqual(UDMF.UnifiedDataType.HYPERLINK); + expect(records[3].getType()).assertEqual(UDMF.UnifiedDataType.HTML); + expect(records[4].getType()).assertEqual(UDMF.UnifiedDataType.FILE); + expect(records[5].getType()).assertEqual(UDMF.UnifiedDataType.FOLDER); + expect(records[6].getType()).assertEqual(UDMF.UnifiedDataType.IMAGE); + expect(records[7].getType()).assertEqual(UDMF.UnifiedDataType.VIDEO); + expect(records[8].getType()).assertEqual(UDMF.UnifiedDataType.SYSTEM_DEFINED_RECORD); + expect(records[9].getType()).assertEqual(UDMF.UnifiedDataType.SYSTEM_DEFINED_PIXEL_MAP); + expect(records[10].getType()).assertEqual(UDMF.UnifiedDataType.SYSTEM_DEFINED_FORM); + expect(records[11].getType()).assertEqual(UDMF.UnifiedDataType.SYSTEM_DEFINED_APP_ITEM); + expect(records[12].getType()).assertEqual(UDMF.UnifiedDataType.APPLICATION_DEFINED_RECORD); + console.info('UdmfAllRecordsTest end'); + }); +}); \ No newline at end of file diff --git a/udmf/framework/jskitsimpl/unittest/UdmfPromiseJsTest.js b/udmf/framework/jskitsimpl/unittest/UdmfPromiseJsTest.js new file mode 100644 index 0000000000000000000000000000000000000000..d53d47e1ea2717e757f441b5000c643beaee1a37 --- /dev/null +++ b/udmf/framework/jskitsimpl/unittest/UdmfPromiseJsTest.js @@ -0,0 +1,411 @@ +/* + * 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. + */ + +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from 'deccjsunit/index'; +import UDMF from '@ohos.data.UDMF'; + +const TEXT_CONTEXT_01 = 'TextContent01'; +const TEXT_CONTEXT_02 = 'TextContent02'; +const ERROR_PARAMETER = '401'; + +describe('UdmfPromiseJSTest', function () { + + let gPlainText1 = new UDMF.PlainText(); + gPlainText1.textContent = TEXT_CONTEXT_01; + let gPlainText2 = new UDMF.PlainText(); + gPlainText2.textContent = TEXT_CONTEXT_02; + + const optionsValid = { intention: 'DataHub', }; + const optionsInValidIntention = { intention: 'Drag', }; + const optionsInValidKey = { key: 'udmf://drag/com.test.demo/123456789', }; + const optionsInValidAll = { intention: 'DataHub', key: 'udmf://drag/com.test.demo/123456789' }; + const unifiedData01 = new UDMF.UnifiedData(gPlainText1); + const unifiedData02 = new UDMF.UnifiedData(gPlainText2); + const unifiedDataInvalid = new UDMF.UnifiedData(); + + /** + * @tc.name UdmfInsertPromiseInvalidOptionsTest + * @tc.desc Test Js Api insertData with invalid options + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('UdmfInsertPromiseInvalidOptionsTest', 0, async function (done) { + const TAG = 'UdmfInsertPromiseInvalidOptionsTest:'; + console.info(TAG, 'start'); + try { + UDMF.insertData(optionsInValidIntention, unifiedData01).then(() => { + console.info(TAG, 'Unreachable code!'); + expect(null).assertFail(); + done(); + }).catch(() => { + console.info(TAG, 'Unreachable code!'); + expect(null).assertFail(); + done(); + }); + } catch (e) { + console.error(TAG, `get e. code is ${e.code},message is ${e.message} `); + expect(e.code === ERROR_PARAMETER).assertTrue(); + done(); + } + console.info(TAG, 'end'); + }); + + /** + * @tc.name UdmfInsertPromiseInvalidDataTest + * @tc.desc Test Js Api insertData with invalid UnifiedData + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('UdmfInsertPromiseInvalidDataTest', 0, async function (done) { + const TAG = 'UdmfInsertPromiseInvalidDataTest:'; + console.info(TAG, 'start'); + try { + UDMF.insertData(optionsValid, unifiedDataInvalid).then(() => { + console.info(TAG, 'Unreachable code!'); + expect(null).assertFail(); + done(); + }).catch((err) => { + console.error(TAG, `get fail. code is ${err.code},message is ${err.message} `); + expect(err.code === ERROR_PARAMETER).assertTrue(); + done(); + }); + } catch (e) { + console.error(TAG, 'Unreachable code!'); + expect(null).assertFail(); + done(); + } + console.info(TAG, 'end'); + }); + + /** + * @tc.name UdmfInsertPromiseSucTest + * @tc.desc Test Js Api insertData successful + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('UdmfInsertPromiseSucTest', 0, async function (done) { + const TAG = 'UdmfInsertPromiseSucTest:'; + console.info(TAG, 'start'); + try { + UDMF.insertData(optionsValid, unifiedData01).then((data) => { + console.info(TAG, `insert success. The key: ${data}`); + let options = { key: data }; + console.info(TAG, `query start. The options: ${JSON.stringify(options)}`); + UDMF.queryData(options).then((data) => { + console.info(TAG, 'query success.'); + console.info(TAG, `data.length = ${data.length}.`); + expect(data.length).assertEqual(1); + let records = data[0].getRecords(); + console.info(TAG, `records.length = ${records.length}.`); + console.info(TAG, `records[0].getType() = ${records[0].getType()}.`); + console.info(TAG, `records[0].textContent = ${records[0].textContent}.`); + expect(records.length).assertEqual(1); + expect(records[0].getType()).assertEqual(UDMF.UnifiedDataType.PLAIN_TEXT); + expect(records[0].textContent).assertEqual(TEXT_CONTEXT_01); + done(); + }).catch(() => { + console.info(TAG, 'Unreachable code!'); + expect(null).assertFail(); + done(); + }); + }).catch(() => { + console.info(TAG, 'Unreachable code!'); + expect(null).assertFail(); + done(); + }); + } catch (e) { + console.error(TAG, 'Unreachable code!'); + expect(null).assertFail(); + done(); + } + console.info(TAG, 'end'); + }); + + /** + * @tc.name UdmfUpdatePromiseInvalidOptionsTest + * @tc.desc Test Js Api updateData with invalid options + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('UdmfUpdatePromiseInvalidOptionsTest', 0, async function (done) { + const TAG = 'UdmfUpdatePromiseInvalidOptionsTest:'; + console.info(TAG, 'start'); + try { + UDMF.updateData(optionsInValidKey, unifiedData01).then(() => { + console.info(TAG, 'Unreachable code!'); + expect(null).assertFail(); + done(); + }).catch(() => { + console.info(TAG, 'Unreachable code!'); + expect(null).assertFail(); + done(); + }); + } catch (e) { + console.error(TAG, `get e. code is ${e.code},message is ${e.message} `); + expect(e.code === ERROR_PARAMETER).assertTrue(); + done(); + } + console.info(TAG, 'end'); + }); + + /** + * @tc.name UdmfUpdatePromiseInvalidDataTest + * @tc.desc Test Js Api updateData with invalid UnifiedData + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('UdmfUpdatePromiseInvalidDataTest', 0, async function (done) { + const TAG = 'UdmfUpdatePromiseInvalidDataTest:'; + console.info(TAG, 'start'); + try { + UDMF.insertData(optionsValid, unifiedData01).then((data) => { + console.info(TAG, `insert success. The key: ${data}`); + let options = { key: data }; + console.info(TAG, `query start. The options: ${JSON.stringify(options)}`); + UDMF.updateData(options, unifiedDataInvalid).then(() => { + console.info(TAG, 'Unreachable code!'); + expect(null).assertFail(); + done(); + }).catch((err) => { + console.error(TAG, `get fail. code is ${err.code},message is ${err.message} `); + expect(err.code === ERROR_PARAMETER).assertTrue(); + done(); + }); + }).catch(() => { + console.info(TAG, 'Unreachable code!'); + expect(null).assertFail(); + done(); + }); + } catch (e) { + console.error(TAG, 'Unreachable code!'); + expect(null).assertFail(); + done(); + } + console.info(TAG, 'end'); + }); + + /** + * @tc.name UdmfUpdatePromiseSucTest + * @tc.desc Test Js Api updateData successful + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('UdmfUpdatePromiseSucTest', 0, async function (done) { + const TAG = 'UdmfUpdatePromiseSucTest:'; + console.info(TAG, 'start'); + try { + UDMF.insertData(optionsValid, unifiedData01).then((data) => { + console.info(TAG, `insert success. The key: ${data}`); + let options = { key: data }; + console.info(TAG, `query start. The options: ${JSON.stringify(options)}`); + UDMF.updateData(options, unifiedData02).then((data) => { + console.info(TAG, 'update success.'); + UDMF.queryData(options).then((data) => { + console.info(TAG, 'query success.'); + expect(data.length).assertEqual(1); + let records = data[0].getRecords(); + expect(records.length).assertEqual(1); + expect(records[0].getType()).assertEqual(UDMF.UnifiedDataType.PLAIN_TEXT); + expect(records[0].textContent).assertEqual(TEXT_CONTEXT_02); + done(); + }).catch(() => { + console.info(TAG, 'Unreachable code!'); + expect(null).assertFail(); + done(); + }); + }).catch(() => { + console.info(TAG, 'Unreachable code!'); + expect(null).assertFail(); + done(); + }); + }).catch(() => { + console.info(TAG, 'Unreachable code!'); + expect(null).assertFail(); + done(); + }); + } catch (e) { + console.error(TAG, 'Unreachable code!'); + expect(null).assertFail(); + done(); + } + console.info(TAG, 'end'); + }); + + + /** + * @tc.name UdmfQueryPromiseInvalidOptionsTest + * @tc.desc Test Js Api queryData with invalid options + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('UdmfQueryPromiseInvalidOptionsTest', 0, async function (done) { + const TAG = 'UdmfQueryPromiseInvalidOptionsTest:'; + console.info(TAG, 'start'); + try { + UDMF.queryData(optionsInValidAll).then(() => { + console.error(TAG, 'Unreachable code!'); + expect(null).assertFail(); + done(); + }).catch(() => { + console.error(TAG, 'Unreachable code!'); + expect(null).assertFail(); + done(); + }); + } catch (e) { + console.error(TAG, `get e. code is ${e.code},message is ${e.message} `); + expect(e.code === ERROR_PARAMETER).assertTrue(); + done(); + } + console.info(TAG, 'end'); + }); + + /** + * @tc.name UdmfQueryPromiseSucTest + * @tc.desc Test Js Api queryData successful + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('UdmfQueryPromiseSucTest', 0, async function (done) { + const TAG = 'UdmfQueryPromiseSucTest:'; + console.info(TAG, 'start'); + try { + UDMF.deleteData(optionsValid).then(() => { + console.info(TAG, 'delete success.'); + UDMF.queryData(optionsValid).then(() => { + console.error(TAG, 'Unreachable code!'); + expect(null).assertFail(); + done(); + }).catch((err) => { + console.info(TAG, 'query has no data.'); + UDMF.insertData(optionsValid, unifiedData01).then((data) => { + console.info(TAG, `insert success. The key: ${data}`); + UDMF.insertData(optionsValid, unifiedData01).then((data) => { + console.info(TAG, `insert success. The key: ${data}`); + UDMF.queryData(optionsValid).then((data) => { + console.info(TAG, 'query success.'); + expect(data.length).assertEqual(2); + done(); + }).catch(() => { + console.error(TAG, 'Unreachable code!'); + expect(null).assertFail(); + done(); + }); + }).catch(() => { + console.error(TAG, 'Unreachable code!'); + expect(null).assertFail(); + done(); + }); + }).catch(() => { + console.error(TAG, 'Unreachable code!'); + expect(null).assertFail(); + done(); + }); + }); + }).catch(() => { + console.error(TAG, 'Unreachable code!'); + expect(null).assertFail(); + done(); + }); + } catch (e) { + console.error(TAG, 'Unreachable code!'); + expect(null).assertFail(); + done(); + } + console.info(TAG, 'end'); + }); + + + /** + * @tc.name UdmfDeletePromiseInvalidOptionsTest + * @tc.desc Test Js Api deleteData with invalid options + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('UdmfDeletePromiseInvalidOptionsTest', 0, async function (done) { + const TAG = 'UdmfDeletePromiseInvalidOptionsTest:'; + console.info(TAG, 'start'); + try { + UDMF.deleteData(optionsInValidAll).then(() => { + console.error(TAG, 'Unreachable code!'); + expect(null).assertFail(); + done(); + }).catch(() => { + console.error(TAG, 'Unreachable code!'); + expect(null).assertFail(); + done(); + }); + } catch (e) { + console.error(TAG, `get e. code is ${e.code},message is ${e.message} `); + expect(e.code === ERROR_PARAMETER).assertTrue(); + done(); + } + console.info(TAG, 'end'); + }); + + /** + * @tc.name UdmfDeletePromiseSucTest + * @tc.desc Test Js Api deleteData successful + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('UdmfDeletePromiseSucTest', 0, async function (done) { + const TAG = 'UdmfDeletePromiseSucTest:'; + console.info(TAG, 'start'); + try { + UDMF.insertData(optionsValid, unifiedData01).then((data) => { + console.info(TAG, `insert success. The key: ${data}`); + let options = { key: data }; + console.info(TAG, `query start. The options: ${JSON.stringify(options)}`); + UDMF.queryData(options).then((data) => { + console.info(TAG, 'query success.'); + expect(data.length).assertEqual(1); + UDMF.deleteData(options).then((data) => { + console.info(TAG, 'delete success.'); + expect(data.length).assertEqual(1); + let records = data[0].getRecords(); + expect(records.length).assertEqual(1); + expect(records[0].getType()).assertEqual(UDMF.UnifiedDataType.PLAIN_TEXT); + expect(records[0].textContent).assertEqual(TEXT_CONTEXT_01); + UDMF.queryData(options).then(() => { + console.error(TAG, 'Unreachable code!'); + expect(null).assertFail(); + done(); + }).catch(() => { + console.info(TAG, 'query has no data.'); + done(); + }); + }).catch(() => { + console.error(TAG, 'Unreachable code!'); + expect(null).assertFail(); + done(); + }); + }).catch(() => { + console.error(TAG, 'Unreachable code!'); + expect(null).assertFail(); + done(); + }); + }).catch(() => { + console.error(TAG, 'Unreachable code!'); + expect(null).assertFail(); + done(); + }); + } catch (e) { + console.error(TAG, 'Unreachable code!'); + expect(null).assertFail(); + done(); + } + console.info(TAG, 'end'); + }); +}); \ No newline at end of file diff --git a/udmf/framework/jskitsimpl/unittest/config.json b/udmf/framework/jskitsimpl/unittest/config.json new file mode 100644 index 0000000000000000000000000000000000000000..8330ee4468aaebac16fe810c4e01c0c3a27fd801 --- /dev/null +++ b/udmf/framework/jskitsimpl/unittest/config.json @@ -0,0 +1,62 @@ +{ + "app": { + "bundleName": "com.example.myapplication", + "vendor": "example", + "version": { + "code": 1, + "name": "1.0" + }, + "apiVersion": { + "compatible": 4, + "target": 5 + } + }, + "deviceConfig": {}, + "module": { + "package": "com.example.myapplication", + "name": ".MyApplication", + "deviceType": [ + "default", + "tablet", + "phone" + ], + "distro": { + "deliveryWithInstall": true, + "moduleName": "entry", + "moduleType": "entry" + }, + "abilities": [ + { + "visible": true, + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "action.system.home" + ] + } + ], + "name": "com.example.myapplication.MainAbility", + "icon": "$media:icon", + "description": "$string:mainability_description", + "label": "MyApplication", + "type": "page", + "launchType": "standard" + } + ], + "js": [ + { + "pages": [ + "pages/index/index" + ], + "name": "default", + "window": { + "designWidth": 720, + "autoDesignWidth": false + } + } + ] + } +} \ No newline at end of file diff --git a/udmf/framework/service/distributeddata_udmf_ipc_interface_code.h b/udmf/framework/service/distributeddata_udmf_ipc_interface_code.h new file mode 100644 index 0000000000000000000000000000000000000000..ed14f6dbeb3b6fa7dca7fbc112f469aa5933a5db --- /dev/null +++ b/udmf/framework/service/distributeddata_udmf_ipc_interface_code.h @@ -0,0 +1,34 @@ +/* + * 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 DISTRIBUTEDDATA_UDMF_IPC_INTERFACE_CODE_H +#define DISTRIBUTEDDATA_UDMF_IPC_INTERFACE_CODE_H + +/* SAID:1301 FeatureSystem:udmf_service */ +namespace OHOS::UDMF { +enum class UdmfServiceInterfaceCode : uint32_t { + CODE_HEAD = 0, + SET_DATA = CODE_HEAD, + GET_DATA, + GET_BATCH_DATA, + UPDATE_DATA, + DELETE_DATA, + GET_SUMMARY, + ADD_PRIVILEGE, + SYNC, + CODE_BUTT +}; +} // namespace OHOS::UDMF +#endif // DISTRIBUTEDDATA_UDMF_IPC_INTERFACE_CODE_H \ No newline at end of file diff --git a/udmf/framework/service/udmf_service.h b/udmf/framework/service/udmf_service.h new file mode 100644 index 0000000000000000000000000000000000000000..1c154657859bb7a6b08614608020ea34326ac692 --- /dev/null +++ b/udmf/framework/service/udmf_service.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef UDMF_SERVICE_H +#define UDMF_SERVICE_H + +#include <string> +#include <vector> + +#include "iremote_broker.h" + +#include "error_code.h" +#include "unified_data.h" +#include "unified_meta.h" +#include "unified_types.h" + +namespace OHOS { +namespace UDMF { +/* + * UDMF service interface + */ +class UdmfService { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.UDMF.UdmfService"); + UdmfService() = default; + virtual ~UdmfService() = default; + + virtual int32_t SetData(CustomOption &option, UnifiedData &unifiedData, std::string &key) = 0; + virtual int32_t GetData(const QueryOption &query, UnifiedData &unifiedData) = 0; + virtual int32_t GetBatchData(const QueryOption &query, std::vector<UnifiedData> &unifiedDataSet) = 0; + virtual int32_t UpdateData(const QueryOption &query, UnifiedData &unifiedData) = 0; + virtual int32_t DeleteData(const QueryOption &query, std::vector<UnifiedData> &unifiedDataSet) = 0; + virtual int32_t GetSummary(const QueryOption &query, Summary &summary) = 0; + virtual int32_t AddPrivilege(const QueryOption &query, Privilege &privilege) = 0; + virtual int32_t Sync(const QueryOption &query, const std::vector<std::string> &devices) = 0; + + static constexpr int32_t MAX_DATA_SIZE = 4 * 1024 * 1024; + static constexpr int32_t MAX_RECORD_SIZE = 2 * 1024 * 1024; +}; +} // namespace UDMF +} // namespace OHOS +#endif // UDMF_SERVICE_H \ No newline at end of file diff --git a/udmf/framework/service/udmf_service_client.cpp b/udmf/framework/service/udmf_service_client.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ecaab7ecdfe5dfbd69b7b8019f0c5bce606c3646 --- /dev/null +++ b/udmf/framework/service/udmf_service_client.cpp @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "udmf_service_client.h" + +#include "iservice_registry.h" +#include "system_ability_definition.h" + +#include "logger.h" + +namespace OHOS { +namespace UDMF { +std::shared_ptr<UdmfServiceClient> UdmfServiceClient::instance_; +std::mutex UdmfServiceClient::mutex_; +sptr<DistributedKv::IKvStoreDataService> UdmfServiceClient::kvDataServiceProxy_; + +UdmfServiceClient::UdmfServiceClient(const sptr<UdmfServiceProxy> &proxy) : udmfProxy_(proxy) +{ + LOG_INFO(UDMF_SERVICE, "construct"); +} + +std::shared_ptr<UdmfServiceClient> UdmfServiceClient::GetInstance() +{ + std::lock_guard<decltype(mutex_)> lockGuard(mutex_); + if (instance_ != nullptr) { + return instance_; + } + sptr<DistributedKv::IKvStoreDataService> ability = GetDistributedKvDataService(); + if (ability == nullptr) { + return nullptr; + } + sptr<IRemoteObject> service = ability->GetFeatureInterface("udmf"); + if (service == nullptr) { + return nullptr; + } + sptr<UdmfServiceProxy> proxy = iface_cast<UdmfServiceProxy>(service); + if (proxy == nullptr) { + return nullptr; + } + instance_ = std::make_shared<UdmfServiceClient>(proxy); + return instance_; +} + +sptr<DistributedKv::IKvStoreDataService> UdmfServiceClient::GetDistributedKvDataService() +{ + if (kvDataServiceProxy_ != nullptr) { + return kvDataServiceProxy_; + } + LOG_INFO(UDMF_SERVICE, "create remote proxy."); + auto samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (samgr == nullptr) { + LOG_ERROR(UDMF_SERVICE, "get samgr fail."); + return nullptr; + } + + auto remote = samgr->CheckSystemAbility(DISTRIBUTED_KV_DATA_SERVICE_ABILITY_ID); + kvDataServiceProxy_ = iface_cast<DistributedKv::IKvStoreDataService>(remote); + if (kvDataServiceProxy_ == nullptr) { + LOG_ERROR(UDMF_SERVICE, "initialize proxy failed."); + return nullptr; + } + return kvDataServiceProxy_; +} + +int32_t UdmfServiceClient::SetData(CustomOption &option, UnifiedData &unifiedData, std::string &key) +{ + LOG_INFO(UDMF_SERVICE, "start"); + return udmfProxy_->SetData(option, unifiedData, key); +} + +int32_t UdmfServiceClient::GetData(const QueryOption &query, UnifiedData &unifiedData) +{ + LOG_INFO(UDMF_SERVICE, "start"); + return udmfProxy_->GetData(query, unifiedData); +} + +int32_t UdmfServiceClient::GetBatchData(const QueryOption &query, std::vector<UnifiedData> &unifiedDataSet) +{ + LOG_INFO(UDMF_SERVICE, "start"); + return udmfProxy_->GetBatchData(query, unifiedDataSet); +} + +int32_t UdmfServiceClient::UpdateData(const QueryOption &query, UnifiedData &unifiedData) +{ + LOG_INFO(UDMF_SERVICE, "start"); + return udmfProxy_->UpdateData(query, unifiedData); +} + +int32_t UdmfServiceClient::DeleteData(const QueryOption &query, std::vector<UnifiedData> &unifiedDataSet) +{ + LOG_INFO(UDMF_SERVICE, "start"); + return udmfProxy_->DeleteData(query, unifiedDataSet); +} + +int32_t UdmfServiceClient::GetSummary(const QueryOption &query, Summary &summary) +{ + LOG_INFO(UDMF_SERVICE, "start"); + return udmfProxy_->GetSummary(query, summary); +} + +int32_t UdmfServiceClient::AddPrivilege(const QueryOption &query, Privilege &privilege) +{ + LOG_INFO(UDMF_SERVICE, "start"); + return udmfProxy_->AddPrivilege(query, privilege); +} + +int32_t UdmfServiceClient::Sync(const QueryOption &query, const std::vector<std::string> &devices) +{ + LOG_INFO(UDMF_SERVICE, "start"); + return udmfProxy_->Sync(query, devices); +} +} // namespace UDMF +} // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/service/udmf_service_client.h b/udmf/framework/service/udmf_service_client.h new file mode 100644 index 0000000000000000000000000000000000000000..c61740bb5456c2fcb93dfe8a0d40076e298e315d --- /dev/null +++ b/udmf/framework/service/udmf_service_client.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef UDMF_SERVICE_CLIENT_H +#define UDMF_SERVICE_CLIENT_H + +#include <mutex> +#include <string> + +#include "ikvstore_data_service.h" +#include "iremote_broker.h" + +#include "udmf_service.h" +#include "udmf_service_proxy.h" + +namespace OHOS { +namespace UDMF { +class UdmfServiceClient final : public UdmfService { +public: + explicit UdmfServiceClient(const sptr<UdmfServiceProxy> &proxy); + ~UdmfServiceClient() override = default; + static std::shared_ptr<UdmfServiceClient> GetInstance(); + + int32_t SetData(CustomOption &option, UnifiedData &unifiedData, std::string &key) override; + int32_t GetData(const QueryOption &query, UnifiedData &unifiedData) override; + int32_t GetBatchData(const QueryOption &query, std::vector<UnifiedData> &unifiedDataSet) override; + int32_t UpdateData(const QueryOption &query, UnifiedData &unifiedData) override; + int32_t DeleteData(const QueryOption &query, std::vector<UnifiedData> &unifiedDataSet) override; + int32_t GetSummary(const QueryOption &query, Summary &summary) override; + int32_t AddPrivilege(const QueryOption &query, Privilege &privilege) override; + int32_t Sync(const QueryOption &query, const std::vector<std::string> &devices) override; + +private: + static std::shared_ptr<UdmfServiceClient> instance_; + static std::mutex mutex_; + static sptr<DistributedKv::IKvStoreDataService> kvDataServiceProxy_; + static sptr<DistributedKv::IKvStoreDataService> GetDistributedKvDataService(); + sptr<UdmfServiceProxy> udmfProxy_; +}; +} // namespace UDMF +} // namespace OHOS +#endif // UDMF_SERVICE_CLIENT_H \ No newline at end of file diff --git a/udmf/framework/service/udmf_service_proxy.cpp b/udmf/framework/service/udmf_service_proxy.cpp new file mode 100644 index 0000000000000000000000000000000000000000..448c5f3c83f945d9a2819c375704a2512e3ec3f7 --- /dev/null +++ b/udmf/framework/service/udmf_service_proxy.cpp @@ -0,0 +1,265 @@ +/* + * 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 "udmf_service_proxy.h" + +#include "ipc_types.h" + +#include "logger.h" +#include "tlv_util.h" +#include "udmf_types_util.h" + +namespace OHOS { +namespace UDMF { +#define IPC_SEND(code, reply, ...) \ + ({ \ + int32_t __status = E_OK; \ + do { \ + MessageParcel request; \ + if (!request.WriteInterfaceToken(GetDescriptor())) { \ + __status = E_WRITE_PARCEL_ERROR; \ + break; \ + } \ + if (!ITypesUtil::Marshal(request, ##__VA_ARGS__)) { \ + __status = E_WRITE_PARCEL_ERROR; \ + break; \ + } \ + MessageOption option; \ + auto result = SendRequest(code, request, reply, option); \ + if (result != 0) { \ + LOG_ERROR(UDMF_SERVICE, "SendRequest failed, result = %{public}d!", result); \ + __status = E_IPC; \ + break; \ + } \ + \ + ITypesUtil::Unmarshal(reply, __status); \ + } while (0); \ + __status; \ + }) + +UdmfServiceProxy::UdmfServiceProxy(const sptr<IRemoteObject> &object) : IRemoteProxy<IUdmfService>(object) +{ +} + +int32_t UdmfServiceProxy::SetData(CustomOption &option, UnifiedData &unifiedData, std::string &key) +{ + LOG_DEBUG(UDMF_SERVICE, "start, tag: %{public}d", option.intention); + if (!UnifiedDataUtils::IsValidIntention(option.intention)) { + LOG_ERROR(UDMF_SERVICE, "Invalid intention"); + return E_INVALID_PARAMETERS; + } + if (unifiedData.IsEmpty()) { + LOG_ERROR(UDMF_SERVICE, "Empty data without any record!"); + return E_INVALID_PARAMETERS; + } + if (unifiedData.GetSize() > UdmfService::MAX_DATA_SIZE) { + LOG_ERROR(UDMF_SERVICE, "Exceeded the limit!"); + return E_INVALID_PARAMETERS; + } + for (const auto &record : unifiedData.GetRecords()) { + if (record == nullptr) { + LOG_ERROR(UDMF_SERVICE, "record is nullptr!"); + return E_INVALID_PARAMETERS; + } + if (record->GetSize() > UdmfService::MAX_RECORD_SIZE) { + LOG_ERROR(UDMF_SERVICE, "Exceeded record limit!"); + return E_INVALID_PARAMETERS; + } + } + MessageParcel reply; + int32_t status = IPC_SEND(UdmfServiceInterfaceCode::SET_DATA, reply, option, unifiedData); + if (status != E_OK) { + LOG_ERROR(UDMF_SERVICE, "status:0x%{public}x!", status); + return status; + } + if (!ITypesUtil::Unmarshal(reply, key)) { + LOG_ERROR(UDMF_SERVICE, "Unmarshal status failed!"); + return E_READ_PARCEL_ERROR; + } + return status; +} + +int32_t UdmfServiceProxy::GetData(const QueryOption &query, UnifiedData &unifiedData) +{ + LOG_DEBUG(UDMF_SERVICE, "start, tag: %{public}s", query.key.c_str()); + UnifiedKey key(query.key); + if (!key.IsValid()) { + LOG_ERROR(UDMF_SERVICE, "invalid key"); + return E_INVALID_PARAMETERS; + } + MessageParcel reply; + int32_t status = IPC_SEND(UdmfServiceInterfaceCode::GET_DATA, reply, query); + if (status != E_OK) { + LOG_ERROR(UDMF_SERVICE, "status:0x%{public}x, key:%{public}s!", status, query.key.c_str()); + return status; + } + if (!ITypesUtil::Unmarshal(reply, unifiedData)) { + LOG_ERROR(UDMF_SERVICE, "Unmarshal UnifiedData failed!"); + return E_READ_PARCEL_ERROR; + } + return status; +} + +int32_t UdmfServiceProxy::GetBatchData(const QueryOption &query, std::vector<UnifiedData> &unifiedDataSet) +{ + LOG_DEBUG(UDMF_SERVICE, "start, tag: intention = %{public}d, key = %{public}s", query.intention, query.key.c_str()); + auto find = UD_INTENTION_MAP.find(query.intention); + std::string intention = find == UD_INTENTION_MAP.end() ? intention : find->second; + if (!UnifiedDataUtils::IsValidOptions(query.key, intention)) { + LOG_ERROR(UDMF_SERVICE, "invalid option"); + return E_INVALID_PARAMETERS; + } + MessageParcel reply; + int32_t status = IPC_SEND(UdmfServiceInterfaceCode::GET_BATCH_DATA, reply, query); + if (status != E_OK) { + LOG_ERROR(UDMF_SERVICE, "status:0x%{public}x, key:%{public}s, intention:%{public}d!", status, + query.key.c_str(), query.intention); + return status; + } + if (!ITypesUtil::Unmarshal(reply, unifiedDataSet)) { + LOG_ERROR(UDMF_SERVICE, "Unmarshal unifiedDataSet failed!"); + return E_READ_PARCEL_ERROR; + } + return status; +} + +int32_t UdmfServiceProxy::UpdateData(const QueryOption &query, UnifiedData &unifiedData) +{ + LOG_DEBUG(UDMF_SERVICE, "start, tag: %{public}s", query.key.c_str()); + UnifiedKey key(query.key); + if (!key.IsValid() || !UnifiedDataUtils::IsPersist(key.intention)) { + LOG_ERROR(UDMF_SERVICE, "invalid key"); + return E_INVALID_PARAMETERS; + } + if (unifiedData.GetSize() > UdmfService::MAX_DATA_SIZE) { + LOG_ERROR(UDMF_SERVICE, "Exceeded the limit!"); + return E_INVALID_PARAMETERS; + } + if (unifiedData.IsEmpty()) { + LOG_ERROR(UDMF_SERVICE, "Empty data without any record!"); + return E_INVALID_PARAMETERS; + } + for (const auto &record : unifiedData.GetRecords()) { + if (record == nullptr) { + LOG_ERROR(UDMF_SERVICE, "record is nullptr!"); + return E_INVALID_PARAMETERS; + } + if (record->GetSize() > UdmfService::MAX_RECORD_SIZE) { + LOG_ERROR(UDMF_SERVICE, "Exceeded record limit!"); + return E_INVALID_PARAMETERS; + } + } + MessageParcel reply; + int32_t status = IPC_SEND(UdmfServiceInterfaceCode::UPDATE_DATA, reply, query, unifiedData); + if (status != E_OK) { + LOG_ERROR(UDMF_SERVICE, "status:0x%{public}x!", status); + return status; + } + return status; +} + +int32_t UdmfServiceProxy::DeleteData(const QueryOption &query, std::vector<UnifiedData> &unifiedDataSet) +{ + LOG_DEBUG(UDMF_SERVICE, "start, tag: intention = %{public}d, key = %{public}s", query.intention, query.key.c_str()); + auto find = UD_INTENTION_MAP.find(query.intention); + std::string intention = find == UD_INTENTION_MAP.end() ? intention : find->second; + if (!UnifiedDataUtils::IsValidOptions(query.key, intention)) { + LOG_ERROR(UDMF_SERVICE, "invalid option"); + return E_INVALID_PARAMETERS; + } + MessageParcel reply; + int32_t status = IPC_SEND(UdmfServiceInterfaceCode::DELETE_DATA, reply, query); + if (status != E_OK) { + LOG_ERROR(UDMF_SERVICE, "status:0x%{public}x,key: %{public}s, intention:%{public}s", status, query.key.c_str(), + UD_INTENTION_MAP.at(query.intention).c_str()); + return status; + } + if (!ITypesUtil::Unmarshal(reply, unifiedDataSet)) { + LOG_ERROR(UDMF_SERVICE, "Unmarshal unifiedDataSet failed!"); + return E_READ_PARCEL_ERROR; + } + LOG_DEBUG(UDMF_SERVICE, "end."); + return status; +} + +int32_t UdmfServiceProxy::GetSummary(const QueryOption &query, Summary &summary) +{ + LOG_DEBUG(UDMF_SERVICE, "start, tag: %{public}s", query.key.c_str()); + UnifiedKey key(query.key); + if (!key.IsValid()) { + LOG_ERROR(UDMF_SERVICE, "invalid key"); + return E_INVALID_PARAMETERS; + } + MessageParcel reply; + int32_t status = IPC_SEND(UdmfServiceInterfaceCode::GET_SUMMARY, reply, query); + if (status != E_OK) { + LOG_ERROR(UDMF_SERVICE, "status:0x%{public}x, key:%{public}s!", status, query.key.c_str()); + return status; + } + if (!ITypesUtil::Unmarshal(reply, summary)) { + LOG_ERROR(UDMF_SERVICE, "Unmarshal summary failed!"); + return E_READ_PARCEL_ERROR; + } + LOG_DEBUG(UDMF_SERVICE, "end."); + return status; +} + +int32_t UdmfServiceProxy::AddPrivilege(const QueryOption &query, Privilege &privilege) +{ + LOG_DEBUG(UDMF_SERVICE, "start, key: %{public}s", query.key.c_str()); + UnifiedKey key(query.key); + if (!key.IsValid()) { + LOG_ERROR(UDMF_SERVICE, "invalid key"); + return E_INVALID_PARAMETERS; + } + MessageParcel reply; + int32_t status = IPC_SEND(UdmfServiceInterfaceCode::ADD_PRIVILEGE, reply, query, privilege); + if (status != E_OK) { + LOG_ERROR(UDMF_SERVICE, "status:0x%{public}x, key:%{public}s", status, query.key.c_str()); + } + LOG_DEBUG(UDMF_SERVICE, "end."); + return status; +} + +int32_t UdmfServiceProxy::Sync(const QueryOption &query, const std::vector<std::string> &devices) +{ + LOG_DEBUG(UDMF_SERVICE, "start, key: %{public}s", query.key.c_str()); + UnifiedKey key(query.key); + if (!key.IsValid()) { + LOG_ERROR(UDMF_SERVICE, "invalid key"); + return E_INVALID_PARAMETERS; + } + MessageParcel reply; + int32_t status = IPC_SEND(UdmfServiceInterfaceCode::SYNC, reply, query, devices); + if (status != E_OK) { + LOG_ERROR(UDMF_SERVICE, "status:0x%{public}x, key:%{public}s", status, query.key.c_str()); + } + LOG_DEBUG(UDMF_SERVICE, "end."); + return status; +} + +int32_t UdmfServiceProxy::SendRequest(UdmfServiceInterfaceCode code, MessageParcel &data, + MessageParcel &reply, MessageOption &option) +{ + sptr<IRemoteObject> remote = Remote(); + if (remote == nullptr) { + return E_IPC; + } + int err = remote->SendRequest(static_cast<uint32_t>(code), data, reply, option); + LOG_DEBUG(UDMF_SERVICE, "err: %{public}d", err); + return err; +} +} // namespace UDMF +} // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/service/udmf_service_proxy.h b/udmf/framework/service/udmf_service_proxy.h new file mode 100644 index 0000000000000000000000000000000000000000..b1baf72136cd62a2e57bcb46bffb4a0c0d66f1ea --- /dev/null +++ b/udmf/framework/service/udmf_service_proxy.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef UDMF_SERVICE_PROXY_H +#define UDMF_SERVICE_PROXY_H + +#include <string> + +#include "iremote_broker.h" +#include "iremote_proxy.h" + +#include "distributeddata_udmf_ipc_interface_code.h" +#include "udmf_service.h" + +namespace OHOS { +namespace UDMF { +class IUdmfService : public UdmfService, public IRemoteBroker { +public: + using UdmfService::UdmfService; +}; + +class UdmfServiceProxy : public IRemoteProxy<IUdmfService> { +public: + explicit UdmfServiceProxy(const sptr<IRemoteObject> &object); + + int32_t SetData(CustomOption &option, UnifiedData &unifiedData, std::string &key) override; + int32_t GetData(const QueryOption &query, UnifiedData &unifiedData) override; + int32_t GetBatchData(const QueryOption &query, std::vector<UnifiedData> &unifiedDataSet) override; + int32_t UpdateData(const QueryOption &query, UnifiedData &unifiedData) override; + int32_t DeleteData(const QueryOption &query, std::vector<UnifiedData> &unifiedDataSet) override; + int32_t GetSummary(const QueryOption &query, Summary &summary) override; + int32_t AddPrivilege(const QueryOption &query, Privilege &privilege) override; + int32_t Sync(const QueryOption &query, const std::vector<std::string> &devices) override; + +private: + static inline BrokerDelegator<UdmfServiceProxy> delegator_; + int32_t SendRequest(UdmfServiceInterfaceCode code, MessageParcel &data, + MessageParcel &reply, MessageOption &option); +}; +} // namespace UDMF +} // namespace OHOS +#endif // UDMF_SERVICE_PROXY_H \ No newline at end of file diff --git a/udmf/interfaces/innerkits/BUILD.gn b/udmf/interfaces/innerkits/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..09e2d256f803bd1862ab033b98ee7a7b9fdde7f0 --- /dev/null +++ b/udmf/interfaces/innerkits/BUILD.gn @@ -0,0 +1,78 @@ +# Copyright (c) 2022 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import("//build/ohos.gni") +import("//foundation/distributeddatamgr/udmf/udmf.gni") + +config("udmf_client_config") { + include_dirs = [ + "${udmf_interfaces_path}/innerkits/client", + "${udmf_interfaces_path}/innerkits/common", + "${udmf_interfaces_path}/innerkits/data", + + "${udmf_framework_path}/common", + "${udmf_framework_path}/service", + "${kv_store_path}/frameworks/common", + "//third_party/libuv/include", + "//third_party/node/src", + "${kv_store_path}/frameworks/innerkitsimpl/distributeddatafwk/include", + "${kv_store_path}/frameworks/innerkitsimpl/distributeddatafwk/src", + "${kv_store_path}/interfaces/innerkits/distributeddata/include", + ] +} + +ohos_shared_library("udmf_client") { + sources = [ + "${udmf_framework_path}/common/tlv_util.cpp", + "${udmf_framework_path}/common/udmf_types_util.cpp", + "${udmf_framework_path}/innerkitsimpl/client/udmf_client.cpp", + "${udmf_framework_path}/innerkitsimpl/common/unified_key.cpp", + "${udmf_framework_path}/innerkitsimpl/common/unified_meta.cpp", + "${udmf_framework_path}/innerkitsimpl/data/application_defined_record.cpp", + "${udmf_framework_path}/innerkitsimpl/data/audio.cpp", + "${udmf_framework_path}/innerkitsimpl/data/file.cpp", + "${udmf_framework_path}/innerkitsimpl/data/folder.cpp", + "${udmf_framework_path}/innerkitsimpl/data/html.cpp", + "${udmf_framework_path}/innerkitsimpl/data/image.cpp", + "${udmf_framework_path}/innerkitsimpl/data/link.cpp", + "${udmf_framework_path}/innerkitsimpl/data/plain_text.cpp", + "${udmf_framework_path}/innerkitsimpl/data/system_defined_appitem.cpp", + "${udmf_framework_path}/innerkitsimpl/data/system_defined_form.cpp", + "${udmf_framework_path}/innerkitsimpl/data/system_defined_pixelmap.cpp", + "${udmf_framework_path}/innerkitsimpl/data/system_defined_record.cpp", + "${udmf_framework_path}/innerkitsimpl/data/text.cpp", + "${udmf_framework_path}/innerkitsimpl/data/unified_data.cpp", + "${udmf_framework_path}/innerkitsimpl/data/unified_record.cpp", + "${udmf_framework_path}/innerkitsimpl/data/video.cpp", + "${udmf_framework_path}/service/udmf_service_client.cpp", + "${udmf_framework_path}/service/udmf_service_proxy.cpp", + ] + + public_configs = [ ":udmf_client_config" ] + + external_deps = [ + "access_token:libaccesstoken_sdk", + "bundle_framework:appexecfwk_core", + "c_utils:utils", + "hilog:libhilog", + "hitrace:hitrace_meter", + "hitrace:libhitracechain", + "ipc:ipc_core", + "kv_store:distributeddata_inner", + "samgr:samgr_proxy", + ] + + innerapi_tags = [ "platformsdk" ] + subsystem_name = "distributeddatamgr" + + part_name = "udmf" +} diff --git a/udmf/interfaces/innerkits/client/udmf_client.h b/udmf/interfaces/innerkits/client/udmf_client.h new file mode 100644 index 0000000000000000000000000000000000000000..a6eb010ecc72a6425d22e9ffa64eca54c8da9f54 --- /dev/null +++ b/udmf/interfaces/innerkits/client/udmf_client.h @@ -0,0 +1,44 @@ +/* + * 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 UDMF_CLIENT_H +#define UDMF_CLIENT_H + +#include <string> +#include <vector> + +#include "unified_data.h" +#include "error_code.h" +#include "unified_meta.h" +#include "unified_types.h" + +namespace OHOS { +namespace UDMF { +class UdmfClient { +public: + static UdmfClient &GetInstance(); + + Status SetData(CustomOption &option, UnifiedData &unifiedData, std::string &key); + Status GetData(const QueryOption &query, UnifiedData &unifiedData); + Status GetBatchData(const QueryOption &query, std::vector<UnifiedData> &unifiedDataSet); + Status UpdateData(const QueryOption &query, UnifiedData &unifiedData); + Status DeleteData(const QueryOption &query, std::vector<UnifiedData> &unifiedDataSet); + Status GetSummary(const QueryOption &query, Summary& summary); + Status AddPrivilege(const QueryOption &query, Privilege &privilege); + Status Sync(const QueryOption &query, const std::vector<std::string> &devices); +}; +} // namespace UDMF +} // namespace OHOS +#endif // UDMF_CLIENT_H \ No newline at end of file diff --git a/udmf/interfaces/innerkits/common/error_code.h b/udmf/interfaces/innerkits/common/error_code.h new file mode 100644 index 0000000000000000000000000000000000000000..f50a2518f0c0b3ccffe5f3dcd9a10ca4fc0e4024 --- /dev/null +++ b/udmf/interfaces/innerkits/common/error_code.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 UDMF_ERROR_CODE_H +#define UDMF_ERROR_CODE_H + +#include <cstdint> + +#include <errors.h> + +namespace OHOS { +namespace UDMF { +enum UdmfModule { + UDMF_MODULE_SERVICE_ID = 0x07, +}; + +// UDMF error offset, used only in this file. +constexpr ErrCode UDMF_ERR_OFFSET = ErrCodeOffset(SUBSYS_DISTRIBUTEDDATAMNG, UDMF_MODULE_SERVICE_ID); + +enum Status : int32_t { + E_OK = ERR_OK, + E_WRITE_PARCEL_ERROR = UDMF_ERR_OFFSET, + E_READ_PARCEL_ERROR, + E_IPC, + E_ERROR, + E_NO_PERMISSION, + E_INVALID_PARAMETERS, + E_DB_ERROR, + E_UNKNOWN, + E_BUTT, +}; +} // namespace UDMF +} // namespace OHOS +#endif // UDMF_ERROR_CODE_H \ No newline at end of file diff --git a/udmf/interfaces/innerkits/common/unified_key.h b/udmf/interfaces/innerkits/common/unified_key.h new file mode 100644 index 0000000000000000000000000000000000000000..c39ed841228e7298cbf7263b63918dd79291e39a --- /dev/null +++ b/udmf/interfaces/innerkits/common/unified_key.h @@ -0,0 +1,40 @@ +/* + * 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 UDMF_UNIFIED_KEY_H +#define UDMF_UNIFIED_KEY_H + +#include <bitset> +#include <string> + +namespace OHOS { +namespace UDMF { +constexpr int MAX_BIT_SIZE = 128; +struct UnifiedKey { + UnifiedKey() = default; + explicit UnifiedKey(std::string key); + UnifiedKey(std::string intention, std::string bundle, std::string groupId); + std::string key; + std::string intention; + std::string bundleName; + std::string groupId; + std::string GetUnifiedKey(); + bool IsValid(); + void PreliminaryWork(); + bool CheckCharacter(std::string data, std::bitset<MAX_BIT_SIZE> rule); +}; +} // namespace UDMF +} // namespace OHOS +#endif // UDMF_UNIFIED_KEY_H \ No newline at end of file diff --git a/udmf/interfaces/innerkits/common/unified_meta.h b/udmf/interfaces/innerkits/common/unified_meta.h new file mode 100644 index 0000000000000000000000000000000000000000..8ea052f5f6e38b6ff476cd7e8601ea87bb77d984 --- /dev/null +++ b/udmf/interfaces/innerkits/common/unified_meta.h @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2023-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 UNIFIED_META_H +#define UNIFIED_META_H + +#include <array> +#include <cstdint> +#include <map> +#include <memory> +#include <string> +#include <unordered_map> +#include <variant> +#include <vector> + +#include "string_ex.h" + +namespace OHOS { +namespace UDMF { +enum UDType : int32_t { + TEXT = 0, + PLAIN_TEXT, + STYLED_TEXT, + HYPERLINK, + HTML, + FILE, + FOLDER, + MEDIA, + IMAGE, + VIDEO, + AUDIO, + OFFICE, + EBOOK, + COMPRESSION, + GENERAL, + SYSTEM_DEFINED_FORM, + SYSTEM_DEFINED_RECORD, + SYSTEM_DEFINED_APP_ITEM, + SYSTEM_DEFINED_PIXEL_MAP, + APPLICATION_DEFINED_RECORD, + UD_BUTT +}; + +static const std::unordered_map<int32_t, std::string> UD_TYPE_MAP { + { TEXT, "Text" }, + { PLAIN_TEXT, "Text.PlainText" }, + { STYLED_TEXT, "Text.StyledText" }, + { HYPERLINK, "Text.Hyperlink" }, + { HTML, "Text.HTML" }, + { FILE, "File" }, + { FOLDER, "File.Folder" }, + { MEDIA, "File.Media" }, + { OFFICE, "File.Office" }, + { EBOOK, "File.Ebook" }, + { COMPRESSION, "File.Compression" }, + { GENERAL, "File.General" }, + { IMAGE, "File.Media.Image" }, + { VIDEO, "File.Media.Video" }, + { AUDIO, "File.Media.Audio" }, + { SYSTEM_DEFINED_RECORD, "SystemDefinedType" }, + { SYSTEM_DEFINED_FORM, "SystemDefinedType.Form" }, + { SYSTEM_DEFINED_APP_ITEM, "SystemDefinedType.AppItem" }, + { SYSTEM_DEFINED_PIXEL_MAP, "SystemDefinedType.PixelMap" }, + { APPLICATION_DEFINED_RECORD, "ApplicationDefinedType" }, + { UD_BUTT, "INVALID" } +}; + +static const std::unordered_map<int32_t, std::string> JS_UD_TYPE_NAME_MAP { + { TEXT, "TEXT" }, + { PLAIN_TEXT, "PLAIN_TEXT" }, + { HYPERLINK, "HYPERLINK" }, + { HTML, "HTML" }, + { FILE, "FILE" }, + { IMAGE, "IMAGE" }, + { VIDEO, "VIDEO" }, + { AUDIO, "AUDIO" }, + { FOLDER, "FOLDER" }, + { SYSTEM_DEFINED_RECORD, "SYSTEM_DEFINED_RECORD" }, + { SYSTEM_DEFINED_FORM, "SYSTEM_DEFINED_FORM" }, + { SYSTEM_DEFINED_APP_ITEM, "SYSTEM_DEFINED_APP_ITEM" }, + { SYSTEM_DEFINED_PIXEL_MAP, "SYSTEM_DEFINED_PIXEL_MAP" }, + { APPLICATION_DEFINED_RECORD, "APPLICATION_DEFINED_RECORD" }, +}; + +/* + * UnifiedData variant definitions. + */ +using UDVariant = std::variant<int32_t, int64_t, bool, double, std::string, std::vector<uint8_t>>; +using UDDetails = std::map<std::string, UDVariant>; + +/* + * UnifiedData Intention. + */ +enum Intention : int32_t { + UD_INTENTION_BASE = 0, + UD_INTENTION_DRAG, + UD_INTENTION_DATA_HUB, + UD_INTENTION_BUTT, +}; + +static const std::unordered_map<int32_t, std::string> UD_INTENTION_MAP { + { UD_INTENTION_DRAG, "drag" }, + { UD_INTENTION_DATA_HUB, "DataHub" }, +}; + +static const std::unordered_map<int32_t, std::string> JS_UD_INTENTION_NAME_MAP { + { UD_INTENTION_DATA_HUB, "DATA_HUB" }, +}; + +class UnifiedDataUtils { +public: + static bool IsValidType(int32_t value); + static bool IsValidIntention(int32_t value); + static size_t GetVariantSize(UDVariant &variant); + static size_t GetDetailsSize(UDDetails &details); + static bool IsPersist(const Intention &intention); + static bool IsPersist(const std::string &intention); + static Intention GetIntentionByString(const std::string &intention); + static bool IsValidOptions(const std::string &key, std::string &intention); +}; +} // namespace UDMF +} // namespace OHOS +#endif // UNIFIED_META_H \ No newline at end of file diff --git a/udmf/interfaces/innerkits/common/unified_types.h b/udmf/interfaces/innerkits/common/unified_types.h new file mode 100644 index 0000000000000000000000000000000000000000..10d6faf77fbfb49fed3fa2b8b34f5c02cdde89ad --- /dev/null +++ b/udmf/interfaces/innerkits/common/unified_types.h @@ -0,0 +1,83 @@ +/* + * 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 UDMF_UNIFIED_TYPES_H +#define UDMF_UNIFIED_TYPES_H + +#include <map> +#include <string> + +#include "unified_key.h" +#include "unified_meta.h" + +namespace OHOS { +namespace UDMF { +enum DataStatus : int32_t { + WORKING = 0, + HISTORY, + DELETED, + FADE +}; + +struct Summary { + std::map<std::string, int64_t> summary; + int64_t totalSize; +}; + +struct Privilege { + uint32_t tokenId; + std::string readPermission; + std::string writePermission; +}; + +struct Runtime { + UnifiedKey key; + bool isPrivate {}; + std::vector<Privilege> privileges; + // time when the data is created + time_t createTime {}; + // name of the package for creating data + std::string sourcePackage; + // current data status + DataStatus dataStatus { WORKING }; + // current data version + std::int32_t dataVersion {}; + // time when the data is last modified + time_t lastModifiedTime {}; + // time when data is written to the udmf + std::string createPackage; + // device ID of the data source + std::string deviceId; +}; + +/* + * Options for sharing data through UDMF. + */ +struct CustomOption { + Intention intention {}; + uint32_t tokenId {}; +}; + +/* + * Options for querying data from UDMF. + */ +struct QueryOption { + std::string key; + Intention intention {}; + uint32_t tokenId {}; +}; +} // namespace UDMF +} // namespace OHOS +#endif // UDMF_UNIFIED_TYPES_H \ No newline at end of file diff --git a/udmf/interfaces/innerkits/common/visibility.h b/udmf/interfaces/innerkits/common/visibility.h new file mode 100644 index 0000000000000000000000000000000000000000..bce9d1264d1405daf89f261d1aac326baa639fd8 --- /dev/null +++ b/udmf/interfaces/innerkits/common/visibility.h @@ -0,0 +1,23 @@ +/* + * 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 UDMF_VISIBILITY_H +#define UDMF_VISIBILITY_H + +#ifndef API_EXPORT +#define API_EXPORT __attribute__((visibility ("default"))) +#endif + +#endif // UDMF_VISIBILITY_H diff --git a/udmf/interfaces/innerkits/data/application_defined_record.h b/udmf/interfaces/innerkits/data/application_defined_record.h new file mode 100644 index 0000000000000000000000000000000000000000..47bf2000d83505b5e9e8540078591153121fb80a --- /dev/null +++ b/udmf/interfaces/innerkits/data/application_defined_record.h @@ -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. + */ + +#ifndef UDMF_APPLICATION_DEFINED_RECORD_H +#define UDMF_APPLICATION_DEFINED_RECORD_H + +#include "unified_record.h" + +namespace OHOS { +namespace UDMF { +class ApplicationDefinedRecord : public UnifiedRecord { +public: + ApplicationDefinedRecord(); + explicit ApplicationDefinedRecord(std::string type); + explicit ApplicationDefinedRecord(std::string type, std::vector<uint8_t> &data); + + int64_t GetSize() override; + + std::string GetApplicationDefinedType() const; + void SetApplicationDefinedType(const std::string &type); + + std::vector<uint8_t> GetRawData() const; + void SetRawData(const std::vector<uint8_t> &rawData); +protected: + std::string applicationDefinedType; + std::vector<uint8_t> rawData_; +}; +} // namespace UDMF +} // namespace OHOS + +#endif // UDMF_APPLICATION_DEFINED_RECORD_H diff --git a/udmf/interfaces/innerkits/data/audio.h b/udmf/interfaces/innerkits/data/audio.h new file mode 100644 index 0000000000000000000000000000000000000000..00adcde01b62e5b1ead65f1f2f4268d1f503f2a5 --- /dev/null +++ b/udmf/interfaces/innerkits/data/audio.h @@ -0,0 +1,31 @@ +/* + * 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 UDMF_AUDIO_H +#define UDMF_AUDIO_H + +#include "file.h" + +namespace OHOS { +namespace UDMF { +class Audio : public File { +public: + Audio(); + explicit Audio(const std::string &uri); +}; +} // namespace UDMF +} // namespace OHOS + +#endif // UDMF_AUDIO_H diff --git a/udmf/interfaces/innerkits/data/file.h b/udmf/interfaces/innerkits/data/file.h new file mode 100644 index 0000000000000000000000000000000000000000..aecd0aa6a26266fa03ea7efa15051d211b415972 --- /dev/null +++ b/udmf/interfaces/innerkits/data/file.h @@ -0,0 +1,45 @@ +/* + * 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 UDMF_FILE_H +#define UDMF_FILE_H + +#include "unified_record.h" + +namespace OHOS { +namespace UDMF { +class File : public UnifiedRecord { +public: + File(); + explicit File(const std::string &uri); + int64_t GetSize() override; + + std::string GetUri() const; + void SetUri(const std::string &uri); + + std::string GetRemoteUri() const; + void SetRemoteUri(const std::string &uri); + + void SetDetails(UDDetails &variantMap); + UDDetails GetDetails() const; + +protected: + std::string oriUri_; + std::string remoteUri_; + UDDetails details_; +}; +} // namespace UDMF +} // namespace OHOS +#endif // UDMF_FILE_H diff --git a/udmf/interfaces/innerkits/data/folder.h b/udmf/interfaces/innerkits/data/folder.h new file mode 100644 index 0000000000000000000000000000000000000000..4d9c5dde303b2d179c23f1aaa842495a5be1a9a9 --- /dev/null +++ b/udmf/interfaces/innerkits/data/folder.h @@ -0,0 +1,30 @@ +/* + * 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 UDMF_FOLDER_H +#define UDMF_FOLDER_H + +#include "file.h" + +namespace OHOS { +namespace UDMF { +class Folder : public File { +public: + Folder(); + explicit Folder(const std::string &uri); +}; +} // namespace UDMF +} // namespace OHOS +#endif // UDMF_FOLDER_H diff --git a/udmf/interfaces/innerkits/data/html.h b/udmf/interfaces/innerkits/data/html.h new file mode 100644 index 0000000000000000000000000000000000000000..f696d3ce4c9aa27591884ed17a51e67b59f0ee2c --- /dev/null +++ b/udmf/interfaces/innerkits/data/html.h @@ -0,0 +1,42 @@ +/* + * 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 UDMF_HTML_H +#define UDMF_HTML_H + +#include "text.h" + +namespace OHOS { +namespace UDMF { +class Html : public Text { +public: + Html(); + explicit Html(const std::string &htmlContent, const std::string &plainContent); + + int64_t GetSize() override; + + std::string GetHtmlContent() const; + void SetHtmlContent(const std::string &htmlContent); + std::string GetPlainContent() const; + void SetPlainContent(const std::string &htmlContent); + +private: + std::string htmlContent_; + std::string plainContent_; +}; +} // namespace UDMF +} // namespace OHOS + +#endif // UDMF_HTML_H diff --git a/udmf/interfaces/innerkits/data/image.h b/udmf/interfaces/innerkits/data/image.h new file mode 100644 index 0000000000000000000000000000000000000000..0a07e358d1459d1b04aa639219bdd53d7b872f7a --- /dev/null +++ b/udmf/interfaces/innerkits/data/image.h @@ -0,0 +1,31 @@ +/* + * 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 UDMF_IMAGE_H +#define UDMF_IMAGE_H + +#include "file.h" + +namespace OHOS { +namespace UDMF { +class Image : public File { +public: + Image(); + explicit Image(const std::string &uri); +}; +} // namespace UDMF +} // namespace OHOS + +#endif // UDMF_IMAGE_H diff --git a/udmf/interfaces/innerkits/data/link.h b/udmf/interfaces/innerkits/data/link.h new file mode 100644 index 0000000000000000000000000000000000000000..b28cb2176d500103e40fdb8c1b746261db54e487 --- /dev/null +++ b/udmf/interfaces/innerkits/data/link.h @@ -0,0 +1,42 @@ +/* + * 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 UDMF_LINK_H +#define UDMF_LINK_H + +#include "text.h" + +namespace OHOS { +namespace UDMF { +class Link : public Text { +public: + Link(); + explicit Link(const std::string &url); + explicit Link(const std::string &url, const std::string &description); + + int64_t GetSize() override; + + std::string GetUrl() const; + void SetUrl(const std::string &url); + std::string GetDescription() const; + void SetDescription(const std::string &description); + +private: + std::string url_; + std::string description_; +}; +} // namespace UDMF +} // namespace OHOS +#endif // UDMF_LINK_H diff --git a/udmf/interfaces/innerkits/data/plain_text.h b/udmf/interfaces/innerkits/data/plain_text.h new file mode 100644 index 0000000000000000000000000000000000000000..e6cdfaaeadf5a6a75dc25a23d7126d389bc67c21 --- /dev/null +++ b/udmf/interfaces/innerkits/data/plain_text.h @@ -0,0 +1,42 @@ +/* + * 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 UDMF_PLAIN_TEXT_H +#define UDMF_PLAIN_TEXT_H + +#include "text.h" + +namespace OHOS { +namespace UDMF { +class PlainText : public Text { +public: + PlainText(); + explicit PlainText(const std::string &content, const std::string &abstract); + + int64_t GetSize() override; + + std::string GetContent() const; + void SetContent(const std::string &content); + std::string GetAbstract() const; + void SetAbstract(const std::string &abstract); + +private: + std::string content_; + std::string abstract_; +}; +} // namespace UDMF +} // namespace OHOS + +#endif // UDMF_PLAIN_TEXT_H diff --git a/udmf/interfaces/innerkits/data/system_defined_appitem.h b/udmf/interfaces/innerkits/data/system_defined_appitem.h new file mode 100644 index 0000000000000000000000000000000000000000..6cdbb384d0e632084249259ef579ce6f6c7f10f6 --- /dev/null +++ b/udmf/interfaces/innerkits/data/system_defined_appitem.h @@ -0,0 +1,52 @@ +/* + * 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 UDMF_SYSTEM_DEFINED_APPITEM_H +#define UDMF_SYSTEM_DEFINED_APPITEM_H + +#include "system_defined_record.h" + +namespace OHOS { +namespace UDMF { +class SystemDefinedAppItem : public SystemDefinedRecord { +public: + SystemDefinedAppItem(); + + int64_t GetSize() override; + + std::string GetAppId() const; + void SetAppId(const std::string &appId); + std::string GetAppName() const; + void SetAppName(const std::string &appName); + std::string GetAppIconId() const; + void SetAppIconId(const std::string &appIconId); + std::string GetAppLabelId() const; + void SetAppLabelId(const std::string &appLabelId); + std::string GetBundleName() const; + void SetBundleName(const std::string &bundleName); + std::string GetAbilityName() const; + void SetAbilityName(const std::string &abilityName); + +private: + std::string appId_; + std::string appName_; + std::string appIconId_; + std::string appLabelId_; + std::string bundleName_; + std::string abilityName_; +}; +} // namespace UDMF +} // namespace OHOS +#endif // UDMF_SYSTEM_DEFINED_APPITEM_H diff --git a/udmf/interfaces/innerkits/data/system_defined_form.h b/udmf/interfaces/innerkits/data/system_defined_form.h new file mode 100644 index 0000000000000000000000000000000000000000..f6f3059e0e62f17ab3321f7e3dadde7d333d4790 --- /dev/null +++ b/udmf/interfaces/innerkits/data/system_defined_form.h @@ -0,0 +1,49 @@ +/* + * 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 UDMF_SYSTEM_DEFINED_FORM_H +#define UDMF_SYSTEM_DEFINED_FORM_H + +#include "system_defined_record.h" + +namespace OHOS { +namespace UDMF { +class SystemDefinedForm : public SystemDefinedRecord { +public: + SystemDefinedForm(); + + int64_t GetSize() override; + + int32_t GetFormId() const; + void SetFormId(const int32_t &formId); + std::string GetFormName() const; + void SetFormName(const std::string &formName); + std::string GetBundleName() const; + void SetBundleName(const std::string &bundleName); + std::string GetAbilityName() const; + void SetAbilityName(const std::string &abilityName); + std::string GetModule() const; + void SetModule(const std::string &module); + +private: + int32_t formId_; + std::string formName_; + std::string bundleName_; + std::string abilityName_; + std::string module_; +}; +} // namespace UDMF +} // namespace OHOS +#endif // UDMF_SYSTEM_DEFINED_FORM_H diff --git a/udmf/interfaces/innerkits/data/system_defined_pixelmap.h b/udmf/interfaces/innerkits/data/system_defined_pixelmap.h new file mode 100644 index 0000000000000000000000000000000000000000..9d3cc755b24e1ff39f9ec8441303e9a84e823fce --- /dev/null +++ b/udmf/interfaces/innerkits/data/system_defined_pixelmap.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 UDMF_SYSTEM_DEFINED_PIXELMAP_H +#define UDMF_SYSTEM_DEFINED_PIXELMAP_H + +#include "system_defined_record.h" + +namespace OHOS { +namespace UDMF { +class SystemDefinedPixelMap : public SystemDefinedRecord { +public: + SystemDefinedPixelMap(); + explicit SystemDefinedPixelMap(std::vector<uint8_t> &data); + + int64_t GetSize() override; + + std::vector<uint8_t> GetRawData() const; + void SetRawData(const std::vector<uint8_t> &rawData); +private: + std::vector<uint8_t> rawData_; +}; +} // namespace UDMF +} // namespace OHOS +#endif // UDMF_SYSTEM_DEFINED_PIXELMAP_H diff --git a/udmf/interfaces/innerkits/data/system_defined_record.h b/udmf/interfaces/innerkits/data/system_defined_record.h new file mode 100644 index 0000000000000000000000000000000000000000..ecf51c28bb6fc0eade5fe15b47f59eaac9054537 --- /dev/null +++ b/udmf/interfaces/innerkits/data/system_defined_record.h @@ -0,0 +1,39 @@ +/* + * 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 UDMF_SYSTEM_DEFINED_RECORD_H +#define UDMF_SYSTEM_DEFINED_RECORD_H + +#include "unified_record.h" + +namespace OHOS { +namespace UDMF { +class SystemDefinedRecord : public UnifiedRecord { +public: + explicit SystemDefinedRecord(); + + int64_t GetSize() override; + + void AddProperty(const std::string &property, UDVariant &value); + UDVariant GetPropertyByName(const std::string &property) const; + void SetDetails(UDDetails &details); + UDDetails GetDetails() const; + +protected: + UDDetails details_; +}; +} // namespace UDMF +} // namespace OHOS +#endif // UDMF_SYSTEM_DEFINED_RECORD_H \ No newline at end of file diff --git a/udmf/interfaces/innerkits/data/text.h b/udmf/interfaces/innerkits/data/text.h new file mode 100644 index 0000000000000000000000000000000000000000..82369c7833920bba549348acb5e6705e9b67f4aa --- /dev/null +++ b/udmf/interfaces/innerkits/data/text.h @@ -0,0 +1,40 @@ +/* + * 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 UDMF_TEXT_H +#define UDMF_TEXT_H + +#include "unified_record.h" + +namespace OHOS { +namespace UDMF { +constexpr int MAX_TEXT_LEN = 20 * 1024 * 1024; +class Text : public UnifiedRecord { +public: + Text(); + explicit Text(UDDetails &variantMap); + + int64_t GetSize() override; + + void SetDetails(UDDetails &variantMap); + UDDetails GetDetails() const; + +protected: + UDDetails details_; +}; +} // namespace UDMF +} // namespace OHOS + +#endif // UDMF_TEXT_H diff --git a/udmf/interfaces/innerkits/data/unified_data.h b/udmf/interfaces/innerkits/data/unified_data.h new file mode 100644 index 0000000000000000000000000000000000000000..2cc052d520dc7fe5e914bf47f3ffc73a73981208 --- /dev/null +++ b/udmf/interfaces/innerkits/data/unified_data.h @@ -0,0 +1,47 @@ +/* + * 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 UDMF_UNIFIED_DATA_H +#define UDMF_UNIFIED_DATA_H + +#include "unified_record.h" + +namespace OHOS { +namespace UDMF { +class UnifiedData { +public: + int64_t GetSize(); + + std::string GetGroupId() const; + + std::shared_ptr<Runtime> GetRuntime() const; + void SetRuntime(Runtime &runtime); + + void AddRecord(const std::shared_ptr<UnifiedRecord> &record); + std::shared_ptr<UnifiedRecord> GetRecordAt(std::size_t index); + void SetRecords(std::vector<std::shared_ptr<UnifiedRecord>> records); + std::vector<std::shared_ptr<UnifiedRecord>> GetRecords() const; + + std::vector<UDType> GetUDTypes(); + + bool IsEmpty() const; + +private: + std::shared_ptr<Runtime> runtime_; + std::vector<std::shared_ptr<UnifiedRecord>> records_; +}; +} // namespace UDMF +} // namespace OHOS +#endif // UDMF_UNIFIED_DATA_H diff --git a/udmf/interfaces/innerkits/data/unified_record.h b/udmf/interfaces/innerkits/data/unified_record.h new file mode 100644 index 0000000000000000000000000000000000000000..ade232ac0db05346f72c6a1f5102932c0eeabb6a --- /dev/null +++ b/udmf/interfaces/innerkits/data/unified_record.h @@ -0,0 +1,49 @@ +/* + * 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 UDMF_UNIFIED_RECORD_H +#define UDMF_UNIFIED_RECORD_H + +#include <memory> +#include <string> +#include <variant> +#include <vector> + +#include "unified_types.h" + +namespace OHOS { +namespace UDMF { +class UnifiedRecord { +public: + UnifiedRecord(); + explicit UnifiedRecord(UDType type); + virtual ~UnifiedRecord() = default; + + UDType GetType() const; + void SetType(const UDType &type); + virtual int64_t GetSize(); + + std::string GetUid() const; + void SetUid(const std::string &id); + +protected: + UDType dataType_; + +private: + std::string uid_; // unique identifier +}; +} // namespace UDMF +} // namespace OHOS +#endif // UDMF_UNIFIED_RECORD_H diff --git a/udmf/interfaces/innerkits/data/video.h b/udmf/interfaces/innerkits/data/video.h new file mode 100644 index 0000000000000000000000000000000000000000..ea80bf81032de1d9230219d86edcaaebd34b93d3 --- /dev/null +++ b/udmf/interfaces/innerkits/data/video.h @@ -0,0 +1,30 @@ +/* + * 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 UDMF_VIDEO_H +#define UDMF_VIDEO_H + +#include "file.h" + +namespace OHOS { +namespace UDMF { +class Video : public File { +public: + Video(); + explicit Video(const std::string &uri); +}; +} // namespace UDMF +} // namespace OHOS +#endif // UDMF_VIDEO_H diff --git a/udmf/interfaces/jskits/BUILD.gn b/udmf/interfaces/jskits/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..a139a9dcf07d802d6ea1ae6443eea211f2e025d5 --- /dev/null +++ b/udmf/interfaces/jskits/BUILD.gn @@ -0,0 +1,134 @@ +# Copyright (c) 2022 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import("//build/ohos.gni") +import("//foundation/distributeddatamgr/udmf/udmf.gni") + +config("udmf_napi_config") { + include_dirs = [ + "${udmf_interfaces_path}/innerkits/client", + "${udmf_interfaces_path}/innerkits/common", + "${udmf_interfaces_path}/innerkits/data", + "${udmf_interfaces_path}/jskits/common", + "${udmf_interfaces_path}/jskits/data", + + "${udmf_framework_path}/common", + "${udmf_framework_path}/service", + + "//third_party/libuv/include", + "//third_party/node/src", + + "${aafwk_inner_api_path}/ability_manager/include", + "${aafwk_kits_path}/appkit/native/app/include/", + "${aafwk_kits_path}/ability/native/include", + "${aafwk_napi_path}/inner/napi_common", + "${aafwk_service_path}/abilitymgr/include", + "${aafwk_service_path}/common/include", + ] +} + +ohos_shared_library("udmf_napi") { + sources = [ + "${udmf_framework_path}/jskitsimpl/common/napi_data_utils.cpp", + "${udmf_framework_path}/jskitsimpl/common/napi_error_utils.cpp", + "${udmf_framework_path}/jskitsimpl/common/napi_queue.cpp", + "${udmf_framework_path}/jskitsimpl/data/application_defined_record_napi.cpp", + "${udmf_framework_path}/jskitsimpl/data/audio_napi.cpp", + "${udmf_framework_path}/jskitsimpl/data/file_napi.cpp", + "${udmf_framework_path}/jskitsimpl/data/folder_napi.cpp", + "${udmf_framework_path}/jskitsimpl/data/html_napi.cpp", + "${udmf_framework_path}/jskitsimpl/data/image_napi.cpp", + "${udmf_framework_path}/jskitsimpl/data/link_napi.cpp", + "${udmf_framework_path}/jskitsimpl/data/plain_text_napi.cpp", + "${udmf_framework_path}/jskitsimpl/data/summary_napi.cpp", + "${udmf_framework_path}/jskitsimpl/data/system_defined_appitem_napi.cpp", + "${udmf_framework_path}/jskitsimpl/data/system_defined_form_napi.cpp", + "${udmf_framework_path}/jskitsimpl/data/system_defined_pixelmap_napi.cpp", + "${udmf_framework_path}/jskitsimpl/data/system_defined_record_napi.cpp", + "${udmf_framework_path}/jskitsimpl/data/text_napi.cpp", + "${udmf_framework_path}/jskitsimpl/data/udmf_napi.cpp", + "${udmf_framework_path}/jskitsimpl/data/unified_data_napi.cpp", + "${udmf_framework_path}/jskitsimpl/data/unified_record_napi.cpp", + "${udmf_framework_path}/jskitsimpl/data/video_napi.cpp", + "${udmf_interfaces_path}/jskits/module/udmf_napi_module.cpp", + ] + public_configs = [ ":udmf_napi_config" ] + + deps = [ + "${third_party_path}/bounds_checking_function:libsec_shared", + "../innerkits:udmf_client", + ] + + external_deps = [ + "ability_base:base", + "ability_runtime:ability_manager", + "ability_runtime:abilitykit_native", + "ability_runtime:napi_base_context", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:distributeddata_inner", + "napi:ace_napi", + ] + + relative_install_dir = "module/data" + subsystem_name = "distributeddatamgr" + part_name = "udmf" +} + +ohos_shared_library("udmf_data_napi") { + sources = [ + "${udmf_framework_path}/jskitsimpl/common/napi_data_utils.cpp", + "${udmf_framework_path}/jskitsimpl/common/napi_error_utils.cpp", + "${udmf_framework_path}/jskitsimpl/common/napi_queue.cpp", + "${udmf_framework_path}/jskitsimpl/data/application_defined_record_napi.cpp", + "${udmf_framework_path}/jskitsimpl/data/audio_napi.cpp", + "${udmf_framework_path}/jskitsimpl/data/file_napi.cpp", + "${udmf_framework_path}/jskitsimpl/data/folder_napi.cpp", + "${udmf_framework_path}/jskitsimpl/data/html_napi.cpp", + "${udmf_framework_path}/jskitsimpl/data/image_napi.cpp", + "${udmf_framework_path}/jskitsimpl/data/link_napi.cpp", + "${udmf_framework_path}/jskitsimpl/data/plain_text_napi.cpp", + "${udmf_framework_path}/jskitsimpl/data/summary_napi.cpp", + "${udmf_framework_path}/jskitsimpl/data/system_defined_appitem_napi.cpp", + "${udmf_framework_path}/jskitsimpl/data/system_defined_form_napi.cpp", + "${udmf_framework_path}/jskitsimpl/data/system_defined_pixelmap_napi.cpp", + "${udmf_framework_path}/jskitsimpl/data/system_defined_record_napi.cpp", + "${udmf_framework_path}/jskitsimpl/data/text_napi.cpp", + "${udmf_framework_path}/jskitsimpl/data/udmf_napi.cpp", + "${udmf_framework_path}/jskitsimpl/data/unified_data_napi.cpp", + "${udmf_framework_path}/jskitsimpl/data/unified_record_napi.cpp", + "${udmf_framework_path}/jskitsimpl/data/video_napi.cpp", + "${udmf_interfaces_path}/jskits/module/udmf_napi_module.cpp", + ] + public_configs = [ ":udmf_napi_config" ] + + deps = [ + "${third_party_path}/bounds_checking_function:libsec_shared", + "../innerkits:udmf_client", + ] + + external_deps = [ + "ability_base:base", + "ability_runtime:ability_manager", + "ability_runtime:abilitykit_native", + "ability_runtime:napi_base_context", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:distributeddata_inner", + "napi:ace_napi", + ] + + subsystem_name = "distributeddatamgr" + part_name = "udmf" +} diff --git a/udmf/interfaces/jskits/common/napi_data_utils.h b/udmf/interfaces/jskits/common/napi_data_utils.h new file mode 100644 index 0000000000000000000000000000000000000000..bc19dd561c13e053d6de83790f763c3ed52a168a --- /dev/null +++ b/udmf/interfaces/jskits/common/napi_data_utils.h @@ -0,0 +1,120 @@ +/* + * 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 UDMF_NAPI_DATA_UTILS_H +#define UDMF_NAPI_DATA_UTILS_H + +#include <cstdint> +#include <map> +#include <memory> +#include <string> +#include <variant> +#include <vector> + +#include "napi/native_api.h" +#include "napi/native_common.h" +#include "napi/native_node_api.h" +#include "napi_common_want.h" +#include "securec.h" + +#include "logger.h" +#include "unified_meta.h" + +namespace OHOS { +namespace UDMF { +class NapiDataUtils { +public: + /* napi_value <-> bool */ + static napi_status GetValue(napi_env env, napi_value in, bool &out); + static napi_status SetValue(napi_env env, const bool &in, napi_value &out); + + /* napi_value <-> int32_t */ + static napi_status GetValue(napi_env env, napi_value in, int32_t &out); + static napi_status SetValue(napi_env env, const int32_t &in, napi_value &out); + + /* napi_value <-> int64_t */ + static napi_status GetValue(napi_env env, napi_value in, int64_t &out); + static napi_status SetValue(napi_env env, const int64_t &in, napi_value &out); + + /* napi_value <-> float */ + static napi_status GetValue(napi_env env, napi_value in, float &out); + static napi_status SetValue(napi_env env, const float &in, napi_value &out); + + /* napi_value <-> double */ + static napi_status GetValue(napi_env env, napi_value in, double &out); + static napi_status SetValue(napi_env env, const double &in, napi_value &out); + + /* napi_value <-> std::string */ + static napi_status GetValue(napi_env env, napi_value in, std::string &out); + static napi_status SetValue(napi_env env, const std::string &in, napi_value &out); + + /* napi_value <-> std::vector<std::string> */ + static napi_status GetValue(napi_env env, napi_value in, std::vector<std::string> &out); + static napi_status SetValue(napi_env env, const std::vector<std::string> &in, napi_value &out); + + /* napi_value <-> std::vector<uint8_t> */ + static napi_status GetValue(napi_env env, napi_value in, std::vector<uint8_t> &out); + static napi_status SetValue(napi_env env, const std::vector<uint8_t> &in, napi_value &out); + + /* napi_value <-> std::map<std::string, int32_t> */ + static napi_status GetValue(napi_env env, napi_value in, std::map<std::string, int32_t> &out); + static napi_status SetValue(napi_env env, const std::map<std::string, int32_t> &in, napi_value &out); + + /* napi_value <-> std::map<std::string, int64_t> */ + static napi_status GetValue(napi_env env, napi_value in, std::map<std::string, int64_t> &out); + static napi_status SetValue(napi_env env, const std::map<std::string, int64_t> &in, napi_value &out); + + /* napi_value <-> UDVariant */ + static napi_status GetValue(napi_env env, napi_value in, UDVariant &out); + static napi_status SetValue(napi_env env, const UDVariant &in, napi_value &out); + + /* napi_value <-> UDDetails */ + static napi_status GetValue(napi_env env, napi_value in, UDDetails &out); + static napi_status SetValue(napi_env env, const UDDetails &in, napi_value &out); + + static bool IsTypeForNapiValue(napi_env env, napi_value param, napi_valuetype expectType); + + static bool IsNull(napi_env env, napi_value value); + /* napi_define_class wrapper */ + static napi_value DefineClass(napi_env env, const std::string &name, const napi_property_descriptor *properties, + size_t count, napi_callback newcb); + +private: + enum { + /* std::map<key, value> to js::tuple<key, value> */ + TUPLE_KEY = 0, + TUPLE_VALUE, + TUPLE_SIZE + }; +}; + +#define LOG_ERROR_RETURN(condition, message, retVal) \ + do { \ + if (!(condition)) { \ + LOG_ERROR(UDMF_KITS_NAPI, "test (" #condition ") failed: " message); \ + return retVal; \ + } \ + } while (0) + +#define LOG_ERROR_RETURN_VOID(condition, message) \ + do { \ + if (!(condition)) { \ + LOG_ERROR(UDMF_KITS_NAPI, "test (" #condition ") failed: " message); \ + return; \ + } \ + } while (0) +} // namespace UDMF +} // namespace OHOS +#endif // UDMF_NAPI_DATA_UTILS_H diff --git a/udmf/interfaces/jskits/common/napi_error_utils.h b/udmf/interfaces/jskits/common/napi_error_utils.h new file mode 100644 index 0000000000000000000000000000000000000000..51a526406c36bf55ae12e368bf9f92a0c3e04b45 --- /dev/null +++ b/udmf/interfaces/jskits/common/napi_error_utils.h @@ -0,0 +1,78 @@ +/* + * 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 UDMF_ERROR_UTILS_H +#define UDMF_ERROR_UTILS_H + +#include <map> +#include <optional> +#include <string> + +#include "js_native_api.h" +#include "napi/native_common.h" + +#include "error_code.h" +#include "logger.h" + + +namespace OHOS { +namespace UDMF { +struct NapiErrorCode { + int32_t status; + int32_t jsCode; + const char *message; +}; + +const std::optional<NapiErrorCode> GetErrorCode(int32_t errorCode); +Status GenerateNapiError(Status error, int32_t &errCode, std::string &errMessage); +void ThrowNapiError(napi_env env, int32_t errCode, const std::string &errMessage, bool isParamsCheck = true); +napi_value GenerateErrorMsg(napi_env env, NapiErrorCode jsInfo); + +#define ASSERT_ERR(env, assertion, errorcode, message) \ + do { \ + if (!(assertion)) { \ + ThrowNapiError(env, errorcode, message); \ + return nullptr; \ + } \ + } while (0) + +#define ASSERT_ERR_VOID(env, assertion, errorcode, message) \ + do { \ + if (!(assertion)) { \ + ThrowNapiError(env, errorcode, message); \ + return; \ + } \ + } 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 UDMF +} // namespace OHOS +#endif // UDMF_ERROR_UTILS_H diff --git a/udmf/interfaces/jskits/common/napi_queue.h b/udmf/interfaces/jskits/common/napi_queue.h new file mode 100644 index 0000000000000000000000000000000000000000..093ef7b571dc3882fbd16384acb8b4ec39814d33 --- /dev/null +++ b/udmf/interfaces/jskits/common/napi_queue.h @@ -0,0 +1,168 @@ +/* + * 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 UDMF_NAPI_QUEUE_H +#define UDMF_NAPI_QUEUE_H + +#include <functional> +#include <memory> +#include <string> + +#include "napi/native_api.h" +#include "napi/native_common.h" +#include "napi/native_node_api.h" +#include "napi_error_utils.h" + +namespace OHOS { +namespace UDMF { +using NapiCbInfoParser = std::function<void(size_t argc, napi_value *argv)>; +using NapiAsyncExecute = std::function<void(void)>; +using NapiAsyncComplete = std::function<void(napi_value &)>; +static constexpr size_t ARGC_MAX = 6; +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, const 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_deferred deferred = nullptr; + napi_async_work work = nullptr; + napi_ref callbackRef = nullptr; + napi_ref selfRef = nullptr; + + NapiAsyncExecute execute = nullptr; + NapiAsyncComplete complete = nullptr; + std::shared_ptr<ContextBase> hold; /* cross thread data */ + + 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); \ + LOG_ERROR(UDMF_KITS_NAPI, "test (" #condition ") failed: " message); \ + return; \ + } \ + } while (0) + +#define ASSERT_STATUS(ctxt, message) \ + do { \ + if ((ctxt)->status != napi_ok) { \ + (ctxt)->error = std::string(message); \ + LOG_ERROR(UDMF_KITS_NAPI, "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)) { \ + LOG_ERROR(UDMF_KITS_NAPI, "test (" #condition ") failed: " message); \ + return retVal; \ + } \ + } while (0) + +#define ASSERT_VOID(condition, message) \ + do { \ + if (!(condition)) { \ + LOG_ERROR(UDMF_KITS_NAPI, "test (" #condition ") failed: " message); \ + return; \ + } \ + } while (0) + +#define ASSERT_FALSE(condition, message) \ + do { \ + if (!(condition)) { \ + LOG_ERROR(UDMF_KITS_NAPI, "test (" #condition ") failed: " message); \ + return false; \ + } \ + } 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) + +#define ASSERT_CALL_DELETE(env, theCall, object) \ + do { \ + if ((theCall) != napi_ok) { \ + delete (object); \ + GET_AND_THROW_LAST_ERROR((env)); \ + return; \ + } \ + } while (0) + +#define ASSERT_CALL_VOID(env, theCall) \ + do { \ + if ((theCall) != napi_ok) { \ + GET_AND_THROW_LAST_ERROR((env)); \ + return; \ + } \ + } while (0) + +#define ASSERT_WITH_ERRCODE(ctxt, condition, errcode, message) \ + do { \ + if (!(condition)) { \ + (ctxt)->status = napi_generic_failure; \ + GenerateNapiError(errcode, (ctxt)->jsCode, (ctxt)->error); \ + LOG_ERROR(UDMF_KITS_NAPI, "test (" #condition ") failed: " message); \ + return; \ + } \ + } while (0) + +class NapiQueue { +public: + static napi_value AsyncWork(napi_env env, std::shared_ptr<ContextBase> 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 + }; + + static void GenerateOutput(ContextBase *ctxt); +}; +} // namespace UDMF +} // namespace OHOS +#endif // UDMF_NAPI_QUEUE_H diff --git a/udmf/interfaces/jskits/data/application_defined_record_napi.h b/udmf/interfaces/jskits/data/application_defined_record_napi.h new file mode 100644 index 0000000000000000000000000000000000000000..ff12f1c29ad21f665e6495873b81bd18ce1fb6be --- /dev/null +++ b/udmf/interfaces/jskits/data/application_defined_record_napi.h @@ -0,0 +1,48 @@ +/* + * 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 UDMF_APPLICATION_DEFINED_RECORD_NAPI_H +#define UDMF_APPLICATION_DEFINED_RECORD_NAPI_H + +#include <memory> + +#include "napi/native_api.h" +#include "napi/native_node_api.h" + +namespace OHOS { +namespace UDMF { +struct ContextBase; +class UnifiedRecord; +class ApplicationDefinedRecord; +class ApplicationDefinedRecordNapi { +public: + static napi_value Constructor(napi_env env); + static void NewInstance(napi_env env, std::shared_ptr<UnifiedRecord> in, napi_value &out); + std::shared_ptr<ApplicationDefinedRecord> value_; + +private: + static napi_value New(napi_env env, napi_callback_info info); + static void Destructor(napi_env env, void *data, void *hint); + static ApplicationDefinedRecordNapi *GetApplicationDefinedRecord( + napi_env env, napi_callback_info info, std::shared_ptr<ContextBase> ctxt); + + static napi_value GetApplicationDefinedType(napi_env env, napi_callback_info info); + static napi_value SetApplicationDefinedType(napi_env env, napi_callback_info info); + static napi_value GetRawData(napi_env env, napi_callback_info info); + static napi_value SetRawData(napi_env env, napi_callback_info info); +}; +} // namespace UDMF +} // namespace OHOS +#endif // UDMF_APPLICATION_DEFINED_RECORD_NAPI_H diff --git a/udmf/interfaces/jskits/data/audio_napi.h b/udmf/interfaces/jskits/data/audio_napi.h new file mode 100644 index 0000000000000000000000000000000000000000..89b0fc69f809371feaa6d1395ab2e72b2176c7a6 --- /dev/null +++ b/udmf/interfaces/jskits/data/audio_napi.h @@ -0,0 +1,44 @@ +/* + * 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 UDMF_AUDIO_NAPI_H +#define UDMF_AUDIO_NAPI_H + +#include <memory> + +#include "napi/native_api.h" +#include "napi/native_node_api.h" + +namespace OHOS { +namespace UDMF { +struct ContextBase; +class UnifiedRecord; +class Audio; +class AudioNapi { +public: + static napi_value Constructor(napi_env env); + static void NewInstance(napi_env env, std::shared_ptr<UnifiedRecord> in, napi_value &out); + std::shared_ptr<Audio> value_; + +private: + static napi_value New(napi_env env, napi_callback_info info); + static void Destructor(napi_env env, void *data, void *hint); + static AudioNapi *GetAudio(napi_env env, napi_callback_info info, std::shared_ptr<ContextBase> ctxt); + static napi_value GetAudioUri(napi_env env, napi_callback_info info); + static napi_value SetAudioUri(napi_env env, napi_callback_info info); +}; +} // namespace UDMF +} // namespace OHOS +#endif // UDMF_AUDIO_NAPI_H diff --git a/udmf/interfaces/jskits/data/file_napi.h b/udmf/interfaces/jskits/data/file_napi.h new file mode 100644 index 0000000000000000000000000000000000000000..b76eb6795f65986774f09a1b178da05453d34f23 --- /dev/null +++ b/udmf/interfaces/jskits/data/file_napi.h @@ -0,0 +1,47 @@ +/* + * 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 UDMF_FILE_NAPI_H +#define UDMF_FILE_NAPI_H + +#include <memory> + +#include "napi/native_api.h" +#include "napi/native_node_api.h" + +namespace OHOS { +namespace UDMF { +struct ContextBase; +class UnifiedRecord; +class File; +class FileNapi { +public: + static napi_value Constructor(napi_env env); + static void NewInstance(napi_env env, std::shared_ptr<UnifiedRecord> in, napi_value &out); + static napi_value GetDetails(napi_env env, napi_callback_info info); + static napi_value SetDetails(napi_env env, napi_callback_info info); + static napi_value GetUri(napi_env env, napi_callback_info info); + static napi_value SetUri(napi_env env, napi_callback_info info); + std::shared_ptr<File> value_; + +private: + static napi_value New(napi_env env, napi_callback_info info); + static void Destructor(napi_env env, void *data, void *hint); + static FileNapi *GetFile(napi_env env, napi_callback_info info, std::shared_ptr<ContextBase> ctxt); +}; +} // namespace UDMF +} // namespace OHOS + +#endif // UDMF_FILE_NAPI_H diff --git a/udmf/interfaces/jskits/data/folder_napi.h b/udmf/interfaces/jskits/data/folder_napi.h new file mode 100644 index 0000000000000000000000000000000000000000..3919911546474732792f41a74d001e71e8c8be08 --- /dev/null +++ b/udmf/interfaces/jskits/data/folder_napi.h @@ -0,0 +1,44 @@ +/* + * 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 UDMF_FOLDER_NAPI_H +#define UDMF_FOLDER_NAPI_H + +#include <memory> + +#include "napi/native_api.h" +#include "napi/native_node_api.h" + +namespace OHOS { +namespace UDMF { +struct ContextBase; +class UnifiedRecord; +class Folder; +class FolderNapi { +public: + static napi_value Constructor(napi_env env); + static void NewInstance(napi_env env, std::shared_ptr<UnifiedRecord> in, napi_value &out); + std::shared_ptr<Folder> value_; + +private: + static napi_value New(napi_env env, napi_callback_info info); + static void Destructor(napi_env env, void *data, void *hint); + static FolderNapi *GetFolder(napi_env env, napi_callback_info info, std::shared_ptr<ContextBase> ctxt); + static napi_value GetFolderUri(napi_env env, napi_callback_info info); + static napi_value SetFolderUri(napi_env env, napi_callback_info info); +}; +} // namespace UDMF +} // namespace OHOS +#endif // UDMF_FOLDER_NAPI_H diff --git a/udmf/interfaces/jskits/data/html_napi.h b/udmf/interfaces/jskits/data/html_napi.h new file mode 100644 index 0000000000000000000000000000000000000000..8807a26b800abc668215ec4893bfba38a40b0f71 --- /dev/null +++ b/udmf/interfaces/jskits/data/html_napi.h @@ -0,0 +1,47 @@ +/* + * 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 UDMF_HTML_NAPI_H +#define UDMF_HTML_NAPI_H + +#include <memory> + +#include "napi/native_api.h" +#include "napi/native_node_api.h" + +namespace OHOS { +namespace UDMF { +struct ContextBase; +class UnifiedRecord; +class Html; +class HtmlNapi { +public: + static napi_value Constructor(napi_env env); + static void NewInstance(napi_env env, std::shared_ptr<UnifiedRecord> in, napi_value &out); + std::shared_ptr<Html> value_; + +private: + static napi_value New(napi_env env, napi_callback_info info); + static void Destructor(napi_env env, void *data, void *hint); + static HtmlNapi *GetHtml(napi_env env, napi_callback_info info, std::shared_ptr<ContextBase> ctxt); + + static napi_value GetHtmlContent(napi_env env, napi_callback_info info); + static napi_value SetHtmlContent(napi_env env, napi_callback_info info); + static napi_value GetPlainContent(napi_env env, napi_callback_info info); + static napi_value SetPlainContent(napi_env env, napi_callback_info info); +}; +} // namespace UDMF +} // namespace OHOS +#endif // UDMF_HTML_NAPI_H diff --git a/udmf/interfaces/jskits/data/image_napi.h b/udmf/interfaces/jskits/data/image_napi.h new file mode 100644 index 0000000000000000000000000000000000000000..fb7589ff7c15092b09941fb53502539c21524006 --- /dev/null +++ b/udmf/interfaces/jskits/data/image_napi.h @@ -0,0 +1,44 @@ +/* + * 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 UDMF_IMAGE_NAPI_H +#define UDMF_IMAGE_NAPI_H + +#include <memory> + +#include "napi/native_api.h" +#include "napi/native_node_api.h" + +namespace OHOS { +namespace UDMF { +struct ContextBase; +class UnifiedRecord; +class Image; +class ImageNapi { +public: + static napi_value Constructor(napi_env env); + static void NewInstance(napi_env env, std::shared_ptr<UnifiedRecord> in, napi_value &out); + std::shared_ptr<Image> value_; + +private: + static napi_value New(napi_env env, napi_callback_info info); + static void Destructor(napi_env env, void *data, void *hint); + static ImageNapi *GetImage(napi_env env, napi_callback_info info, std::shared_ptr<ContextBase> ctxt); + static napi_value GetImageUri(napi_env env, napi_callback_info info); + static napi_value SetImageUri(napi_env env, napi_callback_info info); +}; +} // namespace UDMF +} // namespace OHOS +#endif // UDMF_IMAGE_NAPI_H diff --git a/udmf/interfaces/jskits/data/link_napi.h b/udmf/interfaces/jskits/data/link_napi.h new file mode 100644 index 0000000000000000000000000000000000000000..081457d1435ed3c994e0fa05f897c708c7659ec0 --- /dev/null +++ b/udmf/interfaces/jskits/data/link_napi.h @@ -0,0 +1,48 @@ +/* + * 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 UDMF_LINK_NAPI_H +#define UDMF_LINK_NAPI_H + +#include <memory> + +#include "napi/native_api.h" +#include "napi/native_node_api.h" + +namespace OHOS { +namespace UDMF { +struct ContextBase; +class UnifiedRecord; +class Link; +class LinkNapi { +public: + static napi_value Constructor(napi_env env); + static void NewInstance(napi_env env, std::shared_ptr<UnifiedRecord> in, napi_value &out); + std::shared_ptr<Link> value_; + +private: + static napi_value New(napi_env env, napi_callback_info info); + static void Destructor(napi_env env, void *data, void *hint); + static LinkNapi *GetLink(napi_env env, napi_callback_info info, std::shared_ptr<ContextBase> ctxt); + + static napi_value GetUrl(napi_env env, napi_callback_info info); + static napi_value SetUrl(napi_env env, napi_callback_info info); + + static napi_value GetDescription(napi_env env, napi_callback_info info); + static napi_value SetDescription(napi_env env, napi_callback_info info); +}; +} // namespace UDMF +} // namespace OHOS +#endif // UDMF_LINK_NAPI_H diff --git a/udmf/interfaces/jskits/data/plain_text_napi.h b/udmf/interfaces/jskits/data/plain_text_napi.h new file mode 100644 index 0000000000000000000000000000000000000000..676206000d9f342654c036818c9df2f495824ecb --- /dev/null +++ b/udmf/interfaces/jskits/data/plain_text_napi.h @@ -0,0 +1,47 @@ +/* + * 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 UDMF_PLAIN_TEXT_NAPI_H +#define UDMF_PLAIN_TEXT_NAPI_H + +#include <memory> + +#include "napi/native_api.h" +#include "napi/native_node_api.h" + +namespace OHOS { +namespace UDMF { +struct ContextBase; +class UnifiedRecord; +class PlainText; +class PlainTextNapi { +public: + static napi_value Constructor(napi_env env); + static void NewInstance(napi_env env, std::shared_ptr<UnifiedRecord> in, napi_value &out); + std::shared_ptr<PlainText> value_; + +private: + static napi_value New(napi_env env, napi_callback_info info); + static void Destructor(napi_env env, void *data, void *hint); + static PlainTextNapi *GetPlainText(napi_env env, napi_callback_info info, std::shared_ptr<ContextBase> ctxt); + + static napi_value GetContent(napi_env env, napi_callback_info info); + static napi_value SetContent(napi_env env, napi_callback_info info); + static napi_value GetAbstract(napi_env env, napi_callback_info info); + static napi_value SetAbstract(napi_env env, napi_callback_info info); +}; +} // namespace UDMF +} // namespace OHOS +#endif // UDMF_PLAIN_TEXT_NAPI_H \ No newline at end of file diff --git a/udmf/interfaces/jskits/data/summary_napi.h b/udmf/interfaces/jskits/data/summary_napi.h new file mode 100644 index 0000000000000000000000000000000000000000..069cabf83f47e75b61c9f84054688a5b530bfaa6 --- /dev/null +++ b/udmf/interfaces/jskits/data/summary_napi.h @@ -0,0 +1,44 @@ +/* + * 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 UDMF_SUMMARY_NAPI_H +#define UDMF_SUMMARY_NAPI_H + +#include <memory> + +#include "napi/native_api.h" +#include "napi/native_node_api.h" + +namespace OHOS { +namespace UDMF { +struct ContextBase; +struct Summary; +class SummaryNapi { +public: + static napi_value Constructor(napi_env env); + static void NewInstance(napi_env env, std::shared_ptr<Summary> in, napi_value &out); + std::shared_ptr<Summary> value_; + +private: + static napi_value New(napi_env env, napi_callback_info info); + static void Destructor(napi_env env, void *data, void *hint); + static SummaryNapi *GetDataSummary(napi_env env, napi_callback_info info, std::shared_ptr<ContextBase> ctxt); + + static napi_value GetSummary(napi_env env, napi_callback_info info); + static napi_value GetTotal(napi_env env, napi_callback_info info); +}; +} // namespace UDMF +} // namespace OHOS +#endif // UDMF_SUMMARY_NAPI_H \ No newline at end of file diff --git a/udmf/interfaces/jskits/data/system_defined_appitem_napi.h b/udmf/interfaces/jskits/data/system_defined_appitem_napi.h new file mode 100644 index 0000000000000000000000000000000000000000..deef608156a056e69bf680912f442f89a216feee --- /dev/null +++ b/udmf/interfaces/jskits/data/system_defined_appitem_napi.h @@ -0,0 +1,62 @@ +/* + * 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 UDMF_SYSTEM_DEFINED_APPITEM_NAPI_H +#define UDMF_SYSTEM_DEFINED_APPITEM_NAPI_H + +#include <memory> + +#include "napi/native_api.h" +#include "napi/native_node_api.h" + +namespace OHOS { +namespace UDMF { +struct ContextBase; +class UnifiedRecord; +class SystemDefinedAppItem; +class SystemDefinedAppItemNapi { +public: + static napi_value Constructor(napi_env env); + static void NewInstance(napi_env env, std::shared_ptr<UnifiedRecord> in, napi_value &out); + std::shared_ptr<SystemDefinedAppItem> value_; + +private: + static napi_value New(napi_env env, napi_callback_info info); + static void Destructor(napi_env env, void *data, void *hint); + static SystemDefinedAppItemNapi *GetSystemDefinedAppItem( + napi_env env, napi_callback_info info, std::shared_ptr<ContextBase> ctxt); + + static napi_value GetAppId(napi_env env, napi_callback_info info); + static napi_value SetAppId(napi_env env, napi_callback_info info); + + static napi_value GetAppName(napi_env env, napi_callback_info info); + static napi_value SetAppName(napi_env env, napi_callback_info info); + + static napi_value GetAppIconId(napi_env env, napi_callback_info info); + static napi_value SetAppIconId(napi_env env, napi_callback_info info); + + static napi_value GetAppLabelId(napi_env env, napi_callback_info info); + static napi_value SetAppLabelId(napi_env env, napi_callback_info info); + + static napi_value GetBundleName(napi_env env, napi_callback_info info); + static napi_value SetBundleName(napi_env env, napi_callback_info info); + + static napi_value GetAbilityName(napi_env env, napi_callback_info info); + static napi_value SetAbilityName(napi_env env, napi_callback_info info); +}; +} // namespace UDMF +} // namespace OHOS + +#endif // UDMF_SYSTEM_DEFINED_APPITEM_NAPI_H diff --git a/udmf/interfaces/jskits/data/system_defined_form_napi.h b/udmf/interfaces/jskits/data/system_defined_form_napi.h new file mode 100644 index 0000000000000000000000000000000000000000..191ba59a396396487dafcec1a7c5692101cd3376 --- /dev/null +++ b/udmf/interfaces/jskits/data/system_defined_form_napi.h @@ -0,0 +1,59 @@ +/* + * 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 UDMF_SYSTEM_DEFINED_FORM_NAPI_H +#define UDMF_SYSTEM_DEFINED_FORM_NAPI_H + +#include <memory> + +#include "napi/native_api.h" +#include "napi/native_node_api.h" + +namespace OHOS { +namespace UDMF { +struct ContextBase; +class UnifiedRecord; +class SystemDefinedForm; +class SystemDefinedFormNapi { +public: + static napi_value Constructor(napi_env env); + static void NewInstance(napi_env env, std::shared_ptr<UnifiedRecord> in, napi_value &out); + std::shared_ptr<SystemDefinedForm> value_; + +private: + static napi_value New(napi_env env, napi_callback_info info); + static void Destructor(napi_env env, void *data, void *hint); + static SystemDefinedFormNapi *GetSystemDefinedForm( + napi_env env, napi_callback_info info, std::shared_ptr<ContextBase> ctxt); + + static napi_value GetFormId(napi_env env, napi_callback_info info); + static napi_value SetFormId(napi_env env, napi_callback_info info); + + static napi_value GetFormName(napi_env env, napi_callback_info info); + static napi_value SetFormName(napi_env env, napi_callback_info info); + + static napi_value GetBundleName(napi_env env, napi_callback_info info); + static napi_value SetBundleName(napi_env env, napi_callback_info info); + + static napi_value GetAbilityName(napi_env env, napi_callback_info info); + static napi_value SetAbilityName(napi_env env, napi_callback_info info); + + static napi_value GetModule(napi_env env, napi_callback_info info); + static napi_value SetModule(napi_env env, napi_callback_info info); +}; +} // namespace UDMF +} // namespace OHOS + +#endif // UDMF_SYSTEM_DEFINED_FORM_NAPI_H diff --git a/udmf/interfaces/jskits/data/system_defined_pixelmap_napi.h b/udmf/interfaces/jskits/data/system_defined_pixelmap_napi.h new file mode 100644 index 0000000000000000000000000000000000000000..eb64b3ba0228b326780cfbcd083e47fbd69fa232 --- /dev/null +++ b/udmf/interfaces/jskits/data/system_defined_pixelmap_napi.h @@ -0,0 +1,47 @@ +/* + * 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 UDMF_SYSTEM_DEFINED_PIXELMAP_NAPI_H +#define UDMF_SYSTEM_DEFINED_PIXELMAP_NAPI_H + +#include <memory> + +#include "napi/native_api.h" +#include "napi/native_node_api.h" + +namespace OHOS { +namespace UDMF { +struct ContextBase; +class UnifiedRecord; +class SystemDefinedPixelMap; +class SystemDefinedPixelMapNapi { +public: + static napi_value Constructor(napi_env env); + static void NewInstance(napi_env env, std::shared_ptr<UnifiedRecord> in, napi_value &out); + std::shared_ptr<SystemDefinedPixelMap> value_; + +private: + static napi_value New(napi_env env, napi_callback_info info); + static void Destructor(napi_env env, void *data, void *hint); + static SystemDefinedPixelMapNapi *GetSystemDefinedPixelMap( + napi_env env, napi_callback_info info, std::shared_ptr<ContextBase> ctxt); + + static napi_value GetRawData(napi_env env, napi_callback_info info); + static napi_value SetRawData(napi_env env, napi_callback_info info); +}; +} // namespace UDMF +} // namespace OHOS + +#endif // UDMF_SYSTEM_DEFINED_PIXELMAP_NAPI_H diff --git a/udmf/interfaces/jskits/data/system_defined_record_napi.h b/udmf/interfaces/jskits/data/system_defined_record_napi.h new file mode 100644 index 0000000000000000000000000000000000000000..8881c49cb0540e3f996e6bdbf656a36019341285 --- /dev/null +++ b/udmf/interfaces/jskits/data/system_defined_record_napi.h @@ -0,0 +1,45 @@ +/* + * 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 UDMF_SYSTEM_DEFINED_RECORD_NAPI_H +#define UDMF_SYSTEM_DEFINED_RECORD_NAPI_H + +#include <memory> + +#include "napi/native_api.h" +#include "napi/native_node_api.h" + +namespace OHOS { +namespace UDMF { +struct ContextBase; +class UnifiedRecord; +class SystemDefinedRecord; +class SystemDefinedRecordNapi { +public: + static napi_value Constructor(napi_env env); + static void NewInstance(napi_env env, std::shared_ptr<UnifiedRecord> in, napi_value &out); + static napi_value GetDetails(napi_env env, napi_callback_info info); + static napi_value SetDetails(napi_env env, napi_callback_info info); + std::shared_ptr<SystemDefinedRecord> value_; + +private: + static napi_value New(napi_env env, napi_callback_info info); + static void Destructor(napi_env env, void *data, void *hint); + static SystemDefinedRecordNapi *GetSystemDefinedRecord( + napi_env env, napi_callback_info info, std::shared_ptr<ContextBase> ctxt); +}; +} // namespace UDMF +} // namespace OHOS +#endif // UDMF_SYSTEM_DEFINED_RECORD_NAPI_H \ No newline at end of file diff --git a/udmf/interfaces/jskits/data/text_napi.h b/udmf/interfaces/jskits/data/text_napi.h new file mode 100644 index 0000000000000000000000000000000000000000..110f12d42236a50756a792527ed2c5d541e781f6 --- /dev/null +++ b/udmf/interfaces/jskits/data/text_napi.h @@ -0,0 +1,44 @@ +/* + * 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 UDMF_TEXT_NAPI_H +#define UDMF_TEXT_NAPI_H + +#include <memory> + +#include "napi/native_api.h" +#include "napi/native_node_api.h" + +namespace OHOS { +namespace UDMF { +struct ContextBase; +class UnifiedRecord; +class Text; +class TextNapi { +public: + static napi_value Constructor(napi_env env); + static void NewInstance(napi_env env, std::shared_ptr<UnifiedRecord> in, napi_value &out); + static napi_value GetDetails(napi_env env, napi_callback_info info); + static napi_value SetDetails(napi_env env, napi_callback_info info); + std::shared_ptr<Text> value_; + +private: + static napi_value New(napi_env env, napi_callback_info info); + static void Destructor(napi_env env, void *data, void *hint); + static TextNapi *GetText(napi_env env, napi_callback_info info, std::shared_ptr<ContextBase> ctxt); +}; +} // namespace UDMF +} // namespace OHOS +#endif // UDMF_TEXT_NAPI_H \ No newline at end of file diff --git a/udmf/interfaces/jskits/data/udmf_napi.h b/udmf/interfaces/jskits/data/udmf_napi.h new file mode 100644 index 0000000000000000000000000000000000000000..775f270cebfb8bc93bb5fd9ad9f71b672e3f3145 --- /dev/null +++ b/udmf/interfaces/jskits/data/udmf_napi.h @@ -0,0 +1,44 @@ +/* + * 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 UDMF_NAPI_H +#define UDMF_NAPI_H + +#include <string> + +#include "napi/native_api.h" +#include "napi/native_node_api.h" + +namespace OHOS { +namespace UDMF { +class UDMFNapi { +public: + static napi_value UDMFInit(napi_env env, napi_value exports); + +private: + static napi_value CreateUnifiedDataType(napi_env env); + static napi_value CreateIntention(napi_env env); + static napi_status SetNamedProperty( + napi_env env, napi_value &obj, const std::string &name, const std::string &value); + static napi_value InsertData(napi_env env, napi_callback_info info); + static napi_value UpdateData(napi_env env, napi_callback_info info); + static napi_value QueryData(napi_env env, napi_callback_info info); + static napi_value DeleteData(napi_env env, napi_callback_info info); + static napi_status GetNamedProperty(napi_env env, napi_value &obj, const std::string &key, std::string &value); +}; +} // namespace UDMF +} // namespace OHOS + +#endif // UDMF_NAPI_H diff --git a/udmf/interfaces/jskits/data/unified_data_napi.h b/udmf/interfaces/jskits/data/unified_data_napi.h new file mode 100644 index 0000000000000000000000000000000000000000..f9cd9beddaebe5cf0f2ed5b18f63e3a4e1fbf916 --- /dev/null +++ b/udmf/interfaces/jskits/data/unified_data_napi.h @@ -0,0 +1,44 @@ +/* + * 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 UDMF_UNIFIED_DATA_NAPI_H +#define UDMF_UNIFIED_DATA_NAPI_H + +#include <memory> + +#include "napi/native_api.h" + +namespace OHOS { +namespace UDMF { +class UnifiedData; +class UnifiedRecord; +class UnifiedDataNapi { +public: + static napi_value Constructor(napi_env env); + static void NewInstance(napi_env env, std::shared_ptr<UnifiedData> in, napi_value &out); + std::shared_ptr<UnifiedData> value_; + +private: + static napi_value New(napi_env env, napi_callback_info info); + static void Destructor(napi_env env, void *data, void *hint); + static UnifiedDataNapi *GetUnifiedData(napi_env env, napi_callback_info info); + + static napi_value AddRecord(napi_env env, napi_callback_info info); + static napi_value GetRecords(napi_env env, napi_callback_info info); + static void GetRecord(napi_env env, std::shared_ptr<UnifiedRecord> in, napi_value &out); +}; +} // namespace UDMF +} // namespace OHOS +#endif // UDMF_UNIFIED_DATA_NAPI_H diff --git a/udmf/interfaces/jskits/data/unified_record_napi.h b/udmf/interfaces/jskits/data/unified_record_napi.h new file mode 100644 index 0000000000000000000000000000000000000000..c3833df7ce39428d7c542d8eb440aaac3fad2be0 --- /dev/null +++ b/udmf/interfaces/jskits/data/unified_record_napi.h @@ -0,0 +1,42 @@ +/* + * 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 UDMF_UNIFIED_RECORD_NAPI_H +#define UDMF_UNIFIED_RECORD_NAPI_H + +#include <memory> + +#include "napi/native_api.h" +#include "napi/native_node_api.h" + +namespace OHOS { +namespace UDMF { +struct ContextBase; +class UnifiedRecord; +class UnifiedRecordNapi { +public: + static napi_value Constructor(napi_env env); + static napi_value GetType(napi_env env, napi_callback_info info); + std::shared_ptr<UnifiedRecord> value_; + +private: + static napi_value New(napi_env env, napi_callback_info info); + static void Destructor(napi_env env, void *nativeObject, void *finalize_hint); + static UnifiedRecordNapi *GetUnifiedRecord( + napi_env env, napi_callback_info info, std::shared_ptr<ContextBase> ctxt); +}; +} // namespace UDMF +} // namespace OHOS +#endif // UDMF_UNIFIED_RECORD_NAPI_H diff --git a/udmf/interfaces/jskits/data/video_napi.h b/udmf/interfaces/jskits/data/video_napi.h new file mode 100644 index 0000000000000000000000000000000000000000..a848f04d196e6be603e93cb6fe25ce4a84c88788 --- /dev/null +++ b/udmf/interfaces/jskits/data/video_napi.h @@ -0,0 +1,44 @@ +/* + * 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 UDMF_VIDEO_NAPI_H +#define UDMF_VIDEO_NAPI_H + +#include <memory> + +#include "napi/native_api.h" +#include "napi/native_node_api.h" + +namespace OHOS { +namespace UDMF { +struct ContextBase; +class UnifiedRecord; +class Video; +class VideoNapi { +public: + static napi_value Constructor(napi_env env); + static void NewInstance(napi_env env, std::shared_ptr<UnifiedRecord> in, napi_value &out); + std::shared_ptr<Video> value_; + +private: + static napi_value New(napi_env env, napi_callback_info info); + static void Destructor(napi_env env, void *data, void *hint); + static VideoNapi *GetVideo(napi_env env, napi_callback_info info, std::shared_ptr<ContextBase> ctxt); + static napi_value GetVideoUri(napi_env env, napi_callback_info info); + static napi_value SetVideoUri(napi_env env, napi_callback_info info); +}; +} // namespace UDMF +} // namespace OHOS +#endif // UDMF_VIDEO_NAPI_H diff --git a/udmf/interfaces/jskits/module/udmf_napi_module.cpp b/udmf/interfaces/jskits/module/udmf_napi_module.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fdc5c41d8b66329ba84198f4f601c6e4431d0eec --- /dev/null +++ b/udmf/interfaces/jskits/module/udmf_napi_module.cpp @@ -0,0 +1,98 @@ +/* + * 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 "application_defined_record_napi.h" +#include "audio_napi.h" +#include "file_napi.h" +#include "folder_napi.h" +#include "html_napi.h" +#include "image_napi.h" +#include "link_napi.h" +#include "logger.h" +#include "plain_text_napi.h" +#include "summary_napi.h" +#include "system_defined_appitem_napi.h" +#include "system_defined_form_napi.h" +#include "system_defined_pixelmap_napi.h" +#include "system_defined_record_napi.h" +#include "text_napi.h" +#include "udmf_napi.h" +#include "unified_data_napi.h" +#include "unified_record_napi.h" +#include "video_napi.h" + +using namespace OHOS::UDMF; + +EXTERN_C_START +static napi_value Init(napi_env env, napi_value exports) +{ + OHOS::UDMF::UDMFNapi::UDMFInit(env, exports); + + napi_status status = + napi_set_named_property(env, exports, "UnifiedData", OHOS::UDMF::UnifiedDataNapi::Constructor(env)); + LOG_INFO(UDMF_KITS_NAPI, "init UnifiedData %{public}d", status); + status = napi_set_named_property(env, exports, "Summary", OHOS::UDMF::SummaryNapi::Constructor(env)); + LOG_INFO(UDMF_KITS_NAPI, "init Summary %{public}d", status); + status = napi_set_named_property(env, exports, "UnifiedRecord", OHOS::UDMF::UnifiedRecordNapi::Constructor(env)); + LOG_INFO(UDMF_KITS_NAPI, "init UnifiedRecord %{public}d", status); + status = napi_set_named_property(env, exports, "Text", OHOS::UDMF::TextNapi::Constructor(env)); + LOG_INFO(UDMF_KITS_NAPI, "init Text %{public}d", status); + status = napi_set_named_property(env, exports, "PlainText", OHOS::UDMF::PlainTextNapi::Constructor(env)); + LOG_INFO(UDMF_KITS_NAPI, "init PlainText %{public}d", status); + status = napi_set_named_property(env, exports, "Hyperlink", OHOS::UDMF::LinkNapi::Constructor(env)); + LOG_INFO(UDMF_KITS_NAPI, "init Hyperlink %{public}d", status); + status = napi_set_named_property(env, exports, "HTML", OHOS::UDMF::HtmlNapi::Constructor(env)); + LOG_INFO(UDMF_KITS_NAPI, "init HTML %{public}d", status); + status = napi_set_named_property(env, exports, "File", OHOS::UDMF::FileNapi::Constructor(env)); + LOG_INFO(UDMF_KITS_NAPI, "init File %{public}d", status); + status = napi_set_named_property(env, exports, "Image", OHOS::UDMF::ImageNapi::Constructor(env)); + LOG_INFO(UDMF_KITS_NAPI, "init Image %{public}d", status); + status = napi_set_named_property(env, exports, "Video", OHOS::UDMF::VideoNapi::Constructor(env)); + LOG_INFO(UDMF_KITS_NAPI, "init Video %{public}d", status); + status = napi_set_named_property(env, exports, "Audio", OHOS::UDMF::AudioNapi::Constructor(env)); + LOG_INFO(UDMF_KITS_NAPI, "init Audio %{public}d", status); + status = napi_set_named_property(env, exports, "Folder", OHOS::UDMF::FolderNapi::Constructor(env)); + LOG_INFO(UDMF_KITS_NAPI, "init Folder %{public}d", status); + status = napi_set_named_property( + env, exports, "SystemDefinedRecord", OHOS::UDMF::SystemDefinedRecordNapi::Constructor(env)); + LOG_INFO(UDMF_KITS_NAPI, "init SystemDefinedRecord %{public}d", status); + status = napi_set_named_property( + env, exports, "SystemDefinedForm", OHOS::UDMF::SystemDefinedFormNapi::Constructor(env)); + LOG_INFO(UDMF_KITS_NAPI, "init SDForm %{public}d", status); + status = napi_set_named_property( + env, exports, "SystemDefinedAppItem", OHOS::UDMF::SystemDefinedAppItemNapi::Constructor(env)); + LOG_INFO(UDMF_KITS_NAPI, "init SDAppItem %{public}d", status); + status = napi_set_named_property( + env, exports, "SystemDefinedPixelMap", OHOS::UDMF::SystemDefinedPixelMapNapi::Constructor(env)); + LOG_INFO(UDMF_KITS_NAPI, "init SDPixelMap %{public}d", status); + status = napi_set_named_property( + env, exports, "ApplicationDefinedRecord", OHOS::UDMF::ApplicationDefinedRecordNapi::Constructor(env)); + LOG_INFO(UDMF_KITS_NAPI, "init ApplicationDefinedRecord %{public}d", status); + return exports; +} +EXTERN_C_END + +static napi_module _module = { .nm_version = 1, + .nm_flags = 0, + .nm_filename = nullptr, + .nm_register_func = Init, + .nm_modname = "data.UDMF", + .nm_priv = ((void *)0), + .reserved = { 0 } }; + +extern "C" __attribute__((constructor)) void RegisterUDMFUnifiedDataModule(void) +{ + napi_module_register(&_module); +} diff --git a/udmf/udmf.gni b/udmf/udmf.gni new file mode 100644 index 0000000000000000000000000000000000000000..a38869fa42703459d47dd083bbd32641ebe97a21 --- /dev/null +++ b/udmf/udmf.gni @@ -0,0 +1,44 @@ +# Copyright (c) 2022-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. + +third_party_path = "//third_party" + +aafwk_path = "//foundation/ability/ability_runtime" + +aafwk_inner_api_path = "${aafwk_path}/interfaces/inner_api" + +aafwk_kits_path = "${aafwk_path}/frameworks/kits" + +aafwk_napi_path = "${aafwk_path}/frameworks/js/napi" + +aafwk_service_path = "${aafwk_path}/services" + +access_kit_path = "//base/security/access_token" + +arkui_path = "//foundation/arkui" + +ddms_path = "//foundation/distributeddatamgr/datamgr_service" + +file_service_path = "//foundation/filemanagement/app_file_service" + +udmf_root_path = "//foundation/distributeddatamgr/udmf" + +udmf_framework_path = "${udmf_root_path}/framework" + +udmf_interfaces_path = "${udmf_root_path}/interfaces" + +udmf_service_path = "${udmf_root_path}/service" + +kv_store_path = "//foundation/distributeddatamgr/kv_store" + +developer_test_path = "//test/testfwk/developer_test"