From 4c039b17b9cd1c4becf23284bb2897ae2d2863cb Mon Sep 17 00:00:00 2001 From: wangkun Date: Tue, 26 Oct 2021 21:17:04 +0800 Subject: [PATCH] add KVManager JS Interface Signed-off-by: wangkun --- .../distributeddata/include/js_util.h | 1 + .../distributeddata/include/kv_manager.h | 22 ++ .../distributeddata/src/js_util.cpp | 14 ++ .../distributeddata/src/kv_manager.cpp | 232 +++++++++++++++++- 4 files changed, 268 insertions(+), 1 deletion(-) diff --git a/frameworks/jskitsimpl/distributeddata/include/js_util.h b/frameworks/jskitsimpl/distributeddata/include/js_util.h index 5e457ffbc..7dce00ad4 100644 --- a/frameworks/jskitsimpl/distributeddata/include/js_util.h +++ b/frameworks/jskitsimpl/distributeddata/include/js_util.h @@ -38,6 +38,7 @@ public: static napi_value Convert2JSNumber(napi_env env, const std::vector &data); static napi_value Convert2JSNotification(napi_env env, const DistributedKv::ChangeNotification ¬ification); static napi_value Convert2JSTupleArray(napi_env env, std::map &data); + static napi_value Convert2JSStoreIdList(napi_env env, const std::vector &idList); static DistributedKv::Options Convert2Options(napi_env env, napi_value jsOptions); static std::vector Convert2Vector(napi_env env, napi_value jsValue); static std::vector ConvertUint8Array2Vector(napi_env env, napi_value jsValue); diff --git a/frameworks/jskitsimpl/distributeddata/include/kv_manager.h b/frameworks/jskitsimpl/distributeddata/include/kv_manager.h index 90bd20c57..579ce523e 100644 --- a/frameworks/jskitsimpl/distributeddata/include/kv_manager.h +++ b/frameworks/jskitsimpl/distributeddata/include/kv_manager.h @@ -20,17 +20,39 @@ #include "napi/native_api.h" #include "napi/native_node_api.h" #include "distributed_kv_data_manager.h" +#include "kvstore_death_recipient.h" namespace OHOS::DistributedData { class KVManager { public: static napi_value CreateKVManager(napi_env env, napi_callback_info info); static napi_value GetKVStore(napi_env env, napi_callback_info info); + static napi_value CloseKVStore(napi_env env, napi_callback_info info); + static napi_value DeleteKVStore(napi_env env, napi_callback_info info); + static napi_value GetAllKVStoreId(napi_env env, napi_callback_info info); + static napi_value On(napi_env env, napi_callback_info info); + static napi_value Off(napi_env env, napi_callback_info info); private: static napi_value GetCtor(napi_env env); static napi_value Initialize(napi_env env, napi_callback_info info); DistributedKv::DistributedKvDataManager kvDataManager_ {}; std::string bundleName_ {}; + std::mutex deathMutex_ {}; + std::map> mapDeathRecipient_ {}; +}; + +class DeathRecipient : public DistributedKv::KvStoreDeathRecipient { +public: + DeathRecipient(napi_env env, napi_value callback); + virtual ~DeathRecipient(); + virtual void OnRemoteDied() override; +private: + struct EventDataWorker { + const DeathRecipient *deathRecipient = nullptr; + }; + napi_ref callback_ = nullptr; + napi_env env_; + uv_loop_s *loop_ = nullptr; }; } #endif // OHOS_KV_MANAGER_H diff --git a/frameworks/jskitsimpl/distributeddata/src/js_util.cpp b/frameworks/jskitsimpl/distributeddata/src/js_util.cpp index 902dcdd66..fd41b39b7 100644 --- a/frameworks/jskitsimpl/distributeddata/src/js_util.cpp +++ b/frameworks/jskitsimpl/distributeddata/src/js_util.cpp @@ -115,6 +115,20 @@ napi_value JSUtil::Convert2JSTupleArray(napi_env env, std::map &idList) +{ + napi_value result = nullptr; + napi_create_array_with_length(env, idList.size(), &result); + int index = 0; + for (const auto &id : idList) { + napi_value storeId = nullptr; + napi_create_object(env, &storeId); + storeId = Convert2JSString(env, id.storeId); + napi_set_element(env, result, index++, storeId); + } + return result; +} + std::vector JSUtil::Convert2StringArray(napi_env env, napi_value jsValue) { bool isArray = false; diff --git a/frameworks/jskitsimpl/distributeddata/src/kv_manager.cpp b/frameworks/jskitsimpl/distributeddata/src/kv_manager.cpp index 949a68adc..cf54931cb 100644 --- a/frameworks/jskitsimpl/distributeddata/src/kv_manager.cpp +++ b/frameworks/jskitsimpl/distributeddata/src/kv_manager.cpp @@ -16,6 +16,7 @@ #include "kv_manager.h" #include +#include #include "js_util.h" #include "distributed_kv_data_manager.h" #include "async_call.h" @@ -113,6 +114,189 @@ napi_value KVManager::GetKVStore(napi_env env, napi_callback_info info) return asyncCall.Call(env, exec); } +napi_value KVManager::CloseKVStore(napi_env env, napi_callback_info info) +{ + struct ContextInfo { + KVManager *proxy = nullptr; + napi_status status = napi_generic_failure; + std::string appId; + std::string storeId; + }; + auto ctxInfo = std::make_shared(); + auto input = [ctxInfo](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status { + ZLOGD("CloseKVStore parser to native params %{public}d!", static_cast(argc)); + NAPI_ASSERT_BASE(env, (argc == 3), "should 3 parameters!", napi_invalid_arg); + NAPI_ASSERT_BASE(env, self != nullptr, "self is nullptr", napi_invalid_arg); + NAPI_CALL_BASE(env, napi_unwrap(env, self, reinterpret_cast(&ctxInfo->proxy)), napi_invalid_arg); + NAPI_ASSERT_BASE(env, ctxInfo->proxy != nullptr, "there is no native kv store", napi_invalid_arg); + ctxInfo->appId = JSUtil::Convert2String(env, argv[0]); + ctxInfo->storeId = JSUtil::Convert2String(env, argv[1]); + return napi_ok; + }; + auto output = [ctxInfo](napi_env env, napi_value *result) -> napi_status { + ZLOGD("close kv store success!"); + return ctxInfo->status; + }; + auto exec = [ctxInfo](AsyncCall::Context *ctx) { + AppId appId { ctxInfo->appId }; + StoreId storeId { ctxInfo->storeId }; + Status status = ctxInfo->proxy->kvDataManager_.CloseKvStore(appId, storeId); + ZLOGD("CloseKVStore status:%{public}d", status); + if (status == Status::SUCCESS || status == Status::STORE_NOT_FOUND || + status == Status::STORE_NOT_OPEN) { + ctxInfo->status = napi_ok; + } + }; + auto context = std::make_shared(input, output); + // AsyncCallback at position 3 + AsyncCall asyncCall(env, info, context, 3); + return asyncCall.Call(env, exec); +} + +napi_value KVManager::DeleteKVStore(napi_env env, napi_callback_info info) +{ + struct ContextInfo { + KVManager *proxy = nullptr; + napi_status status = napi_generic_failure; + std::string appId; + std::string storeId; + }; + auto ctxInfo = std::make_shared(); + auto input = [ctxInfo](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status { + ZLOGD("DeleteKVStore parser to native params %{public}d!", static_cast(argc)); + NAPI_ASSERT_BASE(env, (argc == 2), "should 2 parameters!", napi_invalid_arg); + NAPI_ASSERT_BASE(env, self != nullptr, "self is nullptr", napi_invalid_arg); + NAPI_CALL_BASE(env, napi_unwrap(env, self, reinterpret_cast(&ctxInfo->proxy)), napi_invalid_arg); + NAPI_ASSERT_BASE(env, ctxInfo->proxy != nullptr, "there is no native kv store", napi_invalid_arg); + ctxInfo->appId = JSUtil::Convert2String(env, argv[0]); + ctxInfo->storeId = JSUtil::Convert2String(env, argv[1]); + return napi_ok; + }; + auto output = [ctxInfo](napi_env env, napi_value *result) -> napi_status { + ZLOGD("delete kv store success!"); + return ctxInfo->status; + }; + auto exec = [ctxInfo](AsyncCall::Context *ctx) { + AppId appId { ctxInfo->appId }; + StoreId storeId { ctxInfo->storeId }; + Status status = ctxInfo->proxy->kvDataManager_.DeleteKvStore(appId, storeId); + ZLOGD("DeleteKVStore status:%{public}d", status); + if (status == Status::SUCCESS || status == Status::STORE_NOT_FOUND) { + ctxInfo->status = napi_ok; + } + }; + auto context = std::make_shared(input, output); + // AsyncCallback at position 2 + AsyncCall asyncCall(env, info, context, 2); + return asyncCall.Call(env, exec); +} + +napi_value KVManager::GetAllKVStoreId(napi_env env, napi_callback_info info) +{ + struct ContextInfo { + KVManager *proxy = nullptr; + napi_status status = napi_generic_failure; + std::string appId; + std::vector storeIdList; + }; + auto ctxInfo = std::make_shared(); + auto input = [ctxInfo](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status { + ZLOGD("GetAllKVStoreId parser to native params %{public}d!", static_cast(argc)); + NAPI_ASSERT_BASE(env, (argc == 1), "should 1 parameters!", napi_invalid_arg); + NAPI_ASSERT_BASE(env, self != nullptr, "self is nullptr", napi_invalid_arg); + NAPI_CALL_BASE(env, napi_unwrap(env, self, reinterpret_cast(&ctxInfo->proxy)), napi_invalid_arg); + NAPI_ASSERT_BASE(env, ctxInfo->proxy != nullptr, "there is no native kv store", napi_invalid_arg); + ctxInfo->appId = JSUtil::Convert2String(env, argv[0]); + return napi_ok; + }; + auto output = [ctxInfo](napi_env env, napi_value *result) -> napi_status { + ZLOGD("GetAllKVStoreId success!"); + *result = JSUtil::Convert2JSStoreIdList(env, ctxInfo->storeIdList); + return ctxInfo->status; + }; + auto exec = [ctxInfo](AsyncCall::Context *ctx) { + AppId appId { ctxInfo->appId }; + ctxInfo->proxy->kvDataManager_.GetAllKvStoreId(appId, + [ctxInfo](Status status, std::vector &idList) { + ZLOGD("GetAllKVStoreId status:%{public}d, size:%{public}d", status, static_cast(idList.size())); + if (status == Status::SUCCESS) { + ctxInfo->status = napi_ok; + ctxInfo->storeIdList = idList; + } + }); + }; + auto context = std::make_shared(input, output); + // AsyncCallback at position 1 + AsyncCall asyncCall(env, info, context, 1); + return asyncCall.Call(env, exec); +} + +napi_value KVManager::On(napi_env env, napi_callback_info info) +{ + napi_value self = nullptr; + size_t argc = JSUtil::MAX_ARGC; + napi_value argv[JSUtil::MAX_ARGC] = {nullptr}; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &self, nullptr)); + // max num of argc is 2 + NAPI_ASSERT(env, argc == 2, "args is out of range"); + NAPI_ASSERT(env, self != nullptr, "self is nullptr"); + napi_valuetype type; + napi_typeof(env, argv[0], &type); + NAPI_ASSERT(env, type == napi_string, "event not string type"); + std::string event = JSUtil::Convert2String(env, argv[0]); + napi_valuetype valueType; + napi_typeof(env, argv[1], &valueType); + NAPI_ASSERT(env, valueType == napi_function, "callback is not a function"); + + KVManager *proxy = nullptr; + NAPI_CALL(env, napi_unwrap(env, self, reinterpret_cast(&proxy))); + NAPI_ASSERT(env, proxy != nullptr, "there is no native kv manager"); + + std::lock_guard lck(proxy->deathMutex_); + auto it = proxy->mapDeathRecipient_.find(argv[1]); + if (it != proxy->mapDeathRecipient_.end()) { + ZLOGD("KVManager::On callback already registe!"); + } else { + std::shared_ptr kvStoreDeathRecipientPtr = + std::make_shared(env, argv[1]); + proxy->kvDataManager_.RegisterKvStoreServiceDeathRecipient(kvStoreDeathRecipientPtr); + proxy->mapDeathRecipient_.insert(std::make_pair(argv[1], kvStoreDeathRecipientPtr)); + } + return nullptr; +} + +napi_value KVManager::Off(napi_env env, napi_callback_info info) +{ + napi_value self = nullptr; + size_t argc = JSUtil::MAX_ARGC; + napi_value argv[JSUtil::MAX_ARGC] = {nullptr}; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &self, nullptr)); + // max num of argc is 2 + NAPI_ASSERT(env, argc == 2, "args is out of range"); + NAPI_ASSERT(env, self != nullptr, "self is nullptr"); + napi_valuetype type; + napi_typeof(env, argv[0], &type); + NAPI_ASSERT(env, type == napi_string, "event not string type"); + std::string event = JSUtil::Convert2String(env, argv[0]); + napi_valuetype valueType; + napi_typeof(env, argv[1], &valueType); + NAPI_ASSERT(env, valueType == napi_function, "callback is not a function"); + + KVManager *proxy = nullptr; + NAPI_CALL(env, napi_unwrap(env, self, reinterpret_cast(&proxy))); + NAPI_ASSERT(env, proxy != nullptr, "there is no native kv manager"); + + std::lock_guard lck(proxy->deathMutex_); + auto it = proxy->mapDeathRecipient_.find(argv[1]); + if (it != proxy->mapDeathRecipient_.end()) { + proxy->kvDataManager_.UnRegisterKvStoreServiceDeathRecipient(it->second); + proxy->mapDeathRecipient_.erase(argv[1]); + } else { + ZLOGD("KVManager::On callback already unregiste!"); + } + return nullptr; +} + napi_value KVManager::GetCtor(napi_env env) { napi_value cons; @@ -122,7 +306,12 @@ napi_value KVManager::GetCtor(napi_env env) } napi_property_descriptor clzDes[] = { - DECLARE_NAPI_METHOD("getKVStore", GetKVStore) + DECLARE_NAPI_METHOD("getKVStore", GetKVStore), + DECLARE_NAPI_METHOD("closeKVStore", CloseKVStore), + DECLARE_NAPI_METHOD("deleteKVStore", DeleteKVStore), + DECLARE_NAPI_METHOD("getAllKVStoreId", GetAllKVStoreId), + DECLARE_NAPI_METHOD("on", On), + DECLARE_NAPI_METHOD("off", Off), }; NAPI_CALL(env, napi_define_class(env, "KVManager", NAPI_AUTO_LENGTH, Initialize, nullptr, sizeof(clzDes) / sizeof(napi_property_descriptor), clzDes, &cons)); @@ -143,6 +332,11 @@ napi_value KVManager::Initialize(napi_env env, napi_callback_info info) proxy->bundleName_ = JSUtil::Convert2String(env, bundle); auto finalize = [](napi_env env, void* data, void* hint) { KVManager *proxy = reinterpret_cast(data); + for (auto &it : proxy->mapDeathRecipient_) { + proxy->kvDataManager_.UnRegisterKvStoreServiceDeathRecipient(it.second); + } + std::lock_guard lck(proxy->deathMutex_); + proxy->mapDeathRecipient_.clear(); delete proxy; }; if (napi_wrap(env, self, proxy, finalize, nullptr, nullptr) != napi_ok) { @@ -151,4 +345,40 @@ napi_value KVManager::Initialize(napi_env env, napi_callback_info info) } return self; } + +DeathRecipient::DeathRecipient(napi_env env, napi_value callback) + : env_(env) +{ + napi_create_reference(env, callback, 1, &callback_); + napi_get_uv_event_loop(env, &loop_); +} + +DeathRecipient::~DeathRecipient() +{ + napi_delete_reference(env_, callback_); +} + +void DeathRecipient::OnRemoteDied() +{ + EventDataWorker *eventDataWorker = new EventDataWorker(); + eventDataWorker->deathRecipient = this; + uv_work_t *work = new uv_work_t; + work->data = eventDataWorker; + uv_queue_work(loop_, work, + [](uv_work_t *work) {}, + [](uv_work_t *work, int status) { + EventDataWorker *eventDataInner = reinterpret_cast(work->data); + napi_value callback = nullptr; + napi_get_reference_value(eventDataInner->deathRecipient->env_, + eventDataInner->deathRecipient->callback_, &callback); + napi_value global = nullptr; + napi_value result = nullptr; + napi_get_global(eventDataInner->deathRecipient->env_, &global); + napi_call_function(eventDataInner->deathRecipient->env_, global, callback, 0, nullptr, &result); + delete eventDataInner; + eventDataInner = nullptr; + delete work; + work = nullptr; + }); +} } -- Gitee