Single Logger implementation for FairLogger & FairMQLogger

This commit is contained in:
Alexey Rybalchenko 2017-10-11 15:49:49 +02:00 committed by Mohammad Al-Turany
parent d3e0b9fc97
commit 4e942e489b
26 changed files with 295 additions and 1287 deletions

View File

@ -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
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/logger>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}>
$<INSTALL_INTERFACE:include/fairmq>
@ -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
$<$<PLATFORM_ID:Linux>:rt>
PRIVATE # only libFairMQ links against private dependencies

View File

@ -41,7 +41,10 @@ auto DeviceRunner::Run() -> int
fEvents.Emit<hooks::ModifyRawCmdLineArgs>(*this);
////////////////////////
fConfig.ParseAll(fRawCmdLineArgs, true);
if (fConfig.ParseAll(fRawCmdLineArgs, true))
{
return 0;
}
////// CALL HOOK ///////
fEvents.Emit<hooks::InstantiateDevice>(*this);

View File

@ -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<timestamp_t>(now.tv_sec) * 1000000;
}

View File

@ -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 <Logger.h>
using timestamp_t = unsigned long long;

View File

@ -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 */

View File

@ -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 <boost/version.hpp>
#include <boost/log/core/core.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/log/support/date_time.hpp>
#include <boost/log/utility/setup/common_attributes.hpp>
#include <boost/log/utility/manipulators/to_log.hpp>
#include <boost/log/utility/formatting_ostream.hpp>
#include <boost/log/sinks/text_ostream_backend.hpp>
#include <boost/log/sinks/text_file_backend.hpp>
#include <boost/log/sinks/sync_frontend.hpp>
#include <boost/log/sinks/basic_sink_frontend.hpp>
#include <boost/log/expressions.hpp>
#include <boost/log/expressions/attr.hpp>
#include <boost/log/expressions/attr_fwd.hpp>
#include <boost/log/expressions/keyword.hpp>
#if BOOST_VERSION < 105600
#include "fairroot_null_deleter.h"
using empty_deleter_t = fairroot::null_deleter;
#else
#include <boost/core/null_deleter.hpp>
using empty_deleter_t = boost::null_deleter;
#endif
#include <boost/make_shared.hpp>
#include <boost/shared_ptr.hpp>
#include <fstream>
#include <ostream>
#include <string>
#include <vector>
#include <sstream>
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<fair::mq::logger::SeverityLevel> globalLogger;
globalLogger.add_attribute("TimeStamp", blog::attributes::local_clock());
fair::mq::logger::DefaultConsoleInit();
return globalLogger;
}
namespace fair
{
namespace mq
{
namespace logger
{
vector<boost::shared_ptr<blog::sinks::basic_sink_frontend>> 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<bptime::ptime>("TimeStamp", "%H:%M:%S");
dateTimeFormatter(view, os);
os << "\033[0m][" << view.attribute_values()["Severity"].extract<SeverityLevel, TagConsole>() << "] " << view.attribute_values()["Message"].extract<string>();
}
void InitFileLogFormatter(const blog::record_view& view, blog::formatting_ostream& os)
{
os << "[";
auto dateTimeFormatter = blog::expressions::stream << blog::expressions::format_date_time<bptime::ptime>("TimeStamp", "%H:%M:%S");
dateTimeFormatter(view, os);
os << "][" << view.attribute_values()["Severity"].extract<SeverityLevel, TagFile>() << "] " << view.attribute_values()["Message"].extract<string>();
}
// 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<SeverityLevel, TagConsole> const& manip)
{
SeverityLevel level = manip.get();
size_t idx = static_cast<size_t>(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<int>(level) << ")";
}
return stream;
}
// overload operator for file output
blog::formatting_ostream& operator<<(blog::formatting_ostream& stream, blog::to_log_manip<SeverityLevel, TagFile> const& manip)
{
SeverityLevel level = manip.get();
size_t idx = static_cast<size_t>(level);
if (idx < gLogSeverityLevelString.size())
{
stream << gLogSeverityLevelString.at(idx);
}
else
{
stream << writeIn("Unknown log level ", color::FG_RED) << "(int level = " << static_cast<int>(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<blog::sinks::text_ostream_backend>;
RemoveRegisteredSinks();
// CONSOLE - all severity except error
boost::shared_ptr<TextSink> sink = boost::make_shared<TextSink>();
// add "console" output stream to our sink
sink->locked_backend()->add_stream(boost::shared_ptr<ostream>(&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<TextSink> sinkError = boost::make_shared<TextSink>();
sinkError->locked_backend()->add_stream(boost::shared_ptr<ostream>(&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<SeverityLevel>();
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<SeverityLevel>();
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<SinkBackend>;
boost::shared_ptr<SinkBackend> backend = boost::make_shared<SinkBackend>(
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> sink = boost::make_shared<Sink>(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<SeverityLevel>();
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

View File

@ -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 <boost/version.hpp>
#include <boost/log/sources/global_logger_storage.hpp>
#include <boost/log/sources/severity_logger.hpp>
#include <boost/log/sources/record_ostream.hpp>
#include <array>
namespace fair
{
namespace mq
{
namespace logger
{
enum SeverityLevel
{
TRACE,
DEBUG,
RESULTS,
INFO,
STATE,
WARN,
ERROR,
NOLOG
};
static const std::array<std::string, 8> 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<fair::mq::logger::SeverityLevel>)
// 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

View File

@ -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 <boost/log/support/date_time.hpp>
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) *********"<<std::endl;
SET_LOG_CONSOLE_LEVEL(TRACE);
test_logger();
std::cout << "----------------------------"<<std::endl;
SET_LOG_CONSOLE_LEVEL(DEBUG);
test_logger();
std::cout << "----------------------------"<<std::endl;
SET_LOG_CONSOLE_LEVEL(RESULTS);
test_logger();
std::cout << "----------------------------"<<std::endl;
SET_LOG_CONSOLE_LEVEL(INFO);
test_logger();
std::cout << "----------------------------"<<std::endl;
SET_LOG_CONSOLE_LEVEL(WARN);
test_logger();
std::cout << "----------------------------"<<std::endl;
SET_LOG_CONSOLE_LEVEL(ERROR);
test_logger();
std::cout << "----------------------------"<<std::endl;
SET_LOG_CONSOLE_LEVEL(STATE);
test_logger();
std::cout << "----------------------------"<<std::endl;
}
int main()
{
test_console_level();
SET_LOG_CONSOLE_LEVEL(INFO);
std::cout << "----------------------------"<<std::endl;
LOG(INFO)<<"open log file 1";
ADD_LOG_FILESINK("test_log1",ERROR);
test_logger();
std::cout << "----------------------------"<<std::endl;
LOG(INFO)<<"open log file 2";
ADD_LOG_FILESINK("test_log2",STATE);
test_logger();
// advanced commands
std::cout << "----------------------------"<<std::endl;
LOG(INFO)<<"open log file 3";// custom file sink setting
// AddFileSink([](const boost::log::attribute_value_set& attr_set)
// {
// auto sev = attr_set["Severity"].extract<custom_severity_level>();
// 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 << "----------------------------"<<std::endl;
LOG(INFO)<<"set filter of last sink";// custom file sink setting
// get last added sink and reset filter to WARN and ERROR
FairMQ::Logger::sinkList.back()->set_filter([](const boost::log::attribute_value_set& attr_set)
{
auto sev = attr_set["Severity"].extract<custom_severity_level>();
return (sev == FairMQ::WARN) || (sev == FairMQ::ERROR);
});
test_logger();
// remove all sinks, and restart console sinks
ReinitLogger(false);
test_logger();
return 0;
}

View File

@ -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<string>("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<string>("<xmlattr>.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<string>("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<FairMQChannel>
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<string>() << std::endl;
cout << setw(level+1) << level << ": " << p.first << " " << p.second.get_value<string>() << endl;
PrintPropertyTree(p.second.get_child(""), level + 1);
}
}

View File

@ -8,30 +8,27 @@
/*
* File: FairMQProgOptions.cxx
* Author: winckler
*
*
* Created on March 11, 2015, 10:20 PM
*/
#include "FairMQProgOptions.h"
#include <algorithm>
#include "FairMQParser.h"
#include "FairMQSuboptParser.h"
#include "FairMQLogger.h"
#include <algorithm>
#include <iostream>
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<std::string>& cmdLineArgs, bool allowUnregistered)
int FairMQProgOptions::ParseAll(const vector<string>& cmdLineArgs, bool allowUnregistered)
{
std::vector<const char*> argv(cmdLineArgs.size());
vector<const char*> 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<char**>(argv.data()), allowUnregistered);
return ParseAll(argv.size(), const_cast<char**>(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<string>("severity");
string logFile = GetValue<string>("log-to-file");
bool color = GetValue<bool>("color");
string verbosity = GetValue<string>("verbosity");
string logFile = GetValue<string>("log-to-file");
bool color = GetValue<bool>("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<string>(methodKey, channel.GetMethod());
UpdateVarMap<string>(addressKey, channel.GetAddress());
UpdateVarMap<string>(transportKey, channel.GetTransport());
//UpdateVarMap<string>(sndBufSizeKey, to_string(channel.GetSndBufSize()));// string API
UpdateVarMap<int>(sndBufSizeKey, channel.GetSndBufSize());
//UpdateVarMap<string>(rcvBufSizeKey, to_string(channel.GetRcvBufSize()));// string API
UpdateVarMap<int>(rcvBufSizeKey, channel.GetRcvBufSize());
//UpdateVarMap<string>(sndKernelSizeKey, to_string(channel.GetSndKernelSize()));// string API
UpdateVarMap<int>(sndKernelSizeKey, channel.GetSndKernelSize());
//UpdateVarMap<string>(rcvKernelSizeKey, to_string(channel.GetRcvKernelSize()));// string API
UpdateVarMap<int>(rcvKernelSizeKey, channel.GetRcvKernelSize());
//UpdateVarMap<string>(rateLoggingKey,to_string(channel.GetRateLogging()));// string API
UpdateVarMap<int>(rateLoggingKey, channel.GetRateLogging());
/*
LOG(DEBUG) << "Update MQ parameters of variable map";
LOG(DEBUG) << "key = " << typeKey <<"\t value = " << GetValue<string>(typeKey);
LOG(DEBUG) << "key = " << methodKey <<"\t value = " << GetValue<string>(methodKey);
LOG(DEBUG) << "key = " << addressKey <<"\t value = " << GetValue<string>(addressKey);
LOG(DEBUG) << "key = " << sndBufSizeKey << "\t value = " << GetValue<int>(sndBufSizeKey);
LOG(DEBUG) << "key = " << rcvBufSizeKey <<"\t value = " << GetValue<int>(rcvBufSizeKey);
LOG(DEBUG) << "key = " << sndKernelSizeKey << "\t value = " << GetValue<int>(sndKernelSizeKey);
LOG(DEBUG) << "key = " << rcvKernelSizeKey <<"\t value = " << GetValue<int>(rcvKernelSizeKey);
LOG(DEBUG) << "key = " << rateLoggingKey <<"\t value = " << GetValue<int>(rateLoggingKey);
*/
index++;
}
UpdateVarMap<int>(p.first + ".numSockets", index);
UpdateVarMap<int>("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<string>(), "Device ID (required argument).")
("io-threads", po::value<int >()->default_value(1), "Number of I/O threads.")
("transport", po::value<string>()->default_value("zeromq"), "Transport ('zeromq'/'nanomsg').")
("config", po::value<string>()->default_value("static"), "Config source ('static'/<config library filename>).")
("network-interface", po::value<string>()->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<string>(), "Use provided value instead of device id for fetching the configuration from the config file.")
("catch-signals", po::value<int >()->default_value(1), "Enable signal handling (1/0).")
("initialization-timeout", po::value<int >()->default_value(120), "Timeout for the initialization in seconds (when expecting dynamic initialization).")
("port-range-min", po::value<int >()->default_value(22000), "Start of the port range for dynamic initialization.")
("port-range-max", po::value<int >()->default_value(32000), "End of the port range for dynamic initialization.")
("log-to-file", po::value<string>()->default_value(""), "Log output to a file.")
("print-channels", po::value<bool >()->implicit_value(true), "Print registered channel endpoints in a machine-readable format (<channel name>:<min num subchannels>:<max num subchannels>)")
("shm-segment-size", po::value<size_t>()->default_value(2000000000), "Shared memory: size of the shared memory segment (in bytes).")
("rate", po::value<float >()->default_value(0.), "Rate for conditional run loop (Hz).")
("session", po::value<string>()->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<string>(), "Device ID (required argument).")
("io-threads", po::value<int >()->default_value(1), "Number of I/O threads.")
("transport", po::value<string>()->default_value("zeromq"), "Transport ('zeromq'/'nanomsg').")
("config", po::value<string>()->default_value("static"), "Config source ('static'/<config library filename>).")
("network-interface", po::value<string>()->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<string>(), "Use provided value instead of device id for fetching the configuration from the config file.")
("initialization-timeout", po::value<int >()->default_value(120), "Timeout for the initialization in seconds (when expecting dynamic initialization).")
("port-range-min", po::value<int >()->default_value(22000), "Start of the port range for dynamic initialization.")
("port-range-max", po::value<int >()->default_value(32000), "End of the port range for dynamic initialization.")
("log-to-file", po::value<string>()->default_value(""), "Log output to a file.")
("print-channels", po::value<bool >()->implicit_value(true), "Print registered channel endpoints in a machine-readable format (<channel name>:<min num subchannels>:<max num subchannels>)")
("shm-segment-size", po::value<size_t>()->default_value(2000000000), "Shared memory: size of the shared memory segment (in bytes).")
("rate", po::value<float >()->default_value(0.), "Rate for conditional run loop (Hz).")
("session", po::value<string>()->default_value("default"), "Session name.")
;
fMQParserOptions.add_options()
("config-xml-string", po::value<vector<string>>()->multitoken(), "XML input as command line string.")
// ("config-xml-file", po::value<string>(), "XML input as file.")
("config-json-string", po::value<vector<string>>()->multitoken(), "JSON input as command line string.")
// ("config-json-file", po::value<string>(), "JSON input as file.")
("mq-config", po::value<string>(), "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<std::vector<std::string>>()->multitoken()->composing(), "Configuration of single or multiple channel(s) by comma separated key=value list")
(FairMQParser::SUBOPT::OptionKeyChannelConfig, po::value<vector<string>>()->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<int>(val));
}
//if we get there it means something is wrong
LOG(ERROR) << "update of FairMQChannel map failed for the following key: "
<< channelName<<"."<<index<<"."<<member;
return 1;
}
}
*/
// ----------------------------------------------------------------------------------
int FairMQProgOptions::UpdateChannelMap(const string& channelName, int index, const string& member, int val)
{
if (member == "sndBufSize")
@ -469,9 +352,8 @@ int FairMQProgOptions::UpdateChannelMap(const string& channelName, int index, co
}
else
{
//if we get there it means something is wrong
LOG(ERROR) << "update of FairMQChannel map failed for the following key: "
<< channelName << "." << index << "." << member;
// if we get there it means something is wrong
LOG(ERROR) << "update of FairMQChannel map failed for the following key: " << channelName << "." << index << "." << member;
return 1;
}
}

View File

@ -18,16 +18,15 @@
#include <fairmq/EventManager.h>
#include "FairProgOptions.h"
#include "FairMQChannel.h"
#include <unordered_map>
#include <functional>
#include <map>
#include <set>
#include <mutex>
#include <string>
#include "FairProgOptions.h"
#include "FairMQChannel.h"
namespace fair
{
namespace mq
@ -43,17 +42,15 @@ class FairMQProgOptions : public FairProgOptions
{
protected:
using FairMQMap = std::unordered_map<std::string, std::vector<FairMQChannel>>;
//using signal_type = boost::signals2::signal<void(const std::string&, const std::string&)>;// string API
//using signal_type_ptr = boost::shared_ptr<signal_type>;// string API
public:
FairMQProgOptions();
virtual ~FairMQProgOptions();
void ParseAll(const std::vector<std::string>& cmdLineArgs, bool allowUnregistered);
// parse command line and txt/INI configuration file.
int ParseAll(const std::vector<std::string>& 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 <typename T, typename ...Args>
@ -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<std::string>(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<T, int>::value || std::is_same<T, std::string>::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
<<"' is not found in the variable map";
return 1;
}
}
catch (std::exception& e)
{
LOG(ERROR) << "Caught exception on key "<<key;
abort();
}
return 0;
}
*/
//overload for string literal
/*int UpdateValue(const std::string& key, const char* val) // string API
{
UpdateValue<std::string>(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<fair::mq::PropertyChangeAsString, std::string>(subscriber);
}
/*
template <typename F>
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<signal_type>());
(*fSignalMap.at(key)).connect(std::forward<F>(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<std::string, int> fChannelInfo;
@ -315,36 +212,20 @@ class FairMQProgOptions : public FairProgOptions
using MQKey = std::tuple<std::string, int, std::string>;//store key info
std::map<std::string, MQKey> 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<std::string, signal_type_ptr > 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<typename T>
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<T,const char*>::value || !std::is_same<T, char*>::value,
static_assert(!std::is_same<T,const char*>::value || !std::is_same<T, char*>::value,
"In template member FairMQProgOptions::EmitUpdate<T>(key,val) the types const char* or char* for the calback signatures are not supported.");
fEvents.Emit<fair::mq::PropertyChange, T>(key, val);
fEvents.Emit<fair::mq::PropertyChangeAsString, std::string>(key, GetStringValue(key));

View File

@ -15,49 +15,30 @@
#include "FairProgOptions.h"
#include <iomanip>
#include <sstream>
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<std::string>(&fVerbosityLevel)->default_value("DEBUG"), "Verbosity level : TRACE, DEBUG, RESULTS, INFO, WARN, ERROR, STATE, NOLOG")
("log-color", po::value<bool>()->default_value(true), "logger color: true or false")
("severity", po::value<string>()->default_value("debug"), "Log severity level : trace, debug, info, state, warn, error, fatal, nolog")
("verbosity", po::value<string>()->default_value("medium"), "Log verbosity level : veryhigh, high, medium, low")
("color", po::value<bool>()->default_value(true), "Log color (true/false)")
("print-options", po::value<bool>()->implicit_value(true), "print options in machine-readable format (<option>:<computed-value>:<type>:<description>)");
fSeverityMap["TRACE"] = fair::mq::logger::SeverityLevel::TRACE;
fSeverityMap["DEBUG"] = fair::mq::logger::SeverityLevel::DEBUG;
fSeverityMap["RESULTS"] = fair::mq::logger::SeverityLevel::RESULTS;
fSeverityMap["INFO"] = fair::mq::logger::SeverityLevel::INFO;
fSeverityMap["WARN"] = fair::mq::logger::SeverityLevel::WARN;
fSeverityMap["ERROR"] = fair::mq::logger::SeverityLevel::ERROR;
fSeverityMap["STATE"] = fair::mq::logger::SeverityLevel::STATE;
fSeverityMap["NOLOG"] = fair::mq::logger::SeverityLevel::NOLOG;
}
/// Destructor
FairProgOptions::~FairProgOptions()
{
}
/// //////////////////////////////////////////////////////////////////////////////////////////////////////
/// Add option descriptions
int FairProgOptions::AddToCmdLineOptions(const po::options_description optDesc, bool visible)
{
@ -69,61 +50,11 @@ int FairProgOptions::AddToCmdLineOptions(const po::options_description optDesc,
return 0;
}
int FairProgOptions::AddToCfgFileOptions(const po::options_description optDesc, bool visible)
{
//if UseConfigFile() not yet called, then enable it with required file name to be provided by command line
if (!fUseConfigFile)
{
UseConfigFile();
}
fConfigFileOptions.add(optDesc);
if (visible)
{
fVisibleOptions.add(optDesc);
}
return 0;
}
//*
po::options_description& FairProgOptions::GetCmdLineOptions()
{
return fCmdLineOptions;
}
po::options_description& FairProgOptions::GetCfgFileOptions()
{
return fConfigFileOptions;
}
po::options_description& FairProgOptions::GetEnvironmentOptions()
{
return fEnvironmentDesc;
}
int FairProgOptions::AddToEnvironmentOptions(const po::options_description optDesc)
{
fEnvironmentDesc.add(optDesc);
return 0;
}
void FairProgOptions::UseConfigFile(const string& filename)
{
fUseConfigFile = true;
if (filename.empty())
{
fConfigDesc.add_options()
("config-file", po::value<boost::filesystem::path>(&fConfigFile)->required(), "Path to configuration file (required argument)");
AddToCmdLineOptions(fConfigDesc);
}
else
{
fConfigFile = filename;
}
}
/// //////////////////////////////////////////////////////////////////////////////////////////////////////
/// Parser
int FairProgOptions::ParseCmdLine(const int argc, char const* const* argv, const po::options_description& desc, po::variables_map& varmap, bool allowUnregistered)
{
// get options from cmd line and store in variable map
@ -140,9 +71,9 @@ int FairProgOptions::ParseCmdLine(const int argc, char const* const* argv, const
po::store(po::parse_command_line(argc, argv, desc), varmap);
}
// call the virtual NotifySwitchOption method to handle switch options like e.g. "--help" or "--version"
// Handles options like "--help" or "--version"
// return 1 if switch options found in varmap
if (NotifySwitchOption())
if (ImmediateOptions())
{
return 1;
}
@ -156,89 +87,8 @@ int FairProgOptions::ParseCmdLine(const int argc, char const* const* argv, const
return ParseCmdLine(argc, argv, desc, fVarMap, allowUnregistered);
}
int FairProgOptions::ParseCfgFile(ifstream& ifs, const po::options_description& desc, po::variables_map& varmap, bool allowUnregistered)
{
if (!ifs)
{
LOG(ERROR) << "can not open configuration file";
return -1;
}
else
{
po::store(parse_config_file(ifs, desc, allowUnregistered), varmap);
po::notify(varmap);
}
return 0;
}
int FairProgOptions::ParseCfgFile(const string& filename, const po::options_description& desc, po::variables_map& varmap, bool allowUnregistered)
{
ifstream ifs(filename.c_str());
if (!ifs)
{
LOG(ERROR) << "can not open configuration file: " << filename;
return -1;
}
else
{
po::store(parse_config_file(ifs, desc, allowUnregistered), varmap);
po::notify(varmap);
}
return 0;
}
int FairProgOptions::ParseCfgFile(const string& filename, const po::options_description& desc, bool allowUnregistered)
{
return ParseCfgFile(filename,desc,fVarMap,allowUnregistered);
}
int FairProgOptions::ParseCfgFile(ifstream& ifs, const po::options_description& desc, bool allowUnregistered)
{
return ParseCfgFile(ifs,desc,fVarMap,allowUnregistered);
}
int FairProgOptions::ParseEnvironment(const function<string(string)>& environmentMapper)
{
po::store(po::parse_environment(fEnvironmentDesc, environmentMapper), fVarMap);
po::notify(fVarMap);
return 0;
}
int FairProgOptions::PrintHelp() const
{
cout << fVisibleOptions << "\n";
return 0;
}
int FairProgOptions::PrintOptionsRaw()
{
MapVarValInfo_t mapInfo;
for (const auto& m : fVarMap)
{
mapInfo[m.first] = GetVariableValueInfo(m.second);
}
for (const auto& p : mapInfo)
{
string keyStr;
string valueStr;
string typeInfoStr;
string defaultStr;
string emptyStr;
keyStr = p.first;
tie(valueStr, typeInfoStr, defaultStr, emptyStr) = p.second;
auto option = fCmdLineOptions.find_nothrow(keyStr, false);
cout << keyStr << ":" << valueStr << ":" << typeInfoStr << ":" << (option ? option->description() : "<not found>") << endl;
}
return 0;
}
int FairProgOptions::PrintOptions()
{
// //////////////////////////////////
// Method to overload.
// -> loop over variable map and print its content
// -> In this example the following types are supported:
@ -283,20 +133,27 @@ int FairProgOptions::PrintOptions()
// formatting and printing
LOG(DEBUG) << setfill ('*') << setw (totalLength + 3) << "*";// +3 because of string " = "
string PrintOptionsTitle = " Configuration ";
stringstream ss;
ss << "\n";
ss << setfill('*') << setw(totalLength + 3) << "*" << "\n"; // +3 because of string " = "
string title = " Configuration ";
int leftSpaceLength = 0;
int rightSpaceLength = 0;
int leftTitleShiftLength = 0;
int rightTitleShiftLength = 0;
leftTitleShiftLength = PrintOptionsTitle.length() / 2;
leftTitleShiftLength = title.length() / 2;
if ((PrintOptionsTitle.length()) % 2)
if ((title.length()) % 2)
{
rightTitleShiftLength = leftTitleShiftLength + 1;
}
else
{
rightTitleShiftLength = leftTitleShiftLength;
}
leftSpaceLength = (totalLength + 3) / 2 - leftTitleShiftLength;
if ((totalLength + 3) % 2)
@ -308,11 +165,11 @@ int FairProgOptions::PrintOptions()
rightSpaceLength = (totalLength + 3) / 2 - rightTitleShiftLength;
}
LOG(DEBUG) << setfill ('*') << setw(leftSpaceLength) << "*"
<< setw(PrintOptionsTitle.length()) << PrintOptionsTitle
<< setfill ('*') << setw(rightSpaceLength) << "*";
ss << setfill ('*') << setw(leftSpaceLength) << "*"
<< setw(title.length()) << title
<< setfill ('*') << setw(rightSpaceLength) << "*" << "\n";
LOG(DEBUG) << setfill ('*') << setw (totalLength+3) << "*";
ss << setfill ('*') << setw (totalLength+3) << "*" << "\n";
for (const auto& p : mapinfo)
{
@ -323,36 +180,46 @@ int FairProgOptions::PrintOptions()
string emptyStr;
keyStr = p.first;
tie(valueStr, typeInfoStr, defaultStr, emptyStr) = p.second;
LOG(DEBUG) << std::setfill(' ')
<< setw(maxLength1st) << left
<< p.first << " = "
<< setw(maxLength2nd)
<< valueStr
<< setw(maxLengthTypeInfo)
<< typeInfoStr
<< setw(maxLengthDefault)
<< defaultStr
<< setw(maxLengthEmpty)
<< emptyStr;
ss << setfill(' ')
<< setw(maxLength1st) << left
<< p.first << " = "
<< setw(maxLength2nd)
<< valueStr
<< setw(maxLengthTypeInfo)
<< typeInfoStr
<< setw(maxLengthDefault)
<< defaultStr
<< setw(maxLengthEmpty)
<< emptyStr
<< "\n";
}
LOG(DEBUG) << setfill ('*') << setw (totalLength + 3) << "*";// +3 for " = "
ss << setfill ('*') << setw(totalLength + 3) << "*";// +3 for " = "
LOG(DEBUG) << ss.str();
return 0;
}
int FairProgOptions::NotifySwitchOption()
int FairProgOptions::PrintOptionsRaw()
{
// Method to overload.
if (fVarMap.count("help"))
MapVarValInfo_t mapInfo;
for (const auto& m : fVarMap)
{
cout << "***** FAIR Program Options ***** \n" << fVisibleOptions;
return 1;
mapInfo[m.first] = GetVariableValueInfo(m.second);
}
if (fVarMap.count("version"))
for (const auto& p : mapInfo)
{
cout << "alpha version 0.0\n";
return 1;
string keyStr;
string valueStr;
string typeInfoStr;
string defaultStr;
string emptyStr;
keyStr = p.first;
tie(valueStr, typeInfoStr, defaultStr, emptyStr) = p.second;
auto option = fCmdLineOptions.find_nothrow(keyStr, false);
cout << keyStr << ":" << valueStr << ":" << typeInfoStr << ":" << (option ? option->description() : "<not found>") << endl;
}
return 0;

View File

@ -16,27 +16,28 @@
#define FAIRPROGOPTIONS_H
#include "FairMQLogger.h"
#include "FairProgOptionsHelper.h"
#include <boost/program_options.hpp>
#include <boost/filesystem.hpp>
#include "FairProgOptionsHelper.h"
#include <string>
#include <vector>
#include <iostream>
#include <fstream>
#include <iterator>
#include <mutex>
#include <tuple>
/*
* FairProgOptions abstract base class
* parse command line, configuration file options as well as environment variables.
*
* parse command line, configuration file options.
*
* The user defines in the derived class the option descriptions and
* the pure virtual ParseAll() method
*
*
* class MyOptions : public FairProgOptions
* {
* public :
* public :
* MyOptions() : FairProgOptions()
* {
* fCmdlineOptions.add(fGenericDesc);
@ -80,13 +81,7 @@ class FairProgOptions
// add options_description
int AddToCmdLineOptions(const po::options_description optDesc, bool visible = true);
int AddToCfgFileOptions(const po::options_description optDesc, bool visible = true);
int AddToEnvironmentOptions(const po::options_description optDesc);
po::options_description& GetCmdLineOptions();
po::options_description& GetCfgFileOptions();
po::options_description& GetEnvironmentOptions();
void UseConfigFile(const std::string& filename = "");
// get value corresponding to the key
template<typename T>
@ -108,9 +103,8 @@ class FairProgOptions
}
catch (std::exception& e)
{
LOG(ERROR) << "Exception thrown for the key '" << key << "'";
LOG(ERROR) << e.what();
this->PrintHelp();
LOG(error) << "Exception thrown for the key '" << key << "'";
LOG(error) << e.what();
}
return val;
@ -168,44 +162,26 @@ class FairProgOptions
int ParseCmdLine(const int argc, char const* const* argv, const po::options_description& desc, po::variables_map& varmap, bool allowUnregistered = false);
int ParseCmdLine(const int argc, char const* const* argv, const po::options_description& desc, bool allowUnregistered = false);
int ParseCfgFile(const std::string& filename, const po::options_description& desc, po::variables_map& varmap, bool allowUnregistered = false);
int ParseCfgFile(const std::string& filename, const po::options_description& desc, bool allowUnregistered = false);
int ParseCfgFile(std::ifstream& ifs, const po::options_description& desc, po::variables_map& varmap, bool allowUnregistered = false);
int ParseCfgFile(std::ifstream& ifs, const po::options_description& desc, bool allowUnregistered = false);
int ParseEnvironment(const std::function<std::string(std::string)>&);
virtual void ParseAll(const int argc, char const* const* argv, bool allowUnregistered = false) = 0;// TODO change return type to bool and propagate to executable
virtual int ParseAll(const int argc, char const* const* argv, bool allowUnregistered = false) = 0;// TODO change return type to bool and propagate to executable
virtual int PrintOptions();
virtual int PrintOptionsRaw();
int PrintHelp() const;
protected:
// options container
po::variables_map fVarMap;
// basic description categories
po::options_description fGenericDesc;
po::options_description fConfigDesc;
po::options_description fEnvironmentDesc;
po::options_description fHiddenDesc;
po::options_description fGeneralDesc;
// Description of cmd line and simple configuration file (configuration file like txt, but not like xml json ini)
po::options_description fCmdLineOptions;
po::options_description fConfigFileOptions;
// Description which is printed in help command line
// to handle logger severity
std::map<std::string, fair::mq::logger::SeverityLevel> fSeverityMap;
po::options_description fVisibleOptions;
mutable std::mutex fConfigMutex;
std::string fVerbosityLevel;
bool fUseConfigFile;
boost::filesystem::path fConfigFile;
virtual int NotifySwitchOption();
virtual int ImmediateOptions() = 0;
// UpdateVarMap() and replace() --> helper functions to modify the value of variable map after calling po::store
template<typename T>
@ -227,7 +203,7 @@ class FairProgOptions
VarValInfo_t GetVariableValueInfo(const po::variable_value& varValue);
static void Max(int &val, const int &comp)
static void Max(int& val, const int& comp)
{
if (comp > val)
{

View File

@ -1,48 +1,44 @@
<fairMQOptions>
<device name="merger" id="merger" >
<channel name="two_inputs_channel" >
<socket name="input1" >
<type>pull</type>
<method>bind</method>
<address>tcp://*:5569</address>
<sndBufSize>1000</sndBufSize>
<rcvBufSize>1000</rcvBufSize>
<rateLogging>1</rateLogging>
</socket>
<socket name="input2" >
<type>pull</type>
<method>bind</method>
<address>tcp://*:5570</address>
<sndBufSize>1000</sndBufSize>
<rcvBufSize>1000</rcvBufSize>
<rateLogging>1</rateLogging>
</socket>
</channel>
<channel name="one_output_channel" >
<socket name="output1" >
<type>push</type>
<method>connect</method>
<address>tcp://*:5571</address>
<sndBufSize>1000</sndBufSize>
<rcvBufSize>1000</rcvBufSize>
<rateLogging>1</rateLogging>
</socket>
</channel>
<device name="merger" id="merger">
<channel name="two_inputs_channel">
<socket name="input1">
<type>pull</type>
<method>bind</method>
<address>tcp://*:5569</address>
<sndBufSize>1000</sndBufSize>
<rcvBufSize>1000</rcvBufSize>
<rateLogging>1</rateLogging>
</socket>
<socket name="input2">
<type>pull</type>
<method>bind</method>
<address>tcp://*:5570</address>
<sndBufSize>1000</sndBufSize>
<rcvBufSize>1000</rcvBufSize>
<rateLogging>1</rateLogging>
</socket>
</channel>
<channel name="one_output_channel">
<socket name="output1">
<type>push</type>
<method>connect</method>
<address>tcp://*:5571</address>
<sndBufSize>1000</sndBufSize>
<rcvBufSize>1000</rcvBufSize>
<rateLogging>1</rateLogging>
</socket>
</channel>
</device>
<device name="sink" id="sink" >
<channel name="one_input" >
<socket name="input1" >
<type>pull</type>
<method>bind</method>
<address>tcp://localhost:5571</address>
<sndBufSize>1000</sndBufSize>
<rcvBufSize>1000</rcvBufSize>
<rateLogging>1</rateLogging>
</socket>
<device name="sink" id="sink">
<channel name="one_input">
<socket name="input1">
<type>pull</type>
<method>bind</method>
<address>tcp://localhost:5571</address>
<sndBufSize>1000</sndBufSize>
<rcvBufSize>1000</rcvBufSize>
<rateLogging>1</rateLogging>
</socket>
</channel>
</device>
</fairMQOptions>

View File

@ -10,19 +10,13 @@
#include "FairMQParser.h"
#include "FairMQProgOptions.h"
//////////////////////////////////////////////////////////////
// tests
//////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////
// Parse xml from file
int testXML1(FairMQProgOptions* config)
{
LOG(INFO)<<"--------- test XML1 ---------\n";
std::string filename;
std::string XMLrootNode;
filename=config->GetValue<std::string>("config-xml-file");
XMLrootNode=config->GetValue<std::string>("xml.config.node.root");
std::string id=config->GetValue<std::string>("id");
@ -30,12 +24,11 @@ int testXML1(FairMQProgOptions* config)
// other xml parser test
config->UserParser<FairMQParser::MQXML2>(filename);
config->UserParser<FairMQParser::MQXML3>(filename,"merger");
LOG(INFO)<<"--------- test XML1 end ---------\n";
return 0;
}
// Parse xml from command line
int testXML2(FairMQProgOptions* config)
{
@ -44,14 +37,14 @@ int testXML2(FairMQProgOptions* config)
std::string XMLrootNode;
std::string id=config->GetValue<std::string>("id");
XMLrootNode=config->GetValue<std::string>("xml.config.node.root");
// Note: convert the vector<string> into one string with GetStringValue(key)
XML=config->GetStringValue("config-xml-string");
std::stringstream iss;
iss << XML;
config->UserParser<FairMQParser::XML>(iss,id,XMLrootNode);
LOG(INFO)<<"--------- test XML2 end ---------\n";
return 0;
}
@ -63,12 +56,12 @@ int testJSON1(FairMQProgOptions* config)
std::string filename;
std::string JSONrootNode;
std::string id=config->GetValue<std::string>("id");
filename=config->GetValue<std::string>("config-json-file");
JSONrootNode=config->GetValue<std::string>("json.config.node.root");
config->UserParser<FairMQParser::JSON>(filename,id,JSONrootNode);
LOG(INFO)<<"--------- test JSON1 end ---------\n";
return 0;
}
@ -81,59 +74,63 @@ int testJSON2(FairMQProgOptions* config)
std::string JSONrootNode;
std::string id=config->GetValue<std::string>("id");
JSONrootNode=config->GetValue<std::string>("json.config.node.root");
// Note: convert the vector<string> into one string with GetStringValue(key)
JSON=config->GetStringValue("config-json-string");
std::stringstream iss;
iss << JSON;
config->UserParser<FairMQParser::JSON>(iss,id,JSONrootNode);
LOG(INFO)<<"--------- test JSON2 end ---------\n";
return 0;
}
//////////////////////////////////////////////////////////////
/// main
//////////////////////////////////////////////////////////////
int main(int argc, char** argv)
{
FairMQProgOptions* config= new FairMQProgOptions();
try
{
po::options_description format_desc("XML or JSON input");
format_desc.add_options()
format_desc.add_options()
("xml.config.node.root", po::value<std::string>()->default_value("fairMQOptions"), "xml root node ")
("json.config.node.root", po::value<std::string>()->default_value("fairMQOptions"), "json root node ")
;
config->AddToCmdLineOptions(format_desc);
// Parse command line
if(config->ParseAll(argc,argv))
if (config->ParseAll(argc,argv))
{
return 0;
}
// Set severity level (Default is 0=DEBUG)
int verbosity = config->GetValue<int>("verbosity");
FairMQLogger::Level lvl=static_cast<FairMQLogger::Level>(verbosity);
int severity = config->GetValue<int>("severity");
FairMQLogger::Level lvl=static_cast<FairMQLogger::Level>(severity);
SET_LOGGER_LEVEL(lvl);
// Parse xml or json from cmd line or file
if(config->GetVarMap().count("config-xml-file"))
if (config->GetVarMap().count("config-xml-file"))
{
testXML1(config);
if(config->GetVarMap().count("config-xml-string"))
}
if (config->GetVarMap().count("config-xml-string"))
{
testXML2(config);
if(config->GetVarMap().count("config-json-file"))
}
if (config->GetVarMap().count("config-json-file"))
{
testJSON1(config);
if(config->GetVarMap().count("config-json-string"))
}
if (config->GetVarMap().count("config-json-string"))
{
testJSON2(config);
}
}
catch (std::exception& e)
{
@ -142,9 +139,3 @@ int main(int argc, char** argv)
}
return 0;
}

View File

@ -15,17 +15,16 @@
//////////////////////////////////////////////////////////////
int main(int argc, char** argv)
{
{
try
{
FairMQProgOptions config;
po::options_description format_desc("XML input");
format_desc.add_options()
("xml.config.node.root", po::value<std::string>()->default_value("fairMQOptions"), "xml root node ")
;
po::options_description io_file_opt_desc("I/O file Options");
io_file_opt_desc.add_options()
("input.file.name", po::value<std::string>(), "input file name")
@ -38,21 +37,20 @@ int main(int argc, char** argv)
config.AddToCmdLineOptions(format_desc,true);
config.AddToCmdLineOptions(io_file_opt_desc,true);
config.EnableCfgFile();// UseConfigFile (by default config file is not defined)
config.AddToCfgFileOptions(format_desc,false);//false because already added to visible
config.AddToCfgFileOptions(io_file_opt_desc,false);
// Parse command line and config file
if(config.ParseAll(argc,argv))
return 0;
// Set severity level (Default is 0=DEBUG)
int verbosity=config.GetValue<int>("verbosity");
FairMQLogger::Level lvl=static_cast<FairMQLogger::Level>(verbosity);
int severity = config.GetValue<int>("severity");
FairMQLogger::Level lvl = static_cast<FairMQLogger::Level>(severity);
SET_LOGGER_LEVEL(lvl);
// parse XML file
std::string filename;
std::string XMLrootNode;
@ -61,8 +59,6 @@ int main(int argc, char** argv)
XMLrootNode=config.GetValue<std::string>("xml.config.node.root");
std::string id=config.GetValue<std::string>("id");
config.UserParser<FairMQParser::XML>(filename,id,XMLrootNode);
}
catch (std::exception& e)
{
@ -71,9 +67,3 @@ int main(int argc, char** argv)
}
return 0;
}

View File

@ -6,6 +6,6 @@ VERBOSE="DEBUG"
JSONCONFIGFILE="@CMAKE_BINARY_DIR@/bin/config/ex1-sampler-sink.json"
########################## start DEVICE
DEVICE="runConfigExample --transport $TRANSPORT --verbosity $VERBOSE"
DEVICE="runConfigExample --transport $TRANSPORT --severity $VERBOSE"
DEVICE+=" --id sampler1 --mq-config $JSONCONFIGFILE"
@CMAKE_BINARY_DIR@/bin/$DEVICE

View File

@ -127,43 +127,43 @@ auto Control::InteractiveMode() -> void
switch (input)
{
case 'i':
LOG(INFO) << "[i] init device";
LOG(INFO) << "\n\n --> [i] init device\n";
ChangeDeviceState(DeviceStateTransition::InitDevice);
break;
case 'j':
LOG(INFO) << "[j] init task";
LOG(INFO) << "\n\n --> [j] init task\n";
ChangeDeviceState(DeviceStateTransition::InitTask);
break;
case 'p':
LOG(INFO) << "[p] pause";
LOG(INFO) << "\n\n --> [p] pause\n";
ChangeDeviceState(DeviceStateTransition::Pause);
break;
case 'r':
LOG(INFO) << "[r] run";
LOG(INFO) << "\n\n --> [r] run\n";
ChangeDeviceState(DeviceStateTransition::Run);
break;
case 's':
LOG(INFO) << "[s] stop";
LOG(INFO) << "\n\n --> [s] stop\n";
ChangeDeviceState(DeviceStateTransition::Stop);
break;
case 't':
LOG(INFO) << "[t] reset task";
LOG(INFO) << "\n\n --> [t] reset task\n";
ChangeDeviceState(DeviceStateTransition::ResetTask);
break;
case 'd':
LOG(INFO) << "[d] reset device";
LOG(INFO) << "\n\n --> [d] reset device\n";
ChangeDeviceState(DeviceStateTransition::ResetDevice);
break;
case 'h':
LOG(INFO) << "[h] help";
LOG(INFO) << "\n\n --> [h] help\n";
PrintInteractiveHelp();
break;
// case 'x':
// LOG(INFO) << "[x] ERROR";
// LOG(INFO) << "\n\n --> [x] ERROR\n";
// ChangeDeviceState(DeviceStateTransition::ERROR_FOUND);
// break;
case 'q':
LOG(INFO) << "[q] end";
LOG(INFO) << "\n\n --> [q] end\n";
keepRunning = false;
break;
default:
@ -197,8 +197,8 @@ auto Control::InteractiveMode() -> void
auto Control::PrintInteractiveHelp() -> void
{
LOG(INFO) << "Use keys to control the state machine:";
LOG(INFO) << "[h] help, [p] pause, [r] run, [s] stop, [t] reset task, [d] reset device, [q] end, [j] init task, [i] init device";
LOG(INFO) << "Use keys to control the state machine:\n\n"
<< "[h] help, [p] pause, [r] run, [s] stop, [t] reset task, [d] reset device, [q] end, [j] init task, [i] init device\n";
}
auto Control::WaitForNextState() -> DeviceState
@ -219,7 +219,7 @@ auto Control::StaticMode() -> void
try
{
RunStartupSequence();
{
// Wait for next state, which is DeviceState::Ready,
// or for device termination request

View File

@ -65,6 +65,7 @@ SAMPLER+=" --id bsampler1"
#SAMPLER+=" --io-threads 2"
#SAMPLER+=" --control static"
SAMPLER+=" --transport $transport"
SAMPLER+=" --severity debug"
SAMPLER+=" --msg-size $msgSize"
SAMPLER+=" --same-msg $sameMsg"
# SAMPLER+=" --msg-rate 1000"
@ -80,6 +81,7 @@ SINK+=" --id sink1"
#SINK+=" --io-threads 2"
#SINK+=" --control static"
SINK+=" --transport $transport"
SINK+=" --severity debug"
SINK+=" --max-iterations $maxIterations"
SINK+=" --mq-config @CMAKE_BINARY_DIR@/bin/config/benchmark.json"
xterm -geometry 90x23+550+0 -hold -e $affinitySink @CMAKE_BINARY_DIR@/bin/$SINK &

View File

@ -14,7 +14,7 @@ echo "Usage: startShmPrototype [message size=1000000]"
SAMPLER="shm-prototype-sampler"
SAMPLER+=" --id sampler1"
SAMPLER+=" --transport $transport"
# SAMPLER+=" --verbosity TRACE"
# SAMPLER+=" --severity TRACE"
SAMPLER+=" --msg-size $msgSize"
# SAMPLER+=" --msg-rate 1000"
SAMPLER+=" --mq-config @CMAKE_BINARY_DIR@/bin/config/shm-prototype.json"
@ -23,27 +23,27 @@ xterm -geometry 80x32+0+0 -hold -e @CMAKE_BINARY_DIR@/bin/prototype/shmem/$SAMPL
SINK1="shm-prototype-sink"
SINK1+=" --id sink1"
SINK1+=" --transport $transport"
# SINK1+=" --verbose TRACE"
# SINK1+=" --severity TRACE"
SINK1+=" --mq-config @CMAKE_BINARY_DIR@/bin/config/shm-prototype.json"
xterm -geometry 80x32+500+0 -hold -e @CMAKE_BINARY_DIR@/bin/prototype/shmem/$SINK1 &
# SINK2="shm-prototype-sink"
# SINK2+=" --id sink2"
# SINK2+=" --transport $transport"
# # SINK2+=" --verbose TRACE"
# # SINK2+=" --severity TRACE"
# SINK2+=" --mq-config @CMAKE_BINARY_DIR@/bin/config/shm-prototype.json"
# xterm -geometry 80x32+500+500 -hold -e @CMAKE_BINARY_DIR@/bin/prototype/shmem/$SINK2 &
# SINK3="shm-prototype-sink"
# SINK3+=" --id sink3"
# SINK3+=" --transport $transport"
# # SINK3+=" --verbose TRACE"
# # SINK3+=" --severity TRACE"
# SINK3+=" --mq-config @CMAKE_BINARY_DIR@/bin/config/shm-prototype.json"
# xterm -geometry 80x32+1000+0 -hold -e @CMAKE_BINARY_DIR@/bin/prototype/shmem/$SINK3 &
# SINK4="shm-prototype-sink"
# SINK4+=" --id sink4"
# SINK4+=" --transport $transport"
# # SINK4+=" --verbose TRACE"
# # SINK4+=" --severity TRACE"
# SINK4+=" --mq-config @CMAKE_BINARY_DIR@/bin/config/shm-prototype.json"
# xterm -geometry 80x32+1000+500 -hold -e @CMAKE_BINARY_DIR@/bin/prototype/shmem/$SINK4 &

View File

@ -27,7 +27,7 @@ auto RunPoller(string transport, int pollType) -> void
stringstream cmd;
cmd << runTestDevice
<< " --id pollout_"<< transport
<< " --control static --verbosity DEBUG --log-color false"
<< " --control static --severity DEBUG --color false"
<< " --session " << session << " --mq-config \"" << mqConfig << "\"";
pollout = execute(cmd.str(), "[POLLOUT]");
});
@ -37,7 +37,7 @@ auto RunPoller(string transport, int pollType) -> void
stringstream cmd;
cmd << runTestDevice
<< " --id pollin_" << transport
<< " --control static --verbosity DEBUG --log-color false"
<< " --control static --severity DEBUG --color false"
<< " --session " << session << " --mq-config \"" << mqConfig << "\" --poll-type " << pollType;
pollin = execute(cmd.str(), "[POLLIN]");
});

View File

@ -25,24 +25,24 @@ auto RunPubSub(string transport) -> void
auto pub = execute_result{"", 0};
thread pub_thread([&]() {
stringstream cmd;
cmd << runTestDevice << " --id pub_" << transport << " --control static --verbosity DEBUG "
<< "--session " << session << " --log-color false --mq-config \"" << mqConfig << "\"";
cmd << runTestDevice << " --id pub_" << transport << " --control static --severity DEBUG "
<< "--session " << session << " --color false --mq-config \"" << mqConfig << "\"";
pub = execute(cmd.str(), "[PUB]");
});
auto sub1 = execute_result{"", 0};
thread sub1_thread([&]() {
stringstream cmd;
cmd << runTestDevice << " --id sub_1" << transport << " --control static --verbosity DEBUG "
<< "--session " << session << " --log-color false --mq-config \"" << mqConfig << "\"";
cmd << runTestDevice << " --id sub_1" << transport << " --control static --severity DEBUG "
<< "--session " << session << " --color false --mq-config \"" << mqConfig << "\"";
sub1 = execute(cmd.str(), "[SUB1]");
});
auto sub2 = execute_result{"", 0};
thread sub2_thread([&]() {
stringstream cmd;
cmd << runTestDevice << " --id sub_2" << transport << " --control static --verbosity DEBUG "
<< "--session " << session << " --log-color false --mq-config \"" << mqConfig << "\"";
cmd << runTestDevice << " --id sub_2" << transport << " --control static --severity DEBUG "
<< "--session " << session << " --color false --mq-config \"" << mqConfig << "\"";
sub2 = execute(cmd.str(), "[SUB2]");
});

View File

@ -25,16 +25,16 @@ auto RunPushPull(string transport) -> void
auto push = execute_result{"", 100};
thread push_thread([&]() {
stringstream cmd;
cmd << runTestDevice << " --id push_" << transport << " --control static --verbosity DEBUG "
<< "--session " << session << " --log-color false --mq-config \"" << mqConfig << "\"";
cmd << runTestDevice << " --id push_" << transport << " --control static --severity DEBUG "
<< "--session " << session << " --color false --mq-config \"" << mqConfig << "\"";
push = execute(cmd.str(), "[PUSH]");
});
auto pull = execute_result{"", 100};
thread pull_thread([&]() {
stringstream cmd;
cmd << runTestDevice << " --id pull_" << transport << " --control static --verbosity DEBUG "
<< "--session " << session << " --log-color false --mq-config \"" << mqConfig << "\"";
cmd << runTestDevice << " --id pull_" << transport << " --control static --severity DEBUG "
<< "--session " << session << " --color false --mq-config \"" << mqConfig << "\"";
pull = execute(cmd.str(), "[PULL]");
});

View File

@ -25,24 +25,24 @@ auto RunReqRep(string transport) -> void
auto rep = execute_result{ "", 0 };
thread rep_thread([&]() {
stringstream cmd;
cmd << runTestDevice << " --id rep_" << transport << " --control static --verbosity DEBUG "
<< "--session " << session << " --log-color false --mq-config \"" << mqConfig << "\"";
cmd << runTestDevice << " --id rep_" << transport << " --control static --severity DEBUG "
<< "--session " << session << " --color false --mq-config \"" << mqConfig << "\"";
rep = execute(cmd.str(), "[REP]");
});
auto req1 = execute_result{ "", 0 };
thread req1_thread([&]() {
stringstream cmd;
cmd << runTestDevice << " --id req_1" << transport << " --control static --verbosity DEBUG "
<< "--session " << session << " --log-color false --mq-config \"" << mqConfig << "\"";
cmd << runTestDevice << " --id req_1" << transport << " --control static --severity DEBUG "
<< "--session " << session << " --color false --mq-config \"" << mqConfig << "\"";
req1 = execute(cmd.str(), "[REQ1]");
});
auto req2 = execute_result{ "", 0 };
thread req2_thread([&]() {
stringstream cmd;
cmd << runTestDevice << " --id req_2" << transport << " --control static --verbosity DEBUG "
<< "--session " << session << " --log-color false --mq-config \"" << mqConfig << "\"";
cmd << runTestDevice << " --id req_2" << transport << " --control static --severity DEBUG "
<< "--session " << session << " --color false --mq-config \"" << mqConfig << "\"";
req2 = execute(cmd.str(), "[REQ2]");
});

View File

@ -21,8 +21,8 @@ auto RunTransferTimeout(string transport) -> void
{
size_t session{fair::mq::tools::UuidHash()};
stringstream cmd;
cmd << runTestDevice << " --id transfer_timeout_" << transport << " --control static --verbosity DEBUG "
<< "--session " << session << " --log-color false --mq-config \"" << mqConfig << "\"";
cmd << runTestDevice << " --id transfer_timeout_" << transport << " --control static --severity DEBUG "
<< "--session " << session << " --color false --mq-config \"" << mqConfig << "\"";
auto res = execute(cmd.str());
cerr << res.error_out;

View File

@ -40,7 +40,7 @@ auto execute(string cmd, string log_prefix) -> execute_result
out << log_prefix << cmd << endl;
// Execute command and capture stderr, add log_prefix line by line
redi::ipstream in(cmd, redi::pstreams::pstderr);
redi::ipstream in(cmd, redi::pstreams::pstdout);
auto line = string{};
while (getline(in, line))
{