1 /*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #define LOG_TAG "JS_SingleKVStore"
16 #include "js_single_kv_store.h"
17 #include "js_util.h"
18 #include "js_kv_store_resultset.h"
19 #include "datashare_predicates.h"
20 #include "js_query.h"
21 #include "log_print.h"
22 #include "napi_queue.h"
23 #include "uv_queue.h"
24 #include "kv_utils.h"
25
26 using namespace OHOS::DistributedKv;
27 using namespace OHOS::DataShare;
28 namespace OHOS::DistributedKVStore {
29
30 std::map<std::string, JsSingleKVStore::Exec> JsSingleKVStore::onEventHandlers_ = {
31 { "dataChange", JsSingleKVStore::OnDataChange },
32 { "syncComplete", JsSingleKVStore::OnSyncComplete }
33 };
34
35 std::map<std::string, JsSingleKVStore::Exec> JsSingleKVStore::offEventHandlers_ = {
36 { "dataChange", JsSingleKVStore::OffDataChange },
37 { "syncComplete", JsSingleKVStore::OffSyncComplete }
38 };
39
40 std::map<napi_valuetype, std::string> JsSingleKVStore::valueTypeToString_ = {
41 { napi_string, std::string("string") },
42 { napi_number, std::string("integer") },
43 { napi_object, std::string("bytearray") },
44 { napi_boolean, std::string("bollean") },
45 };
46
ValidSubscribeType(uint8_t type)47 static bool ValidSubscribeType(uint8_t type)
48 {
49 return (SUBSCRIBE_LOCAL <= type) && (type <= SUBSCRIBE_LOCAL_REMOTE);
50 }
51
ToSubscribeType(uint8_t type)52 static SubscribeType ToSubscribeType(uint8_t type)
53 {
54 return static_cast<SubscribeType>(type + 1);
55 }
56
JsSingleKVStore(const std::string & storeId)57 JsSingleKVStore::JsSingleKVStore(const std::string& storeId)
58 : storeId_(storeId)
59 {
60 }
61
SetKvStorePtr(std::shared_ptr<SingleKvStore> kvStore)62 void JsSingleKVStore::SetKvStorePtr(std::shared_ptr<SingleKvStore> kvStore)
63 {
64 kvStore_ = kvStore;
65 }
66
GetKvStorePtr()67 std::shared_ptr<SingleKvStore> JsSingleKVStore::GetKvStorePtr()
68 {
69 return kvStore_;
70 }
71
SetContextParam(std::shared_ptr<ContextParam> param)72 void JsSingleKVStore::SetContextParam(std::shared_ptr<ContextParam> param)
73 {
74 param_ = param;
75 }
76
SetUvQueue(std::shared_ptr<UvQueue> uvQueue)77 void JsSingleKVStore::SetUvQueue(std::shared_ptr<UvQueue> uvQueue)
78 {
79 uvQueue_ = uvQueue;
80 }
81
IsSchemaStore() const82 bool JsSingleKVStore::IsSchemaStore() const
83 {
84 return isSchemaStore_;
85 }
86
SetSchemaInfo(bool isSchemaStore)87 void JsSingleKVStore::SetSchemaInfo(bool isSchemaStore)
88 {
89 isSchemaStore_ = isSchemaStore;
90 }
91
~JsSingleKVStore()92 JsSingleKVStore::~JsSingleKVStore()
93 {
94 ZLOGD("no memory leak for JsSingleKVStore");
95 if (kvStore_ == nullptr) {
96 return;
97 }
98
99 std::lock_guard<std::mutex> lck(listMutex_);
100 for (uint8_t type = SUBSCRIBE_LOCAL; type < SUBSCRIBE_COUNT; type++) {
101 for (auto& observer : dataObserver_[type]) {
102 auto subscribeType = ToSubscribeType(type);
103 kvStore_->UnSubscribeKvStore(subscribeType, observer);
104 observer->Clear();
105 }
106 dataObserver_[type].clear();
107 }
108
109 kvStore_->UnRegisterSyncCallback();
110 for (auto &syncObserver : syncObservers_) {
111 syncObserver->Clear();
112 }
113 syncObservers_.clear();
114 }
115
Constructor(napi_env env)116 napi_value JsSingleKVStore::Constructor(napi_env env)
117 {
118 const napi_property_descriptor properties[] = {
119 DECLARE_NAPI_FUNCTION("put", JsSingleKVStore::Put),
120 DECLARE_NAPI_FUNCTION("delete", JsSingleKVStore::Delete),
121 DECLARE_NAPI_FUNCTION("putBatch", JsSingleKVStore::PutBatch),
122 DECLARE_NAPI_FUNCTION("deleteBatch", JsSingleKVStore::DeleteBatch),
123 DECLARE_NAPI_FUNCTION("startTransaction", JsSingleKVStore::StartTransaction),
124 DECLARE_NAPI_FUNCTION("commit", JsSingleKVStore::Commit),
125 DECLARE_NAPI_FUNCTION("rollback", JsSingleKVStore::Rollback),
126 DECLARE_NAPI_FUNCTION("enableSync", JsSingleKVStore::EnableSync),
127 DECLARE_NAPI_FUNCTION("setSyncRange", JsSingleKVStore::SetSyncRange),
128 DECLARE_NAPI_FUNCTION("backup", JsSingleKVStore::Backup),
129 DECLARE_NAPI_FUNCTION("restore", JsSingleKVStore::Restore),
130 DECLARE_NAPI_FUNCTION("deleteBackup", JsSingleKVStore::DeleteBackup),
131
132 DECLARE_NAPI_FUNCTION("get", JsSingleKVStore::Get),
133 DECLARE_NAPI_FUNCTION("getEntries", JsSingleKVStore::GetEntries),
134 DECLARE_NAPI_FUNCTION("getResultSet", JsSingleKVStore::GetResultSet),
135 DECLARE_NAPI_FUNCTION("closeResultSet", JsSingleKVStore::CloseResultSet),
136 DECLARE_NAPI_FUNCTION("getResultSize", JsSingleKVStore::GetResultSize),
137 DECLARE_NAPI_FUNCTION("removeDeviceData", JsSingleKVStore::RemoveDeviceData),
138 DECLARE_NAPI_FUNCTION("sync", JsSingleKVStore::Sync),
139 DECLARE_NAPI_FUNCTION("setSyncParam", JsSingleKVStore::SetSyncParam),
140 DECLARE_NAPI_FUNCTION("getSecurityLevel", JsSingleKVStore::GetSecurityLevel),
141 DECLARE_NAPI_FUNCTION("on", JsSingleKVStore::OnEvent), /* same to JsDeviceKVStore */
142 DECLARE_NAPI_FUNCTION("off", JsSingleKVStore::OffEvent) /* same to JsDeviceKVStore */
143 };
144 size_t count = sizeof(properties) / sizeof(properties[0]);
145 return JSUtil::DefineClass(env, "SingleKVStore", properties, count, JsSingleKVStore::New);
146 }
147
148 /*
149 * [JS API Prototype]
150 * [AsyncCallback]
151 * put(key:string, value:Uint8Array | string | boolean | number, callback: AsyncCallback<void>):void;
152 * [Promise]
153 * put(key:string, value:Uint8Array | string | boolean | number):Promise<void>;
154 */
Put(napi_env env,napi_callback_info info)155 napi_value JsSingleKVStore::Put(napi_env env, napi_callback_info info)
156 {
157 struct PutContext : public ContextBase {
158 std::string key;
159 JSUtil::KvStoreVariant value;
160 };
161 auto ctxt = std::make_shared<PutContext>();
162 ctxt->GetCbInfo(env, info, [env, ctxt](size_t argc, napi_value* argv) {
163 // required 2 arguments :: <key> <value>
164 ASSERT_BUSINESS_ERR(ctxt, argc >= 2, Status::INVALID_ARGUMENT, "The number of parameters is incorrect.");
165 ctxt->status = JSUtil::GetValue(env, argv[0], ctxt->key);
166 ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::INVALID_ARGUMENT, "The type of key must be string.");
167 ctxt->status = JSUtil::GetValue(env, argv[1], ctxt->value);
168 if (ctxt->status != napi_ok) {
169 ctxt->isThrowError = true;
170 napi_valuetype ntype = napi_undefined;
171 napi_typeof(env, argv[0], &ntype);
172 auto type = valueTypeToString_.find(ntype);
173 ThrowNapiError(env, Status::INVALID_ARGUMENT, "The type of value must be " + type->second);
174 return;
175 }
176 });
177 ASSERT_NULL(!ctxt->isThrowError, "Put exit");
178
179 auto execute = [ctxt]() {
180 DistributedKv::Key key(ctxt->key);
181 bool isSchemaStore = reinterpret_cast<JsSingleKVStore *>(ctxt->native)->IsSchemaStore();
182 auto &kvStore = reinterpret_cast<JsSingleKVStore *>(ctxt->native)->kvStore_;
183 DistributedKv::Value value = isSchemaStore ? DistributedKv::Blob(std::get<std::string>(ctxt->value))
184 : JSUtil::VariantValue2Blob(ctxt->value);
185 Status status = kvStore->Put(key, value);
186 ZLOGD("kvStore->Put return %{public}d", status);
187 ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ?
188 napi_ok : napi_generic_failure;
189 };
190 return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute);
191 }
192
193 /*
194 * [JS API Prototype]
195 * [AsyncCallback]
196 * delete(key: string, callback: AsyncCallback<void>): void;
197 * [Promise]
198 * delete(key: string): Promise<void>;
199 */
Delete(napi_env env,napi_callback_info info)200 napi_value JsSingleKVStore::Delete(napi_env env, napi_callback_info info)
201 {
202 struct DeleteContext : public ContextBase {
203 std::string key;
204 std::vector<DistributedKv::Blob> keys;
205 napi_valuetype type;
206 };
207 auto ctxt = std::make_shared<DeleteContext>();
208 ctxt->GetCbInfo(env, info, [env, ctxt](size_t argc, napi_value* argv) {
209 // required 1 arguments :: <key> || <predicates>
210 ASSERT_BUSINESS_ERR(ctxt, argc == 1, Status::INVALID_ARGUMENT, "The number of parameter is incorrect.");
211 ctxt->type = napi_undefined;
212 ctxt->status = napi_typeof(env, argv[0], &(ctxt->type));
213 if (ctxt->type == napi_string) {
214 ctxt->status = JSUtil::GetValue(env, argv[0], ctxt->key);
215 ZLOGD("kvStore->Delete %{public}.6s status:%{public}d", ctxt->key.c_str(), ctxt->status);
216 ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::INVALID_ARGUMENT,
217 "The type of key must be string.");
218 } else if (ctxt->type == napi_object) {
219 ctxt->status = JSUtil::GetValue(env, argv[0], ctxt->keys);
220 ZLOGD("kvStore->Delete status:%{public}d", ctxt->status);
221 ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::INVALID_ARGUMENT,
222 "The parameters predicates is incorrect.");
223 }
224 });
225 ASSERT_NULL(!ctxt->isThrowError, "Delete exit");
226
227 return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), [ctxt]() {
228 Status status = Status::INVALID_ARGUMENT;
229 if (ctxt->type == napi_string) {
230 OHOS::DistributedKv::Key key(ctxt->key);
231 auto& kvStore = reinterpret_cast<JsSingleKVStore*>(ctxt->native)->kvStore_;
232 status = kvStore->Delete(key);
233 ZLOGD("kvStore->Delete %{public}.6s status:%{public}d", ctxt->key.c_str(), status);
234 } else if (ctxt->type == napi_object) {
235 auto& kvStore = reinterpret_cast<JsSingleKVStore*>(ctxt->native)->kvStore_;
236 status = kvStore->DeleteBatch(ctxt->keys);
237 ZLOGD("kvStore->DeleteBatch status:%{public}d", status);
238 }
239 ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ?
240 napi_ok : napi_generic_failure;
241 });
242 }
243
244 /*
245 * [JS API Prototype]
246 * [Callback]
247 * on(event:'syncComplete',syncCallback: Callback<Array<[string, number]>>):void;
248 * on(event:'dataChange', subType: SubscribeType, observer: Callback<ChangeNotification>): void;
249 */
OnEvent(napi_env env,napi_callback_info info)250 napi_value JsSingleKVStore::OnEvent(napi_env env, napi_callback_info info)
251 {
252 auto ctxt = std::make_shared<ContextBase>();
253 auto input = [env, ctxt](size_t argc, napi_value* argv) {
254 // required 2 arguments :: <event> [...] <callback>
255 ASSERT_BUSINESS_ERR(ctxt, argc >= 2, Status::INVALID_ARGUMENT, "The number of parameters is incorrect.");
256 std::string event;
257 ctxt->status = JSUtil::GetValue(env, argv[0], event);
258 ZLOGI("subscribe to event:%{public}s", event.c_str());
259 auto handle = onEventHandlers_.find(event);
260 ASSERT_BUSINESS_ERR(ctxt, handle != onEventHandlers_.end(), Status::INVALID_ARGUMENT,
261 "The type of parameters event is incorrect.");
262 // shift 1 argument, for JsSingleKVStore::Exec.
263 handle->second(env, argc - 1, &argv[1], ctxt);
264 };
265 ctxt->GetCbInfoSync(env, info, input);
266 ASSERT_NULL(!ctxt->isThrowError, "OnEvent exit");
267 if (ctxt->status != napi_ok) {
268 ThrowNapiError(env, Status::INVALID_ARGUMENT, "");
269 }
270 return nullptr;
271 }
272
273 /*
274 * [JS API Prototype]
275 * [Callback]
276 * off(event:'syncComplete',syncCallback: Callback<Array<[string, number]>>):void;
277 * off(event:'dataChange', subType: SubscribeType, observer: Callback<ChangeNotification>): void;
278 */
OffEvent(napi_env env,napi_callback_info info)279 napi_value JsSingleKVStore::OffEvent(napi_env env, napi_callback_info info)
280 {
281 auto ctxt = std::make_shared<ContextBase>();
282 auto input = [env, ctxt](size_t argc, napi_value* argv) {
283 // required 1 arguments :: <event> [callback]
284 ASSERT_BUSINESS_ERR(ctxt, argc != 0, Status::INVALID_ARGUMENT, "The number of parameters is incorrect.");
285 std::string event;
286 ctxt->status = JSUtil::GetValue(env, argv[0], event);
287 ZLOGI("unsubscribe to event:%{public}s", event.c_str());
288 auto handle = offEventHandlers_.find(event);
289 ASSERT_BUSINESS_ERR(ctxt, handle != offEventHandlers_.end(), Status::INVALID_ARGUMENT,
290 "The type of parameters event is incorrect.");
291 // shift 1 argument, for JsSingleKVStore::Exec.
292 handle->second(env, argc - 1, &argv[1], ctxt);
293 };
294 ctxt->GetCbInfoSync(env, info, input);
295 ASSERT_NULL(!ctxt->isThrowError, "OffEvent exit");
296 if (ctxt->status != napi_ok) {
297 ThrowNapiError(env, Status::INVALID_ARGUMENT, "");
298 }
299 return nullptr;
300 }
301
302 /*
303 * [JS API Prototype]
304 * [AsyncCallback]
305 * putBatch(entries: Entry[], callback: AsyncCallback<void>):void;
306 * [Promise]
307 * putBatch(entries: Entry[]):Promise<void>;
308 */
PutBatch(napi_env env,napi_callback_info info)309 napi_value JsSingleKVStore::PutBatch(napi_env env, napi_callback_info info)
310 {
311 struct PutBatchContext : public ContextBase {
312 std::vector<Entry> entries;
313 };
314 auto ctxt = std::make_shared<PutBatchContext>();
315 ctxt->GetCbInfo(env, info, [env, ctxt](size_t argc, napi_value* argv) {
316 // required 1 arguments :: <entries>
317 ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::INVALID_ARGUMENT, "The number of parameters is incorrect.");
318 auto isSchemaStore = reinterpret_cast<JsSingleKVStore*>(ctxt->native)->IsSchemaStore();
319 ctxt->status = JSUtil::GetValue(env, argv[0], ctxt->entries, isSchemaStore);
320 ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::INVALID_ARGUMENT,
321 "The type of entries is incorrect.");
322 });
323 ASSERT_NULL(!ctxt->isThrowError, "PutBatch exit");
324
325 auto execute = [ctxt]() {
326 auto& kvStore = reinterpret_cast<JsSingleKVStore*>(ctxt->native)->kvStore_;
327 Status status = kvStore->PutBatch(ctxt->entries);
328 ZLOGD("kvStore->DeleteBatch return %{public}d", status);
329 ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ?
330 napi_ok : napi_generic_failure;
331 };
332 return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute);
333 }
334
335 /*
336 * [JS API Prototype]
337 * [AsyncCallback]
338 * deleteBatch(keys: string[], callback: AsyncCallback<void>):void;
339 * [Promise]
340 * deleteBatch(keys: string[]):Promise<void>;
341 */
DeleteBatch(napi_env env,napi_callback_info info)342 napi_value JsSingleKVStore::DeleteBatch(napi_env env, napi_callback_info info)
343 {
344 struct DeleteBatchContext : public ContextBase {
345 std::vector<std::string> keys;
346 };
347 auto ctxt = std::make_shared<DeleteBatchContext>();
348 auto input = [env, ctxt](size_t argc, napi_value* argv) {
349 // required 1 arguments :: <keys>
350 ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::INVALID_ARGUMENT, "The number of parameters is incorrect.");
351 ctxt->status = JSUtil::GetValue(env, argv[0], ctxt->keys);
352 ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::INVALID_ARGUMENT, "The type of keys is incorrect.");
353 };
354 ctxt->GetCbInfo(env, info, input);
355 ASSERT_NULL(!ctxt->isThrowError, "DeleteBatch exit");
356
357 auto execute = [ctxt]() {
358 std::vector<DistributedKv::Key> keys;
359 for (auto it : ctxt->keys) {
360 DistributedKv::Key key(it);
361 keys.push_back(key);
362 }
363 auto& kvStore = reinterpret_cast<JsSingleKVStore*>(ctxt->native)->kvStore_;
364 Status status = kvStore->DeleteBatch(keys);
365 ZLOGD("kvStore->DeleteBatch return %{public}d", status);
366 ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ?
367 napi_ok : napi_generic_failure;
368 };
369 return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute);
370 }
371
372 /*
373 * [JS API Prototype]
374 * [AsyncCallback]
375 * startTransaction(callback: AsyncCallback<void>):void;
376 * [Promise]
377 * startTransaction() : Promise<void>;
378 */
StartTransaction(napi_env env,napi_callback_info info)379 napi_value JsSingleKVStore::StartTransaction(napi_env env, napi_callback_info info)
380 {
381 auto ctxt = std::make_shared<ContextBase>();
382 ctxt->GetCbInfo(env, info);
383
384 auto execute = [ctxt]() {
385 auto& kvStore = reinterpret_cast<JsSingleKVStore*>(ctxt->native)->kvStore_;
386 Status status = kvStore->StartTransaction();
387 ZLOGD("kvStore->StartTransaction return %{public}d", status);
388 ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ?
389 napi_ok : napi_generic_failure;
390 };
391 return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute);
392 }
393
394 /*
395 * [JS API Prototype]
396 * [AsyncCallback]
397 * commit(callback: AsyncCallback<void>):void;
398 * [Promise]
399 * commit() : Promise<void>;
400 */
Commit(napi_env env,napi_callback_info info)401 napi_value JsSingleKVStore::Commit(napi_env env, napi_callback_info info)
402 {
403 auto ctxt = std::make_shared<ContextBase>();
404 ctxt->GetCbInfo(env, info);
405
406 auto execute = [ctxt]() {
407 auto& kvStore = reinterpret_cast<JsSingleKVStore*>(ctxt->native)->kvStore_;
408 Status status = kvStore->Commit();
409 ZLOGD("kvStore->Commit return %{public}d", status);
410 ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ?
411 napi_ok : napi_generic_failure;
412 };
413 return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute);
414 }
415
416 /*
417 * [JS API Prototype]
418 * [AsyncCallback]
419 * rollback(callback: AsyncCallback<void>):void;
420 * [Promise]
421 * rollback() : Promise<void>;
422 */
Rollback(napi_env env,napi_callback_info info)423 napi_value JsSingleKVStore::Rollback(napi_env env, napi_callback_info info)
424 {
425 auto ctxt = std::make_shared<ContextBase>();
426 ctxt->GetCbInfo(env, info);
427
428 auto execute = [ctxt]() {
429 auto& kvStore = reinterpret_cast<JsSingleKVStore*>(ctxt->native)->kvStore_;
430 Status status = kvStore->Rollback();
431 ZLOGD("kvStore->Commit return %{public}d", status);
432 ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ?
433 napi_ok : napi_generic_failure;
434 };
435 return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute);
436 }
437
438 /*
439 * [JS API Prototype]
440 * [AsyncCallback]
441 * enableSync(enabled:boolean, callback: AsyncCallback<void>):void;
442 * [Promise]
443 * enableSync(enabled:boolean) : Promise<void>;
444 */
EnableSync(napi_env env,napi_callback_info info)445 napi_value JsSingleKVStore::EnableSync(napi_env env, napi_callback_info info)
446 {
447 struct EnableSyncContext : public ContextBase {
448 bool enable = false;
449 };
450 auto ctxt = std::make_shared<EnableSyncContext>();
451 auto input = [env, ctxt](size_t argc, napi_value* argv) {
452 // required 1 arguments :: <enable>
453 ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::INVALID_ARGUMENT, "The number of parameters is incorrect.");
454 ctxt->status = napi_get_value_bool(env, argv[0], &ctxt->enable);
455 ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::INVALID_ARGUMENT,
456 "The parameters of enable is incorrect.");
457 };
458 ctxt->GetCbInfo(env, info, input);
459 ASSERT_NULL(!ctxt->isThrowError, "EnableSync exit");
460
461 auto execute = [ctxt]() {
462 auto& kvStore = reinterpret_cast<JsSingleKVStore*>(ctxt->native)->kvStore_;
463 Status status = kvStore->SetCapabilityEnabled(ctxt->enable);
464 ZLOGD("kvStore->SetCapabilityEnabled return %{public}d", status);
465 ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ?
466 napi_ok : napi_generic_failure;
467 };
468 return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute);
469 }
470
471 /*
472 * [JS API Prototype]
473 * [AsyncCallback]
474 * setSyncRange(localLabels:string[], remoteSupportLabels:string[], callback: AsyncCallback<void>):void;
475 * [Promise]
476 * setSyncRange(localLabels:string[], remoteSupportLabels:string[]) : Promise<void>;
477 */
SetSyncRange(napi_env env,napi_callback_info info)478 napi_value JsSingleKVStore::SetSyncRange(napi_env env, napi_callback_info info)
479 {
480 struct SyncRangeContext : public ContextBase {
481 std::vector<std::string> localLabels;
482 std::vector<std::string> remoteSupportLabels;
483 };
484 auto ctxt = std::make_shared<SyncRangeContext>();
485 auto input = [env, ctxt](size_t argc, napi_value* argv) {
486 // required 2 arguments :: <localLabels> <remoteSupportLabels>
487 ASSERT_BUSINESS_ERR(ctxt, argc >= 2, Status::INVALID_ARGUMENT, "The number of parameters is incorrect.");
488 ctxt->status = JSUtil::GetValue(env, argv[0], ctxt->localLabels);
489 ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::INVALID_ARGUMENT,
490 "The type of parameter localLabels is string array.");
491 ctxt->status = JSUtil::GetValue(env, argv[1], ctxt->remoteSupportLabels);
492 ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::INVALID_ARGUMENT,
493 "The type of parameter remoteSupportLabels is string array.");
494 };
495 ctxt->GetCbInfo(env, info, input);
496 ASSERT_NULL(!ctxt->isThrowError, "SetSyncRange exit");
497
498 auto execute = [ctxt]() {
499 auto& kvStore = reinterpret_cast<JsSingleKVStore*>(ctxt->native)->kvStore_;
500 Status status = kvStore->SetCapabilityRange(ctxt->localLabels, ctxt->remoteSupportLabels);
501 ZLOGD("kvStore->SetCapabilityRange return %{public}d", status);
502 ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ?
503 napi_ok : napi_generic_failure;
504 };
505 return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute);
506 }
507
508 /*
509 * [JS API Prototype]
510 * [AsyncCallback]
511 * backup(file:string, callback: AsyncCallback<void>):void;
512 * [Promise]
513 * backup(file:string): Promise<void>;
514 */
Backup(napi_env env,napi_callback_info info)515 napi_value JsSingleKVStore::Backup(napi_env env, napi_callback_info info)
516 {
517 struct BackupContext : public ContextBase {
518 std::string file;
519 };
520 auto ctxt = std::make_shared<BackupContext>();
521 auto input = [env, ctxt](size_t argc, napi_value* argv) {
522 // required 1 arguments :: <file>
523 ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::INVALID_ARGUMENT, "The number of parameters is incorrect.");
524 ctxt->status = JSUtil::GetValue(env, argv[0], ctxt->file);
525 ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::INVALID_ARGUMENT,
526 "The type of parameter file is string.");
527 };
528 ctxt->GetCbInfo(env, info, input);
529 ASSERT_NULL(!ctxt->isThrowError, "Backup exit");
530
531 auto execute = [ctxt]() {
532 auto jsKvStore = reinterpret_cast<JsSingleKVStore*>(ctxt->native);
533 Status status = jsKvStore->kvStore_->Backup(ctxt->file, jsKvStore->param_->baseDir);
534 ZLOGD("kvStore->Backup return %{public}d", status);
535 ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ?
536 napi_ok : napi_generic_failure;
537 };
538 return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute);
539 }
540
541 /*
542 * [JS API Prototype]
543 * [AsyncCallback]
544 * restore(file:string, callback: AsyncCallback<void>):void;
545 * [Promise]
546 * restore(file:string): Promise<void>;
547 */
Restore(napi_env env,napi_callback_info info)548 napi_value JsSingleKVStore::Restore(napi_env env, napi_callback_info info)
549 {
550 struct RestoreContext : public ContextBase {
551 std::string file;
552 };
553 auto ctxt = std::make_shared<RestoreContext>();
554 auto input = [env, ctxt](size_t argc, napi_value* argv) {
555 // required 1 arguments :: <file>
556 ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::INVALID_ARGUMENT, "The number of parameters is incorrect.");
557 ctxt->status = JSUtil::GetValue(env, argv[0], ctxt->file);
558 ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::INVALID_ARGUMENT,
559 "The type of parameter file is string.");
560 };
561 ctxt->GetCbInfo(env, info, input);
562 ASSERT_NULL(!ctxt->isThrowError, "Restore exit");
563
564 auto execute = [ctxt]() {
565 auto jsKvStore = reinterpret_cast<JsSingleKVStore*>(ctxt->native);
566 Status status = jsKvStore->kvStore_->Restore(ctxt->file, jsKvStore->param_->baseDir);
567 ZLOGD("kvStore->Restore return %{public}d", status);
568 ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ?
569 napi_ok : napi_generic_failure;
570 };
571 return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute);
572 }
573
574 /*
575 * [JS API Prototype]
576 * [AsyncCallback]
577 * deleteBackup(files:Array<string>, callback: AsyncCallback<Array<[string, number]>>):void;
578 * [Promise]
579 * deleteBackup(files:Array<string>): Promise<Array<[string, number]>>;
580 */
DeleteBackup(napi_env env,napi_callback_info info)581 napi_value JsSingleKVStore::DeleteBackup(napi_env env, napi_callback_info info)
582 {
583 struct DeleteBackupContext : public ContextBase {
584 std::vector<std::string> files;
585 std::map<std::string, DistributedKv::Status> results;
586 };
587 auto ctxt = std::make_shared<DeleteBackupContext>();
588 auto input = [env, ctxt](size_t argc, napi_value* argv) {
589 // required 1 arguments :: <files>
590 ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::INVALID_ARGUMENT, "The number of parameters is incorrect.");
591 ctxt->status = JSUtil::GetValue(env, argv[0], ctxt->files);
592 ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::INVALID_ARGUMENT,
593 "The type of parameter file is string.");
594 };
595 ctxt->GetCbInfo(env, info, input);
596 ASSERT_NULL(!ctxt->isThrowError, "DeleteBackup exit");
597
598 auto execute = [ctxt]() {
599 auto jsKvStore = reinterpret_cast<JsSingleKVStore*>(ctxt->native);
600 Status status = jsKvStore->kvStore_->DeleteBackup(ctxt->files,
601 jsKvStore->param_->baseDir, ctxt->results);
602 ZLOGD("kvStore->DeleteBackup return %{public}d", status);
603 ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ?
604 napi_ok : napi_generic_failure;
605 };
606 auto output = [env, ctxt](napi_value& result) {
607 ctxt->status = JSUtil::SetValue(env, ctxt->results, result);
608 ASSERT_STATUS(ctxt, "output failed!");
609 };
610 return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute, output);
611 }
612
613 /*
614 * [JS API Prototype] JsSingleKVStore::OnDataChange is private non-static.
615 * [Callback]
616 * on(event:'dataChange', subType: SubscribeType, observer: Callback<ChangeNotification>): void;
617 */
OnDataChange(napi_env env,size_t argc,napi_value * argv,std::shared_ptr<ContextBase> ctxt)618 void JsSingleKVStore::OnDataChange(napi_env env, size_t argc, napi_value* argv, std::shared_ptr<ContextBase> ctxt)
619 {
620 // required 2 arguments :: <SubscribeType> <observer>
621 ASSERT_BUSINESS_ERR(ctxt, argc >= 2, Status::INVALID_ARGUMENT, "The number of parameters is incorrect.");
622
623 int32_t type = SUBSCRIBE_COUNT;
624 ctxt->status = napi_get_value_int32(env, argv[0], &type);
625 ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::INVALID_ARGUMENT, "");
626 ASSERT_BUSINESS_ERR(ctxt, ValidSubscribeType(type), Status::INVALID_ARGUMENT,
627 "The type of parameter event is incorrect.");
628
629 napi_valuetype valueType = napi_undefined;
630 ctxt->status = napi_typeof(env, argv[1], &valueType);
631 ASSERT_BUSINESS_ERR(ctxt, (ctxt->status == napi_ok) && (valueType == napi_function), Status::INVALID_ARGUMENT,
632 "The type of parameter Callback is incorrect.");
633
634 ZLOGI("subscribe data change type %{public}d", type);
635 auto proxy = reinterpret_cast<JsSingleKVStore*>(ctxt->native);
636 std::lock_guard<std::mutex> lck(proxy->listMutex_);
637 for (auto& it : proxy->dataObserver_[type]) {
638 if (JSUtil::Equals(env, argv[1], it->GetCallback())) {
639 ZLOGI("function is already subscribe type");
640 return;
641 }
642 }
643
644 Status status = proxy->Subscribe(type,
645 std::make_shared<DataObserver>(proxy->uvQueue_, argv[1], proxy->IsSchemaStore()));
646 ThrowNapiError(env, status, "", false);
647 }
648
649 /*
650 * [JS API Prototype] JsSingleKVStore::OffDataChange is private non-static.
651 * [Callback]
652 * on(event:'dataChange', subType: SubscribeType, observer: Callback<ChangeNotification>): void;
653 * [NOTES!!!] no SubscribeType while off...
654 * off(event:'dataChange', observer: Callback<ChangeNotification>): void;
655 */
OffDataChange(napi_env env,size_t argc,napi_value * argv,std::shared_ptr<ContextBase> ctxt)656 void JsSingleKVStore::OffDataChange(napi_env env, size_t argc, napi_value* argv, std::shared_ptr<ContextBase> ctxt)
657 {
658 // required 1 arguments :: [callback]
659 ASSERT_BUSINESS_ERR(ctxt, argc <= 1, Status::INVALID_ARGUMENT, "The number of parameters is incorrect.");
660 // have 1 arguments :: have the callback
661 if (argc == 1) {
662 napi_valuetype valueType = napi_undefined;
663 ctxt->status = napi_typeof(env, argv[0], &valueType);
664 ASSERT_BUSINESS_ERR(ctxt, (ctxt->status == napi_ok) && (valueType == napi_function), Status::INVALID_ARGUMENT,
665 "The type of parameter Callback is incorrect.");
666 }
667
668 ZLOGI("unsubscribe dataChange, %{public}s specified observer.", (argc == 0) ? "without": "with");
669
670 auto proxy = reinterpret_cast<JsSingleKVStore*>(ctxt->native);
671 bool found = false;
672 Status status = Status::SUCCESS;
673 auto traverseType = [argc, argv, proxy, env, &found, &status](uint8_t type, auto& observers) {
674 auto it = observers.begin();
675 while (it != observers.end()) {
676 if ((argc == 1) && !JSUtil::Equals(env, argv[0], (*it)->GetCallback())) {
677 ++it;
678 continue; // specified observer and not current iterator
679 }
680 found = true;
681 status = proxy->UnSubscribe(type, *it);
682 if (status != Status::SUCCESS) {
683 break; // stop on fail.
684 }
685 it = observers.erase(it);
686 }
687 };
688
689 std::lock_guard<std::mutex> lck(proxy->listMutex_);
690 for (uint8_t type = SUBSCRIBE_LOCAL; type < SUBSCRIBE_COUNT; type++) {
691 traverseType(type, proxy->dataObserver_[type]);
692 if (status != Status::SUCCESS) {
693 break; // stop on fail.
694 }
695 }
696 ASSERT_BUSINESS_ERR(ctxt, found || (argc == 0), Status::INVALID_ARGUMENT, "not Subscribed!");
697 ThrowNapiError(env, status, "", false);
698 }
699
700 /*
701 * [JS API Prototype] JsSingleKVStore::OnSyncComplete is private non-static.
702 * [Callback]
703 * on(event:'syncComplete',syncCallback: Callback<Array<[string, number]>>):void;
704 */
OnSyncComplete(napi_env env,size_t argc,napi_value * argv,std::shared_ptr<ContextBase> ctxt)705 void JsSingleKVStore::OnSyncComplete(napi_env env, size_t argc, napi_value* argv, std::shared_ptr<ContextBase> ctxt)
706 {
707 // required 1 arguments :: <callback>
708 ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::INVALID_ARGUMENT, "The number of parameters is incorrect.");
709 napi_valuetype valueType = napi_undefined;
710 ctxt->status = napi_typeof(env, argv[0], &valueType);
711 ASSERT_BUSINESS_ERR(ctxt, (ctxt->status == napi_ok) && (valueType == napi_function), Status::INVALID_ARGUMENT,
712 "The type of parameter Callback is incorrect.");
713
714 auto proxy = reinterpret_cast<JsSingleKVStore*>(ctxt->native);
715 ctxt->status = proxy->RegisterSyncCallback(std::make_shared<SyncObserver>(proxy->uvQueue_, argv[0]));
716 ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::INVALID_ARGUMENT, "RegisterSyncCallback failed!");
717 }
718
719 /*
720 * [JS API Prototype] JsSingleKVStore::OffSyncComplete is private non-static.
721 * [Callback]
722 * off(event:'syncComplete',syncCallback: Callback<Array<[string, number]>>):void;
723 */
OffSyncComplete(napi_env env,size_t argc,napi_value * argv,std::shared_ptr<ContextBase> ctxt)724 void JsSingleKVStore::OffSyncComplete(napi_env env, size_t argc, napi_value* argv, std::shared_ptr<ContextBase> ctxt)
725 {
726 // required 1 arguments :: [callback]
727 auto proxy = reinterpret_cast<JsSingleKVStore*>(ctxt->native);
728 // have 1 arguments :: have the callback
729 if (argc == 1) {
730 napi_valuetype valueType = napi_undefined;
731 ctxt->status = napi_typeof(env, argv[0], &valueType);
732 ASSERT_BUSINESS_ERR(ctxt, (ctxt->status == napi_ok) && (valueType == napi_function), Status::INVALID_ARGUMENT,
733 "The type of parameter Callback is incorrect.");
734 std::lock_guard<std::mutex> lck(proxy->listMutex_);
735 auto it = proxy->syncObservers_.begin();
736 while (it != proxy->syncObservers_.end()) {
737 if (JSUtil::Equals(env, argv[0], (*it)->GetCallback())) {
738 (*it)->Clear();
739 proxy->syncObservers_.erase(it);
740 break;
741 }
742 }
743 ctxt->status = napi_ok;
744 }
745 ZLOGI("unsubscribe syncComplete, %{public}s specified observer.", (argc == 0) ? "without": "with");
746 if (argc == 0 || proxy->syncObservers_.empty()) {
747 ctxt->status = proxy->UnRegisterSyncCallback();
748 }
749 ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::INVALID_ARGUMENT, "UnRegisterSyncCallback failed!");
750 }
751
752 /*
753 * [Internal private non-static]
754 */
RegisterSyncCallback(std::shared_ptr<SyncObserver> callback)755 napi_status JsSingleKVStore::RegisterSyncCallback(std::shared_ptr<SyncObserver> callback)
756 {
757 Status status = kvStore_->RegisterSyncCallback(callback);
758 if (status != Status::SUCCESS) {
759 callback->Clear();
760 return napi_generic_failure;
761 }
762 std::lock_guard<std::mutex> lck(listMutex_);
763 syncObservers_.push_back(callback);
764 return napi_ok;
765 }
766
UnRegisterSyncCallback()767 napi_status JsSingleKVStore::UnRegisterSyncCallback()
768 {
769 Status status = kvStore_->UnRegisterSyncCallback();
770 if (status != Status::SUCCESS) {
771 return napi_generic_failure;
772 }
773 std::lock_guard<std::mutex> lck(listMutex_);
774 for (auto &syncObserver : syncObservers_) {
775 syncObserver->Clear();
776 }
777 syncObservers_.clear();
778 return napi_ok;
779 }
780
Subscribe(uint8_t type,std::shared_ptr<DataObserver> observer)781 Status JsSingleKVStore::Subscribe(uint8_t type, std::shared_ptr<DataObserver> observer)
782 {
783 auto subscribeType = ToSubscribeType(type);
784 Status status = kvStore_->SubscribeKvStore(subscribeType, observer);
785 ZLOGD("kvStore_->SubscribeKvStore(%{public}d) return %{public}d", type, status);
786 if (status != Status::SUCCESS) {
787 observer->Clear();
788 return status;
789 }
790 dataObserver_[type].push_back(observer);
791 return status;
792 }
793
UnSubscribe(uint8_t type,std::shared_ptr<DataObserver> observer)794 Status JsSingleKVStore::UnSubscribe(uint8_t type, std::shared_ptr<DataObserver> observer)
795 {
796 auto subscribeType = ToSubscribeType(type);
797 Status status = kvStore_->UnSubscribeKvStore(subscribeType, observer);
798 ZLOGD("kvStore_->UnSubscribeKvStore(%{public}d) return %{public}d", type, status);
799 if (status == Status::SUCCESS) {
800 observer->Clear();
801 return status;
802 }
803 return status;
804 }
805
OnChange(const ChangeNotification & notification)806 void JsSingleKVStore::DataObserver::OnChange(const ChangeNotification& notification)
807 {
808 ZLOGD("data change insert:%{public}zu, update:%{public}zu, delete:%{public}zu",
809 notification.GetInsertEntries().size(), notification.GetUpdateEntries().size(),
810 notification.GetDeleteEntries().size());
811 KvStoreObserver::OnChange(notification);
812
813 auto args = [notification, isSchema = isSchema_](napi_env env, int& argc, napi_value* argv) {
814 // generate 1 arguments for callback function.
815 argc = 1;
816 JSUtil::SetValue(env, notification, argv[0], isSchema);
817 };
818 AsyncCall(args);
819 }
820
SyncCompleted(const std::map<std::string,DistributedKv::Status> & results)821 void JsSingleKVStore::SyncObserver::SyncCompleted(const std::map<std::string, DistributedKv::Status>& results)
822 {
823 auto args = [results](napi_env env, int& argc, napi_value* argv) {
824 // generate 1 arguments for callback function.
825 argc = 1;
826 JSUtil::SetValue(env, results, argv[0]);
827 };
828 AsyncCall(args);
829 }
830
831 /*
832 * [JS API Prototype]
833 * [AsyncCallback]
834 * get(key:string, callback:AsyncCallback<boolean|string|number|Uint8Array>):void;
835 * [Promise]
836 * get(key:string):Promise<boolean|string|number|Uint8Array>;
837 */
Get(napi_env env,napi_callback_info info)838 napi_value JsSingleKVStore::Get(napi_env env, napi_callback_info info)
839 {
840 struct GetContext : public ContextBase {
841 std::string key;
842 JSUtil::KvStoreVariant value;
843 };
844 auto ctxt = std::make_shared<GetContext>();
845 auto input = [env, ctxt](size_t argc, napi_value* argv) {
846 // required 1 arguments :: <key>
847 ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::INVALID_ARGUMENT, "The number of parameters is incorrect.");
848 ctxt->status = JSUtil::GetValue(env, argv[0], ctxt->key);
849 ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::INVALID_ARGUMENT, "The type of key must be string.");
850 };
851 ctxt->GetCbInfo(env, info, input);
852 ASSERT_NULL(!ctxt->isThrowError, "Get exit");
853
854 ZLOGD("key=%{public}.8s", ctxt->key.c_str());
855 auto execute = [env, ctxt]() {
856 OHOS::DistributedKv::Key key(ctxt->key);
857 OHOS::DistributedKv::Value value;
858 auto kvStore = reinterpret_cast<JsSingleKVStore*>(ctxt->native)->GetKvStorePtr();
859 bool isSchemaStore = reinterpret_cast<JsSingleKVStore*>(ctxt->native)->IsSchemaStore();
860 Status status = kvStore->Get(key, value);
861 ZLOGD("kvStore->Get return %{public}d", status);
862 ctxt->value = isSchemaStore ? value.ToString() : JSUtil::Blob2VariantValue(value);
863 ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ?
864 napi_ok : napi_generic_failure;
865 };
866 auto output = [env, ctxt](napi_value& result) {
867 ctxt->status = JSUtil::SetValue(env, ctxt->value, result);
868 ASSERT_STATUS(ctxt, "output failed");
869 };
870 return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute, output);
871 }
872
873 struct VariantArgs {
874 DataQuery dataQuery;
875 std::string errMsg = "";
876 };
877
GetVariantArgs(napi_env env,size_t argc,napi_value * argv,VariantArgs & va)878 static napi_status GetVariantArgs(napi_env env, size_t argc, napi_value* argv, VariantArgs& va)
879 {
880 // required 1 arguments :: <keyPrefix/query>
881 napi_valuetype type = napi_undefined;
882 napi_status status = napi_typeof(env, argv[0], &type);
883 if (status != napi_ok || (type != napi_string && type != napi_object)) {
884 va.errMsg = "The type of parameters keyPrefix/query is incorrect.";
885 return status != napi_ok ? status : napi_invalid_arg;
886 }
887 if (type == napi_string) {
888 std::string keyPrefix;
889 JSUtil::GetValue(env, argv[0], keyPrefix);
890 if (keyPrefix.empty()) {
891 va.errMsg = "The type of parameters keyPrefix is incorrect.";
892 return napi_invalid_arg;
893 }
894 va.dataQuery.KeyPrefix(keyPrefix);
895 } else if (type == napi_object) {
896 bool result = false;
897 status = napi_instanceof(env, argv[0], JsQuery::Constructor(env), &result);
898 if ((status == napi_ok) && (result != false)) {
899 JsQuery *jsQuery = nullptr;
900 status = JSUtil::Unwrap(env, argv[0], reinterpret_cast<void **>(&jsQuery), JsQuery::Constructor(env));
901 if (jsQuery == nullptr) {
902 va.errMsg = "The parameters query is incorrect.";
903 return napi_invalid_arg;
904 }
905 va.dataQuery = jsQuery->GetDataQuery();
906 } else {
907 status = JSUtil::GetValue(env, argv[0], va.dataQuery);
908 ZLOGD("kvStoreDataShare->GetResultSet return %{public}d", status);
909 }
910 }
911 return status;
912 };
913
914 /*
915 * [JS API Prototype]
916 * getEntries(keyPrefix:string, callback:AsyncCallback<Entry[]>):void
917 * getEntries(keyPrefix:string):Promise<Entry[]>
918 *
919 * getEntries(query:Query, callback:AsyncCallback<Entry[]>):void
920 * getEntries(query:Query) : Promise<Entry[]>
921 */
GetEntries(napi_env env,napi_callback_info info)922 napi_value JsSingleKVStore::GetEntries(napi_env env, napi_callback_info info)
923 {
924 struct GetEntriesContext : public ContextBase {
925 VariantArgs va;
926 std::vector<Entry> entries;
927 };
928 auto ctxt = std::make_shared<GetEntriesContext>();
929 auto input = [env, ctxt](size_t argc, napi_value* argv) {
930 // required 1 arguments :: <keyPrefix/query>
931 ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::INVALID_ARGUMENT, "The number of parameters is incorrect.");
932 ctxt->status = GetVariantArgs(env, argc, argv, ctxt->va);
933 ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::INVALID_ARGUMENT, ctxt->va.errMsg);
934 };
935 ctxt->GetCbInfo(env, info, input);
936 ASSERT_NULL(!ctxt->isThrowError, "GetEntries exit");
937
938 auto execute = [ctxt]() {
939 auto kvStore = reinterpret_cast<JsSingleKVStore*>(ctxt->native)->GetKvStorePtr();
940 Status status = kvStore->GetEntries(ctxt->va.dataQuery, ctxt->entries);
941 ZLOGD("kvStore->GetEntries() return %{public}d", status);
942 ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ?
943 napi_ok : napi_generic_failure;
944 };
945 auto output = [env, ctxt](napi_value& result) {
946 auto isSchemaStore = reinterpret_cast<JsSingleKVStore*>(ctxt->native)->IsSchemaStore();
947 ctxt->status = JSUtil::SetValue(env, ctxt->entries, result, isSchemaStore);
948 ASSERT_STATUS(ctxt, "output failed!");
949 };
950 return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute, output);
951 }
952
953 /*
954 * [JS API Prototype]
955 * getResultSet(keyPrefix:string, callback:AsyncCallback<KvStoreResultSet>):void
956 * getResultSet(keyPrefix:string):Promise<KvStoreResultSet>
957 *
958 * getResultSet(query:Query, callback:AsyncCallback<KvStoreResultSet>):void
959 * getResultSet(query:Query):Promise<KvStoreResultSet>
960 */
GetResultSet(napi_env env,napi_callback_info info)961 napi_value JsSingleKVStore::GetResultSet(napi_env env, napi_callback_info info)
962 {
963 struct GetResultSetContext : public ContextBase {
964 VariantArgs va;
965 JsKVStoreResultSet* resultSet = nullptr;
966 napi_ref ref = nullptr;
967 };
968 auto ctxt = std::make_shared<GetResultSetContext>();
969 auto input = [env, ctxt](size_t argc, napi_value* argv) {
970 // required 1 arguments :: <keyPrefix/query>
971 ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::INVALID_ARGUMENT, "The number of parameters is incorrect.");
972 ctxt->status = GetVariantArgs(env, argc, argv, ctxt->va);
973 ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::INVALID_ARGUMENT, ctxt->va.errMsg);
974 ctxt->ref = JSUtil::NewWithRef(env, 0, nullptr, reinterpret_cast<void**>(&ctxt->resultSet),
975 JsKVStoreResultSet::Constructor(env));
976 ASSERT_BUSINESS_ERR(ctxt, ctxt->resultSet != nullptr, Status::INVALID_ARGUMENT,
977 "KVStoreResultSet::New failed!");
978 };
979 ctxt->GetCbInfo(env, info, input);
980 ASSERT_NULL(!ctxt->isThrowError, "GetResultSet exit");
981
982 auto execute = [ctxt]() {
983 std::shared_ptr<KvStoreResultSet> kvResultSet;
984 auto kvStore = reinterpret_cast<JsSingleKVStore*>(ctxt->native)->GetKvStorePtr();
985 Status status = kvStore->GetResultSet(ctxt->va.dataQuery, kvResultSet);
986 ZLOGD("kvStore->GetResultSet() return %{public}d", status);
987
988 ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ?
989 napi_ok : napi_generic_failure;
990 ctxt->resultSet->SetKvStoreResultSetPtr(kvResultSet);
991 };
992 auto output = [env, ctxt](napi_value& result) {
993 ctxt->status = napi_get_reference_value(env, ctxt->ref, &result);
994 napi_delete_reference(env, ctxt->ref);
995 ASSERT_STATUS(ctxt, "output kvResultSet failed");
996 };
997 return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute, output);
998 }
999
1000 /*
1001 * [JS API Prototype]
1002 * closeResultSet(resultSet:KVStoreResultSet, callback: AsyncCallback<void>):void
1003 * closeResultSet(resultSet:KVStoreResultSet):Promise<void>
1004 */
CloseResultSet(napi_env env,napi_callback_info info)1005 napi_value JsSingleKVStore::CloseResultSet(napi_env env, napi_callback_info info)
1006 {
1007 struct CloseResultSetContext : public ContextBase {
1008 JsKVStoreResultSet* resultSet = nullptr;
1009 };
1010 auto ctxt = std::make_shared<CloseResultSetContext>();
1011 auto input = [env, ctxt](size_t argc, napi_value* argv) {
1012 // required 1 arguments :: <resultSet>
1013 ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::INVALID_ARGUMENT, "The number of parameters is incorrect.");
1014 napi_valuetype type = napi_undefined;
1015 ctxt->status = napi_typeof(env, argv[0], &type);
1016 ASSERT_BUSINESS_ERR(ctxt, type == napi_object, Status::INVALID_ARGUMENT,
1017 "The type of parameters resultSet is incorrect.");
1018 ctxt->status = JSUtil::Unwrap(env, argv[0], reinterpret_cast<void**>(&ctxt->resultSet),
1019 JsKVStoreResultSet::Constructor(env));
1020 ASSERT_BUSINESS_ERR(ctxt, ctxt->resultSet != nullptr, Status::INVALID_ARGUMENT,
1021 "The parameters resultSet is incorrect.");
1022 };
1023 ctxt->GetCbInfo(env, info, input);
1024 ASSERT_NULL(!ctxt->isThrowError, "CloseResultSet exit");
1025
1026 auto execute = [ctxt]() {
1027 auto kvStore = reinterpret_cast<JsSingleKVStore*>(ctxt->native)->GetKvStorePtr();
1028 auto resultSet = ctxt->resultSet->GetKvStoreResultSetPtr();
1029 Status status = kvStore->CloseResultSet(resultSet);
1030 ZLOGD("kvStore->CloseResultSet return %{public}d", status);
1031 ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ?
1032 napi_ok : napi_generic_failure;
1033 };
1034 return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute);
1035 }
1036
1037 /*
1038 * [JS API Prototype]
1039 * getResultSize(query:Query, callback: AsyncCallback<number>):void
1040 * getResultSize(query:Query):Promise<number>
1041 */
GetResultSize(napi_env env,napi_callback_info info)1042 napi_value JsSingleKVStore::GetResultSize(napi_env env, napi_callback_info info)
1043 {
1044 struct ResultSizeContext : public ContextBase {
1045 JsQuery* query = nullptr;
1046 int resultSize = 0;
1047 };
1048 auto ctxt = std::make_shared<ResultSizeContext>();
1049 auto input = [env, ctxt](size_t argc, napi_value* argv) {
1050 // required 1 arguments :: <query>
1051 ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::INVALID_ARGUMENT, "The number of parameters is incorrect.");
1052 napi_valuetype type = napi_undefined;
1053 ctxt->status = napi_typeof(env, argv[0], &type);
1054 ASSERT_BUSINESS_ERR(ctxt, type == napi_object, Status::INVALID_ARGUMENT,
1055 "The type of parameters query is incorrect.");
1056 ctxt->status = JSUtil::Unwrap(env, argv[0], reinterpret_cast<void**>(&ctxt->query), JsQuery::Constructor(env));
1057 ASSERT_BUSINESS_ERR(ctxt, ctxt->query != nullptr, Status::INVALID_ARGUMENT,
1058 "The parameters query is incorrect.");
1059 };
1060 ctxt->GetCbInfo(env, info, input);
1061 ASSERT_NULL(!ctxt->isThrowError, "GetResultSize exit");
1062
1063 auto execute = [ctxt]() {
1064 auto kvStore = reinterpret_cast<JsSingleKVStore*>(ctxt->native)->GetKvStorePtr();
1065 auto query = ctxt->query->GetDataQuery();
1066 Status status = kvStore->GetCount(query, ctxt->resultSize);
1067 ZLOGD("kvStore->GetCount() return %{public}d", status);
1068 ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ?
1069 napi_ok : napi_generic_failure;
1070 };
1071 auto output = [env, ctxt](napi_value& result) {
1072 ctxt->status = JSUtil::SetValue(env, static_cast<int32_t>(ctxt->resultSize), result);
1073 ASSERT_STATUS(ctxt, "output resultSize failed!");
1074 };
1075 return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute, output);
1076 }
1077
1078 /*
1079 * [JS API Prototype]
1080 * removeDeviceData(deviceId:string, callback: AsyncCallback<void>):void
1081 * removeDeviceData(deviceId:string):Promise<void>
1082 */
RemoveDeviceData(napi_env env,napi_callback_info info)1083 napi_value JsSingleKVStore::RemoveDeviceData(napi_env env, napi_callback_info info)
1084 {
1085 struct RemoveDeviceContext : public ContextBase {
1086 std::string deviceId;
1087 };
1088 auto ctxt = std::make_shared<RemoveDeviceContext>();
1089 auto input = [env, ctxt](size_t argc, napi_value* argv) {
1090 // required 1 arguments :: <deviceId>
1091 ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::INVALID_ARGUMENT, "The number of parameters is incorrect.");
1092 ctxt->status = JSUtil::GetValue(env, argv[0], ctxt->deviceId);
1093 ASSERT_BUSINESS_ERR(ctxt, (!ctxt->deviceId.empty()) && (ctxt->status == napi_ok), Status::INVALID_ARGUMENT,
1094 "The parameters deviceId is incorrect.");
1095 };
1096 ctxt->GetCbInfo(env, info, input);
1097 ASSERT_NULL(!ctxt->isThrowError, "RemoveDeviceData exit");
1098
1099 auto execute = [ctxt]() {
1100 auto kvStore = reinterpret_cast<JsSingleKVStore*>(ctxt->native)->GetKvStorePtr();
1101 Status status = kvStore->RemoveDeviceData(ctxt->deviceId);
1102 ZLOGD("kvStore->RemoveDeviceData return %{public}d", status);
1103 ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ?
1104 napi_ok : napi_generic_failure;
1105 };
1106 return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute);
1107 }
1108
1109 /*
1110 * [JS API Prototype]
1111 * sync(deviceIdList:string[], mode:SyncMode, allowedDelayMs?:number):void
1112 */
Sync(napi_env env,napi_callback_info info)1113 napi_value JsSingleKVStore::Sync(napi_env env, napi_callback_info info)
1114 {
1115 struct SyncContext : public ContextBase {
1116 std::vector<std::string> deviceIdList;
1117 uint32_t mode = 0;
1118 uint32_t allowedDelayMs = 0;
1119 JsQuery* query = nullptr;
1120 napi_valuetype type = napi_undefined;
1121 };
1122 auto ctxt = std::make_shared<SyncContext>();
1123 auto input = [env, ctxt](size_t argc, napi_value* argv) {
1124 // required 3 arguments :: <deviceIdList> <mode> [allowedDelayMs]
1125 ASSERT_BUSINESS_ERR(ctxt, argc >= 2, Status::INVALID_ARGUMENT, "The number of parameters is incorrect.");
1126 ctxt->status = JSUtil::GetValue(env, argv[0], ctxt->deviceIdList);
1127 ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::INVALID_ARGUMENT,
1128 "The deviceIdList parameters is incorrect.");
1129 napi_typeof(env, argv[1], &ctxt->type);
1130 if (ctxt->type == napi_object) {
1131 ctxt->status = JSUtil::Unwrap(env,
1132 argv[1], reinterpret_cast<void**>(&ctxt->query), JsQuery::Constructor(env));
1133 ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::INVALID_ARGUMENT,
1134 "The parameters mode is incorrect.");
1135 ctxt->status = JSUtil::GetValue(env, argv[2], ctxt->mode);
1136 }
1137 if (ctxt->type == napi_number) {
1138 ctxt->status = JSUtil::GetValue(env, argv[1], ctxt->mode);
1139 if (argc == 3) {
1140 ctxt->status = JSUtil::GetValue(env, argv[2], ctxt->allowedDelayMs);
1141 }
1142 }
1143 ASSERT_BUSINESS_ERR(ctxt, (ctxt->mode <= uint32_t(SyncMode::PUSH_PULL)) && (ctxt->status == napi_ok),
1144 Status::INVALID_ARGUMENT, "The number of parameters is incorrect.");
1145 };
1146 ctxt->GetCbInfoSync(env, info, input);
1147 ASSERT_NULL(!ctxt->isThrowError, "Sync exit");
1148
1149 ZLOGD("sync deviceIdList.size=%{public}d, mode:%{public}u, allowedDelayMs:%{public}u",
1150 (int)ctxt->deviceIdList.size(), ctxt->mode, ctxt->allowedDelayMs);
1151
1152 auto kvStore = reinterpret_cast<JsSingleKVStore*>(ctxt->native)->GetKvStorePtr();
1153 Status status = Status::INVALID_ARGUMENT;
1154 if (ctxt->type == napi_object) {
1155 auto query = ctxt->query->GetDataQuery();
1156 status = kvStore->Sync(ctxt->deviceIdList, static_cast<SyncMode>(ctxt->mode), query, nullptr);
1157 }
1158 if (ctxt->type == napi_number) {
1159 status = kvStore->Sync(ctxt->deviceIdList, static_cast<SyncMode>(ctxt->mode), ctxt->allowedDelayMs);
1160 }
1161 ZLOGD("kvStore->Sync return %{public}d!", status);
1162 ThrowNapiError(env, status, "", false);
1163 return nullptr;
1164 }
1165
1166 /*
1167 * [JS API Prototype]
1168 * setSyncParam(defaultAllowedDelayMs:number, callback: AsyncCallback<number>):void
1169 * setSyncParam(defaultAllowedDelayMs:number):Promise<void>
1170 */
SetSyncParam(napi_env env,napi_callback_info info)1171 napi_value JsSingleKVStore::SetSyncParam(napi_env env, napi_callback_info info)
1172 {
1173 struct SyncParamContext : public ContextBase {
1174 uint32_t allowedDelayMs;
1175 };
1176 auto ctxt = std::make_shared<SyncParamContext>();
1177 auto input = [env, ctxt](size_t argc, napi_value* argv) {
1178 // required 1 arguments :: <allowedDelayMs>
1179 ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::INVALID_ARGUMENT, "The number of parameters is incorrect.");
1180 ctxt->status = JSUtil::GetValue(env, argv[0], ctxt->allowedDelayMs);
1181 ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::INVALID_ARGUMENT,
1182 "The parameters allowedDelayMs is incorrect.");
1183 };
1184 ctxt->GetCbInfo(env, info, input);
1185 ASSERT_NULL(!ctxt->isThrowError, "SetSyncParam exit");
1186
1187 auto execute = [ctxt]() {
1188 auto kvStore = reinterpret_cast<JsSingleKVStore*>(ctxt->native)->GetKvStorePtr();
1189 KvSyncParam syncParam { ctxt->allowedDelayMs };
1190 Status status = kvStore->SetSyncParam(syncParam);
1191 ZLOGD("kvStore->SetSyncParam return %{public}d", status);
1192 ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ?
1193 napi_ok : napi_generic_failure;
1194 };
1195 return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute);
1196 }
1197
1198 /*
1199 * [JS API Prototype]
1200 * getSecurityLevel(callback: AsyncCallback<SecurityLevel>):void
1201 * getSecurityLevel():Promise<SecurityLevel>
1202 */
GetSecurityLevel(napi_env env,napi_callback_info info)1203 napi_value JsSingleKVStore::GetSecurityLevel(napi_env env, napi_callback_info info)
1204 {
1205 struct SecurityLevelContext : public ContextBase {
1206 SecurityLevel securityLevel;
1207 };
1208 auto ctxt = std::make_shared<SecurityLevelContext>();
1209 ctxt->GetCbInfo(env, info);
1210
1211 auto execute = [ctxt]() {
1212 auto kvStore = reinterpret_cast<JsSingleKVStore*>(ctxt->native)->GetKvStorePtr();
1213 Status status = kvStore->GetSecurityLevel(ctxt->securityLevel);
1214 ZLOGD("kvStore->GetSecurityLevel return %{public}d", status);
1215 ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ?
1216 napi_ok : napi_generic_failure;
1217 };
1218 auto output = [env, ctxt](napi_value& result) {
1219 ctxt->status = JSUtil::SetValue(env, static_cast<uint8_t>(ctxt->securityLevel), result);
1220 ASSERT_STATUS(ctxt, "output failed!");
1221 };
1222 return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute, output);
1223 }
1224
New(napi_env env,napi_callback_info info)1225 napi_value JsSingleKVStore::New(napi_env env, napi_callback_info info)
1226 {
1227 ZLOGD("Constructor single kv store!");
1228 std::string storeId;
1229 auto ctxt = std::make_shared<ContextBase>();
1230 auto input = [env, ctxt, &storeId](size_t argc, napi_value* argv) {
1231 // required 2 arguments :: <storeId> <options>
1232 ASSERT_BUSINESS_ERR(ctxt, argc >= 2, Status::INVALID_ARGUMENT, "The number of parameters is incorrect.");
1233 ctxt->status = JSUtil::GetValue(env, argv[0], storeId);
1234 ASSERT_BUSINESS_ERR(ctxt, (ctxt->status == napi_ok) && !storeId.empty(), Status::INVALID_ARGUMENT,
1235 "The type of storeId must be string.");
1236 };
1237 ctxt->GetCbInfoSync(env, info, input);
1238 ASSERT_NULL(!ctxt->isThrowError, "SingleKVStore new exit");
1239 ASSERT_ERR(env, ctxt->status == napi_ok, Status::INVALID_ARGUMENT, "no memory for kvStore");
1240
1241 JsSingleKVStore* kvStore = new (std::nothrow) JsSingleKVStore(storeId);
1242 ASSERT_ERR(env, kvStore != nullptr, Status::INVALID_ARGUMENT, "no memory for kvStore");
1243
1244 auto finalize = [](napi_env env, void* data, void* hint) {
1245 ZLOGI("singleKVStore finalize.");
1246 auto* kvStore = reinterpret_cast<JsSingleKVStore*>(data);
1247 ASSERT_VOID(kvStore != nullptr, "finalize null!");
1248 delete kvStore;
1249 };
1250 ASSERT_CALL(env, napi_wrap(env, ctxt->self, kvStore, finalize, nullptr, nullptr), kvStore);
1251 return ctxt->self;
1252 }
1253 } // namespace OHOS::DistributedKVStore
1254