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 return RegisterPlugin(plugin, pluginPath, info);
105 }
106
RegisterPlugin(const PluginModulePtr & plugin,const std::string & pluginPath,const PluginModuleInfo & pluginInfo)107 bool PluginManager::RegisterPlugin(const PluginModulePtr& plugin, const std::string& pluginPath,
108 const PluginModuleInfo& pluginInfo)
109 {
110 RegisterPluginRequest request;
111 request.set_request_id(commandPoller_->GetRequestId());
112 request.set_path(pluginPath);
113 request.set_sha256(ComputeFileSha256(pluginPath));
114 RegisterPluginResponse response;
115 request.set_name(pluginInfo.name);
116 request.set_buffer_size_hint(pluginInfo.bufferSizeHint);
117 request.set_is_standalone_data(pluginInfo.isStandaloneFileData);
118 request.set_out_file_name(pluginInfo.outFileName);
119 request.set_plugin_version(pluginInfo.pluginVersion);
120 if (commandPoller_->RegisterPlugin(request, response)) {
121 if (response.status() == ResponseStatus::OK) {
122 HILOG_DEBUG(LOG_CORE, "%s:response.plugin_id() = %d", __func__, response.plugin_id());
123 pluginIds_[pluginInfo.name] = response.plugin_id();
124 pluginModules_.insert(std::pair<uint32_t, std::shared_ptr<PluginModule>>(response.plugin_id(), plugin));
125 pluginPathAndNameMap_.insert(
126 {pluginPath, pluginInfo.name}
127 );
128 HILOG_DEBUG(LOG_CORE, "%s:registerPlugin ok", __func__);
129 } else {
130 HILOG_DEBUG(LOG_CORE, "%s:registerPlugin fail 1", __func__);
131 return false;
132 }
133 } else {
134 HILOG_DEBUG(LOG_CORE, "%s:registerPlugin fail 2", __func__);
135 return false;
136 }
137
138 return true;
139 }
140
RemovePlugin(const std::string & pluginPath)141 bool PluginManager::RemovePlugin(const std::string& pluginPath)
142 {
143 if (pluginPathAndNameMap_.count(pluginPath) == 0) {
144 HILOG_DEBUG(LOG_CORE, "%s:not find plugin: %s", __func__, pluginPath.c_str());
145 return false;
146 }
147
148 std::string pluginName = pluginPathAndNameMap_[pluginPath];
149 auto it = pluginIds_.find(pluginName);
150 if (it == pluginIds_.end()) {
151 HILOG_DEBUG(LOG_CORE, "%s:plugin not exist", __func__);
152 return false;
153 }
154 uint32_t index = it->second;
155
156 // stop plugin if plugin running
157 if (pluginModules_[index]->IsRunning()) {
158 HILOG_WARN(LOG_CORE, "%s:plugin delete while using, stop plugin", __func__);
159
160 // delete schedule task if POLLING mode
161 if (pluginModules_[index]->GetSampleMode() == PluginModule::SampleMode::POLLING) {
162 HILOG_WARN(LOG_CORE, "%s:delete schedule task plugin name = %s", __func__, pluginName.c_str());
163 if (!scheduleTaskManager_.UnscheduleTask(pluginName)) {
164 HILOG_WARN(LOG_CORE, "%s:delete schedule task plugin name = %s failed!", __func__, pluginName.c_str());
165 }
166 }
167
168 if (!pluginModules_[index]->StopSession()) {
169 HILOG_WARN(LOG_CORE, "%s:plugin stop failed!", __func__);
170 }
171 }
172
173 // Unload plugin if plugin loaded
174 if (pluginModules_[index]->IsLoaded()) {
175 HILOG_WARN(LOG_CORE, "%s:plugin delete while using, unload plugin", __func__);
176 if (!pluginModules_[index]->Unload()) {
177 HILOG_WARN(LOG_CORE, "%s:unload plugin failed!", __func__);
178 }
179 }
180
181 UnregisterPluginRequest request;
182 request.set_request_id(commandPoller_->GetRequestId());
183 request.set_plugin_id(index);
184 UnregisterPluginResponse response;
185 if (commandPoller_->UnregisterPlugin(request, response)) {
186 if (response.status() != ResponseStatus::OK) {
187 HILOG_DEBUG(LOG_CORE, "%s:registerPlugin fail 1", __func__);
188 return false;
189 }
190 } else {
191 HILOG_DEBUG(LOG_CORE, "%s:registerPlugin fail 2", __func__);
192 return false;
193 }
194
195 auto itPluginModules = pluginModules_.find(index);
196 if (it == pluginIds_.end()) {
197 HILOG_DEBUG(LOG_CORE, "%s:plugin not exist", __func__);
198 return false;
199 }
200 pluginModules_.erase(itPluginModules);
201 pluginIds_.erase(it);
202 return true;
203 }
204
LoadPlugin(const std::string & pluginName)205 bool PluginManager::LoadPlugin(const std::string& pluginName)
206 {
207 HILOG_DEBUG(LOG_CORE, "%s:size = %zu", __func__, pluginIds_.size());
208 auto it = pluginIds_.find(pluginName);
209 if (it == pluginIds_.end()) {
210 HILOG_DEBUG(LOG_CORE, "%s:plugin not exist", __func__);
211 return false;
212 }
213 uint32_t index = it->second;
214
215 if (!pluginModules_[index]->Load()) {
216 return false;
217 }
218 if (!pluginModules_[index]->BindFunctions()) {
219 return false;
220 }
221 return true;
222 }
223
UnloadPlugin(const std::string & pluginName)224 bool PluginManager::UnloadPlugin(const std::string& pluginName)
225 {
226 auto it = pluginIds_.find(pluginName);
227 if (it == pluginIds_.end()) {
228 HILOG_DEBUG(LOG_CORE, "%s:plugin not exist", __func__);
229 return false;
230 }
231
232 return UnloadPlugin(it->second);
233 }
234
UnloadPlugin(const uint32_t pluginId)235 bool PluginManager::UnloadPlugin(const uint32_t pluginId)
236 {
237 HILOG_INFO(LOG_CORE, "%s:ready!", __func__);
238 if (pluginModules_.find(pluginId) == pluginModules_.end()) {
239 HILOG_DEBUG(LOG_CORE, "%s:plugin not exist", __func__);
240 return false;
241 }
242 if (!pluginModules_[pluginId]->Unload()) {
243 return false;
244 }
245 return true;
246 }
247
CreatePluginSession(const std::vector<ProfilerPluginConfig> & config)248 bool PluginManager::CreatePluginSession(const std::vector<ProfilerPluginConfig>& config)
249 {
250 HILOG_DEBUG(LOG_CORE, "%s:ready", __func__);
251
252 for (size_t idx = 0; idx < config.size(); ++idx) {
253 HILOG_DEBUG(LOG_CORE, "%s:config->name() = %s", __func__, config[idx].name().c_str());
254 auto it = pluginIds_.find(config[idx].name());
255 if (it == pluginIds_.end()) {
256 HILOG_DEBUG(LOG_CORE, "%s:plugin not find", __func__);
257 return false;
258 }
259
260 HILOG_DEBUG(LOG_CORE, "%s:index = %d", __func__, it->second);
261 pluginModules_[it->second]->SetConfigData(config[idx].config_data());
262 }
263 return true;
264 }
265
DestroyPluginSession(const std::vector<uint32_t> & pluginIds)266 bool PluginManager::DestroyPluginSession(const std::vector<uint32_t>& pluginIds)
267 {
268 for (uint32_t id : pluginIds) {
269 auto it = pluginModules_.find(id);
270 if (it == pluginModules_.end()) {
271 HILOG_DEBUG(LOG_CORE, "%s:plugin not find", __func__);
272 return false;
273 }
274 }
275 return true;
276 }
277
StartPluginSession(const std::vector<uint32_t> & pluginIds,const std::vector<ProfilerPluginConfig> & config,PluginResult & result)278 bool PluginManager::StartPluginSession(const std::vector<uint32_t>& pluginIds,
279 const std::vector<ProfilerPluginConfig>& config, PluginResult& result)
280 {
281 HILOG_INFO(LOG_CORE, "%s:ready!", __func__);
282 size_t idx = 0;
283
284 for (uint32_t id : pluginIds) {
285 auto it = pluginModules_.find(id);
286 if (it == pluginModules_.end()) {
287 HILOG_DEBUG(LOG_CORE, "%s:plugin not find", __func__);
288 return false;
289 }
290 auto plugin = pluginModules_[id];
291 auto cfgData = plugin->GetConfigData();
292 if (!plugin->StartSession(reinterpret_cast<const uint8_t*>(cfgData.c_str()), cfgData.size())) {
293 return false;
294 }
295
296 if (plugin->GetSampleMode() == PluginModule::SampleMode::POLLING) {
297 if (idx > config.size()) {
298 HILOG_WARN(LOG_CORE, "%s:idx %zu out of size %zu", __func__, idx, config.size());
299 return false;
300 }
301 auto interval = ScheduleTaskManager::ms(config[idx].sample_interval());
302 std::string pluginName = config[idx].name();
303 HILOG_DEBUG(LOG_CORE, "%s:interval = %ld", __func__, static_cast<long>(interval.count()));
304 HILOG_DEBUG(LOG_CORE, "%s:pluginName = %s", __func__, pluginName.c_str());
305 auto callback = std::bind(&PluginManager::PullResult, this, id);
306 if (interval.count() == 0) {
307 HILOG_DEBUG(LOG_CORE, "%s:scheduleTask interval == 0 error!", __func__);
308 return false;
309 }
310 if (!scheduleTaskManager_.ScheduleTask(pluginName, callback, interval)) {
311 HILOG_DEBUG(LOG_CORE, "%s:scheduleTask failed!", __func__);
312 return false;
313 }
314 }
315
316 // need update standalone plugin output file name
317 if (plugin->GetStandaloneFileData()) {
318 std::string pluginOutFileName = "";
319 plugin->GetOutFileName(pluginOutFileName);
320 result.set_plugin_id(id);
321 result.set_out_file_name(pluginOutFileName);
322 }
323
324 idx++;
325 }
326
327 return true;
328 }
329
StopPluginSession(const std::vector<uint32_t> & pluginIds)330 bool PluginManager::StopPluginSession(const std::vector<uint32_t>& pluginIds)
331 {
332 HILOG_INFO(LOG_CORE, "%s:ready!", __func__);
333 for (uint32_t id : pluginIds) {
334 if (pluginModules_.find(id) == pluginModules_.end()) {
335 HILOG_DEBUG(LOG_CORE, "%s:plugin not find", __func__);
336 return false;
337 }
338 if (pluginModules_[id]->GetSampleMode() == PluginModule::SampleMode::POLLING) {
339 for (auto it : pluginIds_) {
340 if (it.second == id) {
341 HILOG_DEBUG(LOG_CORE, "%s:find plugin name = %s", __func__, it.first.c_str());
342 if (!scheduleTaskManager_.UnscheduleTask(it.first)) {
343 return false;
344 }
345 }
346 }
347 }
348 if (!pluginModules_[id]->StopSession()) {
349 return false;
350 }
351 }
352 return true;
353 }
354
ReportPluginBasicData(const std::vector<uint32_t> & pluginIds)355 bool PluginManager::ReportPluginBasicData(const std::vector<uint32_t>& pluginIds)
356 {
357 HILOG_INFO(LOG_CORE, "%s:ready!", __func__);
358 for (uint32_t id : pluginIds) {
359 if (pluginModules_.find(id) == pluginModules_.end()) {
360 HILOG_ERROR(LOG_CORE, "%s:plugin not find", __func__);
361 return false;
362 }
363 // notify plugin to report basic data
364 if (!pluginModules_[id]->ReportBasicData()) {
365 HILOG_ERROR(LOG_CORE, "%s:report basic data failed", __func__);
366 return false;
367 }
368 }
369 return true;
370 }
371
SubmitResult(const PluginResult & pluginResult)372 bool PluginManager::SubmitResult(const PluginResult& pluginResult)
373 {
374 HILOG_INFO(LOG_CORE, "%s:ready!", __func__);
375 NotifyResultRequest request;
376 if (commandPoller_ == nullptr) {
377 HILOG_DEBUG(LOG_CORE, "%s:commandPoller_ is null", __func__);
378 return false;
379 }
380 request.set_request_id(commandPoller_->GetRequestId());
381 request.set_command_id(0);
382 PluginResult* p = request.add_result();
383 *p = pluginResult;
384 NotifyResultResponse response;
385 if (!commandPoller_->NotifyResult(request, response)) {
386 HILOG_DEBUG(LOG_CORE, "%s:fail 1", __func__);
387 return false;
388 }
389 if (response.status() != ResponseStatus::OK) {
390 HILOG_DEBUG(LOG_CORE, "%s:fail 2", __func__);
391 return false;
392 }
393 HILOG_DEBUG(LOG_CORE, "%s:ok", __func__);
394 return true;
395 }
396
PullResult(uint32_t pluginId)397 bool PluginManager::PullResult(uint32_t pluginId)
398 {
399 uint32_t size = 0;
400 std::string name = "";
401 std::string version = "";
402 auto it = pluginModules_.find(pluginId);
403 if (it == pluginModules_.end()) {
404 HILOG_DEBUG(LOG_CORE, "%s:plugin not find", __func__);
405 return false;
406 }
407 pluginModules_[pluginId]->GetBufferSizeHint(size);
408 pluginModules_[pluginId]->GetPluginName(name);
409 pluginModules_[pluginId]->GetPluginVersion(version);
410 std::unique_ptr<uint8_t[]> buffer(new (std::nothrow) uint8_t[size]);
411 if (buffer == nullptr) {
412 HILOG_DEBUG(LOG_CORE, "%s:buffer new failed!", __func__);
413 return false;
414 }
415
416 int length = it->second->ReportResult(buffer.get(), size);
417 if (length < 0) {
418 return false;
419 }
420
421 ProfilerPluginData pluginData;
422 pluginData.set_name(name);
423 pluginData.set_version(version);
424 pluginData.set_status(0);
425 pluginData.set_data(buffer.get(), length);
426
427 struct timespec ts;
428 clock_gettime(CLOCK_REALTIME, &ts);
429
430 pluginData.set_clock_id(ProfilerPluginData::CLOCKID_REALTIME);
431 pluginData.set_tv_sec(ts.tv_sec);
432 pluginData.set_tv_nsec(ts.tv_nsec);
433
434 auto writer = std::static_pointer_cast<BufferWriter>(pluginModules_[pluginId]->GetWriter());
435 CHECK_NOTNULL(writer, false, "PullResult GetWriter nullptr");
436
437 writer->WriteMessage(pluginData, name);
438 writer->Flush();
439 return true;
440 }
441
CreateWriter(std::string pluginName,uint32_t bufferSize,int smbFd,int eventFd)442 bool PluginManager::CreateWriter(std::string pluginName, uint32_t bufferSize, int smbFd, int eventFd)
443 {
444 auto it = pluginIds_.find(pluginName);
445 if (it == pluginIds_.end()) {
446 HILOG_DEBUG(LOG_CORE, "%s:plugin not exist", __func__);
447 return false;
448 }
449 uint32_t index = it->second;
450
451 if (bufferSize > 0) {
452 HILOG_DEBUG(LOG_CORE, "%s:%s Use ShareMemory %d", __func__, pluginName.c_str(), bufferSize);
453 std::string pluginVersion = "";
454 pluginModules_[index]->GetPluginVersion(pluginVersion);
455 pluginModules_[index]->RegisterWriter(
456 std::make_shared<BufferWriter>(pluginName, pluginVersion, bufferSize, smbFd, eventFd, index));
457 } else {
458 HILOG_ERROR(LOG_CORE, "%s:no shared memory buffer allocated!", __func__);
459 return false;
460 }
461 return true;
462 }
463
ResetWriter(uint32_t pluginId)464 bool PluginManager::ResetWriter(uint32_t pluginId)
465 {
466 if (pluginModules_.find(pluginId) == pluginModules_.end()) {
467 HILOG_DEBUG(LOG_CORE, "%s:plugin not exist", __func__);
468 return false;
469 }
470 HILOG_DEBUG(LOG_CORE, "%s:resetWriter %u", __func__, pluginId);
471 pluginModules_[pluginId]->RegisterWriter(nullptr);
472 return true;
473 }
474