nnc: Implement PluginManager class (#273)
authorVitaliy Cherepanov/AI Tools Lab/Engineer/삼성전자 <v.cherepanov@samsung.com>
Mon, 4 Jun 2018 09:50:08 +0000 (12:50 +0300)
committerSergey Vostokov/AI Tools Lab/Staff Engineer/삼성전자 <s.vostokov@samsung.com>
Mon, 4 Jun 2018 09:50:08 +0000 (12:50 +0300)
nnc: Implement PluginsManager class

This class will search, load, initialize plugins and
delegate plugins to modules by plugin type

Signed-off-by: Vitaliy Cherepanov <v.cherepanov@samsung.com>
contrib/nnc/include/module/plugin/PluginManager.h [new file with mode: 0644]
contrib/nnc/src/module/plugin/PluginManager.cpp [new file with mode: 0644]

diff --git a/contrib/nnc/include/module/plugin/PluginManager.h b/contrib/nnc/include/module/plugin/PluginManager.h
new file mode 100644 (file)
index 0000000..9b2eeb4
--- /dev/null
@@ -0,0 +1,63 @@
+#ifndef __PLUGIN_MANAGER_H__
+#define __PLUGIN_MANAGER_H__
+
+#include <vector>
+
+#include "PluginData.h"
+#include "PluginProxy.h"
+#include "module/AbstractModule.h"
+
+namespace nncc
+{
+namespace contrib
+{
+namespace module
+{
+namespace plugin
+{
+
+class PluginManagerException : public foundation::Exception
+{
+public:
+  PluginManagerException() = delete;
+  explicit PluginManagerException(const std::string &info);
+  PluginManagerException(Exception &e, const std::string &info);
+};
+
+class PluginManager
+{
+public:
+  static const std::string paramPluginPath;
+  static const std::string paramVerboseLoading;
+  static const std::string paramPluginHelp;
+
+  PluginManager();
+
+  void setConfig(std::shared_ptr<config::DataList> conf);
+  void loadPlugins(std::vector<AbstractModule *> &modules);
+  static PluginManager &getInstance();
+  void help() const;
+
+  friend std::ostream &operator<<(std::ostream &st, const PluginManager &mod);
+
+private:
+  std::vector<std::string> getPluginPathList();
+
+  void applyParam(const std::string &name);
+  void applyParam(const std::string &name, const std::string &value);
+
+  std::vector<AbstractModule *> _modules;
+
+  std::vector<std::shared_ptr<PluginProxy>> _plugins;
+  std::shared_ptr<config::DataList> _config;
+  std::string _pluginsPath;
+  std::vector<config::PluginParam> _supportedParams;
+  bool _showPluginInfo;
+};
+
+} // namespace plugin
+} // namespace module
+} // namespace contrib
+} // namespace nncc
+
+#endif // __PLUGIN_MANAGER_H__
diff --git a/contrib/nnc/src/module/plugin/PluginManager.cpp b/contrib/nnc/src/module/plugin/PluginManager.cpp
new file mode 100644 (file)
index 0000000..2729cc3
--- /dev/null
@@ -0,0 +1,197 @@
+#include <iostream>
+#include <dlfcn.h>
+#include <dirent.h>
+#include <cstring>
+
+#include "module/plugin/PluginProxy.h"
+#include "module/plugin/PluginSession.h"
+#include "module/plugin/PluginManager.h"
+
+#include "PluginException.h"
+#include "ConfigException.h"
+
+namespace nncc
+{
+namespace contrib
+{
+namespace module
+{
+namespace plugin
+{
+
+const std::string PluginManager::paramPluginPath = "plugins-path";
+const std::string PluginManager::paramVerboseLoading = "plugins-verbose";
+const std::string PluginManager::paramPluginHelp = "plugins-help";
+
+std::vector<std::string> PluginManager::getPluginPathList() {
+  std::vector<std::string> pluginPathList;
+  std::vector<std::string> dirList;
+
+  // Push first path
+  dirList.clear();
+  dirList.push_back(_pluginsPath);
+
+  while (!dirList.empty()) {
+    const auto curPluginsPath = dirList.back();
+    dirList.pop_back();
+
+    DIR *dir;
+    struct dirent *ent;
+    if ((dir = opendir(curPluginsPath.c_str())) != nullptr) {
+      while ((ent = readdir(dir)) != nullptr) {
+        if ((ent->d_type == DT_DIR) && (std::string(ent->d_name) != ".") &&
+            (std::string(ent->d_name) != "..")) {
+          std::string f = curPluginsPath + std::string("/") + std::string(ent->d_name);
+          dirList.push_back(f);
+        } else if (strstr(ent->d_name, ".so") != nullptr) {
+          std::string f = curPluginsPath + std::string("/") + std::string(ent->d_name);
+          pluginPathList.push_back(f);
+        }
+      }
+      closedir(dir);
+    } else {
+      // could not open directory
+      // TODO add some log
+    }
+  }
+  return pluginPathList;
+}
+
+void PluginManager::loadPlugins(std::vector<AbstractModule *> &modules) {
+  std::cout << "Current plugin path is <" << _pluginsPath << ">" << std::endl;
+  auto plugins = getPluginPathList();
+
+  for (const auto &pluginPath : plugins) {
+    try {
+      auto pl = PluginProxy::create(pluginPath);
+      auto plInst = pl->getPluginInstance();
+      std::shared_ptr<config::AbstractSession> session = std::make_shared<config::PluginSession>();
+      plInst->setSession(session);
+      plInst->fillSession();
+
+      if (_showPluginInfo)
+        std::cout << "plugin <" + pluginPath + ">: {" << std::endl
+                  << "name <" + pl->getPluginName() + "> " << std::endl
+                  << dynamic_cast<config::PluginSession &>(*session) << std::endl
+                  << "}" << std::endl;
+
+      _plugins.push_back(pl);
+    }
+    catch (PluginException &e) {
+      if (_showPluginInfo)
+        std::cout << "plugin <" + pluginPath << ">: {" << std::endl
+                  << "bad plugin :" << e.what() << std::endl
+                  << "}" << std::endl;
+    }
+    catch (config::DataException &eOp) {
+      std::cout << "bad plugin info <" + pluginPath << ">:" << eOp.what() << std::endl;
+    }
+  }
+
+  if (_plugins.empty())
+    throw PluginManagerException("No plugins found");
+
+  // Fill modules by plugins
+  for (auto &pl : _plugins) {
+    for (auto m : modules) {
+      auto session =
+          dynamic_cast<config::PluginSession *>(pl->getPluginInstance()->getSession().get());
+      if (m->getModuleType() == session->getPluginType()) {
+        m->registerPlugin(pl);
+        break;
+      }
+    }
+  }
+
+  for (auto m : modules) {
+    std::cout << *m;
+  }
+}
+
+std::ostream &operator<<(std::ostream &st, const PluginManager &mod) {
+  for (const auto &pl : mod._plugins)
+    st << pl << std::endl;
+  return st;
+}
+
+PluginManager &PluginManager::getInstance() {
+  static PluginManager instance;
+  return instance;
+}
+
+void PluginManager::setConfig(std::shared_ptr<config::DataList> conf) {
+  try {
+    _config = conf;
+    auto plist = config::DataList::intersection(*conf, _supportedParams);
+
+    for (auto &p : plist->getElements()) {
+      if (p.second.hasValue())
+        applyParam(p.second.getName(), p.second.getValue());
+      else
+        applyParam(p.second.getName());
+    }
+  }
+  catch (ConfigException &e) {
+    throw PluginManagerException(e, "config error");
+  }
+  catch (PluginException &e) {
+    throw PluginManagerException(e, "plugin error");
+  }
+}
+
+void PluginManager::applyParam(const std::string &name) {
+  if (name == paramPluginHelp) {
+    help();
+  } else if (name == paramVerboseLoading) {
+    _showPluginInfo = true;
+  } else {
+    std::string info =
+        "[ERR]" + std::string(__func__) + " <" + name + ">" + " WRONG SINGLE PARAMETER";
+    throw ConfigException(info);
+  }
+}
+
+void PluginManager::applyParam(const std::string &name, const std::string &value) {
+  std::cout << __func__ << " <" + name + "> = " + value << std::endl;
+  if (name == paramPluginPath) {
+    _pluginsPath = value;
+  } else {
+    help();
+    std::string info =
+        "[ERR]" + std::string(__func__) + " <" + name + "> = " + value + " WRONG PARAMETER";
+    throw ConfigException(info);
+  }
+}
+
+void PluginManager::help() const {
+  std::cout << "HELP" << std::endl;
+
+  for (auto &p : _supportedParams)
+    if (!p.isOptional())
+      std::cout << "--" << p.getName() << " ";
+
+  for (auto &p : _supportedParams)
+    if (p.isOptional())
+      std::cout << "[--" << p.getName() << "] ";
+  std::cout << std::endl;
+
+  for (auto &p : _supportedParams)
+    std::cout << p << std::endl;
+}
+
+PluginManager::PluginManager() : _config(nullptr), _showPluginInfo(false) {
+  _supportedParams = {{paramPluginPath, "[path]", true},
+                      {paramVerboseLoading, "[show found plugins info]", true},
+                      {paramPluginHelp, "[help]", true}};
+}
+
+PluginManagerException::PluginManagerException(const std::string &info) : Exception(info) {}
+
+PluginManagerException::PluginManagerException(Exception &e, const std::string &info)
+    : Exception(e, info) {
+}
+
+} // namespace plugin
+} // namespace module
+} // namespace contrib
+} // namespace nncc