diff --git a/frameworks/innerkitsimpl/distributeddatafwk/src/data_query.cpp b/frameworks/innerkitsimpl/distributeddatafwk/src/data_query.cpp index 897a63bb44290ef2748f2a38e91b8b3d4f7c23a9..6ff0a512d2d90d4ca95e61557a76a8a51aa9992a 100755 --- a/frameworks/innerkitsimpl/distributeddatafwk/src/data_query.cpp +++ b/frameworks/innerkitsimpl/distributeddatafwk/src/data_query.cpp @@ -509,6 +509,21 @@ DataQuery& DataQuery::KeyPrefix(const std::string &prefix) return *this; } +DataQuery& DataQuery::DeviceId(const std::string &deviceId) +{ + std::string device = deviceId; + if (ValidateField(device)) { + std::string start; + start.append(SPACE); + start.append(DEVICE_ID); + start.append(SPACE); + EscapeSpace(device); + start.append(device); + str_ = start + str_; // start with diveceId + } + return *this; +} + DataQuery& DataQuery::SetSuggestIndex(const std::string &index) { std::string suggestIndex = index; diff --git a/frameworks/innerkitsimpl/distributeddatafwk/src/single_kvstore_client.cpp b/frameworks/innerkitsimpl/distributeddatafwk/src/single_kvstore_client.cpp index aa7a82de01cc06914ae7890ddda99c9858f2c856..6ee6c46bd36f91752613a17efe94f47048e97e2d 100755 --- a/frameworks/innerkitsimpl/distributeddatafwk/src/single_kvstore_client.cpp +++ b/frameworks/innerkitsimpl/distributeddatafwk/src/single_kvstore_client.cpp @@ -387,7 +387,7 @@ Status SingleKvStoreClient::Rollback() Status SingleKvStoreClient::SetSyncParam(const KvSyncParam &syncParam) { - KvParam input(TransferTypeToByteArray(syncParam)); + KvParam input(TransferTypeToByteArray(syncParam.allowedDelayMs)); KvParam output; return Control(KvControlCmd::SET_SYNC_PARAM, input, output); } @@ -400,8 +400,8 @@ Status SingleKvStoreClient::GetSyncParam(KvSyncParam &syncParam) if (ret != Status::SUCCESS) { return ret; } - if (output.Size() == sizeof(syncParam)) { - syncParam = TransferByteArrayToType(output.Data()); + if (output.Size() == sizeof(uint32_t)) { + syncParam.allowedDelayMs = TransferByteArrayToType(output.Data()); return Status::SUCCESS; } return Status::ERROR; @@ -413,7 +413,9 @@ Status SingleKvStoreClient::Control(KvControlCmd cmd, const KvParam &inputParam, if (kvStoreProxy_ != nullptr) { sptr kvParam; Status status = kvStoreProxy_->Control(cmd, inputParam, kvParam); - output = *kvParam; + if ((status == Status::SUCCESS) && (kvParam != nullptr)) { + output = *kvParam; + } return status; } ZLOGE("singleKvstore proxy is nullptr."); diff --git a/frameworks/jskitsimpl/distributeddata/include/async_call.h b/frameworks/jskitsimpl/distributeddata/include/async_call.h deleted file mode 100644 index 892ff9c3b615c83860ca20afcb5fbabb6eede698..0000000000000000000000000000000000000000 --- a/frameworks/jskitsimpl/distributeddata/include/async_call.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (c) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef OHOS_ASYNC_CALL_H -#define OHOS_ASYNC_CALL_H - -#include -#include -#include "js_util.h" -#include "napi/native_common.h" -#include "napi/native_api.h" -#include "napi/native_node_api.h" - -namespace OHOS::DistributedData { -class AsyncCall final { -public: - class Context { - public: - using InputAction = std::function; - using OutputAction = std::function; - using ExecAction = std::function; - Context(InputAction input, OutputAction output): input_(std::move(input)), output_(std::move(output)) {}; - virtual ~Context() {}; - void SetAction(InputAction input, OutputAction output = nullptr) - { - input_ = input; - output_ = output; - } - - void SetAction(OutputAction output) - { - SetAction(nullptr, std::move(output)); - } - - virtual napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) - { - if (input_ == nullptr) { - return napi_ok; - } - return input_(env, argc, argv, self); - } - - virtual napi_status operator()(napi_env env, napi_value *result) - { - if (output_ == nullptr) { - *result = nullptr; - return napi_ok; - } - return output_(env, result); - } - - virtual void Exec() - { - if (exec_ == nullptr) { - return; - } - exec_(this); - }; - protected: - friend class AsyncCall; - InputAction input_ = nullptr; - OutputAction output_ = nullptr; - ExecAction exec_ = nullptr; - }; - - // The default AsyncCallback in the parameters is at the end position. - static constexpr size_t ASYNC_DEFAULT_POS = -1; - AsyncCall(napi_env env, napi_callback_info info, std::shared_ptr context, size_t pos = ASYNC_DEFAULT_POS); - ~AsyncCall(); - napi_value Call(napi_env env, Context::ExecAction exec = nullptr); - napi_value SyncCall(napi_env env, Context::ExecAction exec = nullptr); -private: - enum { - ARG_ERROR, - ARG_DATA, - ARG_BUTT - }; - static void OnExecute(napi_env env, void *data); - static void OnComplete(napi_env env, napi_status status, void *data); - struct AsyncContext { - std::shared_ptr ctx = nullptr; - napi_ref callback = nullptr; - napi_ref self = nullptr; - napi_deferred defer = nullptr; - napi_async_work work = nullptr; - }; - static void DeleteContext(napi_env env, AsyncContext *context); - - AsyncContext *context_ = nullptr; - napi_env env_ = nullptr; -}; -} - -#endif // OHOS_ASYNC_CALL_H diff --git a/frameworks/jskitsimpl/distributeddata/include/js_device_kv_store.h b/frameworks/jskitsimpl/distributeddata/include/js_device_kv_store.h new file mode 100644 index 0000000000000000000000000000000000000000..4ad679afaf243fecab7bae47e26348591e48eb5c --- /dev/null +++ b/frameworks/jskitsimpl/distributeddata/include/js_device_kv_store.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef OHOS_DEVICE_KV_STORE_H +#define OHOS_DEVICE_KV_STORE_H +#include "js_kv_manager.h" +#include "js_kv_store.h" +#include "napi_queue.h" + +namespace OHOS::DistributedData { +class JsDeviceKVStore : public JsKVStore { +public: + JsDeviceKVStore(const std::string& storeId); + ~JsDeviceKVStore() = default; + + static napi_value Constructor(napi_env env); + + static napi_value New(napi_env env, napi_callback_info info); + +private: + static napi_value Get(napi_env env, napi_callback_info info); + static napi_value GetEntries(napi_env env, napi_callback_info info); + static napi_value GetResultSet(napi_env env, napi_callback_info info); + static napi_value CloseResultSet(napi_env env, napi_callback_info info); + static napi_value GetResultSize(napi_env env, napi_callback_info info); + static napi_value RemoveDeviceData(napi_env env, napi_callback_info info); + static napi_value Sync(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); +}; +} +#endif // OHOS_DEVICE_KV_STORE_H diff --git a/frameworks/jskitsimpl/distributeddata/include/js_field_node.h b/frameworks/jskitsimpl/distributeddata/include/js_field_node.h new file mode 100644 index 0000000000000000000000000000000000000000..3c5deb41290f45b1514849081c9ab2ffec955caa --- /dev/null +++ b/frameworks/jskitsimpl/distributeddata/include/js_field_node.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef OHOS_FIELD_NODE_H +#define OHOS_FIELD_NODE_H +#include +#include + +#include "js_util.h" +#include "napi_queue.h" + +namespace OHOS::DistributedData { +class JsFieldNode { +public: + JsFieldNode(const std::string& fName); + ~JsFieldNode() = default; + + std::string GetFieldName(); + std::string GetValueForJson(); + + static napi_value Constructor(napi_env env); + + static napi_value New(napi_env env, napi_callback_info info); + +private: + static napi_value AppendChild(napi_env env, napi_callback_info info); + static napi_value ToJson(napi_env env, napi_callback_info info); + static napi_value GetDefaultValue(napi_env env, napi_callback_info info); + static napi_value SetDefaultValue(napi_env env, napi_callback_info info); + static napi_value GetNullable(napi_env env, napi_callback_info info); + static napi_value SetNullable(napi_env env, napi_callback_info info); + static napi_value GetValueType(napi_env env, napi_callback_info info); + static napi_value SetValueType(napi_env env, napi_callback_info info); + + std::string Dump(); + std::string ValueToString(JSUtil::KvStoreVariant value); + std::string ValueTypeToString(uint32_t type); + + std::list fields; + std::string fieldName; + uint32_t valueType = JSUtil::INVALID; + JSUtil::KvStoreVariant defaultValue; + bool isWithDefaultValue = false; + bool isNullable = false; +}; +} +#endif // OHOS_FIELD_NODE_H diff --git a/frameworks/jskitsimpl/distributeddata/include/js_kv_manager.h b/frameworks/jskitsimpl/distributeddata/include/js_kv_manager.h new file mode 100644 index 0000000000000000000000000000000000000000..fab69a69ed0592eac52e440db849e2c77cfd7a97 --- /dev/null +++ b/frameworks/jskitsimpl/distributeddata/include/js_kv_manager.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef OHOS_KV_MANAGER_H +#define OHOS_KV_MANAGER_H +#include "distributed_kv_data_manager.h" +#include "kvstore_death_recipient.h" +#include "napi_queue.h" +#include "uv_queue.h" + +namespace OHOS::DistributedData { +class JsKVManager { +public: + JsKVManager(const std::string &bundleName); + ~JsKVManager(); + + static napi_value CreateKVManager(napi_env env, napi_callback_info info); + + static napi_value Constructor(napi_env env); + + static napi_value New(napi_env env, napi_callback_info info); + +private: + 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: + DistributedKv::DistributedKvDataManager kvDataManager_ {}; + std::string bundleName_ {}; + std::mutex deathMutex_ {}; + std::list> deathRecipient_ {}; +}; + +class DeathRecipient : public DistributedKv::KvStoreDeathRecipient, public UvQueue { +public: + DeathRecipient(napi_env env, napi_value callback); + virtual ~DeathRecipient() = default; + + virtual void OnRemoteDied() override; +}; +} +#endif // OHOS_KV_MANAGER_H diff --git a/frameworks/jskitsimpl/distributeddata/include/single_kv_store.h b/frameworks/jskitsimpl/distributeddata/include/js_kv_store.h similarity index 31% rename from frameworks/jskitsimpl/distributeddata/include/single_kv_store.h rename to frameworks/jskitsimpl/distributeddata/include/js_kv_store.h index f9a2737513cbf51b7c71d0f8713868884ed279de..58c33f7354b4f2e3ede1bbb57007617833f6ebbb 100644 --- a/frameworks/jskitsimpl/distributeddata/include/single_kv_store.h +++ b/frameworks/jskitsimpl/distributeddata/include/js_kv_store.h @@ -12,106 +12,92 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#ifndef OHOS_SINGLE_KV_STORE_H -#define OHOS_SINGLE_KV_STORE_H -#include -#include "napi/native_common.h" -#include "napi/native_api.h" -#include "napi/native_node_api.h" -#include "kv_manager.h" -#include "async_call.h" +#ifndef OHOS_KV_STORE_H +#define OHOS_KV_STORE_H +#include "napi_queue.h" #include "single_kvstore.h" +#include "uv_queue.h" namespace OHOS::DistributedData { -class SingleKVStore final { +enum { + /* exported js SubscribeType is (DistributedKv::SubscribeType-1) */ + SUBSCRIBE_LOCAL = 0, /* i.e. SubscribeType::SUBSCRIBE_TYPE_LOCAL-1 */ + SUBSCRIBE_REMOTE = 1, /* i.e. SubscribeType::SUBSCRIBE_TYPE_REMOTE-1 */ + SUBSCRIBE_LOCAL_REMOTE = 2, /* i.e. SubscribeType::SUBSCRIBE_TYPE_ALL--1 */ + SUBSCRIBE_COUNT = 3 +}; + +/* [NOTES] + * OHOS::DistributedData::JsKVStore is NOT related to DistributedKv::KvStore!!! + * OHOS::DistributedData::JsKVStore is wrapped for DistributedKv::SingleKvStore... + */ +class JsKVStore { public: - SingleKVStore() = default; - ~SingleKVStore(); - SingleKVStore &operator=(std::shared_ptr &&singleKvStore); - bool operator==(const std::shared_ptr &singleKvStore); - static napi_value GetCtor(napi_env env); - static napi_value OnEvent(napi_env env, napi_callback_info info); - static napi_value Sync(napi_env env, napi_callback_info info); + JsKVStore(const std::string& storeId); + virtual ~JsKVStore(); + + void SetNative(std::shared_ptr& kvStore); + std::shared_ptr& GetNative(); + + static bool IsInstanceOf(napi_env env, napi_value obj, const std::string& storeId, napi_value constructor); + + /* public static members */ static napi_value Put(napi_env env, napi_callback_info info); - static napi_value Get(napi_env env, napi_callback_info info); static napi_value Delete(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); + static napi_value PutBatch(napi_env env, napi_callback_info info); + static napi_value DeleteBatch(napi_env env, napi_callback_info info); + static napi_value StartTransaction(napi_env env, napi_callback_info info); + static napi_value Commit(napi_env env, napi_callback_info info); + static napi_value Rollback(napi_env env, napi_callback_info info); + static napi_value EnableSync(napi_env env, napi_callback_info info); + static napi_value SetSyncRange(napi_env env, napi_callback_info info); + private: - enum JSSubscribeType { - SUBSCRIBE_LOCAL = 0, - SUBSCRIBE_REMOTE = 1, - SUBSCRIBE_ALL = 2, - }; - - struct ContextInfo : public AsyncCall::Context { - SingleKVStore *proxy = nullptr; - std::string key; - std::vector value; - napi_status status = napi_generic_failure; - ContextInfo() : Context(nullptr, nullptr) { }; - ContextInfo(InputAction input, OutputAction output) : Context(std::move(input), std::move(output)) { }; - virtual ~ContextInfo() {}; - - napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) override - { - NAPI_ASSERT_BASE(env, self != nullptr, "self is nullptr", napi_invalid_arg); - NAPI_CALL_BASE(env, napi_unwrap(env, self, reinterpret_cast(&proxy)), napi_invalid_arg); - NAPI_ASSERT_BASE(env, proxy != nullptr, "there is no native kv store", napi_invalid_arg); - return Context::operator()(env, argc, argv, self); - } - napi_status operator()(napi_env env, napi_value *result) override - { - if (status != napi_ok) { - return status; - } - return Context::operator()(env, result); - } - }; - - using Exec = std::function; - static napi_value Initialize(napi_env env, napi_callback_info info); - - static napi_status OnDataChange(napi_env env, size_t argc, napi_value *argv, napi_value self, napi_value *result); - static napi_status OnSyncComplete(napi_env env, size_t argc, napi_value *argv, napi_value self, napi_value *result); - static std::map eventHandlers_; + /* private static members */ + static napi_status OnDataChange(napi_env env, size_t argc, napi_value* argv, JsKVStore* kvStore); + static napi_status OffDataChange(napi_env env, size_t argc, napi_value* argv, JsKVStore* kvStore); + static napi_status OnSyncComplete(napi_env env, size_t argc, napi_value* argv, JsKVStore* kvStore); + static napi_status OffSyncComplete(napi_env env, size_t argc, napi_value* argv, JsKVStore* kvStore); + + /* private non-static members */ + napi_status Subscribe(uint8_t type, std::shared_ptr observer); + napi_status UnSubscribe(uint8_t type, std::shared_ptr observer); + + napi_status RegisterSyncCallback(std::shared_ptr sync); + napi_status UnRegisterSyncCallback(); + + /* private non-static members */ std::shared_ptr kvStore_ = nullptr; + std::string storeId_; + + using Exec = std::function; + static std::map onEventHandlers_; + static std::map offEventHandlers_; + std::shared_ptr syncObserver_ = nullptr; - std::shared_ptr dataObserver_[SUBSCRIBE_ALL + 1]; + std::mutex listMutex_ {}; + std::list> dataObserver_[SUBSCRIBE_COUNT]; }; -class DataObserver : public DistributedKv::KvStoreObserver { +class DataObserver : public DistributedKv::KvStoreObserver, public UvQueue { public: DataObserver(napi_env env, napi_value callback); - virtual ~DataObserver(); - void OnChange(const DistributedKv::ChangeNotification ¬ification, - std::shared_ptr snapshot) override; - void OnChange(const DistributedKv::ChangeNotification ¬ification) override; -private: - struct EventDataWorker { - const DataObserver *observer = nullptr; - const DistributedKv::ChangeNotification data; - EventDataWorker(const DataObserver * const & observerIn, const DistributedKv::ChangeNotification &dataIn) - : observer(observerIn), - data(dataIn) {} - }; - napi_ref callback_ = nullptr; - napi_env env_; - uv_loop_s *loop_ = nullptr; + virtual ~DataObserver() = default; + + void OnChange(const DistributedKv::ChangeNotification& notification, + std::shared_ptr snapshot) override; + void OnChange(const DistributedKv::ChangeNotification& notification) override; }; -class SyncObserver : public DistributedKv::KvStoreSyncCallback { +class SyncObserver : public DistributedKv::KvStoreSyncCallback, public UvQueue { public: SyncObserver(napi_env env, napi_value callback); - virtual ~SyncObserver(); - void SyncCompleted(const std::map &results) override; -private: - struct EventDataWorker { - const SyncObserver *observer = nullptr; - std::map data; - }; - napi_ref callback_ = nullptr; - napi_env env_; - uv_loop_s *loop_ = nullptr; + virtual ~SyncObserver() = default; + + void SyncCompleted(const std::map& results) override; }; -} +} // namespace OHOS::DistributedData #endif // OHOS_SINGLE_KV_STORE_H diff --git a/frameworks/jskitsimpl/distributeddata/include/js_kv_store_resultset.h b/frameworks/jskitsimpl/distributeddata/include/js_kv_store_resultset.h new file mode 100644 index 0000000000000000000000000000000000000000..45ba972df6a8a7a7db828bc91c4521bcbfeb6b94 --- /dev/null +++ b/frameworks/jskitsimpl/distributeddata/include/js_kv_store_resultset.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef OHOS_KV_STORE_RESELTSET_H +#define OHOS_KV_STORE_RESELTSET_H +#include +#include "napi_queue.h" +#include "kvstore_result_set.h" + +namespace OHOS::DistributedData { +class JsKVStoreResultSet { +public: + JsKVStoreResultSet() = default; + ~JsKVStoreResultSet() = default; + + void SetNative(std::shared_ptr& resultSet); + std::shared_ptr& GetNative(); + + static napi_value Constructor(napi_env env); + static napi_value New(napi_env env, napi_callback_info info); +private: + static napi_value GetCount(napi_env env, napi_callback_info info); + static napi_value GetPosition(napi_env env, napi_callback_info info); + static napi_value MoveToFirst(napi_env env, napi_callback_info info); + static napi_value MoveToLast(napi_env env, napi_callback_info info); + static napi_value MoveToNext(napi_env env, napi_callback_info info); + static napi_value MoveToPrevious(napi_env env, napi_callback_info info); + static napi_value Move(napi_env env, napi_callback_info info); + static napi_value MoveToPosition(napi_env env, napi_callback_info info); + static napi_value IsFirst(napi_env env, napi_callback_info info); + static napi_value IsLast(napi_env env, napi_callback_info info); + static napi_value IsBeforeFirst(napi_env env, napi_callback_info info); + static napi_value IsAfterLast(napi_env env, napi_callback_info info); + static napi_value GetEntry(napi_env env, napi_callback_info info); + + std::shared_ptr resultSet_ = nullptr; +}; +} +#endif // OHOS_KV_STORE_RESELTSET_H + diff --git a/frameworks/jskitsimpl/distributeddata/include/js_query.h b/frameworks/jskitsimpl/distributeddata/include/js_query.h new file mode 100644 index 0000000000000000000000000000000000000000..528cd32c31219bfe08e0983404df9ba292b8ddc3 --- /dev/null +++ b/frameworks/jskitsimpl/distributeddata/include/js_query.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef OHOS_QUERY_H +#define OHOS_QUERY_H +#include + +#include "data_query.h" +#include "napi_queue.h" + +namespace OHOS::DistributedData { +class JsQuery { +public: + JsQuery() = default; + ~JsQuery() = default; + + DistributedKv::DataQuery& GetNative(); + + static napi_value Constructor(napi_env env); + + static napi_value New(napi_env env, napi_callback_info info); + +private: + static napi_value Reset(napi_env env, napi_callback_info info); + static napi_value EqualTo(napi_env env, napi_callback_info info); + static napi_value NotEqualTo(napi_env env, napi_callback_info info); + static napi_value GreaterThan(napi_env env, napi_callback_info info); + static napi_value LessThan(napi_env env, napi_callback_info info); + static napi_value GreaterThanOrEqualTo(napi_env env, napi_callback_info info); + static napi_value LessThanOrEqualTo(napi_env env, napi_callback_info info); + static napi_value IsNull(napi_env env, napi_callback_info info); + static napi_value InNumber(napi_env env, napi_callback_info info); + static napi_value InString(napi_env env, napi_callback_info info); + static napi_value NotInNumber(napi_env env, napi_callback_info info); + static napi_value NotInString(napi_env env, napi_callback_info info); + static napi_value Like(napi_env env, napi_callback_info info); + static napi_value Unlike(napi_env env, napi_callback_info info); + static napi_value And(napi_env env, napi_callback_info info); + static napi_value Or(napi_env env, napi_callback_info info); + static napi_value OrderByAsc(napi_env env, napi_callback_info info); + static napi_value OrderByDesc(napi_env env, napi_callback_info info); + static napi_value Limit(napi_env env, napi_callback_info info); + static napi_value IsNotNull(napi_env env, napi_callback_info info); + static napi_value BeginGroup(napi_env env, napi_callback_info info); + static napi_value EndGroup(napi_env env, napi_callback_info info); + static napi_value PrefixKey(napi_env env, napi_callback_info info); + static napi_value SetSuggestIndex(napi_env env, napi_callback_info info); + static napi_value DeviceId(napi_env env, napi_callback_info info); + static napi_value GetSqlLike(napi_env env, napi_callback_info info); + +private: + DistributedKv::DataQuery query_; +}; +} +#endif // OHOS_QUERY_H diff --git a/frameworks/jskitsimpl/distributeddata/include/js_schema.h b/frameworks/jskitsimpl/distributeddata/include/js_schema.h new file mode 100644 index 0000000000000000000000000000000000000000..1d1eee275b4a1c2247c5c4bd3f5c396a0a7ba694 --- /dev/null +++ b/frameworks/jskitsimpl/distributeddata/include/js_schema.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef OHOS_SCHEMA_H +#define OHOS_SCHEMA_H +#include + +#include "js_util.h" +#include "js_field_node.h" +#include "napi_queue.h" + +namespace OHOS::DistributedData { +class JsSchema { +public: + JsSchema(napi_env env); + ~JsSchema(); + + static napi_value Constructor(napi_env env); + + static napi_value New(napi_env env, napi_callback_info info); +private: + static napi_value ToJson(napi_env env, napi_callback_info info); + static napi_value GetRootNode(napi_env env, napi_callback_info info); + static napi_value SetRootNode(napi_env env, napi_callback_info info); + static napi_value GetMode(napi_env env, napi_callback_info info); + static napi_value SetMode(napi_env env, napi_callback_info info); + static napi_value GetSkip(napi_env env, napi_callback_info info); + static napi_value SetSkip(napi_env env, napi_callback_info info); + static napi_value GetIndexes(napi_env env, napi_callback_info info); + static napi_value SetIndexes(napi_env env, napi_callback_info info); + + std::string Dump(); + + enum { + SCHEMA_MODE_SLOPPY, + SCHEMA_MODE_STRICT, + }; + JsFieldNode* rootNode = nullptr; + napi_env env = nullptr; // manage the root. set/get. + napi_ref ref = nullptr; // manage the root. set/get. + + std::vector indexes; + uint32_t mode = SCHEMA_MODE_SLOPPY; + uint32_t skip = 0; +}; +} +#endif // OHOS_SCHEMA_H diff --git a/frameworks/jskitsimpl/distributeddata/include/js_single_kv_store.h b/frameworks/jskitsimpl/distributeddata/include/js_single_kv_store.h new file mode 100644 index 0000000000000000000000000000000000000000..c1fb1aef3eaa90d0940424651134a38e6b66cba7 --- /dev/null +++ b/frameworks/jskitsimpl/distributeddata/include/js_single_kv_store.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef OHOS_SINGLE_KV_STORE_H +#define OHOS_SINGLE_KV_STORE_H +#include "js_kv_manager.h" +#include "js_kv_store.h" +#include "napi_queue.h" + +namespace OHOS::DistributedData { +class JsSingleKVStore : public JsKVStore { +public: + JsSingleKVStore(const std::string& storeId); + ~JsSingleKVStore() = default; + + static napi_value Constructor(napi_env env); + + static napi_value New(napi_env env, napi_callback_info info); +private: + static napi_value Get(napi_env env, napi_callback_info info); + static napi_value GetEntries(napi_env env, napi_callback_info info); + static napi_value GetResultSet(napi_env env, napi_callback_info info); + static napi_value CloseResultSet(napi_env env, napi_callback_info info); + static napi_value GetResultSize(napi_env env, napi_callback_info info); + static napi_value RemoveDeviceData(napi_env env, napi_callback_info info); + static napi_value Sync(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); + static napi_value SetSyncParam(napi_env env, napi_callback_info info); + static napi_value GetSecurityLevel(napi_env env, napi_callback_info info); +}; +} +#endif // OHOS_SINGLE_KV_STORE_H diff --git a/frameworks/jskitsimpl/distributeddata/include/js_util.h b/frameworks/jskitsimpl/distributeddata/include/js_util.h index c47682a4aa9af7b89741cb6b73269bcef5f422c8..e7dd53f82fed9a2cbecedf6f1e2a62829e08aa39 100644 --- a/frameworks/jskitsimpl/distributeddata/include/js_util.h +++ b/frameworks/jskitsimpl/distributeddata/include/js_util.h @@ -14,59 +14,152 @@ */ #ifndef OHOS_JS_UTIL_H #define OHOS_JS_UTIL_H - #include -#include #include -#include "napi/native_common.h" +#include + +#include "change_notification.h" #include "napi/native_api.h" +#include "napi/native_common.h" #include "napi/native_node_api.h" -#include "types.h" -#define DECLARE_NAPI_METHOD(name, func) { name, 0, func, 0, 0, 0, napi_default, 0 } namespace OHOS::DistributedData { -class JSUtil { +using namespace OHOS::DistributedKv; + +class JSUtil final { public: - static constexpr int32_t MAX_ARGC = 6; - static constexpr int32_t MAX_NUMBER_BYTES = 8; - static constexpr int32_t MAX_LEN = 4096; - - static std::string Convert2String(napi_env env, napi_value jsString); - static napi_value Convert2JSString(napi_env env, const std::string &cString); - static napi_value Convert2JSString(napi_env env, const std::vector &key); - static napi_value Convert2JSValue(napi_env env, const std::vector &data); - 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 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); - static std::vector ConvertString2Vector(napi_env env, napi_value jsValue); - static std::vector ConvertNumber2Vector(napi_env env, napi_value jsValue); - static std::vector ConvertBool2Vector(napi_env env, napi_value jsValue); - static std::vector Convert2StringArray(napi_env env, napi_value jsValue); -private: - static napi_value GetJSEntries(napi_env env, const std::list &entries); - static napi_value GetJSEntries(napi_env env, const std::vector &entries); - enum ValueType : uint8_t { - /** Indicates that the value type is string. */ + enum { + /* Blob's first byte is the blob's data ValueType */ STRING = 0, - /** Indicates that the value type is int. */ INTEGER = 1, - /** Indicates that the value type is float. */ FLOAT = 2, - /** Indicates that the value type is byte array. */ BYTE_ARRAY = 3, - /** Indicates that the value type is boolean. */ BOOLEAN = 4, - /** Indicates that the value type is double. */ DOUBLE = 5, + INVALID = 255 + }; + + /* for kvStore Put/Get : boolean|string|number|Uint8Array */ + using KvStoreVariant = std::variant, bool, double>; + static KvStoreVariant Blob2VariantValue(const Blob& blob); + static Blob VariantValue2Blob(const KvStoreVariant& value); + + /* for query value related : number|string|boolean */ + using QueryVariant = std::variant; + + /* 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 <-> uint32_t */ + static napi_status GetValue(napi_env env, napi_value in, uint32_t& out); + static napi_status SetValue(napi_env env, const uint32_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 <-> 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 <-> KvStoreVariant */ + static napi_status GetValue(napi_env env, napi_value in, KvStoreVariant& out); + static napi_status SetValue(napi_env env, const KvStoreVariant& in, napi_value& out); + + /* napi_value <-> QueryVariant */ + static napi_status GetValue(napi_env env, napi_value in, QueryVariant& out); + static napi_status SetValue(napi_env env, const QueryVariant& in, napi_value& out); + + /* napi_value <-> std::vector */ + static napi_status GetValue(napi_env env, napi_value in, std::vector& out); + static napi_status SetValue(napi_env env, const std::vector& in, napi_value& out); - INVALID = 255, + /* napi_value <-> std::vector */ + static napi_status GetValue(napi_env env, napi_value in, std::vector& out); + static napi_status SetValue(napi_env env, const std::vector& in, napi_value& out); + + /* napi_value <-> std::vector */ + static napi_status GetValue(napi_env env, napi_value in, std::vector& out); + static napi_status SetValue(napi_env env, const std::vector& in, napi_value& out); + + /* napi_value <-> std::vector */ + static napi_status GetValue(napi_env env, napi_value in, std::vector& out); + static napi_status SetValue(napi_env env, const std::vector& in, napi_value& out); + + /* napi_value <-> std::vector */ + static napi_status GetValue(napi_env env, napi_value in, std::vector& out); + static napi_status SetValue(napi_env env, const std::vector& in, napi_value& out); + + /* napi_value <-> std::vector */ + static napi_status GetValue(napi_env env, napi_value in, std::vector& out); + static napi_status SetValue(napi_env env, const std::vector& in, napi_value& out); + + /* napi_value <-> ChangeNotification */ + static napi_status GetValue(napi_env env, napi_value in, ChangeNotification& out); + static napi_status SetValue(napi_env env, const ChangeNotification& in, napi_value& out); + + /* napi_value <-> Options */ + static napi_status GetValue(napi_env env, napi_value in, Options& out); + static napi_status SetValue(napi_env env, const Options& in, napi_value& out); + + /* napi_value <-> Entry */ + static napi_status GetValue(napi_env env, napi_value in, Entry& out); + static napi_status SetValue(napi_env env, const Entry& in, napi_value& out); + + /* napi_value <-> Options */ + static napi_status GetValue(napi_env env, napi_value in, std::list& out); + static napi_status SetValue(napi_env env, const std::list& in, napi_value& out); + + /* napi_value <-> std::vector */ + static napi_status GetValue(napi_env env, napi_value in, std::vector& out); + static napi_status SetValue(napi_env env, const std::vector& in, napi_value& out); + + /* napi_value <-> std::vector */ + static napi_status GetValue(napi_env env, napi_value in, std::vector& out); + static napi_status SetValue(napi_env env, const std::vector& in, napi_value& out); + + /* napi_value <-> std::map */ + static napi_status GetValue(napi_env env, napi_value in, std::map& out); + static napi_status SetValue(napi_env env, const std::map& in, napi_value& out); + + /* napi_get_named_property wrapper */ + template + static inline napi_status GetNamedProperty(napi_env env, napi_value in, const std::string& prop, T& value) + { + napi_value inner = nullptr; + napi_status status = napi_get_named_property(env, in, prop.data(), &inner); + if ((status == napi_ok) && (inner != nullptr)) { + return GetValue(env, inner, value); + } + return status; + }; + + /* 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); + + /* napi_new_instance wrapper */ + static napi_ref NewWithRef(napi_env env, size_t argc, napi_value* argv, void** out, napi_value constructor); + + /* napi_unwrap with napi_instanceof */ + static napi_status Unwrap(napi_env env, napi_value in, void** out, napi_value constructor); + +private: + enum { + /* std::map to js::tuple */ + TUPLE_KEY = 0, + TUPLE_VALUE, + TUPLE_SIZE }; - static constexpr int32_t TYPE_POS = 0; - static constexpr int32_t DATA_POS = TYPE_POS + 1; - static constexpr int32_t TUPLE_SIZE = 2; }; } #endif // OHOS_JS_UTIL_H diff --git a/frameworks/jskitsimpl/distributeddata/include/napi_queue.h b/frameworks/jskitsimpl/distributeddata/include/napi_queue.h new file mode 100644 index 0000000000000000000000000000000000000000..ff07403d99acef6b3678e0efac5f4a1d5ddc55f0 --- /dev/null +++ b/frameworks/jskitsimpl/distributeddata/include/napi_queue.h @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef OHOS_NAPI_QUEUE_H +#define OHOS_NAPI_QUEUE_H +#include + +#include "log_print.h" +#include "napi/native_api.h" +#include "napi/native_common.h" +#include "napi/native_node_api.h" + +namespace OHOS::DistributedData { +using namespace OHOS::DistributedKv; // for ZLOGD/ZLOGE +constexpr size_t ARGC_MAX = 6; + +using NapiCbInfoParser = std::function; +using NapiAsyncExecute = std::function; +using NapiAsyncComplete = std::function; + +struct ContextBase { + virtual ~ContextBase(); + void GetCbInfo( + napi_env env, napi_callback_info info, NapiCbInfoParser parse = NapiCbInfoParser(), bool sync = false); + + inline napi_status GetCbInfoSync(napi_env env, napi_callback_info info, NapiCbInfoParser parse = NapiCbInfoParser()) + { + /* sync = true, means no callback, not AsyncWork. */ + GetCbInfo(env, info, parse, true); + NAPI_ASSERT_BASE(env, status == napi_ok, "invalid arguments!", status); + return status; // return napi_status for NAPI_CALL(). + } + + napi_env env = nullptr; + napi_value output = nullptr; + napi_status status = napi_invalid_arg; + std::string error; + + 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 hold; /* cross thread data */ + + friend class NapiQueue; +}; + +/* ZLOGE on condition related to argc/argv, */ +#define ZLOGE_ON_ARGS(ctxt, condition, message) \ + do { \ + if (!(condition)) { \ + (ctxt)->status = napi_invalid_arg; \ + (ctxt)->error = std::string(message); \ + ZLOGE("test (" #condition ") failed: " message); \ + return; \ + } \ + } while (0) + +#define ZLOGE_ON_STATUS(ctxt, message) \ + do { \ + if ((ctxt)->status != napi_ok) { \ + (ctxt)->error = std::string(message); \ + ZLOGE("test (ctxt->status == napi_ok) failed: " message); \ + return; \ + } \ + } while (0) + +#define ZLOGE_RETURN(condition, message, retVal) \ + do { \ + if (!(condition)) { \ + ZLOGE("test (" #condition ") failed: " message); \ + return retVal; \ + } \ + } while (0) + +#define ZLOGE_RETURN_VOID(condition, message) \ + do { \ + if (!(condition)) { \ + ZLOGE("test (" #condition ") failed: " message); \ + return; \ + } \ + } while (0) + +class NapiQueue { +public: + static napi_value AsyncWork(napi_env env, std::shared_ptr ctxt, const std::string& name, + NapiAsyncExecute execute = NapiAsyncExecute(), NapiAsyncComplete complete = NapiAsyncComplete()); + +private: + enum { + /* AsyncCallback / Promise output result index */ + RESULT_ERROR = 0, + RESULT_DATA = 1, + RESULT_ALL = 2 + }; + static void GenerateOutput(ContextBase* ctxt); +}; +} +#endif // OHOS_NAPI_QUEUE_H diff --git a/frameworks/jskitsimpl/distributeddata/include/kv_manager.h b/frameworks/jskitsimpl/distributeddata/include/uv_queue.h similarity index 58% rename from frameworks/jskitsimpl/distributeddata/include/kv_manager.h rename to frameworks/jskitsimpl/distributeddata/include/uv_queue.h index 90bd20c578f590baa725956844193b56cd5dd84e..87dc117024fab53b8ebaf736671eadc0bce8a293 100644 --- a/frameworks/jskitsimpl/distributeddata/include/kv_manager.h +++ b/frameworks/jskitsimpl/distributeddata/include/uv_queue.h @@ -12,25 +12,32 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#ifndef OHOS_KV_MANAGER_H -#define OHOS_KV_MANAGER_H +#ifndef OHOS_UV_QUEUE_H +#define OHOS_UV_QUEUE_H +#include -#include -#include "napi/native_common.h" #include "napi/native_api.h" +#include "napi/native_common.h" #include "napi/native_node_api.h" -#include "distributed_kv_data_manager.h" +#include "uv.h" + namespace OHOS::DistributedData { -class KVManager { +class UvQueue { + using NapiArgsGenerator = std::function; + public: - static napi_value CreateKVManager(napi_env env, napi_callback_info info); - static napi_value GetKVStore(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); + UvQueue(napi_env env, napi_value callback); + virtual ~UvQueue(); + + bool operator==(napi_value value); - DistributedKv::DistributedKvDataManager kvDataManager_ {}; - std::string bundleName_ {}; + void CallFunction(NapiArgsGenerator genArgs = NapiArgsGenerator()); + +private: + napi_env env_ = nullptr; + napi_ref callback_ = nullptr; + NapiArgsGenerator args; + uv_loop_s* loop_ = nullptr; }; } -#endif // OHOS_KV_MANAGER_H +#endif // OHOS_UV_QUEUE_H diff --git a/frameworks/jskitsimpl/distributeddata/src/async_call.cpp b/frameworks/jskitsimpl/distributeddata/src/async_call.cpp deleted file mode 100644 index 41f588809b4b8cf0556b8c5c882609da1daa264f..0000000000000000000000000000000000000000 --- a/frameworks/jskitsimpl/distributeddata/src/async_call.cpp +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright (c) 2021 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 "AsyncCall" -#include "async_call.h" -#include -#include "log_print.h" - -using namespace OHOS::DistributedKv; -namespace OHOS::DistributedData { -AsyncCall::AsyncCall(napi_env env, napi_callback_info info, std::shared_ptr context, size_t pos) - : env_(env) -{ - context_ = new AsyncContext(); - size_t argc = JSUtil::MAX_ARGC; - napi_value self = nullptr; - napi_value argv[JSUtil::MAX_ARGC] = {nullptr}; - NAPI_CALL_RETURN_VOID(env, napi_get_cb_info(env, info, &argc, argv, &self, nullptr)); - NAPI_ASSERT_BASE(env, pos <= argc, " Invalid Args!", NAPI_RETVAL_NOTHING); - pos = ((pos == ASYNC_DEFAULT_POS) ? (argc - 1) : pos); - if (pos >= 0 && pos < argc) { - napi_valuetype valueType = napi_undefined; - napi_typeof(env, argv[pos], &valueType); - if (valueType == napi_function) { - napi_create_reference(env, argv[pos], 1, &context_->callback); - argc = pos; - } - } - NAPI_CALL_RETURN_VOID(env, (*context)(env, argc, argv, self)); - context_->ctx = std::move(context); - napi_create_reference(env, self, 1, &context_->self); -} - -AsyncCall::~AsyncCall() -{ - if (context_ == nullptr) { - return; - } - - DeleteContext(env_, context_); -} - -napi_value AsyncCall::Call(napi_env env, Context::ExecAction exec) -{ - if ((context_ == nullptr) || (context_->ctx == nullptr)) { - ZLOGD("context_ or context_->ctx is null"); - return nullptr; - } - ZLOGD("async call exec"); - context_->ctx->exec_ = std::move(exec); - napi_value promise = nullptr; - if (context_->callback == nullptr) { - napi_create_promise(env, &context_->defer, &promise); - } else { - napi_get_undefined(env, &promise); - } - napi_async_work work = context_->work; - napi_value resource = nullptr; - napi_create_string_utf8(env, "AsyncCall", NAPI_AUTO_LENGTH, &resource); - napi_create_async_work(env, nullptr, resource, AsyncCall::OnExecute, AsyncCall::OnComplete, context_, &work); - context_->work = work; - context_ = nullptr; - napi_queue_async_work(env, work); - ZLOGD("async call exec"); - return promise; -} - -napi_value AsyncCall::SyncCall(napi_env env, AsyncCall::Context::ExecAction exec) -{ - if ((context_ == nullptr) || (context_->ctx == nullptr)) { - ZLOGD("context_ or context_->ctx is null"); - return nullptr; - } - context_->ctx->exec_ = std::move(exec); - napi_value promise = nullptr; - if (context_->callback == nullptr) { - napi_create_promise(env, &context_->defer, &promise); - } else { - napi_get_undefined(env, &promise); - } - AsyncCall::OnExecute(env, context_); - AsyncCall::OnComplete(env, napi_ok, context_); - return promise; -} - -void AsyncCall::OnExecute(napi_env env, void *data) -{ - ZLOGD("run the async runnable"); - AsyncContext *context = reinterpret_cast(data); - context->ctx->Exec(); -} - -void AsyncCall::OnComplete(napi_env env, napi_status status, void *data) -{ - ZLOGD("run the js callback function"); - AsyncContext *context = reinterpret_cast(data); - napi_value output = nullptr; - napi_status runStatus = (*context->ctx)(env, &output); - napi_value result[ARG_BUTT] = { 0 }; - if (status == napi_ok && runStatus == napi_ok) { - napi_get_undefined(env, &result[ARG_ERROR]); - if (output != nullptr) { - result[ARG_DATA] = output; - } else { - napi_get_undefined(env, &result[ARG_DATA]); - } - } else { - napi_value message = nullptr; - napi_create_string_utf8(env, "async call failed", NAPI_AUTO_LENGTH, &message); - napi_create_error(env, nullptr, message, &result[ARG_ERROR]); - napi_get_undefined(env, &result[ARG_DATA]); - } - if (context->defer != nullptr) { - // promise - if (status == napi_ok && runStatus == napi_ok) { - napi_resolve_deferred(env, context->defer, result[ARG_DATA]); - } else { - napi_reject_deferred(env, context->defer, result[ARG_ERROR]); - } - } else { - // callback - napi_value callback = nullptr; - napi_get_reference_value(env, context->callback, &callback); - napi_value returnValue; - napi_call_function(env, nullptr, callback, ARG_BUTT, result, &returnValue); - } - DeleteContext(env, context); -} -void AsyncCall::DeleteContext(napi_env env, AsyncContext *context) -{ - if (env != nullptr) { - napi_delete_reference(env, context->callback); - napi_delete_reference(env, context->self); - napi_delete_async_work(env, context->work); - } - delete context; -} -} \ No newline at end of file diff --git a/frameworks/jskitsimpl/distributeddata/src/entry_point.cpp b/frameworks/jskitsimpl/distributeddata/src/entry_point.cpp index ce56ad52e7159b9310b8716829fd82bf7b87b90c..49e6f3ff2a4902924bcbb67a29b071e40968ad9b 100644 --- a/frameworks/jskitsimpl/distributeddata/src/entry_point.cpp +++ b/frameworks/jskitsimpl/distributeddata/src/entry_point.cpp @@ -13,50 +13,161 @@ * limitations under the License. */ #define LOG_TAG "EntryPoint" -#include "napi/native_api.h" -#include "napi/native_node_api.h" -#include "kv_manager.h" +#include "js_field_node.h" +#include "js_kv_manager.h" +#include "js_kv_store.h" +#include "js_query.h" +#include "js_schema.h" #include "js_util.h" #include "log_print.h" + using namespace OHOS::DistributedData; using namespace OHOS::DistributedKv; -extern const char _binary_distributed_data_js_start[]; -extern const char _binary_distributed_data_js_end[]; +static napi_status SetNamedProperty(napi_env env, napi_value& obj, const std::string& name, int32_t value) +{ + napi_value property = nullptr; + napi_status status = napi_create_int32(env, value, &property); + ZLOGE_RETURN(status == napi_ok, "int32_t to napi_value failed!", status); + status = napi_set_named_property(env, obj, name.c_str(), property); + ZLOGE_RETURN(status == napi_ok, "napi_set_named_property failed!", status); + return status; +} -static napi_value Init(napi_env env, napi_value exports) +static napi_value ExportUserType(napi_env env) { - napi_property_descriptor desc = DECLARE_NAPI_METHOD("createKVManager", KVManager::CreateKVManager); - napi_status status = napi_define_properties(env, exports, 1, &desc); - ZLOGI("init distributedData %{public}d", status); - return exports; + constexpr int32_t SAME_USER_ID = 0; + + napi_value userType = nullptr; + napi_create_object(env, &userType); + SetNamedProperty(env, userType, "SAME_USER_ID", SAME_USER_ID); + return userType; +} + +static napi_value ExportConstants(napi_env env) +{ + constexpr int32_t MAX_KEY_LENGTH = 1024; + constexpr int32_t MAX_VALUE_LENGTH = 4194303; + constexpr int32_t MAX_KEY_LENGTH_DEVICE = 896; + constexpr int32_t MAX_STORE_ID_LENGTH = 128; + constexpr int32_t MAX_QUERY_LENGTH = 512000; + constexpr int32_t MAX_BATCH_SIZE = 128; + + napi_value constants = nullptr; + napi_create_object(env, &constants); + SetNamedProperty(env, constants, "MAX_KEY_LENGTH", MAX_KEY_LENGTH); + SetNamedProperty(env, constants, "MAX_VALUE_LENGTH", MAX_VALUE_LENGTH); + SetNamedProperty(env, constants, "MAX_KEY_LENGTH_DEVICE", MAX_KEY_LENGTH_DEVICE); + SetNamedProperty(env, constants, "MAX_STORE_ID_LENGTH", MAX_STORE_ID_LENGTH); + SetNamedProperty(env, constants, "MAX_QUERY_LENGTH", MAX_QUERY_LENGTH); + SetNamedProperty(env, constants, "MAX_BATCH_SIZE", MAX_BATCH_SIZE); + return constants; } -// function name: NAPI_{ModuleName}_GetJSCode -extern "C" __attribute__((visibility("default"))) void NAPI_data_distributedData_GetJSCode(const char** buf, - int* bufLen) +static napi_value ExportValueType(napi_env env) { - if (buf != nullptr) { - *buf = _binary_distributed_data_js_start; - } + napi_value valueType = nullptr; + napi_create_object(env, &valueType); + SetNamedProperty(env, valueType, "STRING", (int32_t)JSUtil::STRING); + SetNamedProperty(env, valueType, "INTEGER", (int32_t)JSUtil::INTEGER); + SetNamedProperty(env, valueType, "FLOAT", (int32_t)JSUtil::FLOAT); + SetNamedProperty(env, valueType, "BYTE_ARRAY", (int32_t)JSUtil::BYTE_ARRAY); + SetNamedProperty(env, valueType, "BOOLEAN", (int32_t)JSUtil::BOOLEAN); + SetNamedProperty(env, valueType, "DOUBLE", (int32_t)JSUtil::DOUBLE); + return valueType; +} + +static napi_value ExportSyncMode(napi_env env) +{ + napi_value syncMode = nullptr; + napi_create_object(env, &syncMode); + SetNamedProperty(env, syncMode, "PULL_ONLY", (int32_t)SyncMode::PULL); + SetNamedProperty(env, syncMode, "PUSH_ONLY", (int32_t)SyncMode::PUSH); + SetNamedProperty(env, syncMode, "PUSH_PULL", (int32_t)SyncMode::PUSH_PULL); + return syncMode; +} + +static napi_value ExportSubscribeType(napi_env env) +{ + napi_value subscribeType = nullptr; + napi_create_object(env, &subscribeType); - if (bufLen != nullptr) { - *bufLen = _binary_distributed_data_js_end - _binary_distributed_data_js_start; - } + SetNamedProperty(env, subscribeType, "SUBSCRIBE_TYPE_LOCAL", (int32_t)SUBSCRIBE_LOCAL); + SetNamedProperty(env, subscribeType, "SUBSCRIBE_TYPE_REMOTE", (int32_t)SUBSCRIBE_REMOTE); + SetNamedProperty(env, subscribeType, "SUBSCRIBE_TYPE_ALL", (int32_t)SUBSCRIBE_LOCAL_REMOTE); + return subscribeType; +} + +static napi_value ExportKVStoreType(napi_env env) +{ + napi_value kvStoreType = nullptr; + napi_create_object(env, &kvStoreType); + SetNamedProperty(env, kvStoreType, "DEVICE_COLLABORATION", (int32_t)KvStoreType::DEVICE_COLLABORATION); + SetNamedProperty(env, kvStoreType, "SINGLE_VERSION", (int32_t)KvStoreType::SINGLE_VERSION); + SetNamedProperty(env, kvStoreType, "MULTI_VERSION", (int32_t)KvStoreType::MULTI_VERSION); + return kvStoreType; +} + +static napi_value ExportSecurityLevel(napi_env env) +{ + napi_value securityLevel = nullptr; + napi_create_object(env, &securityLevel); + SetNamedProperty(env, securityLevel, "NO_LEVEL", (int32_t)SecurityLevel::NO_LABEL); + SetNamedProperty(env, securityLevel, "S0", (int32_t)SecurityLevel::S0); + SetNamedProperty(env, securityLevel, "S1", (int32_t)SecurityLevel::S1); + SetNamedProperty(env, securityLevel, "S2", (int32_t)SecurityLevel::S2); + SetNamedProperty(env, securityLevel, "S3", (int32_t)SecurityLevel::S3); + SetNamedProperty(env, securityLevel, "S4", (int32_t)SecurityLevel::S4); + return securityLevel; +} + +static napi_status InitEnumerates(napi_env env, napi_value exports) +{ + const napi_property_descriptor properties[] = { + DECLARE_NAPI_PROPERTY("UserType", ExportUserType(env)), + DECLARE_NAPI_PROPERTY("Constants", ExportConstants(env)), + DECLARE_NAPI_PROPERTY("ValueType", ExportValueType(env)), + DECLARE_NAPI_PROPERTY("SyncMode", ExportSyncMode(env)), + DECLARE_NAPI_PROPERTY("SubscribeType", ExportSubscribeType(env)), + DECLARE_NAPI_PROPERTY("KVStoreType", ExportKVStoreType(env)), + DECLARE_NAPI_PROPERTY("SecurityLevel", ExportSecurityLevel(env)), + }; + size_t count = sizeof(properties) / sizeof(properties[0]); + + return napi_define_properties(env, exports, count, properties); +} + +static napi_value Init(napi_env env, napi_value exports) +{ + const napi_property_descriptor desc[] = { + DECLARE_NAPI_FUNCTION("createKVManager", JsKVManager::CreateKVManager) + }; + napi_status status = napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); + ZLOGI("init createKVManager %{public}d", status); + + status = napi_set_named_property(env, exports, "FieldNode", JsFieldNode::Constructor(env)); + ZLOGI("init FieldNode %{public}d", status); + + status = napi_set_named_property(env, exports, "Schema", JsSchema::Constructor(env)); + ZLOGI("init Schema %{public}d", status); + + status = napi_set_named_property(env, exports, "Query", JsQuery::Constructor(env)); + ZLOGI("init Query %{public}d", status); + + status = InitEnumerates(env, exports); + ZLOGI("init Enumerate Constants %{public}d", status); + return exports; } static __attribute__((constructor)) void RegisterModule() { - static napi_module module = { - .nm_version = 1, + static napi_module module = { .nm_version = 1, .nm_flags = 0, .nm_filename = nullptr, .nm_register_func = Init, .nm_modname = "data.distributedData", - .nm_priv = ((void *)0), - .reserved = { 0 } - }; + .nm_priv = ((void*)0), + .reserved = { 0 } }; napi_module_register(&module); ZLOGI("module register data.distributedData"); } - diff --git a/frameworks/jskitsimpl/distributeddata/src/js_device_kv_store.cpp b/frameworks/jskitsimpl/distributeddata/src/js_device_kv_store.cpp new file mode 100644 index 0000000000000000000000000000000000000000..db2fc9f30a7e569daa4fc135a59695728672b8ae --- /dev/null +++ b/frameworks/jskitsimpl/distributeddata/src/js_device_kv_store.cpp @@ -0,0 +1,437 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#define LOG_TAG "JS_DeviceKVStore" +#include "js_device_kv_store.h" +#include + +#include "js_kv_store_resultset.h" +#include "js_query.h" +#include "js_util.h" +#include "log_print.h" +#include "napi_queue.h" +#include "uv_queue.h" + +using namespace OHOS::DistributedKv; + +namespace OHOS::DistributedData { +constexpr int DEVICEID_WIDTH = 4; +static std::string GetDeviceKey(const std::string& deviceId, const std::string& key) +{ + std::ostringstream oss; + oss << std::setfill('0') << std::setw(DEVICEID_WIDTH) << deviceId.length(); + oss << deviceId << key; + return oss.str(); +} + +JsDeviceKVStore::JsDeviceKVStore(const std::string& storeId) + : JsKVStore(storeId) +{ +} + +napi_value JsDeviceKVStore::Constructor(napi_env env) +{ + const napi_property_descriptor properties[] = { + DECLARE_NAPI_FUNCTION("put", JsKVStore::Put), + DECLARE_NAPI_FUNCTION("delete", JsKVStore::Delete), + DECLARE_NAPI_FUNCTION("putBatch", JsKVStore::PutBatch), + DECLARE_NAPI_FUNCTION("deleteBatch", JsKVStore::DeleteBatch), + DECLARE_NAPI_FUNCTION("startTransaction", JsKVStore::StartTransaction), + DECLARE_NAPI_FUNCTION("commit", JsKVStore::Commit), + DECLARE_NAPI_FUNCTION("rollback", JsKVStore::Rollback), + DECLARE_NAPI_FUNCTION("enableSync", JsKVStore::EnableSync), + DECLARE_NAPI_FUNCTION("setSyncRange", JsKVStore::SetSyncRange), + /* JsDeviceKVStore externs JsKVStore */ + DECLARE_NAPI_FUNCTION("get", JsDeviceKVStore::Get), + DECLARE_NAPI_FUNCTION("getEntries", JsDeviceKVStore::GetEntries), + DECLARE_NAPI_FUNCTION("getResultSet", JsDeviceKVStore::GetResultSet), + DECLARE_NAPI_FUNCTION("closeResultSet", JsDeviceKVStore::CloseResultSet), + DECLARE_NAPI_FUNCTION("getResultSize", JsDeviceKVStore::GetResultSize), + DECLARE_NAPI_FUNCTION("removeDeviceData", JsDeviceKVStore::RemoveDeviceData), + DECLARE_NAPI_FUNCTION("sync", JsDeviceKVStore::Sync), + DECLARE_NAPI_FUNCTION("on", JsKVStore::OnEvent), /* same to JsSingleKVStore */ + DECLARE_NAPI_FUNCTION("off", JsKVStore::OffEvent) /* same to JsSingleKVStore */ + }; + size_t count = sizeof(properties) / sizeof(properties[0]); + + return JSUtil::DefineClass(env, "DeviceKVStore", properties, count, JsDeviceKVStore::New); +} + +/* + * [JS API Prototype] + * [AsyncCallback] + * get(deviceId:string, key:string, callback:AsyncCallback):void; + * [Promise] + * get(deviceId:string, key:string):Promise; + */ +napi_value JsDeviceKVStore::Get(napi_env env, napi_callback_info info) +{ + ZLOGD("DeviceKVStore::get()"); + struct GetContext : public ContextBase { + std::string deviceId; + std::string key; + JSUtil::KvStoreVariant value; + }; + auto ctxt = std::make_shared(); + auto input = [env, ctxt](size_t argc, napi_value* argv) { + // number 2 means: required 2 arguments, + + ZLOGE_ON_ARGS(ctxt, argc == 2, "invalid arguments!"); + ctxt->status = JSUtil::GetValue(env, argv[0], ctxt->deviceId); + ZLOGE_ON_STATUS(ctxt, "invalid arg[0], i.e. invalid deviceId!"); + ctxt->status = JSUtil::GetValue(env, argv[1], ctxt->key); + ZLOGE_ON_STATUS(ctxt, "invalid arg[1], i.e. invalid key!"); + }; + ctxt->GetCbInfo(env, info, input); + + auto execute = [ctxt]() { + std::string deviceKey = GetDeviceKey(ctxt->deviceId, ctxt->key); + OHOS::DistributedKv::Key key(deviceKey); + OHOS::DistributedKv::Value value; + auto& kvStore = reinterpret_cast(ctxt->native)->GetNative(); + Status status = kvStore->Get(deviceKey, value); + ZLOGD("kvStore->Get return %{public}d", status); + ctxt->value = JSUtil::Blob2VariantValue(value); + ctxt->status = (status == Status::SUCCESS) ? napi_ok : napi_generic_failure; + ZLOGE_ON_STATUS(ctxt, "kvStore->Get() failed!"); + }; + auto output = [env, ctxt](napi_value& result) { + ctxt->status = JSUtil::SetValue(env, ctxt->value, result); + ZLOGE_ON_STATUS(ctxt, "output failed"); + }; + return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute, output); +} + +enum class ArgsType : uint8_t { + /* input arguments' combination type */ + DEVICEID_KEYPREFIX = 0, + DEVICEID_QUERY, + QUERY, + UNKNOWN = 255 +}; +struct VariantArgs { + /* input arguments' combinations */ + std::string deviceId; + std::string keyPrefix; + JsQuery* query; + ArgsType type = ArgsType::UNKNOWN; +}; + +static napi_status GetVariantArgs(napi_env env, size_t argc, napi_value* argv, VariantArgs& va) +{ + ZLOGE_RETURN(argc > 0, "invalid arguments!", napi_invalid_arg); + napi_valuetype type = napi_undefined; + napi_status status = napi_typeof(env, argv[0], &type); + ZLOGE_RETURN((type == napi_string) || (type == napi_object), "invalid arg[0], type error!", napi_invalid_arg); + if (type == napi_string) { + // number 2 means: required 2 arguments, + ZLOGE_RETURN(argc == 2, "invalid arguments!", napi_invalid_arg); + status = JSUtil::GetValue(env, argv[0], va.deviceId); + ZLOGE_RETURN(!va.deviceId.empty(), "invalid arg[0], i.e. invalid deviceId!", napi_invalid_arg); + + status = napi_typeof(env, argv[1], &type); + ZLOGE_RETURN((type == napi_string) || (type == napi_object), "invalid arg[1], type error!", napi_invalid_arg); + if (type == napi_string) { + status = JSUtil::GetValue(env, argv[1], va.keyPrefix); + ZLOGE_RETURN(!va.keyPrefix.empty(), "invalid arg[1], i.e. invalid keyPrefix!", napi_invalid_arg); + va.type = ArgsType::DEVICEID_KEYPREFIX; + } else if (type == napi_object) { + status = JSUtil::Unwrap(env, argv[1], (void**)(&va.query), JsQuery::Constructor(env)); + ZLOGE_RETURN(va.query != nullptr, "invalid arg[1], i.e. invalid query!", napi_invalid_arg); + va.type = ArgsType::DEVICEID_QUERY; + } + } else if (type == napi_object) { + // number 1 means: required 1 arguments, + ZLOGE_RETURN(argc == 1, "invalid arguments!", napi_invalid_arg); + status = JSUtil::Unwrap(env, argv[0], (void**)(&va.query), JsQuery::Constructor(env)); + ZLOGE_RETURN(va.query != nullptr, "invalid arg[0], i.e. invalid query!", napi_invalid_arg); + va.type = ArgsType::QUERY; + } + return status; +}; + +/* + * [JS API Prototype] + * getEntries(deviceId:string, keyPrefix:string, callback:AsyncCallback):void + * getEntries(deviceId:string, keyPrefix:string):Promise + * + * getEntries(query:Query, callback:AsyncCallback):void + * getEntries(query:Query) : Promise + * + * getEntries(deviceId:string, query:Query):callback:AsyncCallback):void + * getEntries(deviceId:string, query:Query):Promise + */ +napi_value JsDeviceKVStore::GetEntries(napi_env env, napi_callback_info info) +{ + ZLOGD("DeviceKVStore::GetEntries()"); + struct GetEntriesContext : public ContextBase { + VariantArgs va; + std::vector entries; + }; + auto ctxt = std::make_shared(); + auto input = [env, ctxt](size_t argc, napi_value* argv) { + ctxt->status = GetVariantArgs(env, argc, argv, ctxt->va); + ZLOGE_ON_STATUS(ctxt, "invalid arguments!"); + }; + ctxt->GetCbInfo(env, info, input); + + auto execute = [ctxt]() { + auto& kvStore = reinterpret_cast(ctxt->native)->GetNative(); + Status status = Status::INVALID_ARGUMENT; + if (ctxt->va.type == ArgsType::DEVICEID_KEYPREFIX) { + std::string deviceKey = GetDeviceKey(ctxt->va.deviceId, ctxt->va.keyPrefix); + OHOS::DistributedKv::Key keyPrefix(deviceKey); + status = kvStore->GetEntries(keyPrefix, ctxt->entries); + ZLOGD("kvStore->GetEntries() return %{public}d", status); + } else if (ctxt->va.type == ArgsType::DEVICEID_QUERY) { + auto query = ctxt->va.query->GetNative(); + query.DeviceId(ctxt->va.deviceId); + status = kvStore->GetEntriesWithQuery(query.ToString(), ctxt->entries); + ZLOGD("kvStore->GetEntriesWithQuery() return %{public}d", status); + } else if (ctxt->va.type == ArgsType::QUERY) { + auto query = ctxt->va.query->GetNative(); + status = kvStore->GetEntriesWithQuery(query.ToString(), ctxt->entries); + ZLOGD("kvStore->GetEntriesWithQuery() return %{public}d", status); + } + ctxt->status = (status == Status::SUCCESS) ? napi_ok : napi_generic_failure; + ZLOGE_ON_STATUS(ctxt, "kvStore->GetEntries() failed!"); + }; + auto output = [env, ctxt](napi_value& result) { + ctxt->status = JSUtil::SetValue(env, ctxt->entries, result); + ZLOGE_ON_STATUS(ctxt, "output failed!"); + }; + return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute, output); +} + +/* + * [JS API Prototype] + * getResultSet(deviceId:string, keyPrefix:string, callback:AsyncCallback):void + * getResultSet(deviceId:string, keyPrefix:string):Promise + * + * getResultSet(query:Query, callback:AsyncCallback):void + * getResultSet(query:Query):Promise + * + * getResultSet(deviceId:string, query:Query, callback:AsyncCallback):void + * getResultSet(deviceId:string, query:Query):Promise + */ +napi_value JsDeviceKVStore::GetResultSet(napi_env env, napi_callback_info info) +{ + ZLOGD("DeviceKVStore::GetResultSet()"); + struct GetResultSetContext : public ContextBase { + VariantArgs va; + JsKVStoreResultSet* resultSet = nullptr; + napi_ref ref = nullptr; + }; + auto ctxt = std::make_shared(); + auto input = [env, ctxt](size_t argc, napi_value* argv) { + ctxt->status = GetVariantArgs(env, argc, argv, ctxt->va); + ZLOGE_ON_STATUS(ctxt, "invalid arguments!"); + ctxt->ref = JSUtil::NewWithRef(env, 0, nullptr, (void**)(&ctxt->resultSet), + JsKVStoreResultSet::Constructor(env)); + ZLOGE_ON_ARGS(ctxt, ctxt->resultSet != nullptr, "KVStoreResultSet::New failed!"); + }; + ctxt->GetCbInfo(env, info, input); + + auto execute = [ctxt]() { + std::shared_ptr kvResultSet; + auto& kvStore = reinterpret_cast(ctxt->native)->GetNative(); + Status status = Status::INVALID_ARGUMENT; + if (ctxt->va.type == ArgsType::DEVICEID_KEYPREFIX) { + std::string deviceKey = GetDeviceKey(ctxt->va.deviceId, ctxt->va.keyPrefix); + OHOS::DistributedKv::Key keyPrefix(deviceKey); + status = kvStore->GetResultSet(keyPrefix, kvResultSet); + ZLOGD("kvStore->GetEntries() return %{public}d", status); + } else if (ctxt->va.type == ArgsType::DEVICEID_QUERY) { + auto query = ctxt->va.query->GetNative(); + query.DeviceId(ctxt->va.deviceId); + status = kvStore->GetResultSetWithQuery(query.ToString(), kvResultSet); + ZLOGD("kvStore->GetEntriesWithQuery() return %{public}d", status); + } else if (ctxt->va.type == ArgsType::QUERY) { + auto query = ctxt->va.query->GetNative(); + status = kvStore->GetResultSetWithQuery(query.ToString(), kvResultSet); + ZLOGD("kvStore->GetEntriesWithQuery() return %{public}d", status); + } + ctxt->status = (status == Status::SUCCESS) ? napi_ok : napi_generic_failure; + ZLOGE_ON_STATUS(ctxt, "kvStore->GetResultSet() failed!"); + ctxt->resultSet->SetNative(kvResultSet); + }; + auto output = [env, ctxt](napi_value& result) { + ctxt->status = napi_get_reference_value(env, ctxt->ref, &result); + napi_delete_reference(env, ctxt->ref); + ZLOGE_ON_STATUS(ctxt, "output KvResultSet failed"); + }; + return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute, output); +} + +/* + * [JS API Prototype] + * closeResultSet(resultSet:KVStoreResultSet, callback: AsyncCallback):void + * closeResultSet(resultSet:KVStoreResultSet):Promise + */ +napi_value JsDeviceKVStore::CloseResultSet(napi_env env, napi_callback_info info) +{ + ZLOGD("DeviceKVStore::CloseResultSet()"); + struct CloseResultSetContext : public ContextBase { + JsKVStoreResultSet* resultSet = nullptr; + }; + auto ctxt = std::make_shared(); + auto input = [env, ctxt](size_t argc, napi_value* argv) { + // required 1 arguments :: + ZLOGE_ON_ARGS(ctxt, argc == 1, "invalid arguments!"); + napi_valuetype type = napi_undefined; + ctxt->status = napi_typeof(env, argv[0], &type); + ZLOGE_ON_ARGS(ctxt, type == napi_object, "invalid arg[0], i.e. invalid resultSet!"); + ctxt->status = JSUtil::Unwrap(env, argv[0], (void**)(&ctxt->resultSet), + JsKVStoreResultSet::Constructor(env)); + ZLOGE_ON_ARGS(ctxt, ctxt->resultSet != nullptr, "invalid arg[0], i.e. invalid resultSet!"); + }; + ctxt->GetCbInfo(env, info, input); + + auto execute = [ctxt]() { + auto& kvStore = reinterpret_cast(ctxt->native)->GetNative(); + Status status = kvStore->CloseResultSet(ctxt->resultSet->GetNative()); + ZLOGD("kvStore->CloseResultSet return %{public}d", status); + ctxt->status = (status == Status::SUCCESS) ? napi_ok : napi_generic_failure; + ZLOGE_ON_STATUS(ctxt, "kvStore->CloseResultSet failed!"); + }; + return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute); +} + +/* + * [JS API Prototype] + * getResultSize(query:Query, callback: AsyncCallback):void + * getResultSize(query:Query):Promise + * + * getResultSize(deviceId:string, query:Query, callback: AsyncCallback):void + * getResultSize(deviceId:string, query:Query):Promise + */ +napi_value JsDeviceKVStore::GetResultSize(napi_env env, napi_callback_info info) +{ + ZLOGD("DeviceKVStore::GetResultSize()"); + struct ResultSizeContext : public ContextBase { + VariantArgs va; + int resultSize = 0; + }; + auto ctxt = std::make_shared(); + auto input = [env, ctxt](size_t argc, napi_value* argv) { + ctxt->status = GetVariantArgs(env, argc, argv, ctxt->va); + ZLOGE_ON_ARGS(ctxt, (ctxt->va.type == ArgsType::DEVICEID_QUERY) || (ctxt->va.type == ArgsType::QUERY), + "invalid arguments!"); + ZLOGE_ON_STATUS(ctxt, "invalid arguments!"); + }; + + ctxt->GetCbInfo(env, info, input); + auto execute = [ctxt]() { + auto& kvStore = reinterpret_cast(ctxt->native)->GetNative(); + auto query = ctxt->va.query->GetNative(); + if (ctxt->va.type == ArgsType::DEVICEID_QUERY) { + query.DeviceId(ctxt->va.deviceId); + } + Status status = kvStore->GetCountWithQuery(query.ToString(), ctxt->resultSize); + ZLOGD("kvStore->GetCountWithQuery() return %{public}d", status); + ctxt->status = (status == Status::SUCCESS) ? napi_ok : napi_generic_failure; + ZLOGE_ON_STATUS(ctxt, "kvStore->GetCountWithQuery() failed!"); + }; + auto output = [env, ctxt](napi_value& result) { + ctxt->status = JSUtil::SetValue(env, static_cast(ctxt->resultSize), result); + ZLOGE_ON_STATUS(ctxt, "output resultSize failed!"); + }; + return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute, output); +} + +/* + * [JS API Prototype] + * removeDeviceData(deviceId:string, callback: AsyncCallback):void + * removeDeviceData(deviceId:string):Promise + */ +napi_value JsDeviceKVStore::RemoveDeviceData(napi_env env, napi_callback_info info) +{ + ZLOGD("DeviceKVStore::RemoveDeviceData()"); + struct RemoveDeviceContext : public ContextBase { + std::string deviceId; + }; + auto ctxt = std::make_shared(); + auto input = [env, ctxt](size_t argc, napi_value* argv) { + // required 1 arguments :: + ZLOGE_ON_ARGS(ctxt, argc == 1, "invalid arguments!"); + ctxt->status = JSUtil::GetValue(env, argv[0], ctxt->deviceId); + ZLOGE_ON_STATUS(ctxt, "invalid arg[0], i.e. invalid deviceId!"); + }; + ctxt->GetCbInfo(env, info, input); + + auto execute = [ctxt]() { + auto& kvStore = reinterpret_cast(ctxt->native)->GetNative(); + Status status = kvStore->RemoveDeviceData(ctxt->deviceId); + ZLOGD("kvStore->RemoveDeviceData return %{public}d", status); + ctxt->status = (status == Status::SUCCESS) ? napi_ok : napi_generic_failure; + ZLOGE_ON_STATUS(ctxt, "kvStore->RemoveDeviceData() failed!"); + }; + return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute); +} + +/* + * [JS API Prototype] + * sync(deviceIdList:string[], mode:SyncMode):void + */ +napi_value JsDeviceKVStore::Sync(napi_env env, napi_callback_info info) +{ + struct SyncContext : public ContextBase { + std::vector deviceIdList; + uint32_t mode = 0; + }; + auto ctxt = std::make_shared(); + auto input = [env, ctxt](size_t argc, napi_value* argv) { + // required 2 arguments :: + + ZLOGE_ON_ARGS(ctxt, argc == 2, "invalid arguments!"); + ctxt->status = JSUtil::GetValue(env, argv[0], ctxt->deviceIdList); + ZLOGE_ON_STATUS(ctxt, "invalid arg[0], i.e. invalid deviceIdList!"); + ctxt->status = JSUtil::GetValue(env, argv[1], ctxt->mode); + ZLOGE_ON_STATUS(ctxt, "invalid arg[1], i.e. invalid mode!"); + ZLOGE_ON_ARGS(ctxt, ctxt->mode <= uint32_t(SyncMode::PUSH_PULL), "invalid arg[1], i.e. invalid mode!"); + }; + NAPI_CALL(env, ctxt->GetCbInfoSync(env, info, input)); + + auto& kvStore = reinterpret_cast(ctxt->native)->GetNative(); + Status status = kvStore->Sync(ctxt->deviceIdList, static_cast(ctxt->mode)); + ZLOGD("kvStore->Sync return %{public}d!", status); + NAPI_ASSERT(env, status == Status::SUCCESS, "kvStore->Sync() failed!"); + return nullptr; +} + +napi_value JsDeviceKVStore::New(napi_env env, napi_callback_info info) +{ + ZLOGD("Constructor single kv store!"); + std::string storeId; + auto ctxt = std::make_shared(); + auto input = [env, ctxt, &storeId](size_t argc, napi_value* argv) { + // required 2 arguments :: + ZLOGE_ON_ARGS(ctxt, argc == 2, "invalid arguments!"); + ctxt->status = JSUtil::GetValue(env, argv[0], storeId); + ZLOGE_ON_STATUS(ctxt, "invalid arg[0], i.e. invalid storeId!"); + ZLOGE_ON_ARGS(ctxt, !storeId.empty(), "invalid arg[0], i.e. invalid storeId!"); + }; + NAPI_CALL(env, ctxt->GetCbInfoSync(env, info, input)); + + JsDeviceKVStore* kvStore = new (std::nothrow) JsDeviceKVStore(storeId); + NAPI_ASSERT(env, kvStore !=nullptr, "no memory for kvStore"); + + auto finalize = [](napi_env env, void* data, void* hint) { + ZLOGD("deviceKvStore finalize."); + auto* kvStore = reinterpret_cast(data); + ZLOGE_RETURN_VOID(kvStore != nullptr, "finalize null!"); + delete kvStore; + }; + NAPI_CALL(env, napi_wrap(env, ctxt->self, kvStore, finalize, nullptr, nullptr)); + return ctxt->self; +} +} // namespace OHOS::DistributedData diff --git a/frameworks/jskitsimpl/distributeddata/src/js_field_node.cpp b/frameworks/jskitsimpl/distributeddata/src/js_field_node.cpp new file mode 100644 index 0000000000000000000000000000000000000000..22401d771751c5eaa5c9202e5ba88f18297aaeb2 --- /dev/null +++ b/frameworks/jskitsimpl/distributeddata/src/js_field_node.cpp @@ -0,0 +1,290 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#define LOG_TAG "JS_FieldNode" +#include "js_field_node.h" +#include + +#include "js_util.h" +#include "log_print.h" +#include "napi_queue.h" +#include "uv_queue.h" + +using namespace OHOS::DistributedKv; +using json = nlohmann::json; + +namespace OHOS::DistributedData { +static std::string FIELDNAME = "FIELDNAME"; +static std::string VALUETYPE = "VALUETYPE"; +static std::string DEFAULTVALUE = "DEFAULTVALUE"; +static std::string ISWITHDEFAULTVALUE = "ISWITHDEFAULTVALUE"; +static std::string ISNULLABLE = "ISNULLABLE"; +static std::string CHILDREN = "CHILDREN"; + +JsFieldNode::JsFieldNode(const std::string& fName) + : fieldName(fName) +{ +} + +std::string JsFieldNode::GetFieldName() +{ + return fieldName; +} + +std::string JsFieldNode::GetValueForJson() +{ + if (!fields.empty()) { + /* example: + { "field_root": { + "field_child1": "LONG, NOT NULL, DEFAULT 88", + "field_child2": "LONG, NOT NULL, DEFAULT 88" } } */ + json jsFields; + for (auto fld : fields) { + jsFields[fld->fieldName] = fld->GetValueForJson(); + } + return jsFields.dump(); + } + + /* example: { "field_name": "LONG, NOT NULL, DEFAULT 88" } */ + return ValueTypeToString(valueType) + "," + (isNullable ? "NULL" : "NOT NULL"); +} + +napi_value JsFieldNode::Constructor(napi_env env) +{ + const napi_property_descriptor properties[] = { + DECLARE_NAPI_FUNCTION("appendChild", JsFieldNode::AppendChild), + DECLARE_NAPI_FUNCTION("toJson", JsFieldNode::ToJson), + DECLARE_NAPI_GETTER_SETTER("default", JsFieldNode::GetDefaultValue, JsFieldNode::SetDefaultValue), + DECLARE_NAPI_GETTER_SETTER("nullable", JsFieldNode::GetNullable, JsFieldNode::SetNullable), + DECLARE_NAPI_GETTER_SETTER("type", JsFieldNode::GetValueType, JsFieldNode::SetValueType) + }; + size_t count = sizeof(properties) / sizeof(properties[0]); + return JSUtil::DefineClass(env, "FieldNode", properties, count, JsFieldNode::New); +} + +napi_value JsFieldNode::New(napi_env env, napi_callback_info info) +{ + ZLOGD("FieldNode::New"); + std::string fieldName; + auto ctxt = std::make_shared(); + auto input = [env, ctxt, &fieldName](size_t argc, napi_value* argv) { + // required 1 arguments :: + ZLOGE_ON_ARGS(ctxt, argc == 1, "invalid arguments!"); + ctxt->status = JSUtil::GetValue(env, argv[0], fieldName); + ZLOGE_ON_STATUS(ctxt, "invalid arg[0], i.e. invalid fieldName!"); + ZLOGE_ON_ARGS(ctxt, !fieldName.empty(), "invalid arg[0], i.e. invalid fieldName!"); + }; + NAPI_CALL(env, ctxt->GetCbInfoSync(env, info, input)); + + JsFieldNode* fieldNode = new (std::nothrow) JsFieldNode(fieldName); + NAPI_ASSERT(env, fieldNode != nullptr, "no memory for fieldNode"); + + auto finalize = [](napi_env env, void* data, void* hint) { + ZLOGD("fieldNode finalize."); + auto* field = reinterpret_cast(data); + ZLOGE_RETURN_VOID(field != nullptr, "finalize null!"); + delete field; + }; + NAPI_CALL(env, napi_wrap(env, ctxt->self, fieldNode, finalize, nullptr, nullptr)); + return ctxt->self; +} + +napi_value JsFieldNode::AppendChild(napi_env env, napi_callback_info info) +{ + ZLOGD("FieldNode::AppendChild"); + JsFieldNode* child = nullptr; + auto ctxt = std::make_shared(); + auto input = [env, ctxt, &child](size_t argc, napi_value* argv) { + // required 1 arguments :: + ZLOGE_ON_ARGS(ctxt, argc == 1, "invalid arguments!"); + ctxt->status = JSUtil::Unwrap(env, argv[0], (void**)(&child), JsFieldNode::Constructor(env)); + ZLOGE_ON_STATUS(ctxt, "napi_unwrap to FieldNode failed"); + ZLOGE_ON_ARGS(ctxt, child != nullptr, "invalid arg[0], i.e. invalid FieldNode!"); + }; + NAPI_CALL(env, ctxt->GetCbInfoSync(env, info, input)); + + auto fieldNode = reinterpret_cast(ctxt->native); + fieldNode->fields.push_back(child); + + napi_get_boolean(env, true, &ctxt->output); + return ctxt->output; +} + +napi_value JsFieldNode::ToJson(napi_env env, napi_callback_info info) +{ + ZLOGD("FieldNode::ToJson"); + auto ctxt = std::make_shared(); + NAPI_CALL(env, ctxt->GetCbInfoSync(env, info)); + + auto fieldNode = reinterpret_cast(ctxt->native); + std::string js = fieldNode->Dump(); + JSUtil::SetValue(env, js, ctxt->output); + return ctxt->output; +} + +napi_value JsFieldNode::GetDefaultValue(napi_env env, napi_callback_info info) +{ + ZLOGD("FieldNode::GetDefaultValue"); + auto ctxt = std::make_shared(); + NAPI_CALL(env, ctxt->GetCbInfoSync(env, info)); + + auto fieldNode = reinterpret_cast(ctxt->native); + JSUtil::SetValue(env, fieldNode->defaultValue, ctxt->output); + return ctxt->output; +} + +napi_value JsFieldNode::SetDefaultValue(napi_env env, napi_callback_info info) +{ + ZLOGD("FieldNode::SetDefaultValue"); + auto ctxt = std::make_shared(); + JSUtil::KvStoreVariant vv; + auto input = [env, ctxt, &vv](size_t argc, napi_value* argv) { + // required 1 arguments :: + ZLOGE_ON_ARGS(ctxt, argc == 1, "invalid arguments!"); + ctxt->status = JSUtil::GetValue(env, argv[0], vv); + ZLOGE_ON_STATUS(ctxt, "invalid arg[0], i.e. invalid defaultValue!"); + }; + NAPI_CALL(env, ctxt->GetCbInfoSync(env, info, input)); + + auto fieldNode = reinterpret_cast(ctxt->native); + fieldNode->defaultValue = vv; + return nullptr; +} + +napi_value JsFieldNode::GetNullable(napi_env env, napi_callback_info info) +{ + ZLOGD("FieldNode::GetNullable"); + auto ctxt = std::make_shared(); + NAPI_CALL(env, ctxt->GetCbInfoSync(env, info)); + + auto fieldNode = reinterpret_cast(ctxt->native); + JSUtil::SetValue(env, fieldNode->isNullable, ctxt->output); + return ctxt->output; +} + +napi_value JsFieldNode::SetNullable(napi_env env, napi_callback_info info) +{ + ZLOGD("FieldNode::SetNullable"); + auto ctxt = std::make_shared(); + bool isNullable = false; + auto input = [env, ctxt, &isNullable](size_t argc, napi_value* argv) { + // required 1 arguments :: + ZLOGE_ON_ARGS(ctxt, argc == 1, "invalid arguments!"); + ctxt->status = JSUtil::GetValue(env, argv[0], isNullable); + ZLOGE_ON_STATUS(ctxt, "invalid arg[0], i.e. invalid isNullable!"); + }; + NAPI_CALL(env, ctxt->GetCbInfoSync(env, info, input)); + + auto fieldNode = reinterpret_cast(ctxt->native); + fieldNode->isNullable = isNullable; + return nullptr; +} + +napi_value JsFieldNode::GetValueType(napi_env env, napi_callback_info info) +{ + ZLOGD("FieldNode::New"); + auto ctxt = std::make_shared(); + NAPI_CALL(env, ctxt->GetCbInfoSync(env, info)); + + auto fieldNode = reinterpret_cast(ctxt->native); + JSUtil::SetValue(env, fieldNode->valueType, ctxt->output); + return ctxt->output; +} + +napi_value JsFieldNode::SetValueType(napi_env env, napi_callback_info info) +{ + ZLOGD("FieldNode::New"); + auto ctxt = std::make_shared(); + uint32_t type = 0; + auto input = [env, ctxt, &type](size_t argc, napi_value* argv) { + // required 1 arguments :: + ZLOGE_ON_ARGS(ctxt, argc == 1, "invalid arguments!"); + ctxt->status = JSUtil::GetValue(env, argv[0], type); + ZLOGE_ON_STATUS(ctxt, "invalid arg[0], i.e. invalid valueType!"); + ZLOGE_ON_ARGS(ctxt, (JSUtil::STRING <= type) && (type <= JSUtil::DOUBLE), + "invalid arg[0], i.e. invalid valueType!"); + }; + NAPI_CALL(env, ctxt->GetCbInfoSync(env, info, input)); + + auto fieldNode = reinterpret_cast(ctxt->native); + fieldNode->valueType = type; + return nullptr; +} + +std::string JsFieldNode::ValueToString(JSUtil::KvStoreVariant value) +{ + auto strValue = std::get_if(&value); + if (strValue != nullptr) { + return (*strValue); + } + auto intValue = std::get_if(&value); + if (intValue != nullptr) { + return std::to_string(*intValue); + } + auto fltValue = std::get_if(&value); + if (fltValue != nullptr) { + return std::to_string(*fltValue); + } + auto boolValue = std::get_if(&value); + if (boolValue != nullptr) { + return std::to_string(*boolValue); + } + auto dblValue = std::get_if(&value); + if (dblValue != nullptr) { + return std::to_string(*dblValue); + } + ZLOGE("ValueType is INVALID"); + return std::string(); +} + +std::string JsFieldNode::ValueTypeToString(uint32_t type) +{ + // DistributedDB::FieldType + switch (type) { + case JSUtil::STRING: + return std::string("STRING"); + case JSUtil::INTEGER: + return std::string("INTEGER"); + case JSUtil::FLOAT: + return std::string("FLOAT"); + case JSUtil::BYTE_ARRAY: + return std::string("BYTE_ARRAY"); + case JSUtil::BOOLEAN: + return std::string("BOOLEAN"); + case JSUtil::DOUBLE: + return std::string("DOUBLE"); + default: + ZLOGE("ValueType is INVALID"); + break; + } + return std::string(); +} +std::string JsFieldNode::Dump() +{ + json jsFields; + for (auto fld : fields) { + jsFields.push_back(fld->Dump()); + } + + json jsNode = { + { FIELDNAME, fieldName }, + { VALUETYPE, ValueTypeToString(valueType) }, + { DEFAULTVALUE, ValueToString(defaultValue) }, + { ISWITHDEFAULTVALUE, isWithDefaultValue }, + { ISNULLABLE, isNullable }, + { CHILDREN, jsFields.dump() } + }; + return jsNode.dump(); +} +} diff --git a/frameworks/jskitsimpl/distributeddata/src/js_kv_manager.cpp b/frameworks/jskitsimpl/distributeddata/src/js_kv_manager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e290fab50637080e1248b58f07669aaeb57f0e5d --- /dev/null +++ b/frameworks/jskitsimpl/distributeddata/src/js_kv_manager.cpp @@ -0,0 +1,378 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#define LOG_TAG "JS_KVManager" +#include "js_kv_manager.h" +#include "distributed_kv_data_manager.h" +#include "js_device_kv_store.h" +#include "js_single_kv_store.h" +#include "js_util.h" +#include "log_print.h" +#include "napi_queue.h" + +using namespace OHOS::DistributedKv; + +namespace OHOS::DistributedData { +bool IsStoreTypeSupported(Options options) +{ + return (options.kvStoreType == KvStoreType::DEVICE_COLLABORATION) + || (options.kvStoreType == KvStoreType::SINGLE_VERSION); +} + +JsKVManager::JsKVManager(const std::string& bundleName) + : bundleName_(bundleName) +{ +} + +JsKVManager::~JsKVManager() +{ + ZLOGD("no memory leak for JsKVManager"); + std::lock_guard lck(deathMutex_); + for (auto& it : deathRecipient_) { + kvDataManager_.UnRegisterKvStoreServiceDeathRecipient(it); + } + deathRecipient_.clear(); +} + +/* + * [JS API Prototype] + * [AsyncCB] createKVManager(config: KVManagerConfig, callback: AsyncCallback): void; + * [Promise] createKVManager(config: KVManagerConfig) : Promise; + */ +napi_value JsKVManager::CreateKVManager(napi_env env, napi_callback_info info) +{ + ZLOGD("CreateKVManager in"); + struct ContextInfo : public ContextBase { + JsKVManager* kvManger = nullptr; + napi_ref ref = nullptr; + }; + auto ctxt = std::make_shared(); + auto input = [env, ctxt](size_t argc, napi_value* argv) { + // required 1 arguments :: + ZLOGE_ON_ARGS(ctxt, argc == 1, "invalid arguments!"); + std::string bundleName; + ctxt->status = JSUtil::GetNamedProperty(env, argv[0], "bundleName", bundleName); + ZLOGE_ON_ARGS(ctxt, (ctxt->status == napi_ok) && !bundleName.empty(), "invalid bundleName!"); + + ctxt->ref = JSUtil::NewWithRef(env, argc, argv, (void**)&ctxt->kvManger, JsKVManager::Constructor(env)); + ZLOGE_ON_ARGS(ctxt, ctxt->kvManger != nullptr, "KVManager::New failed!"); + }; + ctxt->GetCbInfo(env, info, input); + + auto noExecute = NapiAsyncExecute(); + auto output = [env, ctxt](napi_value& result) { + ctxt->status = napi_get_reference_value(env, ctxt->ref, &result); + napi_delete_reference(env, ctxt->ref); + ZLOGE_ON_STATUS(ctxt, "output KVManager failed"); + }; + return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), noExecute, output); +} + +struct GetKVStoreContext : public ContextBase { + std::string storeId; + Options options; + JsKVStore* kvStore = nullptr; + napi_ref ref = nullptr; + + void GetCbInfo(napi_env env, napi_callback_info info) + { + auto input = [env, this](size_t argc, napi_value* argv) { + // required 2 arguments :: + ZLOGE_ON_ARGS(this, argc == 2, "invalid arguments!"); + status = JSUtil::GetValue(env, argv[0], storeId); + ZLOGE_ON_ARGS(this, (status == napi_ok) && !storeId.empty(), "invalid storeId!"); + status = JSUtil::GetValue(env, argv[1], options); + ZLOGE_ON_STATUS(this, "invalid options!"); + ZLOGE_ON_ARGS(this, IsStoreTypeSupported(options), "invalid options.KvStoreType"); + ZLOGD("GetKVStore kvStoreType=%{public}d", options.kvStoreType); + if (options.kvStoreType == KvStoreType::DEVICE_COLLABORATION) { + ref = JSUtil::NewWithRef(env, argc, argv, (void**)&kvStore, JsDeviceKVStore::Constructor(env)); + } else if (options.kvStoreType == KvStoreType::SINGLE_VERSION) { + ref = JSUtil::NewWithRef(env, argc, argv, (void**)&kvStore, JsSingleKVStore::Constructor(env)); + } + }; + ContextBase::GetCbInfo(env, info, input); + } +}; + +/* + * [JS API Prototype] + * [AsyncCallback] + * getKVStore(storeId: string, options: Options, callback: AsyncCallback): void; + * [Promise] + * getKVStore(storeId: string, options: Options): Promise; + */ +napi_value JsKVManager::GetKVStore(napi_env env, napi_callback_info info) +{ + ZLOGD("GetKVStore in"); + auto ctxt = std::make_shared(); + ctxt->GetCbInfo(env, info); + + auto execute = [ctxt]() { + auto kvm = reinterpret_cast(ctxt->native); + ZLOGE_ON_ARGS(ctxt, kvm != nullptr, "KVManager is null, failed!"); + AppId appId = { kvm->bundleName_ }; + StoreId storeId = { ctxt->storeId }; + std::shared_ptr kvStore; + Status status = kvm->kvDataManager_.GetSingleKvStore(ctxt->options, appId, storeId, kvStore); + ZLOGD("GetSingleKvStore return status:%{public}d", status); + ctxt->status = (status == Status::SUCCESS) ? napi_ok : napi_generic_failure; + ZLOGE_ON_STATUS(ctxt, "KVManager->GetSingleKvStore() failed!"); + ctxt->kvStore->SetNative(kvStore); + }; + auto output = [env, ctxt](napi_value& result) { + ctxt->status = napi_get_reference_value(env, ctxt->ref, &result); + napi_delete_reference(env, ctxt->ref); + ZLOGE_ON_STATUS(ctxt, "output KvStore failed"); + }; + return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute, output); +} + +/* + * [JS API Prototype] + * [AsyncCB] closeKVStore(appId: string, storeId: string, kvStore: KVStore, callback: AsyncCallback):void + * [Promise] closeKVStore(appId: string, storeId: string, kvStore: KVStore):Promise + */ +napi_value JsKVManager::CloseKVStore(napi_env env, napi_callback_info info) +{ + ZLOGD("CloseKVStore in"); + struct ContextInfo : public ContextBase { + std::string appId; + std::string storeId; + napi_value kvStore; + }; + auto ctxt = std::make_shared(); + auto input = [env, ctxt](size_t argc, napi_value* argv) { + // required 3 arguments :: + ZLOGE_ON_ARGS(ctxt, argc == 3, "invalid arguments!"); + ctxt->status = JSUtil::GetValue(env, argv[0], ctxt->appId); + ZLOGE_ON_ARGS(ctxt, (ctxt->status == napi_ok) && !ctxt->appId.empty(), "invalid appId!"); + ctxt->status = JSUtil::GetValue(env, argv[1], ctxt->storeId); + ZLOGE_ON_ARGS(ctxt, (ctxt->status == napi_ok) && !ctxt->storeId.empty(), "invalid storeId!"); + ZLOGE_ON_ARGS(ctxt, argv[2] != nullptr, "kvStore is nullptr!"); + bool isSingle = JsKVStore::IsInstanceOf(env, argv[2], ctxt->storeId, JsSingleKVStore::Constructor(env)); + bool isDevice = JsKVStore::IsInstanceOf(env, argv[2], ctxt->storeId, JsDeviceKVStore::Constructor(env)); + ZLOGE_ON_ARGS(ctxt, isSingle || isDevice, "kvStore unmatch to storeId!"); + }; + ctxt->GetCbInfo(env, info, input); + + auto execute = [ctxt]() { + AppId appId { ctxt->appId }; + StoreId storeId { ctxt->storeId }; + Status status = reinterpret_cast(ctxt->native)->kvDataManager_.CloseKvStore(appId, storeId); + ZLOGD("CloseKVStore return status:%{public}d", status); + ctxt->status + = ((status == Status::SUCCESS) || (status == Status::STORE_NOT_FOUND) || (status == Status::STORE_NOT_OPEN)) + ? napi_ok + : napi_generic_failure; + }; + return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute); +} + +/* + * [JS API Prototype] + * [AsyncCB] deleteKVStore(appId: string, storeId: string, callback: AsyncCallback): void + * [Promise] deleteKVStore(appId: string, storeId: string):Promise + */ +napi_value JsKVManager::DeleteKVStore(napi_env env, napi_callback_info info) +{ + ZLOGD("DeleteKVStore in"); + struct ContextInfo : public ContextBase { + std::string appId; + std::string storeId; + }; + auto ctxt = std::make_shared(); + auto input = [env, ctxt](size_t argc, napi_value* argv) { + // required 2 arguments :: + ZLOGE_ON_ARGS(ctxt, argc >= 2, "invalid arguments!"); + size_t index = 0; + ctxt->status = JSUtil::GetValue(env, argv[index++], ctxt->appId); + ZLOGE_ON_ARGS(ctxt, !ctxt->appId.empty(), "invalid appId"); + ctxt->status = JSUtil::GetValue(env, argv[index++], ctxt->storeId); + ZLOGE_ON_ARGS(ctxt, !ctxt->storeId.empty(), "invalid storeId"); + }; + ctxt->GetCbInfo(env, info, input); + + auto execute = [ctxt]() { + AppId appId { ctxt->appId }; + StoreId storeId { ctxt->storeId }; + Status status = reinterpret_cast(ctxt->native)->kvDataManager_.DeleteKvStore(appId, storeId); + ZLOGD("DeleteKvStore status:%{public}d", status); + ctxt->status = (status == Status::SUCCESS) ? napi_ok : napi_generic_failure; + }; + return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute); +} + +/* + * [JS API Prototype] + * [AsyncCB] getAllKVStoreId(appId: string, callback: AsyncCallback):void + * [Promise] getAllKVStoreId(appId: string):Promise + */ +napi_value JsKVManager::GetAllKVStoreId(napi_env env, napi_callback_info info) +{ + ZLOGD("GetAllKVStoreId in"); + struct ContextInfo : public ContextBase { + std::string appId; + std::vector storeIdList; + }; + + auto ctxt = std::make_shared(); + auto input = [env, ctxt](size_t argc, napi_value* argv) { + // required 1 arguments :: + ZLOGE_ON_ARGS(ctxt, argc == 1, "invalid arguments!"); + ctxt->status = JSUtil::GetValue(env, argv[0], ctxt->appId); + ZLOGE_ON_ARGS(ctxt, !ctxt->appId.empty(), "invalid appId!"); + }; + ctxt->GetCbInfo(env, info, input); + + auto execute = [ctxt]() { + auto kvm = reinterpret_cast(ctxt->native); + ZLOGE_ON_ARGS(ctxt, kvm != nullptr, "KVManager is null, failed!"); + AppId appId { ctxt->appId }; + Status status = kvm->kvDataManager_.GetAllKvStoreId(appId, ctxt->storeIdList); + ZLOGD("execute status:%{public}d", status); + ctxt->status = (status == Status::SUCCESS) ? napi_ok : napi_generic_failure; + }; + auto output = [env, ctxt](napi_value& result) { + ctxt->status = JSUtil::SetValue(env, ctxt->storeIdList, result); + ZLOGD("output status:%{public}d", ctxt->status); + }; + return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute, output); +} + +napi_value JsKVManager::On(napi_env env, napi_callback_info info) +{ + auto ctxt = std::make_shared(); + auto input = [env, ctxt](size_t argc, napi_value* argv) { + // required 2 arguments :: + ZLOGE_ON_ARGS(ctxt, argc == 2, "invalid arguments!"); + std::string event; + ctxt->status = JSUtil::GetValue(env, argv[0], event); + ZLOGI("subscribe to event:%{public}s", event.c_str()); + ZLOGE_ON_ARGS(ctxt, event == "distributedDataServiceDie", "invalid arg[0], i.e. invalid event!"); + + napi_valuetype valueType = napi_undefined; + ctxt->status = napi_typeof(env, argv[1], &valueType); + ZLOGE_ON_STATUS(ctxt, "napi_typeof failed!"); + ZLOGE_ON_ARGS(ctxt, valueType == napi_function, "callback is not a function"); + + JsKVManager* proxy = reinterpret_cast(ctxt->native); + ZLOGE_ON_ARGS(ctxt, proxy != nullptr, "there is no native kv manager"); + + std::lock_guard lck(proxy->deathMutex_); + for (auto& it : proxy->deathRecipient_) { + auto recipient = std::static_pointer_cast(it); + if (*recipient == argv[1]) { + ZLOGD("KVManager::On callback already register!"); + return; + } + } + auto kvStoreDeathRecipient = std::make_shared(env, argv[1]); + proxy->kvDataManager_.RegisterKvStoreServiceDeathRecipient(kvStoreDeathRecipient); + proxy->deathRecipient_.push_back(kvStoreDeathRecipient); + ZLOGD("on mapsize: %{public}d", static_cast(proxy->deathRecipient_.size())); + }; + NAPI_CALL(env, ctxt->GetCbInfoSync(env, info, input)); + return nullptr; +} + +napi_value JsKVManager::Off(napi_env env, napi_callback_info info) +{ + ZLOGD("KVManager::Off()"); + auto ctxt = std::make_shared(); + auto input = [env, ctxt](size_t argc, napi_value* argv) { + // required 1 or 2 arguments :: [callback] + ZLOGE_ON_ARGS(ctxt, (argc == 1) || (argc == 2), "invalid arguments!"); + std::string event; + ctxt->status = JSUtil::GetValue(env, argv[0], event); + // required 1 arguments :: + ZLOGI("unsubscribe to event:%{public}s %{public}s specified", event.c_str(), (argc == 1) ? "without": "with"); + ZLOGE_ON_ARGS(ctxt, event == "distributedDataServiceDie", "invalid arg[0], i.e. invalid event!"); + // have 2 arguments :: have the [callback] + if (argc == 2) { + napi_valuetype valueType = napi_undefined; + ctxt->status = napi_typeof(env, argv[1], &valueType); + ZLOGE_ON_STATUS(ctxt, "napi_typeof failed!"); + ZLOGE_ON_ARGS(ctxt, valueType == napi_function, "callback is not a function"); + } + JsKVManager* proxy = reinterpret_cast(ctxt->native); + std::lock_guard lck(proxy->deathMutex_); + auto it = proxy->deathRecipient_.begin(); + while (it != proxy->deathRecipient_.end()) { + auto recipient = std::static_pointer_cast(*it); + // have 2 arguments :: have the [callback] + if ((argc == 1) || *recipient == argv[1]) { + proxy->kvDataManager_.UnRegisterKvStoreServiceDeathRecipient(*it); + it = proxy->deathRecipient_.erase(it); + } else { + ++it; + } + } + ZLOGD("off mapsize: %{public}d", static_cast(proxy->deathRecipient_.size())); + }; + NAPI_CALL(env, ctxt->GetCbInfoSync(env, info, input)); + ZLOGD("KVManager::Off callback is not register or already unregister!"); + return nullptr; +} + +napi_value JsKVManager::Constructor(napi_env env) +{ + const napi_property_descriptor properties[] = { + DECLARE_NAPI_FUNCTION("getKVStore", JsKVManager::GetKVStore), + DECLARE_NAPI_FUNCTION("closeKVStore", JsKVManager::CloseKVStore), + DECLARE_NAPI_FUNCTION("deleteKVStore", JsKVManager::DeleteKVStore), + DECLARE_NAPI_FUNCTION("getAllKVStoreId", JsKVManager::GetAllKVStoreId), + DECLARE_NAPI_FUNCTION("on", JsKVManager::On), + DECLARE_NAPI_FUNCTION("off", JsKVManager::Off) + }; + size_t count = sizeof(properties) / sizeof(properties[0]); + return JSUtil::DefineClass(env, "KVManager", properties, count, JsKVManager::New); +} + +napi_value JsKVManager::New(napi_env env, napi_callback_info info) +{ + std::string bundleName; + auto ctxt = std::make_shared(); + auto input = [env, ctxt, &bundleName](size_t argc, napi_value* argv) { + // required 1 arguments :: + ZLOGE_ON_ARGS(ctxt, argc == 1, "invalid arguments!"); + ctxt->status = JSUtil::GetNamedProperty(env, argv[0], "bundleName", bundleName); + ZLOGE_ON_STATUS(ctxt, "invalid arg[0], i.e. invalid bundleName!"); + ZLOGE_ON_ARGS(ctxt, !bundleName.empty(), "invalid arg[0], i.e. invalid bundleName!"); + }; + NAPI_CALL(env, ctxt->GetCbInfoSync(env, info, input)); + + JsKVManager* kvManager = new (std::nothrow) JsKVManager(bundleName); + NAPI_ASSERT(env, kvManager !=nullptr, "no memory for kvManager"); + + auto finalize = [](napi_env env, void* data, void* hint) { + ZLOGD("kvManager finalize."); + auto* kvManager = reinterpret_cast(data); + ZLOGE_RETURN_VOID(kvManager != nullptr, "finalize null!"); + delete kvManager; + }; + NAPI_CALL(env, napi_wrap(env, ctxt->self, kvManager, finalize, nullptr, nullptr)); + return ctxt->self; +} + +DeathRecipient::DeathRecipient(napi_env env, napi_value callback) + : UvQueue(env, callback) +{ +} + +void DeathRecipient::OnRemoteDied() +{ + CallFunction(); +} +} diff --git a/frameworks/jskitsimpl/distributeddata/src/js_kv_store.cpp b/frameworks/jskitsimpl/distributeddata/src/js_kv_store.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8015361d634f96b81dccf183a59a7ea70d5cba22 --- /dev/null +++ b/frameworks/jskitsimpl/distributeddata/src/js_kv_store.cpp @@ -0,0 +1,634 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#define LOG_TAG "JS_KVStore" +#include "js_kv_store.h" +#include "js_util.h" +#include "js_kv_store_resultset.h" +#include "log_print.h" +#include "napi_queue.h" +#include "single_kvstore.h" + +using namespace OHOS::DistributedKv; + +namespace OHOS::DistributedData { +std::map JsKVStore::onEventHandlers_ = { + { "dataChange", JsKVStore::OnDataChange }, + { "syncComplete", JsKVStore::OnSyncComplete } +}; + +std::map JsKVStore::offEventHandlers_ = { + { "dataChange", JsKVStore::OffDataChange }, + { "syncComplete", JsKVStore::OffSyncComplete } +}; + +static bool ValidSubscribeType(uint8_t type) +{ + return (SUBSCRIBE_LOCAL <= type) && (type <= SUBSCRIBE_LOCAL_REMOTE); +} + +static SubscribeType ToSubscribeType(uint8_t type) +{ + return static_cast(type + 1); +} + +JsKVStore::JsKVStore(const std::string& storeId) + : storeId_(storeId) +{ +} + +JsKVStore::~JsKVStore() +{ + ZLOGD("no memory leak for JsKVStore"); + if (kvStore_ == nullptr) { + return; + } + + std::lock_guard lck(listMutex_); + for (uint8_t type = SUBSCRIBE_LOCAL; type < SUBSCRIBE_COUNT; type++) { + for (auto& it : dataObserver_[type]) { + auto observer = std::static_pointer_cast(it); + auto subscribeType = ToSubscribeType(type); + kvStore_->UnSubscribeKvStore(subscribeType, observer); + } + dataObserver_[type].clear(); + } + + if (syncObserver_ != nullptr) { + kvStore_->UnRegisterSyncCallback(); + } +} + +void JsKVStore::SetNative(std::shared_ptr& kvStore) +{ + kvStore_ = kvStore; +} + +std::shared_ptr& JsKVStore::GetNative() +{ + return kvStore_; +} + +bool JsKVStore::IsInstanceOf(napi_env env, napi_value obj, const std::string& storeId, napi_value constructor) +{ + bool result = false; + napi_status status = napi_instanceof(env, obj, constructor, &result); + ZLOGE_RETURN(result, "is not instance of JsKVStore!", false); + + JsKVStore* kvStore = nullptr; + status = napi_unwrap(env, obj, (void**)&kvStore); + ZLOGE_RETURN((status == napi_ok) && (kvStore != nullptr), "can not unwrap to JsKVStore!", false); + return kvStore->storeId_ == storeId; +} + +/* + * [JS API Prototype] + * [AsyncCallback] + * put(key:string, value:Uint8Array | string | boolean | number, callback: AsyncCallback):void; + * [Promise] + * put(key:string, value:Uint8Array | string | boolean | number):Promise; + */ +napi_value JsKVStore::Put(napi_env env, napi_callback_info info) +{ + ZLOGD("KVStore::Put()"); + struct PutContext : public ContextBase { + std::string key; + std::vector value; + }; + + auto ctxt = std::make_shared(); + + ctxt->GetCbInfo(env, info, [env, ctxt](size_t argc, napi_value* argv) { + // required 2 arguments :: + ZLOGE_ON_ARGS(ctxt, argc == 2, "invalid arguments!"); + ctxt->status = JSUtil::GetValue(env, argv[0], ctxt->key); + ZLOGE_ON_STATUS(ctxt, "invalid arg[0], i.e. invalid key!"); + JSUtil::KvStoreVariant vv; + ctxt->status = JSUtil::GetValue(env, argv[1], vv); + ZLOGE_ON_STATUS(ctxt, "invalid arg[1], i.e. invalid value!"); + DistributedKv::Blob blob = JSUtil::VariantValue2Blob(vv); + ctxt->value = blob.Data(); + }); + + auto execute = [ctxt]() { + OHOS::DistributedKv::Key key(ctxt->key); + OHOS::DistributedKv::Value value(ctxt->value); + auto& kvStore = reinterpret_cast(ctxt->native)->kvStore_; + Status status = kvStore->Put(key, value); + ZLOGD("kvStore->Put return %{public}d", status); + ctxt->status = (status == Status::SUCCESS) ? napi_ok : napi_generic_failure; + ZLOGE_ON_STATUS(ctxt, "kvStore->Put() failed!"); + }; + return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute); +} + +/* + * [JS API Prototype] + * [AsyncCallback] + * delete(key: string, callback: AsyncCallback): void; + * [Promise] + * delete(key: string): Promise; + */ +napi_value JsKVStore::Delete(napi_env env, napi_callback_info info) +{ + ZLOGD("KVStore::Delete()"); + struct DeleteContext : public ContextBase { + std::string key; + }; + auto ctxt = std::make_shared(); + + ctxt->GetCbInfo(env, info, [env, ctxt](size_t argc, napi_value* argv) { + // required 1 arguments :: + ZLOGE_ON_ARGS(ctxt, argc == 1, "invalid arguments!"); + ctxt->status = JSUtil::GetValue(env, argv[0], ctxt->key); + ZLOGE_ON_STATUS(ctxt, "invalid arg[0], i.e. invalid key!"); + }); + + return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), [ctxt]() { + OHOS::DistributedKv::Key key(ctxt->key); + auto& kvStore = reinterpret_cast(ctxt->native)->kvStore_; + Status status = kvStore->Delete(key); + ZLOGD("kvStore->Put return %{public}d", status); + ctxt->status = (status == Status::SUCCESS) ? napi_ok : napi_generic_failure; + ZLOGE_ON_STATUS(ctxt, "kvStore->Delete() failed!"); + }); +} + +/* + * [JS API Prototype] + * [Callback] + * on(event:'syncComplete',syncCallback: Callback>):void; + * on(event:'dataChange', subType: SubscribeType, observer: Callback): void; + */ +napi_value JsKVStore::OnEvent(napi_env env, napi_callback_info info) +{ + ZLOGD("in"); + auto ctxt = std::make_shared(); + auto input = [env, ctxt](size_t argc, napi_value* argv) { + // required 2 arguments :: [...] + ZLOGE_ON_ARGS(ctxt, argc >= 2, "invalid arguments!"); + std::string event; + ctxt->status = JSUtil::GetValue(env, argv[0], event); + ZLOGI("subscribe to event:%{public}s", event.c_str()); + auto handle = onEventHandlers_.find(event); + ZLOGE_ON_ARGS(ctxt, handle != onEventHandlers_.end(), "invalid arg[0], i.e. unsupported event"); + // shift 1 argument, for JsKVStore::Exec. + handle->second(env, argc - 1, &argv[1], reinterpret_cast(ctxt->native)); + }; + NAPI_CALL(env, ctxt->GetCbInfoSync(env, info, input)); + return nullptr; +} + +/* + * [JS API Prototype] + * [Callback] + * off(event:'syncComplete',syncCallback: Callback>):void; + * off(event:'dataChange', subType: SubscribeType, observer: Callback): void; + */ +napi_value JsKVStore::OffEvent(napi_env env, napi_callback_info info) +{ + ZLOGD("in"); + auto ctxt = std::make_shared(); + auto input = [env, ctxt](size_t argc, napi_value* argv) { + // required 1 arguments :: [callback] + ZLOGE_ON_ARGS(ctxt, argc >= 1, "invalid arguments!"); + std::string event; + ctxt->status = JSUtil::GetValue(env, argv[0], event); + ZLOGI("unsubscribe to event:%{public}s", event.c_str()); + auto handle = offEventHandlers_.find(event); + ZLOGE_ON_ARGS(ctxt, handle != offEventHandlers_.end(), "invalid arg[0], i.e. unsupported event"); + // shift 1 argument, for JsKVStore::Exec. + handle->second(env, argc - 1, &argv[1], reinterpret_cast(ctxt->native)); + }; + NAPI_CALL(env, ctxt->GetCbInfoSync(env, info, input)); + return nullptr; +} + +/* + * [JS API Prototype] + * [AsyncCallback] + * putBatch(entries: Entry[], callback: AsyncCallback):void; + * [Promise] + * putBatch(entries: Entry[]):Promise; + */ +napi_value JsKVStore::PutBatch(napi_env env, napi_callback_info info) +{ + struct PutBatchContext : public ContextBase { + std::vector entries; + }; + auto ctxt = std::make_shared(); + + ctxt->GetCbInfo(env, info, [env, ctxt](size_t argc, napi_value* argv) { + // required 1 arguments :: + ZLOGE_ON_ARGS(ctxt, argc == 1, "invalid arguments!"); + ctxt->status = JSUtil::GetValue(env, argv[0], ctxt->entries); + ZLOGE_ON_STATUS(ctxt, "invalid arg[0], i.e. invalid entries!"); + }); + + auto execute = [ctxt]() { + auto& kvStore = reinterpret_cast(ctxt->native)->kvStore_; + Status status = kvStore->PutBatch(ctxt->entries); + ZLOGD("kvStore->DeleteBatch return %{public}d", status); + ctxt->status = (status == Status::SUCCESS) ? napi_ok : napi_generic_failure; + ZLOGE_ON_STATUS(ctxt, "kvStore->PutBatch() failed!"); + }; + return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute); +} + +/* + * [JS API Prototype] + * [AsyncCallback] + * deleteBatch(keys: string[], callback: AsyncCallback):void; + * [Promise] + * deleteBatch(keys: string[]):Promise; + */ +napi_value JsKVStore::DeleteBatch(napi_env env, napi_callback_info info) +{ + struct DeleteBatchContext : public ContextBase { + std::vector keys; + }; + auto ctxt = std::make_shared(); + auto input = [env, ctxt](size_t argc, napi_value* argv) { + // required 1 arguments :: + ZLOGE_ON_ARGS(ctxt, argc == 1, "invalid arguments!"); + JSUtil::GetValue(env, argv[0], ctxt->keys); + ZLOGE_ON_STATUS(ctxt, "invalid arg[0], i.e. invalid keys!"); + }; + ctxt->GetCbInfo(env, info, input); + + auto execute = [ctxt]() { + std::vector keys; + for (auto it : ctxt->keys) { + DistributedKv::Key key(it); + keys.push_back(key); + } + auto& kvStore = reinterpret_cast(ctxt->native)->kvStore_; + Status status = kvStore->DeleteBatch(keys); + ZLOGD("kvStore->DeleteBatch return %{public}d", status); + ctxt->status = (status == Status::SUCCESS) ? napi_ok : napi_generic_failure; + ZLOGE_ON_STATUS(ctxt, "kvStore->DeleteBatch failed!"); + }; + return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute); +} + +/* + * [JS API Prototype] + * [AsyncCallback] + * startTransaction(callback: AsyncCallback):void; + * [Promise] + * startTransaction() : Promise; + */ +napi_value JsKVStore::StartTransaction(napi_env env, napi_callback_info info) +{ + auto ctxt = std::make_shared(); + ctxt->GetCbInfo(env, info); + + auto execute = [ctxt]() { + auto& kvStore = reinterpret_cast(ctxt->native)->kvStore_; + Status status = kvStore->StartTransaction(); + ZLOGD("kvStore->StartTransaction return %{public}d", status); + ctxt->status = (status == Status::SUCCESS) ? napi_ok : napi_generic_failure; + ZLOGE_ON_STATUS(ctxt, "kvStore->StartTransaction() failed!"); + }; + return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute); +} + +/* + * [JS API Prototype] + * [AsyncCallback] + * commit(callback: AsyncCallback):void; + * [Promise] + * commit() : Promise; + */ +napi_value JsKVStore::Commit(napi_env env, napi_callback_info info) +{ + auto ctxt = std::make_shared(); + ctxt->GetCbInfo(env, info); + + auto execute = [ctxt]() { + auto& kvStore = reinterpret_cast(ctxt->native)->kvStore_; + Status status = kvStore->Commit(); + ZLOGD("kvStore->Commit return %{public}d", status); + ctxt->status = (status == Status::SUCCESS) ? napi_ok : napi_generic_failure; + ZLOGE_ON_STATUS(ctxt, "kvStore->Commit() failed!"); + }; + return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute); +} + +/* + * [JS API Prototype] + * [AsyncCallback] + * rollback(callback: AsyncCallback):void; + * [Promise] + * rollback() : Promise; + */ +napi_value JsKVStore::Rollback(napi_env env, napi_callback_info info) +{ + auto ctxt = std::make_shared(); + ctxt->GetCbInfo(env, info); + + auto execute = [ctxt]() { + auto& kvStore = reinterpret_cast(ctxt->native)->kvStore_; + Status status = kvStore->Rollback(); + ZLOGD("kvStore->Commit return %{public}d", status); + ctxt->status = (status == Status::SUCCESS) ? napi_ok : napi_generic_failure; + ZLOGE_ON_STATUS(ctxt, "kvStore->Rollback() failed!"); + }; + return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute); +} + +/* + * [JS API Prototype] + * [AsyncCallback] + * enableSync(enabled:boolean, callback: AsyncCallback):void; + * [Promise] + * enableSync(enabled:boolean) : Promise; + */ +napi_value JsKVStore::EnableSync(napi_env env, napi_callback_info info) +{ + struct EnableSyncContext : public ContextBase { + bool enable = false; + }; + auto ctxt = std::make_shared(); + auto input = [env, ctxt](size_t argc, napi_value* argv) { + // required 1 arguments :: + ZLOGE_ON_ARGS(ctxt, argc == 1, "invalid arguments!"); + ctxt->status = napi_get_value_bool(env, argv[0], &ctxt->enable); + ZLOGE_ON_STATUS(ctxt, "invalid arg[0], i.e. invalid enabled!"); + }; + ctxt->GetCbInfo(env, info, input); + + auto execute = [ctxt]() { + auto& kvStore = reinterpret_cast(ctxt->native)->kvStore_; + Status status = kvStore->SetCapabilityEnabled(ctxt->enable); + ZLOGD("kvStore->SetCapabilityEnabled return %{public}d", status); + ctxt->status = (status == Status::SUCCESS) ? napi_ok : napi_generic_failure; + ZLOGE_ON_STATUS(ctxt, "kvStore->SetCapabilityEnabled() failed!"); + }; + return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute); +} + +/* + * [JS API Prototype] + * [AsyncCallback] + * setSyncRange(localLabels:string[], remoteSupportLabels:string[], callback: AsyncCallback):void; + * [Promise] + * setSyncRange(localLabels:string[], remoteSupportLabels:string[]) : Promise; + */ +napi_value JsKVStore::SetSyncRange(napi_env env, napi_callback_info info) +{ + struct SyncRangeContext : public ContextBase { + std::vector localLabels; + std::vector remoteSupportLabels; + }; + auto ctxt = std::make_shared(); + auto input = [env, ctxt](size_t argc, napi_value* argv) { + // required 2 arguments :: + ZLOGE_ON_ARGS(ctxt, argc == 2, "invalid arguments!"); + ctxt->status = JSUtil::GetValue(env, argv[0], ctxt->localLabels); + ZLOGE_ON_STATUS(ctxt, "invalid arg[0], i.e. invalid localLabels!"); + ctxt->status = JSUtil::GetValue(env, argv[1], ctxt->remoteSupportLabels); + ZLOGE_ON_STATUS(ctxt, "invalid arg[1], i.e. invalid remoteSupportLabels!"); + }; + ctxt->GetCbInfo(env, info, input); + + auto execute = [ctxt]() { + auto& kvStore = reinterpret_cast(ctxt->native)->kvStore_; + Status status = kvStore->SetCapabilityRange(ctxt->localLabels, ctxt->remoteSupportLabels); + ZLOGD("kvStore->SetCapabilityRange return %{public}d", status); + ctxt->status = (status == Status::SUCCESS) ? napi_ok : napi_generic_failure; + ZLOGE_ON_STATUS(ctxt, "kvStore->SetCapabilityRange() failed!"); + }; + return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute); +} + +/* + * [JS API Prototype] JsKVStore::OnDataChange is private non-static. + * [Callback] + * on(event:'dataChange', subType: SubscribeType, observer: Callback): void; + */ +napi_status JsKVStore::OnDataChange(napi_env env, size_t argc, napi_value* argv, JsKVStore* proxy) +{ + // required 2 arguments :: + NAPI_ASSERT_BASE(env, argc == 2, "invalid arguments on dataChange!", napi_invalid_arg); + + int32_t type = SUBSCRIBE_COUNT; + napi_get_value_int32(env, argv[0], &type); + NAPI_ASSERT_BASE(env, ValidSubscribeType(type), "invalid arg[1], i.e. invalid subscribeType", napi_invalid_arg); + + napi_valuetype valueType = napi_undefined; + NAPI_CALL_BASE(env, napi_typeof(env, argv[1], &valueType), napi_invalid_arg); + NAPI_ASSERT_BASE(env, valueType == napi_function, "invalid arg[2], i.e. invalid callback", napi_invalid_arg); + + ZLOGI("subscribe data change type %{public}d", type); + std::lock_guard lck(proxy->listMutex_); + for (auto& it : proxy->dataObserver_[type]) { + auto observer = std::static_pointer_cast(it); + if (*observer == argv[1]) { + ZLOGI("function is already subscribe type"); + return napi_ok; + } + } + + std::shared_ptr observer = std::make_shared(env, argv[1]); + napi_status status = proxy->Subscribe(type, observer); + NAPI_ASSERT_BASE(env, status == napi_ok, "Subscribe failed!", status); + return status; +} + +/* + * [JS API Prototype] JsKVStore::OffDataChange is private non-static. + * [Callback] + * on(event:'dataChange', subType: SubscribeType, observer: Callback): void; + * [NOTES!!!] no SubscribeType while off... + * off(event:'dataChange', observer: Callback): void; + */ +napi_status JsKVStore::OffDataChange(napi_env env, size_t argc, napi_value* argv, JsKVStore* proxy) +{ + // required 1 arguments :: [callback] + NAPI_ASSERT_BASE(env, argc <= 1, "invalid arguments, too many arguments!", napi_invalid_arg); + // have 1 arguments :: have the callback + if (argc == 1) { + napi_valuetype valueType = napi_undefined; + NAPI_CALL_BASE(env, napi_typeof(env, argv[0], &valueType), napi_invalid_arg); + NAPI_ASSERT_BASE(env, valueType == napi_function, "invalid arg[1], i.e. invalid callback", napi_invalid_arg); + } + ZLOGI("unsubscribe dataChange, %{public}s specified observer.", (argc == 0) ? "without": "with"); + + bool found = false; + napi_status status = napi_ok; + auto traverse1Type = [argc, argv, proxy, &found, &status](uint8_t type, auto& observers) { + auto it = observers.begin(); + while (it != observers.end()) { + auto observer = std::static_pointer_cast(*it); + if ((argc == 1) && !(*observer == argv[0])) { + ++it; + continue; // specified observer and not current iterator + } + found = true; + status = proxy->UnSubscribe(type, observer); + if (status != napi_ok) { + break; // stop on fail. + } + it = observers.erase(it); + } + }; + + std::lock_guard lck(proxy->listMutex_); + for (uint8_t type = SUBSCRIBE_LOCAL; type < SUBSCRIBE_COUNT; type++) { + traverse1Type(type, proxy->dataObserver_[type]); + if (status != napi_ok) { + break; // stop on fail. + } + } + found |= (argc == 0); // no specified observer, don't care about found or not. + + NAPI_ASSERT_BASE(env, found, "not Subscribed!", status); + NAPI_ASSERT_BASE(env, status == napi_ok, "UnSubscribe failed!", status); + return status; +} + +/* + * [JS API Prototype] JsKVStore::OnSyncComplete is private non-static. + * [Callback] + * on(event:'syncComplete',syncCallback: Callback>):void; + */ +napi_status JsKVStore::OnSyncComplete(napi_env env, size_t argc, napi_value* argv, JsKVStore* proxy) +{ + // required 1 arguments :: + NAPI_ASSERT_BASE(env, argc == 1, "invalid arguments on syncComplete!", napi_invalid_arg); + napi_valuetype valueType = napi_undefined; + NAPI_CALL_BASE(env, napi_typeof(env, argv[0], &valueType), napi_invalid_arg); + NAPI_ASSERT_BASE(env, valueType == napi_function, "invalid arg[1], i.e. invalid callback", napi_invalid_arg); + + std::shared_ptr callback = std::make_shared(env, argv[0]); + return proxy->RegisterSyncCallback(callback); +} + +/* + * [JS API Prototype] JsKVStore::OffSyncComplete is private non-static. + * [Callback] + * off(event:'syncComplete',syncCallback: Callback>):void; + */ +napi_status JsKVStore::OffSyncComplete(napi_env env, size_t argc, napi_value* argv, JsKVStore* proxy) +{ + // required 1 arguments :: [callback] + NAPI_ASSERT_BASE(env, argc <= 1, "invalid arguments, too many arguments!", napi_invalid_arg); + ZLOGI("unsubscribe syncComplete, %{public}s specified observer.", (argc == 0) ? "without": "with"); + // have 1 arguments :: have the callback + if (argc == 1) { + napi_valuetype valueType = napi_undefined; + NAPI_CALL_BASE(env, napi_typeof(env, argv[0], &valueType), napi_invalid_arg); + NAPI_ASSERT_BASE(env, valueType == napi_function, "invalid arg[1], i.e. invalid callback", napi_invalid_arg); + auto observer = std::static_pointer_cast(proxy->syncObserver_); + NAPI_ASSERT_BASE(env, *observer == argv[0], "invalid arg[1], not Subscribed", napi_invalid_arg); + } + return proxy->UnRegisterSyncCallback(); +} + +/* + * [Internal private non-static] + */ +napi_status JsKVStore::RegisterSyncCallback(std::shared_ptr callback) +{ + if (syncObserver_) { + kvStore_->UnRegisterSyncCallback(); + syncObserver_.reset(); + } + + Status status = kvStore_->RegisterSyncCallback(callback); + if (status != Status::SUCCESS) { + return napi_generic_failure; + } + syncObserver_ = callback; + return napi_ok; +} + +napi_status JsKVStore::UnRegisterSyncCallback() +{ + Status status = kvStore_->UnRegisterSyncCallback(); + if (status != Status::SUCCESS) { + return napi_generic_failure; + } + syncObserver_.reset(); + return napi_ok; +} + +napi_status JsKVStore::Subscribe(uint8_t type, std::shared_ptr observer) +{ + auto subscribeType = ToSubscribeType(type); + Status status = kvStore_->SubscribeKvStore(subscribeType, observer); + ZLOGD("kvStore_->SubscribeKvStore(%{public}d) return %{public}d", type, status); + if (status == Status::SUCCESS) { + dataObserver_[type].push_back(observer); + } + return (status == Status::SUCCESS) ? napi_ok : napi_generic_failure; +} + +napi_status JsKVStore::UnSubscribe(uint8_t type, std::shared_ptr observer) +{ + auto subscribeType = ToSubscribeType(type); + Status status = kvStore_->UnSubscribeKvStore(subscribeType, observer); + ZLOGD("kvStore_->UnSubscribeKvStore(%{public}d) return %{public}d", type, status); + return (status == Status::SUCCESS) ? napi_ok : napi_generic_failure; +} + +/* + * DataObserver + */ +DataObserver::DataObserver(napi_env env, napi_value callback) + : UvQueue(env, callback) +{ +} + +void DataObserver::OnChange(const ChangeNotification& notification, std::shared_ptr snapshot) +{ + ZLOGD("data change insert:%{public}zu, update:%{public}zu, delete:%{public}zu", + notification.GetInsertEntries().size(), notification.GetUpdateEntries().size(), + notification.GetDeleteEntries().size()); +} + +void DataObserver::OnChange(const ChangeNotification& notification) +{ + ZLOGD("data change insert:%{public}zu, update:%{public}zu, delete:%{public}zu", + notification.GetInsertEntries().size(), notification.GetUpdateEntries().size(), + notification.GetDeleteEntries().size()); + KvStoreObserver::OnChange(notification); + + auto args = [notification](napi_env env, int& argc, napi_value* argv) { + // generate 1 arguments for callback function. + argc = 1; + JSUtil::SetValue(env, notification, argv[0]); + }; + CallFunction(args); +} + +/* + * SyncObserver + */ +SyncObserver::SyncObserver(napi_env env, napi_value callback) + : UvQueue(env, callback) +{ +} + +void SyncObserver::SyncCompleted(const std::map& results) +{ + auto args = [results](napi_env env, int& argc, napi_value* argv) { + // generate 1 arguments for callback function. + argc = 1; + JSUtil::SetValue(env, results, argv[0]); + }; + CallFunction(args); +} +} // namespace OHOS::DistributedData diff --git a/frameworks/jskitsimpl/distributeddata/src/js_kv_store_resultset.cpp b/frameworks/jskitsimpl/distributeddata/src/js_kv_store_resultset.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a38ed3c9dae6a5c4c08cddfb532c52e49b714813 --- /dev/null +++ b/frameworks/jskitsimpl/distributeddata/src/js_kv_store_resultset.cpp @@ -0,0 +1,260 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#define LOG_TAG "JS_KVStoreResultSet" +#include "js_kv_store_resultset.h" +#include "js_util.h" +#include "log_print.h" +#include "napi_queue.h" +#include "uv_queue.h" + +using namespace OHOS::DistributedKv; +namespace OHOS::DistributedData { +void JsKVStoreResultSet::SetNative(std::shared_ptr& resultSet) +{ + resultSet_ = resultSet; +} + +std::shared_ptr& JsKVStoreResultSet::GetNative() +{ + return resultSet_; +} + +napi_value JsKVStoreResultSet::Constructor(napi_env env) +{ + const napi_property_descriptor properties[] = { + DECLARE_NAPI_FUNCTION("getCount", JsKVStoreResultSet::GetCount), + DECLARE_NAPI_FUNCTION("getPosition", JsKVStoreResultSet::GetPosition), + DECLARE_NAPI_FUNCTION("moveToFirst", JsKVStoreResultSet::MoveToFirst), + DECLARE_NAPI_FUNCTION("moveToLast", JsKVStoreResultSet::MoveToLast), + DECLARE_NAPI_FUNCTION("moveToNext", JsKVStoreResultSet::MoveToNext), + DECLARE_NAPI_FUNCTION("moveToPrevious", JsKVStoreResultSet::MoveToPrevious), + DECLARE_NAPI_FUNCTION("move", JsKVStoreResultSet::Move), + DECLARE_NAPI_FUNCTION("moveToPosition", JsKVStoreResultSet::MoveToPosition), + DECLARE_NAPI_FUNCTION("isFirst", JsKVStoreResultSet::IsFirst), + DECLARE_NAPI_FUNCTION("isLast", JsKVStoreResultSet::IsLast), + DECLARE_NAPI_FUNCTION("isBeforeFirst", JsKVStoreResultSet::IsBeforeFirst), + DECLARE_NAPI_FUNCTION("isAfterLast", JsKVStoreResultSet::IsAfterLast), + DECLARE_NAPI_FUNCTION("getEntry", JsKVStoreResultSet::GetEntry) + }; + size_t count = sizeof(properties) / sizeof(properties[0]); + return JSUtil::DefineClass(env, "KVStoreResultSet", properties, count, JsKVStoreResultSet::New); +} + +napi_value JsKVStoreResultSet::New(napi_env env, napi_callback_info info) +{ + ZLOGD("constructor JsKVStoreResultSet!"); + auto ctxt = std::make_shared(); + NAPI_CALL(env, ctxt->GetCbInfoSync(env, info)); + + JsKVStoreResultSet* resultSet = new (std::nothrow) JsKVStoreResultSet(); + NAPI_ASSERT(env, resultSet !=nullptr, "no memory for resultSet"); + + auto finalize = [](napi_env env, void* data, void* hint) { + ZLOGD("kvStoreResultSet finalize."); + auto* resultSet = reinterpret_cast(data); + ZLOGE_RETURN_VOID(resultSet != nullptr, "finalize null!"); + delete resultSet; + }; + NAPI_CALL(env, napi_wrap(env, ctxt->self, resultSet, finalize, nullptr, nullptr)); + return ctxt->self; +} + +napi_value JsKVStoreResultSet::GetCount(napi_env env, napi_callback_info info) /* number */ +{ + ZLOGD("KVStoreResultSet::GetCount()"); + auto ctxt = std::make_shared(); + NAPI_CALL(env, ctxt->GetCbInfoSync(env, info)); + ZLOGD("KVStoreResultSet::GetCount(status=%{public}d)", ctxt->status); + + auto& resultSet = reinterpret_cast(ctxt->native)->resultSet_; + int count = resultSet->GetCount(); + + napi_create_int32(env, count, &ctxt->output); + return ctxt->output; +} + +napi_value JsKVStoreResultSet::GetPosition(napi_env env, napi_callback_info info) /* number */ +{ + ZLOGD("KVStoreResultSet::GetPosition()"); + auto ctxt = std::make_shared(); + NAPI_CALL(env, ctxt->GetCbInfoSync(env, info)); + + auto& resultSet = reinterpret_cast(ctxt->native)->resultSet_; + int position = resultSet->GetPosition(); + + napi_create_int32(env, position, &ctxt->output); + return ctxt->output; +} + +napi_value JsKVStoreResultSet::MoveToFirst(napi_env env, napi_callback_info info) /* boolean */ +{ + ZLOGD("KVStoreResultSet::MoveToFirst()"); + auto ctxt = std::make_shared(); + NAPI_CALL(env, ctxt->GetCbInfoSync(env, info)); + + auto& resultSet = reinterpret_cast(ctxt->native)->resultSet_; + bool isMoved = resultSet->MoveToFirst(); + + napi_get_boolean(env, isMoved, &ctxt->output); + return ctxt->output; +} + +napi_value JsKVStoreResultSet::MoveToLast(napi_env env, napi_callback_info info) /* boolean */ +{ + ZLOGD("KVStoreResultSet::MoveToFirst()"); + auto ctxt = std::make_shared(); + NAPI_CALL(env, ctxt->GetCbInfoSync(env, info)); + + auto& resultSet = reinterpret_cast(ctxt->native)->resultSet_; + bool isMoved = resultSet->MoveToLast(); + + napi_get_boolean(env, isMoved, &ctxt->output); + return ctxt->output; +} + +napi_value JsKVStoreResultSet::MoveToNext(napi_env env, napi_callback_info info) /* boolean */ +{ + ZLOGD("KVStoreResultSet::MoveToNext()"); + auto ctxt = std::make_shared(); + NAPI_CALL(env, ctxt->GetCbInfoSync(env, info)); + + auto& resultSet = reinterpret_cast(ctxt->native)->resultSet_; + bool isMoved = resultSet->MoveToNext(); + + napi_get_boolean(env, isMoved, &ctxt->output); + return ctxt->output; +} + +napi_value JsKVStoreResultSet::MoveToPrevious(napi_env env, napi_callback_info info) /* boolean */ +{ + ZLOGD("KVStoreResultSet::MoveToPrevious()"); + auto ctxt = std::make_shared(); + NAPI_CALL(env, ctxt->GetCbInfoSync(env, info)); + + auto& resultSet = reinterpret_cast(ctxt->native)->resultSet_; + bool isMoved = resultSet->MoveToPrevious(); + + napi_get_boolean(env, isMoved, &ctxt->output); + return ctxt->output; +} + +napi_value JsKVStoreResultSet::Move(napi_env env, napi_callback_info info) /* boolean */ +{ + ZLOGD("KVStoreResultSet::Move()"); + int offset = 0; + auto ctxt = std::make_shared(); + auto input = [env, ctxt, &offset](size_t argc, napi_value* argv) { + // required 1 arguments :: + ZLOGE_ON_ARGS(ctxt, argc == 1, "invalid arguments!"); + ctxt->status = napi_get_value_int32(env, argv[0], (int32_t*)&offset); + }; + NAPI_CALL(env, ctxt->GetCbInfoSync(env, info, input)); + + auto& resultSet = reinterpret_cast(ctxt->native)->resultSet_; + bool isMoved = resultSet->Move(offset); + + napi_get_boolean(env, isMoved, &ctxt->output); + return ctxt->output; +} + +napi_value JsKVStoreResultSet::MoveToPosition(napi_env env, napi_callback_info info) /* boolean */ +{ + int position = 0; + auto ctxt = std::make_shared(); + auto input = [env, ctxt, &position](size_t argc, napi_value* argv) { + // required 1 arguments :: + ZLOGE_ON_ARGS(ctxt, argc == 1, "invalid arguments!"); + ctxt->status = napi_get_value_int32(env, argv[0], (int32_t*)&position); + }; + NAPI_CALL(env, ctxt->GetCbInfoSync(env, info, input)); + ZLOGD("KVStoreResultSet::MoveToPosition(%{public}d)", position); + + auto& resultSet = reinterpret_cast(ctxt->native)->resultSet_; + bool isMoved = resultSet->MoveToPosition(position); + + napi_get_boolean(env, isMoved, &ctxt->output); + return ctxt->output; +} + +napi_value JsKVStoreResultSet::IsFirst(napi_env env, napi_callback_info info) /* boolean */ +{ + ZLOGD("KVStoreResultSet::IsFirst()"); + auto ctxt = std::make_shared(); + NAPI_CALL(env, ctxt->GetCbInfoSync(env, info)); + + auto& resultSet = reinterpret_cast(ctxt->native)->resultSet_; + bool isFirst = resultSet->IsFirst(); + + napi_get_boolean(env, isFirst, &ctxt->output); + return ctxt->output; +} + +napi_value JsKVStoreResultSet::IsLast(napi_env env, napi_callback_info info) /* boolean */ +{ + ZLOGD("KVStoreResultSet::IsLast()"); + auto ctxt = std::make_shared(); + NAPI_CALL(env, ctxt->GetCbInfoSync(env, info)); + + auto& resultSet = reinterpret_cast(ctxt->native)->resultSet_; + bool isLast = resultSet->IsLast(); + + napi_get_boolean(env, isLast, &ctxt->output); + return ctxt->output; +} + +napi_value JsKVStoreResultSet::IsBeforeFirst(napi_env env, napi_callback_info info) /* boolean */ +{ + ZLOGD("KVStoreResultSet::IsBeforeFirst()"); + auto ctxt = std::make_shared(); + NAPI_CALL(env, ctxt->GetCbInfoSync(env, info)); + + auto& resultSet = reinterpret_cast(ctxt->native)->resultSet_; + bool isBeforeFirst = resultSet->IsBeforeFirst(); + + napi_get_boolean(env, isBeforeFirst, &ctxt->output); + return ctxt->output; +} + +napi_value JsKVStoreResultSet::IsAfterLast(napi_env env, napi_callback_info info) /* boolean */ +{ + ZLOGD("KVStoreResultSet::IsAfterLast()"); + auto ctxt = std::make_shared(); + NAPI_CALL(env, ctxt->GetCbInfoSync(env, info)); + + auto& resultSet = reinterpret_cast(ctxt->native)->resultSet_; + bool isAfterLast = resultSet->IsAfterLast(); + + napi_get_boolean(env, isAfterLast, &ctxt->output); + return ctxt->output; +} + +napi_value JsKVStoreResultSet::GetEntry(napi_env env, napi_callback_info info) /* Entry */ +{ + ZLOGD("KVStoreResultSet::GetEntry()"); + auto ctxt = std::make_shared(); + NAPI_CALL(env, ctxt->GetCbInfoSync(env, info)); + + DistributedKv::Entry entry; + auto& resultSet = reinterpret_cast(ctxt->native)->resultSet_; + auto status = resultSet->GetEntry(entry); + if (status != Status::SUCCESS) { + return nullptr; + } + + ctxt->status = JSUtil::SetValue(env, entry, ctxt->output); + NAPI_ASSERT(env, ctxt->status == napi_ok, "GetEntry failed!"); + return ctxt->output; +} +} // \ No newline at end of file diff --git a/frameworks/jskitsimpl/distributeddata/src/js_query.cpp b/frameworks/jskitsimpl/distributeddata/src/js_query.cpp new file mode 100644 index 0000000000000000000000000000000000000000..377508616c66af80ece90df7d50aec458e26658b --- /dev/null +++ b/frameworks/jskitsimpl/distributeddata/src/js_query.cpp @@ -0,0 +1,640 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#define LOG_TAG "JS_Query" +#include "js_query.h" +#include "js_util.h" +#include "log_print.h" +#include "napi_queue.h" +#include "uv_queue.h" + +using namespace OHOS::DistributedKv; + +namespace OHOS::DistributedData { +DataQuery& JsQuery::GetNative() +{ + return query_; +} + +napi_value JsQuery::Constructor(napi_env env) +{ + const napi_property_descriptor properties[] = { + DECLARE_NAPI_FUNCTION("reset", JsQuery::Reset), + DECLARE_NAPI_FUNCTION("equalTo", JsQuery::EqualTo), + DECLARE_NAPI_FUNCTION("notEqualTo", JsQuery::NotEqualTo), + DECLARE_NAPI_FUNCTION("greaterThan", JsQuery::GreaterThan), + DECLARE_NAPI_FUNCTION("lessThan", JsQuery::LessThan), + DECLARE_NAPI_FUNCTION("greaterThanOrEqualTo", JsQuery::GreaterThanOrEqualTo), + DECLARE_NAPI_FUNCTION("lessThanOrEqualTo", JsQuery::LessThanOrEqualTo), + DECLARE_NAPI_FUNCTION("isNull", JsQuery::IsNull), + DECLARE_NAPI_FUNCTION("inNumber", JsQuery::InNumber), + DECLARE_NAPI_FUNCTION("inString", JsQuery::InString), + DECLARE_NAPI_FUNCTION("notInNumber", JsQuery::NotInNumber), + DECLARE_NAPI_FUNCTION("notInString", JsQuery::NotInString), + DECLARE_NAPI_FUNCTION("like", JsQuery::Like), + DECLARE_NAPI_FUNCTION("unlike", JsQuery::Unlike), + DECLARE_NAPI_FUNCTION("and", JsQuery::And), + DECLARE_NAPI_FUNCTION("or", JsQuery::Or), + DECLARE_NAPI_FUNCTION("orderByAsc", JsQuery::OrderByAsc), + DECLARE_NAPI_FUNCTION("orderByDesc", JsQuery::OrderByDesc), + DECLARE_NAPI_FUNCTION("limit", JsQuery::Limit), + DECLARE_NAPI_FUNCTION("isNotNull", JsQuery::IsNotNull), + DECLARE_NAPI_FUNCTION("beginGroup", JsQuery::BeginGroup), + DECLARE_NAPI_FUNCTION("endGroup", JsQuery::EndGroup), + DECLARE_NAPI_FUNCTION("prefixKey", JsQuery::PrefixKey), + DECLARE_NAPI_FUNCTION("setSuggestIndex", JsQuery::SetSuggestIndex), + DECLARE_NAPI_FUNCTION("deviceId", JsQuery::DeviceId), + DECLARE_NAPI_FUNCTION("getSqlLike", JsQuery::GetSqlLike) + }; + size_t count = sizeof(properties) / sizeof(properties[0]); + return JSUtil::DefineClass(env, "Query", properties, count, JsQuery::New); +} + +/* + * [JS API Prototype] + * var query = new ddm.JsQuery(); + */ +napi_value JsQuery::New(napi_env env, napi_callback_info info) +{ + auto ctxt = std::make_shared(); + NAPI_CALL(env, ctxt->GetCbInfoSync(env, info)); + + JsQuery* query = new (std::nothrow) JsQuery(); + NAPI_ASSERT(env, query !=nullptr, "no memory for query"); + + auto finalize = [](napi_env env, void* data, void* hint) { + ZLOGD("query finalize."); + auto* query = reinterpret_cast(data); + ZLOGE_RETURN_VOID(query != nullptr, "finalize null!"); + delete query; + }; + NAPI_CALL(env, napi_wrap(env, ctxt->self, query, finalize, nullptr, nullptr)); + return ctxt->self; +} + +napi_value JsQuery::Reset(napi_env env, napi_callback_info info) +{ + ZLOGD("Query::Reset()"); + auto ctxt = std::make_shared(); + NAPI_CALL(env, ctxt->GetCbInfoSync(env, info)); + + auto& query = reinterpret_cast(ctxt->native)->query_; + query.Reset(); + return ctxt->self; +} + +struct ValueContext : public ContextBase { + std::string field; + JSUtil::QueryVariant vv; + + napi_status GetValueSync(napi_env env, napi_callback_info info) + { + auto input = [this, env](size_t argc, napi_value* argv) { + // required 2 arguments :: + ZLOGE_ON_ARGS(this, argc == 2, "invalid arguments!"); + status = JSUtil::GetValue(env, argv[0], field); + ZLOGE_ON_STATUS(this, "invalid arg[0], i.e. invalid field!"); + status = JSUtil::GetValue(env, argv[1], vv); + ZLOGE_ON_STATUS(this, "invalid arg[1], i.e. invalid value!"); + }; + return GetCbInfoSync(env, info, input); + } +}; + +/* [js] equalTo(field:string, value:number|string|boolean):JsQuery */ +napi_value JsQuery::EqualTo(napi_env env, napi_callback_info info) +{ + ZLOGD("Query::EqualTo()"); + auto ctxt = std::make_shared(); + NAPI_CALL(env, ctxt->GetValueSync(env, info)); + + auto& query = reinterpret_cast(ctxt->native)->query_; + auto strValue = std::get_if(&ctxt->vv); + if (strValue != nullptr) { + query.EqualTo(ctxt->field, *strValue); + } else { + auto boolValue = std::get_if(&ctxt->vv); + if (boolValue != nullptr) { + query.EqualTo(ctxt->field, *boolValue); + } else { + auto dblValue = std::get_if(&ctxt->vv); + if (dblValue != nullptr) { + query.EqualTo(ctxt->field, *dblValue); + } + } + } + return ctxt->self; +} + +napi_value JsQuery::NotEqualTo(napi_env env, napi_callback_info info) +{ + ZLOGD("Query::NotEqualTo()"); + auto ctxt = std::make_shared(); + NAPI_CALL(env, ctxt->GetValueSync(env, info)); + + auto& query = reinterpret_cast(ctxt->native)->query_; + auto strValue = std::get_if(&ctxt->vv); + if (strValue != nullptr) { + query.NotEqualTo(ctxt->field, *strValue); + } else { + auto boolValue = std::get_if(&ctxt->vv); + if (boolValue != nullptr) { + query.NotEqualTo(ctxt->field, *boolValue); + } else { + auto dblValue = std::get_if(&ctxt->vv); + if (dblValue != nullptr) { + query.NotEqualTo(ctxt->field, *dblValue); + } + } + } + return ctxt->self; +} + +napi_value JsQuery::GreaterThan(napi_env env, napi_callback_info info) +{ + ZLOGD("Query::GreaterThan()"); + auto ctxt = std::make_shared(); + NAPI_CALL(env, ctxt->GetValueSync(env, info)); + + auto& query = reinterpret_cast(ctxt->native)->query_; + auto strValue = std::get_if(&ctxt->vv); + if (strValue != nullptr) { + query.GreaterThan(ctxt->field, *strValue); + } else { + auto boolValue = std::get_if(&ctxt->vv); + if (boolValue != nullptr) { + query.GreaterThan(ctxt->field, *boolValue); + } else { + auto dblValue = std::get_if(&ctxt->vv); + if (dblValue != nullptr) { + query.GreaterThan(ctxt->field, *dblValue); + } + } + } + return ctxt->self; +} + +napi_value JsQuery::LessThan(napi_env env, napi_callback_info info) +{ + ZLOGD("Query::LessThan()"); + auto ctxt = std::make_shared(); + NAPI_CALL(env, ctxt->GetValueSync(env, info)); + + auto& query = reinterpret_cast(ctxt->native)->query_; + auto strValue = std::get_if(&ctxt->vv); + if (strValue != nullptr) { + query.LessThan(ctxt->field, *strValue); + } else { + auto boolValue = std::get_if(&ctxt->vv); + if (boolValue != nullptr) { + query.LessThan(ctxt->field, *boolValue); + } else { + auto dblValue = std::get_if(&ctxt->vv); + if (dblValue != nullptr) { + query.LessThan(ctxt->field, *dblValue); + } + } + } + return ctxt->self; +} + +napi_value JsQuery::GreaterThanOrEqualTo(napi_env env, napi_callback_info info) +{ + ZLOGD("Query::GreaterThanOrEqualTo()"); + auto ctxt = std::make_shared(); + NAPI_CALL(env, ctxt->GetValueSync(env, info)); + + auto& query = reinterpret_cast(ctxt->native)->query_; + auto strValue = std::get_if(&ctxt->vv); + if (strValue != nullptr) { + query.GreaterThanOrEqualTo(ctxt->field, *strValue); + } else { + auto boolValue = std::get_if(&ctxt->vv); + if (boolValue != nullptr) { + query.GreaterThanOrEqualTo(ctxt->field, *boolValue); + } else { + auto dblValue = std::get_if(&ctxt->vv); + if (dblValue != nullptr) { + query.GreaterThanOrEqualTo(ctxt->field, *dblValue); + } + } + } + return ctxt->self; +} + +napi_value JsQuery::LessThanOrEqualTo(napi_env env, napi_callback_info info) +{ + ZLOGD("Query::LessThanOrEqualTo()"); + auto ctxt = std::make_shared(); + NAPI_CALL(env, ctxt->GetValueSync(env, info)); + + auto& query = reinterpret_cast(ctxt->native)->query_; + auto strValue = std::get_if(&ctxt->vv); + if (strValue != nullptr) { + query.LessThanOrEqualTo(ctxt->field, *strValue); + } else { + auto boolValue = std::get_if(&ctxt->vv); + if (boolValue != nullptr) { + query.LessThanOrEqualTo(ctxt->field, *boolValue); + } else { + auto dblValue = std::get_if(&ctxt->vv); + if (dblValue != nullptr) { + query.LessThanOrEqualTo(ctxt->field, *dblValue); + } + } + } + return ctxt->self; +} + +napi_value JsQuery::IsNull(napi_env env, napi_callback_info info) +{ + std::string field; + auto ctxt = std::make_shared(); + auto input = [env, ctxt, &field](size_t argc, napi_value* argv) { + // required 1 arguments :: + ZLOGE_ON_ARGS(ctxt, argc == 1, "invalid arguments!"); + ctxt->status = JSUtil::GetValue(env, argv[0], field); + ZLOGE_ON_STATUS(ctxt, "invalid arg[0], i.e. invalid field!"); + }; + NAPI_CALL(env, ctxt->GetCbInfoSync(env, info, input)); + + auto& query = reinterpret_cast(ctxt->native)->query_; + query.IsNull(field); + return ctxt->self; +} + +/* + * InNumber / NotInNumber + * [NOTES] Recommented to use the napi_typedarray_type + * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects#indexed_collections + */ +enum class NumberType : uint8_t { + NUMBER_INT, + NUMBER_LONG, + NUMBER_DOUBLE, + NUMBER_INVALID = 255 +}; +struct NumbersContext : public ContextBase { + std::string field; + std::vector intList; + std::vector longList; + std::vector doubleList; + NumberType innerType = NumberType::NUMBER_INVALID; + + napi_status GetNumberSync(napi_env env, napi_callback_info info) + { + auto input = [this, env](size_t argc, napi_value* argv) { + // required 2 arguments :: + ZLOGE_ON_ARGS(this, argc == 2, "invalid arguments!"); + status = JSUtil::GetValue(env, argv[0], field); + ZLOGE_ON_STATUS(this, "invalid arg[0], i.e. invalid field!"); + + bool isTypedArray = false; + status = napi_is_typedarray(env, argv[1], &isTypedArray); + ZLOGD("arg[1] %{public}s a TypedArray", isTypedArray ? "is" : "is not"); + if (isTypedArray && (status == napi_ok)) { + napi_typedarray_type type = napi_biguint64_array; + size_t length = 0; + napi_value buffer = nullptr; + size_t offset = 0; + void* data = nullptr; + status = napi_get_typedarray_info(env, argv[1], &type, &length, &data, &buffer, &offset); + ZLOGE_ON_STATUS(this, "invalid arg[1], i.e. invalid number array!"); + if (type < napi_uint32_array) { + status = JSUtil::GetValue(env, argv[1], intList); + innerType = NumberType::NUMBER_INT; + } else if (type == napi_bigint64_array || type == napi_uint32_array) { + status = JSUtil::GetValue(env, argv[1], longList); + innerType = NumberType::NUMBER_LONG; + } else { + status = JSUtil::GetValue(env, argv[1], doubleList); + innerType = NumberType::NUMBER_DOUBLE; + } + } else { + bool isArray = false; + status = napi_is_array(env, argv[1], &isArray); + ZLOGE_ON_ARGS(this, isArray, "invalid arg[1], i.e. invalid number array!"); + ZLOGD("arg[1] %{public}s a Array, treat as array of double.", isTypedArray ? "is" : "is not"); + status = JSUtil::GetValue(env, argv[1], doubleList); + ZLOGE_ON_STATUS(this, "invalid arg[1], i.e. invalid number array!"); + innerType = NumberType::NUMBER_DOUBLE; + }; + }; + return GetCbInfoSync(env, info, input); + } +}; + +napi_value JsQuery::InNumber(napi_env env, napi_callback_info info) +{ + auto ctxt = std::make_shared(); + NAPI_CALL(env, ctxt->GetNumberSync(env, info)); + + auto& query = reinterpret_cast(ctxt->native)->query_; + if (ctxt->innerType == NumberType::NUMBER_INT) { + query.InInt(ctxt->field, ctxt->intList); + } else if (ctxt->innerType == NumberType::NUMBER_LONG) { + query.InLong(ctxt->field, ctxt->longList); + } else if (ctxt->innerType == NumberType::NUMBER_DOUBLE) { + query.InDouble(ctxt->field, ctxt->doubleList); + } + return ctxt->self; +} + +napi_value JsQuery::InString(napi_env env, napi_callback_info info) +{ + struct StringsContext : public ContextBase { + std::string field; + std::vector valueList; + }; + auto ctxt = std::make_shared(); + auto input = [env, ctxt](size_t argc, napi_value* argv) { + // required 2 arguments :: + ZLOGE_ON_ARGS(ctxt, argc == 2, "invalid arguments!"); + ctxt->status = JSUtil::GetValue(env, argv[0], ctxt->field); + ZLOGE_ON_STATUS(ctxt, "invalid arg[0], i.e. invalid field!"); + ctxt->status = JSUtil::GetValue(env, argv[1], ctxt->valueList); + ZLOGE_ON_STATUS(ctxt, "invalid arg[0], i.e. invalid valueList!"); + }; + NAPI_CALL(env, ctxt->GetCbInfoSync(env, info, input)); + + auto& query = reinterpret_cast(ctxt->native)->query_; + query.InString(ctxt->field, ctxt->valueList); + return ctxt->self; +} + +napi_value JsQuery::NotInNumber(napi_env env, napi_callback_info info) +{ + auto ctxt = std::make_shared(); + NAPI_CALL(env, ctxt->GetNumberSync(env, info)); + + auto& query = reinterpret_cast(ctxt->native)->query_; + if (ctxt->innerType == NumberType::NUMBER_INT) { + query.NotInInt(ctxt->field, ctxt->intList); + } else if (ctxt->innerType == NumberType::NUMBER_LONG) { + query.NotInLong(ctxt->field, ctxt->longList); + } else if (ctxt->innerType == NumberType::NUMBER_DOUBLE) { + query.NotInDouble(ctxt->field, ctxt->doubleList); + } + return ctxt->self; +} + +napi_value JsQuery::NotInString(napi_env env, napi_callback_info info) +{ + ZLOGD("Query::NotInString()"); + struct StringsContext : public ContextBase { + std::string field; + std::vector valueList; + }; + auto ctxt = std::make_shared(); + auto input = [env, ctxt](size_t argc, napi_value* argv) { + // required 2 arguments :: + ZLOGE_ON_ARGS(ctxt, argc == 2, "invalid arguments!"); + ctxt->status = JSUtil::GetValue(env, argv[0], ctxt->field); + ZLOGE_ON_STATUS(ctxt, "invalid arg[0], i.e. invalid field!"); + ctxt->status = JSUtil::GetValue(env, argv[1], ctxt->valueList); + ZLOGE_ON_STATUS(ctxt, "invalid arg[1], i.e. invalid valueList!"); + }; + NAPI_CALL(env, ctxt->GetCbInfoSync(env, info, input)); + + auto& query = reinterpret_cast(ctxt->native)->query_; + query.NotInString(ctxt->field, ctxt->valueList); + return ctxt->self; +} + +napi_value JsQuery::Like(napi_env env, napi_callback_info info) +{ + ZLOGD("Query::Like()"); + struct LikeContext : public ContextBase { + std::string field; + std::string value; + }; + auto ctxt = std::make_shared(); + auto input = [env, ctxt](size_t argc, napi_value* argv) { + // required 2 arguments :: + ZLOGE_ON_ARGS(ctxt, argc == 2, "invalid arguments!"); + ctxt->status = JSUtil::GetValue(env, argv[0], ctxt->field); + ZLOGE_ON_STATUS(ctxt, "invalid arg[0], i.e. invalid field!"); + ctxt->status = JSUtil::GetValue(env, argv[1], ctxt->value); + ZLOGE_ON_STATUS(ctxt, "invalid arg[1], i.e. invalid value!"); + }; + NAPI_CALL(env, ctxt->GetCbInfoSync(env, info, input)); + + auto& query = reinterpret_cast(ctxt->native)->query_; + query.Like(ctxt->field, ctxt->value); + return ctxt->self; +} + +napi_value JsQuery::Unlike(napi_env env, napi_callback_info info) +{ + ZLOGD("Query::Unlike()"); + struct UnlikeContext : public ContextBase { + std::string field; + std::string value; + }; + auto ctxt = std::make_shared(); + auto input = [env, ctxt](size_t argc, napi_value* argv) { + // required 2 arguments :: + ZLOGE_ON_ARGS(ctxt, argc == 2, "invalid arguments!"); + ctxt->status = JSUtil::GetValue(env, argv[0], ctxt->field); + ZLOGE_ON_STATUS(ctxt, "invalid arg[0], i.e. invalid field!"); + ctxt->status = JSUtil::GetValue(env, argv[1], ctxt->value); + ZLOGE_ON_STATUS(ctxt, "invalid arg[1], i.e. invalid value!"); + }; + NAPI_CALL(env, ctxt->GetCbInfoSync(env, info, input)); + + auto& query = reinterpret_cast(ctxt->native)->query_; + query.Unlike(ctxt->field, ctxt->value); + return ctxt->self; +} + +napi_value JsQuery::And(napi_env env, napi_callback_info info) +{ + ZLOGD("Query::And()"); + auto ctxt = std::make_shared(); + NAPI_CALL(env, ctxt->GetCbInfoSync(env, info)); + + auto& query = reinterpret_cast(ctxt->native)->query_; + query.And(); + return ctxt->self; +} + +napi_value JsQuery::Or(napi_env env, napi_callback_info info) +{ + ZLOGD("Query::Or()"); + auto ctxt = std::make_shared(); + NAPI_CALL(env, ctxt->GetCbInfoSync(env, info)); + + auto& query = reinterpret_cast(ctxt->native)->query_; + query.Or(); + return ctxt->self; +} + +napi_value JsQuery::OrderByAsc(napi_env env, napi_callback_info info) +{ + ZLOGD("Query::OrderByAsc()"); + std::string field; + auto ctxt = std::make_shared(); + auto input = [env, ctxt, &field](size_t argc, napi_value* argv) { + // required 1 arguments :: + ZLOGE_ON_ARGS(ctxt, argc == 1, "invalid arguments!"); + ctxt->status = JSUtil::GetValue(env, argv[0], field); + ZLOGE_ON_STATUS(ctxt, "invalid arg[0], i.e. invalid field!"); + }; + NAPI_CALL(env, ctxt->GetCbInfoSync(env, info, input)); + + auto& query = reinterpret_cast(ctxt->native)->query_; + query.OrderByAsc(field); + return ctxt->self; +} + +napi_value JsQuery::OrderByDesc(napi_env env, napi_callback_info info) +{ + ZLOGD("Query::OrderByAsc()"); + std::string field; + auto ctxt = std::make_shared(); + auto input = [env, ctxt, &field](size_t argc, napi_value* argv) { + // required 1 arguments :: + ZLOGE_ON_ARGS(ctxt, argc == 1, "invalid arguments!"); + ctxt->status = JSUtil::GetValue(env, argv[0], field); + ZLOGE_ON_STATUS(ctxt, "invalid arg[0], i.e. invalid field!"); + }; + NAPI_CALL(env, ctxt->GetCbInfoSync(env, info, input)); + + auto& query = reinterpret_cast(ctxt->native)->query_; + query.OrderByDesc(field); + return ctxt->self; +} + +napi_value JsQuery::Limit(napi_env env, napi_callback_info info) +{ + struct LimitContext : public ContextBase { + int number; + int offset; + }; + auto ctxt = std::make_shared(); + auto input = [env, ctxt](size_t argc, napi_value* argv) { + // required 2 arguments :: + ZLOGE_ON_ARGS(ctxt, argc == 2, "invalid arguments!"); + ctxt->status = napi_get_value_int32(env, argv[0], &ctxt->number); + ZLOGE_ON_STATUS(ctxt, "invalid arg[0], i.e. invalid number!"); + ctxt->status = napi_get_value_int32(env, argv[1], &ctxt->offset); + ZLOGE_ON_STATUS(ctxt, "invalid arg[1], i.e. invalid offset!"); + }; + NAPI_CALL(env, ctxt->GetCbInfoSync(env, info, input)); + auto& query = reinterpret_cast(ctxt->native)->query_; + query.Limit(ctxt->number, ctxt->offset); + return ctxt->self; +} + +napi_value JsQuery::IsNotNull(napi_env env, napi_callback_info info) +{ + ZLOGD("Query::IsNotNull()"); + std::string field; + auto ctxt = std::make_shared(); + auto input = [env, ctxt, &field](size_t argc, napi_value* argv) { + // required 1 arguments :: + ZLOGE_ON_ARGS(ctxt, argc == 1, "invalid arguments!"); + ctxt->status = JSUtil::GetValue(env, argv[0], field); + ZLOGE_ON_STATUS(ctxt, "invalid arg[0], i.e. invalid field!"); + }; + NAPI_CALL(env, ctxt->GetCbInfoSync(env, info, input)); + + auto& query = reinterpret_cast(ctxt->native)->query_; + query.IsNotNull(field); + return ctxt->self; +} + +napi_value JsQuery::BeginGroup(napi_env env, napi_callback_info info) +{ + ZLOGD("Query::BeginGroup()"); + auto ctxt = std::make_shared(); + NAPI_CALL(env, ctxt->GetCbInfoSync(env, info)); + auto& query = reinterpret_cast(ctxt->native)->query_; + query.BeginGroup(); + return ctxt->self; +} + +napi_value JsQuery::EndGroup(napi_env env, napi_callback_info info) +{ + ZLOGD("Query::EndGroup()"); + auto ctxt = std::make_shared(); + NAPI_CALL(env, ctxt->GetCbInfoSync(env, info)); + + auto& query = reinterpret_cast(ctxt->native)->query_; + query.EndGroup(); + return ctxt->self; +} + +napi_value JsQuery::PrefixKey(napi_env env, napi_callback_info info) +{ + std::string prefix; + auto ctxt = std::make_shared(); + auto input = [env, ctxt, &prefix](size_t argc, napi_value* argv) { + // required 1 arguments :: + ZLOGE_ON_ARGS(ctxt, argc == 1, "invalid arguments!"); + ctxt->status = JSUtil::GetValue(env, argv[0], prefix); + ZLOGE_ON_STATUS(ctxt, "invalid arg[0], i.e. invalid prefix!"); + }; + NAPI_CALL(env, ctxt->GetCbInfoSync(env, info, input)); + + auto& query = reinterpret_cast(ctxt->native)->query_; + query.KeyPrefix(prefix); + return ctxt->self; +} + +napi_value JsQuery::SetSuggestIndex(napi_env env, napi_callback_info info) +{ + std::string suggestIndex; + auto ctxt = std::make_shared(); + auto input = [env, ctxt, &suggestIndex](size_t argc, napi_value* argv) { + // required 1 arguments :: + ZLOGE_ON_ARGS(ctxt, argc == 1, "invalid arguments!"); + ctxt->status = JSUtil::GetValue(env, argv[0], suggestIndex); + ZLOGE_ON_STATUS(ctxt, "invalid arg[0], i.e. invalid suggestIndex!"); + }; + NAPI_CALL(env, ctxt->GetCbInfoSync(env, info, input)); + + auto& query = reinterpret_cast(ctxt->native)->query_; + query.SetSuggestIndex(suggestIndex); + return ctxt->self; +} + +napi_value JsQuery::DeviceId(napi_env env, napi_callback_info info) +{ + std::string deviceId; + auto ctxt = std::make_shared(); + auto input = [env, ctxt, &deviceId](size_t argc, napi_value* argv) { + // required 1 arguments :: + ZLOGE_ON_ARGS(ctxt, argc == 1, "invalid arguments!"); + ctxt->status = JSUtil::GetValue(env, argv[0], deviceId); + ZLOGE_ON_STATUS(ctxt, "invalid arg[0], i.e. invalid deviceId!"); + }; + NAPI_CALL(env, ctxt->GetCbInfoSync(env, info, input)); + + auto& query = reinterpret_cast(ctxt->native)->query_; + query.DeviceId(deviceId); + return ctxt->self; +} + +// getSqlLike():string +napi_value JsQuery::GetSqlLike(napi_env env, napi_callback_info info) +{ + auto ctxt = std::make_shared(); + NAPI_CALL(env, ctxt->GetCbInfoSync(env, info)); + + auto& query = reinterpret_cast(ctxt->native)->query_; + JSUtil::SetValue(env, query.ToString(), ctxt->output); + return ctxt->output; +} +} // \ No newline at end of file diff --git a/frameworks/jskitsimpl/distributeddata/src/js_schema.cpp b/frameworks/jskitsimpl/distributeddata/src/js_schema.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0318060693a5c8a26a67338574f798df31ece8c6 --- /dev/null +++ b/frameworks/jskitsimpl/distributeddata/src/js_schema.cpp @@ -0,0 +1,235 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#define LOG_TAG "JS_Schema" +#include "js_schema.h" +#include + +#include "js_util.h" +#include "log_print.h" +#include "napi_queue.h" +#include "uv_queue.h" + +using namespace OHOS::DistributedKv; +using json = nlohmann::json; + +namespace OHOS::DistributedData { +static std::string LABEL = "Schema"; +static std::string SCHEMA_VERSION = "SCHEMA_VERSION"; +static std::string SCHEMA_MODE = "SCHEMA_MODE"; +static std::string SCHEMA_DEFINE = "SCHEMA_DEFINE"; +static std::string SCHEMA_INDEX = "SCHEMA_INDEX"; +static std::string SCHEMA_SKIPSIZE = "SCHEMA_SKIPSIZE"; +static std::string DEFAULT_SCHEMA_VERSION = "1.0"; + +JsSchema::JsSchema(napi_env env_) + : env(env_) +{ +} + +JsSchema::~JsSchema() +{ + ZLOGD("no memory leak for JsSchema"); + if (ref != nullptr) { + napi_delete_reference(env, ref); + } +} + +napi_value JsSchema::Constructor(napi_env env) +{ + ZLOGD("Init JsSchema"); + const napi_property_descriptor properties[] = { + DECLARE_NAPI_FUNCTION("toJsonString", JsSchema::ToJson), + DECLARE_NAPI_GETTER_SETTER("root", JsSchema::GetRootNode, JsSchema::SetRootNode), + DECLARE_NAPI_GETTER_SETTER("mode", JsSchema::GetMode, JsSchema::SetMode), + DECLARE_NAPI_GETTER_SETTER("skip", JsSchema::GetSkip, JsSchema::SetSkip) + }; + size_t count = sizeof(properties) / sizeof(properties[0]); + return JSUtil::DefineClass(env, "Schema", properties, count, JsSchema::New); +} + +napi_value JsSchema::New(napi_env env, napi_callback_info info) +{ + ZLOGD("Schema::New"); + auto ctxt = std::make_shared(); + NAPI_CALL(env, ctxt->GetCbInfoSync(env, info)); + + JsSchema* schema = new (std::nothrow) JsSchema(env); + NAPI_ASSERT(env, schema !=nullptr, "no memory for schema"); + + auto finalize = [](napi_env env, void* data, void* hint) { + ZLOGD("Schema finalize."); + auto* schema = reinterpret_cast(data); + ZLOGE_RETURN_VOID(schema != nullptr, "finalize null!"); + delete schema; + }; + NAPI_CALL(env, napi_wrap(env, ctxt->self, schema, finalize, nullptr, nullptr)); + return ctxt->self; +} + +napi_value JsSchema::ToJson(napi_env env, napi_callback_info info) +{ + ZLOGD("Schema::New"); + auto ctxt = std::make_shared(); + NAPI_CALL(env, ctxt->GetCbInfoSync(env, info)); + + auto schema = reinterpret_cast(ctxt->native); + auto json = schema->Dump(); + JSUtil::SetValue(env, json, ctxt->output); + return ctxt->output; +} + +napi_value JsSchema::GetRootNode(napi_env env, napi_callback_info info) +{ + ZLOGD("Schema::GetRootNode"); + auto ctxt = std::make_shared(); + NAPI_CALL(env, ctxt->GetCbInfoSync(env, info)); + + auto schema = reinterpret_cast(ctxt->native); + if (schema->rootNode == nullptr) { + int argc = 1; + napi_value argv[1] = { nullptr }; + std::string root(SCHEMA_DEFINE); + JSUtil::SetValue(env, root, argv[0]); + schema->ref = JSUtil::NewWithRef(env, argc, argv, + (void**)&schema->rootNode, JsFieldNode::Constructor(env)); + } + NAPI_ASSERT(env, schema->ref != nullptr, "no root, please set first!"); + NAPI_CALL(env, napi_get_reference_value(env, schema->ref, &ctxt->output)); + return ctxt->output; +} + +napi_value JsSchema::SetRootNode(napi_env env, napi_callback_info info) +{ + ZLOGD("Schema::SetRootNode"); + auto ctxt = std::make_shared(); + auto input = [env, ctxt](size_t argc, napi_value* argv) { + // required 2 arguments :: + ZLOGE_ON_ARGS(ctxt, argc == 1, "invalid arguments!"); + JsFieldNode* node = nullptr; + ctxt->status = JSUtil::Unwrap(env, argv[0], (void**)(&node), JsFieldNode::Constructor(env)); + ZLOGE_ON_STATUS(ctxt, "napi_unwrap to FieldNode failed"); + ZLOGE_ON_ARGS(ctxt, node != nullptr, "invalid arg[0], i.e. invalid node!"); + + auto schema = reinterpret_cast(ctxt->native); + if (schema->ref != nullptr) { + napi_delete_reference(env, schema->ref); + } + ctxt->status = napi_create_reference(env, argv[0], 1, &schema->ref); + ZLOGE_ON_STATUS(ctxt, "napi_create_reference to FieldNode failed"); + schema->rootNode = node; + }; + NAPI_CALL(env, ctxt->GetCbInfoSync(env, info, input)); + return ctxt->self; +} + +napi_value JsSchema::GetMode(napi_env env, napi_callback_info info) +{ + auto ctxt = std::make_shared(); + NAPI_CALL(env, ctxt->GetCbInfoSync(env, info)); + + auto schema = reinterpret_cast(ctxt->native); + JSUtil::SetValue(env, schema->mode, ctxt->output); + return ctxt->output; +} + +napi_value JsSchema::SetMode(napi_env env, napi_callback_info info) +{ + auto ctxt = std::make_shared(); + uint32_t mode = false; + auto input = [env, ctxt, &mode](size_t argc, napi_value* argv) { + // required 1 arguments :: + ZLOGE_ON_ARGS(ctxt, argc == 1, "invalid arguments!"); + ctxt->status = JSUtil::GetValue(env, argv[0], mode); + ZLOGE_ON_STATUS(ctxt, "invalid arg[0], i.e. invalid mode!"); + }; + NAPI_CALL(env, ctxt->GetCbInfoSync(env, info, input)); + + auto schema = reinterpret_cast(ctxt->native); + schema->mode = mode; + return nullptr; +} + +napi_value JsSchema::GetSkip(napi_env env, napi_callback_info info) +{ + auto ctxt = std::make_shared(); + NAPI_CALL(env, ctxt->GetCbInfoSync(env, info)); + + auto schema = reinterpret_cast(ctxt->native); + JSUtil::SetValue(env, schema->skip, ctxt->output); + return ctxt->output; +} + +napi_value JsSchema::SetSkip(napi_env env, napi_callback_info info) +{ + auto ctxt = std::make_shared(); + uint32_t skip = false; + auto input = [env, ctxt, &skip](size_t argc, napi_value* argv) { + // required 1 arguments :: + ZLOGE_ON_ARGS(ctxt, argc == 1, "invalid arguments!"); + ctxt->status = JSUtil::GetValue(env, argv[0], skip); + ZLOGE_ON_STATUS(ctxt, "invalid arg[0], i.e. invalid skip size!"); + }; + NAPI_CALL(env, ctxt->GetCbInfoSync(env, info, input)); + + auto schema = reinterpret_cast(ctxt->native); + schema->skip = skip; + return nullptr; +} + +napi_value JsSchema::GetIndexes(napi_env env, napi_callback_info info) +{ + auto ctxt = std::make_shared(); + NAPI_CALL(env, ctxt->GetCbInfoSync(env, info)); + + auto schema = reinterpret_cast(ctxt->native); + JSUtil::SetValue(env, schema->indexes, ctxt->output); + return ctxt->output; +} + +napi_value JsSchema::SetIndexes(napi_env env, napi_callback_info info) +{ + auto ctxt = std::make_shared(); + std::vector indexes; + auto input = [env, ctxt, &indexes](size_t argc, napi_value* argv) { + // required 1 arguments :: + ZLOGE_ON_ARGS(ctxt, argc == 1, "invalid arguments!"); + ctxt->status = JSUtil::GetValue(env, argv[0], indexes); + ZLOGE_ON_STATUS(ctxt, "invalid arg[0], i.e. invalid indexes!"); + }; + NAPI_CALL(env, ctxt->GetCbInfoSync(env, info, input)); + + auto schema = reinterpret_cast(ctxt->native); + schema->indexes = indexes; + return nullptr; +} + +std::string JsSchema::Dump() +{ + json jsIndexes; + for (auto idx : indexes) { + jsIndexes.push_back(idx); + } + ZLOGD("indexes: %{public}s", jsIndexes.dump().c_str()); + ZLOGD("rootNode: %{public}s", rootNode->GetValueForJson().c_str()); + json js = { + { SCHEMA_VERSION, DEFAULT_SCHEMA_VERSION }, + { SCHEMA_MODE, (mode == SCHEMA_MODE_STRICT) ? "STRICT" : "COMPATIBLE" }, + { SCHEMA_DEFINE, rootNode->GetValueForJson() }, + { SCHEMA_INDEX, jsIndexes.dump() }, + { SCHEMA_SKIPSIZE, skip }, + }; + return js.dump(); +} +} diff --git a/frameworks/jskitsimpl/distributeddata/src/js_single_kv_store.cpp b/frameworks/jskitsimpl/distributeddata/src/js_single_kv_store.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3f1391ac9da0f0d4c3c75b45bd602ca9e3a7191e --- /dev/null +++ b/frameworks/jskitsimpl/distributeddata/src/js_single_kv_store.cpp @@ -0,0 +1,459 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#define LOG_TAG "JS_SingleKVStore" +#include "js_single_kv_store.h" +#include "js_util.h" +#include "js_kv_store_resultset.h" +#include "js_query.h" +#include "log_print.h" +#include "napi_queue.h" +#include "uv_queue.h" + +using namespace OHOS::DistributedKv; + +namespace OHOS::DistributedData { +JsSingleKVStore::JsSingleKVStore(const std::string& storeId) + : JsKVStore(storeId) +{ +} + +napi_value JsSingleKVStore::Constructor(napi_env env) +{ + const napi_property_descriptor properties[] = { + DECLARE_NAPI_FUNCTION("put", JsKVStore::Put), + DECLARE_NAPI_FUNCTION("delete", JsKVStore::Delete), + DECLARE_NAPI_FUNCTION("putBatch", JsKVStore::PutBatch), + DECLARE_NAPI_FUNCTION("deleteBatch", JsKVStore::DeleteBatch), + DECLARE_NAPI_FUNCTION("startTransaction", JsKVStore::StartTransaction), + DECLARE_NAPI_FUNCTION("commit", JsKVStore::Commit), + DECLARE_NAPI_FUNCTION("rollback", JsKVStore::Rollback), + DECLARE_NAPI_FUNCTION("enableSync", JsKVStore::EnableSync), + DECLARE_NAPI_FUNCTION("setSyncRange", JsKVStore::SetSyncRange), + /* JsSingleKVStore externs JsKVStore */ + DECLARE_NAPI_FUNCTION("get", JsSingleKVStore::Get), + DECLARE_NAPI_FUNCTION("getEntries", JsSingleKVStore::GetEntries), + DECLARE_NAPI_FUNCTION("getResultSet", JsSingleKVStore::GetResultSet), + DECLARE_NAPI_FUNCTION("closeResultSet", JsSingleKVStore::CloseResultSet), + DECLARE_NAPI_FUNCTION("getResultSize", JsSingleKVStore::GetResultSize), + DECLARE_NAPI_FUNCTION("removeDeviceData", JsSingleKVStore::RemoveDeviceData), + DECLARE_NAPI_FUNCTION("sync", JsSingleKVStore::Sync), + DECLARE_NAPI_FUNCTION("setSyncParam", JsSingleKVStore::SetSyncParam), + DECLARE_NAPI_FUNCTION("getSecurityLevel", JsSingleKVStore::GetSecurityLevel), + DECLARE_NAPI_FUNCTION("on", JsKVStore::OnEvent), /* same to JsDeviceKVStore */ + DECLARE_NAPI_FUNCTION("off", JsKVStore::OffEvent) /* same to JsDeviceKVStore */ + }; + size_t count = sizeof(properties) / sizeof(properties[0]); + return JSUtil::DefineClass(env, "SingleKVStore", properties, count, JsSingleKVStore::New); +} + +/* + * [JS API Prototype] + * [AsyncCallback] + * get(key:string, callback:AsyncCallback):void; + * [Promise] + * get(key:string):Promise; + */ +napi_value JsSingleKVStore::Get(napi_env env, napi_callback_info info) +{ + ZLOGD("SingleKVStore::Get()"); + struct GetContext : public ContextBase { + std::string key; + JSUtil::KvStoreVariant value; + }; + auto ctxt = std::make_shared(); + auto input = [env, ctxt](size_t argc, napi_value* argv) { + // required 1 arguments :: + ZLOGE_ON_ARGS(ctxt, argc == 1, "invalid arguments!"); + + ctxt->status = JSUtil::GetValue(env, argv[0], ctxt->key); + ZLOGE_ON_STATUS(ctxt, "invalid arg[0], i.e. invalid key!"); + }; + ctxt->GetCbInfo(env, info, input); + ZLOGD("key=%{public}.8s", ctxt->key.c_str()); + + auto execute = [ctxt]() { + OHOS::DistributedKv::Key key(ctxt->key); + OHOS::DistributedKv::Value value; + auto& kvStore = reinterpret_cast(ctxt->native)->GetNative(); + Status status = kvStore->Get(key, value); + ZLOGD("kvStore->Get return %{public}d", status); + ctxt->value = JSUtil::Blob2VariantValue(value); + ctxt->status = (status == Status::SUCCESS) ? napi_ok : napi_generic_failure; + ZLOGE_ON_STATUS(ctxt, "kvStore->Get() failed!"); + }; + auto output = [env, ctxt](napi_value& result) { + ctxt->status = JSUtil::SetValue(env, ctxt->value, result); + ZLOGE_ON_STATUS(ctxt, "output failed"); + }; + return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute, output); +} + +enum class ArgsType : uint8_t { + /* input arguments' combination type */ + KEYPREFIX = 0, + QUERY, + UNKNOWN = 255 +}; +struct VariantArgs { + /* input arguments' combinations */ + std::string keyPrefix; + JsQuery* query; + ArgsType type = ArgsType::UNKNOWN; +}; + +static napi_status GetVariantArgs(napi_env env, size_t argc, napi_value* argv, VariantArgs& va) +{ + // required 1 arguments :: + ZLOGE_RETURN(argc == 1, "invalid arguments!", napi_invalid_arg); + napi_valuetype type = napi_undefined; + napi_status status = napi_typeof(env, argv[0], &type); + ZLOGE_RETURN((type == napi_string) || (type == napi_object), "invalid arg[0], type error!", napi_invalid_arg); + if (type == napi_string) { + status = JSUtil::GetValue(env, argv[0], va.keyPrefix); + ZLOGE_RETURN(!va.keyPrefix.empty(), "invalid arg[0], i.e. invalid keyPrefix!", napi_invalid_arg); + va.type = ArgsType::KEYPREFIX; + } else if (type == napi_object) { + status = JSUtil::Unwrap(env, argv[0], (void**)(&va.query), JsQuery::Constructor(env)); + ZLOGE_RETURN(va.query != nullptr, "invalid arg[0], i.e. invalid query!", napi_invalid_arg); + va.type = ArgsType::QUERY; + } + return status; +}; + +/* + * [JS API Prototype] + * getEntries(keyPrefix:string, callback:AsyncCallback):void + * getEntries(keyPrefix:string):Promise + * + * getEntries(query:Query, callback:AsyncCallback):void + * getEntries(query:Query) : Promise + */ +napi_value JsSingleKVStore::GetEntries(napi_env env, napi_callback_info info) +{ + ZLOGD("SingleKVStore::GetEntries()"); + struct GetEntriesContext : public ContextBase { + VariantArgs va; + std::vector entries; + }; + auto ctxt = std::make_shared(); + auto input = [env, ctxt](size_t argc, napi_value* argv) { + // required 1 arguments :: + ZLOGE_ON_ARGS(ctxt, argc == 1, "invalid arguments!"); + ctxt->status = GetVariantArgs(env, argc, argv, ctxt->va); + ZLOGE_ON_STATUS(ctxt, "invalid arguments!"); + }; + ctxt->GetCbInfo(env, info, input); + + auto execute = [ctxt]() { + auto& kvStore = reinterpret_cast(ctxt->native)->GetNative(); + Status status = Status::INVALID_ARGUMENT; + if (ctxt->va.type == ArgsType::KEYPREFIX) { + OHOS::DistributedKv::Key keyPrefix(ctxt->va.keyPrefix); + status = kvStore->GetEntries(keyPrefix, ctxt->entries); + ZLOGD("kvStore->GetEntries() return %{public}d", status); + } else if (ctxt->va.type == ArgsType::QUERY) { + auto query = ctxt->va.query->GetNative(); + status = kvStore->GetEntriesWithQuery(query.ToString(), ctxt->entries); + ZLOGD("kvStore->GetEntriesWithQuery() return %{public}d", status); + } + ctxt->status = (status == Status::SUCCESS) ? napi_ok : napi_generic_failure; + ZLOGE_ON_STATUS(ctxt, "kvStore->GetEntries() failed"); + }; + auto output = [env, ctxt](napi_value& result) { + ctxt->status = JSUtil::SetValue(env, ctxt->entries, result); + ZLOGE_ON_STATUS(ctxt, "output failed!"); + }; + return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute, output); +} + +/* + * [JS API Prototype] + * getResultSet(keyPrefix:string, callback:AsyncCallback):void + * getResultSet(keyPrefix:string):Promise + * + * getResultSet(query:Query, callback:AsyncCallback):void + * getResultSet(query:Query):Promise + */ +napi_value JsSingleKVStore::GetResultSet(napi_env env, napi_callback_info info) +{ + ZLOGD("SingleKVStore::GetResultSet()"); + struct GetResultSetContext : public ContextBase { + VariantArgs va; + JsKVStoreResultSet* resultSet = nullptr; + napi_ref ref = nullptr; + }; + auto ctxt = std::make_shared(); + auto input = [env, ctxt](size_t argc, napi_value* argv) { + // required 1 arguments :: + ZLOGE_ON_ARGS(ctxt, argc == 1, "invalid arguments!"); + ctxt->status = GetVariantArgs(env, argc, argv, ctxt->va); + ZLOGE_ON_STATUS(ctxt, "invalid arguments!"); + ctxt->ref = JSUtil::NewWithRef(env, 0, nullptr, (void**)(&ctxt->resultSet), + JsKVStoreResultSet::Constructor(env)); + ZLOGE_ON_ARGS(ctxt, ctxt->resultSet != nullptr, "KVStoreResultSet::New failed!"); + ZLOGE_ON_ARGS(ctxt, ctxt->ref != nullptr, "KVStoreResultSet::New failed!"); + }; + ctxt->GetCbInfo(env, info, input); + + auto execute = [ctxt]() { + std::shared_ptr kvResultSet; + auto& kvStore = reinterpret_cast(ctxt->native)->GetNative(); + Status status = Status::INVALID_ARGUMENT; + if (ctxt->va.type == ArgsType::KEYPREFIX) { + OHOS::DistributedKv::Key keyPrefix(ctxt->va.keyPrefix); + status = kvStore->GetResultSet(keyPrefix, kvResultSet); + ZLOGD("kvStore->GetEntries() return %{public}d", status); + } else if (ctxt->va.type == ArgsType::QUERY) { + auto query = ctxt->va.query->GetNative(); + status = kvStore->GetResultSetWithQuery(query.ToString(), kvResultSet); + ZLOGD("kvStore->GetEntriesWithQuery() return %{public}d", status); + } + ctxt->status = (status == Status::SUCCESS) ? napi_ok : napi_generic_failure; + ZLOGE_ON_STATUS(ctxt, "kvStore->GetResultSet() failed!"); + ctxt->resultSet->SetNative(kvResultSet); + }; + auto output = [env, ctxt](napi_value& result) { + ctxt->status = napi_get_reference_value(env, ctxt->ref, &result); + napi_delete_reference(env, ctxt->ref); + ZLOGE_ON_STATUS(ctxt, "output kvResultSet failed"); + }; + return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute, output); +} + +/* + * [JS API Prototype] + * closeResultSet(resultSet:KVStoreResultSet, callback: AsyncCallback):void + * closeResultSet(resultSet:KVStoreResultSet):Promise + */ +napi_value JsSingleKVStore::CloseResultSet(napi_env env, napi_callback_info info) +{ + ZLOGD("SingleKVStore::CloseResultSet()"); + struct CloseResultSetContext : public ContextBase { + JsKVStoreResultSet* resultSet = nullptr; + }; + auto ctxt = std::make_shared(); + auto input = [env, ctxt](size_t argc, napi_value* argv) { + // required 1 arguments :: + ZLOGE_ON_ARGS(ctxt, argc == 1, "invalid arguments!"); + napi_valuetype type = napi_undefined; + ctxt->status = napi_typeof(env, argv[0], &type); + ZLOGE_ON_ARGS(ctxt, type == napi_object, "invalid arg[0], i.e. invalid resultSet!"); + ctxt->status = JSUtil::Unwrap(env, argv[0], (void**)(&ctxt->resultSet), + JsKVStoreResultSet::Constructor(env)); + ZLOGE_ON_ARGS(ctxt, ctxt->resultSet != nullptr, "invalid arg[0], i.e. invalid resultSet!"); + }; + ctxt->GetCbInfo(env, info, input); + + auto execute = [ctxt]() { + auto& kvStore = reinterpret_cast(ctxt->native)->GetNative(); + Status status = kvStore->CloseResultSet(ctxt->resultSet->GetNative()); + ZLOGD("kvStore->CloseResultSet return %{public}d", status); + ctxt->status = (status == Status::SUCCESS) ? napi_ok : napi_generic_failure; + ZLOGE_ON_STATUS(ctxt, "kvStore->CloseResultSet failed!"); + }; + return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute); +} +/* + * [JS API Prototype] + * getResultSize(query:Query, callback: AsyncCallback):void + * getResultSize(query:Query):Promise + */ +napi_value JsSingleKVStore::GetResultSize(napi_env env, napi_callback_info info) +{ + ZLOGD("SingleKVStore::GetResultSize()"); + struct ResultSizeContext : public ContextBase { + JsQuery* query = nullptr; + int resultSize = 0; + }; + auto ctxt = std::make_shared(); + auto input = [env, ctxt](size_t argc, napi_value* argv) { + // required 1 arguments :: + ZLOGE_ON_ARGS(ctxt, argc == 1, "invalid arguments!"); + napi_valuetype type = napi_undefined; + ctxt->status = napi_typeof(env, argv[0], &type); + ZLOGE_ON_ARGS(ctxt, type == napi_object, "invalid arg[0], i.e. invalid query!"); + ctxt->status = JSUtil::Unwrap(env, argv[0], (void**)(&ctxt->query), JsQuery::Constructor(env)); + ZLOGE_ON_ARGS(ctxt, ctxt->query != nullptr, "invalid arg[0], i.e. invalid query!"); + }; + ctxt->GetCbInfo(env, info, input); + + auto execute = [ctxt]() { + auto& kvStore = reinterpret_cast(ctxt->native)->GetNative(); + auto query = ctxt->query->GetNative(); + Status status = kvStore->GetCountWithQuery(query.ToString(), ctxt->resultSize); + ZLOGD("kvStore->GetCountWithQuery() return %{public}d", status); + ctxt->status = (status == Status::SUCCESS) ? napi_ok : napi_generic_failure; + ZLOGE_ON_STATUS(ctxt, "kvStore->GetCountWithQuery() failed!"); + }; + auto output = [env, ctxt](napi_value& result) { + ctxt->status = JSUtil::SetValue(env, static_cast(ctxt->resultSize), result); + ZLOGE_ON_STATUS(ctxt, "output resultSize failed!"); + }; + return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute, output); +} + +/* + * [JS API Prototype] + * removeDeviceData(deviceId:string, callback: AsyncCallback):void + * removeDeviceData(deviceId:string):Promise + */ +napi_value JsSingleKVStore::RemoveDeviceData(napi_env env, napi_callback_info info) +{ + ZLOGD("SingleKVStore::RemoveDeviceData()"); + struct RemoveDeviceContext : public ContextBase { + std::string deviceId; + }; + auto ctxt = std::make_shared(); + auto input = [env, ctxt](size_t argc, napi_value* argv) { + // required 1 arguments :: + ZLOGE_ON_ARGS(ctxt, argc == 1, "invalid arguments!"); + ctxt->status = JSUtil::GetValue(env, argv[0], ctxt->deviceId); + ZLOGE_ON_STATUS(ctxt, "invalid arg[0], i.e. invalid deviceId!"); + }; + ctxt->GetCbInfo(env, info, input); + + auto execute = [ctxt]() { + auto& kvStore = reinterpret_cast(ctxt->native)->GetNative(); + Status status = kvStore->RemoveDeviceData(ctxt->deviceId); + ZLOGD("kvStore->RemoveDeviceData return %{public}d", status); + ctxt->status = (status == Status::SUCCESS) ? napi_ok : napi_generic_failure; + ZLOGE_ON_STATUS(ctxt, "kvStore->RemoveDeviceData failed!"); + }; + return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute); +} + +/* + * [JS API Prototype] + * sync(deviceIdList:string[], mode:SyncMode, allowedDelayMs?:number):void + */ +napi_value JsSingleKVStore::Sync(napi_env env, napi_callback_info info) +{ + struct SyncContext : public ContextBase { + std::vector deviceIdList; + uint32_t mode = 0; + uint32_t allowedDelayMs = 0; + }; + auto ctxt = std::make_shared(); + auto input = [env, ctxt](size_t argc, napi_value* argv) { + // required 3 arguments :: [allowedDelayMs] + ZLOGE_ON_ARGS(ctxt, (argc == 2) || (argc == 3), "invalid arguments!"); + ctxt->status = JSUtil::GetValue(env, argv[0], ctxt->deviceIdList); + ZLOGE_ON_STATUS(ctxt, "invalid arg[0], i.e. invalid deviceIdList!"); + ctxt->status = JSUtil::GetValue(env, argv[1], ctxt->mode); + ZLOGE_ON_STATUS(ctxt, "invalid arg[1], i.e. invalid mode!"); + ZLOGE_ON_ARGS(ctxt, ctxt->mode <= uint32_t(SyncMode::PUSH_PULL), "invalid arg[1], i.e. invalid mode!"); + // have 3 arguments :: have the allowedDelayMs + if (argc == 3) { + ctxt->status = JSUtil::GetValue(env, argv[2], ctxt->allowedDelayMs); + ZLOGE_ON_STATUS(ctxt, "invalid arg[1], i.e. invalid allowedDelayMs!"); + } + }; + NAPI_CALL(env, ctxt->GetCbInfoSync(env, info, input)); + ZLOGD("sync deviceIdList.size=%{public}d, mode:%{public}u, allowedDelayMs:%{public}u", + (int)ctxt->deviceIdList.size(), ctxt->mode, ctxt->allowedDelayMs); + + auto& kvStore = reinterpret_cast(ctxt->native)->GetNative(); + Status status = kvStore->Sync(ctxt->deviceIdList, static_cast(ctxt->mode), ctxt->allowedDelayMs); + ZLOGD("kvStore->Sync return %{public}d!", status); + NAPI_ASSERT(env, status == Status::SUCCESS, "kvStore->Sync() failed!"); + return nullptr; +} + +/* + * [JS API Prototype] + * setSyncParam(defaultAllowedDelayMs:number, callback: AsyncCallback):void + * setSyncParam(defaultAllowedDelayMs:number):Promise + */ +napi_value JsSingleKVStore::SetSyncParam(napi_env env, napi_callback_info info) +{ + ZLOGD("SingleKVStore::SetSyncParam()"); + struct SyncParamContext : public ContextBase { + uint32_t allowedDelayMs; + }; + auto ctxt = std::make_shared(); + auto input = [env, ctxt](size_t argc, napi_value* argv) { + // required 1 arguments :: + ZLOGE_ON_ARGS(ctxt, argc == 1, "invalid arguments!"); + ctxt->status = JSUtil::GetValue(env, argv[0], ctxt->allowedDelayMs); + ZLOGE_ON_STATUS(ctxt, "get allowedDelayMs failed!"); + }; + ctxt->GetCbInfo(env, info, input); + + auto execute = [ctxt]() { + auto& kvStore = reinterpret_cast(ctxt->native)->GetNative(); + KvSyncParam syncParam { ctxt->allowedDelayMs }; + Status status = kvStore->SetSyncParam(syncParam); + ZLOGD("kvStore->SetSyncParam return %{public}d", status); + ctxt->status = (status == Status::SUCCESS) ? napi_ok : napi_generic_failure; + ZLOGE_ON_STATUS(ctxt, "output failed!"); + }; + return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute); +} + +/* + * [JS API Prototype] + * getSecurityLevel(callback: AsyncCallback):void + * getSecurityLevel():Promise + */ +napi_value JsSingleKVStore::GetSecurityLevel(napi_env env, napi_callback_info info) +{ + ZLOGD("SingleKVStore::GetSecurityLevel()"); + struct SecurityLevelContext : public ContextBase { + SecurityLevel securityLevel; + }; + auto ctxt = std::make_shared(); + ctxt->GetCbInfo(env, info); + + auto execute = [ctxt]() { + auto& kvStore = reinterpret_cast(ctxt->native)->GetNative(); + Status status = kvStore->GetSecurityLevel(ctxt->securityLevel); + ZLOGD("kvStore->GetSecurityLevel return %{public}d", status); + ctxt->status = (status == Status::SUCCESS) ? napi_ok : napi_generic_failure; + ZLOGE_ON_STATUS(ctxt, "GetSecurityLevel failed!"); + }; + auto output = [env, ctxt](napi_value& result) { + ctxt->status = JSUtil::SetValue(env, static_cast(ctxt->securityLevel), result); + ZLOGE_ON_STATUS(ctxt, "output failed!"); + }; + return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute, output); +} + +napi_value JsSingleKVStore::New(napi_env env, napi_callback_info info) +{ + ZLOGD("Constructor single kv store!"); + std::string storeId; + auto ctxt = std::make_shared(); + auto input = [env, ctxt, &storeId](size_t argc, napi_value* argv) { + // required 2 arguments :: + ZLOGE_ON_ARGS(ctxt, argc == 2, "invalid arguments!"); + ctxt->status = JSUtil::GetValue(env, argv[0], storeId); + ZLOGE_ON_STATUS(ctxt, "invalid arg[0], i.e. invalid storeId!"); + ZLOGE_ON_ARGS(ctxt, !storeId.empty(), "invalid arg[0], i.e. invalid storeId!"); + }; + NAPI_CALL(env, ctxt->GetCbInfoSync(env, info, input)); + + JsSingleKVStore* kvStore = new (std::nothrow) JsSingleKVStore(storeId); + NAPI_ASSERT(env, kvStore !=nullptr, "no memory for kvStore"); + + auto finalize = [](napi_env env, void* data, void* hint) { + ZLOGD("singleKVStore finalize."); + auto* kvStore = reinterpret_cast(data); + ZLOGE_RETURN_VOID(kvStore != nullptr, "finalize null!"); + delete kvStore; + }; + NAPI_CALL(env, napi_wrap(env, ctxt->self, kvStore, finalize, nullptr, nullptr)); + return ctxt->self; +} +} // namespace OHOS::DistributedData diff --git a/frameworks/jskitsimpl/distributeddata/src/js_util.cpp b/frameworks/jskitsimpl/distributeddata/src/js_util.cpp index 3e2f913d1be87fc3dcea8878259f56ef69dabb48..1a0af823790d9a3efdb44858df6b1fccacfb4891 100644 --- a/frameworks/jskitsimpl/distributeddata/src/js_util.cpp +++ b/frameworks/jskitsimpl/distributeddata/src/js_util.cpp @@ -13,316 +13,965 @@ * limitations under the License. */ #define LOG_TAG "JSUtil" - #include "js_util.h" +#include #include + #include "log_print.h" +#include "napi_queue.h" using namespace OHOS::DistributedKv; + namespace OHOS::DistributedData { -DistributedKv::Options JSUtil::Convert2Options(napi_env env, napi_value jsOptions) +constexpr int32_t STR_MAX_LENGTH = 4096; +constexpr size_t STR_TAIL_LENGTH = 1; + +/* napi_value <-> bool */ +napi_status JSUtil::GetValue(napi_env env, napi_value in, bool& out) { - DistributedKv::Options options; - napi_value value = nullptr; - napi_get_named_property(env, jsOptions, "createIfMissing", &value); - if (value != nullptr) { - napi_get_value_bool(env, value, &options.createIfMissing); + ZLOGD("napi_value <- bool"); + return napi_get_value_bool(env, in, &out); +} + +napi_status JSUtil::SetValue(napi_env env, const bool& in, napi_value& out) +{ + ZLOGD("napi_value -> bool"); + return napi_get_boolean(env, in, &out); +} + +/* napi_value <-> int32_t */ +napi_status JSUtil::GetValue(napi_env env, napi_value in, int32_t& out) +{ + ZLOGD("napi_value -> uint32_t"); + return napi_get_value_int32(env, in, &out); +} + +napi_status JSUtil::SetValue(napi_env env, const int32_t& in, napi_value& out) +{ + ZLOGD("napi_value <- uint32_t"); + return napi_create_int32(env, in, &out); +} + +/* napi_value <-> uint32_t */ +napi_status JSUtil::GetValue(napi_env env, napi_value in, uint32_t& out) +{ + ZLOGD("napi_value -> uint32_t"); + return napi_get_value_uint32(env, in, &out); +} + +napi_status JSUtil::SetValue(napi_env env, const uint32_t& in, napi_value& out) +{ + ZLOGD("napi_value <- uint32_t"); + return napi_create_uint32(env, in, &out); +} + +/* napi_value <-> int64_t */ +napi_status JSUtil::GetValue(napi_env env, napi_value in, int64_t& out) +{ + ZLOGD("napi_value <- int64_t"); + return napi_get_value_int64(env, in, &out); +} + +napi_status JSUtil::SetValue(napi_env env, const int64_t& in, napi_value& out) +{ + ZLOGD("napi_value <- int64_t"); + return napi_create_int64(env, in, &out); +} + +/* napi_value <-> double */ +napi_status JSUtil::GetValue(napi_env env, napi_value in, double& out) +{ + ZLOGD("napi_value -> double"); + return napi_get_value_double(env, in, &out); +} + +napi_status JSUtil::SetValue(napi_env env, const double& in, napi_value& out) +{ + ZLOGD("napi_value <- double"); + return napi_create_double(env, in, &out); +} + +/* napi_value <-> std::string */ +napi_status JSUtil::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; } - value = nullptr; - napi_get_named_property(env, jsOptions, "encrypt", &value); - if (value != nullptr) { - napi_get_value_bool(env, value, &options.encrypt); + ZLOGD("napi_value -> std::string get length %{public}d", (int)maxLen); + 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; } - value = nullptr; - napi_get_named_property(env, jsOptions, "backup", &value); - if (value != nullptr) { - napi_get_value_bool(env, value, &options.backup); + return status; +} + +napi_status JSUtil::SetValue(napi_env env, const std::string& in, napi_value& out) +{ + ZLOGD("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 */ +napi_status JSUtil::GetValue(napi_env env, napi_value in, std::vector& out) +{ + ZLOGD("napi_value -> std::vector"); + bool isArray = false; + napi_is_array(env, in, &isArray); + ZLOGE_RETURN(isArray, "not an array", napi_invalid_arg); + + uint32_t length = 0; + napi_status status = napi_get_array_length(env, in, &length); + ZLOGE_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); + ZLOGE_RETURN((item != nullptr) && (status == napi_ok), "no element", napi_invalid_arg); + std::string value; + status = GetValue(env, item, value); + ZLOGE_RETURN(status == napi_ok, "not a string", napi_invalid_arg); + out.push_back(value); } - value = nullptr; - options.autoSync = false; - napi_get_named_property(env, jsOptions, "autoSync", &value); - if (value != nullptr) { - napi_get_value_bool(env, value, &options.autoSync); + return status; +} + +napi_status JSUtil::SetValue(napi_env env, const std::vector& in, napi_value& out) +{ + ZLOGD("napi_value <- std::vector"); + napi_status status = napi_create_array_with_length(env, in.size(), &out); + ZLOGE_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); + ZLOGE_RETURN((status == napi_ok), "napi_set_element failed!", status); } - value = nullptr; - napi_get_named_property(env, jsOptions, "kvStoreType", &value); - if (value != nullptr) { - int32_t storeType = DistributedKv::DEVICE_COLLABORATION; - napi_get_value_int32(env, value, &storeType); - options.kvStoreType = static_cast(storeType); + return status; +} + +JSUtil::KvStoreVariant JSUtil::Blob2VariantValue(const DistributedKv::Blob& blob) +{ + auto& data = blob.Data(); + // number 2 means: valid Blob must have more than 2 bytes. + if (data.size() < 2) { + ZLOGE("Blob have no data!"); + return JSUtil::KvStoreVariant(); } - value = nullptr; - napi_get_named_property(env, jsOptions, "securityLevel", &value); - if (value != nullptr) { - napi_get_value_int32(env, value, &options.securityLevel); + // number 1 means: skip the first byte, byte[0] is real data type. + std::vector real(data.begin() + 1, data.end()); + ZLOGD("Blob::type %{public}d size=%{public}d", static_cast(data[0]), static_cast(real.size())); + if (data[0] == JSUtil::STRING) { + return JSUtil::KvStoreVariant(std::string(real.begin(), real.end())); } - return options; + if (data[0] == JSUtil::INTEGER) { + uint32_t tmp4int = be32toh(*reinterpret_cast(&(real[0]))); + return JSUtil::KvStoreVariant(*reinterpret_cast(&tmp4int)); + } + if (data[0] == JSUtil::FLOAT) { + uint32_t tmp4flt = be32toh(*reinterpret_cast(&(real[0]))); + return JSUtil::KvStoreVariant(*reinterpret_cast((void*)(&tmp4flt))); + } + if (data[0] == JSUtil::BYTE_ARRAY) { + return JSUtil::KvStoreVariant(std::vector(real.begin(), real.end())); + } + if (data[0] == JSUtil::BOOLEAN) { + return JSUtil::KvStoreVariant(static_cast(real[0])); + } + if (data[0] == JSUtil::DOUBLE) { + uint64_t tmp4dbl = be64toh(*reinterpret_cast(&(real[0]))); + return JSUtil::KvStoreVariant(*reinterpret_cast((void*)(&tmp4dbl))); + } + ZLOGE("Blob::Type is INVALID"); + return JSUtil::KvStoreVariant(); } -std::string JSUtil::Convert2String(napi_env env, napi_value jsString) +DistributedKv::Blob JSUtil::VariantValue2Blob(const JSUtil::KvStoreVariant& value) { - size_t maxLen = JSUtil::MAX_LEN; - napi_status status = napi_get_value_string_utf8(env, jsString, NULL, 0, &maxLen); - if (status != napi_ok) { - GET_AND_THROW_LAST_ERROR((env)); - maxLen = JSUtil::MAX_LEN; + std::vector data; + auto strValue = std::get_if(&value); + if (strValue != nullptr) { + data.push_back(JSUtil::STRING); + data.insert(data.end(), (*strValue).begin(), (*strValue).end()); } - if (maxLen <= 0) { - return std::string(); + auto u8ArrayValue = std::get_if>(&value); + if (u8ArrayValue != nullptr) { + data.push_back(JSUtil::BYTE_ARRAY); + data.insert(data.end(), (*u8ArrayValue).begin(), (*u8ArrayValue).end()); + } + auto boolValue = std::get_if(&value); + if (boolValue != nullptr) { + data.push_back(JSUtil::BOOLEAN); + data.push_back(static_cast(*boolValue)); } - char *buf = new char[maxLen + 1]; - if (buf == nullptr) { - return std::string(); + uint8_t *tmp = nullptr; + auto intValue = std::get_if(&value); + if (intValue != nullptr) { + int32_t tmp4int = *intValue; // copy value, and make it available in stack space. + htobe32(*reinterpret_cast(&tmp4int)); + tmp = reinterpret_cast(&tmp4int); + data.push_back(JSUtil::INTEGER); + data.insert(data.end(), tmp, tmp + sizeof(int32_t) / sizeof(uint8_t)); } - size_t len = 0; - status = napi_get_value_string_utf8(env, jsString, buf, maxLen + 1, &len); - if (status != napi_ok) { - GET_AND_THROW_LAST_ERROR((env)); + auto fltValue = std::get_if(&value); + if (fltValue != nullptr) { + float tmp4flt = *fltValue; // copy value, and make it available in stack space. + uint32_t tmp32 = htobe32(*reinterpret_cast(&tmp4flt)); + tmp = reinterpret_cast(&tmp32); + data.push_back(JSUtil::FLOAT); + data.insert(data.end(), tmp, tmp + sizeof(float) / sizeof(uint8_t)); } - buf[len] = 0; - std::string value(buf); - delete[] buf; - return value; + auto dblValue = std::get_if(&value); + if (dblValue != nullptr) { + double tmp4dbl = *dblValue; // copy value, and make it available in stack space. + uint64_t tmp64 = htobe64(*reinterpret_cast(&tmp4dbl)); + tmp = reinterpret_cast(&tmp64); + data.push_back(JSUtil::DOUBLE); + data.insert(data.end(), tmp, tmp + sizeof(double) / sizeof(uint8_t)); + } + return DistributedKv::Blob(data); } -napi_value JSUtil::Convert2JSNotification(napi_env env, const DistributedKv::ChangeNotification ¬ification) +/* napi_value <-> KvStoreVariant */ +napi_status JSUtil::GetValue(napi_env env, napi_value in, JSUtil::KvStoreVariant& out) { - napi_value result = nullptr; - napi_create_object(env, &result); - napi_set_named_property(env, result, "deviceId", Convert2JSString(env, notification.GetDeviceId())); - napi_set_named_property(env, result, "insertEntries", GetJSEntries(env, notification.GetInsertEntries())); - napi_set_named_property(env, result, "updateEntries", GetJSEntries(env, notification.GetUpdateEntries())); - napi_set_named_property(env, result, "deleteEntries", GetJSEntries(env, notification.GetDeleteEntries())); - return result; + napi_valuetype type = napi_undefined; + napi_status status = napi_typeof(env, in, &type); + ZLOGE_RETURN((status == napi_ok), "invalid type", status); + switch (type) { + case napi_boolean: { + bool vBool = false; + status = JSUtil::GetValue(env, in, vBool); + out = vBool; + break; + } + case napi_number: { + double vNum = 0.0f; + status = JSUtil::GetValue(env, in, vNum); + out = vNum; + break; + } + case napi_string: { + std::string vString; + status = JSUtil::GetValue(env, in, vString); + out = vString; + break; + } + case napi_object: { + std::vector vct; + status = JSUtil::GetValue(env, in, vct); + out = vct; + break; + } + default: + ZLOGE(" napi_value -> KvStoreVariant not [Uint8Array | string | boolean | number] type=%{public}d", type); + status = napi_invalid_arg; + break; + } + return status; } -napi_value JSUtil::Convert2JSTupleArray(napi_env env, std::map &data) +napi_status JSUtil::SetValue(napi_env env, const JSUtil::KvStoreVariant& in, napi_value& out) { - napi_value result = nullptr; - napi_create_array_with_length(env, data.size(), &result); - int index = 0; - for (const auto &[key, value] : data) { - 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, 0, jsKey); - napi_value jsValue = nullptr; - napi_create_int32(env, value, &jsValue); - napi_set_element(env, element, 1, jsValue); - napi_set_element(env, result, index++, element); + auto strValue = std::get_if(&in); + if (strValue != nullptr) { + return SetValue(env, *strValue, out); + } + auto intValue = std::get_if(&in); + if (intValue != nullptr) { + return SetValue(env, *intValue, out); + } + auto fltValue = std::get_if(&in); + if (fltValue != nullptr) { + return SetValue(env, *fltValue, out); } - return result; + auto pUint8 = std::get_if>(&in); + if (pUint8 != nullptr) { + return SetValue(env, *pUint8, out); + } + auto boolValue = std::get_if(&in); + if (boolValue != nullptr) { + return SetValue(env, *boolValue, out); + } + auto dblValue = std::get_if(&in); + if (dblValue != nullptr) { + return SetValue(env, *dblValue, out); + } + + ZLOGE("napi_value <- KvStoreVariant INVALID value type"); + return napi_invalid_arg; } -std::vector JSUtil::Convert2StringArray(napi_env env, napi_value jsValue) +/* napi_value <-> QueryVariant */ +napi_status JSUtil::GetValue(napi_env env, napi_value in, JSUtil::QueryVariant& out) { - bool isArray = false; - napi_is_array(env, jsValue, &isArray); - NAPI_ASSERT_BASE(env, isArray, "not array", { }); - uint32_t length = 0; - napi_get_array_length(env, jsValue, &length); - std::vector devices; - for (uint32_t i = 0; i < length; ++i) { - napi_value deviceId = nullptr; - napi_get_element(env, jsValue, i, &deviceId); - if (deviceId == nullptr) { - continue; + napi_valuetype type = napi_undefined; + napi_status status = napi_typeof(env, in, &type); + ZLOGE_RETURN((status == napi_ok), "invalid type", status); + ZLOGD("napi_value -> QueryVariant type=%{public}d", type); + switch (type) { + case napi_boolean: { + bool vBool = false; + status = JSUtil::GetValue(env, in, vBool); + out = vBool; + break; + } + case napi_number: { + double vNum = 0.0f; + status = JSUtil::GetValue(env, in, vNum); + out = vNum; + break; } - devices.push_back(Convert2String(env, deviceId)); + case napi_string: { + std::string vString; + status = JSUtil::GetValue(env, in, vString); + out = vString; + break; + } + default: + status = napi_invalid_arg; + break; + } + ZLOGE_RETURN((status == napi_ok), "napi_value -> QueryVariant bad value!", status); + return status; +} + +napi_status JSUtil::SetValue(napi_env env, const JSUtil::QueryVariant& in, napi_value& out) +{ + ZLOGD("napi_value <- QueryVariant "); + napi_status status = napi_invalid_arg; + auto strValue = std::get_if(&in); + if (strValue != nullptr) { + status = SetValue(env, *strValue, out); } - return devices; + auto boolValue = std::get_if(&in); + if (boolValue != nullptr) { + status = SetValue(env, *boolValue, out); + } + auto dblValue = std::get_if(&in); + if (dblValue != nullptr) { + status = SetValue(env, *dblValue, out); + } else { + ZLOGD("napi_value <- QueryVariant INVALID value type"); + } + return status; +} + +/* napi_value <-> std::vector */ +napi_status JSUtil::GetValue(napi_env env, napi_value in, std::vector& out) +{ + ZLOGD("napi_value -> std::vector "); + 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); + ZLOGD("array type=%{public}d length=%{public}d offset=%{public}d", (int)type, (int)length, (int)offset); + ZLOGE_RETURN(status == napi_ok, "napi_get_typedarray_info failed!", napi_invalid_arg); + ZLOGE_RETURN(type == napi_uint8_array, "is not Uint8Array!", napi_invalid_arg); + ZLOGE_RETURN((length > 0) && (data != nullptr), "invalid data!", napi_invalid_arg); + out.assign((uint8_t*)data, ((uint8_t*)data) + length); + return status; } -napi_value JSUtil::Convert2JSString(napi_env env, const std::vector &key) +napi_status JSUtil::SetValue(napi_env env, const std::vector& in, napi_value& out) { - std::string realkey(key.begin(), key.end()); - napi_value jsKey = nullptr; - napi_create_string_utf8(env, realkey.c_str(), realkey.size(), &jsKey); - return jsKey; + ZLOGD("napi_value <- std::vector "); + ZLOGE_RETURN(in.size() > 0, "invalid std::vector", napi_invalid_arg); + void* data = nullptr; + napi_value buffer = nullptr; + napi_status status = napi_create_arraybuffer(env, in.size(), &data, &buffer); + ZLOGE_RETURN((status == napi_ok), "create array buffer failed!", status); + + if (memcpy_s(data, in.size(), in.data(), in.size()) != EOK) { + ZLOGE("memcpy_s not EOK"); + return napi_invalid_arg; + } + status = napi_create_typedarray(env, napi_uint8_array, in.size(), buffer, 0, &out); + ZLOGE_RETURN((status == napi_ok), "napi_value <- std::vector invalid value", status); + return status; } -napi_value JSUtil::Convert2JSValue(napi_env env, const std::vector &data) +template +void TypedArray2Vector(uint8_t* data, size_t length, napi_typedarray_type type, std::vector& out) { - napi_value result = nullptr; - napi_get_undefined(env, &result); - NAPI_ASSERT_BASE(env, data.size() > 1, "invalid data", result); - napi_create_object(env, &result); - napi_value jsType = nullptr; - napi_create_int32(env, data[0], &jsType); - napi_set_named_property(env, result, "type", jsType); - napi_value jsValue = nullptr; - switch (data[0]) { - case STRING: - napi_create_string_utf8(env, reinterpret_cast(data.data() + DATA_POS), data.size() - DATA_POS, - &jsValue); + auto convert = [&out](auto* data, size_t elements) { + for (size_t index = 0; index < elements; index++) { + out.push_back(static_cast(data[index])); + } + }; + + switch (type) { + case napi_int8_array: + convert(reinterpret_cast(data), length); break; - case BOOLEAN: - napi_get_boolean(env, *(reinterpret_cast(data.data() + DATA_POS)), &jsValue); + case napi_uint8_array: + convert(data, length); break; - case BYTE_ARRAY: { - uint8_t *native = nullptr; - napi_value buffer = nullptr; - napi_create_arraybuffer(env, data.size() - DATA_POS, reinterpret_cast(&native), &buffer); - memcpy_s(native, data.size() - DATA_POS, data.data() + DATA_POS, data.size() - DATA_POS); - napi_create_typedarray(env, napi_uint8_array, data.size() - DATA_POS, buffer, 0, &jsValue); + case napi_uint8_clamped_array: + convert(data, length); break; - } - default: - jsValue = Convert2JSNumber(env, data); + case napi_int16_array: + convert(reinterpret_cast(data), length / sizeof(int16_t)); + break; + case napi_uint16_array: + convert(reinterpret_cast(data), length / sizeof(uint16_t)); + break; + case napi_int32_array: + convert(reinterpret_cast(data), length / sizeof(int32_t)); + break; + case napi_uint32_array: + convert(reinterpret_cast(data), length / sizeof(uint32_t)); + break; + case napi_float32_array: + convert(reinterpret_cast(data), length / sizeof(float)); + break; + case napi_float64_array: + convert(reinterpret_cast(data), length / sizeof(double)); + break; + case napi_bigint64_array: + convert(reinterpret_cast(data), length / sizeof(int64_t)); + break; + case napi_biguint64_array: + convert(reinterpret_cast(data), length / sizeof(uint64_t)); break; + default: + ZLOGE_RETURN_VOID(false, "[FATAL] invalid napi_typedarray_type!"); } - napi_set_named_property(env, result, "value", jsValue); - return result; } -std::vector JSUtil::Convert2Vector(napi_env env, napi_value jsValue) +/* napi_value <-> std::vector */ +napi_status JSUtil::GetValue(napi_env env, napi_value in, std::vector& out) { - napi_valuetype valueType; - napi_typeof(env, jsValue, &valueType); - switch (valueType) { - case napi_boolean: - return ConvertBool2Vector(env, jsValue); - case napi_number: - return ConvertNumber2Vector(env, jsValue); - case napi_string: - return ConvertString2Vector(env, jsValue); - case napi_object: - return ConvertUint8Array2Vector(env, jsValue); - default: - break; + ZLOGD("napi_value -> std::vector "); + napi_typedarray_type type = napi_biguint64_array; + size_t length = 0; + napi_value buffer = nullptr; + size_t offset = 0; + uint8_t* data = nullptr; + napi_status status = napi_get_typedarray_info(env, in, &type, &length, (void**)&data, &buffer, &offset); + ZLOGD("array type=%{public}d length=%{public}d offset=%{public}d", (int)type, (int)length, (int)offset); + ZLOGE_RETURN(status == napi_ok, "napi_get_typedarray_info failed!", napi_invalid_arg); + ZLOGE_RETURN(type <= napi_int32_array, "is not int32 supported typed array!", napi_invalid_arg); + ZLOGE_RETURN((length > 0) && (data != nullptr), "invalid data!", napi_invalid_arg); + TypedArray2Vector(data, length, type, out); + return status; +} + +napi_status JSUtil::SetValue(napi_env env, const std::vector& in, napi_value& out) +{ + ZLOGD("napi_value <- std::vector "); + size_t bytes = in.size() * sizeof(int32_t); + ZLOGE_RETURN(bytes > 0, "invalid std::vector", napi_invalid_arg); + void* data = nullptr; + napi_value buffer = nullptr; + napi_status status = napi_create_arraybuffer(env, bytes, &data, &buffer); + ZLOGE_RETURN((status == napi_ok), "invalid buffer", status); + + if (memcpy_s(data, bytes, in.data(), bytes) != EOK) { + ZLOGE("memcpy_s not EOK"); + return napi_invalid_arg; } - return {INVALID}; + status = napi_create_typedarray(env, napi_int32_array, in.size(), buffer, 0, &out); + ZLOGE_RETURN((status == napi_ok), "invalid buffer", status); + return status; } -std::vector JSUtil::ConvertUint8Array2Vector(napi_env env, napi_value jsValue) +/* napi_value <-> std::vector */ +napi_status JSUtil::GetValue(napi_env env, napi_value in, std::vector& out) { - bool isTypedArray = false; - if (napi_is_typedarray(env, jsValue, &isTypedArray) != napi_ok || !isTypedArray) { - return {INVALID}; + ZLOGD("napi_value -> std::vector "); + napi_typedarray_type type = napi_biguint64_array; + size_t length = 0; + napi_value buffer = nullptr; + size_t offset = 0; + uint8_t* data = nullptr; + napi_status status = napi_get_typedarray_info(env, in, &type, &length, (void**)&data, &buffer, &offset); + ZLOGD("napi_get_typedarray_info type=%{public}d", (int)type); + ZLOGE_RETURN(status == napi_ok, "napi_get_typedarray_info failed!", napi_invalid_arg); + ZLOGE_RETURN((type <= napi_uint16_array) || (type == napi_uint32_array), "invalid type!", napi_invalid_arg); + ZLOGE_RETURN((length > 0) && (data != nullptr), "invalid data!", napi_invalid_arg); + TypedArray2Vector(data, length, type, out); + return status; +} + +napi_status JSUtil::SetValue(napi_env env, const std::vector& in, napi_value& out) +{ + ZLOGD("napi_value <- std::vector "); + size_t bytes = in.size() * sizeof(uint32_t); + ZLOGE_RETURN(bytes > 0, "invalid std::vector", napi_invalid_arg); + void* data = nullptr; + napi_value buffer = nullptr; + napi_status status = napi_create_arraybuffer(env, bytes, &data, &buffer); + ZLOGE_RETURN((status == napi_ok), "invalid buffer", status); + + if (memcpy_s(data, bytes, in.data(), bytes) != EOK) { + ZLOGE("memcpy_s not EOK"); + return napi_invalid_arg; } + status = napi_create_typedarray(env, napi_uint32_array, in.size(), buffer, 0, &out); + ZLOGE_RETURN((status == napi_ok), "invalid buffer", status); + return status; +} - napi_typedarray_type type; +/* napi_value <-> std::vector */ +napi_status JSUtil::GetValue(napi_env env, napi_value in, std::vector& out) +{ + ZLOGD("napi_value -> std::vector "); + napi_typedarray_type type = napi_biguint64_array; size_t length = 0; napi_value buffer = nullptr; size_t offset = 0; - uint8_t *data = nullptr; - NAPI_CALL_BASE(env, napi_get_typedarray_info(env, jsValue, &type, - &length, reinterpret_cast(&data), &buffer, &offset), { INVALID }); - if (type != napi_uint8_array || length == 0 || data == nullptr) { - return {INVALID}; + uint8_t* data = nullptr; + napi_status status = napi_get_typedarray_info(env, in, &type, &length, (void**)&data, &buffer, &offset); + ZLOGD("array type=%{public}d length=%{public}d offset=%{public}d", (int)type, (int)length, (int)offset); + ZLOGE_RETURN(status == napi_ok, "napi_get_typedarray_info failed!", napi_invalid_arg); + ZLOGE_RETURN((type <= napi_uint32_array) || (type == napi_bigint64_array), "invalid type!", napi_invalid_arg); + ZLOGE_RETURN((length > 0) && (data != nullptr), "invalid data!", napi_invalid_arg); + TypedArray2Vector(data, length, type, out); + return status; +} + +napi_status JSUtil::SetValue(napi_env env, const std::vector& in, napi_value& out) +{ + ZLOGD("napi_value <- std::vector "); + size_t bytes = in.size() * sizeof(int64_t); + ZLOGE_RETURN(bytes > 0, "invalid std::vector", napi_invalid_arg); + void* data = nullptr; + napi_value buffer = nullptr; + napi_status status = napi_create_arraybuffer(env, bytes, &data, &buffer); + ZLOGE_RETURN((status == napi_ok), "invalid buffer", status); + + if (memcpy_s(data, bytes, in.data(), bytes) != EOK) { + ZLOGE("memcpy_s not EOK"); + return napi_invalid_arg; + } + status = napi_create_typedarray(env, napi_bigint64_array, in.size(), buffer, 0, &out); + ZLOGE_RETURN((status == napi_ok), "invalid buffer", status); + return status; +} +/* napi_value <-> std::vector */ +napi_status JSUtil::GetValue(napi_env env, napi_value in, std::vector& out) +{ + bool isTypedArray = false; + napi_status status = napi_is_typedarray(env, in, &isTypedArray); + ZLOGD("napi_value -> std::vector input %{public}s a TypedArray", isTypedArray ? "is" : "is not"); + if (isTypedArray) { + ZLOGD("napi_value -> std::vector "); + napi_typedarray_type type = napi_biguint64_array; + size_t length = 0; + napi_value buffer = nullptr; + size_t offset = 0; + uint8_t* data = nullptr; + status = napi_get_typedarray_info(env, in, &type, &length, (void**)&data, &buffer, &offset); + ZLOGD("napi_get_typedarray_info status=%{public}d type=%{public}d", status, (int)type); + ZLOGE_RETURN(status == napi_ok, "napi_get_typedarray_info failed!", napi_invalid_arg); + ZLOGE_RETURN((length > 0) && (data != nullptr), "invalid data!", napi_invalid_arg); + TypedArray2Vector(data, length, type, out); + } else { + bool isArray = false; + status = napi_is_array(env, in, &isArray); + ZLOGD("napi_value -> std::vector input %{public}s an Array", isArray ? "is" : "is not"); + ZLOGE_RETURN((status == napi_ok) && isArray, "invalid data!", napi_invalid_arg); + uint32_t length = 0; + status = napi_get_array_length(env, in, &length); + ZLOGE_RETURN((status == napi_ok) && (length > 0), "invalid data!", napi_invalid_arg); + for (uint32_t i = 0; i < length; ++i) { + napi_value item = nullptr; + status = napi_get_element(env, in, i, &item); + ZLOGE_RETURN((item != nullptr) && (status == napi_ok), "no element", napi_invalid_arg); + double vi = 0.0f; + status = napi_get_value_double(env, item, &vi); + ZLOGE_RETURN(status == napi_ok, "element not a double", napi_invalid_arg); + out.push_back(vi); + } } - std::vector result(sizeof(uint8_t) + length); - result[TYPE_POS] = BYTE_ARRAY; - memcpy_s(result.data() + DATA_POS, result.size() - DATA_POS, data, length); - return result; + return status; +} + +napi_status JSUtil::SetValue(napi_env env, const std::vector& in, napi_value& out) +{ + ZLOGD("napi_value <- std::vector "); + (void)(env); + (void)(in); + (void)(out); + ZLOGE_RETURN(false, "std::vector to napi_value, unsupported!", napi_invalid_arg); + return napi_invalid_arg; } -std::vector JSUtil::ConvertString2Vector(napi_env env, napi_value jsValue) +/* napi_value <-> std::map */ +napi_status JSUtil::GetValue(napi_env env, napi_value in, std::map& out) { - std::string value = Convert2String(env, jsValue); - std::vector result(sizeof(uint8_t) + value.size()); - result[TYPE_POS] = STRING; - if (memcpy_s(result.data() + DATA_POS, result.size() - DATA_POS, value.data(), value.size()) != EOK) { - result[TYPE_POS] = INVALID; + ZLOGD("napi_value -> std::map "); + (void)(env); + (void)(in); + (void)(out); + ZLOGE_RETURN(false, "std::map from napi_value, unsupported!", napi_invalid_arg); + return napi_invalid_arg; +} + +napi_status JSUtil::SetValue(napi_env env, const std::map& in, napi_value& out) +{ + ZLOGD("napi_value <- std::map "); + napi_status status = napi_create_array_with_length(env, in.size(), &out); + ZLOGE_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(value), &jsValue); + napi_set_element(env, element, TUPLE_VALUE, jsValue); + napi_set_element(env, out, index++, element); } - return result; + return status; } -std::vector JSUtil::ConvertNumber2Vector(napi_env env, napi_value jsValue) +/* + * interface Value { + * type: ValueType; + * value: Uint8Array | string | number | boolean; + * } + * interface Entry { + * key: string; + * value: Value; + * } + */ +/* napi_value <-> DistributedKv::Entry */ +napi_status JSUtil::GetValue(napi_env env, napi_value in, DistributedKv::Entry& out) { - // the JavaScript number is 64 bits double. - double value = 0; - auto status = napi_get_value_double(env, jsValue, &value); - if (status == napi_ok) { - std::vector result(sizeof(uint8_t) + sizeof(double)); - result[TYPE_POS] = DOUBLE; - uint8_t byteValue[MAX_NUMBER_BYTES]; - errno_t err = memcpy_s(byteValue, MAX_NUMBER_BYTES, &value, sizeof(double)); - if (err != EOK) { - return {INVALID}; - } - err = memcpy_s(result.data() + DATA_POS, sizeof(double), byteValue, sizeof(byteValue)); - if (err != EOK) { - return {INVALID}; + ZLOGD("napi_value -> DistributedKv::Entry "); + napi_value propKey = nullptr; + napi_status status = napi_get_named_property(env, in, "key", &propKey); + ZLOGE_RETURN((status == napi_ok), "no property key", status); + std::string key; + status = GetValue(env, propKey, key); + ZLOGE_RETURN((status == napi_ok), "no value of key", status); + out.key = key; + + napi_value propValue = nullptr; + status = napi_get_named_property(env, in, "value", &propValue); + ZLOGE_RETURN((status == napi_ok), "no property value", status); + + napi_value propVType = nullptr; + status = napi_get_named_property(env, propValue, "type", &propVType); + ZLOGE_RETURN((status == napi_ok), "no property value.type", status); + int32_t type = 0; // int8_t + status = GetValue(env, propVType, type); + ZLOGE_RETURN((status == napi_ok), "no value of value.type", status); + + napi_value propVValue = nullptr; + status = napi_get_named_property(env, propValue, "value", &propVValue); + ZLOGE_RETURN((status == napi_ok), "no property value.value", status); + KvStoreVariant value = 0; + status = GetValue(env, propVValue, value); + ZLOGE_RETURN((status == napi_ok), "no value of value.value", status); + + out.value = JSUtil::VariantValue2Blob(value); + if (type != out.value[0]) { + ZLOGE("unmarch type[%{public}d] to value.type[%{public}d]", (int)type, (int)out.value[0]); + } + return status; +} + +napi_status JSUtil::SetValue(napi_env env, const DistributedKv::Entry& in, napi_value& out) +{ + ZLOGD("napi_value <- DistributedKv::Entry "); + napi_status status = napi_create_object(env, &out); + ZLOGE_RETURN((status == napi_ok), "invalid entry object", status); + + napi_value key = nullptr; + status = SetValue(env, in.key.ToString(), key); + ZLOGE_RETURN((status == napi_ok), "invalid entry key", status); + napi_set_named_property(env, out, "key", key); + + ZLOGE_RETURN((in.value.Size() > 0), "invalid entry value", status); + napi_value value = nullptr; + + status = napi_create_object(env, &value); + ZLOGE_RETURN((status == napi_ok), "invalid value object", status); + napi_value vType = nullptr; + napi_create_int32(env, in.value[0], &vType); + napi_set_named_property(env, value, "type", vType); + + napi_value vValue = nullptr; + status = SetValue(env, Blob2VariantValue(in.value), vValue); // Blob + ZLOGE_RETURN((status == napi_ok), "invalid entry value", status); + napi_set_named_property(env, value, "value", vValue); + + napi_set_named_property(env, out, "value", value); + return status; +} + +/* napi_value <-> std::list */ +napi_status JSUtil::GetValue(napi_env env, napi_value in, std::list& out) +{ + ZLOGD("napi_value -> std::list "); + bool isArray = false; + napi_is_array(env, in, &isArray); + ZLOGE_RETURN(isArray, "not array", napi_invalid_arg); + + uint32_t length = 0; + napi_status status = napi_get_array_length(env, in, &length); + ZLOGE_RETURN((status == napi_ok) && (length > 0), "get_array failed!", status); + for (uint32_t i = 0; i < length; ++i) { + napi_value item = nullptr; + status = napi_get_element(env, in, i, &item); + ZLOGE_RETURN((status == napi_ok), "no element", status); + if ((status != napi_ok) || (item == nullptr)) { + continue; } - return result; + DistributedKv::Entry entry; + status = GetValue(env, item, entry); + out.push_back(entry); } + return status; +} - return {INVALID}; +napi_status JSUtil::SetValue(napi_env env, const std::list& in, napi_value& out) +{ + ZLOGD("napi_value <- std::list %{public}u", static_cast(in.size())); + napi_status status = napi_create_array_with_length(env, in.size(), &out); + ZLOGE_RETURN(status == napi_ok, "create array failed!", status); + int index = 0; + for (const auto& item : in) { + napi_value entry = nullptr; + SetValue(env, item, entry); + napi_set_element(env, out, index++, entry); + } + return status; } -std::vector JSUtil::ConvertBool2Vector(napi_env env, napi_value jsValue) +/* napi_value <-> std::vector */ +napi_status JSUtil::GetValue(napi_env env, napi_value in, std::vector& out) { - std::vector result; - result.resize(sizeof(uint8_t) + sizeof(int32_t)); - result[TYPE_POS] = BOOLEAN; - bool value = false; - napi_get_value_bool(env, jsValue, &value); - *reinterpret_cast(result.data() + DATA_POS) = value ? 1 : 0; - return result; + ZLOGD("napi_value -> std::vector "); + bool isArray = false; + napi_is_array(env, in, &isArray); + ZLOGE_RETURN(isArray, "not array", napi_invalid_arg); + + uint32_t length = 0; + napi_status status = napi_get_array_length(env, in, &length); + ZLOGE_RETURN((status == napi_ok) && (length > 0), "get_array failed!", status); + for (uint32_t i = 0; i < length; ++i) { + napi_value item = nullptr; + status = napi_get_element(env, in, i, &item); + ZLOGE_RETURN((status == napi_ok), "no element", status); + if ((status != napi_ok) || (item == nullptr)) { + continue; + } + DistributedKv::Entry entry; + status = GetValue(env, item, entry); + out.push_back(entry); + } + return status; } -napi_value JSUtil::GetJSEntries(napi_env env, const std::list &entries) +napi_status JSUtil::SetValue(napi_env env, const std::vector& in, napi_value& out) { - napi_value jsValue = nullptr; - napi_create_array_with_length(env, entries.size(), &jsValue); + ZLOGD("napi_value <- std::vector %{public}u", static_cast(in.size())); + napi_status status = napi_create_array_with_length(env, in.size(), &out); + ZLOGE_RETURN(status == napi_ok, "create array failed!", status); int index = 0; - for (const auto &data : entries) { + for (const auto& item : in) { napi_value entry = nullptr; - napi_create_object(env, &entry); - napi_set_named_property(env, entry, "key", Convert2JSString(env, data.key.Data())); - napi_set_named_property(env, entry, "value", Convert2JSValue(env, data.value.Data())); - napi_set_element(env, jsValue, index++, entry); + SetValue(env, item, entry); + napi_set_element(env, out, index++, entry); } - return jsValue; + return status; } -napi_value JSUtil::GetJSEntries(napi_env env, const std::vector &entries) +/* napi_value <-> std::vector */ +napi_status JSUtil::GetValue(napi_env env, napi_value in, std::vector& out) { - napi_value jsValue = nullptr; - napi_create_array_with_length(env, entries.size(), &jsValue); + ZLOGD("napi_value -> std::vector "); + bool isArray = false; + napi_is_array(env, in, &isArray); + ZLOGE_RETURN(isArray, "not array", napi_invalid_arg); + + uint32_t length = 0; + napi_status status = napi_get_array_length(env, in, &length); + ZLOGE_RETURN((status == napi_ok) && (length > 0), "get_array failed!", status); + for (uint32_t i = 0; i < length; ++i) { + napi_value item = nullptr; + status = napi_get_element(env, in, i, &item); + ZLOGE_RETURN((status == napi_ok), "no element", status); + if ((status != napi_ok) || (item == nullptr)) { + continue; + } + std::string value; + status = GetValue(env, item, value); + DistributedKv::StoreId storeId { value }; + out.push_back(storeId); + } + return status; +} + +napi_status JSUtil::SetValue(napi_env env, const std::vector& in, napi_value& out) +{ + ZLOGD("napi_value <- std::vector %{public}u", static_cast(in.size())); + napi_status status = napi_create_array_with_length(env, in.size(), &out); + ZLOGE_RETURN((status == napi_ok), "create_array failed!", status); int index = 0; - for (const auto &data : entries) { + for (const auto& item : in) { napi_value entry = nullptr; - napi_create_object(env, &entry); - napi_set_named_property(env, entry, "key", Convert2JSString(env, data.key.Data())); - napi_set_named_property(env, entry, "value", Convert2JSValue(env, data.value.Data())); - napi_set_element(env, jsValue, index++, entry); + SetValue(env, item.storeId, entry); + napi_set_element(env, out, index++, entry); } - return jsValue; + return status; } -napi_value JSUtil::Convert2JSString(napi_env env, const std::string &cString) +/* napi_value <-> DistributedKv::ChangeNotification */ +napi_status JSUtil::GetValue(napi_env env, napi_value in, DistributedKv::ChangeNotification& out) { - napi_value jsValue = nullptr; - napi_create_string_utf8(env, cString.c_str(), cString.size(), &jsValue); - return jsValue; + ZLOGD("napi_value -> DistributedKv::ChangeNotification "); + (void)(env); + (void)(in); + (void)(out); + ZLOGE_RETURN(false, "DistributedKv::ChangeNotification from napi_value, unsupported!", napi_invalid_arg); + return napi_invalid_arg; } -napi_value JSUtil::Convert2JSNumber(napi_env env, const std::vector &data) +napi_status JSUtil::SetValue(napi_env env, const DistributedKv::ChangeNotification& in, napi_value& out) { - napi_value jsValue = nullptr; - uint8_t byteValue[MAX_NUMBER_BYTES]; - double value; - switch (data[0]) { - case INTEGER: - memcpy_s(byteValue, sizeof(byteValue), data.data() + DATA_POS, sizeof(int32_t)); - value = *(reinterpret_cast(byteValue)); - break; - case FLOAT: - memcpy_s(byteValue, sizeof(byteValue), data.data() + DATA_POS, sizeof(float)); - value = *(reinterpret_cast(byteValue)); - break; - case DOUBLE: - memcpy_s(byteValue, sizeof(byteValue), data.data() + DATA_POS, sizeof(double)); - value = *(reinterpret_cast(byteValue)); - break; - default: - napi_get_undefined(env, &jsValue); - return jsValue; + ZLOGD("napi_value <- DistributedKv::ChangeNotification "); + napi_status status = napi_create_object(env, &out); + ZLOGE_RETURN((status == napi_ok), "napi_create_object for DistributedKv::ChangeNotification failed!", status); + napi_value deviceId = nullptr; + status = SetValue(env, in.GetDeviceId(), deviceId); + ZLOGE_RETURN((status == napi_ok) || (deviceId == nullptr), "GetDeviceId failed!", status); + status = napi_set_named_property(env, out, "deviceId", deviceId); + ZLOGE_RETURN((status == napi_ok), "set_named_property deviceId failed!", status); + + napi_value insertEntries = nullptr; + status = SetValue(env, in.GetInsertEntries(), insertEntries); + ZLOGE_RETURN((status == napi_ok) || (insertEntries == nullptr), "GetInsertEntries failed!", status); + status = napi_set_named_property(env, out, "insertEntries", insertEntries); + ZLOGE_RETURN((status == napi_ok), "set_named_property insertEntries failed!", status); + + napi_value updateEntries = nullptr; + status = SetValue(env, in.GetUpdateEntries(), updateEntries); + ZLOGE_RETURN((status == napi_ok) || (updateEntries == nullptr), "GetUpdateEntries failed!", status); + status = napi_set_named_property(env, out, "updateEntries", updateEntries); + ZLOGE_RETURN((status == napi_ok), "set_named_property updateEntries failed!", status); + + napi_value deleteEntries = nullptr; + status = SetValue(env, in.GetDeleteEntries(), deleteEntries); + ZLOGE_RETURN((status == napi_ok) || (deleteEntries == nullptr), "GetDeleteEntries failed!", status); + status = napi_set_named_property(env, out, "deleteEntries", deleteEntries); + ZLOGE_RETURN((status == napi_ok), "set_named_property deleteEntries failed!", status); + return status; +} + +/* napi_value <-> DistributedKv::Options */ +napi_status JSUtil::GetValue(napi_env env, napi_value in, DistributedKv::Options& options) +{ + ZLOGD("napi_value -> DistributedKv::Options "); + GetNamedProperty(env, in, "createIfMissing", options.createIfMissing); + GetNamedProperty(env, in, "encrypt", options.encrypt); + GetNamedProperty(env, in, "backup", options.backup); + GetNamedProperty(env, in, "autoSync", options.autoSync); + int32_t kvStoreType = 0; + GetNamedProperty(env, in, "kvStoreType", kvStoreType); + options.kvStoreType = static_cast(kvStoreType); + int32_t level = 0; + GetNamedProperty(env, in, "securityLevel", level); + options.securityLevel = level; + return napi_ok; +} + +napi_status JSUtil::SetValue(napi_env env, const DistributedKv::Options& in, napi_value& out) +{ + (void)(env); + (void)(in); + (void)(out); + ZLOGE_RETURN(false, "DistributedKv::Options to napi_value, unsupported!", napi_invalid_arg); + return napi_invalid_arg; +} + +napi_value JSUtil::DefineClass(napi_env env, const std::string& name, + const napi_property_descriptor* properties, size_t count, napi_callback newcb) +{ + // base64("data.distributeddata") as rootPropName, i.e. global. + const std::string rootPropName = "ZGF0YS5kaXN0cmlidXRlZGRhdGE"; + 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) { + ZLOGD("got data.distributeddata.%{public}s as constructor", propName.c_str()); + return constructor; + } + hasProp = false; // no constructor. + } + + NAPI_CALL(env, napi_define_class(env, name.c_str(), name.size(), newcb, nullptr, count, properties, &constructor)); + NAPI_ASSERT(env, constructor != nullptr, "napi_define_class failed!"); + + if (!hasProp) { + napi_set_named_property(env, root, propName.c_str(), constructor); + ZLOGD("save constructor to data.distributeddata.%{public}s", propName.c_str()); + } + return constructor; +} + +napi_ref JSUtil::NewWithRef(napi_env env, size_t argc, napi_value* argv, void** out, napi_value constructor) +{ + napi_value object = nullptr; + napi_status status = napi_new_instance(env, constructor, argc, argv, &object); + ZLOGE_RETURN(status == napi_ok, "napi_new_instance failed", nullptr); + ZLOGE_RETURN(object != nullptr, "napi_new_instance failed", nullptr); + + status = napi_unwrap(env, object, out); + ZLOGE_RETURN(status == napi_ok, "napi_unwrap failed", nullptr); + ZLOGE_RETURN(out != nullptr, "napi_unwrap failed", nullptr); + + napi_ref ref = nullptr; + status = napi_create_reference(env, object, 1, &ref); + ZLOGE_RETURN(status == napi_ok, "napi_create_referenc!e failed", nullptr); + ZLOGE_RETURN(ref != nullptr, "napi_create_referenc!e failed", nullptr); + return ref; +} + +napi_status JSUtil::Unwrap(napi_env env, napi_value in, void** out, napi_value constructor) +{ + if (constructor != nullptr) { + bool isInstance = false; + napi_instanceof(env, in, constructor, &isInstance); + if (!isInstance) { + ZLOGE("not a instance of *"); + return napi_invalid_arg; + } } - napi_create_double(env, value, &jsValue); - return jsValue; + return napi_unwrap(env, in, out); } -} \ No newline at end of file +} // OHOS::DistributedData diff --git a/frameworks/jskitsimpl/distributeddata/src/kv_manager.cpp b/frameworks/jskitsimpl/distributeddata/src/kv_manager.cpp deleted file mode 100644 index 520b731d69e57c4c938f13792dd6cccc54ba6cb6..0000000000000000000000000000000000000000 --- a/frameworks/jskitsimpl/distributeddata/src/kv_manager.cpp +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright (c) 2021 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 "KVManager" - -#include "kv_manager.h" -#include -#include "js_util.h" -#include "distributed_kv_data_manager.h" -#include "async_call.h" -#include "single_kv_store.h" -#include "log_print.h" - -using namespace OHOS::DistributedKv; -namespace OHOS::DistributedData { -static __thread napi_ref g_ctor = nullptr; -napi_value KVManager::CreateKVManager(napi_env env, napi_callback_info info) -{ - ZLOGD("get kv manager!"); - struct ContextInfo { - napi_ref ref = nullptr; - }; - auto ctxInfo = std::make_shared(); - auto input = [ctxInfo](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status { - ZLOGD("CreateKVManager parser to native params %{public}d!", static_cast(argc)); - NAPI_ASSERT_BASE(env, (argc > 0) && (argc <= 2), " should 1 or 2 parameters!", napi_invalid_arg); - napi_value bundle = nullptr; - napi_status retStatus = napi_get_named_property(env, argv[0], "bundleName", &bundle); - NAPI_ASSERT_BASE(env, - ((retStatus == napi_ok) && (bundle != nullptr) && !(JSUtil::Convert2String(env, bundle).empty())), - " bundleName is null!", napi_invalid_arg); - napi_value kvManger = nullptr; - napi_status status = napi_new_instance(env, GetCtor(env), argc, argv, &kvManger); - if ((kvManger == nullptr) || (status != napi_ok)) { - return napi_generic_failure; - } - napi_create_reference(env, kvManger, 1, &(ctxInfo->ref)); - return napi_ok; - }; - auto output = [ctxInfo](napi_env env, napi_value *result) -> napi_status { - napi_status status = napi_get_reference_value(env, ctxInfo->ref, result); - napi_delete_reference(env, ctxInfo->ref); - return status; - }; - auto context = std::make_shared(input, output); - // function createKVManager(config: KVManagerConfig, callback: AsyncCallback): void; - // AsyncCallback at position 1 - AsyncCall asyncCall(env, info, context, 1); - return asyncCall.Call(env); -} - -napi_value KVManager::GetKVStore(napi_env env, napi_callback_info info) -{ - ZLOGD("get kv store!"); - struct ContextInfo { - std::string storeId; - Options options; - KVManager *proxy = nullptr; - SingleKVStore *kvStore = nullptr; - napi_ref ref = nullptr; - }; - auto ctxInfo = std::make_shared(); - auto input = [ctxInfo](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status { - ZLOGD("GetKVStore parser to native params %{public}d!", static_cast(argc)); - 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->storeId = JSUtil::Convert2String(env, argv[0]); - ctxInfo->options = JSUtil::Convert2Options(env, argv[1]); - napi_value kvStore = nullptr; - napi_status status = napi_new_instance(env, SingleKVStore::GetCtor(env), argc, argv, &kvStore); - napi_unwrap(env, kvStore, reinterpret_cast(&ctxInfo->kvStore)); - if (ctxInfo->kvStore == nullptr) { - return napi_invalid_arg; - } - napi_create_reference(env, kvStore, 1, &(ctxInfo->ref)); - return status; - }; - auto output = [ctxInfo](napi_env env, napi_value *result) -> napi_status { - if (*(ctxInfo->kvStore) == nullptr) { - ZLOGE("get kv store failed!"); - *result = nullptr; - napi_delete_reference(env, ctxInfo->ref); - return napi_object_expected; - } - ZLOGD("get kv store success!"); - napi_status status = napi_get_reference_value(env, ctxInfo->ref, result); - napi_delete_reference(env, ctxInfo->ref); - return status; - }; - auto exec = [ctxInfo](AsyncCall::Context *ctx) { - std::shared_ptr kvStore; - ctxInfo->proxy->kvDataManager_.GetSingleKvStore( - ctxInfo->options, {ctxInfo->proxy->bundleName_}, {ctxInfo->storeId}, - kvStore); - *(ctxInfo->kvStore) = std::move(kvStore); - }; - auto context = std::make_shared(input, output); - // getKVStore(storeId: string, options: Options, callback: AsyncCallback): void; - // AsyncCallback at position 2 - AsyncCall asyncCall(env, info, context, 2); - return asyncCall.Call(env, exec); -} - -napi_value KVManager::GetCtor(napi_env env) -{ - napi_value cons; - if (g_ctor != nullptr) { - NAPI_CALL(env, napi_get_reference_value(env, g_ctor, &cons)); - return cons; - } - - napi_property_descriptor clzDes[] = { - DECLARE_NAPI_METHOD("getKVStore", GetKVStore) - }; - NAPI_CALL(env, napi_define_class(env, "KVManager", NAPI_AUTO_LENGTH, Initialize, nullptr, - sizeof(clzDes) / sizeof(napi_property_descriptor), clzDes, &cons)); - NAPI_CALL(env, napi_create_reference(env, cons, 1, &g_ctor)); - return cons; -} - -napi_value KVManager::Initialize(napi_env env, napi_callback_info info) -{ - ZLOGD("constructor kv manager!"); - 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)); - napi_value bundle = nullptr; - NAPI_CALL(env, napi_get_named_property(env, argv[0], "bundleName", &bundle)); - auto *proxy = new KVManager(); - proxy->bundleName_ = JSUtil::Convert2String(env, bundle); - auto finalize = [](napi_env env, void* data, void* hint) { - KVManager *proxy = reinterpret_cast(data); - delete proxy; - }; - if (napi_wrap(env, self, proxy, finalize, nullptr, nullptr) != napi_ok) { - finalize(env, proxy, nullptr); - return nullptr; - } - return self; -} -} diff --git a/frameworks/jskitsimpl/distributeddata/src/napi_queue.cpp b/frameworks/jskitsimpl/distributeddata/src/napi_queue.cpp new file mode 100644 index 0000000000000000000000000000000000000000..88da264709c7d43b26ca976a9bb6fd99fc8c8999 --- /dev/null +++ b/frameworks/jskitsimpl/distributeddata/src/napi_queue.cpp @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#define LOG_TAG "NapiQueue" +#include "napi_queue.h" + +using namespace OHOS::DistributedKv; + +namespace OHOS::DistributedData { +ContextBase::~ContextBase() +{ + ZLOGD("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); + ZLOGE_ON_STATUS(this, "napi_get_cb_info failed!"); + ZLOGE_ON_ARGS(this, argc <= ARGC_MAX, "too many arguments!"); + ZLOGE_ON_ARGS(this, self != nullptr, "no JavaScript this argument!"); + napi_create_reference(env, self, 1, &selfRef); + status = napi_unwrap(env, self, &native); + ZLOGE_ON_STATUS(this, "self unwrap failed!"); + + if (!sync && (argc > 0)) { + // get the last arguments :: + size_t index = argc - 1; + napi_valuetype type = napi_undefined; + napi_status tyst = napi_typeof(env, argv[index], &type); + if ((tyst == napi_ok) && (type == napi_function)) { + status = napi_create_reference(env, argv[index], 1, &callbackRef); + ZLOGE_ON_STATUS(this, "ref callback failed!"); + argc = index; + ZLOGD("async callback, no promise"); + } else { + ZLOGD("no callback, async pormose"); + } + } + + if (parse) { + parse(argc, argv); + } else { + ZLOGE_ON_ARGS(this, argc == 0, "required no arguments!"); + } +} + +napi_value NapiQueue::AsyncWork(napi_env env, std::shared_ptr ctxt, const std::string& name, + NapiAsyncExecute execute, NapiAsyncComplete complete) +{ + ZLOGD("name=%{public}s", name.c_str()); + ctxt->execute = std::move(execute); + ctxt->complete = std::move(complete); + + napi_value promise = nullptr; + if (ctxt->callbackRef == nullptr) { + napi_create_promise(ctxt->env, &ctxt->deferred, &promise); + ZLOGD("create deferred promise"); + } else { + napi_get_undefined(ctxt->env, &promise); + } + + napi_value resource = nullptr; + napi_create_string_utf8(ctxt->env, name.c_str(), NAPI_AUTO_LENGTH, &resource); + napi_create_async_work( + ctxt->env, nullptr, resource, + [](napi_env env, void* data) { + auto ctxt = reinterpret_cast(data); + ZLOGD("napi_async_execute_callback ctxt->status=%{public}d", ctxt->status); + if (ctxt->execute && ctxt->status == napi_ok) { + ZLOGD("call ctxt->execute"); + ctxt->execute(); + } + }, + [](napi_env env, napi_status status, void* data) { + auto ctxt = reinterpret_cast(data); + ZLOGD("napi_async_complete_callback status=%{public}d, ctxt->status=%{public}d", status, ctxt->status); + if ((status != napi_ok) && (ctxt->status == napi_ok)) { + ctxt->status = status; + } + if ((ctxt->complete) && (status == napi_ok) && (ctxt->status == napi_ok)) { + ZLOGD("call ctxt->complete"); + ctxt->complete(ctxt->output); + } + GenerateOutput(ctxt); + }, + (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) +{ + ZLOGD("in"); + napi_value result[RESULT_ALL] = { nullptr }; + 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 message = nullptr; + napi_create_string_utf8(ctxt->env, ctxt->error.c_str(), NAPI_AUTO_LENGTH, &message); + napi_create_error(ctxt->env, nullptr, message, &result[RESULT_ERROR]); + napi_get_undefined(ctxt->env, &result[RESULT_DATA]); + } + if (ctxt->deferred != nullptr) { + if (ctxt->status == napi_ok) { + ZLOGD("deferred promise resolved"); + napi_resolve_deferred(ctxt->env, ctxt->deferred, result[RESULT_DATA]); + } else { + ZLOGD("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; + ZLOGD("call callback function"); + napi_call_function(ctxt->env, nullptr, callback, RESULT_ALL, result, &callbackResult); + } + ctxt->hold.reset(); // release ctxt. + ZLOGD("out"); +} +} // namespace OHOS::DistributedData diff --git a/frameworks/jskitsimpl/distributeddata/src/single_kv_store.cpp b/frameworks/jskitsimpl/distributeddata/src/single_kv_store.cpp deleted file mode 100644 index 64692d9588123d98e002f761370185cba1f0ceef..0000000000000000000000000000000000000000 --- a/frameworks/jskitsimpl/distributeddata/src/single_kv_store.cpp +++ /dev/null @@ -1,366 +0,0 @@ -/* - * Copyright (c) 2021 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 "SingleKVStore" -#include "single_kv_store.h" -#include -#include "async_call.h" -#include "js_util.h" -#include "log_print.h" -#include "single_kvstore.h" - -using namespace OHOS::DistributedKv; -namespace OHOS::DistributedData { -static __thread napi_ref g_ctor = nullptr; -std::map SingleKVStore::eventHandlers_ = { - {"dataChange", SingleKVStore::OnDataChange}, - {"syncComplete", SingleKVStore::OnSyncComplete}, -}; - -SingleKVStore::~SingleKVStore() -{ - if (kvStore_ == nullptr) { - return; - } - - for (int i = 0; i < SUBSCRIBE_ALL + 1; ++i) { - if (dataObserver_[i] == nullptr) { - continue; - } - kvStore_->UnSubscribeKvStore(static_cast(i + 1), dataObserver_[i]); - } - - if (syncObserver_ != nullptr) { - kvStore_->UnRegisterSyncCallback(); - } -} - -napi_value SingleKVStore::GetCtor(napi_env env) -{ - if (g_ctor != nullptr) { - napi_value cons = nullptr; - NAPI_CALL(env, napi_get_reference_value(env, g_ctor, &cons)); - return cons; - } - - napi_property_descriptor clzDes[] = { - DECLARE_NAPI_METHOD("put", SingleKVStore::Put), - DECLARE_NAPI_METHOD("get", SingleKVStore::Get), - DECLARE_NAPI_METHOD("delete", SingleKVStore::Delete), - DECLARE_NAPI_METHOD("on", SingleKVStore::OnEvent), - DECLARE_NAPI_METHOD("sync", SingleKVStore::Sync), - }; - napi_value cons; - NAPI_CALL(env, napi_define_class(env, "SingleKVStore", NAPI_AUTO_LENGTH, Initialize, nullptr, - sizeof(clzDes) / sizeof(napi_property_descriptor), clzDes, &cons)); - NAPI_CALL(env, napi_create_reference(env, cons, 1, &g_ctor)); - return cons; -} - -napi_value SingleKVStore::Put(napi_env env, napi_callback_info info) -{ - auto context = std::make_shared(); - auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status { - // 2 is the max number of parameters - NAPI_ASSERT_BASE(env, argc >= 2, " should 2 or more parameters!", napi_invalid_arg); - context->key = JSUtil::Convert2String(env, argv[0]); - context->value = JSUtil::Convert2Vector(env, argv[1]); - return napi_ok; - }; - auto exec = [context](AsyncCall::Context *ctx) { - OHOS::DistributedKv::Key key(context->key); - OHOS::DistributedKv::Value value(context->value); - Status status = context->proxy->kvStore_->Put(key, value); - context->status = (status != Status::SUCCESS) ? napi_generic_failure : napi_ok; - }; - context->SetAction(std::move(input)); - // 2 is the callback position - AsyncCall asyncCall(env, info, std::dynamic_pointer_cast(context), 2); - return asyncCall.Call(env, exec); -} - -napi_value SingleKVStore::Get(napi_env env, napi_callback_info info) -{ - auto context = std::make_shared(); - auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status { - NAPI_ASSERT_BASE(env, argc >= 1, " should 1 or more parameters!", napi_invalid_arg); - context->key = JSUtil::Convert2String(env, argv[0]); - return napi_ok; - }; - auto output = [context](napi_env env, napi_value *result) -> napi_status { - napi_value data = JSUtil::Convert2JSValue(env, context->value); - return napi_get_named_property(env, data, "value", result); - }; - auto exec = [context](AsyncCall::Context *ctx) { - OHOS::DistributedKv::Key key(context->key); - OHOS::DistributedKv::Value value; - Status status = context->proxy->kvStore_->Get(key, value); - if (status == Status::SUCCESS) { - context->status = napi_ok; - context->value = value.Data(); - } - }; - context->SetAction(std::move(input), std::move(output)); - AsyncCall asyncCall(env, info, std::dynamic_pointer_cast(context), 1); - return asyncCall.Call(env, exec); -} - -napi_value SingleKVStore::Delete(napi_env env, napi_callback_info info) -{ - auto context = std::make_shared(); - auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status { - NAPI_ASSERT_BASE(env, argc >= 1, " should 1 or more parameters!", napi_invalid_arg); - context->key = JSUtil::Convert2String(env, argv[0]); - return napi_ok; - }; - auto exec = [context](AsyncCall::Context *ctx) { - OHOS::DistributedKv::Key key(context->key); - Status status = context->proxy->kvStore_->Delete(key); - if (status == Status::SUCCESS) { - context->status = napi_ok; - } - }; - context->SetAction(std::move(input)); - AsyncCall asyncCall(env, info, std::dynamic_pointer_cast(context), 1); - return asyncCall.Call(env, exec); -} - -napi_value SingleKVStore::OnEvent(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)); - NAPI_ASSERT(env, argc > 0, "there is no args"); - napi_valuetype type; - NAPI_CALL(env, napi_typeof(env, argv[0], &type)); - NAPI_ASSERT(env, type == napi_string, "key not string type"); - std::string event = JSUtil::Convert2String(env, argv[0]); - - ZLOGI("subscribe event:%{public}s", event.c_str()); - auto handle = eventHandlers_.find(event); - NAPI_ASSERT(env, handle != eventHandlers_.end(), "invalid event"); - napi_value result = nullptr; - handle->second(env, argc - 1, &argv[1], self, &result); - return nullptr; -} - -napi_value SingleKVStore::Sync(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)); - // the number of parameters is greater than 2 is error - NAPI_ASSERT_BASE(env, argc >= 2, "args is out of range", nullptr); - NAPI_ASSERT_BASE(env, self != nullptr, "self is nullptr", nullptr); - SingleKVStore *proxy = nullptr; - NAPI_CALL_BASE(env, napi_unwrap(env, self, reinterpret_cast(&proxy)), nullptr); - NAPI_ASSERT_BASE(env, proxy != nullptr, "there is no native kv store", nullptr); - - std::vector devices = JSUtil::Convert2StringArray(env, argv[0]); - int32_t mode = int32_t(SyncMode::PUSH_PULL); - napi_get_value_int32(env, argv[1], &mode); - uint32_t delay = 0; - // 3 is the max number of parameters - if (argc >= 3) { - napi_get_value_uint32(env, argv[2], &delay); // argv[2] is the third parameter - } - ZLOGD("sync data %{public}d, mode:%{public}d, devices:%{public}zu", static_cast(argc), mode, devices.size()); - - Status status = proxy->kvStore_->Sync(devices, static_cast(mode), delay); - NAPI_ASSERT_BASE(env, status == Status::SUCCESS, "call sync failed", nullptr); - return nullptr; -} - -napi_value SingleKVStore::Initialize(napi_env env, napi_callback_info info) -{ - ZLOGD("constructor single kv store!"); - napi_value self = nullptr; - NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &self, nullptr)); - auto *proxy = new SingleKVStore(); - auto release = [proxy]() -> napi_value { - delete proxy; - return nullptr; - }; - auto finalize = [](napi_env env, void *data, void *hint) { - auto *proxy = reinterpret_cast(data); - delete proxy; - }; - NAPI_CALL_BASE(env, napi_wrap(env, self, proxy, finalize, nullptr, nullptr), release()); - return self; -} - -napi_status SingleKVStore::OnDataChange(napi_env env, size_t argc, napi_value *argv, napi_value self, - napi_value *result) -{ - // on(event: 'dataChange', type: SubscribeType, observer: Callback): void; - // except event, there are 2 args - NAPI_ASSERT_BASE(env, argc >= 2, "args is out of range", napi_invalid_arg); - NAPI_ASSERT_BASE(env, self != nullptr, "self is nullptr", napi_invalid_arg); - int32_t type = 0; - napi_get_value_int32(env, argv[0], &type); - NAPI_ASSERT_BASE(env, SUBSCRIBE_LOCAL <= type && type <= SUBSCRIBE_ALL, "type is out of range", napi_invalid_arg); - napi_valuetype valueType = napi_undefined; - napi_typeof(env, argv[1], &valueType); - NAPI_ASSERT_BASE(env, valueType == napi_function, "callback is not a function", napi_invalid_arg); - - SingleKVStore *proxy = nullptr; - NAPI_CALL_BASE(env, napi_unwrap(env, self, reinterpret_cast(&proxy)), napi_invalid_arg); - NAPI_ASSERT_BASE(env, proxy != nullptr, "there is no native kv store", napi_invalid_arg); - - ZLOGI("subscribe data change type %{public}d", type); - std::shared_ptr observer = std::make_shared(env, argv[1]); - Status status = proxy->kvStore_->SubscribeKvStore(static_cast(type + 1), observer); - if (status != Status::SUCCESS) { - return napi_generic_failure; - } - if (proxy->dataObserver_[type] != nullptr) { - proxy->kvStore_->UnSubscribeKvStore(static_cast(type + 1), proxy->dataObserver_[type]); - } - proxy->dataObserver_[type] = std::move(observer); - return napi_ok; -} - -napi_status SingleKVStore::OnSyncComplete(napi_env env, size_t argc, napi_value *argv, napi_value self, - napi_value *result) -{ - // on(event: 'syncComplete', syncCallback: Callback>): void; - // except event, there is 1 arg - NAPI_ASSERT_BASE(env, argc >= 1, "args is out of range", napi_invalid_arg); - NAPI_ASSERT_BASE(env, self != nullptr, "self is nullptr", napi_invalid_arg); - napi_valuetype valueType = napi_undefined; - napi_typeof(env, argv[0], &valueType); - NAPI_ASSERT_BASE(env, valueType == napi_function, "callback is not function", napi_invalid_arg); - - SingleKVStore *proxy = nullptr; - NAPI_CALL_BASE(env, napi_unwrap(env, self, reinterpret_cast(&proxy)), napi_invalid_arg); - NAPI_ASSERT_BASE(env, proxy != nullptr, "there is no native kv store", napi_invalid_arg); - std::shared_ptr observer = std::make_shared(env, argv[0]); - Status status = proxy->kvStore_->RegisterSyncCallback(observer); - if (status != Status::SUCCESS) { - return napi_generic_failure; - } - proxy->syncObserver_ = observer; - return napi_ok; -} - -SingleKVStore &SingleKVStore::operator=(std::shared_ptr &&singleKvStore) -{ - if (kvStore_ == singleKvStore) { - return *this; - } - kvStore_ = std::move(singleKvStore); - return *this; -} - -bool SingleKVStore::operator==(const std::shared_ptr &singleKvStore) -{ - return kvStore_ == singleKvStore; -} - -DataObserver::DataObserver(napi_env env, napi_value callback) - : env_(env) -{ - napi_create_reference(env, callback, 1, &callback_); - napi_get_uv_event_loop(env, &loop_); -} - -DataObserver::~DataObserver() -{ - napi_delete_reference(env_, callback_); -} - -void DataObserver::OnChange(const ChangeNotification ¬ification, std::shared_ptr snapshot) -{ - ZLOGD("data change insert:%{public}zu, update:%{public}zu, delete:%{public}zu", - notification.GetInsertEntries().size(), notification.GetUpdateEntries().size(), - notification.GetDeleteEntries().size()); -} - -void DataObserver::OnChange(const ChangeNotification ¬ification) -{ - ZLOGD("data change insert:%{public}zu, update:%{public}zu, delete:%{public}zu", - notification.GetInsertEntries().size(), notification.GetUpdateEntries().size(), - notification.GetDeleteEntries().size()); - KvStoreObserver::OnChange(notification); - EventDataWorker *eventDataWorker = new EventDataWorker(this, notification); - 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 jsNotification = JSUtil::Convert2JSNotification(eventDataInner->observer->env_, - eventDataInner->data); - napi_value callback = nullptr; - napi_value args[1] = {jsNotification}; - napi_get_reference_value(eventDataInner->observer->env_, eventDataInner->observer->callback_, &callback); - napi_value global = nullptr; - napi_get_global(eventDataInner->observer->env_, &global); - napi_value result; - napi_status callStatus = napi_call_function(eventDataInner->observer->env_, global, callback, - 1, args, &result); - if (callStatus != napi_ok) { - ZLOGE("notify data change failed callStatus:%{public}d callback:%{public}p", callStatus, callback); - } - delete eventDataInner; - eventDataInner = nullptr; - delete work; - work = nullptr; - }); -} - -SyncObserver::SyncObserver(napi_env env, napi_value callback) - : env_(env) -{ - napi_create_reference(env, callback, 1, &callback_); - napi_get_uv_event_loop(env, &loop_); -} - -SyncObserver::~SyncObserver() -{ - napi_delete_reference(env_, callback_); -} - -void SyncObserver::SyncCompleted(const std::map &results) -{ - EventDataWorker *eventDataWorker = new EventDataWorker(); - eventDataWorker->observer = this; - eventDataWorker->data = results; - 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); - std::map dataMap; - for (const auto &[key, value] : eventDataInner->data) { - dataMap.emplace(key, int32_t(value)); - } - napi_value notification = JSUtil::Convert2JSTupleArray(eventDataInner->observer->env_, dataMap); - napi_value callback = nullptr; - napi_value args[1] = {notification}; - napi_get_reference_value(eventDataInner->observer->env_, eventDataInner->observer->callback_, &callback); - napi_value global = nullptr; - napi_value result = nullptr; - napi_get_global(eventDataInner->observer->env_, &global); - napi_call_function(eventDataInner->observer->env_, global, callback, 1, args, &result); - delete eventDataInner; - eventDataInner = nullptr; - delete work; - work = nullptr; - }); -} -} diff --git a/frameworks/jskitsimpl/distributeddata/src/uv_queue.cpp b/frameworks/jskitsimpl/distributeddata/src/uv_queue.cpp new file mode 100644 index 0000000000000000000000000000000000000000..198d336c649cdc9593f5defbc7265ea403d5a4e1 --- /dev/null +++ b/frameworks/jskitsimpl/distributeddata/src/uv_queue.cpp @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2021 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 "UvQueue" +#include "uv_queue.h" +#include "log_print.h" +#include "napi_queue.h" + +namespace OHOS::DistributedData { +UvQueue::UvQueue(napi_env env, napi_value callback) + : env_(env) +{ + napi_create_reference(env, callback, 1, &callback_); + napi_get_uv_event_loop(env, &loop_); +} + +UvQueue::~UvQueue() +{ + ZLOGD("no memory leak for queue-callback"); + napi_delete_reference(env_, callback_); +} + +bool UvQueue::operator==(napi_value value) +{ + napi_value callback = nullptr; + napi_get_reference_value(env_, callback_, &callback); + + bool isEquals = false; + napi_strict_equals(env_, value, callback, &isEquals); + return isEquals; +} + +void UvQueue::CallFunction(NapiArgsGenerator genArgs) +{ + uv_work_t* work = new (std::nothrow) uv_work_t; + if (work == nullptr) { + ZLOGE("no memory for uv_work_t"); + return; + } + work->data = this; + this->args = std::move(genArgs); + + uv_queue_work( + loop_, work, [](uv_work_t* work) {}, + [](uv_work_t* work, int uvstatus) { + auto queue = static_cast(work->data); + int argc = 0; + napi_value argv[ARGC_MAX] = { nullptr }; + if (queue->args) { + queue->args(queue->env_, argc, argv); + } + ZLOGD("queue uv_after_work_cb"); + + napi_value callback = nullptr; + napi_get_reference_value(queue->env_, queue->callback_, &callback); + napi_value global = nullptr; + napi_get_global(queue->env_, &global); + napi_value result; + napi_status status = napi_call_function(queue->env_, global, callback, argc, argv, &result); + if (status != napi_ok) { + ZLOGE("notify data change failed status:%{public}d callback:%{public}p", status, callback); + } + delete work; + work = nullptr; + }); +} +} diff --git a/interfaces/innerkits/distributeddata/include/data_query.h b/interfaces/innerkits/distributeddata/include/data_query.h index b2282e56f1bef70e279e788f7756e8f36ecf7431..dc8a36f865e285ed57fc1316c843444fdc9208cb 100755 --- a/interfaces/innerkits/distributeddata/include/data_query.h +++ b/interfaces/innerkits/distributeddata/include/data_query.h @@ -385,6 +385,13 @@ public: // This Query. KVSTORE_API DataQuery& KeyPrefix(const std::string &prefix); + // Select results with specified device Identifier. + // Parameters: + // deviceId: device Identifier. + // Return: + // This Query. + KVSTORE_API DataQuery& DeviceId(const std::string &deviceId); + // Select results with suggested index. // Parameters: // index: suggested index. diff --git a/interfaces/jskits/distributeddata/BUILD.gn b/interfaces/jskits/distributeddata/BUILD.gn index 109fcc69fc3bed23331012d336b380c5b1c2eb27..3d02530884650af2b16965c2bfe6a516d7e1606f 100644 --- a/interfaces/jskits/distributeddata/BUILD.gn +++ b/interfaces/jskits/distributeddata/BUILD.gn @@ -34,8 +34,9 @@ ohos_copy("distributeddatamgr_declaration") { ohos_shared_library("distributeddata") { include_dirs = [ - "//third_party/node/src", + "//third_party/json/single_include", "//third_party/libuv/include", + "//third_party/node/src", "//utils/native/base/include", "//foundation/distributeddatamgr/distributeddatamgr/interfaces/innerkits/distributeddata/include", "//foundation/distributeddatamgr/distributeddatamgr/frameworks/jskitsimpl/distributeddata/include", @@ -44,15 +45,22 @@ ohos_shared_library("distributeddata") { ] sources = [ - "../../../frameworks/jskitsimpl/distributeddata/src/async_call.cpp", "../../../frameworks/jskitsimpl/distributeddata/src/entry_point.cpp", + "../../../frameworks/jskitsimpl/distributeddata/src/js_device_kv_store.cpp", + "../../../frameworks/jskitsimpl/distributeddata/src/js_field_node.cpp", + "../../../frameworks/jskitsimpl/distributeddata/src/js_kv_manager.cpp", + "../../../frameworks/jskitsimpl/distributeddata/src/js_kv_store.cpp", + "../../../frameworks/jskitsimpl/distributeddata/src/js_kv_store_resultset.cpp", + "../../../frameworks/jskitsimpl/distributeddata/src/js_query.cpp", + "../../../frameworks/jskitsimpl/distributeddata/src/js_schema.cpp", + "../../../frameworks/jskitsimpl/distributeddata/src/js_single_kv_store.cpp", "../../../frameworks/jskitsimpl/distributeddata/src/js_util.cpp", - "../../../frameworks/jskitsimpl/distributeddata/src/kv_manager.cpp", - "../../../frameworks/jskitsimpl/distributeddata/src/single_kv_store.cpp", + "../../../frameworks/jskitsimpl/distributeddata/src/napi_queue.cpp", + "../../../frameworks/jskitsimpl/distributeddata/src/uv_queue.cpp", ] deps = [ - ":distributed_data_js", + #":distributed_data_js", "//foundation/ace/napi:ace_napi", "//foundation/distributeddatamgr/distributeddatamgr/interfaces/innerkits/distributeddata:distributeddata_inner", "//third_party/libuv:uv_static", diff --git a/interfaces/jskits/distributeddata/distributed_data.js b/interfaces/jskits/distributeddata/distributed_data.js index b7868e0ff8f2b6f27de4c50a073711b69c81977b..cb3fcaeccbf94b23e6548556d7e2c72bb421d575 100644 --- a/interfaces/jskits/distributeddata/distributed_data.js +++ b/interfaces/jskits/distributeddata/distributed_data.js @@ -2,6 +2,9 @@ const distributedDataSo = requireInternal('data.distributedData'); export default { createKVManager: distributedDataSo.createKVManager, + Query: distributedDataSo.Query, + FieldNode: distributedDataSo.FieldNode, + Schema: distributedDataSo.Schema, UserType: { SAME_USER_ID: 0, }, diff --git a/services/distributeddataservice/app/BUILD.gn b/services/distributeddataservice/app/BUILD.gn index 67753c29872b527202ed1b6875975568bc56c8a7..d4ec3d01bc6ef4b2d504cf1433f58d3eaf4d2206 100755 --- a/services/distributeddataservice/app/BUILD.gn +++ b/services/distributeddataservice/app/BUILD.gn @@ -115,7 +115,7 @@ ohos_shared_library("distributeddataservice") { "appexecfwk_standard:appexecfwk_core", "battery_manager_native:batterysrv_client", "hiviewdfx_hilog_native:libhilog", - "huks_standard:libhukssdk", + "huks:libhukssdk", "ipc:ipc_core", "permission_standard:libpermissionsdk_standard", "power_manager_native:powermgr_client", diff --git a/services/distributeddataservice/app/src/single_kvstore_impl.cpp b/services/distributeddataservice/app/src/single_kvstore_impl.cpp index 95937c70e0c1a51848ec6b4f457433677dc6a53e..c9ba96be8593aac1875e61c971aff04d56324997 100755 --- a/services/distributeddataservice/app/src/single_kvstore_impl.cpp +++ b/services/distributeddataservice/app/src/single_kvstore_impl.cpp @@ -1515,11 +1515,11 @@ Status SingleKvStoreImpl::Control(KvControlCmd cmd, const KvParam &inputParam, s output = nullptr; switch (cmd) { case KvControlCmd::SET_SYNC_PARAM: { - if (inputParam.Size() != sizeof(KvSyncParam)) { + if (inputParam.Size() != sizeof(uint32_t)) { return Status::IPC_ERROR; } - KvSyncParam syncParam = TransferByteArrayToType(inputParam.Data()); - uint32_t allowedDelayMs = syncParam.allowedDelayMs; + uint32_t allowedDelayMs = TransferByteArrayToType(inputParam.Data()); + ZLOGE("SET_SYNC_PARAM in %{public}d ms", allowedDelayMs); if (allowedDelayMs > 0 && allowedDelayMs < KvStoreSyncManager::SYNC_MIN_DELAY_MS) { return Status::INVALID_ARGUMENT; } @@ -1527,11 +1527,12 @@ Status SingleKvStoreImpl::Control(KvControlCmd cmd, const KvParam &inputParam, s return Status::INVALID_ARGUMENT; } defaultSyncDelayMs_ = allowedDelayMs; + ZLOGE("SET_SYNC_PARAM save %{public}d ms", defaultSyncDelayMs_); return Status::SUCCESS; } case KvControlCmd::GET_SYNC_PARAM: { - KvSyncParam syncParam{defaultSyncDelayMs_}; - output = new KvParam(TransferTypeToByteArray(syncParam)); + output = new KvParam(TransferTypeToByteArray(defaultSyncDelayMs_)); + ZLOGE("GET_SYNC_PARAM read %{public}d ms", defaultSyncDelayMs_); return Status::SUCCESS; } default: { diff --git a/services/distributeddataservice/app/test/BUILD.gn b/services/distributeddataservice/app/test/BUILD.gn index 3c36cc90d3a4fd713fedaa585b41be9fb1767729..e85add8d52b408f448a9ed7878c2b5ce0951064d 100755 --- a/services/distributeddataservice/app/test/BUILD.gn +++ b/services/distributeddataservice/app/test/BUILD.gn @@ -67,7 +67,7 @@ ohos_unittest("KvStoreImplLogicalIsolationTest") { external_deps = [ "battery_manager_native:batterysrv_client", "hiviewdfx_hilog_native:libhilog", - "huks_standard:libhukssdk", + "huks:libhukssdk", "ipc:ipc_core", "permission_standard:libpermissionsdk_standard", "power_manager_native:powermgr_client", @@ -120,7 +120,7 @@ ohos_unittest("KvStoreImplPhysicalIsolationTest") { external_deps = [ "battery_manager_native:batterysrv_client", "hiviewdfx_hilog_native:libhilog", - "huks_standard:libhukssdk", + "huks:libhukssdk", "ipc:ipc_core", "permission_standard:libpermissionsdk_standard", "power_manager_native:powermgr_client", @@ -173,7 +173,7 @@ ohos_unittest("KvStoreDataServiceTest") { external_deps = [ "battery_manager_native:batterysrv_client", "hiviewdfx_hilog_native:libhilog", - "huks_standard:libhukssdk", + "huks:libhukssdk", "ipc:ipc_core", "permission_standard:libpermissionsdk_standard", "power_manager_native:powermgr_client", @@ -226,7 +226,7 @@ ohos_unittest("KvStoreBackupTest") { external_deps = [ "battery_manager_native:batterysrv_client", "hiviewdfx_hilog_native:libhilog", - "huks_standard:libhukssdk", + "huks:libhukssdk", "ipc:ipc_core", "permission_standard:libpermissionsdk_standard", "power_manager_native:powermgr_client", @@ -261,7 +261,7 @@ ohos_unittest("KvStoreFlowCtrlManagerTest") { external_deps = [ "battery_manager_native:batterysrv_client", "hiviewdfx_hilog_native:libhilog", - "huks_standard:libhukssdk", + "huks:libhukssdk", "ipc:ipc_core", "permission_standard:libpermissionsdk_standard", "power_manager_native:powermgr_client", @@ -307,7 +307,7 @@ ohos_unittest("KvStoreSyncManagerTest") { external_deps = [ "battery_manager_native:batterysrv_client", "hiviewdfx_hilog_native:libhilog", - "huks_standard:libhukssdk", + "huks:libhukssdk", "ipc:ipc_core", "permission_standard:libpermissionsdk_standard", "power_manager_native:powermgr_client", @@ -376,7 +376,7 @@ ohos_unittest("KvStoreUninstallerTest") { "aafwk_standard:intent", "battery_manager_native:batterysrv_client", "hiviewdfx_hilog_native:libhilog", - "huks_standard:libhukssdk", + "huks:libhukssdk", "ipc:ipc_core", "permission_standard:libpermissionsdk_standard", "power_manager_native:powermgr_client", diff --git a/services/distributeddataservice/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_space_management_test.cpp b/services/distributeddataservice/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_space_management_test.cpp index 89b76de93c2d6a8ee539ee09550003beb6a51c6f..c2de7b7ee6b386a83ae77258f8ff1745115698a4 100755 --- a/services/distributeddataservice/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_space_management_test.cpp +++ b/services/distributeddataservice/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_space_management_test.cpp @@ -13,8 +13,10 @@ * limitations under the License. */ -#include #include +#include +#include +#include #include "db_constant.h" #include "db_common.h" @@ -136,17 +138,18 @@ void DistributedDBInterfacesSpaceManagementTest::TearDown(void) {} // use another way calculate small file size(2G) static uint64_t CheckRealFileSize(const vector &fileNames) { - int size = 0; + uint64_t size = 0; for (const auto &file : fileNames) { FILE *fileHandle = nullptr; fileHandle = fopen(file.c_str(), "rb"); if (fileHandle == nullptr) { - LOGE("Open file[%s] fail", file.c_str()); + LOGE("Open file[%s] fail[%d]", file.c_str(), errno); continue; } (void)fseek(fileHandle, 0, SEEK_END); - size += ftell(fileHandle); - LOGD("CheckRealFileSize:FileName[%s],size[%lld]", file.c_str(), ftell(fileHandle)); + long fileSize = ftell(fileHandle); + LOGD("CheckRealFileSize:FileName[%s],size[%ld]", file.c_str(), fileSize); + size += static_cast(fileSize); // file is less than 16M. (void)fclose(fileHandle); } return size; @@ -217,7 +220,7 @@ HWTEST_F(DistributedDBInterfacesSpaceManagementTest, GetKvStoreDiskSize001, Test * @tc.require: AR000CQDTD * @tc.author: sunpeng */ -HWTEST_F(DistributedDBInterfacesSpaceManagementTest, GetKvStoreDiskSize002, TestSize.Level1) +HWTEST_F(DistributedDBInterfacesSpaceManagementTest, GetKvStoreDiskSize002, TestSize.Level2) { g_storeId = "distributed_GetKvStoreDiskSize_002"; GetRealFileUrl(); @@ -261,6 +264,7 @@ HWTEST_F(DistributedDBInterfacesSpaceManagementTest, GetKvStoreDiskSize002, Test * @tc.steps: step5/6. Get Db size by GetKvStoreDiskSize. * @tc.expected: step5/6. Return right size and ok. */ + std::this_thread::sleep_for(std::chrono::milliseconds(100)); // for vaccum singleAndMultiDbSize = 0; EXPECT_EQ(g_mgr.GetKvStoreDiskSize(g_storeId, singleAndMultiDbSize), OK); ASSERT_TRUE(dbSizeForCheck != singleAndMultiDbSize);