• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "GdbStoreProxy"
16 #include "napi_gdb_store.h"
17 
18 #include <algorithm>
19 #include <cinttypes>
20 #include <cstdint>
21 #include <vector>
22 
23 #include "db_trace.h"
24 #include "js_utils.h"
25 #include "logger.h"
26 #include "napi_gdb_context.h"
27 #include "napi_gdb_error.h"
28 #include "napi_gdb_js_utils.h"
29 #include "napi_gdb_transaction.h"
30 
31 namespace OHOS::GraphStoreJsKit {
32 
GdbStoreProxy()33 GdbStoreProxy::GdbStoreProxy()
34 {
35 }
36 
~GdbStoreProxy()37 GdbStoreProxy::~GdbStoreProxy()
38 {
39 }
40 
GdbStoreProxy(std::shared_ptr<DBStore> gdbStore)41 GdbStoreProxy::GdbStoreProxy(std::shared_ptr<DBStore> gdbStore)
42 {
43     if (GetInstance() == gdbStore) {
44         return;
45     }
46     SetInstance(std::move(gdbStore));
47 }
48 
operator =(std::shared_ptr<DBStore> gdbStore)49 GdbStoreProxy &GdbStoreProxy::operator=(std::shared_ptr<DBStore> gdbStore)
50 {
51     if (GetInstance() == gdbStore) {
52         return *this;
53     }
54     SetInstance(std::move(gdbStore));
55     return *this;
56 }
57 
IsSystemAppCalled()58 bool GdbStoreProxy::IsSystemAppCalled()
59 {
60     return isSystemAppCalled_;
61 }
62 
GetDescriptors()63 Descriptor GdbStoreProxy::GetDescriptors()
64 {
65     return []() -> std::vector<napi_property_descriptor> {
66         std::vector<napi_property_descriptor> properties = {
67             DECLARE_NAPI_FUNCTION("read", Read),
68             DECLARE_NAPI_FUNCTION("write", Write),
69             DECLARE_NAPI_FUNCTION("createTransaction", CreateTransaction),
70             DECLARE_NAPI_FUNCTION("close", Close),
71         };
72         return properties;
73     };
74 }
75 
Init(napi_env env,napi_value exports)76 void GdbStoreProxy::Init(napi_env env, napi_value exports)
77 {
78     auto jsCtor = OHOS::AppDataMgrJsKit::JSUtils::DefineClass(
79         env, "ohos.data.graphStore", "GraphStore", GetDescriptors(), Initialize);
80     NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, exports, "GraphStore", jsCtor));
81 }
82 
Destructor(napi_env env,void * nativeObject,void * finalize_hint)83 void GdbStoreProxy::Destructor(napi_env env, void *nativeObject, void *finalize_hint)
84 {
85     auto *obj = static_cast<GdbStoreProxy *>(nativeObject);
86     delete obj;
87 }
88 
New(napi_env env,napi_callback_info info)89 napi_value GdbStoreProxy::New(napi_env env, napi_callback_info info)
90 {
91     size_t argc = 1;
92     napi_value argv[1] = { 0 };
93     napi_value thisVar = nullptr;
94     napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
95 
96     // get native object
97     auto *obj = new GdbStoreProxy();
98     ASSERT_CALL(env,
99         napi_wrap(env, thisVar, obj, GdbStoreProxy::Destructor,
100             nullptr, // finalize_hint
101             nullptr),
102         obj);
103     return thisVar;
104 }
105 
Initialize(napi_env env,napi_callback_info info)106 napi_value GdbStoreProxy::Initialize(napi_env env, napi_callback_info info)
107 {
108     napi_value self = nullptr;
109     NAPI_CALL(env, napi_get_cb_info(env, info, NULL, NULL, &self, nullptr));
110     auto finalize = [](napi_env env, void *data, void *hint) {
111         if (data != hint) {
112             LOG_ERROR("GdbStoreProxy memory corrupted! data:0x%016" PRIXPTR "hint:0x%016" PRIXPTR, uintptr_t(data),
113                 uintptr_t(hint));
114             return;
115         }
116         GdbStoreProxy *proxy = reinterpret_cast<GdbStoreProxy *>(data);
117         proxy->SetInstance(nullptr);
118         delete proxy;
119     };
120     auto *proxy = new (std::nothrow) GdbStoreProxy();
121     if (proxy == nullptr) {
122         return nullptr;
123     }
124     napi_status status = napi_wrap(env, self, proxy, finalize, proxy, nullptr);
125     if (status != napi_ok) {
126         LOG_ERROR("GdbStoreProxy napi_wrap failed! code:%{public}d!", status);
127         finalize(env, proxy, proxy);
128         return nullptr;
129     }
130     return self;
131 }
132 
NewInstance(napi_env env,std::shared_ptr<DBStore> value,bool isSystemAppCalled)133 napi_value GdbStoreProxy::NewInstance(napi_env env, std::shared_ptr<DBStore> value, bool isSystemAppCalled)
134 {
135     if (value == nullptr) {
136         LOG_ERROR("dbstore is nullptr");
137         return nullptr;
138     }
139     napi_value cons = OHOS::AppDataMgrJsKit::JSUtils::GetClass(env, "ohos.data.graphStore", "GraphStore");
140     if (cons == nullptr) {
141         LOG_ERROR("Constructor of ResultSet is nullptr!");
142         return nullptr;
143     }
144 
145     napi_value instance = nullptr;
146     auto status = napi_new_instance(env, cons, 0, nullptr, &instance);
147     if (status != napi_ok) {
148         LOG_ERROR("GdbStoreProxy::NewInstance napi_new_instance failed! code:%{public}d!", status);
149         return nullptr;
150     }
151 
152     GdbStoreProxy *proxy = nullptr;
153     status = napi_unwrap(env, instance, reinterpret_cast<void **>(&proxy));
154     if (proxy == nullptr) {
155         LOG_ERROR("GdbStoreProxy::NewInstance native instance is nullptr! code:%{public}d!", status);
156         return instance;
157     }
158     proxy->queue_ = std::make_shared<AppDataMgrJsKit::UvQueue>(env);
159     proxy->SetInstance(std::move(value));
160     proxy->isSystemAppCalled_ = isSystemAppCalled;
161     return instance;
162 }
163 
GetNativeInstance(napi_env env,napi_value self)164 GdbStoreProxy *GetNativeInstance(napi_env env, napi_value self)
165 {
166     GdbStoreProxy *proxy = nullptr;
167     napi_status status = napi_unwrap(env, self, reinterpret_cast<void **>(&proxy));
168     if (proxy == nullptr) {
169         LOG_ERROR("GdbStoreProxy native instance is nullptr! code:%{public}d!", status);
170         return nullptr;
171     }
172     return proxy;
173 }
174 
ParseThis(const napi_env & env,const napi_value & self,const std::shared_ptr<GdbStoreContextBase> & context)175 int ParseThis(const napi_env &env, const napi_value &self, const std::shared_ptr<GdbStoreContextBase> &context)
176 {
177     GdbStoreProxy *obj = GetNativeInstance(env, self);
178     CHECK_RETURN_SET(obj != nullptr, std::make_shared<ParamError>("GdbStore", "not nullptr."));
179     CHECK_RETURN_SET(obj->GetInstance() != nullptr, std::make_shared<InnerError>(E_GRD_DB_INSTANCE_ABNORMAL));
180     context->boundObj = obj;
181     context->gdbStore = obj->GetInstance();
182     return OK;
183 }
184 
ParseGql(const napi_env env,const napi_value arg,const std::shared_ptr<GdbStoreContext> & context)185 int ParseGql(const napi_env env, const napi_value arg, const std::shared_ptr<GdbStoreContext> &context)
186 {
187     context->gql = OHOS::AppDataMgrJsKit::JSUtils::Convert2String(env, arg);
188     CHECK_RETURN_SET(!context->gql.empty(), std::make_shared<ParamError>("gql", "not empty"));
189     CHECK_RETURN_SET(context->gql.size() <= GdbStoreProxy::MAX_GQL_LEN,
190         std::make_shared<ParamError>("gql", "too long"));
191     return OK;
192 }
193 
Read(napi_env env,napi_callback_info info)194 napi_value GdbStoreProxy::Read(napi_env env, napi_callback_info info)
195 {
196     DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__));
197     auto context = std::make_shared<GdbStoreContext>();
198     auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) {
199         CHECK_RETURN_SET_E(argc == 1, std::make_shared<ParamNumError>(" 1 "));
200         CHECK_RETURN(OK == ParseThis(env, self, context));
201         CHECK_RETURN(OK == ParseGql(env, argv[0], context));
202     };
203     auto exec = [context]() -> int {
204         CHECK_RETURN_ERR(context->gdbStore != nullptr);
205         auto queryResult = context->StealGdbStore()->QueryGql(context->gql);
206         context->result = queryResult.second;
207         context->intOutput = queryResult.first;
208         return OK;
209     };
210     auto output = [context](napi_env env, napi_value &result) {
211         result = AppDataMgrJsKit::JSUtils::Convert2JSValue(env, context->result);
212         CHECK_RETURN_SET_E(context->intOutput == OK, std::make_shared<InnerError>(context->intOutput));
213     };
214     context->SetAction(env, info, input, exec, output);
215     CHECK_RETURN_NULL(context->error == nullptr || context->error->GetCode() == OK);
216     return ASYNC_CALL(env, context);
217 }
218 
Write(napi_env env,napi_callback_info info)219 napi_value GdbStoreProxy::Write(napi_env env, napi_callback_info info)
220 {
221     DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__));
222     auto context = std::make_shared<GdbStoreContext>();
223     auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) {
224         CHECK_RETURN_SET_E(argc == 1, std::make_shared<ParamNumError>(" 1 "));
225         CHECK_RETURN(OK == ParseThis(env, self, context));
226         CHECK_RETURN(OK == ParseGql(env, argv[0], context));
227     };
228     auto exec = [context]() -> int {
229         CHECK_RETURN_ERR(context->gdbStore != nullptr);
230         auto executeResult = context->StealGdbStore()->ExecuteGql(context->gql);
231         context->result = executeResult.second;
232         context->intOutput = executeResult.first;
233         return OK;
234     };
235     auto output = [context](napi_env env, napi_value &result) {
236         result = AppDataMgrJsKit::JSUtils::Convert2JSValue(env, context->result);
237         CHECK_RETURN_SET_E(context->intOutput == OK, std::make_shared<InnerError>(context->intOutput));
238     };
239     context->SetAction(env, info, input, exec, output);
240     CHECK_RETURN_NULL(context->error == nullptr || context->error->GetCode() == OK);
241     return ASYNC_CALL(env, context);
242 }
243 
CreateTransaction(napi_env env,napi_callback_info info)244 napi_value GdbStoreProxy::CreateTransaction(napi_env env, napi_callback_info info)
245 {
246     DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__));
247     auto context = std::make_shared<CreateTransactionContext>();
248     auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) {
249         CHECK_RETURN_SET_E(argc == 0, std::make_shared<ParamNumError>(" 0 "));
250         CHECK_RETURN(OK == ParseThis(env, self, context));
251     };
252     auto exec = [context]() -> int {
253         CHECK_RETURN_ERR(context->gdbStore != nullptr);
254         int32_t code = E_ERROR;
255         std::tie(code, context->transaction) = context->StealGdbStore()->CreateTransaction();
256         if (code != E_OK) {
257             context->transaction = nullptr;
258             return code;
259         }
260         return context->transaction != nullptr ? OK : E_ERROR;
261     };
262     auto output = [context](napi_env env, napi_value &result) {
263         result = GdbTransactionProxy::NewInstance(env, context->transaction);
264         CHECK_RETURN_SET_E(result != nullptr, std::make_shared<InnerError>(E_INNER_ERROR));
265     };
266     context->SetAction(env, info, input, exec, output);
267     CHECK_RETURN_NULL(context->error == nullptr || context->error->GetCode() == OK);
268     return ASYNC_CALL(env, context);
269 }
270 
Close(napi_env env,napi_callback_info info)271 napi_value GdbStoreProxy::Close(napi_env env, napi_callback_info info)
272 {
273     DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__));
274     auto context = std::make_shared<GdbStoreContext>();
275     auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) {
276         GdbStoreProxy *proxy = GetNativeInstance(env, self);
277         CHECK_RETURN_SET(proxy != nullptr, std::make_shared<ParamError>("GdbStore", "not nullptr."));
278         if (proxy->GetInstance() == nullptr) {
279             LOG_WARN("GdbStoreProxy native instance is nullptr!");
280             return OK;
281         }
282         context->boundObj = proxy;
283         context->gdbStore = proxy->GetInstance();
284 
285         auto *obj = reinterpret_cast<GdbStoreProxy *>(context->boundObj);
286         obj->SetInstance(nullptr);
287         return OK;
288     };
289     auto exec = [context]() -> int {
290         context->gdbStore = nullptr;
291         return OK;
292     };
293     auto output = [context](napi_env env, napi_value &result) {
294         napi_status status = napi_get_undefined(env, &result);
295         CHECK_RETURN_SET_E(status == napi_ok, std::make_shared<InnerError>(E_ERROR));
296     };
297     context->SetAction(env, info, input, exec, output);
298     CHECK_RETURN_NULL(context->error == nullptr || context->error->GetCode() == OK);
299     return ASYNC_CALL(env, context);
300 }
301 } // namespace OHOS::GraphStoreJsKit