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