From 4e942e489b9643fc04c7fc004bf73650ec653585 Mon Sep 17 00:00:00 2001 From: Alexey Rybalchenko Date: Wed, 11 Oct 2017 15:49:49 +0200 Subject: [PATCH] Single Logger implementation for FairLogger & FairMQLogger --- fairmq/CMakeLists.txt | 16 +- fairmq/DeviceRunner.cxx | 5 +- fairmq/FairMQLogger.cxx | 6 +- fairmq/FairMQLogger.h | 8 +- fairmq/logger/fairroot_null_deleter.h | 27 -- fairmq/logger/logger.cxx | 314 ------------------ fairmq/logger/logger.h | 120 ------- fairmq/logger/run/testLogger.cxx | 113 ------- fairmq/options/FairMQParser.cxx | 18 +- fairmq/options/FairMQProgOptions.cxx | 240 ++++--------- fairmq/options/FairMQProgOptions.h | 143 +------- fairmq/options/FairProgOptions.cxx | 249 ++++---------- fairmq/options/FairProgOptions.h | 50 +-- .../options/ProgOptionTest/macro/testXML.xml | 82 +++-- .../ProgOptionTest/run/testMQoptions1.cxx | 81 ++--- .../ProgOptionTest/run/testMQoptions2.cxx | 28 +- fairmq/options/startConfigExample.sh.in | 2 +- fairmq/plugins/Control.cxx | 26 +- fairmq/run/startMQBenchmark.sh.in | 2 + .../shmem/prototype/startShmPrototype.sh.in | 10 +- fairmq/test/protocols/_poller.cxx | 4 +- fairmq/test/protocols/_pub_sub.cxx | 12 +- fairmq/test/protocols/_push_pull.cxx | 8 +- fairmq/test/protocols/_req_rep.cxx | 12 +- fairmq/test/protocols/_transfer_timeout.cxx | 4 +- fairmq/test/protocols/runner.cxx.in | 2 +- 26 files changed, 295 insertions(+), 1287 deletions(-) delete mode 100644 fairmq/logger/fairroot_null_deleter.h delete mode 100644 fairmq/logger/logger.cxx delete mode 100644 fairmq/logger/logger.h delete mode 100644 fairmq/logger/run/testLogger.cxx diff --git a/fairmq/CMakeLists.txt b/fairmq/CMakeLists.txt index 8dbe9f1b..3b1f1dbc 100644 --- a/fairmq/CMakeLists.txt +++ b/fairmq/CMakeLists.txt @@ -83,7 +83,6 @@ set(FAIRMQ_HEADER_FILES devices/FairMQProxy.h devices/FairMQSink.h devices/FairMQSplitter.h - logger/logger.h options/FairMQParser.h options/FairMQProgOptions.h options/FairMQSuboptParser.h @@ -127,13 +126,9 @@ if(NANOMSG_FOUND) ) endif() -if("${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION}" VERSION_LESS "1.56") - set(FAIRMQ_HEADER_FILES_NAMESPACED ${FAIRMQ_HEADER_FILES_NAMESPACED} - logger/fairroot_null_deleter.h - ) -endif() - - +########################## +# libFairMQ source files # +########################## set(FAIRMQ_SOURCE_FILES DeviceRunner.cxx FairMQChannel.cxx @@ -150,7 +145,6 @@ set(FAIRMQ_SOURCE_FILES devices/FairMQProxy.cxx # devices/FairMQSink.cxx devices/FairMQSplitter.cxx - logger/logger.cxx options/FairMQParser.cxx options/FairMQProgOptions.cxx options/FairMQSuboptParser.cxx @@ -208,6 +202,7 @@ add_library(FairMQ SHARED ####################### target_include_directories(FairMQ PUBLIC # consumers inherit public include directories + $ $ $ $ @@ -224,8 +219,6 @@ target_link_libraries(FairMQ dl pthread Boost::boost - Boost::log - Boost::log_setup Boost::program_options Boost::thread Boost::system @@ -233,6 +226,7 @@ target_link_libraries(FairMQ Boost::regex Boost::date_time Boost::signals + Logger $<$:rt> PRIVATE # only libFairMQ links against private dependencies diff --git a/fairmq/DeviceRunner.cxx b/fairmq/DeviceRunner.cxx index 08474097..380c2ad1 100644 --- a/fairmq/DeviceRunner.cxx +++ b/fairmq/DeviceRunner.cxx @@ -41,7 +41,10 @@ auto DeviceRunner::Run() -> int fEvents.Emit(*this); //////////////////////// - fConfig.ParseAll(fRawCmdLineArgs, true); + if (fConfig.ParseAll(fRawCmdLineArgs, true)) + { + return 0; + } ////// CALL HOOK /////// fEvents.Emit(*this); diff --git a/fairmq/FairMQLogger.cxx b/fairmq/FairMQLogger.cxx index 78f64405..ad652b54 100644 --- a/fairmq/FairMQLogger.cxx +++ b/fairmq/FairMQLogger.cxx @@ -1,8 +1,8 @@ /******************************************************************************** * Copyright (C) 2014 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH * * * - * This software is distributed under the terms of the * - * GNU Lesser General Public Licence (LGPL) version 3, * + * This software is distributed under the terms of the * + * GNU Lesser General Public Licence (LGPL) version 3, * * copied verbatim in the file "LICENSE" * ********************************************************************************/ /** @@ -20,6 +20,6 @@ timestamp_t get_timestamp() { struct timeval now; - gettimeofday(&now, NULL); + gettimeofday(&now, nullptr); return now.tv_usec + static_cast(now.tv_sec) * 1000000; } diff --git a/fairmq/FairMQLogger.h b/fairmq/FairMQLogger.h index afaaa045..d76fbdd2 100644 --- a/fairmq/FairMQLogger.h +++ b/fairmq/FairMQLogger.h @@ -1,8 +1,8 @@ /******************************************************************************** - * Copyright (C) 2014 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH * + * Copyright (C) 2017 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH * * * - * This software is distributed under the terms of the * - * GNU Lesser General Public Licence (LGPL) version 3, * + * This software is distributed under the terms of the * + * GNU Lesser General Public Licence (LGPL) version 3, * * copied verbatim in the file "LICENSE" * ********************************************************************************/ /** @@ -15,7 +15,7 @@ #ifndef FAIRMQLOGGER_H_ #define FAIRMQLOGGER_H_ -#include "logger/logger.h" +#include using timestamp_t = unsigned long long; diff --git a/fairmq/logger/fairroot_null_deleter.h b/fairmq/logger/fairroot_null_deleter.h deleted file mode 100644 index 7c161f9e..00000000 --- a/fairmq/logger/fairroot_null_deleter.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * File: fairroot_null_deleter.h - * Author: winckler - * - * Created on September 21, 2015, 11:50 AM - */ - -#ifndef FAIRROOT_NULL_DELETER_H -#define FAIRROOT_NULL_DELETER_H -// boost like null_deleter introduced for backward compability if boost version < 1.56 - -namespace fairroot -{ - struct null_deleter - { - //! Function object result type - using result_type = void; - /*! - * Does nothing - */ - template< typename T > - void operator() (T*) const noexcept {} - }; - -} -#endif /* FAIRROOT_NULL_DELETER_H */ - diff --git a/fairmq/logger/logger.cxx b/fairmq/logger/logger.cxx deleted file mode 100644 index 0b182833..00000000 --- a/fairmq/logger/logger.cxx +++ /dev/null @@ -1,314 +0,0 @@ -/******************************************************************************** - * Copyright (C) 2014 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH * - * * - * This software is distributed under the terms of the * - * GNU Lesser General Public Licence (LGPL) version 3, * - * copied verbatim in the file "LICENSE" * - ********************************************************************************/ -#include "logger.h" - -#include - -#include -#include - -#include - -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include - -#if BOOST_VERSION < 105600 -#include "fairroot_null_deleter.h" -using empty_deleter_t = fairroot::null_deleter; -#else -#include -using empty_deleter_t = boost::null_deleter; -#endif - -#include -#include - -#include -#include -#include -#include -#include - -using namespace std; -namespace blog = boost::log; -namespace bptime = boost::posix_time; - -struct TagConsole; -struct TagFile; - -BOOST_LOG_ATTRIBUTE_KEYWORD(fairmq_logger_timestamp, "TimeStamp", bptime::ptime) -BOOST_LOG_ATTRIBUTE_KEYWORD(severity, "Severity", fair::mq::logger::SeverityLevel) - -BOOST_LOG_GLOBAL_LOGGER_INIT(global_logger, blog::sources::severity_logger_mt) -{ - blog::sources::severity_logger_mt globalLogger; - globalLogger.add_attribute("TimeStamp", blog::attributes::local_clock()); - fair::mq::logger::DefaultConsoleInit(); - return globalLogger; -} - -namespace fair -{ -namespace mq -{ -namespace logger -{ - -vector> sinkList;// global var - -void InitConsoleLogFormatter(const blog::record_view& view, blog::formatting_ostream& os) -{ - os << "[\033[01;36m"; - - auto dateTimeFormatter = blog::expressions::stream << blog::expressions::format_date_time("TimeStamp", "%H:%M:%S"); - dateTimeFormatter(view, os); - - os << "\033[0m][" << view.attribute_values()["Severity"].extract() << "] " << view.attribute_values()["Message"].extract(); -} - -void InitFileLogFormatter(const blog::record_view& view, blog::formatting_ostream& os) -{ - os << "["; - - auto dateTimeFormatter = blog::expressions::stream << blog::expressions::format_date_time("TimeStamp", "%H:%M:%S"); - dateTimeFormatter(view, os); - - os << "][" << view.attribute_values()["Severity"].extract() << "] " << view.attribute_values()["Message"].extract(); -} - - -// helper function to format in color console output -string writeIn(const string& textInBold, color::Code color) -{ - ostringstream os; - os << "\033[01;" << color << "m" << textInBold << "\033[0m"; - return os.str(); -} - -// overload operator for console output -blog::formatting_ostream& operator<<(blog::formatting_ostream& stream, blog::to_log_manip const& manip) -{ - SeverityLevel level = manip.get(); - size_t idx = static_cast(level); - if (idx < gLogSeverityLevelString.size()) - { - switch (level) - { - case SeverityLevel::TRACE: - stream << writeIn(gLogSeverityLevelString.at(idx), color::FG_BLUE); - break; - - case SeverityLevel::DEBUG: - stream << writeIn(gLogSeverityLevelString.at(idx), color::FG_BLUE); - break; - - case SeverityLevel::RESULTS: - stream << writeIn(gLogSeverityLevelString.at(idx), color::FG_MAGENTA); - break; - - case SeverityLevel::INFO: - stream << writeIn(gLogSeverityLevelString.at(idx), color::FG_GREEN); - break; - - case SeverityLevel::WARN: - stream << writeIn(gLogSeverityLevelString.at(idx), color::FG_YELLOW); - break; - - case SeverityLevel::STATE: - stream << writeIn(gLogSeverityLevelString.at(idx), color::FG_MAGENTA); - break; - - case SeverityLevel::ERROR: - stream << writeIn(gLogSeverityLevelString.at(idx), color::FG_RED); - break; - - case SeverityLevel::NOLOG: - stream << writeIn(gLogSeverityLevelString.at(idx), color::FG_DEFAULT); - break; - - default: - break; - } - } - else - { - stream << writeIn("Unknown log level ", color::FG_RED) << "(int level = " << static_cast(level) << ")"; - } - return stream; -} - -// overload operator for file output -blog::formatting_ostream& operator<<(blog::formatting_ostream& stream, blog::to_log_manip const& manip) -{ - SeverityLevel level = manip.get(); - size_t idx = static_cast(level); - if (idx < gLogSeverityLevelString.size()) - { - stream << gLogSeverityLevelString.at(idx); - } - else - { - stream << writeIn("Unknown log level ", color::FG_RED) << "(int level = " << static_cast(level) << ")"; - } - return stream; -} - -void RemoveRegisteredSinks() -{ - if (sinkList.size() > 0) - { - for (const auto& sink : sinkList) - { - blog::core::get()->remove_sink(sink); - } - sinkList.clear(); - } -} - -void ReinitLogger(bool color, const string& filename, SeverityLevel level) -{ - BOOST_LOG_SEV(global_logger::get(), SeverityLevel::NOLOG) << ""; - RemoveRegisteredSinks(); - DefaultConsoleInit(color); - if (level != SeverityLevel::NOLOG) - { - if (!filename.empty()) - { - DefaultAddFileSink(filename, level); - } - } -} - -// console sink related functions -void DefaultConsoleInit(bool color/* = true*/) -{ - // add a text sink - using TextSink = blog::sinks::synchronous_sink; - - RemoveRegisteredSinks(); - - // CONSOLE - all severity except error - boost::shared_ptr sink = boost::make_shared(); - // add "console" output stream to our sink - sink->locked_backend()->add_stream(boost::shared_ptr(&clog, empty_deleter_t())); - - // specify the format of the log message - if (color) - { - sink->set_formatter(&InitConsoleLogFormatter); - } - else - { - sink->set_formatter(&InitFileLogFormatter); - } - - sink->set_filter(severity != SeverityLevel::ERROR && severity < SeverityLevel::NOLOG); - // add sink to the core - sinkList.push_back(sink); - blog::core::get()->add_sink(sink); - - // CONSOLE - only severity error - boost::shared_ptr sinkError = boost::make_shared(); - sinkError->locked_backend()->add_stream(boost::shared_ptr(&cerr, empty_deleter_t())); - - if (color) - { - sinkError->set_formatter(&InitConsoleLogFormatter); - } - else - { - sinkError->set_formatter(&InitFileLogFormatter); - } - - sinkError->set_filter(severity == SeverityLevel::ERROR); - sinkList.push_back(sinkError); - blog::core::get()->add_sink(sinkError); -} - -int DefaultConsoleSetFilter(SeverityLevel level) -{ - if (sinkList.size() >= 2) - { - sinkList.at(0)->set_filter([level](const blog::attribute_value_set& attrSet) - { - auto sev = attrSet["Severity"].extract(); - auto mainConsoleSinkCondition = (sev != SeverityLevel::ERROR) && (sev < SeverityLevel::NOLOG); - return mainConsoleSinkCondition && (sev >= level); - }); - - sinkList.at(1)->set_filter([level](const blog::attribute_value_set& attrSet) - { - auto sev = attrSet["Severity"].extract(); - auto errorConsoleSinkCondition = sev == SeverityLevel::ERROR; - return errorConsoleSinkCondition && (sev >= level); - }); - return 0; - } - else - { - return 1; - } - - return 0; -} - -// file sink related functions -void DefaultAddFileSink(const string& filename, SeverityLevel level) -{ - // add a text sink - string formattedFilename(filename); - formattedFilename += "_%Y-%m-%d_%H-%M-%S.%N.log"; - - // add a text sink - using SinkBackend = blog::sinks::text_file_backend; - using Sink = blog::sinks::synchronous_sink; - - boost::shared_ptr backend = boost::make_shared( - blog::keywords::file_name = formattedFilename, - blog::keywords::rotation_size = 10 * 1024 * 1024, - // rotate at midnight every day - blog::keywords::time_based_rotation = blog::sinks::file::rotation_at_time_point(0, 0, 0), - // log collector, - // -- maximum total size of the stored log files is 1GB. - // -- minimum free space on the drive is 2GB - blog::keywords::max_size = 1000 * 1024 * 1024, - blog::keywords::min_free_space = 2000 * 1024 * 1024, - blog::keywords::auto_flush = true - //keywords::time_based_rotation = &is_it_time_to_rotate - ); - boost::shared_ptr sink = boost::make_shared(backend); - - // specify the format of the log message - sink->set_formatter(&InitFileLogFormatter); - - // forward lambda for setting the filter - sink->set_filter([level](const blog::attribute_value_set& attrSet) - { - auto sev = attrSet["Severity"].extract(); - return (sev >= level) && (sev < SeverityLevel::NOLOG); - }); - - // add file sinks to core and list - blog::core::get()->add_sink(sink); - sinkList.push_back(sink); -} - -} // namespace logger -} // namespace mq -} // namespace fair diff --git a/fairmq/logger/logger.h b/fairmq/logger/logger.h deleted file mode 100644 index e2415a67..00000000 --- a/fairmq/logger/logger.h +++ /dev/null @@ -1,120 +0,0 @@ -/******************************************************************************** - * Copyright (C) 2014 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH * - * * - * This software is distributed under the terms of the * - * GNU Lesser General Public Licence (LGPL) version 3, * - * copied verbatim in the file "LICENSE" * - ********************************************************************************/ -/* - * File: logger.h - * Author: winckler - * - * Created on August 21, 2015, 6:12 PM - */ -#ifndef FAIR_MQ_LOGGER_H -#define FAIR_MQ_LOGGER_H - -#define BOOST_LOG_DYN_LINK 1 // necessary when linking the boost_log library dynamically -#define FUSION_MAX_VECTOR_SIZE 20 - -#ifdef DEBUG -#undef DEBUG -#warning "The symbol 'DEBUG' is used in FairMQLogger. undefining..." -#endif - -#include - -#include -#include -#include - -#include - -namespace fair -{ -namespace mq -{ -namespace logger -{ - -enum SeverityLevel -{ - TRACE, - DEBUG, - RESULTS, - INFO, - STATE, - WARN, - ERROR, - NOLOG -}; - -static const std::array gLogSeverityLevelString -{ - { - "TRACE", - "DEBUG", - "RESULTS", - "INFO", - "STATE", - "WARN", - "ERROR", - "NOLOG" - } -}; - -namespace color -{ - -enum Code -{ - FG_BLACK = 30, - FG_RED = 31, - FG_GREEN = 32, - FG_YELLOW = 33, - FG_BLUE = 34, - FG_MAGENTA = 35, - FG_CYAN = 36, - FG_WHITE = 37, - FG_DEFAULT = 39, - BG_RED = 41, - BG_GREEN = 42, - BG_BLUE = 44, - BG_DEFAULT = 49 -}; - -} // namespace color - -void ReinitLogger(bool color, const std::string& filename = "", SeverityLevel level = SeverityLevel::NOLOG); -void RemoveRegisteredSinks(); - -// console sink related functions -void DefaultConsoleInit(bool color = true); -int DefaultConsoleSetFilter(SeverityLevel level); - -// file sink related functions -void DefaultAddFileSink(const std::string& filename, SeverityLevel level); - -} // namespace logger -} // namespace mq -} // namespace fair - -// register a global logger (declaration) -BOOST_LOG_GLOBAL_LOGGER(global_logger, boost::log::sources::severity_logger_mt) - -// helper macros - -// global macros (core). Level filters are set globally here, that is to all register sinks -// add empty string if boost 1.59.0 (see : https://svn.boost.org/trac/boost/ticket/11549 ) -#if BOOST_VERSION == 105900 -#define LOG(severity) BOOST_LOG_SEV(global_logger::get(), fair::mq::logger::SeverityLevel::severity) << "" -#define MQLOG(severity) BOOST_LOG_SEV(global_logger::get(), fair::mq::logger::SeverityLevel::severity) << "" -#else -#define LOG(severity) BOOST_LOG_SEV(global_logger::get(), fair::mq::logger::SeverityLevel::severity) -#define MQLOG(severity) BOOST_LOG_SEV(global_logger::get(), fair::mq::logger::SeverityLevel::severity) -#endif - -#define SET_LOG_CONSOLE_LEVEL(loglevel) DefaultConsoleSetFilter(fair::mq::logger::SeverityLevel::loglevel) -#define ADD_LOG_FILESINK(filename, loglevel) DefaultAddFileSink(filename, fair::mq::logger::SeverityLevel::loglevel) - -#endif // FAIR_MQ_LOGGER_H diff --git a/fairmq/logger/run/testLogger.cxx b/fairmq/logger/run/testLogger.cxx deleted file mode 100644 index 31e761cb..00000000 --- a/fairmq/logger/run/testLogger.cxx +++ /dev/null @@ -1,113 +0,0 @@ -/******************************************************************************** - * Copyright (C) 2014 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH * - * * - * This software is distributed under the terms of the * - * GNU Lesser General Public Licence (LGPL) version 3, * - * copied verbatim in the file "LICENSE" * - ********************************************************************************/ - -// WARNING : pragma commands to hide boost warning -// TODO : remove these pragma commands when boost will fix this issue in future release - -#if defined(__clang__) - _Pragma("clang diagnostic push") - _Pragma("clang diagnostic ignored \"-Wshadow\"") - #include "logger.h" - _Pragma("clang diagnostic pop") -#elif defined(__GNUC__) || defined(__GNUG__) - _Pragma("GCC diagnostic push") - _Pragma("GCC diagnostic ignored \"-Wshadow\"") - #include "logger.h" - _Pragma("GCC diagnostic pop") -#endif - -#include - -void test_logger() -{ - LOG(TRACE) << "this is a trace message"; - LOG(DEBUG) << "this is a debug message"; - LOG(RESULTS) << "this is a results message"; - LOG(INFO) << "this is a info message"; - LOG(WARN) << "this is a warning message"; - LOG(ERROR) << "this is an error message"; - LOG(STATE) << "this is a state message"; -} - -void test_console_level() -{ - std::cout<<"********* test logger : SET_LOG_CONSOLE_LEVEL(lvl) *********"<(); - // return (sev == FairMQ::ERROR); - // }, - // boost::log::keywords::file_name = "test_log3_%5N.log", - // boost::log::keywords::rotation_size = 5 * 1024 * 1024, - // boost::log::keywords::time_based_rotation = boost::log::sinks::file::rotation_at_time_point(12, 0, 0) - // ); - - test_logger(); - - std::cout << "----------------------------"<set_filter([](const boost::log::attribute_value_set& attr_set) - { - auto sev = attr_set["Severity"].extract(); - return (sev == FairMQ::WARN) || (sev == FairMQ::ERROR); - }); - test_logger(); - - // remove all sinks, and restart console sinks - ReinitLogger(false); - test_logger(); - return 0; -} diff --git a/fairmq/options/FairMQParser.cxx b/fairmq/options/FairMQParser.cxx index 248c3fae..c815b211 100644 --- a/fairmq/options/FairMQParser.cxx +++ b/fairmq/options/FairMQParser.cxx @@ -73,11 +73,11 @@ FairMQMap XML::UserParser(stringstream& input, const string& deviceId, const str namespace Helper { -void PrintDeviceList(const boost::property_tree::ptree& tree, const std::string& formatFlag) +void PrintDeviceList(const boost::property_tree::ptree& tree, const string& formatFlag) { string deviceIdKey; - // do a first loop just to print the device-id in json input + // do a first loop just to print the device-id in json input for (const auto& p : tree) { if (p.first == "devices") @@ -88,23 +88,23 @@ void PrintDeviceList(const boost::property_tree::ptree& tree, const std::string& if (key != "") { deviceIdKey = key; - LOG(TRACE) << "Found config for device key '" << deviceIdKey << "' in JSON input"; + LOG(DEBUG) << "Found config for device key '" << deviceIdKey << "' in JSON input"; } else { deviceIdKey = q.second.get("id"); - LOG(TRACE) << "Found config for device id '" << deviceIdKey << "' in JSON input"; + LOG(DEBUG) << "Found config for device id '" << deviceIdKey << "' in JSON input"; } } } if (p.first == "device") { - //get id attribute to choose the device + // get id attribute to choose the device if (formatFlag == "xml") { deviceIdKey = p.second.get(".id"); - LOG(TRACE) << "Found config for '" << deviceIdKey << "' in XML input"; + LOG(DEBUG) << "Found config for '" << deviceIdKey << "' in XML input"; } if (formatFlag == "json") @@ -113,12 +113,12 @@ void PrintDeviceList(const boost::property_tree::ptree& tree, const std::string& if (key != "") { deviceIdKey = key; - LOG(TRACE) << "Found config for device key '" << deviceIdKey << "' in JSON input"; + LOG(DEBUG) << "Found config for device key '" << deviceIdKey << "' in JSON input"; } else { deviceIdKey = p.second.get("id"); - LOG(TRACE) << "Found config for device id '" << deviceIdKey << "' in JSON input"; + LOG(DEBUG) << "Found config for device id '" << deviceIdKey << "' in JSON input"; } } } @@ -428,7 +428,7 @@ void SocketParser(const boost::property_tree::ptree& tree, vector void PrintPropertyTree(const boost::property_tree::ptree& tree, int level) { for (const auto& p : tree) { - std::cout << std::setw(level+1) << level << ": " << p.first << " " << p.second.get_value() << std::endl; + cout << setw(level+1) << level << ": " << p.first << " " << p.second.get_value() << endl; PrintPropertyTree(p.second.get_child(""), level + 1); } } diff --git a/fairmq/options/FairMQProgOptions.cxx b/fairmq/options/FairMQProgOptions.cxx index 371c583e..131565f7 100644 --- a/fairmq/options/FairMQProgOptions.cxx +++ b/fairmq/options/FairMQProgOptions.cxx @@ -8,30 +8,27 @@ /* * File: FairMQProgOptions.cxx * Author: winckler - * + * * Created on March 11, 2015, 10:20 PM */ #include "FairMQProgOptions.h" -#include #include "FairMQParser.h" #include "FairMQSuboptParser.h" #include "FairMQLogger.h" + +#include #include using namespace std; FairMQProgOptions::FairMQProgOptions() : FairProgOptions() - , fMQParserOptions("MQ-Device parser options") - , fMQOptionsInCfg("MQ-Device options") - , fMQOptionsInCmd("MQ-Device options") + , fMQParserOptions("FairMQ config parser options") + , fMQCmdOptions("FairMQ device options") , fFairMQMap() - , fHelpTitle("***** FAIRMQ Program Options ***** ") - , fVersion("Beta version 0.1") , fChannelInfo() , fMQKeyMap() - // , fSignalMap() //string API { } @@ -39,86 +36,51 @@ FairMQProgOptions::~FairMQProgOptions() { } -void FairMQProgOptions::ParseAll(const std::vector& cmdLineArgs, bool allowUnregistered) +int FairMQProgOptions::ParseAll(const vector& cmdLineArgs, bool allowUnregistered) { - std::vector argv(cmdLineArgs.size()); + vector argv(cmdLineArgs.size()); - std::transform(cmdLineArgs.begin(), cmdLineArgs.end(), argv.begin(), [](const std::string& str) + transform(cmdLineArgs.begin(), cmdLineArgs.end(), argv.begin(), [](const string& str) { return str.c_str(); }); - ParseAll(argv.size(), const_cast(argv.data()), allowUnregistered); + return ParseAll(argv.size(), const_cast(argv.data()), allowUnregistered); } -void FairMQProgOptions::ParseAll(const int argc, char const* const* argv, bool allowUnregistered) +int FairMQProgOptions::ParseAll(const int argc, char const* const* 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); - } - } - - if (fVarMap.count("print-options")) - { - PrintOptionsRaw(); - exit(EXIT_SUCCESS); + // ParseCmdLine returns 0 if no immediate switches found. + return 1; } // if these options are provided, do no further checks and let the device handle them if (fVarMap.count("print-channels") || fVarMap.count("version")) { - fair::mq::logger::DefaultConsoleSetFilter(fSeverityMap.at("NOLOG")); - return; + fair::Logger::SetConsoleSeverity("nolog"); + return 0; } + string severity = GetValue("severity"); + string logFile = GetValue("log-to-file"); + bool color = GetValue("color"); + string verbosity = GetValue("verbosity"); - string logFile = GetValue("log-to-file"); - bool color = GetValue("log-color"); - - // check if the provided verbosity level is valid, otherwise set to DEBUG - if (fSeverityMap.count(verbosity) == 0) - { - LOG(ERROR) << " verbosity level '" << verbosity << "' unknown, it will be set to DEBUG"; - verbosity = "DEBUG"; - } + fair::Logger::SetVerbosity(verbosity); if (logFile != "") { - fair::mq::logger::ReinitLogger(false, logFile, fSeverityMap.at(verbosity)); - fair::mq::logger::DefaultConsoleSetFilter(fSeverityMap.at("NOLOG")); + fair::Logger::InitFileSink(logFile, severity); + fair::Logger::SetConsoleSeverity("nolog"); } else { - if (!color) - { - fair::mq::logger::ReinitLogger(false); - } - - fair::mq::logger::DefaultConsoleSetFilter(fSeverityMap.at(verbosity)); + fair::Logger::SetConsoleColor(color); + fair::Logger::SetConsoleSeverity(severity); } // check if one of required MQ config option is there @@ -140,9 +102,9 @@ void FairMQProgOptions::ParseAll(const int argc, char const* const* argv, bool a LOG(WARN) << "FairMQProgOptions: no channels configuration provided via neither of:"; for (const auto& p : MQParserKeys) { - LOG(WARN) << " --" << p; + LOG(WARNING) << " --" << p; } - LOG(WARN) << "No channels will be created (You can create them manually)."; + LOG(warn) << "No channels will be created (You can create them manually)."; } else { @@ -180,10 +142,8 @@ void FairMQProgOptions::ParseAll(const int argc, char const* const* argv, bool a } else { - LOG(ERROR) << "mq-config command line called but file extension '" - << ext - << "' not recognized. Program will now exit"; - exit(EXIT_FAILURE); + LOG(error) << "mq-config command line called but file extension '" << ext << "' not recognized. Program will now exit"; + return 1; } } } @@ -213,6 +173,8 @@ void FairMQProgOptions::ParseAll(const int argc, char const* const* argv, bool a } FairProgOptions::PrintOptions(); + + return 0; } int FairMQProgOptions::Store(const FairMQMap& channels) @@ -237,7 +199,7 @@ void FairMQProgOptions::UpdateChannelInfo() fChannelInfo.clear(); for (const auto& c : fFairMQMap) { - fChannelInfo.insert(std::make_pair(c.first, c.second.size())); + fChannelInfo.insert(make_pair(c.first, c.second.size())); } } @@ -275,104 +237,64 @@ void FairMQProgOptions::UpdateMQValues() UpdateVarMap(methodKey, channel.GetMethod()); UpdateVarMap(addressKey, channel.GetAddress()); UpdateVarMap(transportKey, channel.GetTransport()); - - //UpdateVarMap(sndBufSizeKey, to_string(channel.GetSndBufSize()));// string API UpdateVarMap(sndBufSizeKey, channel.GetSndBufSize()); - - //UpdateVarMap(rcvBufSizeKey, to_string(channel.GetRcvBufSize()));// string API UpdateVarMap(rcvBufSizeKey, channel.GetRcvBufSize()); - - //UpdateVarMap(sndKernelSizeKey, to_string(channel.GetSndKernelSize()));// string API UpdateVarMap(sndKernelSizeKey, channel.GetSndKernelSize()); - - //UpdateVarMap(rcvKernelSizeKey, to_string(channel.GetRcvKernelSize()));// string API UpdateVarMap(rcvKernelSizeKey, channel.GetRcvKernelSize()); - - //UpdateVarMap(rateLoggingKey,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 = " << sndBufSizeKey << "\t value = " << GetValue(sndBufSizeKey); - LOG(DEBUG) << "key = " << rcvBufSizeKey <<"\t value = " << GetValue(rcvBufSizeKey); - LOG(DEBUG) << "key = " << sndKernelSizeKey << "\t value = " << GetValue(sndKernelSizeKey); - LOG(DEBUG) << "key = " << rcvKernelSizeKey <<"\t value = " << GetValue(rcvKernelSizeKey); - LOG(DEBUG) << "key = " << rateLoggingKey <<"\t value = " << GetValue(rateLoggingKey); - */ index++; } - UpdateVarMap(p.first + ".numSockets", index); + UpdateVarMap("chans." + p.first + ".numSockets", index); } } -int FairMQProgOptions::NotifySwitchOption() +int FairMQProgOptions::ImmediateOptions() { if (fVarMap.count("help")) { - std::cout << fHelpTitle << std::endl << fVisibleOptions; + cout << "===== FairMQ Program Options =====" << endl << fVisibleOptions; + return 1; + } + + if (fVarMap.count("print-options")) + { + PrintOptionsRaw(); return 1; } return 0; } -void FairMQProgOptions::FillOptionDescription(boost::program_options::options_description& options) -{ - options.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').") - ("config", po::value()->default_value("static"), "Config source ('static'/).") - ("network-interface", po::value()->default_value("default"), "Network interface to bind on (e.g. eth0, ib0..., default will try to detect the interface of the default route).") - ("config-key", po::value(), "Use provided value instead of device id for fetching the configuration from the config file.") - ("catch-signals", po::value()->default_value(1), "Enable signal handling (1/0).") - ("initialization-timeout", po::value()->default_value(120), "Timeout for the initialization in seconds (when expecting dynamic initialization).") - ("port-range-min", po::value()->default_value(22000), "Start of the port range for dynamic initialization.") - ("port-range-max", po::value()->default_value(32000), "End of the port range for dynamic initialization.") - ("log-to-file", po::value()->default_value(""), "Log output to a file.") - ("print-channels", po::value()->implicit_value(true), "Print registered channel endpoints in a machine-readable format (::)") - ("shm-segment-size", po::value()->default_value(2000000000), "Shared memory: size of the shared memory segment (in bytes).") - ("rate", po::value()->default_value(0.), "Rate for conditional run loop (Hz).") - ("session", po::value()->default_value("default"), "Session name.") - ; - -} - void FairMQProgOptions::InitOptionDescription() { - // Id required in command line if config txt file not enabled - if (fUseConfigFile) - { - FillOptionDescription(fMQOptionsInCmd); - - FillOptionDescription(fMQOptionsInCfg); - } - else - { - FillOptionDescription(fMQOptionsInCmd); - } + fMQCmdOptions.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').") + ("config", po::value()->default_value("static"), "Config source ('static'/).") + ("network-interface", po::value()->default_value("default"), "Network interface to bind on (e.g. eth0, ib0..., default will try to detect the interface of the default route).") + ("config-key", po::value(), "Use provided value instead of device id for fetching the configuration from the config file.") + ("initialization-timeout", po::value()->default_value(120), "Timeout for the initialization in seconds (when expecting dynamic initialization).") + ("port-range-min", po::value()->default_value(22000), "Start of the port range for dynamic initialization.") + ("port-range-max", po::value()->default_value(32000), "End of the port range for dynamic initialization.") + ("log-to-file", po::value()->default_value(""), "Log output to a file.") + ("print-channels", po::value()->implicit_value(true), "Print registered channel endpoints in a machine-readable format (::)") + ("shm-segment-size", po::value()->default_value(2000000000), "Shared memory: size of the shared memory segment (in bytes).") + ("rate", po::value()->default_value(0.), "Rate for conditional run loop (Hz).") + ("session", po::value()->default_value("default"), "Session name.") + ; 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") - (FairMQParser::SUBOPT::OptionKeyChannelConfig, po::value>()->multitoken()->composing(), "Configuration of single or multiple channel(s) by comma separated key=value list") + (FairMQParser::SUBOPT::OptionKeyChannelConfig, po::value>()->multitoken()->composing(), "Configuration of single or multiple channel(s) by comma separated key=value list") ; - AddToCmdLineOptions(fGenericDesc); - AddToCmdLineOptions(fMQOptionsInCmd); + AddToCmdLineOptions(fGeneralDesc); + AddToCmdLineOptions(fMQCmdOptions); AddToCmdLineOptions(fMQParserOptions); - - if (fUseConfigFile) - { - AddToCfgFileOptions(fMQOptionsInCfg, false); - AddToCfgFileOptions(fMQParserOptions, false); - } } int FairMQProgOptions::UpdateChannelMap(const string& channelName, int index, const string& member, const string& val) @@ -409,45 +331,6 @@ int FairMQProgOptions::UpdateChannelMap(const string& channelName, int index, co } } -/* -// string API -int FairMQProgOptions::UpdateChannelMap(const string& channelName, int index, const string& member, const 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; - } - else - { - if (member == "sndBufSize" || member == "rcvBufSize" || member == "rateLogging") - { - UpdateChannelMap(channelName,index,member,ConvertTo(val)); - } - - //if we get there it means something is wrong - LOG(ERROR) << "update of FairMQChannel map failed for the following key: " - << channelName<<"."< +#include "FairProgOptions.h" +#include "FairMQChannel.h" + #include #include #include -#include #include #include -#include "FairProgOptions.h" -#include "FairMQChannel.h" - namespace fair { namespace mq @@ -43,17 +42,15 @@ class FairMQProgOptions : public FairProgOptions { protected: using FairMQMap = std::unordered_map>; - //using signal_type = boost::signals2::signal;// string API - //using signal_type_ptr = boost::shared_ptr;// string API public: FairMQProgOptions(); virtual ~FairMQProgOptions(); - void ParseAll(const std::vector& cmdLineArgs, bool allowUnregistered); - // parse command line and txt/INI configuration file. + int ParseAll(const std::vector& cmdLineArgs, bool allowUnregistered); + // parse command line. // default parser for the mq-configuration file (JSON/XML) is called if command line key mq-config is called - virtual void ParseAll(const int argc, char const* const* argv, bool allowUnregistered = false); + int ParseAll(const int argc, char const* const* argv, bool allowUnregistered = false) override; // external parser, store function template @@ -81,93 +78,11 @@ class FairMQProgOptions : public FairProgOptions return fChannelInfo; } - // to customize title of the executable help command line - void SetHelpTitle(const std::string& title) - { - fHelpTitle = title; - } - // to customize the executable version command line - void SetVersion(const std::string& version) - { - fVersion = version; - } - - // store key-value of type T into variable_map. + // store key-value of type T into variable_map. // If key is found in fMQKeyMap, update the FairMQChannelMap accordingly // Note that the fMQKeyMap is filled: - // - if UpdateChannelMap(const FairMQMap& map) method is called + // - if UpdateChannelMap(const FairMQMap& map) method is called // - if UserParser template method is called (it is called in the ParseAll method if json or xml MQ-config files is provided) - - - /* // string API - - //overload for string literal - int UpdateValue(const std::string& key, const char* val) // string API - { - UpdateValue(key,std::string(val)); - return 0; - } - // overload for string values - int UpdateValue(const std::string& key, const std::string& val) // string API - { - try - { - if (fVarMap.count(key)) - { - - - if (!FairMQ::is_this_type(fVarMap.at(key))) - { - LOG(ERROR) << "You try to update a value as string (for key="<< key <<") while it has been defined with a different type in the option description."; - abort(); - } - - // update variable map - UpdateVarMap(key,val); - - if (fMQKeyMap.count(key)) - { - std::string channelName; - int index = 0; - std::string member; - std::tie(channelName, index, member) = fMQKeyMap.at(key); - UpdateChannelMap(channelName, index, member, val); - } - - // execute stored function of a given key if exist - //if (std::is_same::value || std::is_same::value)//if one wants to restrict type - if (fSignalMap.count(key)) - EmitUpdate(key,val); - - return 0; - } - else - { - - LOG(ERROR) <<"UpdatedValue failed because the provided key '" - <(key,val); - return 0; - }*/ - // specialization/overloading for string, pass by const ref int UpdateValue(const std::string& key, const std::string& val) // string API @@ -214,9 +129,7 @@ class FairMQProgOptions : public FairProgOptions } else { - LOG(ERROR) << "UpdatedValue failed because the provided key '" - << key - << "' is not found in the variable map"; + LOG(error) << "UpdateValue failed: key '" << key << "' not found in the variable map"; return 1; } return 0; @@ -284,30 +197,14 @@ class FairMQProgOptions : public FairProgOptions fEvents.Unsubscribe(subscriber); } - /* - template - void Subscribe(const std::string& key, F&& func) - { - if (fVarMap.count(key)) - { - //if key-value not yet found, then add it - if (fSignalMap.find(key) == fSignalMap.end()) - fSignalMap.emplace(key, boost::make_shared()); - (*fSignalMap.at(key)).connect(std::forward(func)); - } - } - */ // replace FairMQChannelMap, and update variable map accordingly int UpdateChannelMap(const FairMQMap& map); protected: + po::options_description fMQCmdOptions; po::options_description fMQParserOptions; - po::options_description fMQOptionsInCfg; - po::options_description fMQOptionsInCmd; FairMQMap fFairMQMap; - std::string fHelpTitle; - std::string fVersion; // map of read channel info - channel name - number of subchannels std::unordered_map fChannelInfo; @@ -315,36 +212,20 @@ class FairMQProgOptions : public FairProgOptions using MQKey = std::tuple;//store key info std::map fMQKeyMap;// key=full path - val=key info - virtual int NotifySwitchOption(); // for custom help & version printing + int ImmediateOptions() override; // for custom help & version printing void InitOptionDescription(); - // fill boost option description with the standard options - static void FillOptionDescription(po::options_description& options); - // read FairMQChannelMap and insert/update corresponding values in variable map // create key for variable map as follow : channelName.index.memberName void UpdateMQValues(); int Store(const FairMQMap& channels); private: - /* - // string API - std::map fSignalMap; - void EmitUpdate(const std::string& key, const char* val) - { - EmitUpdate(key,std::string(val)); - } - void EmitUpdate(const std::string& key, const std::string& val) - { - (*fSignalMap.at(key))(key,val); - } - */ - template void EmitUpdate(const std::string& key, T val) { //compile time check whether T is const char* or char*, and in that case a compile time error is thrown. - static_assert(!std::is_same::value || !std::is_same::value, + static_assert(!std::is_same::value || !std::is_same::value, "In template member FairMQProgOptions::EmitUpdate(key,val) the types const char* or char* for the calback signatures are not supported."); fEvents.Emit(key, val); fEvents.Emit(key, GetStringValue(key)); diff --git a/fairmq/options/FairProgOptions.cxx b/fairmq/options/FairProgOptions.cxx index 351786d0..0e602e40 100644 --- a/fairmq/options/FairProgOptions.cxx +++ b/fairmq/options/FairProgOptions.cxx @@ -15,49 +15,30 @@ #include "FairProgOptions.h" #include +#include using namespace std; -FairProgOptions::FairProgOptions() : - fVarMap(), - fGenericDesc("Generic options description"), - fConfigDesc("Configuration options description"), - fEnvironmentDesc("Environment variables"), - fHiddenDesc("Hidden options description"), - fCmdLineOptions("Command line options"), - fConfigFileOptions("Configuration file options"), - fSeverityMap(), - fVisibleOptions("Visible options"), - fConfigMutex(), - fVerbosityLevel("INFO"), - fUseConfigFile(false), - fConfigFile() +FairProgOptions::FairProgOptions() + : fVarMap() + , fGeneralDesc("General options") + , fCmdLineOptions("Command line options") + , fVisibleOptions("Visible options") + , fConfigMutex() { - - LOG(NOLOG) << "";// temporary hack to prevent throwing exception when accessing empty sinklist --> fixed me - fGenericDesc.add_options() + fGeneralDesc.add_options() ("help,h", "produce help") ("version,v", "print version") - ("verbosity", po::value(&fVerbosityLevel)->default_value("DEBUG"), "Verbosity level : TRACE, DEBUG, RESULTS, INFO, WARN, ERROR, STATE, NOLOG") - ("log-color", po::value()->default_value(true), "logger color: true or false") + ("severity", po::value()->default_value("debug"), "Log severity level : trace, debug, info, state, warn, error, fatal, nolog") + ("verbosity", po::value()->default_value("medium"), "Log verbosity level : veryhigh, high, medium, low") + ("color", po::value()->default_value(true), "Log color (true/false)") ("print-options", po::value()->implicit_value(true), "print options in machine-readable format (