knowrob  2.1.0
A Knowledge Base System for Cognition-enabled Robots
PluginManager.h
Go to the documentation of this file.
1 /*
2  * This file is part of KnowRob, please consult
3  * https://github.com/knowrob/knowrob for license details.
4  */
5 
6 #ifndef KNOWROB_PLUGIN_MANAGER_H_
7 #define KNOWROB_PLUGIN_MANAGER_H_
8 
9 #include <memory>
10 #include <map>
11 #include <string>
12 #include <mutex>
13 #include <boost/property_tree/ptree.hpp>
14 #include "knowrob/plugins/TypedPluginFactory.h"
15 #include "knowrob/plugins/PluginLibrary.h"
16 #include "knowrob/plugins/PluginModule.h"
17 #include "knowrob/Logger.h"
18 #include "knowrob/URI.h"
19 
20 namespace knowrob {
25  template<class T>
26  class PluginManager {
27  public:
29  std::lock_guard<std::mutex> scoped_lock(staticMutex_);
32  (*pluginManagers_)[managerID_] = this;
33  }
34 
35  virtual ~PluginManager() {
36  {
37  std::lock_guard<std::mutex> scoped_lock(staticMutex_);
39  }
40 
41  for (auto &entry : loadedModules_) {
42  entry.second->unloadModule();
43  }
44  loadedModules_.clear();
45  loadedPlugins_.clear();
46  pluginPool_.clear();
47  }
48 
52  auto managerID() const { return managerID_; }
53 
57  const auto &plugins() const { return pluginPool_; }
58 
64  auto it = pluginManagers()->find(managerID);
65  if (it != pluginManagers()->end()) {
66  return it->second;
67  } else {
68  return nullptr;
69  }
70  }
71 
76  std::shared_ptr<NamedPlugin<T>> getPluginWithID(std::string_view pluginID) {
77  auto it = pluginPool_.find(pluginID);
78  if (it != pluginPool_.end()) {
79  return it->second;
80  } else {
81  return {};
82  }
83  }
84 
92  static bool addFactory(std::string_view typeName, const std::shared_ptr<PluginFactory<T>> &factory) {
93  auto &factories = pluginFactories();
94  if (factories.find(typeName) != factories.end()) {
95  KB_WARN("overwriting factory for plugin type '{}'", typeName);
96  }
97  factories.emplace(typeName, factory);
98  return true;
99  }
100 
105  template<class U>
106  static bool addFactory(std::string_view typeName) {
107  return addFactory(typeName, std::make_shared<TypedPluginFactory<U, T>>(typeName));
108  }
109 
119  virtual std::shared_ptr<NamedPlugin<T>> loadPlugin(const boost::property_tree::ptree &config) = 0;
120 
127  virtual std::shared_ptr<NamedPlugin<T>>
128  addPlugin(std::string_view reasonerID, PluginLanguage language, const std::shared_ptr<T> &reasoner) = 0;
129 
134  void removePlugin(const std::shared_ptr<NamedPlugin<T>> &namedPlugin) { pluginPool_.erase(namedPlugin->name()); }
135 
140  void removePlugin(std::string_view pluginID) { pluginPool_.erase(pluginID); }
141 
142  protected:
143  std::shared_ptr<std::map<uint32_t, PluginManager *>> pluginManagers_;
144  // mutex used to interact with static variables
145  std::mutex staticMutex_;
146  // an identifier for this manager
147  uint32_t managerID_;
148  // a counter used to generate unique IDs
149  uint32_t pluginIndex_ = 0;
150 
151  // pool of all plugin instances created via this manager
152  // maps reasoner ID to reasoner instance.
153  std::map<std::string_view, std::shared_ptr<NamedPlugin<T>>, std::less<>> pluginPool_;
154  // maps plugin names to factories used to create plugin instances
155  std::map<std::string, std::shared_ptr<PluginLibrary<T>>, std::less<>> loadedPlugins_;
156  std::map<std::string, std::shared_ptr<PluginModule<T>>, std::less<>> loadedModules_;
157 
158  // counts number of initialized managers
159  static uint32_t &managerIDCounter() {
160  static uint32_t val = 0;
161  return val;
162  }
163 
164  // a reference to the map of plugin factories
165  static auto &pluginFactories() {
166  static std::map<std::string, std::shared_ptr<PluginFactory<T>>, std::less<>> factories;
167  return factories;
168  }
169 
170  // maps manager id to manager
171  static auto &pluginManagers() {
172  static auto val = std::make_shared<std::map<uint32_t, PluginManager *>>();
173  return val;
174  }
175 
176  std::shared_ptr<PluginLibrary<T>> loadSharedLibrary(std::string_view path) {
177  auto absPath = std::filesystem::absolute(path);
178  auto it = loadedPlugins_.find(absPath);
179  if (it == loadedPlugins_.end()) {
180  auto p = std::make_shared<PluginLibrary<T>>(absPath.c_str());
181  auto jt = loadedPlugins_.insert(std::pair<std::string,
182  std::shared_ptr<PluginLibrary<T>>>(absPath, p));
183  if (jt.first->second->loadDLL()) {
184  return jt.first->second;
185  }
186  } else if (it->second->isLoaded()) {
187  return it->second;
188  }
189  KB_WARN("Failed to open plugin library at path '{}'.", path);
190  return {};
191  }
192 
193  std::shared_ptr<PluginModule<T>> loadPythonModule(std::string_view path, std::string_view type) {
194  auto it = loadedModules_.find(path);
195  if (it == loadedModules_.end()) {
196  auto p = std::make_shared<PluginModule<T>>(path, type);
197  auto jt = loadedModules_.insert(std::pair<std::string,
198  std::shared_ptr<PluginModule<T>>>(path, p));
199  if (jt.first->second->loadModule()) {
200  return jt.first->second;
201  }
202  } else if (it->second->isLoaded()) {
203  return it->second;
204  }
205  KB_WARN("Failed to open plugin module at path '{}'.", path);
206  return {};
207  }
208 
209  std::shared_ptr<PluginFactory<T>> findFactory(const boost::property_tree::ptree &config) {
210  auto lib = config.get_optional<std::string>("lib");
211  auto module = config.get_optional<std::string>("module");
212  auto type = config.get_optional<std::string>("type");
213 
214  if (lib.has_value()) {
215  return loadSharedLibrary(URI::resolve(lib.value()));
216  } else if (module.has_value()) {
217  if (type.has_value()) {
218  return loadPythonModule(URI::resolve(module.value()), type.value());
219  } else {
220  KB_WARN("modules require type key in settings, but it's missing for module '{}'.", module.value());
221  }
222  } else if (type.has_value()) {
223  // map type name to a factory
224  const auto &it = pluginFactories().find(type.value());
225  if (it == pluginFactories().end()) {
226  KB_WARN("no factory registered for plugin type '{}'.", type.value());
227  } else {
228  return it->second;
229  }
230  } else {
231  KB_WARN("missing 'type', 'lib' and 'module' key in plugin config.");
232  }
233  return {};
234  }
235 
237  getPluginID(const std::shared_ptr<PluginFactory<T>> &factory, const boost::property_tree::ptree &config) {
238  auto name = config.get_optional<std::string>("name");
239  if (name.has_value()) {
240  return name.value();
241  } else {
242  return std::string(factory->name()) + std::to_string(pluginIndex_++);
243  }
244  }
245  };
246 }
247 
248 #endif //KNOWROB_PLUGIN_MANAGER_H_
#define KB_WARN
Definition: Logger.h:27
std::shared_ptr< PluginFactory< T > > findFactory(const boost::property_tree::ptree &config)
static bool addFactory(std::string_view typeName, const std::shared_ptr< PluginFactory< T >> &factory)
Definition: PluginManager.h:92
std::shared_ptr< std::map< uint32_t, PluginManager * > > pluginManagers_
std::shared_ptr< PluginModule< T > > loadPythonModule(std::string_view path, std::string_view type)
virtual std::shared_ptr< NamedPlugin< T > > loadPlugin(const boost::property_tree::ptree &config)=0
static PluginManager< T > * getManager(uint32_t managerID)
Definition: PluginManager.h:63
static uint32_t & managerIDCounter()
static bool addFactory(std::string_view typeName)
std::map< std::string, std::shared_ptr< PluginLibrary< T > >, std::less<> > loadedPlugins_
std::shared_ptr< PluginLibrary< T > > loadSharedLibrary(std::string_view path)
static auto & pluginManagers()
std::string getPluginID(const std::shared_ptr< PluginFactory< T >> &factory, const boost::property_tree::ptree &config)
std::shared_ptr< NamedPlugin< T > > getPluginWithID(std::string_view pluginID)
Definition: PluginManager.h:76
std::map< std::string, std::shared_ptr< PluginModule< T > >, std::less<> > loadedModules_
auto managerID() const
Definition: PluginManager.h:52
void removePlugin(const std::shared_ptr< NamedPlugin< T >> &namedPlugin)
std::map< std::string_view, std::shared_ptr< NamedPlugin< T > >, std::less<> > pluginPool_
static auto & pluginFactories()
virtual std::shared_ptr< NamedPlugin< T > > addPlugin(std::string_view reasonerID, PluginLanguage language, const std::shared_ptr< T > &reasoner)=0
void removePlugin(std::string_view pluginID)
const auto & plugins() const
Definition: PluginManager.h:57
static std::string resolve(const std::string_view &uriString)
Definition: URI.cpp:79
TermRule & string()
Definition: terms.cpp:63
const IRIAtomPtr type
Definition: rdf.h:15
PluginLanguage
Definition: NamedPlugin.h:16