Commit 83836048 authored by Simon Spannagel's avatar Simon Spannagel
Browse files

Introduce ModuleIdentifier

parent 35efca37
......@@ -11,13 +11,11 @@
using namespace corryvreckan;
Module::Module(Configuration config, std::shared_ptr<Detector> detector)
: Module(config, std::vector<std::shared_ptr<Detector>>{detector}) {}
: Module(std::move(config), std::vector<std::shared_ptr<Detector>>{detector}) {}
Module::~Module() {}
Module::Module(Configuration config, std::vector<std::shared_ptr<Detector>> detectors) {
m_name = config.getName();
m_config = config;
Module::Module(Configuration config, std::vector<std::shared_ptr<Detector>> detectors) : m_config(std::move(config)) {
m_detectors = detectors;
IFLOG(TRACE) {
std::stringstream det;
......@@ -28,6 +26,26 @@ Module::Module(Configuration config, std::vector<std::shared_ptr<Detector>> dete
}
}
/**
* @throws InvalidModuleActionException If this method is called from the constructor
*
* This name is guaranteed to be unique for every single instantiation of all modules
*/
std::string Module::getUniqueName() const {
std::string unique_name = get_identifier().getUniqueName();
if(unique_name.empty()) {
throw InvalidModuleActionException("Cannot uniquely identify module in constructor");
}
return unique_name;
}
void Module::set_identifier(ModuleIdentifier identifier) {
identifier_ = std::move(identifier);
}
ModuleIdentifier Module::get_identifier() const {
return identifier_;
}
std::shared_ptr<Detector> Module::get_detector(std::string name) {
auto it = find_if(
m_detectors.begin(), m_detectors.end(), [&name](std::shared_ptr<Detector> obj) { return obj->name() == name; });
......
......@@ -11,6 +11,7 @@
#include <string>
#include "ModuleIdentifier.hpp"
#include "core/clipboard/Clipboard.hpp"
#include "core/config/Configuration.hpp"
#include "core/detector/Detector.hpp"
......@@ -83,10 +84,11 @@ namespace corryvreckan {
Module& operator=(const Module&) = delete;
/**
* @brief Get the name of this module
* @return Name of the module
* @brief Get the unique name of this module
* @return Unique name
* @note Can be used to interact with ROOT objects that require an unique name
*/
std::string getName() { return m_name; }
std::string getUniqueName() const;
/**
* @brief Get the configuration for this module
......@@ -163,13 +165,22 @@ namespace corryvreckan {
bool has_detector(std::string name);
private:
/**
* @brief Set the module identifier for internal use
* @param identifier Identifier of the instantiation
*/
void set_identifier(ModuleIdentifier identifier);
/**
* @brief Get the module identifier for internal use
* @return Identifier of the instantiation
*/
ModuleIdentifier get_identifier() const;
ModuleIdentifier identifier_;
// Configure the reference detector:
void setReference(std::shared_ptr<Detector> reference) { m_reference = reference; };
std::shared_ptr<Detector> m_reference;
// Name of the module
std::string m_name;
// List of detectors to act on
std::vector<std::shared_ptr<Detector>> m_detectors;
};
......
/**
* @file
* @brief Provide an identifier for module instances
* @copyright Copyright (c) 2017 CERN and the Corryvreckan authors.
* This software is distributed under the terms of the MIT License, copied verbatim in the file "LICENSE.md".
* In applying this license, CERN does not waive the privileges and immunities granted to it by virtue of its status as an
* Intergovernmental Organization or submit itself to any jurisdiction.
*/
#ifndef CORRYVRECKAN_MODULE_IDENTIFIER_H
#define CORRYVRECKAN_MODULE_IDENTIFIER_H
#include <memory>
#include <random>
#include <string>
#include <vector>
namespace corryvreckan {
/**
* @brief Internal identifier for a module
*
* Used by the framework to distinguish between different module instantiations and their priority.
*/
class ModuleIdentifier {
public:
/**
* @brief Constructs an empty identifier
*/
// TODO [doc] Is this method really necessary
ModuleIdentifier() = default;
/**
* @brief Construct an identifier
* @param module_name Name of the module
* @param identifier Unique identifier for the instantiation
* @param prio Priority of this module
*/
ModuleIdentifier(std::string module_name, std::string identifier, int prio)
: name_(std::move(module_name)), identifier_(std::move(identifier)), prio_(prio) {}
/**
* @brief Get the name of the module
* @return Module name
*/
std::string getName() const { return name_; }
/**
* @brief Get the identifier of the instantiation
* @return Module identifier
*/
std::string getIdentifier() const { return identifier_; }
/**
* @brief Get the unique name of the instantiation
* @return Unique module name
*
* The unique name of the module is the name combined with its identifier separated by a semicolon.
*/
std::string getUniqueName() const {
std::string unique_name = name_;
if(!identifier_.empty()) {
unique_name += ":" + identifier_;
}
return unique_name;
}
/**
* @brief Get the priority of the instantiation
* @return Priority level
*
* A lower number indicates a higher priority
*
* @warning It is important to realize that the priority is ordered from high to low numbers
*/
int getPriority() const { return prio_; }
/// @{
/**
* @brief Operators for comparing identifiers
*
* Identifiers are only compared on their unique name, identifiers are not distinguished on priorities
*/
bool operator==(const ModuleIdentifier& other) const { return getUniqueName() == other.getUniqueName(); }
bool operator!=(const ModuleIdentifier& other) const { return getUniqueName() != other.getUniqueName(); }
bool operator<(const ModuleIdentifier& other) const { return getUniqueName() < other.getUniqueName(); }
bool operator<=(const ModuleIdentifier& other) const { return getUniqueName() <= other.getUniqueName(); }
bool operator>(const ModuleIdentifier& other) const { return getUniqueName() > other.getUniqueName(); }
bool operator>=(const ModuleIdentifier& other) const { return getUniqueName() >= other.getUniqueName(); }
/// @}
private:
std::string name_;
std::string identifier_;
int prio_{};
};
} // namespace corryvreckan
#endif
......@@ -311,11 +311,14 @@ void ModuleManager::load_modules() {
// Create the modules from the library
if(global) {
m_modules.emplace_back(create_unique_module(loaded_libraries_[lib_name], config));
auto module = create_unique_module(loaded_libraries_[lib_name], config);
m_modules.push_back(module.second);
m_modules.back()->set_identifier(module.first);
} else {
auto modules = create_detector_modules(loaded_libraries_[lib_name], config, dut_only);
for(const auto& mod : modules) {
m_modules.push_back(mod);
m_modules.push_back(mod.second);
m_modules.back()->set_identifier(mod.first);
}
}
}
......@@ -327,9 +330,12 @@ void ModuleManager::load_modules() {
LOG_PROGRESS(STATUS, "MOD_LOAD_LOOP") << "Loaded " << configs.size() << " modules";
}
Module* ModuleManager::create_unique_module(void* library, Configuration config) {
LOG(TRACE) << "Creating module " << config.getName() << ", using generator \"" << CORRYVRECKAN_GENERATOR_FUNCTION
<< "\"";
std::pair<ModuleIdentifier, Module*> ModuleManager::create_unique_module(void* library, Configuration config) {
// Create the identifier
ModuleIdentifier identifier(config.getName(), "", 0);
LOG(TRACE) << "Creating module " << identifier.getUniqueName() << ", using generator \""
<< CORRYVRECKAN_GENERATOR_FUNCTION << "\"";
// Get the generator function for this module
void* generator = dlsym(library, CORRYVRECKAN_GENERATOR_FUNCTION);
......@@ -386,10 +392,11 @@ Module* ModuleManager::create_unique_module(void* library, Configuration config)
set_module_after(old_settings);
// Return the module to the analysis
return module;
return std::make_pair(identifier, module);
}
std::vector<Module*> ModuleManager::create_detector_modules(void* library, Configuration config, bool dut_only) {
std::vector<std::pair<ModuleIdentifier, Module*>>
ModuleManager::create_detector_modules(void* library, Configuration config, bool dut_only) {
LOG(TRACE) << "Creating instantiations for module " << config.getName() << ", using generator \""
<< CORRYVRECKAN_GENERATOR_FUNCTION << "\"";
......@@ -433,28 +440,26 @@ std::vector<Module*> ModuleManager::create_detector_modules(void* library, Confi
}
}
std::vector<Module*> modules;
std::vector<std::pair<ModuleIdentifier, Module*>> modules;
auto module_base_name = config.getName();
for(const auto& detector : module_det) {
// Set the identifier for this module:
config.setName(module_base_name + "_" + detector->name());
ModuleIdentifier identifier(module_base_name, detector->name(), 0);
// If this should only be instantiated for DUTs, skip otherwise:
if(dut_only && !detector->isDUT()) {
LOG(TRACE) << "Skipping instantiation \"" << config.getName() << "\", detector is no DUT";
LOG(TRACE) << "Skipping instantiation \"" << identifier.getUniqueName() << "\", detector is no DUT";
continue;
}
LOG(TRACE) << "Creating instantiation \"" << config.getName() << "\"";
LOG(TRACE) << "Creating instantiation \"" << identifier.getUniqueName() << "\"";
// Set the log section header
std::string old_section_name = Log::getSection();
std::string section_name = "C:";
section_name += config.getName();
section_name += identifier.getUniqueName();
Log::setSection(section_name);
// Set module specific log settings
auto old_settings = set_module_before(config.getName(), config);
auto old_settings = set_module_before(identifier.getUniqueName(), config);
// Build module
modules.emplace_back(module_generator(config, detector));
modules.emplace_back(identifier, module_generator(config, detector));
// Reset log
Log::setSection(old_section_name);
set_module_after(old_settings);
......@@ -504,12 +509,12 @@ void ModuleManager::run() {
// Set run module section header
std::string old_section_name = Log::getSection();
std::string section_name = "R:";
section_name += module->getName();
section_name += module->getUniqueName();
Log::setSection(section_name);
// Set module specific settings
auto old_settings = set_module_before(module->getName(), module->getConfig());
auto old_settings = set_module_before(module->getUniqueName(), module->getConfig());
// Change to the output file directory
m_directory->cd(module->getName().c_str());
m_directory->cd(module->getUniqueName().c_str());
StatusCode check = module->run(m_clipboard);
// Reset logging
Log::setSection(old_section_name);
......@@ -584,16 +589,16 @@ void ModuleManager::initialiseAll() {
// Set init module section header
std::string old_section_name = Log::getSection();
std::string section_name = "I:";
section_name += module->getName();
section_name += module->getUniqueName();
Log::setSection(section_name);
// Set module specific settings
auto old_settings = set_module_before(module->getName(), module->getConfig());
auto old_settings = set_module_before(module->getUniqueName(), module->getConfig());
// Make a new folder in the output file
m_directory->cd();
m_directory->mkdir(module->getName().c_str());
m_directory->cd(module->getName().c_str());
LOG(INFO) << "Initialising \"" << module->getName() << "\"";
m_directory->mkdir(module->getUniqueName().c_str());
m_directory->cd(module->getUniqueName().c_str());
LOG(INFO) << "Initialising \"" << module->getUniqueName() << "\"";
// Initialise the module
module->initialise();
......@@ -612,13 +617,13 @@ void ModuleManager::finaliseAll() {
// Set init module section header
std::string old_section_name = Log::getSection();
std::string section_name = "F:";
section_name += module->getName();
section_name += module->getUniqueName();
Log::setSection(section_name);
// Set module specific settings
auto old_settings = set_module_before(module->getName(), module->getConfig());
auto old_settings = set_module_before(module->getUniqueName(), module->getConfig());
// Change to the output file directory
m_directory->cd(module->getName().c_str());
m_directory->cd(module->getUniqueName().c_str());
// Finalise the module
module->finalise();
// Reset logging
......@@ -659,7 +664,7 @@ void ModuleManager::finaliseAll() {
void ModuleManager::timing() {
LOG(STATUS) << "===============| Wall-clock timing (seconds) |================";
for(auto& module : m_modules) {
LOG(STATUS) << std::setw(25) << module->getName() << " -- " << std::fixed << std::setprecision(5)
LOG(STATUS) << std::setw(25) << module->getUniqueName() << " -- " << std::fixed << std::setprecision(5)
<< module_execution_time_[module] << " = " << std::setprecision(9)
<< module_execution_time_[module] / m_events << " s/evt";
}
......
......@@ -79,8 +79,9 @@ namespace corryvreckan {
std::atomic<bool> m_terminate;
std::unique_ptr<corryvreckan::ConfigManager> conf_mgr_;
Module* create_unique_module(void* library, corryvreckan::Configuration config);
std::vector<Module*> create_detector_modules(void* library, Configuration config, bool dut_only);
std::pair<ModuleIdentifier, Module*> create_unique_module(void* library, corryvreckan::Configuration config);
std::vector<std::pair<ModuleIdentifier, Module*>>
create_detector_modules(void* library, Configuration config, bool dut_only);
std::tuple<LogLevel, LogFormat> set_module_before(const std::string&, const Configuration& config);
void set_module_after(std::tuple<LogLevel, LogFormat> prev);
......
......@@ -34,6 +34,23 @@ namespace corryvreckan {
}
};
/**
* @ingroup Exceptions
* @brief Informs that a module executes an action is it not allowed to do in particular state
*
* A module for example tries to accesses special methods as Module::getOutputPath which are not allowed in the
* constructors, or sends a message outside the Module::run method.
*/
class InvalidModuleActionException : public LogicError {
public:
/**
* @brief Constructs error with a description
* @param message Text explaining the problem
*/
// TODO [doc] the module itself is missing
explicit InvalidModuleActionException(std::string message) { error_message_ = std::move(message); }
};
/**
* @ingroup Exceptions
* @brief General exception for modules if something goes wrong
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment