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 "plugin_manager.h"
17
18 #include <cstdio>
19 #include <functional>
20 #include <iomanip>
21
22 #include "command_poller.h"
23 #include "logging.h"
24 #include "openssl/sha.h"
25 #include "plugin_service_types.pb.h"
26
27 namespace {
28 constexpr int FILE_READ_CHUNK_SIZE = 4096;
29 constexpr char HEX_CHARS[] = "0123456789abcdef";
30
31 #define HHB(v) (((v) & 0xF0) >> 4)
32 #define LHB(v) ((v) & 0x0F)
33
ComputeFileSha256(const std::string & path)34 std::string ComputeFileSha256(const std::string& path)
35 {
36 uint8_t out[SHA256_DIGEST_LENGTH];
37 uint8_t buffer[FILE_READ_CHUNK_SIZE];
38 char realPath[PATH_MAX + 1] = {0};
39
40 SHA256_CTX sha;
41 SHA256_Init(&sha);
42
43 size_t nbytes = 0;
44 if ((path.length() >= PATH_MAX) || (realpath(path.c_str(), realPath) == nullptr)) {
45 HILOG_ERROR(LOG_CORE, "%s:path is invalid: %s, errno=%d", __func__, path.c_str(), errno);
46 return "";
47 }
48 std::unique_ptr<FILE, decltype(fclose)*> fptr(fopen(realPath, "rb"), fclose);
49 while ((nbytes = fread(buffer, 1, sizeof(buffer), fptr.get())) > 0) {
50 SHA256_Update(&sha, buffer, nbytes);
51 }
52 SHA256_Final(out, &sha);
53
54 std::string result;
55 result.reserve(SHA256_DIGEST_LENGTH + SHA256_DIGEST_LENGTH);
56 for (int i = 0; i < SHA256_DIGEST_LENGTH; i++) {
57 result.push_back(HEX_CHARS[HHB(out[i])]);
58 result.push_back(HEX_CHARS[LHB(out[i])]);
59 }
60
61 HILOG_DEBUG(LOG_CORE, "%s:%s-(%s)", __func__, path.c_str(), result.c_str());
62 return result;
63 }
64 } // namespace
65
~PluginManager()66 PluginManager::~PluginManager() {}
67
SetCommandPoller(const CommandPollerPtr & p)68 void PluginManager::SetCommandPoller(const CommandPollerPtr& p)
69 {
70 this->commandPoller_ = p;
71 }
72
AddPlugin(const std::string & pluginPath)73 bool PluginManager::AddPlugin(const std::string& pluginPath)
74 {
75 PluginModuleInfo info = {"", 0};
76 auto plugin = std::make_shared<PluginModule>(pluginPath);
77 CHECK_TRUE(plugin->Load(), false, "%s:load failed!", __func__);
78
79 if (!plugin->BindFunctions()) {
80 HILOG_DEBUG(LOG_CORE, "%s:bindFunctions failed %s", __func__, pluginPath.c_str());
81 plugin->Unload();
82 return false;
83 }
84
85 if (!plugin->GetInfo(info)) {
86 HILOG_DEBUG(LOG_CORE, "%s:getinfo failed!", __func__);
87 plugin->Unload();
88 return false;
89 }
90
91 std::string pluginName = info.name;
92 if (pluginIds_.find(pluginName) != pluginIds_.end()) {
93 HILOG_DEBUG(LOG_CORE, "%s:already add", __func__);
94 plugin->Unload();
95 return false;
96 }
97 HILOG_DEBUG(LOG_CORE, "%s:add plugin name = %s", __func__, pluginName.c_str());
98
99 if (!plugin->Unload()) {
100 HILOG_DEBUG(LOG_CORE, "%s:unload failed!", __func__);
101 return false;
102 }
103
104 RegisterPluginRequest request;
105 request.set_request_id(commandPoller_->GetRequestId());
106 request.set_path(pluginPath);
107 request.set_sha256(ComputeFileSha256(pluginPath));
108 request.set_name(pluginName);
109 request.set_buffer_size_hint(0);
110 RegisterPluginResponse response;
111
112 if (commandPoller_->RegisterPlugin(request, response)) {
113 if (response.status() == ResponseStatus::OK) {
114 HILOG_DEBUG(LOG_CORE, "%s:response.plugin_id() = %d", __func__, response.plugin_id());
115 pluginIds_[pluginName] = response.plugin_id();
116 pluginModules_.insert(std::pair<uint32_t, std::shared_ptr<PluginModule>>(response.plugin_id(), plugin));
117 pluginPathAndNameMap_.insert(
118 {pluginPath, pluginName}
119 );
120 HILOG_DEBUG(LOG_CORE, "%s:registerPlugin ok", __func__);
121 } else {
122 HILOG_DEBUG(LOG_CORE, "%s:registerPlugin fail 1", __func__);
123 return false;
124 }
125 } else {
126 HILOG_DEBUG(LOG_CORE, "%s:registerPlugin fail 2", __func__);
127 return false;
128 }
129
130 return true;
131 }
132
RemovePlugin(const std::string & pluginPath)133 bool PluginManager::RemovePlugin(const std::string& pluginPath)
134 {
135 if (pluginPathAndNameMap_.count(pluginPath) == 0) {
136 HILOG_DEBUG(LOG_CORE, "%s:not find plugin: %s", __func__, pluginPath.c_str());
137 return false;
138 }
139
140 std::string pluginName = pluginPathAndNameMap_[pluginPath];
141 auto it = pluginIds_.find(pluginName);
142 if (it == pluginIds_.end()) {
143 HILOG_DEBUG(LOG_CORE, "%s:plugin not exist", __func__);
144 return false;
145 }
146 uint32_t index = it->second;
147
148 // stop plugin if plugin running
149 if (pluginModules_[index]->IsRunning()) {
150 HILOG_WARN(LOG_CORE, "%s:plugin delete while using, stop plugin", __func__);
151
152 // delete schedule task if POLLING mode
153 if (pluginModules_[index]->GetSampleMode() == PluginModule::POLLING) {
154 HILOG_WARN(LOG_CORE, "%s:delete schedule task plugin name = %s", __func__, pluginName.c_str());
155 if (!scheduleTaskManager_.UnscheduleTask(pluginName)) {
156 HILOG_WARN(LOG_CORE, "%s:delete schedule task plugin name = %s failed!", __func__, pluginName.c_str());
157 }
158 }
159
160 if (!pluginModules_[index]->StopSession()) {
161 HILOG_WARN(LOG_CORE, "%s:plugin stop failed!", __func__);
162 }
163 }
164
165 // Unload plugin if plugin loaded
166 if (pluginModules_[index]->IsLoaded()) {
167 HILOG_WARN(LOG_CORE, "%s:plugin delete while using, unload plugin", __func__);
168 if (!pluginModules_[index]->Unload()) {
169 HILOG_WARN(LOG_CORE, "%s:unload plugin failed!", __func__);
170 }
171 }
172
173 UnregisterPluginRequest request;
174 request.set_request_id(commandPoller_->GetRequestId());
175 request.set_plugin_id(index);
176 UnregisterPluginResponse response;
177 if (commandPoller_->UnregisterPlugin(request, response)) {
178 if (response.status() != ResponseStatus::OK) {
179 HILOG_DEBUG(LOG_CORE, "%s:registerPlugin fail 1", __func__);
180 return false;
181 }
182 } else {
183 HILOG_DEBUG(LOG_CORE, "%s:registerPlugin fail 2", __func__);
184 return false;
185 }
186
187 auto itPluginModules = pluginModules_.find(index);
188 if (it == pluginIds_.end()) {
189 HILOG_DEBUG(LOG_CORE, "%s:plugin not exist", __func__);
190 return false;
191 }
192 pluginModules_.erase(itPluginModules);
193 pluginIds_.erase(it);
194 return true;
195 }
196
LoadPlugin(const std::string & pluginName)197 bool PluginManager::LoadPlugin(const std::string& pluginName)
198 {
199 HILOG_DEBUG(LOG_CORE, "%s:size = %zu", __func__, pluginIds_.size());
200 auto it = pluginIds_.find(pluginName);
201 if (it == pluginIds_.end()) {
202 HILOG_DEBUG(LOG_CORE, "%s:plugin not exist", __func__);
203 return false;
204 }
205 uint32_t index = it->second;
206
207 if (!pluginModules_[index]->Load()) {
208 return false;
209 }
210 if (!pluginModules_[index]->BindFunctions()) {
211 return false;
212 }
213 return true;
214 }
215
UnloadPlugin(const std::string & pluginName)216 bool PluginManager::UnloadPlugin(const std::string& pluginName)
217 {
218 auto it = pluginIds_.find(pluginName);
219 if (it == pluginIds_.end()) {
220 HILOG_DEBUG(LOG_CORE, "%s:plugin not exist", __func__);
221 return false;
222 }
223
224 return UnloadPlugin(it->second);
225 }
226
UnloadPlugin(const uint32_t pluginId)227 bool PluginManager::UnloadPlugin(const uint32_t pluginId)
228 {
229 HILOG_INFO(LOG_CORE, "%s:ready!", __func__);
230 if (pluginModules_.find(pluginId) == pluginModules_.end()) {
231 HILOG_DEBUG(LOG_CORE, "%s:plugin not exist", __func__);
232 return false;
233 }
234 if (!pluginModules_[pluginId]->Unload()) {
235 return false;
236 }
237 return true;
238 }
239
CreatePluginSession(const std::vector<ProfilerPluginConfig> & config)240 bool PluginManager::CreatePluginSession(const std::vector<ProfilerPluginConfig>& config)
241 {
242 HILOG_DEBUG(LOG_CORE, "%s:ready", __func__);
243
244 for (size_t idx = 0; idx < config.size(); ++idx) {
245 HILOG_DEBUG(LOG_CORE, "%s:config->name() = %s", __func__, config[idx].name().c_str());
246 auto it = pluginIds_.find(config[idx].name());
247 if (it == pluginIds_.end()) {
248 HILOG_DEBUG(LOG_CORE, "%s:plugin not find", __func__);
249 return false;
250 }
251
252 HILOG_DEBUG(LOG_CORE, "%s:index = %d", __func__, it->second);
253 pluginModules_[it->second]->SetConfigData(config[idx].config_data());
254 }
255 return true;
256 }
257
DestroyPluginSession(const std::vector<uint32_t> & pluginIds)258 bool PluginManager::DestroyPluginSession(const std::vector<uint32_t>& pluginIds)
259 {
260 for (uint32_t id : pluginIds) {
261 auto it = pluginModules_.find(id);
262 if (it == pluginModules_.end()) {
263 HILOG_DEBUG(LOG_CORE, "%s:plugin not find", __func__);
264 return false;
265 }
266 }
267 return true;
268 }
269
StartPluginSession(const std::vector<uint32_t> & pluginIds,const std::vector<ProfilerPluginConfig> & config)270 bool PluginManager::StartPluginSession(const std::vector<uint32_t>& pluginIds,
271 const std::vector<ProfilerPluginConfig>& config)
272 {
273 HILOG_INFO(LOG_CORE, "%s:ready!", __func__);
274 size_t idx = 0;
275
276 for (uint32_t id : pluginIds) {
277 auto it = pluginModules_.find(id);
278 if (it == pluginModules_.end()) {
279 HILOG_DEBUG(LOG_CORE, "%s:plugin not find", __func__);
280 return false;
281 }
282 auto plugin = pluginModules_[id];
283 auto cfgData = plugin->GetConfigData();
284 if (!plugin->StartSession(reinterpret_cast<const uint8_t*>(cfgData.c_str()), cfgData.size())) {
285 return false;
286 }
287 if (plugin->GetSampleMode() == PluginModule::POLLING) {
288 if (idx > config.size()) {
289 HILOG_WARN(LOG_CORE, "%s:idx %zu out of size %zu", __func__, idx, config.size());
290 return false;
291 }
292 auto interval = ScheduleTaskManager::ms(config[idx].sample_interval());
293 std::string pluginName = config[idx].name();
294 HILOG_DEBUG(LOG_CORE, "%s:interval = %ld", __func__, static_cast<long>(interval.count()));
295 HILOG_DEBUG(LOG_CORE, "%s:pluginName = %s", __func__, pluginName.c_str());
296 auto callback = std::bind(&PluginManager::PullResult, this, id);
297 if (interval.count() == 0) {
298 HILOG_DEBUG(LOG_CORE, "%s:scheduleTask interval == 0 error!", __func__);
299 return false;
300 }
301 if (!scheduleTaskManager_.ScheduleTask(pluginName, callback, interval)) {
302 HILOG_DEBUG(LOG_CORE, "%s:scheduleTask failed!", __func__);
303 return false;
304 }
305 }
306
307 idx++;
308 }
309
310 return true;
311 }
312
StopPluginSession(const std::vector<uint32_t> & pluginIds)313 bool PluginManager::StopPluginSession(const std::vector<uint32_t>& pluginIds)
314 {
315 HILOG_INFO(LOG_CORE, "%s:ready!", __func__);
316 for (uint32_t id : pluginIds) {
317 if (pluginModules_.find(id) == pluginModules_.end()) {
318 HILOG_DEBUG(LOG_CORE, "%s:plugin not find", __func__);
319 return false;
320 }
321 if (pluginModules_[id]->GetSampleMode() == PluginModule::POLLING) {
322 for (auto it : pluginIds_) {
323 if (it.second == id) {
324 HILOG_DEBUG(LOG_CORE, "%s:find plugin name = %s", __func__, it.first.c_str());
325 if (!scheduleTaskManager_.UnscheduleTask(it.first)) {
326 return false;
327 }
328 }
329 }
330 }
331 if (!pluginModules_[id]->StopSession()) {
332 return false;
333 }
334 }
335 return true;
336 }
337
SubmitResult(const PluginResult & pluginResult)338 bool PluginManager::SubmitResult(const PluginResult& pluginResult)
339 {
340 HILOG_INFO(LOG_CORE, "%s:ready!", __func__);
341 NotifyResultRequest request;
342 if (commandPoller_ == nullptr) {
343 HILOG_DEBUG(LOG_CORE, "%s:commandPoller_ is null", __func__);
344 return false;
345 }
346 request.set_request_id(commandPoller_->GetRequestId());
347 request.set_command_id(0);
348 PluginResult* p = request.add_result();
349 *p = pluginResult;
350 NotifyResultResponse response;
351 if (!commandPoller_->NotifyResult(request, response)) {
352 HILOG_DEBUG(LOG_CORE, "%s:fail 1", __func__);
353 return false;
354 }
355 if (response.status() != ResponseStatus::OK) {
356 HILOG_DEBUG(LOG_CORE, "%s:fail 2", __func__);
357 return false;
358 }
359 HILOG_DEBUG(LOG_CORE, "%s:ok", __func__);
360 return true;
361 }
362
PullResult(uint32_t pluginId)363 bool PluginManager::PullResult(uint32_t pluginId)
364 {
365 uint32_t size = 0;
366 std::string name = "";
367 auto it = pluginModules_.find(pluginId);
368 if (it == pluginModules_.end()) {
369 HILOG_DEBUG(LOG_CORE, "%s:plugin not find", __func__);
370 return false;
371 }
372 pluginModules_[pluginId]->GetBufferSizeHint(size);
373 pluginModules_[pluginId]->GetPluginName(name);
374 std::unique_ptr<uint8_t[]> buffer(new (std::nothrow) uint8_t[size]);
375 if (buffer == nullptr) {
376 HILOG_DEBUG(LOG_CORE, "%s:buffer new failed!", __func__);
377 return false;
378 }
379
380 int length = it->second->ReportResult(buffer.get(), size);
381 if (length < 0) {
382 return false;
383 }
384
385 ProfilerPluginData pluginData;
386 pluginData.set_name(name);
387 pluginData.set_status(0);
388 pluginData.set_data(buffer.get(), length);
389
390 struct timespec ts;
391 clock_gettime(CLOCK_REALTIME, &ts);
392
393 pluginData.set_clock_id(ProfilerPluginData::CLOCKID_REALTIME);
394 pluginData.set_tv_sec(ts.tv_sec);
395 pluginData.set_tv_nsec(ts.tv_nsec);
396
397 auto writer = std::static_pointer_cast<BufferWriter>(pluginModules_[pluginId]->GetWriter());
398 CHECK_NOTNULL(writer, false, "PullResult GetWriter nullptr");
399
400 writer->WriteMessage(pluginData);
401 writer->Flush();
402 return true;
403 }
404
CreateWriter(std::string pluginName,uint32_t bufferSize,int smbFd,int eventFd)405 bool PluginManager::CreateWriter(std::string pluginName, uint32_t bufferSize, int smbFd, int eventFd)
406 {
407 auto it = pluginIds_.find(pluginName);
408 if (it == pluginIds_.end()) {
409 HILOG_DEBUG(LOG_CORE, "%s:plugin not exist", __func__);
410 return false;
411 }
412 uint32_t index = it->second;
413
414 if (bufferSize > 0) {
415 HILOG_DEBUG(LOG_CORE, "%s:%s Use ShareMemory %d", __func__, pluginName.c_str(), bufferSize);
416 pluginModules_[index]->RegisterWriter(
417 std::make_shared<BufferWriter>(pluginName, bufferSize, smbFd, eventFd, index));
418 } else {
419 HILOG_ERROR(LOG_CORE, "%s:no shared memory buffer allocated!", __func__);
420 return false;
421 }
422 return true;
423 }
424
ResetWriter(uint32_t pluginId)425 bool PluginManager::ResetWriter(uint32_t pluginId)
426 {
427 if (pluginModules_.find(pluginId) == pluginModules_.end()) {
428 HILOG_DEBUG(LOG_CORE, "%s:plugin not exist", __func__);
429 return false;
430 }
431 HILOG_DEBUG(LOG_CORE, "%s:resetWriter %u", __func__, pluginId);
432 pluginModules_[pluginId]->RegisterWriter(nullptr);
433 return true;
434 }
435