• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2025 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 #include "napi_app_event_holder.h"
16 
17 #include <cinttypes>
18 
19 #include "app_event_store.h"
20 #include "app_event_util.h"
21 #include "hilog/log.h"
22 #include "napi_error.h"
23 #include "napi_util.h"
24 
25 #undef LOG_DOMAIN
26 #define LOG_DOMAIN 0xD002D07
27 
28 #undef LOG_TAG
29 #define LOG_TAG "NapiHolder"
30 
31 namespace OHOS {
32 namespace HiviewDFX {
33 namespace {
34 constexpr size_t PARAM_NUM = 1;
35 constexpr int DEFAULT_ROW_NUM = 1;
36 constexpr int DEFAULT_SIZE = 512 * 1024; // 512 * 1024: 512KB
37 const std::string HOLDER_CLASS_NAME = "AppEventPackageHolder";
38 
GetObserverSeqByName(const std::string & name)39 int64_t GetObserverSeqByName(const std::string& name)
40 {
41     int64_t observerSeq = -1;
42     if (observerSeq = AppEventStore::GetInstance().QueryObserverSeq(name); observerSeq <= 0) {
43         HILOG_WARN(LOG_CORE, "failed to query seq by name=%{public}s", name.c_str());
44         return -1;
45     }
46     return observerSeq;
47 }
48 }
49 thread_local napi_ref NapiAppEventHolder::constructor_ = nullptr;
50 
NapiAppEventHolder(const std::string & name,int64_t observerSeq)51 NapiAppEventHolder::NapiAppEventHolder(const std::string& name, int64_t observerSeq)
52     : name_(name), observerSeq_(observerSeq), hasSetRow_(false), hasSetSize_(false)
53 {
54     takeRow_ = DEFAULT_ROW_NUM;
55     takeSize_ = DEFAULT_SIZE;
56     packageId_ = 0; // id is incremented from 0
57 
58     // if the seq is invalid, need to get seq by the name(for js constructor)
59     if (observerSeq_ <= 0) {
60         observerSeq_ = GetObserverSeqByName(name_);
61     }
62 }
63 
NapiConstructor(napi_env env,napi_callback_info info)64 napi_value NapiAppEventHolder::NapiConstructor(napi_env env, napi_callback_info info)
65 {
66     size_t paramNum = PARAM_NUM;
67     napi_value params[PARAM_NUM] = { 0 };
68     napi_value thisVar = nullptr;
69     NAPI_CALL(env, napi_get_cb_info(env, info, &paramNum, params, &thisVar, nullptr));
70 
71     if (paramNum < PARAM_NUM) {
72         HILOG_ERROR(LOG_CORE, "hodler failed to construct: invalid param num");
73         return thisVar;
74     }
75     auto holder = new(std::nothrow) NapiAppEventHolder(NapiUtil::GetString(env, params[0]));
76     if (holder == nullptr) {
77         return thisVar;
78     }
79     napi_wrap(
80         env, thisVar, holder,
81         [](napi_env env, void* data, void* hint) {
82             NapiAppEventHolder* holder = (NapiAppEventHolder*)data;
83             delete holder;
84         },
85         nullptr, nullptr);
86     return thisVar;
87 }
88 
NapiExport(napi_env env,napi_value exports)89 napi_value NapiAppEventHolder::NapiExport(napi_env env, napi_value exports)
90 {
91     napi_property_descriptor properties[] = {
92         DECLARE_NAPI_FUNCTION("setRow", NapiSetRow),
93         DECLARE_NAPI_FUNCTION("setSize", NapiSetSize),
94         DECLARE_NAPI_FUNCTION("takeNext", NapiTakeNext)
95     };
96     napi_value holderClass = nullptr;
97     napi_define_class(env, HOLDER_CLASS_NAME.c_str(), HOLDER_CLASS_NAME.size(), NapiConstructor, nullptr,
98         sizeof(properties) / sizeof(properties[0]), properties, &holderClass);
99     NapiUtil::SetNamedProperty(env, exports, HOLDER_CLASS_NAME, holderClass);
100     constructor_ = NapiUtil::CreateReference(env, holderClass);
101     return exports;
102 }
103 
NapiSetRow(napi_env env,napi_callback_info info)104 napi_value NapiAppEventHolder::NapiSetRow(napi_env env, napi_callback_info info)
105 {
106     size_t paramNum = PARAM_NUM;
107     napi_value params[PARAM_NUM] = { 0 };
108     napi_value thisVar = nullptr;
109     NAPI_CALL(env, napi_get_cb_info(env, info, &paramNum, params, &thisVar, nullptr));
110     if (paramNum < PARAM_NUM) {
111         NapiUtil::ThrowError(env, NapiError::ERR_PARAM, NapiUtil::CreateErrMsg("size"));
112         return nullptr;
113     }
114     if (!NapiUtil::IsNumber(env, params[0])) {
115         NapiUtil::ThrowError(env, NapiError::ERR_PARAM, NapiUtil::CreateErrMsg("size", "number"));
116         return nullptr;
117     }
118     int num = NapiUtil::GetInt32(env, params[0]);
119     if (num <= 0) {
120         NapiUtil::ThrowErrorMsg(env, NapiError::ERR_INVALID_SIZE);
121         return NapiUtil::CreateUndefined(env);
122     }
123     NapiAppEventHolder* holder = nullptr;
124     if (napi_unwrap(env, thisVar, (void**)&holder) != napi_ok || holder == nullptr) {
125         return nullptr;
126     }
127     holder->SetRow(num);
128     return NapiUtil::CreateUndefined(env);
129 }
130 
NapiSetSize(napi_env env,napi_callback_info info)131 napi_value NapiAppEventHolder::NapiSetSize(napi_env env, napi_callback_info info)
132 {
133     size_t paramNum = PARAM_NUM;
134     napi_value params[PARAM_NUM] = { 0 };
135     napi_value thisVar = nullptr;
136     NAPI_CALL(env, napi_get_cb_info(env, info, &paramNum, params, &thisVar, nullptr));
137     if (paramNum < PARAM_NUM) {
138         NapiUtil::ThrowError(env, NapiError::ERR_PARAM, NapiUtil::CreateErrMsg("size"));
139         return nullptr;
140     }
141     if (!NapiUtil::IsNumber(env, params[0])) {
142         NapiUtil::ThrowError(env, NapiError::ERR_PARAM, NapiUtil::CreateErrMsg("size", "number"));
143         return nullptr;
144     }
145     int num = NapiUtil::GetInt32(env, params[0]);
146     if (num < 0) {
147         NapiUtil::ThrowErrorMsg(env, NapiError::ERR_INVALID_SIZE);
148         return NapiUtil::CreateUndefined(env);
149     }
150     NapiAppEventHolder* holder = nullptr;
151     if (napi_unwrap(env, thisVar, (void**)&holder) != napi_ok || holder == nullptr) {
152         return nullptr;
153     }
154     holder->SetSize(num);
155     return NapiUtil::CreateUndefined(env);
156 }
157 
NapiTakeNext(napi_env env,napi_callback_info info)158 napi_value NapiAppEventHolder::NapiTakeNext(napi_env env, napi_callback_info info)
159 {
160     napi_value thisVar = nullptr;
161     NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr));
162     NapiAppEventHolder* holder = nullptr;
163     if (napi_unwrap(env, thisVar, (void**)&holder) != napi_ok || holder == nullptr) {
164         return NapiUtil::CreateNull(env);
165     }
166     auto package = holder->TakeNext();
167     if (package == nullptr) {
168         return NapiUtil::CreateNull(env);
169     }
170     AppEventUtil::ReportAppEventReceive(package->events, holder->name_, "takeNext");
171     napi_value packageObj = NapiUtil::CreateObject(env);
172     NapiUtil::SetNamedProperty(env, packageObj, "packageId", NapiUtil::CreateInt32(env, package->packageId));
173     NapiUtil::SetNamedProperty(env, packageObj, "row", NapiUtil::CreateInt32(env, package->row));
174     NapiUtil::SetNamedProperty(env, packageObj, "size", NapiUtil::CreateInt32(env, package->size));
175     NapiUtil::SetNamedProperty(env, packageObj, "data", NapiUtil::CreateStrings(env, package->data));
176     NapiUtil::SetNamedProperty(env, packageObj, "appEventInfos", NapiUtil::CreateEventInfoArray(env, package->events));
177     return packageObj;
178 }
179 
SetRow(int row)180 void NapiAppEventHolder::SetRow(int row)
181 {
182     HILOG_INFO(LOG_CORE, "hodler seq=%{public}" PRId64 " set row=%{public}d", observerSeq_, row);
183     takeRow_ = row;
184     hasSetRow_ = true;
185 }
186 
SetSize(int size)187 void NapiAppEventHolder::SetSize(int size)
188 {
189     HILOG_INFO(LOG_CORE, "hodler seq=%{public}" PRId64 " set size=%{public}d", observerSeq_, size);
190     takeSize_ = size;
191     hasSetSize_ = true;
192 }
193 
TakeNext()194 std::shared_ptr<AppEventPackage> NapiAppEventHolder::TakeNext()
195 {
196     std::vector<std::shared_ptr<AppEventPack>> events;
197     bool shouldTakeSize = hasSetSize_ && !hasSetRow_;
198     int rowNum = shouldTakeSize ? 0 : takeRow_;
199     if (AppEventStore::GetInstance().QueryEvents(events, observerSeq_, rowNum) != 0) {
200         HILOG_WARN(LOG_CORE, "failed to query events, seq=%{public}" PRId64, observerSeq_);
201         return nullptr;
202     }
203     if (events.empty()) {
204         HILOG_DEBUG(LOG_CORE, "end to query events, seq=%{public}" PRId64, observerSeq_);
205         return nullptr;
206     }
207 
208     std::vector<int64_t> eventSeqs;
209     std::vector<std::string> eventStrs;
210     size_t totalSize = 0;
211     auto package = std::make_shared<AppEventPackage>();
212     for (auto event : events) {
213         std::string eventStr = event->GetEventStr();
214         if (shouldTakeSize && static_cast<int>(totalSize + eventStr.size()) > takeSize_) {
215             HILOG_INFO(LOG_CORE, "stop to take data, totalSize=%{public}zu, takeSize=%{public}d",
216                 totalSize, takeSize_);
217             break;
218         }
219         totalSize += eventStr.size();
220         eventStrs.emplace_back(eventStr);
221         eventSeqs.emplace_back(event->GetSeq());
222         package->events.emplace_back(event);
223     }
224     if (eventStrs.empty()) {
225         HILOG_INFO(LOG_CORE, "take data is empty, seq=%{public}" PRId64, observerSeq_);
226         return nullptr;
227     }
228     if (!AppEventStore::GetInstance().DeleteData(observerSeq_, eventSeqs)) {
229         HILOG_INFO(LOG_CORE, "failed to delete mapping data, seq=%{public}" PRId64, observerSeq_);
230         return nullptr;
231     }
232 
233     package->packageId = packageId_++;
234     package->row = static_cast<int>(eventStrs.size());
235     package->size = static_cast<int>(totalSize);
236     package->data = eventStrs;
237     return package;
238 }
239 } // namespace HiviewDFX
240 } // namespace OHOS
241