/******************************************************************************** * Copyright (C) 2014 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH * * * * This software is distributed under the terms of the * * GNU Lesser General Public Licence version 3 (LGPL) version 3, * * copied verbatim in the file "LICENSE" * ********************************************************************************/ /* * File: FairMQProgOptions.cxx * Author: winckler * * Created on March 11, 2015, 10:20 PM */ #include "FairMQProgOptions.h" #include #include "FairMQParser.h" using namespace std; FairMQProgOptions::FairMQProgOptions() : FairProgOptions(), FairMQEventManager() , fMQParserOptions("MQ-Device parser options") , fMQOptionsInCfg("MQ-Device options") , fMQOptionsInCmd("MQ-Device options") , fFairMQMap() , fHelpTitle("***** FAIRMQ Program Options ***** ") , fVersion("Beta version 0.1") , fMQKeyMap() // , fSignalMap() //string API { } // ---------------------------------------------------------------------------------- FairMQProgOptions::~FairMQProgOptions() { } // ---------------------------------------------------------------------------------- void FairMQProgOptions::ParseAll(const int argc, char** argv, bool allowUnregistered) { // init description InitOptionDescription(); // parse command line options if (FairProgOptions::ParseCmdLine(argc, argv, fCmdLineOptions, fVarMap, allowUnregistered)) { // ParseCmdLine return 0 if help or version cmd not called. return 1 if called exit(EXIT_SUCCESS); } // if txt/INI configuration file enabled then parse it as well if (fUseConfigFile) { // check if file exist if (fs::exists(fConfigFile)) { if (FairProgOptions::ParseCfgFile(fConfigFile.string(), fConfigFileOptions, fVarMap, allowUnregistered)) { // ParseCfgFile return -1 if cannot open or read config file. It return 0 otherwise LOG(ERROR) << "Could not parse config"; exit(EXIT_FAILURE); } } else { LOG(ERROR) << "config file '" << fConfigFile << "' not found"; exit(EXIT_FAILURE); } } // set log level before printing (default is 0 = DEBUG level) std::string verbosity = GetValue("verbose"); bool color = GetValue("log-color"); if (!color) { reinit_logger(false); } if (fSeverityMap.count(verbosity)) { set_global_log_level(log_op::operation::GREATER_EQ_THAN, fSeverityMap.at(verbosity)); } else { LOG(ERROR) << " verbosity level '" << verbosity << "' unknown, it will be set to DEBUG"; set_global_log_level(log_op::operation::GREATER_EQ_THAN, fSeverityMap.at("DEBUG")); } // check if one of required MQ config option is there auto parserOption_shptr = fMQParserOptions.options(); bool optionExists = false; vector MQParserKeys; for (const auto& p : parserOption_shptr) { MQParserKeys.push_back(p->canonical_display_name()); if (fVarMap.count(p->canonical_display_name())) { optionExists = true; break; } } if (!optionExists) { LOG(WARN) << "Options to configure FairMQ channels are not provided."; LOG(WARN) << "Please provide the value for one of the following keys:"; for (const auto& p : MQParserKeys) { LOG(WARN) << p; } LOG(WARN) << "No channels will be created (You can create them manually)."; // return 1; } else { // if cmdline mq-config called then use the default xml/json parser if (fVarMap.count("mq-config")) { LOG(DEBUG) << "mq-config: Using default XML/JSON parser"; std::string file = fVarMap["mq-config"].as(); std::string id; if (fVarMap.count("config-key")) { id = fVarMap["config-key"].as(); } else { id = fVarMap["id"].as(); } std::string fileExtension = boost::filesystem::extension(file); std::transform(fileExtension.begin(), fileExtension.end(), fileExtension.begin(), ::tolower); if (fileExtension == ".json") { UserParser(file, id); } else { if (fileExtension == ".xml") { UserParser(file, id); } else { LOG(ERROR) << "mq-config command line called but file extension '" << fileExtension << "' not recognized. Program will now exit"; exit(EXIT_FAILURE); } } } else if (fVarMap.count("config-json-string")) { LOG(DEBUG) << "config-json-string: Parsing JSON string"; std::string id = fVarMap["id"].as(); std::string value = fairmq::ConvertVariableValue().Run(fVarMap.at("config-json-string")); std::stringstream ss; ss << value; UserParser(ss, id); } else if (fVarMap.count("config-xml-string")) { LOG(DEBUG) << "config-json-string: Parsing XML string"; std::string id = fVarMap["id"].as(); std::string value = fairmq::ConvertVariableValue().Run(fVarMap.at("config-xml-string")); std::stringstream ss; ss << value; UserParser(ss, id); } } FairProgOptions::PrintOptions(); } // ---------------------------------------------------------------------------------- int FairMQProgOptions::Store(const FairMQMap& channels) { fFairMQMap = channels; UpdateMQValues(); return 0; } // ---------------------------------------------------------------------------------- // replace FairMQChannelMap, and update variable map accordingly int FairMQProgOptions::UpdateChannelMap(const FairMQMap& channels) { fFairMQMap=channels; UpdateMQValues(); return 0; } // ---------------------------------------------------------------------------------- // read FairMQChannelMap and insert/update corresponding values in variable map // create key for variable map as follow : channelName.index.memberName void FairMQProgOptions::UpdateMQValues() { for(const auto& p : fFairMQMap) { int index = 0; for(const auto& channel : p.second) { std::string typeKey = p.first + "." + std::to_string(index) + ".type"; std::string methodKey = p.first + "." + std::to_string(index) + ".method"; std::string addressKey = p.first + "." + std::to_string(index) + ".address"; std::string propertyKey = p.first + "." + std::to_string(index) + ".property"; std::string sndBufSizeKey = p.first + "." + std::to_string(index) + ".sndBufSize"; std::string rcvBufSizeKey = p.first + "." + std::to_string(index) + ".rcvBufSize"; std::string rateLoggingKey = p.first + "." + std::to_string(index) + ".rateLogging"; fMQKeyMap[typeKey] = std::make_tuple(p.first,index,"type"); fMQKeyMap[methodKey] = std::make_tuple(p.first,index,"method"); fMQKeyMap[addressKey] = std::make_tuple(p.first,index,"address"); fMQKeyMap[propertyKey] = std::make_tuple(p.first,index,"property"); fMQKeyMap[sndBufSizeKey] = std::make_tuple(p.first,index,"sndBufSize"); fMQKeyMap[rcvBufSizeKey] = std::make_tuple(p.first,index,"rcvBufSize"); fMQKeyMap[rateLoggingKey] = std::make_tuple(p.first,index,"rateLogging"); UpdateVarMap(typeKey,channel.GetType()); UpdateVarMap(methodKey,channel.GetMethod()); UpdateVarMap(addressKey,channel.GetAddress()); UpdateVarMap(propertyKey,channel.GetProperty()); //UpdateVarMap(sndBufSizeKey, std::to_string(channel.GetSndBufSize()));// string API UpdateVarMap(sndBufSizeKey,channel.GetSndBufSize()); //UpdateVarMap(rcvBufSizeKey, std::to_string(channel.GetRcvBufSize()));// string API UpdateVarMap(rcvBufSizeKey,channel.GetRcvBufSize()); //UpdateVarMap(rateLoggingKey,std::to_string(channel.GetRateLogging()));// string API UpdateVarMap(rateLoggingKey,channel.GetRateLogging()); /* LOG(DEBUG) << "Update MQ parameters of variable map"; LOG(DEBUG) << "key = " << typeKey <<"\t value = " << GetValue(typeKey); LOG(DEBUG) << "key = " << methodKey <<"\t value = " << GetValue(methodKey); LOG(DEBUG) << "key = " << addressKey <<"\t value = " << GetValue(addressKey); LOG(DEBUG) << "key = " << propertyKey <<"\t value = " << GetValue(propertyKey); LOG(DEBUG) << "key = " << sndBufSizeKey << "\t value = " << GetValue(sndBufSizeKey); LOG(DEBUG) << "key = " << rcvBufSizeKey <<"\t value = " << GetValue(rcvBufSizeKey); LOG(DEBUG) << "key = " << rateLoggingKey <<"\t value = " << GetValue(rateLoggingKey); */ index++; } } } // ---------------------------------------------------------------------------------- int FairMQProgOptions::NotifySwitchOption() { if (fVarMap.count("help")) { LOG(INFO) << fHelpTitle << "\n" << fVisibleOptions; return 1; } if (fVarMap.count("version")) { LOG(INFO) << fVersion << "\n"; return 1; } return 0; } // ---------------------------------------------------------------------------------- void FairMQProgOptions::InitOptionDescription() { // Id required in command line if config txt file not enabled if (fUseConfigFile) { fMQOptionsInCmd.add_options() ("id", po::value(), "Device ID (required argument).") ("io-threads", po::value()->default_value(1), "Number of I/O threads.") ("transport", po::value()->default_value("zeromq"), "Transport ('zeromq'/'nanomsg').") ("deployment", po::value()->default_value("static"), "Deployment ('static'/'dds').") ("control", po::value()->default_value("interactive"), "States control ('interactive'/'static'/'dds').") ("network-interface", po::value()->default_value("eth0"), "Network interface to bind on (e.g. eth0, ib0, wlan0, en0, lo...).") ("config-key", po::value(), "Use provided value instead of device id for fetching the configuration from the config file") ; fMQOptionsInCfg.add_options() ("id", po::value()->required(), "Device ID (required argument).") ("io-threads", po::value()->default_value(1), "Number of I/O threads.") ("transport", po::value()->default_value("zeromq"), "Transport ('zeromq'/'nanomsg').") ("deployment", po::value()->default_value("static"), "Deployment ('static'/'dds').") ("control", po::value()->default_value("interactive"), "States control ('interactive'/'static'/'dds').") ("network-interface", po::value()->default_value("eth0"), "Network interface to bind on (e.g. eth0, ib0, wlan0, en0, lo...).") ("config-key", po::value(), "Use provided value instead of device id for fetching the configuration from the config file") ; } else { fMQOptionsInCmd.add_options() ("id", po::value()->required(), "Device ID (required argument)") ("io-threads", po::value()->default_value(1), "Number of I/O threads") ("transport", po::value()->default_value("zeromq"), "Transport ('zeromq'/'nanomsg').") ("deployment", po::value()->default_value("static"), "Deployment ('static'/'dds').") ("control", po::value()->default_value("interactive"), "States control ('interactive'/'static'/'dds').") ("network-interface", po::value()->default_value("eth0"), "Network interface to bind on (e.g. eth0, ib0, wlan0, en0, lo...).") ("config-key", po::value(), "Use provided value instead of device id for fetching the configuration from the config file") ; } fMQParserOptions.add_options() ("config-xml-string", po::value>()->multitoken(), "XML input as command line string.") // ("config-xml-file", po::value(), "XML input as file.") ("config-json-string", po::value>()->multitoken(), "JSON input as command line string.") // ("config-json-file", po::value(), "JSON input as file.") ("mq-config", po::value(), "JSON/XML input as file. The configuration object will check xml or json file extention and will call the json or xml parser accordingly") ; AddToCmdLineOptions(fGenericDesc); AddToCmdLineOptions(fMQOptionsInCmd); AddToCmdLineOptions(fMQParserOptions); if (fUseConfigFile) { AddToCfgFileOptions(fMQOptionsInCfg, false); AddToCfgFileOptions(fMQParserOptions, false); } } // ---------------------------------------------------------------------------------- int FairMQProgOptions::UpdateChannelMap(const std::string& channelName, int index, const std::string& member, const std::string& val) { if(member == "type") { fFairMQMap.at(channelName).at(index).UpdateType(val); return 0; } if(member == "method") { fFairMQMap.at(channelName).at(index).UpdateMethod(val); return 0; } if(member == "address") { fFairMQMap.at(channelName).at(index).UpdateAddress(val); return 0; } if(member == "property") { fFairMQMap.at(channelName).at(index).UpdateProperty(val); return 0; } else { //if we get there it means something is wrong LOG(ERROR) << "update of FairMQChannel map failed for the following key: " << channelName<<"."<(val)); } //if we get there it means something is wrong LOG(ERROR) << "update of FairMQChannel map failed for the following key: " << channelName<<"."<