• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) Huawei Technologies Co., Ltd. 2023. All rights reserved.
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 "rpc_server.h"
17 
18 #include <cstdint>
19 #include <cstring>
20 #include <functional>
21 #if IS_WASM
22 #include <filesystem>
23 #include "file.h"
24 #endif
25 #include "common_types.h"
26 #include "hilog_parser/ptreader_hilog_parser.h"
27 #include "ptreader_parser.h"
28 #include "pbreader_parser.h"
29 #include "json.hpp"
30 #ifdef ENABLE_RAWTRACE
31 #include "rawtrace_parser.h"
32 #endif
33 #include "string_help.h"
34 #include "trace_streamer_selector.h"
35 #include "ts_common.h"
36 #include "version.h"
37 
38 namespace SysTuning {
39 namespace TraceStreamer {
40 uint32_t g_fileLen = 0;
41 FILE *g_importFileFd = nullptr;
42 const size_t PACKET_HEADER_LENGTH = 1024;
43 const std::string VALUE_STR = "{\"value\":[";
44 const std::string OFFSET = "{\"offset\":";
45 const std::string SIZE = ",\"size\":";
46 const std::string TYPE = ",\"type\":";
47 const std::string EMPTY_VALUE = "{\"value\":[]}";
48 
49 using json = nlohmann::json;
50 namespace jsonns {
51 struct ParserConfig {
52     int32_t taskConfigValue;
53     int32_t appConfigValue;
54     int32_t aniConfigValue;
55     int32_t binderConfigValue;
56     int32_t ffrtConvertConfigValue;
57     int32_t HMKernelConfigValue;
58     int32_t rawTraceCutStartTsValue;
59 };
from_json(const json & j,ParserConfig & v)60 void from_json(const json &j, ParserConfig &v)
61 {
62     j.at("TaskPool").get_to(v.taskConfigValue);
63     j.at("AppStartup").get_to(v.appConfigValue);
64     j.at("AnimationAnalysis").get_to(v.aniConfigValue);
65     j.at("BinderRunnable").get_to(v.binderConfigValue);
66     j.at("FfrtConvert").get_to(v.ffrtConvertConfigValue);
67     j.at("HMKernel").get_to(v.HMKernelConfigValue);
68     if (j.contains("RawTraceCutStartTs")) {
69         v.rawTraceCutStartTsValue = j.at("RawTraceCutStartTs");
70     }
71 }
72 } // namespace jsonns
73 #if IS_WASM
SaveAndParseFfrtData(const uint8_t * data,size_t len,ResultCallBack resultCallBack,bool isFinish)74 bool RpcServer::SaveAndParseFfrtData(const uint8_t *data, size_t len, ResultCallBack resultCallBack, bool isFinish)
75 {
76     auto ffrtFileName = "ffrtFile.txt";
77     static std::ofstream ffrtFile(ffrtFileName, std::ios::binary | std::ios::app);
78     if (!ffrtFile.is_open()) {
79         TS_LOGE("ffrtFile open filed!");
80         return false;
81     }
82     ffrtFile.write(reinterpret_cast<const char *>(data), len);
83     if (ffrtFile.fail() || ffrtFile.bad()) {
84         TS_LOGE("Failed to write data!");
85         ffrtFile.close();
86         return false;
87     }
88     if (!isFinish) {
89         return true;
90     }
91     ffrtFile.close();
92     auto outTraceName = "outTrace.txt";
93     std::ofstream outFile(outTraceName);
94     if (!outFile.is_open()) {
95         ffrtFile.close();
96         std::filesystem::remove_all(ffrtFileName);
97         TS_LOGE("prepare outFile failed.");
98         return false;
99     }
100     FfrtConverter ffrtConverter;
101     auto ret = ffrtConverter.RecoverTraceAndGenerateNewFile(ffrtFileName, outFile);
102     outFile.close();
103     std::filesystem::remove_all(ffrtFileName);
104     if (!ret) {
105         std::filesystem::remove_all(outTraceName);
106         return false;
107     }
108     outFile.close();
109     if (!ReadAndParseData(outTraceName) || !SendConvertedFfrtFile(outTraceName, resultCallBack)) {
110         std::filesystem::remove_all(outTraceName);
111         return false;
112     }
113     std::filesystem::remove_all(outTraceName);
114     return true;
115 }
SaveAndParseZipTraceData(const uint8_t * data,size_t len,ResultCallBack resultCallBack,bool isFinish)116 bool RpcServer::SaveAndParseZipTraceData(const uint8_t *data, size_t len, ResultCallBack resultCallBack, bool isFinish)
117 {
118     auto zipFileName = "zipFile.zip";
119     static std::ofstream zipFile(zipFileName, std::ios::binary | std::ios::app);
120     if (!zipFile.is_open()) {
121         TS_LOGE("zipFile open filed!");
122         return false;
123     }
124     zipFile.write(reinterpret_cast<const char *>(data), len);
125     if (zipFile.fail() || zipFile.bad()) {
126         TS_LOGE("Failed to write data!");
127         zipFile.close();
128         return false;
129     }
130     if (!isFinish) {
131         return true;
132     }
133     zipFile.close();
134     std::string outTraceName;
135     UnZipFile(zipFileName, outTraceName);
136     if (!ReadAndParseData(outTraceName)) {
137         std::filesystem::remove_all(outTraceName);
138         return false;
139     }
140     std::filesystem::remove_all(outTraceName);
141     return true;
142 }
DetermineZlibTrace(const uint8_t * data,size_t len)143 bool RpcServer::DetermineZlibTrace(const uint8_t *data, size_t len)
144 {
145     if (len < ZLIB_MAGIC_NUM_LEN) {
146         return false;
147     }
148     return data[0] == ZLIB_CMF && data[1] == ZLIB_FLG;
149 }
SaveAndParseZlibTraceData(const uint8_t * data,size_t len,ResultCallBack resultCallBack,bool isFinish)150 bool RpcServer::SaveAndParseZlibTraceData(const uint8_t *data, size_t len, ResultCallBack resultCallBack, bool isFinish)
151 {
152     auto zlibFileName = "zlibFile.zlib";
153     static std::ofstream zlibFile(zlibFileName, std::ios::binary | std::ios::app);
154     if (!zlibFile.is_open()) {
155         TS_LOGE("zlibFile open filed!");
156         return false;
157     }
158     zlibFile.write(reinterpret_cast<const char *>(data), len);
159     if (zlibFile.fail() || zlibFile.bad()) {
160         TS_LOGE("Failed to write data!");
161         zlibFile.close();
162         return false;
163     }
164     if (!isFinish) {
165         return true;
166     }
167     zlibFile.close();
168     std::string outTraceName;
169     UnZlibFile(zlibFileName, outTraceName);
170     if (!ReadAndParseData(outTraceName)) {
171         std::filesystem::remove_all(outTraceName);
172         return false;
173     }
174     std::filesystem::remove_all(outTraceName);
175     return true;
176 }
SendConvertedFfrtFile(const std::string & fileName,ResultCallBack resultCallBack)177 bool RpcServer::SendConvertedFfrtFile(const std::string &fileName, ResultCallBack resultCallBack)
178 {
179     if (!resultCallBack) {
180         TS_LOGE("resultCallBack is nullptr!");
181         return false;
182     }
183     std::ifstream inputFile(fileName);
184     if (!inputFile.is_open()) {
185         TS_LOGE("open file : %s failed!", fileName.c_str());
186         return false;
187     }
188     char outData[G_CHUNK_SIZE];
189     while (true) {
190         inputFile.read(outData, G_CHUNK_SIZE);
191         auto readSize = inputFile.gcount();
192         resultCallBack(std::string(outData, readSize), SEND_CONTINUE);
193         if (inputFile.eof()) {
194             break;
195         }
196     }
197     resultCallBack("ok\r\n", SEND_FINISH);
198     return true;
199 }
ReadAndParseData(const std::string & filePath)200 bool RpcServer::ReadAndParseData(const std::string &filePath)
201 {
202     std::ifstream inputFile(filePath);
203     if (!inputFile.is_open()) {
204         TS_LOGE("can not open %s.", filePath.c_str());
205         return false;
206     }
207     uint8_t curParseCnt = 1;
208     while (true) {
209         std::unique_ptr<uint8_t[]> buf = std::make_unique<uint8_t[]>(G_CHUNK_SIZE);
210         inputFile.read(reinterpret_cast<char *>(buf.get()), G_CHUNK_SIZE);
211         auto readSize = inputFile.gcount();
212         if (!ts_->ParseTraceDataSegment(std::move(buf), readSize, false, inputFile.eof(), true)) {
213             return false;
214         }
215         // for rawtrace next parse.the first parse is for last comm data;
216         if (inputFile.eof() && ts_->GetFileType() == TRACE_FILETYPE_RAW_TRACE && curParseCnt < RAW_TRACE_PARSE_MAX) {
217             ++curParseCnt;
218             inputFile.clear();
219             inputFile.seekg(0, std::ios::beg);
220         } else if (inputFile.eof()) {
221             break;
222         }
223     }
224     inputFile.close();
225     return true;
226 }
227 #endif
ParseData(const uint8_t * data,size_t len,ResultCallBack resultCallBack,bool isFinish)228 bool RpcServer::ParseData(const uint8_t *data, size_t len, ResultCallBack resultCallBack, bool isFinish)
229 {
230     g_loadSize += len;
231     do {
232         size_t parseSize = std::min(len, G_CHUNK_SIZE);
233         std::unique_ptr<uint8_t[]> buf = std::make_unique<uint8_t[]>(parseSize);
234         std::copy(data, data + parseSize, buf.get());
235         if (!ts_->ParseTraceDataSegment(std::move(buf), parseSize, false, isFinish && (len <= G_CHUNK_SIZE))) {
236             if (resultCallBack) {
237                 resultCallBack("formaterror\r\n", SEND_FINISH);
238             }
239             return false;
240         }
241         data += parseSize;
242         len -= parseSize;
243         lenParseData_ += parseSize;
244     } while (len > 0);
245     if (resultCallBack) {
246         resultCallBack("ok\r\n", SEND_FINISH);
247     }
248     return true;
249 }
ParseDataWithoutCallback(const uint8_t * data,size_t len,int32_t isFinish,bool isSplitFile)250 bool RpcServer::ParseDataWithoutCallback(const uint8_t *data, size_t len, int32_t isFinish, bool isSplitFile)
251 {
252     g_loadSize += len;
253     do {
254         size_t parseSize = std::min(len, G_CHUNK_SIZE);
255         std::unique_ptr<uint8_t[]> buf = std::make_unique<uint8_t[]>(parseSize);
256         std::copy(data, data + parseSize, buf.get());
257         if (!ts_->ParseTraceDataSegment(std::move(buf), parseSize, isSplitFile, isFinish && (len == parseSize))) {
258             return false;
259         }
260         data += parseSize;
261         len -= parseSize;
262         lenParseData_ += parseSize;
263     } while (len > 0);
264     return true;
265 }
266 
GetLongTraceTimeSnap(std::string dataString)267 bool RpcServer::GetLongTraceTimeSnap(std::string dataString)
268 {
269     int count = dataString.size() / PACKET_HEADER_LENGTH;
270     for (int i = 0; i < count; i++) {
271         if (!GetTimeSnap(dataString)) {
272             TS_LOGE("GetLongTraceTimeSnap error");
273             return false;
274         }
275         dataString = dataString.substr(PACKET_HEADER_LENGTH);
276     }
277     return true;
278 }
GetTimeSnap(std::string dataString)279 bool RpcServer::GetTimeSnap(std::string dataString)
280 {
281     if (dataString.size() < PACKET_HEADER_LENGTH) {
282         TS_LOGE("buffer size less than profiler trace file header");
283         return false;
284     }
285     uint8_t buffer[PACKET_HEADER_LENGTH];
286     (void)memset_s(buffer, sizeof(buffer), 0, sizeof(buffer));
287     int32_t i = 0;
288     for (auto it = dataString.begin(); it != dataString.begin() + PACKET_HEADER_LENGTH; ++it, ++i) {
289         buffer[i] = *it;
290     }
291     ProfilerTraceFileHeader *pHeader = reinterpret_cast<ProfilerTraceFileHeader *>(buffer);
292     if (pHeader->data.length <= PACKET_HEADER_LENGTH || pHeader->data.magic != ProfilerTraceFileHeader::HEADER_MAGIC) {
293         TS_LOGE("Profiler Trace data is truncated or invalid magic! len = %" PRIu64 ", maigc = %" PRIx64 "",
294                 pHeader->data.length, pHeader->data.magic);
295         return false;
296     }
297     std::unique_ptr<TraceTimeSnap> longTraceTimeSnap = std::make_unique<TraceTimeSnap>();
298     longTraceTimeSnap->startTime = pHeader->data.boottime;
299     longTraceTimeSnap->endTime = pHeader->data.boottime + pHeader->data.durationNs;
300     vTraceTimeSnap_.emplace_back(std::move(longTraceTimeSnap));
301     return true;
302 }
LongTraceSplitFile(const uint8_t * data,size_t len,int32_t isFinish,uint32_t pageNum,SplitFileCallBack splitFileCallBack)303 bool RpcServer::LongTraceSplitFile(const uint8_t *data,
304                                    size_t len,
305                                    int32_t isFinish,
306                                    uint32_t pageNum,
307                                    SplitFileCallBack splitFileCallBack)
308 {
309     if (vTraceTimeSnap_.size() <= pageNum) {
310         return false;
311     }
312     ts_->minTs_ = vTraceTimeSnap_[pageNum]->startTime;
313     ts_->maxTs_ = vTraceTimeSnap_[pageNum]->endTime;
314     ParseSplitFileData(data, len, isFinish, splitFileCallBack, true);
315     return true;
316 }
317 
DetermineSystrace(const uint8_t * data,size_t len)318 bool RpcServer::DetermineSystrace(const uint8_t *data, size_t len)
319 {
320     std::string startStr(reinterpret_cast<const char *>(data), std::min<size_t>(len, 20));
321     if (startStr.find("# tracer") != std::string::npos) {
322         return true;
323     }
324     if (startStr.find("# TRACE") != std::string::npos) {
325         return true;
326     }
327     const std::regex systraceMatcher = std::regex(R"(-(\d+)\s+\(?\s*(\d+|-+)?\)?\s?\[(\d+)\]\s*)"
328                                                   R"([a-zA-Z0-9.]{0,5}\s+(\d+\.\d+):\s+(\S+):)");
329     std::smatch matcheLine;
330     std::string bytraceMode(reinterpret_cast<const char *>(data), len);
331     if (std::regex_search(bytraceMode, matcheLine, systraceMatcher)) {
332         return true;
333     }
334     return false;
335 }
336 
DetermineZipTrace(const uint8_t * data,size_t len)337 bool RpcServer::DetermineZipTrace(const uint8_t *data, size_t len)
338 {
339     if (len < 2) {
340         return false;
341     }
342     return data[0] == 'P' && data[1] == 'K';
343 }
344 
SendBytraceSplitFileData(SplitFileCallBack splitFileCallBack,int32_t isFinish)345 bool RpcServer::SendBytraceSplitFileData(SplitFileCallBack splitFileCallBack, int32_t isFinish)
346 {
347     int32_t firstPos = ts_->GetPtreaderParser()->MinSplitPos();
348     int32_t lastPos = ts_->GetPtreaderParser()->MaxSplitPos();
349     TS_CHECK_TRUE(firstPos != INVALID_INT32 && lastPos != INVALID_INT32 && lastPos >= firstPos, false,
350                   "firstPos(%d) or lastPos(%d) is INVALID_INT32!", firstPos, lastPos);
351     const auto &mTraceDataBytrace = ts_->GetPtreaderParser()->GetPtreaderSplitData();
352     // for 10% data
353     int32_t tenPercentDataNum = 0.1 * (lastPos - firstPos);
354     firstPos -= tenPercentDataNum;
355     lastPos += tenPercentDataNum;
356     if (firstPos < 0) {
357         firstPos = 0;
358     }
359     if (lastPos >= mTraceDataBytrace.size()) {
360         lastPos = mTraceDataBytrace.size() - 1;
361     }
362     std::string result = VALUE_STR;
363     for (size_t index = firstPos; index <= lastPos; index++) {
364         result += OFFSET + std::to_string(mTraceDataBytrace[index].first);
365         result += SIZE + std::to_string(mTraceDataBytrace[index].second);
366         result += "},";
367     }
368     if (result != VALUE_STR && !ts_->GetPtreaderParser()->GetPtreaderSplitData().empty()) {
369         result.pop_back();
370         result += "]}\r\n";
371         splitFileCallBack(result, (int32_t)SplitDataDataType::SPLIT_FILE_JSON, isFinish);
372     }
373     TS_LOGI("MinSplitPos=%d, MaxSplitPos=%d, tenPercentDataNum=%d, firstPos=%d, lastPos=%d\nresult=%s",
374             ts_->GetPtreaderParser()->MinSplitPos(), ts_->GetPtreaderParser()->MaxSplitPos(), tenPercentDataNum,
375             firstPos, lastPos, result.data());
376     return true;
377 }
378 
379 #ifdef ENABLE_RAWTRACE
SendRawtraceSplitFileData(SplitFileCallBack splitFileCallBack,int32_t isFinish)380 bool RpcServer::SendRawtraceSplitFileData(SplitFileCallBack splitFileCallBack, int32_t isFinish)
381 {
382     const auto &mTraceRawCpuData = ts_->GetRawtraceData()->GetRawtraceCpuData();
383     const auto &mTraceRawCommData = ts_->GetRawtraceData()->GetRawtraceCommData();
384     std::string result = VALUE_STR;
385 
386     for (size_t commDataIndex = 0; commDataIndex < mTraceRawCommData.size(); commDataIndex++) {
387         result += OFFSET + std::to_string(mTraceRawCommData.at(commDataIndex).splitDataOffset_);
388         result += SIZE + std::to_string(mTraceRawCommData.at(commDataIndex).splitDataSize_);
389         result += TYPE + std::to_string(mTraceRawCommData.at(commDataIndex).splitType_);
390         result += "},";
391     }
392 
393     for (size_t cpuDataIndex = 0; cpuDataIndex < mTraceRawCpuData.size(); cpuDataIndex++) {
394         result += OFFSET + std::to_string(mTraceRawCpuData.at(cpuDataIndex).splitDataOffset_);
395         result += SIZE + std::to_string(mTraceRawCpuData.at(cpuDataIndex).splitDataSize_);
396         result += TYPE + std::to_string(mTraceRawCpuData.at(cpuDataIndex).splitType_);
397         result += "},";
398     }
399     if (result != VALUE_STR && !ts_->GetRawtraceData()->GetRawtraceCommData().empty()) {
400         result.pop_back();
401         result += "]}\r\n";
402         splitFileCallBack(result, (int32_t)SplitDataDataType::SPLIT_FILE_JSON, isFinish);
403     }
404     TS_LOGI("mTraceRawCpuData.size()= %zu, mTraceRawCommData.size()=%zu\n result=%s\n", mTraceRawCpuData.size(),
405             mTraceRawCommData.size(), result.data());
406     return true;
407 }
408 #endif
ParseSplitFileData(const uint8_t * data,size_t len,int32_t isFinish,SplitFileCallBack splitFileCallBack,bool isSplitFile)409 bool RpcServer::ParseSplitFileData(const uint8_t *data,
410                                    size_t len,
411                                    int32_t isFinish,
412                                    SplitFileCallBack splitFileCallBack,
413                                    bool isSplitFile)
414 {
415     if (!ParseDataWithoutCallback(data, len, isFinish, isSplitFile)) {
416         TS_LOGE("ParserData failed!");
417         return false;
418     }
419     if (!isSplitFile || !isFinish) {
420         return false;
421     }
422     if ((ts_->GetFileType() == TRACE_FILETYPE_BY_TRACE || ts_->GetFileType() == TRACE_FILETYPE_HILOG ||
423          ts_->GetFileType() == TRACE_FILETYPE_HI_SYSEVENT)) {
424         SendBytraceSplitFileData(splitFileCallBack, 0);
425         splitFileCallBack(EMPTY_VALUE, (int32_t)SplitDataDataType::SPLIT_FILE_JSON, 1);
426         ts_->GetPtreaderParser()->ClearPtreaderSplitData();
427         ts_->GetTraceDataCache()->isSplitFile_ = false;
428         return true;
429     }
430 #ifdef ENABLE_RAWTRACE
431     if (ts_->GetFileType() == TRACE_FILETYPE_RAW_TRACE) {
432         SendRawtraceSplitFileData(splitFileCallBack, 0);
433         splitFileCallBack(EMPTY_VALUE, (int32_t)SplitDataDataType::SPLIT_FILE_JSON, 1);
434         ts_->GetRawtraceData()->ClearRawTraceData();
435         ts_->GetTraceDataCache()->isSplitFile_ = false;
436         return true;
437     }
438 #endif
439     if (ts_->GetFileType() == TRACE_FILETYPE_H_TRACE) {
440         ProcPbreaderSplitResult(splitFileCallBack);
441     }
442 #ifdef ENABLE_HIPERF
443     if (ts_->GetFileType() == TRACE_FILETYPE_PERF) {
444         ProcPerfSplitResult(splitFileCallBack, true);
445     }
446 #endif
447     splitFileCallBack(EMPTY_VALUE, (int32_t)SplitDataDataType::SPLIT_FILE_JSON, 1);
448     ts_->GetPbreaderParser()->ClearPbreaderSplitData();
449 #ifdef ENABLE_ARKTS
450     ts_->GetPbreaderParser()->GetJsMemoryData()->ClearArkTsSplitFileData();
451 #endif
452     ts_->GetTraceDataCache()->isSplitFile_ = false;
453     return true;
454 }
ProcPbreaderSplitResult(SplitFileCallBack splitFileCallBack)455 void RpcServer::ProcPbreaderSplitResult(SplitFileCallBack splitFileCallBack)
456 {
457     uint64_t dataSize = 0;
458     std::string result = VALUE_STR;
459 #ifdef ENABLE_NATIVE_HOOK
460     ts_->GetPbreaderParser()->ClearNativehookData();
461 #endif
462     for (const auto &itemPbreader : ts_->GetPbreaderParser()->GetPbreaderSplitData()) {
463         dataSize += itemPbreader.second;
464         result += OFFSET + std::to_string(itemPbreader.first);
465         result += SIZE + std::to_string(itemPbreader.second);
466         result += "},";
467     }
468     auto dataSourceType = ts_->GetPbreaderParser()->GetDataSourceType();
469     auto profilerHeader = ts_->GetPbreaderParser()->GetProfilerHeader();
470 #ifdef ENABLE_ARKTS
471     if (dataSourceType == DATA_SOURCE_TYPE_JSMEMORY) {
472         dataSize += ts_->GetPbreaderParser()->GetArkTsConfigData().size() +
473                     ts_->GetPbreaderParser()->GetJsMemoryData()->GetArkTsSize();
474     }
475 #endif
476 #ifdef ENABLE_NATIVE_HOOK
477     for (auto &commProto : ts_->GetTraceDataCache()->HookCommProtos()) {
478         dataSize += (sizeof(uint32_t) + commProto->size());
479     }
480 #endif
481     // Send Header
482     profilerHeader.data.length = PACKET_HEADER_LENGTH + dataSize;
483     std::string buffer(reinterpret_cast<char *>(&profilerHeader), sizeof(profilerHeader));
484     splitFileCallBack(buffer, (int32_t)SplitDataDataType::SPLIT_FILE_DATA, 0);
485     // Send Datas
486 #ifdef ENABLE_NATIVE_HOOK
487     ProcHookCommSplitResult(splitFileCallBack);
488 #endif
489     if (result != VALUE_STR && !ts_->GetPbreaderParser()->GetPbreaderSplitData().empty()) {
490         result.pop_back();
491         result += "]}\r\n";
492         splitFileCallBack(result, (int32_t)SplitDataDataType::SPLIT_FILE_JSON, 0);
493     }
494 #ifdef ENABLE_ARKTS
495     if (dataSourceType == DATA_SOURCE_TYPE_JSMEMORY) {
496         splitFileCallBack(ts_->GetPbreaderParser()->GetArkTsConfigData() +
497                               ts_->GetPbreaderParser()->GetJsMemoryData()->GetArkTsSplitFileData(),
498                           (int32_t)SplitDataDataType::SPLIT_FILE_DATA, 0);
499     }
500 #endif
501 #ifdef ENABLE_HIPERF
502     ProcPerfSplitResult(splitFileCallBack, true);
503 #endif
504 #ifdef ENABLE_EBPF
505     ProcEbpfSplitResult(splitFileCallBack, true);
506 #endif
507 }
508 #ifdef ENABLE_NATIVE_HOOK
ProcHookCommSplitResult(SplitFileCallBack splitFileCallBack)509 void RpcServer::ProcHookCommSplitResult(SplitFileCallBack splitFileCallBack)
510 {
511     std::string lenBuffer(sizeof(uint32_t), 0);
512     for (auto &commProto : ts_->GetTraceDataCache()->HookCommProtos()) {
513         uint32_t len = commProto->size();
514         memcpy_s(const_cast<char *>(lenBuffer.data()), sizeof(uint32_t), &len, sizeof(uint32_t));
515         splitFileCallBack(lenBuffer, (int32_t)SplitDataDataType::SPLIT_FILE_DATA, 0);
516         splitFileCallBack(*commProto, (int32_t)SplitDataDataType::SPLIT_FILE_DATA, 0);
517     }
518     ts_->GetTraceDataCache()->ClearHookCommProtos();
519 }
520 #endif
521 #ifdef ENABLE_EBPF
ProcEbpfSplitResult(SplitFileCallBack splitFileCallBack,bool isLast)522 void RpcServer::ProcEbpfSplitResult(SplitFileCallBack splitFileCallBack, bool isLast)
523 {
524     auto ebpfSplitResult = ts_->GetPbreaderParser()->GetEbpfDataParser()->GetEbpfSplitResult();
525     std::string result = VALUE_STR;
526     for (auto ebpfIter = ebpfSplitResult.begin(); ebpfIter != ebpfSplitResult.end(); ++ebpfIter) {
527         if (ebpfIter->type == (int32_t)SplitDataDataType::SPLIT_FILE_JSON) {
528             result += OFFSET + std::to_string(ebpfIter->originSeg.offset);
529             result += SIZE + std::to_string(ebpfIter->originSeg.size);
530             result += "},";
531         } else {
532             if (result != VALUE_STR) {
533                 result.pop_back();
534                 result += "]}\r\n";
535                 splitFileCallBack(result, (int32_t)SplitDataDataType::SPLIT_FILE_JSON, 0);
536                 result = VALUE_STR;
537             }
538             std::string buffer(reinterpret_cast<char *>(ebpfIter->buffer.address), ebpfIter->buffer.size);
539             splitFileCallBack(buffer, (int32_t)SplitDataDataType::SPLIT_FILE_DATA, 0);
540         }
541     }
542     if (result != VALUE_STR) {
543         result.pop_back();
544         result += "]}\r\n";
545         splitFileCallBack(result, (int32_t)SplitDataDataType::SPLIT_FILE_JSON, 0);
546     }
547 }
548 #endif
549 #ifdef ENABLE_HIPERF
ProcPerfSplitResult(SplitFileCallBack splitFileCallBack,bool isLast)550 void RpcServer::ProcPerfSplitResult(SplitFileCallBack splitFileCallBack, bool isLast)
551 {
552     auto perfSplitResult = ts_->GetPbreaderParser()->GetPerfSplitResult();
553     std::string result = VALUE_STR;
554     for (auto perfIter = perfSplitResult.begin(); perfIter != perfSplitResult.end(); ++perfIter) {
555         if (perfIter->type == (int32_t)SplitDataDataType::SPLIT_FILE_JSON) {
556             result += OFFSET + std::to_string(perfIter->originSeg.offset);
557             result += SIZE + std::to_string(perfIter->originSeg.size);
558             result += "},";
559         } else {
560             if (result != VALUE_STR) {
561                 result.pop_back();
562                 result += "]}\r\n";
563                 splitFileCallBack(result, (int32_t)SplitDataDataType::SPLIT_FILE_JSON, 0);
564                 result = VALUE_STR;
565             }
566             std::string buffer(reinterpret_cast<char *>(perfIter->buffer.address), perfIter->buffer.size);
567             splitFileCallBack(buffer, (int32_t)SplitDataDataType::SPLIT_FILE_DATA, 0);
568         }
569     }
570 
571     if (result != VALUE_STR) {
572         result.pop_back();
573         result += "]}\r\n";
574         splitFileCallBack(result, (int32_t)SplitDataDataType::SPLIT_FILE_JSON, 0);
575     }
576 }
577 #endif
578 
UpdateTraceTime(const uint8_t * data,int32_t len)579 int32_t RpcServer::UpdateTraceTime(const uint8_t *data, int32_t len)
580 {
581     std::unique_ptr<uint8_t[]> buf = std::make_unique<uint8_t[]>(len);
582     std::copy(data, data + len, buf.get());
583     ts_->UpdateTraceRangeTime(buf.get(), len);
584     return 0;
585 }
586 
TraceStreamerInitThirdPartyConfig(const uint8_t * data,int32_t len)587 int32_t RpcServer::TraceStreamerInitThirdPartyConfig(const uint8_t *data, int32_t len)
588 {
589     TS_LOGI("TraceStreamerInitThirdPartyConfig is comming!");
590     std::string thirdPartyConfig = reinterpret_cast<const char *>(data);
591     TS_LOGI("thirdPartyConfig = %s", thirdPartyConfig.c_str());
592     std::vector<std::string> comPonentStr = SplitStringToVec(thirdPartyConfig, ";");
593     const int32_t eventCountPair = 2;
594     if (comPonentStr.size() % eventCountPair != 0) {
595         TS_LOGI("thirdPartyConfig is wrong!");
596         return -1;
597     }
598     for (int32_t m = 0; m < comPonentStr.size(); m += eventCountPair) {
599         int32_t componentId = std::stoi(comPonentStr.at(m));
600         std::string componentName = comPonentStr.at(m + 1);
601         TS_LOGI("comPonentStr[m] = %d, comPonentStr[m + 1] = %s", componentId, componentName.c_str());
602         g_thirdPartyConfig.insert((std::map<int32_t, std::string>::value_type(componentId, componentName)));
603     }
604     return 0;
605 }
606 
ParseDataOver(const uint8_t * data,size_t len,ResultCallBack resultCallBack)607 bool RpcServer::ParseDataOver(const uint8_t *data, size_t len, ResultCallBack resultCallBack)
608 {
609     Unused(data);
610     Unused(len);
611     MetaData *metaData = ts_->GetMetaData();
612     metaData->SetSourceFileName("input stream mode");
613     metaData->SetOutputFileName("wasm mode");
614     metaData->SetParserToolVersion(TRACE_STREAMER_VERSION);
615     metaData->SetParserToolPublishDateTime(TRACE_STREAMER_PUBLISH_VERSION);
616     metaData->SetTraceDataSize(g_loadSize);
617     metaData->SetTraceType((ts_->DataType() == TRACE_FILETYPE_H_TRACE) ? "proto-based-trace" : "txt-based-trace");
618     TS_LOGI("RPC ParseDataOver, has parsed len %zu", lenParseData_);
619     ts_->WaitForParserEnd();
620     if (resultCallBack) {
621         resultCallBack("ok\r\n", SEND_FINISH);
622     }
623     endParseTime_ =
624         (std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()))
625             .count();
626     TS_LOGW("ExportDuration:\t%u ms", static_cast<unsigned int>(endParseTime_ - startParseTime_));
627     TS_LOGW("ExportSpeed:\t%.2f MB/s", (lenParseData_ / (endParseTime_ - startParseTime_)) / 1E3);
628     lenParseData_ = 0;
629     g_loadSize = 0;
630     return true;
631 }
632 
SqlOperate(const uint8_t * data,size_t len,ResultCallBack resultCallBack)633 bool RpcServer::SqlOperate(const uint8_t *data, size_t len, ResultCallBack resultCallBack)
634 {
635     ts_->SetCancel(false);
636     std::string sql(reinterpret_cast<const char *>(data), len);
637     TS_LOGI("RPC SqlOperate(%s, %zu)", sql.c_str(), len);
638 
639     int32_t ret = ts_->OperateDatabase(sql);
640     if (resultCallBack) {
641         std::string response = "ok\r\n";
642         if (ret != 0) {
643             response = "dberror\r\n";
644         }
645         resultCallBack(response, SEND_FINISH);
646     }
647     return (ret == 0);
648 }
649 
SqlQuery(const uint8_t * data,size_t len,ResultCallBack resultCallBack)650 bool RpcServer::SqlQuery(const uint8_t *data, size_t len, ResultCallBack resultCallBack)
651 {
652     ts_->SetCancel(false);
653     std::string sql(reinterpret_cast<const char *>(data), len);
654     TS_LOGI("RPC SqlQuery %zu:%s", len, sql.c_str());
655 
656     int32_t ret = ts_->SearchDatabase(sql, resultCallBack);
657     if (resultCallBack && ret != 0) {
658         resultCallBack("dberror\r\n", SEND_FINISH);
659     }
660     ts_->SetCancel(false);
661     return (ret == 0);
662 }
663 
CancelSqlQuery()664 void RpcServer::CancelSqlQuery()
665 {
666     ts_->SetCancel(true);
667 }
668 
Reset(const uint8_t * data,size_t len,ResultCallBack resultCallBack)669 bool RpcServer::Reset(const uint8_t *data, size_t len, ResultCallBack resultCallBack)
670 {
671     Unused(data);
672     Unused(len);
673     TS_LOGI("RPC reset trace_streamer");
674 
675     ts_->WaitForParserEnd();
676     ts_ = std::make_unique<TraceStreamerSelector>();
677     if (resultCallBack) {
678         resultCallBack("ok\r\n", SEND_FINISH);
679     }
680     return true;
681 }
682 
WasmSqlQuery(const uint8_t * data,size_t len,uint8_t * out,int32_t outLen)683 int32_t RpcServer::WasmSqlQuery(const uint8_t *data, size_t len, uint8_t *out, int32_t outLen)
684 {
685     ts_->SetCancel(false);
686     std::string sql(reinterpret_cast<const char *>(data), len);
687     TS_LOGI("WASM RPC SqlQuery outlen(%d) sql(%zu:%s)", outLen, len, sql.c_str());
688 
689     int32_t ret = ts_->SearchDatabase(sql, out, outLen);
690     return ret;
691 }
SqlMetricsQueryWithCallback(const uint8_t * data,size_t len,ResultCallBack callback) const692 bool RpcServer::SqlMetricsQueryWithCallback(const uint8_t *data, size_t len, ResultCallBack callback) const
693 {
694     ts_->SetCancel(false);
695     std::string metricsName(reinterpret_cast<const char *>(data), len);
696     std::string result = ts_->SearchDatabase(ts_->MetricsSqlQuery(metricsName));
697     if (result == "") {
698         return false;
699     }
700     Metrics metricsOperator;
701     metricsOperator.ParserJson(metricsName, result);
702     for (auto item : metricsOperator.GetMetricsMap()) {
703         if (item.second == metricsName) {
704             metricsOperator.PrintMetricsResult(item.first, callback);
705             return true;
706         }
707     }
708     return true;
709 }
WasmSqlQueryWithCallback(const uint8_t * data,size_t len,ResultCallBack callback) const710 int32_t RpcServer::WasmSqlQueryWithCallback(const uint8_t *data, size_t len, ResultCallBack callback) const
711 {
712     ts_->SetCancel(false);
713     std::string sql(reinterpret_cast<const char *>(data), len);
714     TS_LOGI("WASM RPC SqlQuery sql(%zu:%s)", len, sql.c_str());
715 
716     int32_t ret = ts_->SearchDatabase(sql, callback);
717     return ret;
718 }
WasmSqlQueryToProtoCallback(const uint8_t * data,size_t len,SqllitePreparCacheData::TLVResultCallBack callback) const719 int32_t RpcServer::WasmSqlQueryToProtoCallback(const uint8_t *data,
720                                                size_t len,
721                                                SqllitePreparCacheData::TLVResultCallBack callback) const
722 {
723     ts_->SetCancel(false);
724     std::string strData(reinterpret_cast<const char *>(data), len);
725 
726     int32_t ret = ts_->SearchDatabaseToProto(strData, callback);
727     return ret;
728 }
729 
WasmExportDatabase(ResultCallBack resultCallBack)730 int32_t RpcServer::WasmExportDatabase(ResultCallBack resultCallBack)
731 {
732     return ts_->ExportDatabase("default.db", resultCallBack);
733 }
734 
735 #if IS_WASM
CreateFilePath(const std::string & directory)736 void RpcServer::CreateFilePath(const std::string &directory)
737 {
738     if (std::filesystem::exists(directory)) {
739         return;
740     }
741     if (std::filesystem::create_directories(directory)) {
742         TS_LOGI("create directory success.");
743     } else {
744         TS_LOGI("create directory failed!");
745     }
746 }
747 
WriteToFile(const std::string & fileName,const uint8_t * data,size_t len)748 bool RpcServer::WriteToFile(const std::string &fileName, const uint8_t *data, size_t len)
749 {
750     if (g_importFileFd == nullptr) {
751         g_importFileFd = fopen(fileName.c_str(), "a+");
752         if (g_importFileFd == nullptr) {
753             TS_LOGE("wasm file create failed");
754             return false;
755         }
756     }
757     int32_t writeLength = fwrite(data, len, 1, g_importFileFd);
758     if (!writeLength) {
759         fclose(g_importFileFd);
760         TS_LOGE("wasm write file failed");
761         return false;
762     }
763     return false;
764 }
765 
ReloadSymbolsAndClearELFs(const std::string & directory,const std::string & fileName,int32_t finish,ParseELFFileCallBack & parseELFFile)766 bool RpcServer::ReloadSymbolsAndClearELFs(const std::string &directory,
767                                           const std::string &fileName,
768                                           int32_t finish,
769                                           ParseELFFileCallBack &parseELFFile)
770 {
771     if (finish) {
772         if (!ts_->ReloadSymbolFiles(directory, {fileName})) {
773             if (parseELFFile) {
774                 parseELFFile("formaterror\r\n", SEND_FINISH);
775             }
776             return false;
777         }
778         if (parseELFFile) {
779             parseELFFile("ok\r\n", SEND_FINISH);
780         }
781         std::filesystem::remove_all(directory);
782     }
783     return true;
784 }
785 
DownloadELFCallback(const std::string & filePath,size_t totalLen,const uint8_t * data,size_t len,int32_t finish,ParseELFFileCallBack parseELFFile)786 bool RpcServer::DownloadELFCallback(const std::string &filePath,
787                                     size_t totalLen,
788                                     const uint8_t *data,
789                                     size_t len,
790                                     int32_t finish,
791                                     ParseELFFileCallBack parseELFFile)
792 {
793     g_fileLen += len;
794     std::filesystem::path stdFilePath(filePath);
795     const std::string fileName = stdFilePath.filename().string();
796     const std::string directory = stdFilePath.parent_path().string();
797     CreateFilePath(directory);
798     if (g_fileLen < totalLen) {
799         return WriteToFile(filePath, data, len);
800     }
801     g_fileLen = 0;
802     if (g_importFileFd == nullptr) {
803         g_importFileFd = fopen(filePath.c_str(), "a+");
804         if (g_importFileFd == nullptr) {
805             TS_LOGE("wasm file create failed");
806             return false;
807         }
808     }
809     int32_t writeLength = fwrite(data, len, 1, g_importFileFd);
810     (void)fclose(g_importFileFd);
811     g_importFileFd = nullptr;
812     if (!writeLength) {
813         TS_LOGE("wasm write file failed");
814         return false;
815     }
816     parseELFFile("file send over\r\n", SEND_FINISH);
817     // When the transfer is completed, reload the symbol file, clear the symbol path file list, call the callback
818     // function, and delete the symbol path and all files under it
819     if (!ReloadSymbolsAndClearELFs(directory, fileName, finish, parseELFFile)) {
820         return false;
821     }
822     return true;
823 }
824 #endif
825 
SplitFile(std::string timeSnaps)826 bool RpcServer::SplitFile(std::string timeSnaps)
827 {
828     std::vector<std::string> vTimesnaps = SplitStringToVec(timeSnaps, ";");
829     if (vTimesnaps.size() <= 1) {
830         return false;
831     }
832     ts_->minTs_ = std::stoull(vTimesnaps.at(0));
833     ts_->maxTs_ = std::stoull(vTimesnaps.at(1));
834     TS_LOGI("minTs_=%" PRIu64 ", maxTs_=%" PRIu64 "", ts_->minTs_, ts_->maxTs_);
835     return true;
836 }
837 
ParserConfig(std::string parserConfigJson)838 bool RpcServer::ParserConfig(std::string parserConfigJson)
839 {
840     json jMessage = json::parse(parserConfigJson);
841     jsonns::ParserConfig parserConfig = jMessage.at("config");
842     ts_->UpdateAppStartTraceStatus(parserConfig.appConfigValue);
843     ts_->UpdateAnimationTraceStatus(parserConfig.aniConfigValue);
844     ts_->UpdateTaskPoolTraceStatus(parserConfig.taskConfigValue);
845     ts_->UpdateBinderRunnableTraceStatus(parserConfig.binderConfigValue);
846     ts_->UpdateHMKernelTraceStatus(parserConfig.HMKernelConfigValue);
847     ts_->UpdateRawTraceCutStartTsStatus(parserConfig.rawTraceCutStartTsValue);
848     ffrtConvertEnabled_ = parserConfig.ffrtConvertConfigValue;
849     startParseTime_ =
850         (std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()))
851             .count();
852     return true;
853 }
854 } // namespace TraceStreamer
855 } // namespace SysTuning
856