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 38namespace SysTuning { 39namespace TraceStreamer { 40uint32_t g_fileLen = 0; 41FILE *g_importFileFd = nullptr; 42const size_t PACKET_HEADER_LENGTH = 1024; 43const std::string VALUE_STR = "{\"value\":["; 44const std::string OFFSET = "{\"offset\":"; 45const std::string SIZE = ",\"size\":"; 46const std::string TYPE = ",\"type\":"; 47const std::string EMPTY_VALUE = "{\"value\":[]}"; 48 49using json = nlohmann::json; 50namespace jsonns { 51struct 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}; 60void 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 74bool 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} 116bool 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} 143bool 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} 166bool 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 187bool 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} 209bool 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 226bool 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} 238bool 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} 262bool 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 277bool 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 296bool 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 304bool 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 339bool 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 368bool 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} 414void 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 468void 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 481void 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 509void 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 538int32_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 546int32_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 566bool 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 592bool 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 609bool 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 623void RpcServer::CancelSqlQuery() 624{ 625 ts_->SetCancel(true); 626} 627 628bool 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 642int32_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} 651bool 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} 669int32_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} 678int32_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 689int32_t RpcServer::WasmExportDatabase(ResultCallBack resultCallBack) 690{ 691 return ts_->ExportDatabase("default.db", resultCallBack); 692} 693 694#if IS_WASM 695void 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 709bool 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 727bool 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 746bool 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 791bool 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 803bool 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