ifw-daq 3.1.0
IFW Data Acquisition modules
Loading...
Searching...
No Matches
configManager.cpp
Go to the documentation of this file.
1/**
2 * @file
3 * @ingroup daq_dpm
4 * @copyright (c) Copyright ESO 2022
5 * All Rights Reserved
6 * ESO (eso.org) is an Intergovernmental Organisation, and therefore special legal conditions apply.
7 *
8 * @brief DPM server config
9 */
10#include <configManager.hpp>
11
12#include <fstream>
13#include <iostream>
14#include <stdexcept>
15
16#include <boost/program_options.hpp>
17#include <fmt/chrono.h>
18#include <fmt/format.h>
19#include <fmt/ostream.h>
20#include <fmt/std.h>
21#include <rad/helper.hpp>
22
23#include <daq/log4cplus.hpp>
24
25namespace daq::dpm {
26
27ConfigManager::ConfigManager(log4cplus::Logger logger)
28 : m_logger(std::move(logger)), m_mgr(m_logger) {
29 m_mgr.Register(&m_config.name, {"cfg/procname", "Component instance ID"});
30 m_mgr.Register(&m_config.dataroot, {"cfg/dataroot", "ICS standard DATAROOT directory"});
31 m_mgr.Register(&m_config.workspace, {"cfg/daq/workspace", "DPM merge workspace"});
32 m_mgr.Register(&m_config.rr_uri, {"cfg/req_endpoint", "Request/reply URI"});
33 m_mgr.Register(&m_config.ps_uri, {"cfg/pub_endpoint", "Publish/subscribe URI"});
34 m_mgr.Register(&m_config.no_ipc, {"cfg/no_ipc", "Disables IPC interfaces"});
35 m_mgr.Register(&m_config.db_prefix,
36 {"cfg/oldb_uri_prefix", "CII OLDB prefix 'cii.oldb:/elt/..'"});
37 m_mgr.Register(&m_config.db_timeout, {"cfg/oldb_conn_timeout", "CII OLDB connection timeout"});
38 m_mgr.Register(&m_config.log_level, {"cfg/log_level", "Log verbosity level"});
39 m_mgr.Register(&m_config.log_config, {"cfg/log_properties", "Log configuration file"});
40 m_mgr.Register(&m_config.config_file, {"cfg/filename", "YAML configuration file path"});
41 m_mgr.Register(&m_config.poll_once, {"cfg/poll_once", "Poll scheduler once"});
42
43 m_mgr.Register(&m_config.merge_bin, {"cfg/bin_merge", "DPM Merge application binary."});
44 m_mgr.Register(&m_config.rsync_bin, {"cfg/bin_rsync", "rsync application binary."});
45
46 m_mgr.Register(&m_config.limit_daq, {"cfg/limits/daq", "Concurrency limit: Number of DAQs"});
47 m_mgr.Register(&m_config.limit_merge,
48 {"cfg/limits/merge", "Concurrency limit: Number of merges"});
49 m_mgr.Register(&m_config.limit_net_send,
50 {"cfg/limits/net_send", "Concurrency limit: Number of network send tranfers."});
51 m_mgr.Register(
52 &m_config.limit_net_receive,
53 {"cfg/limits/net_receive", "Concurrency limit: Number of network receive transfers."});
54
55 if (auto root = rad::Helper::GetEnvVar("DATAROOT"); !root.empty()) {
56 m_mgr.Update(&m_config.dataroot, root, {config::Origin::EnvironmentVariable, "$DATAROOT"});
57 }
58}
59
60bool ConfigManager::ParseArguments(int argc, char* argv[]) {
61 namespace po = boost::program_options;
62 try {
64 po::options_description options_desc("Options");
65 // clang-format off
66 // Note be careful of providing default_value as it will be interpreted as if user provided
67 // option!
68 options_desc.add_options()
69 ("help,h", "Print help messages")
70 ("proc-name,n",
71 po::value<std::string>(),
72 "Process name")
73 ("log-level,l",
74 po::value<std::string>(),
75 "Log level: ERROR, WARNING, STATE, EVENT, ACTION, INFO, DEBUG, TRACE")
76 ("config,c",
77 po::value<std::string>(),
78 "Configuration filename")
79 ("db-host,d",
80 po::value<std::string>(),
81 "In-memory DB host (ipaddr:port)")
82 ("rr-uri",
83 po::value<std::string>(),
84 "Request/reply URI")
85 ("ps-uri",
86 po::value<std::string>(),
87 "Publish/subscribe URI")
88 ("workspace",
89 po::value<std::string>(),
90 "workspace path (relative paths are relateive to dataroot)")
91 ("no-ipc",
92 "Disable request/reply, publish/subscribe and OLDB interfaces for standalone mode")
93 ("poll-once",
94 "Poll scheduler once and then exit rather than running until asked to quit (this "
95 "option also implies --no-ipc)")
96 ;
97 // clang-format on
98 po::variables_map options_map;
99 po::store(po::parse_command_line(argc, argv, options_desc), options_map);
100 if (options_map.count("help")) {
101 std::cerr << options_desc << std::endl;
102 return false;
103 }
104 po::notify(options_map);
105
106 if (options_map.count("config")) {
107 auto value = options_map["config"].as<std::string>();
108 m_mgr.Update(&m_config.config_file, value, si);
109 }
110
111 if (options_map.count("log-level")) {
112 // Note we cannot use log4cplus::LogLevel as it's an alias to int and we want to parse
113 // a string using ostream, so we use the daq helper daq::LogLevel instead.
114 auto ll_str = options_map["log-level"].as<std::string>();
115 auto ll = boost::lexical_cast<LogLevel>(ll_str);
116 m_mgr.Update(&m_config.log_level, ll.value, si);
117 }
118
119 if (options_map.count("proc-name")) {
120 auto value = options_map["proc-name"].as<std::string>();
121 if (m_mgr.Update(&m_config.name, value, si)) {
122 // Since proc-name updated we also update default for db-prefix
123 m_mgr.Update(&m_config.db_prefix,
124 "cii.oldb:/elt/" + m_config.name,
125 {daq::config::Origin::Default, "Updated default using proc-name"});
126 }
127 }
128
129 if (options_map.count("db-host")) {
130 LOG4CPLUS_WARN(m_logger,
131 "Command line parameter --db-host|-d is deprecated and only provided "
132 "for compatibility");
133 }
134 if (options_map.count("rr-uri")) {
135 auto value = options_map["rr-uri"].as<std::string>();
136 m_mgr.Update(&m_config.rr_uri, value, si);
137 }
138 if (options_map.count("ps-uri")) {
139 auto value = options_map["ps-uri"].as<std::string>();
140 m_mgr.Update(&m_config.ps_uri, value, si);
141 }
142 if (options_map.count("workspace")) {
143 auto value = options_map["workspace"].as<std::string>();
144 m_mgr.Update(&m_config.workspace, value, si);
145 }
146 if (options_map.count("no-ipc")) {
147 m_mgr.Update(&m_config.no_ipc, true, si);
148 }
149 if (options_map.count("poll-once")) {
150 m_mgr.Update(&m_config.poll_once, true, si);
151 m_mgr.Update(
152 &m_config.no_ipc,
153 true,
154 {config::Origin::CommandLine, "Option is implicitly set due to `--poll-once`"});
155 }
156
157 } catch (...) {
158 std::throw_with_nested(std::runtime_error("Failed to parse command line arguments"));
159 }
160 return true;
161}
162
163void ConfigManager::LoadConfig() try {
164 std::string resolved = rad::Helper::FindFile(m_config.config_file);
165 LOG4CPLUS_INFO(m_logger, "Loading configuration from " << resolved);
166 if (resolved.empty()) {
167 auto msg = fmt::format("Could not resolve config file {}", m_config.config_file);
168 LOG4CPLUS_ERROR(m_logger, msg);
169 throw std::invalid_argument(msg);
170 }
173 auto ifs = std::ifstream(resolved);
174 ifs.exceptions(std::ios_base::badbit);
175
176 elt::configng::CiiConfigDocument config;
177 config.UpdateFromStream(ifs);
178 auto const& root = config.GetInstanceRootNode();
179
181 UpdateFromConfig<std::string>(&m_config.dataroot, root, si);
182 UpdateFromConfig<std::string>(&m_config.workspace, root, si);
183 UpdateFromConfig<std::string>(&m_config.log_config, root, si);
184 UpdateFromConfig<std::string>(&m_config.rr_uri, root, si);
185 UpdateFromConfig<std::string>(&m_config.ps_uri, root, si);
186 UpdateFromConfig<std::string>(&m_config.merge_bin, root, si);
187 UpdateFromConfig<std::string>(&m_config.rsync_bin, root, si);
188 // OLDB
189 UpdateFromConfig<std::string>(&m_config.db_prefix, root, si);
190 UpdateFromConfig<int>(&m_config.db_timeout, root, si);
191 // Concurrency limits
192 UpdateFromConfig<int>(&m_config.limit_daq, root, si);
193 UpdateFromConfig<int>(&m_config.limit_merge, root, si);
194 UpdateFromConfig<int>(&m_config.limit_net_receive, root, si);
195 UpdateFromConfig<int>(&m_config.limit_net_send, root, si);
196
197} catch (...) {
198 std::throw_with_nested(std::runtime_error(
199 fmt::format("Failed to load configuration from {}", m_config.config_file)));
200}
201
202} // namespace daq::dpm
bool Update(AttrType *ptr, T const &value, OriginInfo const &origin)
Update configuration value taking into account the origin of the change.
Definition: manager.hpp:293
void Register(AttrType *ptr, Metadata const &meta)
Registers a configuration parameter/attribute.
Definition: manager.hpp:251
ConfigManager(log4cplus::Logger logger)
bool ParseArguments(int argc, char *argv[])
Parse configuration from command line arguments.
DPM server config.
Declaration of log4cplus helpers.
@ Configuration
Configuration file.
@ Default
Built-in default value.
@ CommandLine
Command line argument.
std::optional< T > GetParamAs(std::string const &query, elt::configng::CiiConfigInstanceNode const &node)
Performs lookup of parameters in the form root/node/leaf relative to the provided node.
Definition: manager.hpp:350
Mutable metadata about a configuration attribute that describes where a value comes from.
Definition: manager.hpp:129
std::string name
Process instance name.
Definition: config.hpp:37
log4cplus::LogLevel log_level
Definition: config.hpp:68
std::string rsync_bin
rsync application name.
Definition: config.hpp:82
std::filesystem::path dataroot
Dataroot, normally this should be configured from environment variable $DATAROOT.
Definition: config.hpp:42
std::string merge_bin
Merge application name.
Definition: config.hpp:77
std::filesystem::path workspace
Workspace.
Definition: config.hpp:49
std::chrono::seconds db_timeout
Definition: config.hpp:67
bool no_ipc
If true (set by command line option only) it disables MAL service registration.
Definition: config.hpp:64
std::string rr_uri
Request/reply URI.
Definition: config.hpp:54
std::string ps_uri
Pub/sub URI.
Definition: config.hpp:59
std::string db_prefix
Definition: config.hpp:66
std::string log_config
Log file, defaults to nothing.
Definition: config.hpp:72
bool poll_once
Run scheduler once.
Definition: config.hpp:94
uint16_t limit_net_send
Definition: config.hpp:98
std::filesystem::path config_file
Configuration file.
Definition: config.hpp:89
uint16_t limit_net_receive
Definition: config.hpp:99