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