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