• 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_service.h"
17  
18  #include <cinttypes>
19  #include <fcntl.h>
20  #include <sys/wait.h>
21  #include <unistd.h>
22  
23  #include "plugin_command_builder.h"
24  #include "plugin_service_impl.h"
25  #include "plugin_session_manager.h"
26  #include "profiler_capability_manager.h"
27  #include "profiler_data_repeater.h"
28  #include "securec.h"
29  #include "share_memory_allocator.h"
30  #include "socket_context.h"
31  
32  namespace {
33  const int PAGE_BYTES = 4096;
34  const int DEFAULT_EVENT_POLLING_INTERVAL = 5000;
35  } // namespace
36  
PluginService()37  PluginService::PluginService()
38  {
39      pluginIdCounter_ = 0;
40      StartService(DEFAULT_UNIX_SOCKET_PATH);
41      pluginCommandBuilder_ = std::make_shared<PluginCommandBuilder>();
42  
43      eventPoller_ = std::make_unique<EpollEventPoller>(DEFAULT_EVENT_POLLING_INTERVAL);
44      CHECK_NOTNULL(eventPoller_, NO_RETVAL, "create event poller FAILED!");
45  
46      eventPoller_->Init();
47      eventPoller_->Start();
48  }
49  
~PluginService()50  PluginService::~PluginService()
51  {
52      if (eventPoller_) {
53          eventPoller_->Stop();
54          eventPoller_->Finalize();
55      }
56  }
57  
SetPluginSessionManager(const PluginSessionManagerPtr & pluginSessionManager)58  void PluginService::SetPluginSessionManager(const PluginSessionManagerPtr& pluginSessionManager)
59  {
60      pluginSessionManager_ = pluginSessionManager;
61  }
62  
GetSemaphore(uint32_t id) const63  SemaphorePtr PluginService::GetSemaphore(uint32_t id) const
64  {
65      std::unique_lock<std::mutex> lock(mutex_);
66      auto it = waitSemphores_.find(id);
67      if (it != waitSemphores_.end()) {
68          return it->second;
69      }
70      return nullptr;
71  }
72  
StartService(const std::string & unixSocketName)73  bool PluginService::StartService(const std::string& unixSocketName)
74  {
75      pluginServiceImpl_ = std::make_shared<PluginServiceImpl>(*this);
76      serviceEntry_ = std::make_shared<ServiceEntry>();
77      if (!serviceEntry_->StartServer(unixSocketName)) {
78          pluginServiceImpl_ = nullptr;
79          serviceEntry_ = nullptr;
80          HILOG_DEBUG(LOG_CORE, "Start IPC Service FAIL");
81          return false;
82      }
83      serviceEntry_->RegisterService(*pluginServiceImpl_.get());
84      return true;
85  }
86  
GetReusePolicy(const ProfilerSessionConfig::BufferConfig & bufferConfig)87  static ShareMemoryBlock::ReusePolicy GetReusePolicy(const ProfilerSessionConfig::BufferConfig& bufferConfig)
88  {
89      if (bufferConfig.policy() == ProfilerSessionConfig::BufferConfig::RECYCLE) {
90          return ShareMemoryBlock::DROP_OLD;
91      }
92      return ShareMemoryBlock::DROP_NONE;
93  }
94  
95  // create plugin session with buffer config
CreatePluginSession(const ProfilerPluginConfig & pluginConfig,const ProfilerSessionConfig::BufferConfig & bufferConfig,const ProfilerDataRepeaterPtr & dataRepeater)96  bool PluginService::CreatePluginSession(const ProfilerPluginConfig& pluginConfig,
97                                          const ProfilerSessionConfig::BufferConfig& bufferConfig,
98                                          const ProfilerDataRepeaterPtr& dataRepeater)
99  {
100      uint32_t pluginId = 0;
101      PluginContextPtr pluginCtx = nullptr;
102      std::string pluginName = pluginConfig.name();
103      std::tie(pluginId, pluginCtx) = GetPluginContext(pluginName);
104      CHECK_NOTNULL(pluginCtx, false, "get PluginContext failed!");
105  
106      pluginCtx->profilerDataRepeater = dataRepeater;
107  
108      uint32_t bufferSize = bufferConfig.pages() * PAGE_BYTES;
109      auto cmd = pluginCommandBuilder_->BuildCreateSessionCmd(pluginConfig, bufferSize);
110      CHECK_TRUE(cmd != nullptr, false, "CreatePluginSession BuildCreateSessionCmd FAIL %s", pluginName.c_str());
111  
112      auto smb = ShareMemoryAllocator::GetInstance().CreateMemoryBlockLocal(pluginName, bufferSize);
113      CHECK_TRUE(smb != nullptr, false, "CreateMemoryBlockLocal FAIL %s", pluginName.c_str());
114  
115      auto policy = GetReusePolicy(bufferConfig);
116      HILOG_DEBUG(LOG_CORE, "CreatePluginSession policy = %d", (int)policy);
117      smb->SetReusePolicy(policy);
118  
119      auto notifier = EventNotifier::Create(0, EventNotifier::NONBLOCK);
120      CHECK_NOTNULL(notifier, false, "create EventNotifier for %s failed!", pluginName.c_str());
121  
122      pluginCtx->shareMemoryBlock = smb;
123      pluginCtx->eventNotifier = notifier;
124      pluginCtx->profilerPluginState.set_state(ProfilerPluginState::LOADED);
125  
126      pluginServiceImpl_->PushCommand(*pluginCtx->context, cmd);
127  
128      pluginCtx->context->SendFileDescriptor(smb->GetfileDescriptor());
129      pluginCtx->context->SendFileDescriptor(notifier->GetFd());
130  
131      eventPoller_->AddFileDescriptor(notifier->GetFd(), std::bind(&PluginService::ReadShareMemory, this, *pluginCtx));
132      HILOG_DEBUG(LOG_CORE, "CreatePluginSession %s done, shmem fd = %d", pluginName.c_str(), smb->GetfileDescriptor());
133      return true;
134  }
135  
136  // create plugin session without buffer config
CreatePluginSession(const ProfilerPluginConfig & pluginConfig,const ProfilerDataRepeaterPtr & dataRepeater)137  bool PluginService::CreatePluginSession(const ProfilerPluginConfig& pluginConfig,
138                                          const ProfilerDataRepeaterPtr& dataRepeater)
139  {
140      uint32_t pluginId = 0;
141      PluginContextPtr pluginCtx = nullptr;
142      std::string pluginName = pluginConfig.name();
143      std::tie(pluginId, pluginCtx) = GetPluginContext(pluginName);
144      CHECK_NOTNULL(pluginCtx, false, "get PluginContext failed!");
145  
146      pluginCtx->profilerDataRepeater = dataRepeater;
147      pluginCtx->shareMemoryBlock = nullptr;
148  
149      auto cmd = pluginCommandBuilder_->BuildCreateSessionCmd(pluginConfig, 0);
150      CHECK_TRUE(cmd != nullptr, false, "CreatePluginSession BuildCreateSessionCmd FAIL %s", pluginName.c_str());
151  
152      pluginCtx->profilerPluginState.set_state(ProfilerPluginState::LOADED);
153      pluginServiceImpl_->PushCommand(*pluginCtx->context, cmd);
154  
155      HILOG_DEBUG(LOG_CORE, "CreatePluginSession %s done!", pluginName.c_str());
156      return true;
157  }
158  
StartPluginSession(const ProfilerPluginConfig & config)159  bool PluginService::StartPluginSession(const ProfilerPluginConfig& config)
160  {
161      uint32_t pluginId = 0;
162      PluginContextPtr pluginCtx = nullptr;
163      std::string pluginName = config.name();
164      std::tie(pluginId, pluginCtx) = GetPluginContext(pluginName);
165      CHECK_NOTNULL(pluginCtx, false, "get PluginContext failed!");
166  
167      auto cmd = pluginCommandBuilder_->BuildStartSessionCmd(config, pluginId);
168      CHECK_TRUE(cmd != nullptr, false, "StartPluginSession BuildStartSessionCmd FAIL %s", pluginName.c_str());
169  
170      pluginCtx->profilerPluginState.set_state(ProfilerPluginState::IN_SESSION);
171      pluginServiceImpl_->PushCommand(*pluginCtx->context, cmd);
172      HILOG_INFO(LOG_CORE, "StartPluginSession %s done!", pluginName.c_str());
173      return true;
174  }
175  
StopPluginSession(const std::string & pluginName)176  bool PluginService::StopPluginSession(const std::string& pluginName)
177  {
178      uint32_t pluginId = 0;
179      PluginContextPtr pluginCtx = nullptr;
180      std::tie(pluginId, pluginCtx) = GetPluginContext(pluginName);
181      CHECK_NOTNULL(pluginCtx, false, "get PluginContext failed!");
182  
183      auto cmd = pluginCommandBuilder_->BuildStopSessionCmd(pluginId);
184      CHECK_TRUE(cmd != nullptr, false, "StopPluginSession BuildStopSessionCmd FAIL %s", pluginName.c_str());
185  
186      pluginCtx->profilerPluginState.set_state(ProfilerPluginState::LOADED);
187      pluginServiceImpl_->PushCommand(*pluginCtx->context, cmd);
188  
189      auto sem = GetSemaphoreFactory().Create(0);
190      CHECK_NOTNULL(sem, false, "create Semaphore for stop %s FAILED!", pluginName.c_str());
191  
192      waitSemphores_[cmd->command_id()] = sem;
193      HILOG_DEBUG(LOG_CORE, "=== StopPluginSession Waiting ... ===");
194      // wait on semaphore at most 30 seconds.
195      if (!sem->TimedWait(30)) {
196          // semaphore timeout
197          HILOG_DEBUG(LOG_CORE, "=== StopPluginSession Waiting FAIL ===");
198          return false;
199      }
200      ReadShareMemory(*pluginCtx);
201      HILOG_DEBUG(LOG_CORE, "StopPluginSession %s done!", pluginName.c_str());
202      return true;
203  }
204  
DestroyPluginSession(const std::string & pluginName)205  bool PluginService::DestroyPluginSession(const std::string& pluginName)
206  {
207      uint32_t pluginId = 0;
208      PluginContextPtr pluginCtx = nullptr;
209      std::tie(pluginId, pluginCtx) = GetPluginContext(pluginName);
210      CHECK_NOTNULL(pluginCtx, false, "get PluginContext failed!");
211  
212      auto cmd = pluginCommandBuilder_->BuildDestroySessionCmd(pluginId);
213      CHECK_TRUE(cmd != nullptr, false, "DestroyPluginSession BuildDestroySessionCmd FAIL %s", pluginName.c_str());
214  
215      if (pluginCtx->shareMemoryBlock) {
216          ShareMemoryAllocator::GetInstance().ReleaseMemoryBlockLocal(pluginName);
217          pluginCtx->shareMemoryBlock = nullptr;
218      }
219  
220      if (pluginCtx->eventNotifier) {
221          eventPoller_->RemoveFileDescriptor(pluginCtx->eventNotifier->GetFd());
222          pluginCtx->eventNotifier = nullptr;
223      }
224  
225      pluginCtx->profilerPluginState.set_state(ProfilerPluginState::REGISTERED);
226      pluginServiceImpl_->PushCommand(*pluginCtx->context, cmd);
227      HILOG_INFO(LOG_CORE, "DestroyPluginSession %s done!", pluginName.c_str());
228      return true;
229  }
230  
RemovePluginSessionCtx(const std::string & pluginName)231  bool PluginService::RemovePluginSessionCtx(const std::string& pluginName)
232  {
233      PluginContextPtr pluginCtx = GetPluginContext(pluginName).second;
234      CHECK_NOTNULL(pluginCtx, false, "get PluginContext failed!");
235  
236      if (pluginCtx->shareMemoryBlock) {
237          ShareMemoryAllocator::GetInstance().ReleaseMemoryBlockLocal(pluginName);
238          pluginCtx->shareMemoryBlock = nullptr;
239      }
240  
241      if (pluginCtx->eventNotifier) {
242          eventPoller_->RemoveFileDescriptor(pluginCtx->eventNotifier->GetFd());
243          pluginCtx->eventNotifier = nullptr;
244      }
245  
246      pluginCtx->profilerPluginState.set_state(ProfilerPluginState::INITED);
247      HILOG_INFO(LOG_CORE, "RemovePluginSessionCtx %s done!", pluginName.c_str());
248      return true;
249  }
250  
GetPluginContext(const std::string & pluginName)251  std::pair<uint32_t, PluginContextPtr> PluginService::GetPluginContext(const std::string& pluginName)
252  {
253      std::unique_lock<std::mutex> lock(mutex_);
254      CHECK_TRUE(nameIndex_.count(pluginName) > 0, std::make_pair(0, nullptr),
255                 "GetPluginContext failed, plugin name `%s` not found!", pluginName.c_str());
256      uint32_t id = nameIndex_[pluginName];
257  
258      CHECK_TRUE(pluginContext_.count(id) > 0, std::make_pair(id, nullptr), "plugin id %u not found!", id);
259      return std::make_pair(id, pluginContext_[id]);
260  }
261  
GetPluginContextById(uint32_t id)262  PluginContextPtr PluginService::GetPluginContextById(uint32_t id)
263  {
264      std::unique_lock<std::mutex> lock(mutex_);
265      CHECK_TRUE(pluginContext_.count(id) > 0, nullptr, "plugin id %u not found!", id);
266      return pluginContext_[id];
267  }
268  
AddPluginInfo(const PluginInfo & pluginInfo)269  bool PluginService::AddPluginInfo(const PluginInfo& pluginInfo)
270  {
271      if (nameIndex_.find(pluginInfo.name) == nameIndex_.end()) { // add new plugin
272          auto pluginCtx = std::make_shared<PluginContext>();
273          CHECK_NOTNULL(pluginCtx, false, "create PluginContext failed!");
274  
275          ProfilerPluginCapability capability;
276          capability.set_path(pluginInfo.path);
277          capability.set_name(pluginInfo.name);
278          CHECK_TRUE(ProfilerCapabilityManager::GetInstance().AddCapability(capability), false,
279                     "AddPluginInfo AddCapability FAIL");
280  
281          pluginCtx->name = pluginInfo.name;
282          pluginCtx->path = pluginInfo.path;
283          pluginCtx->context = pluginInfo.context;
284          pluginCtx->config.set_name(pluginInfo.name);
285          pluginCtx->config.set_plugin_sha256(pluginInfo.sha256);
286          pluginCtx->profilerPluginState.set_name(pluginInfo.name);
287          pluginCtx->profilerPluginState.set_state(ProfilerPluginState::REGISTERED);
288          pluginCtx->sha256 = pluginInfo.sha256;
289          pluginCtx->bufferSizeHint = pluginInfo.bufferSizeHint;
290  
291          uint32_t pluginId = ++pluginIdCounter_;
292          std::unique_lock<std::mutex> lock(mutex_);
293          pluginContext_[pluginId] = pluginCtx;
294          nameIndex_[pluginInfo.name] = pluginId;
295      } else { // update sha256 or bufferSizeHint
296          std::unique_lock<std::mutex> lock(mutex_);
297          CHECK_TRUE(nameIndex_.count(pluginInfo.name) > 0, false, "plugin name %s not found!", pluginInfo.name.c_str());
298  
299          uint32_t pluginId = nameIndex_[pluginInfo.name];
300          CHECK_TRUE(pluginContext_.count(pluginId) > 0, false, "plugin id %u not found!", pluginId);
301          auto pluginCtx = pluginContext_[pluginId];
302  
303          if (pluginInfo.sha256 != "") {
304              pluginCtx->sha256 = pluginInfo.sha256;
305          }
306          if (pluginInfo.bufferSizeHint != 0) {
307              pluginCtx->bufferSizeHint = pluginInfo.bufferSizeHint;
308          }
309      }
310      HILOG_DEBUG(LOG_CORE, "AddPluginInfo for %s done!", pluginInfo.name.c_str());
311  
312      return true;
313  }
314  
GetPluginInfo(const std::string & pluginName,PluginInfo & pluginInfo)315  bool PluginService::GetPluginInfo(const std::string& pluginName, PluginInfo& pluginInfo)
316  {
317      uint32_t pluginId = 0;
318      PluginContextPtr pluginCtx = nullptr;
319      std::tie(pluginId, pluginCtx) = GetPluginContext(pluginName);
320      CHECK_TRUE(pluginId, false, "plugin name %s not found!", pluginName.c_str());
321      CHECK_TRUE(pluginCtx, false, "plugin id %u not found!", pluginId);
322  
323      pluginInfo.id = pluginId;
324      pluginInfo.name = pluginCtx->name;
325      pluginInfo.path = pluginCtx->path;
326      pluginInfo.sha256 = pluginCtx->sha256;
327      pluginInfo.bufferSizeHint = pluginCtx->bufferSizeHint;
328      return true;
329  }
330  
RemovePluginInfo(const PluginInfo & pluginInfo)331  bool PluginService::RemovePluginInfo(const PluginInfo& pluginInfo)
332  {
333      uint32_t pluginId = pluginInfo.id;
334      PluginContextPtr pluginCtx = GetPluginContextById(pluginId);
335      CHECK_NOTNULL(pluginCtx, false, "RemovePluginInfo failed, id %d not found!", pluginId);
336  
337      std::string pluginName = pluginCtx->config.name();
338      CHECK_TRUE(ProfilerCapabilityManager::GetInstance().RemoveCapability(pluginName), false,
339                 "RemovePluginInfo RemoveCapability FAIL %d", pluginId);
340  
341      auto pluginState = pluginCtx->profilerPluginState.state();
342      if (pluginState == ProfilerPluginState::LOADED || pluginState == ProfilerPluginState::IN_SESSION) {
343          std::vector<std::string> pluginNames = {pluginName};
344          pluginSessionManager_->InvalidatePluginSessions(pluginNames);
345          pluginSessionManager_->RemovePluginSessions(pluginNames);
346          this->RemovePluginSessionCtx(pluginName);
347      }
348  
349      std::unique_lock<std::mutex> lock(mutex_);
350      nameIndex_.erase(pluginName);
351      pluginContext_.erase(pluginId);
352      HILOG_DEBUG(LOG_CORE, "RemovePluginInfo for %s done!", pluginName.c_str());
353      return true;
354  }
355  
ReadShareMemory(PluginContext & context)356  void PluginService::ReadShareMemory(PluginContext& context)
357  {
358      CHECK_NOTNULL(context.shareMemoryBlock, NO_RETVAL, "smb of %s is null!", context.path.c_str());
359      uint64_t value = 0;
360      if (context.eventNotifier) {
361          value = context.eventNotifier->Take();
362      }
363      while (true) {
364          auto pluginData = std::make_shared<ProfilerPluginData>();
365          bool ret = context.shareMemoryBlock->TakeData([&](const int8_t data[], uint32_t size) -> bool {
366              int retval = pluginData->ParseFromArray(reinterpret_cast<const char*>(data), size);
367              CHECK_TRUE(retval, false, "parse %d bytes failed!", size);
368              return true;
369          });
370          if (!ret) {
371              break;
372          }
373          if (!context.profilerDataRepeater->PutPluginData(pluginData)) {
374              break;
375          }
376      }
377  }
378  
AppendResult(NotifyResultRequest & request)379  bool PluginService::AppendResult(NotifyResultRequest& request)
380  {
381      pluginCommandBuilder_->GetedCommandResponse(request.command_id());
382      auto sem = GetSemaphore(request.command_id());
383      if (sem) {
384          sem->Post();
385      }
386  
387      int size = request.result_size();
388      HILOG_DEBUG(LOG_CORE, "AppendResult size:%d, cmd id:%d", size, request.command_id());
389      for (int i = 0; i < size; i++) {
390          PluginResult pr = request.result(i);
391          if (pr.data().size() > 0) {
392              HILOG_DEBUG(LOG_CORE, "AppendResult Size : %zu", pr.data().size());
393              uint32_t pluginId = pr.plugin_id();
394              PluginContextPtr pluginCtx = GetPluginContextById(pluginId);
395              CHECK_NOTNULL(pluginCtx, false, "plugin id %u not found!", pluginId);
396              if (pluginCtx->profilerDataRepeater == nullptr) {
397                  HILOG_DEBUG(LOG_CORE, "AppendResult profilerDataRepeater==nullptr %s %d", pr.status().name().c_str(),
398                              pluginId);
399                  return false;
400              }
401              auto pluginData = std::make_shared<ProfilerPluginData>();
402              pluginData->set_name(pr.status().name());
403              pluginData->set_status(0);
404              pluginData->set_data(pr.data());
405              if (!pluginCtx->profilerDataRepeater->PutPluginData(pluginData)) {
406                  return false;
407              }
408          } else {
409              HILOG_DEBUG(LOG_CORE, "Flush?Data From ShareMemory?");
410          }
411      }
412      return true;
413  }
414  
GetPluginStatus()415  std::vector<ProfilerPluginState> PluginService::GetPluginStatus()
416  {
417      std::vector<ProfilerPluginState> status;
418      std::unique_lock<std::mutex> lock(mutex_);
419      for (auto& entry : pluginContext_) {
420          status.push_back(entry.second->profilerPluginState);
421      }
422      return status;
423  }
424  
GetPluginIdByName(std::string name)425  uint32_t PluginService::GetPluginIdByName(std::string name)
426  {
427      std::unique_lock<std::mutex> lock(mutex_);
428      if (nameIndex_.find(name) == nameIndex_.end()) {
429          return 0;
430      }
431      return nameIndex_[name];
432  }
433