ifw-daq  2.0-pre
IFW Data Acquisition modules
config.cpp
Go to the documentation of this file.
1 /**
2  * @file
3  * @ingroup server
4  * @copyright ESO - European Southern Observatory
5  * @author
6  *
7  * @brief Config class source file.
8  */
9 
10 #include "config.hpp"
11 #include "dbInterface.hpp"
12 #include "logger.hpp"
13 
14 #include <rad/assert.hpp>
15 #include <rad/exceptions.hpp>
16 #include <rad/helper.hpp>
17 
18 #include <fmt/format.h>
19 #include <boost/program_options.hpp>
20 
21 #include <iostream>
22 
23 namespace bpo = boost::program_options;
24 
25 namespace server {
26 
28 : m_proc_name(CONFIG_DEFAULT_PROCNAME),
29  m_log_level(CONFIG_DEFAULT_LOGLEVEL),
30  m_log_properties(CONFIG_DEFAULT_LOG_PROPERTIES),
31  m_config_filename(CONFIG_DEFAULT_FILENAME),
32  m_scxml_filename(CONFIG_DEFAULT_SCXML_FILENAME),
33  m_db_host_endpoint(CONFIG_DEFAULT_DB_ENDPOINT),
34  m_db_timeout_sec(CONFIG_DEFAULT_DB_TIMEOUT_SEC),
35  m_req_endpoint(CONFIG_DEFAULT_REQ_ENDPOINT),
36  m_pub_endpoint(CONFIG_DEFAULT_PUB_ENDPOINT),
37  m_out_path(rad::Helper::GetEnvVar(CONFIG_ENVVAR_OUT_PATH)) {
38  RAD_TRACE(GetLogger());
39 
40  /*
41  * @todo these msgs won't be displayed until the DEBUG logLevel is applied.
42  */
43  LOG4CPLUS_DEBUG(GetLogger(), "Default - Log level: <" << m_log_level << ">");
44  LOG4CPLUS_DEBUG(GetLogger(), "Default - Log properties: <" << m_log_properties << ">");
45  LOG4CPLUS_DEBUG(GetLogger(), "Default - Configuration filename: <"
46  << m_config_filename << ">");
47  LOG4CPLUS_DEBUG(GetLogger(), "Default - DB host: <" << m_db_host_endpoint
48  << "> (timeout " << m_db_timeout_sec << " sec)");
49  LOG4CPLUS_DEBUG(GetLogger(), "Default - Requests endpoint: <" << m_req_endpoint
50  << ">");
51  LOG4CPLUS_DEBUG(GetLogger(), "Default - Publish endpoint: <" << m_pub_endpoint
52  << ">");
53 
54  /*
55  * Read environment variables.
56  */
57  std::string db_addr = rad::Helper::GetEnvVar(CONFIG_ENVVAR_DBHOST);
58  if (db_addr.size() > 0) {
59  m_db_host_endpoint = db_addr;
60  LOG4CPLUS_DEBUG(GetLogger(), "EnvVar - DB host: <" << m_db_host_endpoint << ">");
61  }
62  if (!m_out_path.empty()) {
63  LOG4CPLUS_DEBUG(GetLogger(), "EnvVar - Out path: <" << m_out_path << ">");
64  }
65 }
66 
68  RAD_TRACE(GetLogger());
69 }
70 
71 bool Config::ParseOptions(int argc, char *argv[]) {
72  RAD_TRACE(GetLogger());
73 
74  /*
75  * Define command line options.
76  */
77  bpo::options_description options_desc("Options");
78  // clang-format off
79  options_desc.add_options()
80  ("help,h", "Print help messages")
81  ("proc-name,n",
82  bpo::value<std::string>(&m_proc_name)->default_value(m_proc_name),
83  "Process name")
84  ("log-level,l",
85  bpo::value<std::string>(&m_log_level)->default_value(m_log_level),
86  "Log level: ERROR, WARNING, STATE, EVENT, ACTION, INFO, DEBUG, TRACE")
87  ("config,c",
88  bpo::value<std::string>(&m_config_filename)->default_value(m_config_filename),
89  "Configuration filename")
90  ("db-host,d",
91  bpo::value<std::string>(&m_db_host_endpoint)->default_value(m_db_host_endpoint),
92  "In-memory DB host (ipaddr:port)");
93  // clang-format on
94 
95  // Parse the options.
96  try {
97  bpo::variables_map options_map;
98  bpo::store(bpo::parse_command_line(argc, argv, options_desc),
99  options_map);
100  if (options_map.count("help")) {
101  std::cout << options_desc << std::endl;
102  return false;
103  }
104 
105  /*
106  * Throws on error, so do after help in case
107  * there are any problems.
108  */
109  bpo::notify(options_map);
110 
111  if (options_map.count("log-level")) {
112  log4cplus::LogLevelManager& log_mgr = log4cplus::getLogLevelManager();
113  log4cplus::LogLevel ll = log_mgr.fromString(m_log_level);
114  if (ll != log4cplus::NOT_SET_LOG_LEVEL) {
115  GetLogger().setLogLevel(ll);
116  LOG4CPLUS_DEBUG(GetLogger(), "CmdOpt - Log level: <" << m_log_level
117  << ">");
118  } else {
119  std::cout << options_desc << std::endl;
120  throw std::invalid_argument("Invalid log level");
121  }
122  }
123 
124  if (options_map.count("proc-name") == 0) {
125  m_proc_name = std::string(argv[0]);
126  LOG4CPLUS_DEBUG(GetLogger(), "Default - Process name: <" << m_proc_name
127  << ">");
128  } else {
129  LOG4CPLUS_DEBUG(GetLogger(), "CmdOpt - Process name: <" << m_proc_name
130  << ">");
131  }
132 
133  if (options_map.count("db-host")) {
134  LOG4CPLUS_DEBUG(GetLogger(), "CmdOpt - DB host: <" << m_db_host_endpoint
135  << ">");
136  } else {
137  LOG4CPLUS_DEBUG(GetLogger(), "Default - DB host: <" << m_db_host_endpoint
138  << ">");
139  }
140 
141  if (options_map.count("config")) {
142  LOG4CPLUS_DEBUG(GetLogger(), "CmdOpt - Configuration filename: <"
143  << m_config_filename << ">");
144  } else {
145  LOG4CPLUS_DEBUG(GetLogger(), "Default - Configuration filename: <"
146  << m_config_filename << ">");
147  }
148  } catch (bpo::error& e) {
149  std::cerr << "ERROR: " << e.what() << std::endl << std::endl;
150  std::cerr << options_desc << std::endl;
151  throw std::invalid_argument(e.what());
152  }
153 
154  return true;
155 }
156 
157 void Config::LoadConfig(const std::string& filename) {
158  RAD_TRACE(GetLogger());
159 
160  std::string config_filename = filename;
161  if (config_filename == "") {
162  config_filename = m_config_filename;
163  }
164 
165  // resolve filename
166  std::string resolved_config_filename = rad::Helper::FindFile(
167  config_filename);
168  if (resolved_config_filename.size() == 0) {
169  LOG4CPLUS_ERROR(GetLogger(), "Cannot find <" << config_filename << ">");
170  throw rad::Exception("Cannot find " + config_filename, resolved_config_filename);
171  }
172 
173  try {
174  m_config_node = YAML::LoadFile(resolved_config_filename);
175 
178  LOG4CPLUS_DEBUG(GetLogger(), "CfgFile - " << KEY_CONFIG_LOG_PROPERTIES
179  << " = <" << m_log_properties << ">");
180  }
181 
184  .as<std::string>();
185  if (m_req_endpoint.empty()) {
186  throw rad::Exception("Invalid configuration",
187  fmt::format("invalid configuration for '{}': '{}' request "
188  "endpoint must be non-empty and have a trailing "
189  "path separator '/'.", KEY_CONFIG_REQ_ENDPOINT,
190  m_req_endpoint));
191  }
192  LOG4CPLUS_DEBUG(GetLogger(), "CfgFile - " << KEY_CONFIG_REQ_ENDPOINT
193  << " = <" << m_req_endpoint << ">");
194  }
197  .as<std::string>();
198  if (m_pub_endpoint.empty()) {
199  throw rad::Exception("Invalid configuration",
200  fmt::format("invalid configuration for '{}': '{}' publish "
201  "endpoint must be non-empty and have a trailing "
202  "path separator '/'.", KEY_CONFIG_PUB_ENDPOINT,
203  m_pub_endpoint));
204  }
205  LOG4CPLUS_DEBUG(GetLogger(), "CfgFile - " << KEY_CONFIG_PUB_ENDPOINT
206  << " = <" << m_pub_endpoint << ">");
207  }
208 
211  .as<std::string>();
212  LOG4CPLUS_DEBUG(GetLogger(), "CfgFile - " << KEY_CONFIG_DB_ENDPOINT
213  << " = <" << m_db_host_endpoint << ">");
214  }
215 
219  LOG4CPLUS_DEBUG(GetLogger(), "CfgFile - " << KEY_CONFIG_DB_TIMEOUT_SEC
220  << " = <" << m_db_timeout_sec << "> sec");
221  }
222 
225  .as<std::string>();
226  LOG4CPLUS_DEBUG(GetLogger(), "CfgFile - " << KEY_CONFIG_SM_SCXML << " = <"
227  << m_scxml_filename << ">");
228  }
229 
232  m_config_node[KEY_CONFIG_INSTRUMENT_ID].as<std::string>();
233  LOG4CPLUS_DEBUG(GetLogger(), "CfgFile - " << KEY_CONFIG_INSTRUMENT_ID
234  << " = <" << m_instrument_id << ">");
235  } else {
236  LOG4CPLUS_ERROR(GetLogger(), "Required configuration parameter <" <<
237  KEY_CONFIG_INSTRUMENT_ID << "> missing");
238  throw rad::Exception("Invalid configuration: Required parameter empty: "
239  + KEY_CONFIG_INSTRUMENT_ID, resolved_config_filename);
240  }
242  m_out_path = m_config_node[KEY_CONFIG_DATAROOT].as<std::string>();
243  LOG4CPLUS_DEBUG(GetLogger(), "Out path - " << KEY_CONFIG_DATAROOT
244  << " = <" << m_out_path << ">");
245  }
246  } catch (YAML::Exception& e) {
247  throw rad::Exception("Failed to load configuration", resolved_config_filename);
248  }
249  RAD_ASSERT(m_config_node.IsNull() == false);
250 
251  m_config_filename = resolved_config_filename;
252  LOG4CPLUS_DEBUG(GetLogger(), "Loaded configuration file <" << m_config_filename
253  << ">");
254 }
255 
256 const std::string& Config::GetMsgReplierEndpoint() const {
257  RAD_TRACE(GetLogger());
258  return m_req_endpoint;
259 }
260 
261 const std::string& Config::GetPubEndpoint() const {
262  RAD_TRACE(GetLogger());
263  return m_pub_endpoint;
264 }
265 
266 const std::string& Config::GetDbEndpoint() const {
267  RAD_TRACE(GetLogger());
268  return m_db_host_endpoint;
269 }
270 
271 const timeval Config::GetDbTimeout() const {
272  RAD_TRACE(GetLogger());
273  timeval timeout = { m_db_timeout_sec, 0 }; // default
274  return timeout;
275 }
276 
277 const std::string& Config::GetSmScxmlFilename() const {
278  RAD_TRACE(GetLogger());
279  return m_scxml_filename;
280 }
281 
282 const std::string& Config::GetConfigFilename() const {
283  RAD_TRACE(GetLogger());
284  return m_config_filename;
285 }
286 
287 const std::string& Config::GetProcName() const {
288  RAD_TRACE(GetLogger());
289  return m_proc_name;
290 }
291 
292 const std::string& Config::GetLogLevel() const {
293  RAD_TRACE(GetLogger());
294  return m_log_level;
295 }
296 
297 const std::string& Config::GetLogProperties() const {
298  RAD_TRACE(GetLogger());
299  return m_log_properties;
300 }
301 
302 } // namespace server
server::Config::m_req_endpoint
std::string m_req_endpoint
Definition: config.hpp:137
server::CONFIG_DEFAULT_LOG_PROPERTIES
const std::string CONFIG_DEFAULT_LOG_PROPERTIES
Definition: config.hpp:25
server::Config::Config
Config()
Default constructor.
Definition: config.cpp:27
server::KEY_CONFIG_REQ_ENDPOINT
const std::string KEY_CONFIG_REQ_ENDPOINT
Definition: dbInterface.hpp:20
server::KEY_CONFIG_DATAROOT
const std::string KEY_CONFIG_DATAROOT
Definition: dbInterface.hpp:29
server::Config::m_instrument_id
std::string m_instrument_id
Definition: config.hpp:130
server::CONFIG_DEFAULT_PUB_ENDPOINT
const std::string CONFIG_DEFAULT_PUB_ENDPOINT
Definition: config.hpp:29
server::CONFIG_DEFAULT_DB_TIMEOUT_SEC
const int CONFIG_DEFAULT_DB_TIMEOUT_SEC
Definition: config.hpp:27
server::Config::LoadConfig
void LoadConfig(const std::string &filename="")
This method load from a configuration file the application configuration overriding the initializatio...
Definition: config.cpp:157
server::CONFIG_DEFAULT_LOGLEVEL
const std::string CONFIG_DEFAULT_LOGLEVEL
Definition: config.hpp:24
server::Config::m_proc_name
std::string m_proc_name
Definition: config.hpp:129
server::KEY_CONFIG_PUB_ENDPOINT
const std::string KEY_CONFIG_PUB_ENDPOINT
Definition: dbInterface.hpp:21
server::CONFIG_DEFAULT_PROCNAME
const std::string CONFIG_DEFAULT_PROCNAME
Default application configuration values.
Definition: config.hpp:21
server::Config::~Config
virtual ~Config()
Default destructor.
Definition: config.cpp:67
server::Config::m_db_host_endpoint
std::string m_db_host_endpoint
Definition: config.hpp:135
server::KEY_CONFIG_INSTRUMENT_ID
const std::string KEY_CONFIG_INSTRUMENT_ID
Definition: dbInterface.hpp:28
server::CONFIG_ENVVAR_OUT_PATH
const std::string CONFIG_ENVVAR_OUT_PATH
Definition: config.hpp:35
server::KEY_CONFIG_DB_ENDPOINT
const std::string KEY_CONFIG_DB_ENDPOINT
Definition: dbInterface.hpp:22
server::Config::m_out_path
std::string m_out_path
Definition: config.hpp:139
server::Config::GetDbEndpoint
const std::string & GetDbEndpoint() const
Definition: config.cpp:266
server::CONFIG_DEFAULT_SCXML_FILENAME
const std::string CONFIG_DEFAULT_SCXML_FILENAME
Definition: config.hpp:23
server::Config::ParseOptions
bool ParseOptions(int argc, char *argv[])
This method parses the command line parameters overriding the initialization done in the constructor.
Definition: config.cpp:71
server::Config::m_config_filename
std::string m_config_filename
Definition: config.hpp:133
server::Config::m_db_timeout_sec
int m_db_timeout_sec
Definition: config.hpp:136
server::Config::GetPubEndpoint
const std::string & GetPubEndpoint() const
Definition: config.cpp:261
server::Config::m_config_node
YAML::Node m_config_node
Disable assignment operator.
Definition: config.hpp:128
rad
Definition: ioExecutor.hpp:6
server::CONFIG_DEFAULT_REQ_ENDPOINT
const std::string CONFIG_DEFAULT_REQ_ENDPOINT
Definition: config.hpp:28
config.hpp
Config class header file.
server::Config::GetLogProperties
const std::string & GetLogProperties() const
Definition: config.cpp:297
server::Config::GetDbTimeout
const timeval GetDbTimeout() const
Definition: config.cpp:271
server::Config::GetLogLevel
const std::string & GetLogLevel() const
Definition: config.cpp:292
server::Config::m_pub_endpoint
std::string m_pub_endpoint
Definition: config.hpp:138
server::Config::GetSmScxmlFilename
const std::string & GetSmScxmlFilename() const
Definition: config.cpp:277
dbInterface.hpp
DbInterface class header file.
server::CONFIG_DEFAULT_FILENAME
const std::string CONFIG_DEFAULT_FILENAME
Definition: config.hpp:22
server::KEY_CONFIG_DB_TIMEOUT_SEC
const std::string KEY_CONFIG_DB_TIMEOUT_SEC
Definition: dbInterface.hpp:23
server::Config::m_scxml_filename
std::string m_scxml_filename
Definition: config.hpp:134
server::Config::GetConfigFilename
const std::string & GetConfigFilename() const
Definition: config.cpp:282
server::CONFIG_DEFAULT_DB_ENDPOINT
const std::string CONFIG_DEFAULT_DB_ENDPOINT
Definition: config.hpp:26
server
Definition: actionMgr.cpp:21
server::GetLogger
log4cplus::Logger & GetLogger()
Definition: logger.cpp:14
logger.hpp
Default logger name.
server::Config::GetMsgReplierEndpoint
const std::string & GetMsgReplierEndpoint() const
Definition: config.cpp:256
server::Config::m_log_properties
std::string m_log_properties
Definition: config.hpp:132
server::KEY_CONFIG_LOG_PROPERTIES
const std::string KEY_CONFIG_LOG_PROPERTIES
Definition: dbInterface.hpp:27
server::Config::GetProcName
const std::string & GetProcName() const
Definition: config.cpp:287
server::Config::m_log_level
std::string m_log_level
Definition: config.hpp:131
server::KEY_CONFIG_SM_SCXML
const std::string KEY_CONFIG_SM_SCXML
Definition: dbInterface.hpp:24
server::CONFIG_ENVVAR_DBHOST
const std::string CONFIG_ENVVAR_DBHOST
Application configuration environment variables.
Definition: config.hpp:34