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