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