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 "json.hpp"
25 #include "log.h"
26 #include "string_help.h"
27 #include "version.h"
28
29 #define UNUSED(expr) \
30 do { \
31 static_cast<void>(expr); \
32 } while (0)
33 namespace SysTuning {
34 namespace TraceStreamer {
35 uint32_t g_fileLen = 0;
36 FILE* g_importFileFd = nullptr;
37 using json = nlohmann::json;
38 namespace jsonns {
39 struct ParserConfig {
40 int32_t taskConfigValue;
41 int32_t appConfigValue;
42 int32_t aniConfigValue;
43 };
from_json(const json & j,ParserConfig & v)44 void from_json(const json& j, ParserConfig& v)
45 {
46 j.at("TaskPool").get_to(v.taskConfigValue);
47 j.at("AppStartup").get_to(v.appConfigValue);
48 j.at("AnimationAnalysis").get_to(v.aniConfigValue);
49 }
50 } // namespace jsonns
ParseData(const uint8_t * data,size_t len,ResultCallBack resultCallBack)51 bool RpcServer::ParseData(const uint8_t* data, size_t len, ResultCallBack resultCallBack)
52 {
53 g_loadSize += len;
54 size_t blockSize = 1024 * 1024;
55 do {
56 size_t parseSize = std::min(len, blockSize);
57 std::unique_ptr<uint8_t[]> buf = std::make_unique<uint8_t[]>(parseSize);
58 std::copy(data, data + parseSize, buf.get());
59 if (!ts_->ParseTraceDataSegment(std::move(buf), parseSize)) {
60 if (resultCallBack) {
61 resultCallBack("formaterror\r\n", SEND_FINISH);
62 }
63 return false;
64 }
65 data += parseSize;
66 len -= parseSize;
67 lenParseData_ += parseSize;
68 } while (len > 0);
69 if (resultCallBack) {
70 resultCallBack("ok\r\n", SEND_FINISH);
71 }
72 return true;
73 }
74
UpdateTraceTime(const uint8_t * data,int32_t len)75 int32_t RpcServer::UpdateTraceTime(const uint8_t* data, int32_t len)
76 {
77 std::unique_ptr<uint8_t[]> buf = std::make_unique<uint8_t[]>(len);
78 std::copy(data, data + len, buf.get());
79 ts_->UpdateTraceRangeTime(buf.get(), len);
80 return 0;
81 }
82
TraceStreamer_Init_ThirdParty_Config(const uint8_t * data,int32_t len)83 int32_t RpcServer::TraceStreamer_Init_ThirdParty_Config(const uint8_t* data, int32_t len)
84 {
85 TS_LOGE("TraceStreamer_Init_ThirdParty_Config is comming!");
86 std::string thirdPartyConfig = reinterpret_cast<const char*>(data);
87 TS_LOGE("thirdPartyConfig = %s", thirdPartyConfig.c_str());
88 std::vector<std::string> comPonentStr = SplitStringToVec(thirdPartyConfig, ";");
89 const int32_t EVENT_COUNT_PAIR = 2;
90 if (comPonentStr.size() % EVENT_COUNT_PAIR != 0) {
91 TS_LOGE("thirdPartyConfig is wrong!");
92 return -1;
93 }
94 for (int32_t m = 0; m < comPonentStr.size(); m += EVENT_COUNT_PAIR) {
95 int32_t componentId = std::stoi(comPonentStr.at(m));
96 std::string componentName = comPonentStr.at(m + 1);
97 TS_LOGE("comPonentStr[m] = %d, comPonentStr[m + 1] = %s", componentId, componentName.c_str());
98 g_thirdPartyConfig.insert((std::map<int32_t, std::string>::value_type(componentId, componentName)));
99 }
100 return 0;
101 }
102
ParseDataOver(const uint8_t * data,size_t len,ResultCallBack resultCallBack)103 bool RpcServer::ParseDataOver(const uint8_t* data, size_t len, ResultCallBack resultCallBack)
104 {
105 UNUSED(data);
106 UNUSED(len);
107 MetaData* metaData = ts_->GetMetaData();
108 metaData->SetSourceFileName("input stream mode");
109 metaData->SetOutputFileName("wasm mode");
110 metaData->SetParserToolVersion(g_traceStreamerVersion);
111 metaData->SetParserToolPublishDateTime(g_traceStreamerPublishVersion);
112 metaData->SetTraceDataSize(g_loadSize);
113 metaData->SetTraceType((ts_->DataType() == TRACE_FILETYPE_H_TRACE) ? "proto-based-trace" : "txt-based-trace");
114 TS_LOGI("RPC ParseDataOver, has parsed len %zu", lenParseData_);
115
116 ts_->WaitForParserEnd();
117 #ifndef USE_VTABLE
118 ts_->Clear();
119 #endif
120 if (resultCallBack) {
121 resultCallBack("ok\r\n", SEND_FINISH);
122 }
123 lenParseData_ = 0;
124 g_loadSize = 0;
125 return true;
126 }
127
SqlOperate(const uint8_t * data,size_t len,ResultCallBack resultCallBack)128 bool RpcServer::SqlOperate(const uint8_t* data, size_t len, ResultCallBack resultCallBack)
129 {
130 ts_->SetCancel(false);
131 std::string sql(reinterpret_cast<const char*>(data), len);
132 TS_LOGI("RPC SqlOperate(%s, %zu)", sql.c_str(), len);
133
134 int32_t ret = ts_->OperateDatabase(sql);
135 if (resultCallBack) {
136 std::string response = "ok\r\n";
137 if (ret != 0) {
138 response = "dberror\r\n";
139 }
140 resultCallBack(response, SEND_FINISH);
141 }
142 return (ret == 0);
143 }
144
SqlQuery(const uint8_t * data,size_t len,ResultCallBack resultCallBack)145 bool RpcServer::SqlQuery(const uint8_t* data, size_t len, ResultCallBack resultCallBack)
146 {
147 ts_->SetCancel(false);
148 std::string sql(reinterpret_cast<const char*>(data), len);
149 TS_LOGI("RPC SqlQuery %zu:%s", len, sql.c_str());
150
151 int32_t ret = ts_->SearchDatabase(sql, resultCallBack);
152 if (resultCallBack && ret != 0) {
153 resultCallBack("dberror\r\n", SEND_FINISH);
154 }
155 ts_->SetCancel(false);
156 return (ret == 0);
157 }
158
CancelSqlQuery()159 void RpcServer::CancelSqlQuery()
160 {
161 ts_->SetCancel(true);
162 }
163
Reset(const uint8_t * data,size_t len,ResultCallBack resultCallBack)164 bool RpcServer::Reset(const uint8_t* data, size_t len, ResultCallBack resultCallBack)
165 {
166 UNUSED(data);
167 UNUSED(len);
168 TS_LOGI("RPC reset trace_streamer");
169
170 ts_->WaitForParserEnd();
171 ts_ = std::make_unique<TraceStreamerSelector>();
172 if (resultCallBack) {
173 resultCallBack("ok\r\n", SEND_FINISH);
174 }
175 return true;
176 }
177
WasmSqlQuery(const uint8_t * data,size_t len,uint8_t * out,int32_t outLen)178 int32_t RpcServer::WasmSqlQuery(const uint8_t* data, size_t len, uint8_t* out, int32_t outLen)
179 {
180 ts_->SetCancel(false);
181 std::string sql(reinterpret_cast<const char*>(data), len);
182 TS_LOGI("WASM RPC SqlQuery outlen(%d) sql(%zu:%s)", outLen, len, sql.c_str());
183
184 int32_t ret = ts_->SearchDatabase(sql, out, outLen);
185 return ret;
186 }
WasmSqlQueryWithCallback(const uint8_t * data,size_t len,ResultCallBack callback) const187 int32_t RpcServer::WasmSqlQueryWithCallback(const uint8_t* data, size_t len, ResultCallBack callback) const
188 {
189 ts_->SetCancel(false);
190 std::string sql(reinterpret_cast<const char*>(data), len);
191 TS_LOGI("WASM RPC SqlQuery sql(%zu:%s)", len, sql.c_str());
192
193 int32_t ret = ts_->SearchDatabase(sql, callback);
194 return ret;
195 }
196
WasmExportDatabase(ResultCallBack resultCallBack)197 int32_t RpcServer::WasmExportDatabase(ResultCallBack resultCallBack)
198 {
199 return ts_->ExportDatabase("default.db", resultCallBack);
200 }
201
202 #if IS_WASM
DownloadELFCallback(const std::string & fileName,size_t totalLen,const uint8_t * data,size_t len,int32_t finish,ParseELFFileCallBack parseELFFile)203 int32_t RpcServer::DownloadELFCallback(const std::string& fileName,
204 size_t totalLen,
205 const uint8_t* data,
206 size_t len,
207 int32_t finish,
208 ParseELFFileCallBack parseELFFile)
209 {
210 g_fileLen += len;
211 std::string filePath = "";
212 TS_LOGI("fileName = %s", fileName.c_str());
213 std::string symbolsPath = fileName.substr(0, fileName.find("/"));
214 TS_LOGI("symbolsPath = %s", symbolsPath.c_str());
215 filePath = fileName.substr(0, fileName.find_last_of("/"));
216 if (std::filesystem::exists(filePath)) {
217 TS_LOGE("%s exist", filePath.c_str());
218 } else {
219 if (std::filesystem::create_directories(filePath)) {
220 TS_LOGI("create_directories success");
221 } else {
222 TS_LOGI("create_directories failed!");
223 }
224 }
225 TS_LOGI("filePath = %s", filePath.c_str());
226 if (g_fileLen < totalLen) {
227 if (g_importFileFd == nullptr) {
228 g_importFileFd = fopen(fileName.c_str(), "a+");
229 if (g_importFileFd == nullptr) {
230 TS_LOGE("wasm file create failed");
231 return false;
232 }
233 }
234 int32_t writeLength = fwrite(data, len, 1, g_importFileFd);
235 if (!writeLength) {
236 fclose(g_importFileFd);
237 TS_LOGE("wasm write file failed");
238 return false;
239 }
240 return false;
241 }
242 g_fileLen = 0;
243 if (g_importFileFd == nullptr) {
244 g_importFileFd = fopen(fileName.c_str(), "a+");
245 if (g_importFileFd == nullptr) {
246 TS_LOGE("wasm file create failed");
247 return false;
248 }
249 }
250 int32_t writeLength = fwrite(data, len, 1, g_importFileFd);
251 (void)fclose(g_importFileFd);
252 g_importFileFd = nullptr;
253 if (!writeLength) {
254 TS_LOGE("wasm write file failed");
255 return false;
256 }
257 TS_LOGI("symbolsPath = %s, fileName = %s", symbolsPath.c_str(), fileName.c_str());
258 symbolsPathFiles_.emplace_back(fileName);
259 parseELFFile("file send over\r\n", SEND_FINISH);
260
261 if (finish) {
262 if (!ts_->ReloadSymbolFiles(symbolsPath, symbolsPathFiles_)) {
263 symbolsPathFiles_.clear();
264 if (parseELFFile) {
265 parseELFFile("formaterror\r\n", SEND_FINISH);
266 }
267 return false;
268 }
269 symbolsPathFiles_.clear();
270 if (parseELFFile) {
271 parseELFFile("ok\r\n", SEND_FINISH);
272 }
273 std::filesystem::remove_all(symbolsPath);
274 }
275 return true;
276 }
277 #endif
278
ParserConfig(std::string parserConfigJson)279 bool RpcServer::ParserConfig(std::string parserConfigJson)
280 {
281 json jMessage = json::parse(parserConfigJson);
282 jsonns::ParserConfig parserConfig = jMessage.at("config");
283 ts_->UpdateAppStartTraceStatus(parserConfig.appConfigValue);
284 ts_->UpdateAnimationTraceStatus(parserConfig.aniConfigValue);
285 ts_->UpdateTaskPoolTraceStatus(parserConfig.taskConfigValue);
286 return true;
287 }
288 } // namespace TraceStreamer
289 } // namespace SysTuning
290