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