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