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