• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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