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