1 /*
2 * Copyright (c) 2024 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 "CollaborationEditObject"
16
17 #include <future>
18
19 #include "napi_collaboration_edit_object.h"
20
21 #include "db_store_config.h"
22 #include "db_store_manager.h"
23 #include "napi_edit_unit.h"
24 #include "napi_error_utils.h"
25 #include "napi_parser.h"
26 #include "napi_sync_service.h"
27 #include "napi/native_node_api.h"
28
29 namespace OHOS::CollaborationEdit {
30 static constexpr const uint8_t BATCH_INSERT_FUNC_INDEX = 0;
31 static constexpr const uint8_t QUERY_FUNC_INDEX = 1;
32 static constexpr const uint8_t DOWNLOAD_ASSET_FUNC_INDEX = 2;
33 static constexpr const uint8_t UPLOAD_ASSET_FUNC_INDEX = 3;
34 static constexpr const uint8_t DELETE_ASSET_FUNC_INDEX = 4;
35 static constexpr const uint8_t DELETE_LOCAL_ASSET_FUNC_INDEX = 5;
36
37 static constexpr const uint8_t CLOUD_SYNC_PARAM_NUMBER = 2;
38 static const std::map<SyncMode, GRD_SyncModeE> SYNC_MODE_MAP = {
39 {SyncMode::PUSH, GRD_SYNC_MODE_UPLOAD},
40 {SyncMode::PULL, GRD_SYNC_MODE_DOWNLOAD_LOG},
41 {SyncMode::PULL_PUSH, GRD_SYNC_MODE_UP_DOWN_LOG}
42 };
43
CollaborationEditObject(std::string docName,ContextParam param)44 CollaborationEditObject::CollaborationEditObject(std::string docName, ContextParam param)
45 : docName_(docName), param_(std::make_shared<ContextParam>(std::move(param)))
46 {}
47
~CollaborationEditObject()48 CollaborationEditObject::~CollaborationEditObject()
49 {}
50
Initialize(napi_env env,napi_callback_info info)51 napi_value CollaborationEditObject::Initialize(napi_env env, napi_callback_info info)
52 {
53 size_t argc = 2;
54 napi_value argv[2] = {nullptr};
55 napi_value self = nullptr;
56 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &self, nullptr));
57 ContextParam context;
58 napi_status status = NapiUtils::GetValue(env, argv[0], context);
59 ASSERT_THROW_BASE(env, status == napi_ok, Status::INVALID_ARGUMENT, "read context param go wrong", self);
60 std::string docName;
61 status = NapiUtils::GetNamedProperty(env, argv[1], "name", docName);
62 ASSERT_THROW_BASE(env, status == napi_ok, Status::INVALID_ARGUMENT, "read docName param go wrong", self);
63 ASSERT_THROW_BASE(env, !docName.empty(), Status::INVALID_ARGUMENT, "Param Error: invalid name", self);
64 std::string dbFilePath = context.baseDir + "/" + docName;
65 DBStoreConfig config(dbFilePath, docName);
66 std::shared_ptr<DBStore> dbStore = DBStoreManager::GetInstance().GetDBStore(config);
67 if (dbStore == nullptr) {
68 ThrowNapiError(env, Status::INTERNAL_ERROR, "open doc go wrong");
69 return self;
70 }
71
72 CollaborationEditObject *editObject = new (std::nothrow) CollaborationEditObject(docName, context);
73 ASSERT_THROW_BASE(env, editObject != nullptr, Status::INTERNAL_ERROR, "Initialize: new editObject go wrong", self);
74 editObject->SetDBStore(dbStore);
75 auto finalize = [](napi_env env, void *data, void *hint) {
76 CollaborationEditObject *editObject = reinterpret_cast<CollaborationEditObject *>(data);
77 delete editObject;
78 };
79 status = napi_wrap(env, self, editObject, finalize, nullptr, nullptr);
80 if (status != napi_ok) {
81 LOG_ERROR("napi_wrap failed. code:%{public}d", status);
82 delete editObject;
83 return nullptr;
84 }
85 return self;
86 }
87
Constructor(napi_env env)88 napi_value CollaborationEditObject::Constructor(napi_env env)
89 {
90 auto lambda = []() -> std::vector<napi_property_descriptor> {
91 std::vector<napi_property_descriptor> properties = {
92 DECLARE_NAPI_FUNCTION("getEditUnit", GetEditUnit),
93 DECLARE_NAPI_FUNCTION("getUndoRedoManager", GetUndoRedoManager),
94 DECLARE_NAPI_FUNCTION("deleteUndoRedoManager", DeleteUndoRedoManager),
95 DECLARE_NAPI_FUNCTION("getName", GetName),
96 DECLARE_NAPI_FUNCTION("cloudSync", CloudSync),
97 DECLARE_NAPI_FUNCTION("setCloudDB", SetCloudDb),
98 DECLARE_NAPI_FUNCTION("getLocalId", GetLocalId),
99 DECLARE_NAPI_FUNCTION("applyUpdate", ApplyUpdate),
100 DECLARE_NAPI_FUNCTION("writeUpdate", WriteUpdate),
101 };
102 return properties;
103 };
104 return NapiUtils::DefineClass(
105 env, "ohos.data.collaborationEditObject", "CollaborationEditObject", lambda, Initialize);
106 }
107
NewInstance(napi_env env,napi_callback_info info)108 napi_value CollaborationEditObject::NewInstance(napi_env env, napi_callback_info info)
109 {
110 size_t argc = 2;
111 napi_value argv[2] = {nullptr};
112 napi_value editObject = nullptr;
113 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
114
115 napi_status status = napi_new_instance(env, Constructor(env), argc, argv, &editObject);
116 if (editObject == nullptr || status != napi_ok) {
117 LOG_ERROR("[NewInstance] new instance go wrong");
118 }
119 return editObject;
120 }
121
GetEditUnit(napi_env env,napi_callback_info info)122 napi_value CollaborationEditObject::GetEditUnit(napi_env env, napi_callback_info info)
123 {
124 size_t argc = 1;
125 napi_value argv[1] = {nullptr};
126 napi_value self = nullptr;
127 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &self, nullptr));
128 CollaborationEditObject *editObject = nullptr;
129 NAPI_CALL(env, napi_unwrap(env, self, reinterpret_cast<void **>(&editObject)));
130 napi_value napiEditUnit = EditUnit::NewInstance(env, info, self);
131 EditUnit *editUnit = nullptr;
132 napi_status status = napi_unwrap(env, napiEditUnit, reinterpret_cast<void **>(&editUnit));
133 if (status != napi_ok || editUnit == nullptr) {
134 LOG_ERROR("unwrap EditUnit go wrong, status = %{public}d", status);
135 return nullptr;
136 }
137 editUnit->SetDBStore(editObject->GetDBStore());
138 return napiEditUnit;
139 }
140
GetUndoRedoManager(napi_env env,napi_callback_info info)141 napi_value CollaborationEditObject::GetUndoRedoManager(napi_env env, napi_callback_info info)
142 {
143 size_t argc = 2;
144 napi_value argv[2] = {nullptr};
145 napi_value self = nullptr;
146 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &self, nullptr));
147 CollaborationEditObject *editObject = nullptr;
148 NAPI_CALL(env, napi_unwrap(env, self, reinterpret_cast<void **>(&editObject)));
149 napi_value jsUndoManager = UndoManager::NewInstance(env, info);
150 UndoManager *undoManager = nullptr;
151 napi_status status = napi_unwrap(env, jsUndoManager, reinterpret_cast<void **>(&undoManager));
152 if (status != napi_ok || undoManager == nullptr) {
153 LOG_ERROR("unwrap UndoManager go wrong, status = %{public}d", status);
154 return nullptr;
155 }
156 undoManager->SetDBStore(editObject->GetDBStore());
157 int32_t retCode = undoManager->GetAdapter()->CreateUndoManager(undoManager->GetCaptureTimeout());
158 ASSERT_THROW(env, retCode == SUCCESS, retCode, "create undo manager go wrong.");
159 return jsUndoManager;
160 }
161
DeleteUndoRedoManager(napi_env env,napi_callback_info info)162 napi_value CollaborationEditObject::DeleteUndoRedoManager(napi_env env, napi_callback_info info)
163 {
164 size_t argc = 1;
165 napi_value argv[1] = {nullptr};
166 napi_value self = nullptr;
167 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &self, nullptr));
168 CollaborationEditObject *editObject = nullptr;
169 NAPI_CALL(env, napi_unwrap(env, self, reinterpret_cast<void **>(&editObject)));
170 std::string editUnitName;
171 napi_status status = NapiUtils::GetValue(env, argv[0], editUnitName);
172 ASSERT_THROW(env, status == napi_ok, Status::INVALID_ARGUMENT, "read editUnitName go wrong");
173 std::shared_ptr<RdAdapter> adapter = std::make_shared<RdAdapter>();
174 std::string tableName = std::to_string(LABEL_FRAGMENT) + "_" + editUnitName;
175 adapter->SetTableName(tableName);
176 adapter->SetDBStore(editObject->GetDBStore());
177 int32_t retCode = adapter->CloseUndoManager();
178 ASSERT_THROW(env, retCode == SUCCESS, retCode, "close undo manager go wrong.");
179 LOG_INFO("Close undo manager successfully.");
180 return nullptr;
181 }
182
GetName(napi_env env,napi_callback_info info)183 napi_value CollaborationEditObject::GetName(napi_env env, napi_callback_info info)
184 {
185 napi_value self = nullptr;
186 NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &self, nullptr));
187 CollaborationEditObject *editObject = nullptr;
188 napi_status status = napi_unwrap(env, self, reinterpret_cast<void **>(&editObject));
189 if (status != napi_ok) {
190 ThrowNapiError(env, status, "unwrap object go wrong");
191 return nullptr;
192 }
193 napi_value result;
194 NapiUtils::SetValue(env, editObject->docName_, result);
195 return result;
196 }
197
SetCloudDb(napi_env env,napi_callback_info info)198 napi_value CollaborationEditObject::SetCloudDb(napi_env env, napi_callback_info info)
199 {
200 size_t argc = 1;
201 napi_value argv[1] = {nullptr};
202 napi_value self = nullptr;
203 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &self, nullptr));
204
205 CollaborationEditObject *editObject = nullptr;
206 napi_status status = napi_unwrap(env, self, reinterpret_cast<void **>(&editObject));
207 if (status != napi_ok) {
208 ThrowNapiError(env, Status::INTERNAL_ERROR, "unwrap editObject go wrong.");
209 return nullptr;
210 }
211 std::shared_ptr<DBStore> dbStore = editObject->GetDBStore();
212 if (dbStore == nullptr) {
213 ThrowNapiError(env, Status::INVALID_ARGUMENT, "dbStore is null.");
214 return nullptr;
215 }
216 if (dbStore->GetCloudDB() != nullptr) {
217 LOG_INFO("cloudDB already set");
218 return nullptr;
219 }
220
221 std::vector<napi_value> cloudDbFunc;
222 int ret = Parser::ParseCloudDbFields(env, argv[0], cloudDbFunc);
223 if (ret != OK) {
224 ThrowNapiError(env, Status::INVALID_ARGUMENT, "parse cloudDb fields go wrong.");
225 return nullptr;
226 }
227 NapiCloudDb *napiCloudDb = new (std::nothrow) NapiCloudDb();
228 ASSERT_THROW(env, napiCloudDb != nullptr, Status::INTERNAL_ERROR, "new cloud db instance go wrong.");
229 status = CollaborationEditObject::CreateHandlerFunc(env, cloudDbFunc, napiCloudDb);
230 if (status != napi_ok) {
231 delete napiCloudDb;
232 ThrowNapiError(env, Status::INTERNAL_ERROR, "create handler func go wrong.");
233 return nullptr;
234 }
235
236 ret = DBStoreManager::GetInstance().SetCloudDb(dbStore, napiCloudDb);
237 if (ret != 0) {
238 delete napiCloudDb;
239 ThrowNapiError(env, ret, "set cloud db go wrong.");
240 }
241 return nullptr;
242 }
243
CreateHandlerFunc(napi_env env,std::vector<napi_value> & cloudDbFunc,NapiCloudDb * napiCloudDb)244 napi_status CollaborationEditObject::CreateHandlerFunc(napi_env env, std::vector<napi_value> &cloudDbFunc,
245 NapiCloudDb *napiCloudDb)
246 {
247 napi_value name = nullptr;
248 napi_status status = napi_create_string_utf8(env, "batchInsert", NAPI_AUTO_LENGTH, &name);
249 ASSERT(status == napi_ok, "create batchInsert string wrong", status);
250 status = napi_create_threadsafe_function(env, cloudDbFunc[BATCH_INSERT_FUNC_INDEX], nullptr, name, 0, 1,
251 nullptr, nullptr, nullptr, NapiCloudDb::BatchInsertInner, &napiCloudDb->batchInsertInnerFunc_);
252 ASSERT(status == napi_ok, "create batchInsert func wrong", status);
253
254 name = nullptr;
255 status = napi_create_string_utf8(env, "query", NAPI_AUTO_LENGTH, &name);
256 ASSERT(status == napi_ok, "create query string wrong", status);
257 status = napi_create_threadsafe_function(env, cloudDbFunc[QUERY_FUNC_INDEX], nullptr, name, 0, 1,
258 nullptr, nullptr, nullptr, NapiCloudDb::QueryInner, &napiCloudDb->queryInnerFunc_);
259 ASSERT(status == napi_ok, "create query func wrong", status);
260
261 name = nullptr;
262 status = napi_create_string_utf8(env, "downloadAsset", NAPI_AUTO_LENGTH, &name);
263 ASSERT(status == napi_ok, "create downloadAsset string wrong", status);
264 status = napi_create_threadsafe_function(env, cloudDbFunc[DOWNLOAD_ASSET_FUNC_INDEX], nullptr, name, 0, 1,
265 nullptr, nullptr, nullptr, NapiCloudDb::DownloadAssetInner, &napiCloudDb->downloadAssetInnerFunc_);
266 ASSERT(status == napi_ok, "create downloadAsset func wrong", status);
267
268 name = nullptr;
269 status = napi_create_string_utf8(env, "uploadAsset", NAPI_AUTO_LENGTH, &name);
270 ASSERT(status == napi_ok, "create uploadAsset string wrong", status);
271 status = napi_create_threadsafe_function(env, cloudDbFunc[UPLOAD_ASSET_FUNC_INDEX], nullptr, name, 0, 1,
272 nullptr, nullptr, nullptr, NapiCloudDb::UploadAssetInner, &napiCloudDb->uploadAssetInnerFunc_);
273 ASSERT(status == napi_ok, "create uploadAsset func wrong", status);
274
275 name = nullptr;
276 status = napi_create_string_utf8(env, "deleteAsset", NAPI_AUTO_LENGTH, &name);
277 ASSERT(status == napi_ok, "create deleteAsset string wrong", status);
278 status = napi_create_threadsafe_function(env, cloudDbFunc[DELETE_ASSET_FUNC_INDEX], nullptr, name, 0, 1,
279 nullptr, nullptr, nullptr, NapiCloudDb::DeleteAssetInner, &napiCloudDb->deleteAssetInnerFunc_);
280 ASSERT(status == napi_ok, "create deleteAsset func wrong", status);
281
282 name = nullptr;
283 status = napi_create_string_utf8(env, "deleteLocalAsset", NAPI_AUTO_LENGTH, &name);
284 ASSERT(status == napi_ok, "create deleteLocalAsset string wrong", status);
285 status = napi_create_threadsafe_function(env, cloudDbFunc[DELETE_LOCAL_ASSET_FUNC_INDEX], nullptr, name, 0, 1,
286 nullptr, nullptr, nullptr, NapiCloudDb::DeleteLocalAssetInner, &napiCloudDb->deleteLocalAssetInnerFunc_);
287 ASSERT(status == napi_ok, "create deleteLocalAsset func wrong", status);
288 return napi_ok;
289 }
290
Delete(napi_env env,napi_callback_info info)291 napi_value CollaborationEditObject::Delete(napi_env env, napi_callback_info info)
292 {
293 size_t argc = 2;
294 napi_value argv[2] = {nullptr};
295 napi_value self = nullptr;
296 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &self, nullptr));
297 ContextParam context;
298 napi_status status = NapiUtils::GetValue(env, argv[0], context);
299 ASSERT_THROW_BASE(env, status == napi_ok, Status::INVALID_ARGUMENT, "read context param go wrong", self);
300 std::string docName;
301 status = NapiUtils::GetNamedProperty(env, argv[1], "name", docName);
302 ASSERT_THROW_BASE(env, status == napi_ok, Status::INVALID_ARGUMENT, "read docName param go wrong", self);
303 ASSERT_THROW_BASE(env, !docName.empty(), Status::INVALID_ARGUMENT, "Param Error: invalid name", self);
304 std::string dbFilePath = context.baseDir + "/" + docName;
305 DBStoreConfig config(dbFilePath, docName);
306 int ret = DBStoreManager::GetInstance().DeleteDBStore(config);
307 if (ret != 0) {
308 ThrowNapiError(env, Status::INTERNAL_ERROR, "remove dir go wrong");
309 }
310 return nullptr;
311 }
312
ParseCloudSyncMode(const napi_env env,const napi_value arg,std::shared_ptr<SyncContext> context)313 int CollaborationEditObject::ParseCloudSyncMode(const napi_env env, const napi_value arg,
314 std::shared_ptr<SyncContext> context)
315 {
316 int32_t mode = 0;
317 napi_status status = NapiUtils::GetValue(env, arg, mode);
318 if (status != napi_ok || mode < 0 || mode > SyncMode::PULL_PUSH) {
319 LOG_ERROR("CloudSync parse syncMode go wrong, mode: %{public}d", mode);
320 return ERR;
321 }
322 context->syncMode_ = mode;
323 return OK;
324 }
325
ParseThis(const napi_env & env,const napi_value & self,std::shared_ptr<SyncContext> context)326 int CollaborationEditObject::ParseThis(const napi_env &env, const napi_value &self,
327 std::shared_ptr<SyncContext> context)
328 {
329 CollaborationEditObject *editObject = nullptr;
330 napi_status status = napi_unwrap(env, self, reinterpret_cast<void **>(&editObject));
331 if (status != napi_ok || editObject == nullptr) {
332 LOG_ERROR("CloudSync unwrap object go wrong");
333 return ERR;
334 }
335 context->dbStore_ = editObject->GetDBStore();
336 context->boundObj = editObject;
337 return OK;
338 }
339
GetCloudSyncInput(std::shared_ptr<SyncContext> context)340 InputAction CollaborationEditObject::GetCloudSyncInput(std::shared_ptr<SyncContext> context)
341 {
342 return [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> int {
343 LOG_DEBUG("get CloudSync input start.");
344 ASSERT(argc == CLOUD_SYNC_PARAM_NUMBER, "CloudSync read param go wrong", ERR);
345 // set params to sync context
346 ASSERT(OK == ParseThis(env, self, context), "CloudSync get editObject go wrong", ERR);
347 ASSERT(OK == ParseCloudSyncMode(env, argv[0], context), "parse syncMode go wrong", ERR);
348
349 napi_value name = nullptr;
350 ASSERT(napi_ok == napi_create_string_utf8(env, "syncCallback", NAPI_AUTO_LENGTH, &name),
351 "create function name string wrong", ERR);
352 ASSERT(napi_ok == napi_create_threadsafe_function(env, argv[1], nullptr, name, 0, 1, nullptr, nullptr, nullptr,
353 AsyncCall::CloudSyncCallback, &context->callback_), "create syncCallback function wrong", ERR);
354 return OK;
355 };
356 }
357
GetCloudSyncExec(std::shared_ptr<SyncContext> context)358 ExecuteAction CollaborationEditObject::GetCloudSyncExec(std::shared_ptr<SyncContext> context)
359 {
360 return [context]() -> int {
361 LOG_INFO("CollaborationEditObject::CloudSync Async execute.");
362 auto *editObject = reinterpret_cast<CollaborationEditObject *>(context->boundObj);
363 ASSERT(editObject != nullptr && context->dbStore_ != nullptr, "editObject is null or dbStore is null", ERR);
364
365 std::shared_ptr<SyncService> syncService = SyncService::GetInstance();
366 uint64_t syncId = syncService->GetSyncId();
367 context->syncId = syncId;
368 syncService->AddSyncContext(syncId, context);
369 int32_t ret = context->dbStore_->Sync(GetGRDSyncMode(context->syncMode_), syncId,
370 CollaborationEditObject::SyncCallbackFunc);
371 if (ret != GRD_OK) {
372 LOG_ERROR("dbStore sync go wrong, errCode: %{public}d", ret);
373 GRD_SyncProcessT process = {};
374 process.status = GRD_SYNC_PROCESS_FINISHED;
375 process.errCode = ret;
376 process.mode = GRD_SYNC_MODE_INVALID;
377 process.cloudDB = nullptr;
378 process.syncId = context->syncId;
379 SyncCallbackFunc(&process);
380 return ERR;
381 }
382 return OK;
383 };
384 }
385
CloudSync(napi_env env,napi_callback_info info)386 napi_value CollaborationEditObject::CloudSync(napi_env env, napi_callback_info info)
387 {
388 LOG_DEBUG("CloudSync start.");
389 auto context = std::make_shared<SyncContext>();
390 auto input = CollaborationEditObject::GetCloudSyncInput(context);
391 // create cloudSync execute function
392 auto exec = GetCloudSyncExec(context);
393 // create cloudSync output function
394 auto output = [context](napi_env env, napi_value &result) {
395 LOG_DEBUG("CollaborationEditObject::CloudSync output.");
396 if (context->execCode_ != OK) {
397 SyncService::GetInstance()->RemoveSyncContext(context->syncId);
398 }
399 };
400 // parse napi info and register exec/output functions to context
401 int ret = context->SetAll(env, info, input, exec, output);
402 if (ret != OK) {
403 ThrowNapiError(env, Status::INVALID_ARGUMENT, "parse params go wrong");
404 return nullptr;
405 }
406 // register cloudSync task to napi queue
407 ret = AsyncCall::Call(env, context, SYNC_FUNCTION_NAME);
408 if (ret != OK) {
409 if (context->callback_ != nullptr) {
410 napi_release_threadsafe_function(context->callback_, napi_tsfn_release);
411 context->callback_ = nullptr;
412 }
413 context->ReleaseInnerReference();
414 context.reset();
415 ThrowNapiError(env, Status::INTERNAL_ERROR, "register sync task go wrong");
416 }
417 return nullptr;
418 }
419
GetGRDSyncMode(int32_t mode)420 GRD_SyncModeE CollaborationEditObject::GetGRDSyncMode(int32_t mode)
421 {
422 SyncMode syncMode = static_cast<SyncMode>(mode);
423 auto it = SYNC_MODE_MAP.find(syncMode);
424 if (it == SYNC_MODE_MAP.end()) {
425 return GRD_SYNC_MODE_INVALID;
426 }
427 return it->second;
428 }
429
GetProgressCode(int32_t errCode)430 ProgressCode CollaborationEditObject::GetProgressCode(int32_t errCode)
431 {
432 switch (errCode) {
433 case GRD_OK:
434 return ProgressCode::CLOUD_SYNC_SUCCESS;
435 case GRD_SYNC_PREREQUISITES_ABNORMAL:
436 return ProgressCode::CLOUD_NOT_SET;
437 case GRD_INNER_ERR:
438 return ProgressCode::SYNC_INTERNAL_ERROR;
439 default:
440 break;
441 }
442 return ProgressCode::SYNC_EXTERNAL_ERROR;
443 }
444
SyncCallbackFunc(GRD_SyncProcessT * syncProcess)445 void CollaborationEditObject::SyncCallbackFunc(GRD_SyncProcessT *syncProcess)
446 {
447 LOG_INFO("syncId=%{public}" PRIu64 " status=%{public}d, errCode=%{public}d.",
448 syncProcess->syncId, syncProcess->status, syncProcess->errCode);
449
450 // call arkTs callback
451 std::shared_ptr<SyncService> syncService = SyncService::GetInstance();
452 std::shared_ptr<SyncContext> context = syncService->GetSyncContext(syncProcess->syncId);
453 syncService->RemoveSyncContext(syncProcess->syncId);
454 if (context == nullptr) {
455 LOG_ERROR("context is null");
456 return;
457 }
458 napi_threadsafe_function js_cb = context->callback_;
459 context->callback_ = nullptr;
460 context->ReleaseInnerReference();
461 if (js_cb == nullptr) {
462 LOG_ERROR("callback is null");
463 return;
464 }
465
466 napi_status ret = napi_acquire_threadsafe_function(js_cb);
467 if (ret != napi_ok) {
468 LOG_ERROR("acquire thread safe function failed, ret: %{public}d", static_cast<int32_t>(ret));
469 napi_release_threadsafe_function(js_cb, napi_tsfn_release);
470 return;
471 }
472 SyncCallbackParamT param = {};
473 param.detail.code = CollaborationEditObject::GetProgressCode(syncProcess->errCode);
474 param.syncContext = context;
475 context.reset();
476
477 std::future<int> future = param.promise.get_future();
478 ret = napi_call_threadsafe_function(js_cb, ¶m, napi_tsfn_blocking);
479 if (ret != napi_ok) {
480 LOG_ERROR("call function go wrong, ret=%{public}d", static_cast<int32_t>(ret));
481 napi_release_threadsafe_function(js_cb, napi_tsfn_release);
482 return;
483 }
484 std::future_status fstatus = future.wait_for(std::chrono::duration_cast<std::chrono::seconds>(TIME_THRESHOLD));
485 if (fstatus == std::future_status::ready) {
486 future.get();
487 } else {
488 LOG_ERROR("wait for js callback timeout");
489 }
490
491 napi_release_threadsafe_function(js_cb, napi_tsfn_release);
492 LOG_INFO("syncCallback end");
493 }
494
SetDBStore(std::shared_ptr<DBStore> dbStore)495 void CollaborationEditObject::SetDBStore(std::shared_ptr<DBStore> dbStore)
496 {
497 this->dbStore_ = dbStore;
498 }
499
GetDBStore()500 std::shared_ptr<DBStore> CollaborationEditObject::GetDBStore()
501 {
502 return this->dbStore_;
503 }
504
GetLocalId(napi_env env,napi_callback_info info)505 napi_value CollaborationEditObject::GetLocalId(napi_env env, napi_callback_info info)
506 {
507 napi_value self = nullptr;
508 NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &self, nullptr));
509 CollaborationEditObject *editObject = nullptr;
510 napi_status status = napi_unwrap(env, self, reinterpret_cast<void **>(&editObject));
511 ASSERT_THROW(env, status == napi_ok, status, "unwrap object go wrong");
512 std::string localId = (*editObject->dbStore_).GetLocalId();
513 napi_value result;
514 NapiUtils::SetValue(env, localId, result);
515 return result;
516 }
517
ApplyUpdate(napi_env env,napi_callback_info info)518 napi_value CollaborationEditObject::ApplyUpdate(napi_env env, napi_callback_info info)
519 {
520 napi_value self = nullptr;
521 NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &self, nullptr));
522 CollaborationEditObject *editObject = nullptr;
523 napi_status status = napi_unwrap(env, self, reinterpret_cast<void **>(&editObject));
524 ASSERT_THROW(env, status == napi_ok, status, "unwrap object go wrong");
525
526 std::string applyInfo;
527 int32_t ret = (*editObject->dbStore_).ApplyUpdate(applyInfo);
528 ASSERT_THROW(env, ret == OK, ret, "ApplyUpdate go wrong");
529 napi_value result;
530 ret = Parser::ParseJsonStrToJsUpdateNode(env, applyInfo, editObject->dbStore_, result);
531 ASSERT_THROW(env, ret == OK, ret, "ParseJsonStrToJsUpdateNode go wrong");
532 return result;
533 }
534
WriteUpdate(napi_env env,napi_callback_info info)535 napi_value CollaborationEditObject::WriteUpdate(napi_env env, napi_callback_info info)
536 {
537 size_t argc = 3;
538 napi_value argv[3] = {nullptr};
539 napi_value self = nullptr;
540 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &self, nullptr));
541 CollaborationEditObject *editObject = nullptr;
542 napi_status status = napi_unwrap(env, self, reinterpret_cast<void **>(&editObject));
543 ASSERT_THROW(env, status == napi_ok, status, "unwrap object go wrong");
544
545 std::string equipId;
546 status = NapiUtils::GetNamedProperty(env, argv[0], "id", equipId);
547 ASSERT_THROW(env, status == napi_ok, Status::INVALID_ARGUMENT, "read equipId param go wrong");
548
549 std::vector<uint8_t> data;
550 status = NapiUtils::GetNamedProperty(env, argv[0], "data", data);
551 ASSERT_THROW(env, status == napi_ok, Status::INVALID_ARGUMENT, "read data param go wrong");
552
553 int64_t watermark;
554 status = NapiUtils::GetNamedProperty(env, argv[0], "cursor", watermark);
555 ASSERT_THROW(env, status == napi_ok, Status::INVALID_ARGUMENT, "read cursor param go wrong");
556
557 int32_t ret =
558 (*editObject->dbStore_).WriteUpdate(equipId.c_str(), data.data(), data.size(), std::to_string(watermark));
559 ASSERT_THROW(env, ret == OK, ret, "WriteUpdate go wrong");
560 return nullptr;
561 }
562 } // namespace OHOS::CollaborationEdit
563