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