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