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