• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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