Commit 7c9e4121 authored by Simon Spannagel's avatar Simon Spannagel
Browse files

Modules: new createOutputFile() function to be used by all modules.

parent 5aaf6abe
......@@ -39,6 +39,64 @@ ModuleIdentifier Module::get_identifier() const {
return identifier_;
}
/**
* @throws ModuleError If the file cannot be accessed (or created if it did not yet exist)
* @throws InvalidModuleActionException If this method is called from the constructor with the global flag false
* @throws ModuleError If the file exists but the "deny_overwrite" flag is set to true (defaults to false)
* @warning A local path cannot be fetched from the constructor, because the instantiation logic has not finished yet
*
* The output path is automatically created if it does not exists. The path is always accessible if this functions returns.
* Obeys the "deny_overwrite" parameter of the module.
*/
std::string Module::createOutputFile(const std::string& path, bool global) {
std::string file;
if(global) {
file = m_config.get<std::string>("_global_dir", std::string());
} else {
file = m_config.get<std::string>("_output_dir", std::string());
}
// The file name will only be empty if this method is executed from the constructor
if(file.empty()) {
throw InvalidModuleActionException("Cannot access local output path in constructor");
}
try {
// Create all the required main directories
corryvreckan::create_directories(file);
// Add the file itself
file += "/";
file += path;
if(path_is_file(file)) {
auto global_overwrite = getConfigManager()->getGlobalConfiguration().get<bool>("deny_overwrite", false);
if(m_config.get<bool>("deny_overwrite", global_overwrite)) {
throw ModuleError("Overwriting of existing file " + file + " denied.");
}
LOG(WARNING) << "File " << file << " exists and will be overwritten.";
try {
corryvreckan::remove_file(file);
} catch(std::invalid_argument& e) {
throw ModuleError("Deleting file " + file + " failed: " + e.what());
}
}
// Open the file to check if it can be accessed
std::fstream file_stream(file, std::ios_base::out | std::ios_base::app);
if(!file_stream.good()) {
throw std::invalid_argument("file not accessible");
}
// Convert the file to an absolute path
file = get_canonical_path(file);
} catch(std::invalid_argument& e) {
throw ModuleError("Path " + file + " cannot be created");
}
return file;
}
/**
* @throws InvalidModuleActionException If this method is called from the constructor or destructor
* @warning Cannot be used from the constructor, because the instantiation logic has not finished yet
......
......@@ -92,6 +92,14 @@ namespace corryvreckan {
*/
Configuration& getConfig() { return m_config; }
/**
* @brief Create and return an absolute path to be used for output from a relative path
* @param path Relative path to add after the main output directory
* @param global True if the global output directory should be used instead of the module-specific version
* @return Canonical path to an output file
*/
std::string createOutputFile(const std::string& path, bool global = false);
/**
* @brief Initialise the module before the event sequence
*
......
......@@ -336,6 +336,13 @@ std::pair<ModuleIdentifier, Module*> ModuleManager::create_unique_module(void* l
// Create and add module instance config
Configuration& instance_config = conf_manager_->addInstanceConfiguration(identifier, config);
// Specialize instance configuration
auto output_dir = instance_config.get<std::string>("_global_dir");
output_dir += "/";
std::string path_mod_name = identifier.getUniqueName();
std::replace(path_mod_name.begin(), path_mod_name.end(), ':', '_');
output_dir += path_mod_name;
// Convert to correct generator function
auto module_generator =
reinterpret_cast<Module* (*)(Configuration, std::vector<std::shared_ptr<Detector>>)>(generator); // NOLINT
......@@ -353,7 +360,10 @@ std::pair<ModuleIdentifier, Module*> ModuleManager::create_unique_module(void* l
Log::setSection(old_section_name);
set_module_after(old_settings);
// Return the module to the analysis
// Set the module directory afterwards to catch invalid access in constructor
module->get_configuration().set<std::string>("_output_dir", output_dir);
// Return the module to the ModuleManager
return std::make_pair(identifier, module);
}
......@@ -464,6 +474,13 @@ ModuleManager::create_detector_modules(void* library, Configuration config, bool
// Create and add module instance config
Configuration& instance_config = conf_manager_->addInstanceConfiguration(instance.second, config);
// Add internal module config
auto output_dir = instance_config.get<std::string>("_global_dir");
output_dir += "/";
std::string path_mod_name = instance.second.getUniqueName();
std::replace(path_mod_name.begin(), path_mod_name.end(), ':', '/');
output_dir += path_mod_name;
// Set the log section header
std::string old_section_name = Log::getSection();
std::string section_name = "C:";
......@@ -472,10 +489,15 @@ ModuleManager::create_detector_modules(void* library, Configuration config, bool
// Set module specific log settings
auto old_settings = set_module_before(identifier.getUniqueName(), instance_config);
// Build module
modules.emplace_back(identifier, module_generator(instance_config, detector));
Module* module = module_generator(instance_config, detector);
// Reset log
Log::setSection(old_section_name);
set_module_after(old_settings);
// Set the module directory afterwards to catch invalid access in constructor
module->get_configuration().set<std::string>("_output_dir", output_dir);
modules.emplace_back(identifier, module);
}
// Return the list of modules to the analysis
......
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