Skip to content
Snippets Groups Projects
Commit 16dc7bcf authored by Stéphane Del Pino's avatar Stéphane Del Pino
Browse files

Add plugin loading mechanism

Plugins are loaded through environment variables. Two environment
variables are read: PUGS_PLUGIN and PUGS_PLUGIN_DIR

- PUGS_PLUGIN is a string literal that contains the filename of the
dynamic library that contains plugins. One can provide multiple
filename using semicolumn separators.
  ex. PUGS_PLUGIN="/path/to/my/libplugin1.so;/anotherpath/to/another/libplugin2.so"

- PUGS_PLUGIN_DIR is a string literal that contains directory path
where plugins (dynamic libraries) are.  One can provide multiple path
using semicolumn separators. All the dynamic libraries present at the
locations are loaded!
  ex. PUGS_PLUGIN="/path/to/a/plugin/list/;/anotherpath/to/another/plugin/list/"
parent f096d4c3
No related branches found
No related tags found
1 merge request!200Change strategy for modules registration to the ModuleRepository
...@@ -22,12 +22,19 @@ if("${PUGS_SHORT_VERSION}" STREQUAL "") ...@@ -22,12 +22,19 @@ if("${PUGS_SHORT_VERSION}" STREQUAL "")
message(FATAL_ERROR "Unable to compute short version from PUGS_VERSION=${PUGS_VERSION}") message(FATAL_ERROR "Unable to compute short version from PUGS_VERSION=${PUGS_VERSION}")
endif() endif()
# set project version as PUGS_SHORT_VERSION
project (Pugs VERSION ${PUGS_SHORT_VERSION})
# -----------------------------------------------------
# dynamic libraries
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
link_libraries("-rdynamic")
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib") set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
set(CMAKE_CONFIGURATION_TYPES "Release;Debug;Coverage" CACHE STRING INTERNAL FORCE ) #------------------------------------------------------
# set project version as PUGS_SHORT_VERSION set(CMAKE_CONFIGURATION_TYPES "Release;Debug;Coverage" CACHE STRING INTERNAL FORCE )
project (Pugs VERSION ${PUGS_SHORT_VERSION})
#------------------------------------------------------ #------------------------------------------------------
...@@ -380,6 +387,7 @@ include_directories(SYSTEM "${PUGS_SOURCE_DIR}/packages/rang/include") ...@@ -380,6 +387,7 @@ include_directories(SYSTEM "${PUGS_SOURCE_DIR}/packages/rang/include")
include_directories(SYSTEM "${PUGS_SOURCE_DIR}/packages/CLI11/include") include_directories(SYSTEM "${PUGS_SOURCE_DIR}/packages/CLI11/include")
# PEGTL # PEGTL
add_subdirectory(${PUGS_SOURCE_DIR}/packages/PEGTL/)
include_directories(SYSTEM "${PUGS_SOURCE_DIR}/packages/PEGTL/include/tao") include_directories(SYSTEM "${PUGS_SOURCE_DIR}/packages/PEGTL/include/tao")
# Pugs src # Pugs src
...@@ -597,10 +605,6 @@ if("${CMAKE_BUILD_TYPE}" STREQUAL "Coverage") ...@@ -597,10 +605,6 @@ if("${CMAKE_BUILD_TYPE}" STREQUAL "Coverage")
endif() endif()
endif() endif()
# -----------------------------------------------------
link_libraries("-rdynamic")
# ------------------- Source files -------------------- # ------------------- Source files --------------------
# Pugs binary # Pugs binary
add_executable( add_executable(
......
...@@ -13,6 +13,27 @@ ...@@ -13,6 +13,27 @@
#include <set> #include <set>
ModuleRepository* ModuleRepository::m_instance = nullptr;
ModuleRepository&
ModuleRepository::getInstance()
{
if (m_instance == nullptr) {
m_instance = new ModuleRepository;
}
return *m_instance;
}
void
ModuleRepository::destroy()
{
if (m_instance != nullptr) {
delete m_instance;
m_instance = nullptr;
}
}
void void
ModuleRepository::_subscribe(std::unique_ptr<IModule> m) ModuleRepository::_subscribe(std::unique_ptr<IModule> m)
{ {
......
...@@ -31,13 +31,12 @@ class ModuleRepository ...@@ -31,13 +31,12 @@ class ModuleRepository
const IModule::NameValueMap& name_value_map, const IModule::NameValueMap& name_value_map,
SymbolTable& symbol_table); SymbolTable& symbol_table);
static ModuleRepository* m_instance;
public: public:
static ModuleRepository& static ModuleRepository& getInstance();
getInstance()
{ static void destroy();
static ModuleRepository m_instance;
return m_instance;
}
template <typename ModuleT> template <typename ModuleT>
struct Subscribe struct Subscribe
......
#include <analysis/QuadratureManager.hpp> #include <analysis/QuadratureManager.hpp>
#include <dev/ParallelChecker.hpp> #include <dev/ParallelChecker.hpp>
#include <language/PugsParser.hpp> #include <language/PugsParser.hpp>
#include <language/modules/ModuleRepository.hpp>
#include <mesh/DualConnectivityManager.hpp> #include <mesh/DualConnectivityManager.hpp>
#include <mesh/DualMeshManager.hpp> #include <mesh/DualMeshManager.hpp>
#include <mesh/MeshDataManager.hpp> #include <mesh/MeshDataManager.hpp>
...@@ -11,6 +12,8 @@ ...@@ -11,6 +12,8 @@
#include <utils/RandomEngine.hpp> #include <utils/RandomEngine.hpp>
#include <utils/checkpointing/ResumingManager.hpp> #include <utils/checkpointing/ResumingManager.hpp>
#include <utils/PluginsLoader.hpp>
int int
main(int argc, char* argv[]) main(int argc, char* argv[])
{ {
...@@ -20,6 +23,8 @@ main(int argc, char* argv[]) ...@@ -20,6 +23,8 @@ main(int argc, char* argv[])
std::string filename = initialize(argc, argv); std::string filename = initialize(argc, argv);
PluginsLoader plugins_loader;
SynchronizerManager::create(); SynchronizerManager::create();
RandomEngine::create(); RandomEngine::create();
QuadratureManager::create(); QuadratureManager::create();
...@@ -32,6 +37,8 @@ main(int argc, char* argv[]) ...@@ -32,6 +37,8 @@ main(int argc, char* argv[])
parser(filename); parser(filename);
ExecutionStatManager::printInfo(); ExecutionStatManager::printInfo();
ModuleRepository::destroy();
GlobalVariableManager::destroy(); GlobalVariableManager::destroy();
DualMeshManager::destroy(); DualMeshManager::destroy();
......
...@@ -16,6 +16,7 @@ add_library( ...@@ -16,6 +16,7 @@ add_library(
Messenger.cpp Messenger.cpp
Partitioner.cpp Partitioner.cpp
PETScWrapper.cpp PETScWrapper.cpp
PluginsLoader.cpp
PugsUtils.cpp PugsUtils.cpp
RandomEngine.cpp RandomEngine.cpp
ReproducibleSumManager.cpp ReproducibleSumManager.cpp
......
#include <utils/PluginsLoader.hpp>
#include <dlfcn.h>
#include <rang.hpp>
#include <filesystem>
#include <iostream>
#include <sstream>
#include <unistd.h>
#include <vector>
std::vector<std::string>
split(const std::string& full_string)
{
std::vector<std::string> split_string;
std::stringstream is(full_string);
std::string segment;
while (std::getline(is, segment, ';')) {
if (segment.size() > 0) {
split_string.push_back(segment);
}
}
return split_string;
}
void
PluginsLoader::_open(const std::string& plugin)
{
auto handle = dlopen(plugin.c_str(), RTLD_NOW);
if (handle != nullptr) {
m_dl_handler_stack.push(handle);
std::cout << " * \"" << rang::fgB::green << plugin << rang::fg::reset << "\"\n";
} else {
std::cout << " " << rang::fgB::red << "cannot load " << rang::fg::reset << '\"' << rang::fgB::yellow << plugin
<< rang::fg::reset << "\"\n";
}
}
PluginsLoader::PluginsLoader()
{
std::vector<std::string> plugin_vector;
{
char* env = getenv("PUGS_PLUGIN");
if (env != nullptr) {
std::string plugins = env;
plugin_vector = split(plugins);
}
}
{
char* env = getenv("PUGS_PLUGIN_DIR");
if (env != nullptr) {
std::string paths = env;
std::vector<std::string> path_vector = split(paths);
for (auto&& path : path_vector) {
if (access(path.c_str(), R_OK) == -1) {
std::cout << ' ' << rang::fgB::red << 'X' << rang::fg::reset << " cannot access plugin dir \""
<< rang::fgB::yellow << path << rang::fg::reset << "\"\n";
} else {
for (auto&& entry :
std::filesystem::directory_iterator(path,
(std::filesystem::directory_options::follow_directory_symlink |
std::filesystem::directory_options::skip_permission_denied))) {
if (entry.path().extension() == ".so") {
plugin_vector.push_back(entry.path().string());
}
}
}
}
}
}
// keep unique entries
std::sort(plugin_vector.begin(), plugin_vector.end());
plugin_vector.resize(std::distance(plugin_vector.begin(), std::unique(plugin_vector.begin(), plugin_vector.end())));
if (plugin_vector.size() > 0) {
std::cout << rang::style::bold << "Loading plugins" << rang::style::reset << '\n';
for (auto&& plugin : plugin_vector) {
this->_open(plugin);
}
std::cout << "-------------------------------------------------------\n";
}
}
PluginsLoader::~PluginsLoader()
{
while (not m_dl_handler_stack.empty()) {
dlclose(m_dl_handler_stack.top());
m_dl_handler_stack.pop();
}
}
#ifndef PLUGINS_LOADER_HPP
#define PLUGINS_LOADER_HPP
#include <stack>
#include <string>
class PluginsLoader
{
private:
std::stack<void*> m_dl_handler_stack;
void _open(const std::string& filename);
public:
PluginsLoader();
PluginsLoader(const PluginsLoader&) = delete;
PluginsLoader(PluginsLoader&&) = delete;
~PluginsLoader();
};
#endif // PLUGINS_LOADER_HPP
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment