1 /*
2 * Copyright (c) 2021 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
16 #include "htrace_parser.h"
17 #include <unistd.h>
18 #include "binder_filter.h"
19 #include "cpu_filter.h"
20 #include "ftrace_event.pb.h"
21 #include "log.h"
22 #include "memory_plugin_result.pb.h"
23 #include "services/common_types.pb.h"
24 #include "stat_filter.h"
25 #include "trace_plugin_result.pb.h"
26 #if IS_WASM
27 #include "../rpc/wasm_func.h"
28 #endif
29 namespace SysTuning {
30 namespace TraceStreamer {
HtraceParser(TraceDataCache * dataCache,const TraceStreamerFilters * filters)31 HtraceParser::HtraceParser(TraceDataCache* dataCache, const TraceStreamerFilters* filters)
32 : ParserBase(filters),
33 traceDataCache_(dataCache),
34 htraceCpuDetailParser_(std::make_unique<HtraceCpuDetailParser>(dataCache, filters)),
35 htraceSymbolsDetailParser_(std::make_unique<HtraceSymbolsDetailParser>(dataCache, filters)),
36 htraceMemParser_(std::make_unique<HtraceMemParser>(dataCache, filters)),
37 htraceClockDetailParser_(std::make_unique<HtraceClockDetailParser>(dataCache, filters)),
38 htraceHiLogParser_(std::make_unique<HtraceHiLogParser>(dataCache, filters)),
39 htraceNativeHookParser_(std::make_unique<HtraceNativeHookParser>(dataCache, filters)),
40 htraceHidumpParser_(std::make_unique<HtraceHidumpParser>(dataCache, filters)),
41 cpuUsageParser_(std::make_unique<HtraceCpuDataParser>(dataCache, filters)),
42 networkParser_(std::make_unique<HtraceNetworkParser>(dataCache, filters)),
43 diskIOParser_(std::make_unique<HtraceDiskIOParser>(dataCache, filters)),
44 processParser_(std::make_unique<HtraceProcessParser>(dataCache, filters)),
45 ebpfDataParser_(std::make_unique<EbpfDataParser>(dataCache, filters)),
46 hisyseventParser_(std::make_unique<HtraceHisyseventParser>(dataCache, filters))
47 {
48 #if WITH_PERF
49 perfDataParser_ = std::make_unique<PerfDataParser>(dataCache, filters);
50 #endif
51 #ifdef SUPPORTTHREAD
52 supportThread_ = true;
53 dataSegArray_ = std::make_unique<HtraceDataSegment[]>(MAX_SEG_ARRAY_SIZE);
54 #else
55 dataSegArray_ = std::make_unique<HtraceDataSegment[]>(1);
56 #endif
57 }
58
~HtraceParser()59 HtraceParser::~HtraceParser()
60 {
61 TS_LOGI("clockid 2 is for RealTime and 1 is for BootTime");
62 }
63
WaitForParserEnd()64 void HtraceParser::WaitForParserEnd()
65 {
66 if (parseThreadStarted_ || filterThreadStarted_) {
67 toExit_ = true;
68 while (!exited_) {
69 usleep(sleepDur_ * sleepDur_);
70 }
71 }
72 htraceCpuDetailParser_->FilterAllEvents();
73 htraceNativeHookParser_->FinishParseNativeHookData();
74 htraceHiLogParser_->Finish();
75 htraceMemParser_->Finish();
76 htraceNativeHookParser_->Finish();
77 htraceHidumpParser_->Finish();
78 cpuUsageParser_->Finish();
79 networkParser_->Finish();
80 processParser_->Finish();
81 diskIOParser_->Finish();
82 hisyseventParser_->Finish();
83 // keep final upate perf and ebpf data time range
84 ebpfDataParser_->Finish();
85 #if WITH_PERF
86 perfDataParser_->Finish();
87 #endif
88
89 traceDataCache_->GetDataSourceClockIdData()->SetDataSourceClockId(DATA_SOURCE_TYPE_TRACE,
90 dataSourceTypeTraceClockid_);
91 traceDataCache_->GetDataSourceClockIdData()->SetDataSourceClockId(DATA_SOURCE_TYPE_MEM, dataSourceTypeMemClockid_);
92 traceDataCache_->GetDataSourceClockIdData()->SetDataSourceClockId(DATA_SOURCE_TYPE_HILOG,
93 dataSourceTypeHilogClockid_);
94 traceDataCache_->GetDataSourceClockIdData()->SetDataSourceClockId(DATA_SOURCE_TYPE_ALLOCATION,
95 dataSourceTypeAllocationClockid_);
96 traceDataCache_->GetDataSourceClockIdData()->SetDataSourceClockId(DATA_SOURCE_TYPE_FPS, dataSourceTypeFpsClockid_);
97 traceDataCache_->GetDataSourceClockIdData()->SetDataSourceClockId(DATA_SOURCE_TYPE_NETWORK,
98 dataSourceTypeNetworkClockid_);
99 traceDataCache_->GetDataSourceClockIdData()->SetDataSourceClockId(DATA_SOURCE_TYPE_DISKIO,
100 dataSourceTypeDiskioClockid_);
101 traceDataCache_->GetDataSourceClockIdData()->SetDataSourceClockId(DATA_SOURCE_TYPE_CPU, dataSourceTypeCpuClockid_);
102 traceDataCache_->GetDataSourceClockIdData()->SetDataSourceClockId(DATA_SOURCE_TYPE_PROCESS,
103 dataSourceTypeProcessClockid_);
104 traceDataCache_->GetDataSourceClockIdData()->SetDataSourceClockId(DATA_SOURCE_TYPE_HISYSEVENT,
105 dataSourceTypeHisyseventClockid_);
106 traceDataCache_->GetDataSourceClockIdData()->Finish();
107 dataSegArray_.reset();
108 }
109
ParseTraceDataItem(const std::string & buffer)110 void HtraceParser::ParseTraceDataItem(const std::string& buffer)
111 {
112 int head = rawDataHead_;
113 if (!supportThread_) {
114 dataSegArray_[head].seg = std::move(buffer);
115 dataSegArray_[head].status = TS_PARSE_STATUS_SEPRATED;
116 ParserData(dataSegArray_[head]);
117 return;
118 }
119 while (!toExit_) {
120 if (dataSegArray_[head].status.load() != TS_PARSE_STATUS_INIT) {
121 usleep(sleepDur_);
122 continue;
123 }
124 dataSegArray_[head].seg = std::move(buffer);
125 dataSegArray_[head].status = TS_PARSE_STATUS_SEPRATED;
126 rawDataHead_ = (rawDataHead_ + 1) % MAX_SEG_ARRAY_SIZE;
127 break;
128 }
129 if (!parseThreadStarted_) {
130 parseThreadStarted_ = true;
131 int tmp = maxThread_;
132 while (tmp--) {
133 parserThreadCount_++;
134 std::thread ParseTypeThread(&HtraceParser::ParseThread, this);
135 ParseTypeThread.detach();
136 TS_LOGD("parser Thread:%d/%d start working ...\n", maxThread_ - tmp, maxThread_);
137 }
138 }
139 }
FilterData(HtraceDataSegment & seg)140 void HtraceParser::FilterData(HtraceDataSegment& seg)
141 {
142 if (seg.dataType == DATA_SOURCE_TYPE_TRACE) {
143 if (seg.traceData->ftrace_cpu_detail_size()) {
144 htraceCpuDetailParser_->Parse(seg.traceData.get(), clock_); // has Event
145 }
146 if (seg.traceData->symbols_detail_size()) {
147 htraceSymbolsDetailParser_->Parse(seg.traceData.get()); // has Event
148 }
149 if (seg.traceData->clocks_detail_size()) {
150 htraceClockDetailParser_->Parse(seg.traceData.get()); // has Event
151 }
152 } else if (seg.dataType == DATA_SOURCE_TYPE_MEM) {
153 htraceMemParser_->Parse(seg.memData, seg.timeStamp, seg.clockId);
154 } else if (seg.dataType == DATA_SOURCE_TYPE_HILOG) {
155 htraceHiLogParser_->Parse(seg.logData);
156 } else if (seg.dataType == DATA_SOURCE_TYPE_ALLOCATION) {
157 htraceNativeHookParser_->SortNativeHookData(seg.batchNativeHookData);
158 } else if (seg.dataType == DATA_SOURCE_TYPE_FPS) {
159 htraceHidumpParser_->Parse(seg.hidumpInfo);
160 dataSourceTypeFpsClockid_ = htraceHidumpParser_->ClockId();
161 } else if (seg.dataType == DATA_SOURCE_TYPE_NETWORK) {
162 networkParser_->Parse(seg.networkInfo, seg.timeStamp);
163 } else if (seg.dataType == DATA_SOURCE_TYPE_CPU) {
164 cpuUsageParser_->Parse(seg.cpuInfo, seg.timeStamp);
165 } else if (seg.dataType == DATA_SOURCE_TYPE_PROCESS) {
166 processParser_->Parse(seg.processInfo, seg.timeStamp);
167 } else if (seg.dataType == DATA_SOURCE_TYPE_DISKIO) {
168 diskIOParser_->Parse(seg.diskIOInfo, seg.timeStamp);
169 } else if (seg.dataType == DATA_SOURCE_TYPE_HISYSEVENT) {
170 hisyseventParser_->Parse(seg.hisyseventInfo, seg.timeStamp);
171 }
172 if (supportThread_) {
173 filterHead_ = (filterHead_ + 1) % MAX_SEG_ARRAY_SIZE;
174 }
175 seg.status = TS_PARSE_STATUS_INIT;
176 }
FilterThread()177 void HtraceParser::FilterThread()
178 {
179 TS_LOGI("filter thread start work!");
180 while (1) {
181 HtraceDataSegment& seg = dataSegArray_[filterHead_];
182 if (seg.status.load() == TS_PARSE_STATUS_INVALID) {
183 seg.status = TS_PARSE_STATUS_INIT;
184 filterHead_ = (filterHead_ + 1) % MAX_SEG_ARRAY_SIZE;
185 streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_OTHER, STAT_EVENT_DATA_INVALID);
186 TS_LOGD("seprateHead_d:\t%d, parseHead_:\t%d, filterHead_:\t%d\n", rawDataHead_, parseHead_, filterHead_);
187 continue;
188 }
189 if (seg.status.load() != TS_PARSE_STATUS_PARSED) {
190 if (toExit_ && !parserThreadCount_) {
191 TS_LOGI("exiting Filter Thread");
192 exited_ = true;
193 filterThreadStarted_ = false;
194 TS_LOGI("seprateHead:\t%d, parseHead_:\t%d, filterHead_:\t%d, status:%d\n", rawDataHead_, parseHead_,
195 filterHead_, seg.status.load());
196 return;
197 }
198 TS_LOGD("seprateHead:\t%d, parseHead_:\t%d, filterHead_:\t%d, status:%d\n", rawDataHead_, parseHead_,
199 filterHead_, seg.status.load());
200 usleep(sleepDur_);
201 continue;
202 }
203 FilterData(seg);
204 }
205 }
206
ParserData(HtraceDataSegment & dataSeg)207 void HtraceParser::ParserData(HtraceDataSegment& dataSeg)
208 {
209 ProfilerPluginData pluginData;
210 if (!pluginData.ParseFromArray(dataSeg.seg.data(), static_cast<int>(dataSeg.seg.length()))) {
211 TS_LOGW("ProfilerPluginData ParseFromArray failed\n");
212 dataSeg.status = TS_PARSE_STATUS_INVALID;
213 return;
214 }
215 dataSeg.timeStamp = pluginData.tv_nsec() + pluginData.tv_sec() * SEC_TO_NS;
216 if (pluginData.name() == "memory-plugin") {
217 ParseMemory(pluginData, dataSeg);
218 } else if (pluginData.name() == "hilog-plugin" || pluginData.name() == "/data/local/tmp/libhilogplugin.z.so") {
219 ParseHilog(pluginData, dataSeg);
220 } else if (pluginData.name() == "ftrace-plugin" || pluginData.name() == "/data/local/tmp/libftrace_plugin.z.so") {
221 ParseFtrace(pluginData, dataSeg);
222 } else if (pluginData.name() == "nativehook" || pluginData.name() == "hookdaemon") {
223 ParseNativeHook(pluginData, dataSeg);
224 } else if (pluginData.name() == "hidump-plugin" || pluginData.name() == "/data/local/tmp/libhidumpplugin.z.so") {
225 ParseFPS(pluginData, dataSeg);
226 } else if (pluginData.name() == "cpu-plugin") {
227 ParseCpuUsage(pluginData, dataSeg);
228 } else if (pluginData.name() == "network-plugin") {
229 ParseNetwork(pluginData, dataSeg);
230 } else if (pluginData.name() == "diskio-plugin") {
231 ParseDiskIO(pluginData, dataSeg);
232 } else if (pluginData.name() == "process-plugin") {
233 ParseProcess(pluginData, dataSeg);
234 } else if (pluginData.name() == "hisysevent-plugin") {
235 ParseHisysevent(pluginData, dataSeg);
236 } else {
237 #if IS_WASM
238 TraceStreamer_Plugin_Out_Filter(pluginData.data().data(), pluginData.data().length(), pluginData.name());
239 #endif
240 dataSeg.status = TS_PARSE_STATUS_INVALID;
241 streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_OTHER, STAT_EVENT_DATA_INVALID);
242 return;
243 }
244 if (!supportThread_) { // do it only in wasm mode, wasm noThead_ will be true
245 FilterData(dataSeg);
246 }
247 }
ParseThread()248 void HtraceParser::ParseThread()
249 {
250 TS_LOGI("parser thread start work!\n");
251 while (1) {
252 if (supportThread_ && !filterThreadStarted_) {
253 filterThreadStarted_ = true;
254 std::thread ParserThread(&HtraceParser::FilterThread, this);
255 TS_LOGD("FilterThread start working ...\n");
256 ParserThread.detach();
257 }
258 int head = GetNextSegment();
259 if (head < 0) {
260 if (head == ERROR_CODE_EXIT) {
261 TS_LOGI("parse thread exit\n");
262 return;
263 } else if (head == ERROR_CODE_NODATA) {
264 continue;
265 }
266 }
267 HtraceDataSegment& dataSeg = dataSegArray_[head];
268 ParserData(dataSeg);
269 }
270 }
271
ParseMemory(const ProfilerPluginData & pluginData,HtraceDataSegment & dataSeg)272 void HtraceParser::ParseMemory(const ProfilerPluginData& pluginData, HtraceDataSegment& dataSeg)
273 {
274 dataSeg.dataType = DATA_SOURCE_TYPE_MEM;
275 BuiltinClocks clockId = TS_CLOCK_REALTIME;
276 auto clockIdTemp = pluginData.clock_id();
277 if (clockIdTemp == ProfilerPluginData_ClockId_CLOCKID_REALTIME) {
278 clockId = TS_CLOCK_REALTIME;
279 }
280 dataSourceTypeMemClockid_ = clockId;
281 dataSeg.memData.Clear();
282 if (!dataSeg.memData.ParseFromArray(pluginData.data().data(), static_cast<int>(pluginData.data().size()))) {
283 TS_LOGW("tracePacketParseFromArray failed\n");
284 dataSeg.status = TS_PARSE_STATUS_INVALID;
285 return;
286 }
287 if (dataSeg.memData.processesinfo_size()) {
288 dataSeg.dataType = DATA_SOURCE_TYPE_MEM;
289 dataSeg.clockId = clockId;
290 dataSeg.status = TS_PARSE_STATUS_PARSED;
291 } else if (dataSeg.memData.meminfo_size()) {
292 dataSeg.dataType = DATA_SOURCE_TYPE_MEM;
293 dataSeg.clockId = clockId;
294 dataSeg.status = TS_PARSE_STATUS_PARSED;
295 } else if (dataSeg.memData.vmeminfo_size()) {
296 dataSeg.dataType = DATA_SOURCE_TYPE_MEM;
297 dataSeg.clockId = clockId;
298 dataSeg.status = TS_PARSE_STATUS_PARSED;
299 } else {
300 dataSeg.status = TS_PARSE_STATUS_INVALID;
301 }
302 }
ParseHilog(const ProfilerPluginData & pluginData,HtraceDataSegment & dataSeg)303 void HtraceParser::ParseHilog(const ProfilerPluginData& pluginData, HtraceDataSegment& dataSeg)
304 {
305 dataSeg.dataType = DATA_SOURCE_TYPE_HILOG;
306 dataSourceTypeHilogClockid_ = TS_CLOCK_REALTIME;
307 if (!dataSeg.logData.ParseFromArray(pluginData.data().data(), static_cast<int>(pluginData.data().size()))) {
308 TS_LOGW("tracePacketParseFromArray failed\n");
309 dataSeg.status = TS_PARSE_STATUS_PARSED;
310 return;
311 }
312 if (dataSeg.logData.info_size()) {
313 dataSeg.status = TS_PARSE_STATUS_PARSED;
314 return;
315 }
316 dataSeg.status = TS_PARSE_STATUS_INVALID;
317 }
ParseFtrace(const ProfilerPluginData & pluginData,HtraceDataSegment & dataSeg)318 void HtraceParser::ParseFtrace(const ProfilerPluginData& pluginData, HtraceDataSegment& dataSeg)
319 {
320 dataSeg.dataType = DATA_SOURCE_TYPE_TRACE;
321 dataSeg.traceData = std::make_unique<TracePluginResult>();
322 if (!dataSeg.traceData->ParseFromArray(pluginData.data().data(), static_cast<int>(pluginData.data().size()))) {
323 TS_LOGW("tracePacketParseFromArray failed\n");
324 dataSeg.status = TS_PARSE_STATUS_INVALID;
325 return;
326 }
327 if (dataSeg.traceData->ftrace_cpu_stats_size()) {
328 auto cpuStats = dataSeg.traceData->ftrace_cpu_stats(0);
329 auto s = cpuStats.per_cpu_stats(0);
330 TS_LOGD("s.overrun():%lu", s.overrun());
331 TS_LOGD("s.dropped_events():%lu", s.dropped_events());
332 auto clock = cpuStats.trace_clock();
333 if (clock == "boot") {
334 clock_ = TS_CLOCK_BOOTTIME;
335 }
336 dataSeg.clockId = clock_;
337 dataSeg.status = TS_PARSE_STATUS_PARSED;
338 return;
339 }
340 dataSourceTypeTraceClockid_ = TS_CLOCK_BOOTTIME;
341 if (dataSeg.traceData->clocks_detail_size() || dataSeg.traceData->ftrace_cpu_detail_size() ||
342 dataSeg.traceData->symbols_detail_size()) {
343 dataSeg.status = TS_PARSE_STATUS_PARSED;
344 return;
345 }
346 dataSeg.status = TS_PARSE_STATUS_INVALID;
347 }
348
ParseNativeHook(const ProfilerPluginData & pluginData,HtraceDataSegment & dataSeg)349 void HtraceParser::ParseNativeHook(const ProfilerPluginData& pluginData, HtraceDataSegment& dataSeg)
350 {
351 dataSourceTypeAllocationClockid_ = TS_CLOCK_REALTIME;
352 dataSeg.dataType = DATA_SOURCE_TYPE_ALLOCATION;
353 if (!dataSeg.batchNativeHookData.ParseFromArray(pluginData.data().data(),
354 static_cast<int>(pluginData.data().size()))) {
355 TS_LOGW("tracePacketParseFromArray failed\n");
356 dataSeg.status = TS_PARSE_STATUS_INVALID;
357 return;
358 }
359 if (dataSeg.batchNativeHookData.events_size()) {
360 dataSeg.status = TS_PARSE_STATUS_PARSED;
361 return;
362 }
363 dataSeg.status = TS_PARSE_STATUS_INVALID;
364 }
365
ParseFPS(const ProfilerPluginData & pluginData,HtraceDataSegment & dataSeg)366 void HtraceParser::ParseFPS(const ProfilerPluginData& pluginData, HtraceDataSegment& dataSeg)
367 {
368 dataSeg.dataType = DATA_SOURCE_TYPE_FPS;
369 if (!dataSeg.hidumpInfo.ParseFromArray(pluginData.data().data(), static_cast<int>(pluginData.data().size()))) {
370 TS_LOGW("tracePacketParseFromArray failed\n");
371 dataSeg.status = TS_PARSE_STATUS_INVALID;
372 return;
373 }
374 if (dataSeg.hidumpInfo.fps_event_size()) {
375 dataSeg.status = TS_PARSE_STATUS_PARSED;
376 return;
377 }
378 dataSeg.status = TS_PARSE_STATUS_INVALID;
379 }
380
ParseCpuUsage(const ProfilerPluginData & pluginData,HtraceDataSegment & dataSeg)381 void HtraceParser::ParseCpuUsage(const ProfilerPluginData& pluginData, HtraceDataSegment &dataSeg)
382 {
383 dataSourceTypeProcessClockid_ = TS_CLOCK_REALTIME;
384 dataSeg.dataType = DATA_SOURCE_TYPE_CPU;
385 if (!dataSeg.cpuInfo.ParseFromArray(pluginData.data().data(), static_cast<int>(pluginData.data().size()))) {
386 streamFilters_->statFilter_->IncreaseStat(TRACE_CPU_USAGE, STAT_EVENT_DATA_INVALID);
387 TS_LOGW("tracePacketParseFromArray failed\n");
388 dataSeg.status = TS_PARSE_STATUS_INVALID;
389 return;
390 }
391 if (dataSeg.cpuInfo.has_cpu_usage_info() || dataSeg.cpuInfo.thread_info_size()) {
392 dataSeg.status = TS_PARSE_STATUS_PARSED;
393 return;
394 }
395 dataSeg.status = TS_PARSE_STATUS_INVALID;
396 }
ParseNetwork(const ProfilerPluginData & pluginData,HtraceDataSegment & dataSeg)397 void HtraceParser::ParseNetwork(const ProfilerPluginData& pluginData, HtraceDataSegment &dataSeg)
398 {
399 dataSourceTypeProcessClockid_ = TS_CLOCK_REALTIME;
400 dataSeg.dataType = DATA_SOURCE_TYPE_NETWORK;
401 if (!dataSeg.networkInfo.ParseFromArray(pluginData.data().data(), static_cast<int>(pluginData.data().size()))) {
402 streamFilters_->statFilter_->IncreaseStat(TRACE_NETWORK, STAT_EVENT_DATA_INVALID);
403 TS_LOGW("tracePacketParseFromArray failed\n");
404 dataSeg.status = TS_PARSE_STATUS_INVALID;
405 return;
406 }
407 dataSeg.status = TS_PARSE_STATUS_PARSED;
408 }
ParseDiskIO(const ProfilerPluginData & pluginData,HtraceDataSegment & dataSeg)409 void HtraceParser::ParseDiskIO(const ProfilerPluginData& pluginData, HtraceDataSegment &dataSeg)
410 {
411 dataSourceTypeProcessClockid_ = TS_CLOCK_REALTIME;
412 dataSeg.dataType = DATA_SOURCE_TYPE_DISKIO;
413 if (!dataSeg.diskIOInfo.ParseFromArray(pluginData.data().data(), static_cast<int>(pluginData.data().size()))) {
414 streamFilters_->statFilter_->IncreaseStat(TRACE_DISKIO, STAT_EVENT_DATA_INVALID);
415 TS_LOGW("tracePacketParseFromArray failed\n");
416 dataSeg.status = TS_PARSE_STATUS_INVALID;
417 return;
418 }
419 dataSeg.status = TS_PARSE_STATUS_PARSED;
420 }
421
ParseProcess(const ProfilerPluginData & pluginData,HtraceDataSegment & dataSeg)422 void HtraceParser::ParseProcess(const ProfilerPluginData& pluginData, HtraceDataSegment &dataSeg)
423 {
424 dataSourceTypeProcessClockid_ = TS_CLOCK_BOOTTIME;
425 dataSeg.dataType = DATA_SOURCE_TYPE_PROCESS;
426 if (!dataSeg.processInfo.ParseFromArray(pluginData.data().data(), static_cast<int>(pluginData.data().size()))) {
427 streamFilters_->statFilter_->IncreaseStat(TRACE_PROCESS, STAT_EVENT_DATA_INVALID);
428 TS_LOGW("tracePacketParseFromArray failed\n");
429 dataSeg.status = TS_PARSE_STATUS_INVALID;
430 return;
431 }
432 dataSeg.timeStamp = pluginData.tv_nsec() + pluginData.tv_sec() * SEC_TO_NS;
433 dataSeg.status = TS_PARSE_STATUS_PARSED;
434 }
435
ParseHisysevent(const ProfilerPluginData & pluginData,HtraceDataSegment & dataSeg)436 void HtraceParser::ParseHisysevent(const ProfilerPluginData& pluginData, HtraceDataSegment &dataSeg)
437 {
438 dataSourceTypeHisyseventClockid_ = TS_CLOCK_REALTIME;
439 dataSeg.dataType = DATA_SOURCE_TYPE_HISYSEVENT;
440 if (!dataSeg.hisyseventInfo.ParseFromArray(pluginData.data().data(), static_cast<int>(pluginData.data().size()))) {
441 streamFilters_->statFilter_->IncreaseStat(TRACE_HISYSEVENT, STAT_EVENT_DATA_INVALID);
442 TS_LOGW("tracePacketParseFromArray failed\n");
443 dataSeg.status = TS_PARSE_STATUS_INVALID;
444 return;
445 }
446 dataSeg.status = TS_PARSE_STATUS_PARSED;
447 }
448
GetNextSegment()449 int HtraceParser::GetNextSegment()
450 {
451 int head;
452 dataSegMux_.lock();
453 head = parseHead_;
454 HtraceDataSegment& seg = dataSegArray_[head];
455 if (seg.status.load() != TS_PARSE_STATUS_SEPRATED) {
456 if (toExit_) {
457 parserThreadCount_--;
458 TS_LOGI("exiting parser, parserThread Count:%d\n", parserThreadCount_);
459 TS_LOGD("seprateHead_x:\t%d, parseHead_:\t%d, filterHead_:\t%d status:%d\n", rawDataHead_, parseHead_,
460 filterHead_, seg.status.load());
461 dataSegMux_.unlock();
462 if (!parserThreadCount_ && !filterThreadStarted_) {
463 exited_ = true;
464 }
465 return ERROR_CODE_EXIT;
466 }
467 if (seg.status.load() == TS_PARSE_STATUS_PARSING) {
468 dataSegMux_.unlock();
469 usleep(sleepDur_);
470 return ERROR_CODE_NODATA;
471 }
472 dataSegMux_.unlock();
473 usleep(sleepDur_);
474 return ERROR_CODE_NODATA;
475 }
476 parseHead_ = (parseHead_ + 1) % MAX_SEG_ARRAY_SIZE;
477 seg.status = TS_PARSE_STATUS_PARSING;
478 dataSegMux_.unlock();
479 return head;
480 }
ParseDataRecursively(std::deque<uint8_t>::iterator & packagesBegin,size_t & currentLength)481 bool HtraceParser::ParseDataRecursively(std::deque<uint8_t>::iterator& packagesBegin, size_t& currentLength)
482 {
483 if (!hasGotHeader_) {
484 if (InitProfilerTraceFileHeader()) {
485 packagesBuffer_.erase(packagesBuffer_.begin(), packagesBuffer_.begin() + PACKET_HEADER_LENGTH);
486 currentLength -= PACKET_HEADER_LENGTH;
487 packagesBegin += PACKET_HEADER_LENGTH;
488 htraceCurentLength_ = profilerTraceFileHeader_.data.length;
489 htraceCurentLength_ -= PACKET_HEADER_LENGTH;
490 hasGotHeader_ = true;
491 if (!currentLength) {
492 return false;
493 }
494 } else {
495 TS_LOGE("get profiler trace file header failed");
496 return false;
497 }
498 }
499 if (profilerTraceFileHeader_.data.dataType == ProfilerTraceFileHeader::HIPERF_DATA) {
500 if (packagesBuffer_.size() >= profilerTraceFileHeader_.data.length - PACKET_HEADER_LENGTH) {
501 #if WITH_PERF
502 auto size = profilerTraceFileHeader_.data.length - PACKET_HEADER_LENGTH;
503 perfDataParser_->InitPerfDataAndLoad(packagesBuffer_, size);
504 currentLength -= size;
505 packagesBegin += size;
506 profilerTraceFileHeader_.data.dataType = ProfilerTraceFileHeader::UNKNOW_TYPE;
507 hasGotHeader_ = false;
508 return true;
509 #endif
510 }
511 return false;
512 }
513 if (profilerTraceFileHeader_.data.dataType == ProfilerTraceFileHeader::STANDALONE_DATA) {
514 if (EBPF_PLUGIN_NAME.compare(profilerTraceFileHeader_.data.standalonePluginName) == 0 &&
515 packagesBuffer_.size() >= profilerTraceFileHeader_.data.length - PACKET_HEADER_LENGTH) {
516 auto size = profilerTraceFileHeader_.data.length - PACKET_HEADER_LENGTH;
517 ebpfDataParser_->InitAndParseEbpfData(packagesBuffer_, size);
518 currentLength -= size;
519 packagesBegin += size;
520 profilerTraceFileHeader_.data.dataType = ProfilerTraceFileHeader::UNKNOW_TYPE;
521 hasGotHeader_ = false;
522 return true;
523 }
524 #if IS_WASM
525 if (packagesBuffer_.size() >= profilerTraceFileHeader_.data.length - PACKET_HEADER_LENGTH) {
526 auto thirdPartySize = profilerTraceFileHeader_.data.length - PACKET_HEADER_LENGTH;
527 auto buffer = std::make_unique<uint8_t[]>(thirdPartySize).get();
528 std::copy(packagesBuffer_.begin(), packagesBuffer_.begin() + thirdPartySize, buffer);
529 TraceStreamer_Plugin_Out_Filter(reinterpret_cast<const char*>(buffer), thirdPartySize,
530 profilerTraceFileHeader_.data.standalonePluginName);
531 return true;
532 }
533 #endif
534 return false;
535 }
536 while (1) {
537 if (!hasGotSegLength_) {
538 if (currentLength < PACKET_SEG_LENGTH) {
539 break;
540 }
541 std::string bufferLine(packagesBegin, packagesBegin + PACKET_SEG_LENGTH);
542 const uint32_t* len = reinterpret_cast<const uint32_t*>(bufferLine.data());
543 nextLength_ = *len;
544 htraceLength_ += nextLength_ + PACKET_SEG_LENGTH;
545 hasGotSegLength_ = true;
546 currentLength -= PACKET_SEG_LENGTH;
547 packagesBegin += PACKET_SEG_LENGTH;
548 htraceCurentLength_ -= PACKET_SEG_LENGTH;
549 }
550 if (currentLength < nextLength_) {
551 break;
552 }
553 std::string bufferLine(packagesBegin, packagesBegin + nextLength_);
554 ParseTraceDataItem(bufferLine);
555 hasGotSegLength_ = false;
556 packagesBegin += nextLength_;
557 currentLength -= nextLength_;
558 if (nextLength_ > htraceCurentLength_) {
559 TS_LOGE("fatal error, data length not match nextLength_:%u, htraceCurentLength_:%llu", nextLength_,
560 htraceCurentLength_);
561 }
562 htraceCurentLength_ -= nextLength_;
563 if (htraceCurentLength_ == 0) {
564 hasGotHeader_ = false;
565 packagesBuffer_.erase(packagesBuffer_.begin(), packagesBegin);
566 profilerTraceFileHeader_.data.dataType = ProfilerTraceFileHeader::UNKNOW_TYPE;
567 TS_LOGW("read proto finished!");
568 return ParseDataRecursively(packagesBegin, currentLength);
569 }
570 }
571 return true;
572 }
ParseTraceDataSegment(std::unique_ptr<uint8_t[]> bufferStr,size_t size)573 void HtraceParser::ParseTraceDataSegment(std::unique_ptr<uint8_t[]> bufferStr, size_t size)
574 {
575 packagesBuffer_.insert(packagesBuffer_.end(), &bufferStr[0], &bufferStr[size]);
576 auto packagesBegin = packagesBuffer_.begin();
577 auto currentLength = packagesBuffer_.size();
578 if (ParseDataRecursively(packagesBegin, currentLength)) {
579 packagesBuffer_.erase(packagesBuffer_.begin(), packagesBegin);
580 }
581 return;
582 }
583
InitProfilerTraceFileHeader()584 bool HtraceParser::InitProfilerTraceFileHeader()
585 {
586 if (packagesBuffer_.size() < PACKET_HEADER_LENGTH) {
587 TS_LOGE("buffer size less than profiler trace file header");
588 return false;
589 }
590 uint8_t buffer[PACKET_HEADER_LENGTH];
591 memset_s(buffer, PACKET_HEADER_LENGTH, 0, PACKET_HEADER_LENGTH);
592 int i = 0;
593 for (auto it = packagesBuffer_.begin(); it != packagesBuffer_.begin() + PACKET_HEADER_LENGTH; ++it, ++i) {
594 buffer[i] = *it;
595 }
596 auto ret = memcpy_s(&profilerTraceFileHeader_, sizeof(profilerTraceFileHeader_), buffer, PACKET_HEADER_LENGTH);
597 if (ret == -1 || profilerTraceFileHeader_.data.magic != ProfilerTraceFileHeader::HEADER_MAGIC) {
598 TS_LOGE("Get profiler trace file header failed! ret = %d, magic = %lx", ret,
599 profilerTraceFileHeader_.data.magic);
600 return false;
601 }
602 if (profilerTraceFileHeader_.data.length <= PACKET_HEADER_LENGTH) {
603 TS_LOGE("Profiler Trace data is truncated!!!");
604 return false;
605 }
606 TS_LOGI("magic = %llx, length = %llx, dataType = %llx, boottime = %llx", profilerTraceFileHeader_.data.magic,
607 profilerTraceFileHeader_.data.length, profilerTraceFileHeader_.data.dataType,
608 profilerTraceFileHeader_.data.boottime);
609 #if IS_WASM
610 const int DATA_TYPE_CLOCK = 100;
611 int componentId = DATA_TYPE_CLOCK;
612 TraceStreamer_Plugin_Out_SendData(reinterpret_cast<char*>(&profilerTraceFileHeader_),
613 sizeof(profilerTraceFileHeader_), DATA_TYPE_CLOCK);
614 #endif
615 htraceClockDetailParser_->Parse(&profilerTraceFileHeader_);
616 return true;
617 }
618 } // namespace TraceStreamer
619 } // namespace SysTuning
620