addon_manager.cpp
Go to the documentation of this file.
1 
14 #include <opc/common/exception.h>
15 
16 #include <iostream>
17 #include <map>
18 
19 namespace
20 {
21 struct AddonData
22 {
23  Common::AddonId Id;
24  Common::AddonFactory::SharedPtr Factory;
25  std::vector<Common::AddonId> Dependencies;
26  Common::AddonParameters Parameters;
27  Common::Addon::SharedPtr Addon;
28 
29  AddonData(const Common::AddonInformation & configuration)
30  : Id(configuration.Id)
31  , Factory(configuration.Factory)
32  , Dependencies(configuration.Dependencies)
33  , Parameters(configuration.Parameters)
34  {
35  }
36 };
37 
38 bool IsAddonNotStarted(const std::pair<Common::AddonId, AddonData> & addonData)
39 {
40  return addonData.second.Addon == Common::Addon::SharedPtr();
41 }
42 
43 class AddonsManagerImpl : public Common::AddonsManager
44 {
45  typedef std::map<Common::AddonId, AddonData> AddonList;
46 
47 public:
48  AddonsManagerImpl(const Common::Logger::SharedPtr & logger)
49  : Common::AddonsManager(logger)
50  , ManagerStarted(false)
51  {
52  }
53 
54  virtual ~AddonsManagerImpl()
55  {
56  try
57  {
58  if (ManagerStarted)
59  {
60  Stop();
61  }
62  }
63 
64  catch (const Common::Error & err)
65  {
66  LOG_ERROR(Logger, "addons_manager | error: {}", err.GetFullMessage());
67  }
68 
69  catch (...)
70  {
71  LOG_ERROR(Logger, "addons_manager | unknown exception, terminating");
72  std::terminate();
73  }
74  }
75 
76  virtual void Register(const Common::AddonInformation & addonConfiguration)
77  {
78  // TODO lock manager
79  if (ManagerStarted && !addonConfiguration.Dependencies.empty())
80  {
82  }
83 
84  EnsureAddonNotRegistered(addonConfiguration.Id);
85  Addons.insert(std::make_pair(addonConfiguration.Id, AddonData(addonConfiguration)));
86 
87  if (ManagerStarted)
88  {
89  DoStart();
90  }
91  }
92 
93  virtual void Unregister(const Common::AddonId & id)
94  {
95  // TODO lock manager
96  EnsureAddonRegistered(id);
97  AddonData & addonData = Addons.find(id)->second;
98 
99  if (addonData.Addon)
100  {
101  addonData.Addon->Stop();
102  }
103 
104  Addons.erase(id);
105  }
106 
107  virtual Common::Addon::SharedPtr GetAddon(const Common::AddonId & id) const
108  {
109  // TODO lock manager
110  EnsureAddonRegistered(id);
111  EnsureAddonInitialized(id);
112  return Addons.find(id)->second.Addon;
113  }
114 
115  virtual void Start()
116  {
117  if (ManagerStarted)
118  {
120  }
121 
122  // TODO lock manager
123  if (!DoStart())
124  {
125  StopAddons();
127  }
128 
129  ManagerStarted = true;
130  }
131 
132  virtual void Stop()
133  {
134  if (!ManagerStarted)
135  {
137  }
138 
139  StopAddons();
140  ManagerStarted = false;
141  }
142 private:
143  void StopAddons()
144  {
145  if (Addons.empty())
146  { return; }
147 
148  while (AddonData * addonData = GetNextAddonDataForStop())
149  {
150  try
151  {
152  //std::cout << "Stopping addon '" << addonData->Id << "'" << std::endl;
153  addonData->Addon->Stop();
154  addonData->Addon.reset();
155  //std::cout << "Addon '" << addonData->Id << "' successfully stopped." << std::endl;
156  }
157 
158  catch (const std::exception & exc)
159  {
160  LOG_ERROR(Logger, "addons_manager | failed to stop addon '{}': {}", addonData->Id, exc.what());
161  }
162  }
163 
164  Addons.clear();
165  }
166 
167  bool DoStart()
168  {
169  while (AddonData * addonData = GetNextAddonDataForStart())
170  {
171  //std::cout << "Creating addon '" << addonData->Id << "'" << std::endl;
172  Common::Addon::SharedPtr addon = addonData->Factory->CreateAddon();
173 
174  //std::cout << "Initializing addon '" << addonData->Id << "'" << std::endl;
175  try
176  {
177  addon->Initialize(*this, addonData->Parameters);
178  //std::cout << "Addon '" << addonData->Id << "' successfully initialized." << std::endl;
179  }
180 
181  catch (const std::exception & exc)
182  {
183  LOG_ERROR(Logger, "addons_manager | failed to initialize addon '{}': {}", addonData->Id, exc.what());
184  return false;
185  }
186 
187  addonData->Addon = addon;
188  }
189 
190  EnsureAllAddonsStarted();
191  return true;
192  }
193 
194  AddonData * GetNextAddonDataForStart()
195  {
196  for (AddonList::iterator it = Addons.begin(); it != Addons.end(); ++it)
197  {
198  if (!IsAddonStarted(it->second) && IsAllAddonsStarted(it->second.Dependencies))
199  {
200  return &it->second;
201  }
202  }
203 
204  return 0;
205  }
206 
207 
208  AddonData * GetNextAddonDataForStop()
209  {
210  for (AddonList::iterator it = Addons.begin(); it != Addons.end(); ++it)
211  {
212  if (IsAddonStarted(it->second) && IsAllDependentAddonsStopped(it->first))
213  {
214  return &it->second;
215  }
216  }
217 
218  return 0;
219  }
220 
221  bool IsAddonStarted(const AddonData & addonData) const
222  {
223  return static_cast<bool>(addonData.Addon);
224  }
225 
226  bool IsAllAddonsStarted(const std::vector<Common::AddonId> & ids) const
227  {
228  for (std::vector<Common::AddonId>::const_iterator it = ids.begin(); it != ids.end(); ++it)
229  {
230  const AddonList::const_iterator addonIt = Addons.find(*it);
231 
232  if (addonIt == Addons.end())
233  {
235  }
236 
237  if (!IsAddonStarted(addonIt->second))
238  {
239  return false;
240  }
241  }
242 
243  return true;
244  }
245 
246  bool IsAllDependentAddonsStopped(const Common::AddonId & id) const
247  {
248  for (const AddonList::value_type & addonIt : Addons)
249  {
250  // Skip alreay stopped addons.
251  if (!IsAddonStarted(addonIt.second))
252  {
253  continue;
254  }
255 
256  // If current addon depends on passed.
257  const std::vector<Common::AddonId> & deps = addonIt.second.Dependencies;
258 
259  if (std::find(deps.begin(), deps.end(), id) != deps.end())
260  {
261  return false;
262  }
263  }
264 
265  return true;
266  }
267 
268  void EnsureAddonInitialized(Common::AddonId id) const
269  {
270  if (!Addons.find(id)->second.Addon)
271  {
273  }
274  }
275 
276  void EnsureAddonRegistered(Common::AddonId id) const
277  {
278  if (!IsAddonRegistered(id))
279  {
281  }
282  }
283 
284  void EnsureAddonNotRegistered(Common::AddonId id) const
285  {
286  if (IsAddonRegistered(id))
287  {
289  }
290  }
291 
292  bool IsAddonRegistered(Common::AddonId id) const
293  {
294  return Addons.find(id) != Addons.end();
295  }
296 
297  void EnsureAllAddonsStarted() const
298  {
299  AddonList::const_iterator addonIt = std::find_if(Addons.begin(), Addons.end(), IsAddonNotStarted);
300 
301  if (!Addons.empty() && addonIt != Addons.end())
302  {
303  THROW_ERROR1(AddonIsNotStarted, addonIt->first);
304  }
305  }
306 
307 private:
308  AddonList Addons;
309  bool ManagerStarted;
310 };
311 }
312 
313 Common::AddonsManager::UniquePtr Common::CreateAddonsManager(const Common::Logger::SharedPtr & logger)
314 {
315  return AddonsManager::UniquePtr(new AddonsManagerImpl(logger));
316 }
317 
std::string GetFullMessage() const
Definition: exception.cpp:59
#define THROW_ERROR(data)
Definition: exception.h:207
Addon interface definition GNU LGPL.
Common::ErrorData AddonIsNotStarted
Common::ErrorData AddonRegisteredButShouldnt
#define LOG_ERROR(__logger__,...)
Definition: common/logger.h:27
Common::ErrorData AddonNotFound
Common::ErrorData AddonsManagerAlreadyStarted
std::vector< AddonId > Dependencies
Definition: addon_manager.h:33
AddonsManager::UniquePtr CreateAddonsManager(const Common::Logger::SharedPtr &logger)
Get instance of addons core.
Common::ErrorData UnableToRegisterAddonWhenStarted
Errors of Addons Manager GNU LGPL.
std::string AddonId
Definition: addon_manager.h:24
#define THROW_ERROR1(data, param1)
Definition: exception.h:212
Common::ErrorData AddonsManagerAlreadyStopped
Common::ErrorData AddonNotRegistered
Common::ErrorData FailedToStartAddons
Common::ErrorData AddonNotInitializedYet


ros_opcua_impl_freeopcua
Author(s): Denis Štogl
autogenerated on Tue Jan 19 2021 03:06:03