• 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     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