• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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