File NPPluginManager.cxx
File List > core > NPPluginManager.cxx
Go to the documentation of this file
#include "NPPluginManager.h"
#include "NPException.h"
#include "NPFunction.h"
#include <dlfcn.h>
#include <filesystem>
#include <fstream>
#include <iostream>
namespace fs = std::filesystem;
nptool::PluginManager::PluginManager() {}
nptool::PluginManager::~PluginManager() {
// Stop services
}
void* nptool::PluginManager::LoadPlugin(std::string name, bool allow_absent_plugin) {
// Is it already loaded?
auto itH = m_handle.find(name);
if (itH != m_handle.end())
return m_handle[name];
// Does it exist ?
auto it = m_available.find(name);
if (it != m_available.end()) {
// find where is the project base directory
bool found_project_base = false;
fs::path root = ("/");
fs::path project_base = fs::current_path();
fs::path project_yaml("project.yaml");
fs::path project_install("install");
while (!(fs::exists(project_base / project_yaml) && fs::exists(project_base / project_yaml))) {
project_base = project_base.parent_path();
if (project_base == root) {
break;
}
}
if (project_base != root) {
found_project_base = true;
}
nptool::message("green", "core", "PluginManager::LoadPlugin",
"Found project base directory: " + project_base.string());
// try load a duplicate version of the library
bool is_local = true;
std::string local_path = it->second;
auto pos = local_path.find_last_of("/");
local_path = project_base.string() + "/install/lib/" + local_path.substr(pos + 1);
void* handle = dlopen(local_path.c_str(), RTLD_LAZY | RTLD_GLOBAL);
// get the error if any
char* LibError = dlerror();
std::string error;
if (LibError) {
error = LibError;
if (error.find("usedToIdentifyRootClingByDlSym") == std::string::npos) {
// fall back to
handle = dlopen(it->second.c_str(), RTLD_LAZY | RTLD_GLOBAL);
is_local = false;
LibError = dlerror();
if (LibError) {
error = LibError;
if (error.find("usedToIdentifyRootClingByDlSym") == std::string::npos) {
std::string msg = "Fail to load plugin library with error: ";
msg += LibError;
throw nptool::Error("PluginManager", msg);
}
}
}
}
if (is_local)
nptool::message("green", "core", "PluginManager::LoadPlugin",
"Loaded duplicate plugin " + name + " at " + local_path);
else
nptool::message("green", "core", "PluginManager::LoadPlugin", "Loaded plugin " + name + " at " + it->second);
m_handle[name] = handle;
// Check for Data Input Constructor method
std::shared_ptr<nptool::VDataInput> (*data_input_construct)();
data_input_construct = (std::shared_ptr<nptool::VDataInput>(*)())dlsym(handle, "ConstructDataInput");
if (data_input_construct) {
m_DataInputConstruct[name] = data_input_construct;
}
// Check for Data Output Constructor method
std::shared_ptr<nptool::VDataOutput> (*data_output_construct)();
data_output_construct = (std::shared_ptr<nptool::VDataOutput>(*)())dlsym(handle, "ConstructDataOutput");
if (data_output_construct) {
m_DataOutputConstruct[name] = data_output_construct;
}
// Check for User Interface Constructor method
std::shared_ptr<nptool::VUserInterface> (*user_interface_construct)();
user_interface_construct = (std::shared_ptr<nptool::VUserInterface>(*)())dlsym(handle, "ConstructUserInterface");
if (user_interface_construct) {
m_UserInterfaceConstruct[name] = user_interface_construct;
}
// Check for User Analysis Constructor method
std::shared_ptr<nptool::VUserAnalysis> (*user_analysis_construct)();
user_analysis_construct = (std::shared_ptr<nptool::VUserAnalysis>(*)())dlsym(handle, "ConstructUserAnalysis");
if (user_analysis_construct)
m_UserAnalysisConstruct[name] = user_analysis_construct;
// Check for Detector Constructor method
std::shared_ptr<nptool::VDetector> (*detector_construct)();
detector_construct = (std::shared_ptr<nptool::VDetector>(*)())dlsym(handle, "ConstructDetector");
if (detector_construct)
m_DetectorConstruct[name] = detector_construct;
// Check for PrimaryGenerator Constructor method
std::shared_ptr<nptool::VPrimaryGenerator> (*primary_construct)();
primary_construct = (std::shared_ptr<nptool::VPrimaryGenerator>(*)())dlsym(handle, "ConstructPrimaryGenerator");
if (primary_construct)
m_PrimaryGeneratorConstruct[name] = primary_construct;
// Check for ReactionGenerator Constructor method
std::shared_ptr<nptool::VReactionGenerator> (*reaction_construct)();
reaction_construct = (std::shared_ptr<nptool::VReactionGenerator>(*)())dlsym(handle, "ConstructReactionGenerator");
if (reaction_construct)
m_ReactionGeneratorConstruct[name] = reaction_construct;
// Check for PhysicsProcess Constructor method
std::shared_ptr<nptool::VPhysicsProcess> (*process_construct)();
process_construct = (std::shared_ptr<nptool::VPhysicsProcess>(*)())dlsym(handle, "ConstructPhysicsProcess");
if (process_construct)
m_PhysicsProcessConstruct[name] = process_construct;
}
else if (!allow_absent_plugin) {
std::string msg = "Requested plugin does not exist: ";
msg += name;
throw nptool::Warning("PluginManager", msg);
}
return m_handle[name];
}
void nptool::PluginManager::LoadPluginList(std::string file, bool allow_fail) {
std::ifstream f(file);
if (!f.is_open()) {
if (!allow_fail) {
std::string msg = "Fail to open plugin-token file " + file;
throw nptool::Error("PluginManager", msg);
}
else
return;
}
std::string package, token, lib;
std::string path = getenv("NPTOOL_HOME");
if (path.back() != '/')
path += "/";
path += getenv("NPTOOL_ENV");
path += "/lib";
while (f >> package >> token >> lib) {
std::string lib_path = path + "/" + lib;
m_available[token] = lib_path;
}
}
std::shared_ptr<nptool::VDataInput> nptool::PluginManager::ConstructDataInput(std::string name) {
// if plugin does not exist, load it
if (m_handle.find(name) == m_handle.end())
LoadPlugin(name);
// check that the construct exist
if (m_DataInputConstruct.find(name) != m_DataInputConstruct.end()) {
auto input = m_DataInputConstruct[name]();
m_inputs.insert(std::make_pair(name, input));
return input;
}
return nullptr;
}
std::shared_ptr<nptool::VDataOutput> nptool::PluginManager::ConstructDataOutput(std::string name) {
// if plugin does not exist, load it
if (m_handle.find(name) == m_handle.end())
LoadPlugin(name);
// check that the construct exist
if (m_DataOutputConstruct.find(name) != m_DataOutputConstruct.end()) {
auto output = m_DataOutputConstruct[name]();
m_outputs.insert(std::make_pair(name, output));
return output;
}
return nullptr;
}
std::shared_ptr<nptool::VUserInterface> nptool::PluginManager::ConstructUserInterface(std::string name) {
// if plugin does not exist, load it
if (m_handle.find(name) == m_handle.end()) {
LoadPlugin(name);
}
// check that the construct exist
if (m_UserInterfaceConstruct.find(name) != m_UserInterfaceConstruct.end()) {
auto interface = m_UserInterfaceConstruct[name]();
m_interfaces.insert(std::make_pair(name, interface));
return interface;
}
return nullptr;
}
std::shared_ptr<nptool::VUserAnalysis> nptool::PluginManager::ConstructUserAnalysis(std::string name) {
// if plugin does not exist, load it
if (m_handle.find(name) == m_handle.end())
LoadPlugin(name);
// check that the construct exist
if (m_UserAnalysisConstruct.find(name) != m_UserAnalysisConstruct.end())
return m_UserAnalysisConstruct[name]();
return nullptr;
}
std::shared_ptr<nptool::VPrimaryGenerator> nptool::PluginManager::ConstructPrimaryGenerator(std::string name) {
// if plugin does not exist, load it
if (m_handle.find(name) == m_handle.end())
LoadPlugin(name);
// check that the construct exist
if (m_PrimaryGeneratorConstruct.find(name) != m_PrimaryGeneratorConstruct.end())
return m_PrimaryGeneratorConstruct[name]();
return nullptr;
}
std::shared_ptr<nptool::VReactionGenerator> nptool::PluginManager::ConstructReactionGenerator(std::string name) {
// if plugin does not exist, load it
if (m_handle.find(name) == m_handle.end())
LoadPlugin(name);
// check that the construct exist
if (m_ReactionGeneratorConstruct.find(name) != m_ReactionGeneratorConstruct.end())
return m_ReactionGeneratorConstruct[name]();
return nullptr;
}
std::shared_ptr<nptool::VPhysicsProcess> nptool::PluginManager::ConstructPhysicsProcess(std::string name) {
// if plugin does not exist, load it
if (m_handle.find(name) == m_handle.end())
LoadPlugin(name);
// check that the construct exist
if (m_PhysicsProcessConstruct.find(name) != m_PhysicsProcessConstruct.end())
return m_PhysicsProcessConstruct[name]();
return nullptr;
}
std::shared_ptr<nptool::VDetector> nptool::PluginManager::ConstructDetector(std::string name) {
// if plugin does not exist, load it
if (m_handle.find(name) == m_handle.end())
LoadPlugin(name);
// check that the construct exist
if (m_DetectorConstruct.find(name) != m_DetectorConstruct.end())
return m_DetectorConstruct[name]();
return nullptr;
}