From d1bba619391d410c07ed57b1b0b7f6be1778d2d4 Mon Sep 17 00:00:00 2001 From: winckler Date: Thu, 2 Jul 2015 12:13:56 +0200 Subject: [PATCH] - FairMQ options: a) move the XML parser into the FairMQ/options/FairMQParser.h b) add a routine in FairMQProgOption to check whether the necessary XML or JSON input files are there, and send an error message if not there MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Policy based devices: a) rename GenericSampler to base_GenericSampler and use an alias template named GenericSampler b) in base_GenericSampler, rename template parameter to simple variables and use typedef for clarity c) introduce an anonymous function container in the base_GenericSampler host class with a register task template member function and an Executetasks() d) add two new template parameters in base_GenericSampler for the anonymous function container map. parameter is K for the key type (default=int) and L for the value type (default=std::function) - Tutorial7: a) use FairMQProgOption to configure devices in tutorial7 b) introduce several template functions helper in tutorial7 to reduce code redundancy c) show examples in tutorial7 of task registration with callback and lambda expression for the sampler devices d) separate the executable build of the tutorial7 data generator to remove the Roofit banner when executing the MQdevices --- fairmq/CMakeLists.txt | 2 +- fairmq/devices/GenericSampler.h | 159 +++++++++++--- fairmq/devices/GenericSampler.tpl | 206 ++++++++++-------- fairmq/options/FairMQParser.cxx | 20 +- fairmq/options/FairMQParser.h | 6 + fairmq/options/FairMQProgOptions.cxx | 122 +++++++---- fairmq/options/FairMQProgOptions.h | 2 + fairmq/options/FairProgOptions.cxx | 10 +- fairmq/options/FairProgOptions.h | 9 +- .../lib/FairMQParserExample.cxx | 23 -- .../ProgOptionTest/lib/FairMQParserExample.h | 10 +- fairmq/tools/FairMQTools.h | 80 +++++++ 12 files changed, 440 insertions(+), 209 deletions(-) diff --git a/fairmq/CMakeLists.txt b/fairmq/CMakeLists.txt index 0b80e6af..04b7d8ed 100644 --- a/fairmq/CMakeLists.txt +++ b/fairmq/CMakeLists.txt @@ -155,7 +155,7 @@ install(FILES ${FAIRMQHEADERS} DESTINATION include) set(DEPENDENCIES ${DEPENDENCIES} - boost_thread boost_timer boost_system boost_program_options boost_random boost_chrono boost_exception + boost_thread boost_timer boost_system boost_filesystem boost_program_options boost_random boost_chrono boost_exception ) set(LIBRARY_NAME FairMQ) diff --git a/fairmq/devices/GenericSampler.h b/fairmq/devices/GenericSampler.h index 89eeda76..7b04ab47 100644 --- a/fairmq/devices/GenericSampler.h +++ b/fairmq/devices/GenericSampler.h @@ -17,6 +17,7 @@ #include #include +#include #include #include @@ -25,6 +26,7 @@ #include "FairMQDevice.h" #include "FairMQLogger.h" +#include "FairMQTools.h" /* GENERIC SAMPLER (data source) MQ-DEVICE */ /********************************************************************* @@ -33,31 +35,55 @@ * Function to define in (parent) policy classes : * * -------- INPUT POLICY (SAMPLER POLICY) -------- - * SamplerPolicy::InitSampler() - * int64_t SamplerPolicy::GetNumberOfEvent() - * CONTAINER_TYPE SamplerPolicy::GetDataBranch(int64_t eventNr) - * SamplerPolicy::SetFileProperties(Args&... args) + * source_type::InitSampler() // must be there to compile + * int64_t source_type::GetNumberOfEvent() // must be there to compile + * source_type::SetIndex(int64_t eventIdx) // must be there to compile + * CONTAINER_TYPE source_type::GetOutData() // must be there to compile + * source_type::SetFileProperties(Args&... args) // must be there to compile + * source_type::ExecuteTasks() // must be there to compile + * + * void BindSendPart(std::function callback) // enabled if exists + * void BindGetSocketNumber(std::function callback) // enabled if exists + * void BindGetCurrentIndex(std::function callback) // enabled if exists * * -------- OUTPUT POLICY -------- - * OutputPolicy::SerializeMsg(CONTAINER_TYPE) - * OutputPolicy::SetMessage(FairMQMessage* msg) + * serialization_type::SerializeMsg(CONTAINER_TYPE) // must be there to compile + * serialization_type::SetMessage(FairMQMessage* msg) // must be there to compile * **********************************************************************/ -template -class GenericSampler : public FairMQDevice, public SamplerPolicy, public OutputPolicy +//template +//class base_GenericSampler : public FairMQDevice, public source_type, public serialization_type +template +class base_GenericSampler : public FairMQDevice, public T, public U { + typedef T source_type; + typedef U serialization_type; + typedef K key_type; + typedef L task_type; + typedef base_GenericSampler self_type; + public: enum { - InputFile = FairMQDevice::Last, - Branch, - ParFile, - EventRate + EventRate = FairMQDevice::Last, + OutChannelName }; - GenericSampler(); - virtual ~GenericSampler(); + base_GenericSampler(); + virtual ~base_GenericSampler(); + /* + struct trait : source_type::trait, serialization_type::trait + { + //static const SerializationTag serialization = serialization_type::trait::serialization; + //static const FileTag + static const DeviceTag device = kSampler; + typedef base_GenericSampler self_type; + typedef source_type source_type; + typedef serialization_type serialization_type; + }; + + */ virtual void SetTransport(FairMQTransportFactory* factory); void ResetEventCounter(); @@ -65,36 +91,103 @@ class GenericSampler : public FairMQDevice, public SamplerPolicy, public OutputP template void SetFileProperties(Args&... args) { - SamplerPolicy::SetFileProperties(args...); + source_type::SetFileProperties(args...); } - virtual void SetProperty(const int key, const std::string& value); - virtual std::string GetProperty(const int key, const std::string& default_ = ""); virtual void SetProperty(const int key, const int value); virtual int GetProperty(const int key, const int default_ = 0); - - /** - * Sends the currently available output of the Sampler Task as part of a multipart message - * and reinitializes the message to be filled with the next part. - * This method can be given as a callback to the SamplerTask. - * The final message part must be sent with normal Send method. - */ - // temporary disabled - //void SendPart(); - - void SetContinuous(bool flag); - + virtual void SetProperty(const int key, const std::string& value); + virtual std::string GetProperty(const int key, const std::string& default_ = ""); + + void SendPart(int socketIdx); + int GetSocketNumber() const; + int GetCurrentIndex() const; + void SetContinuous(bool flag); + + + /// /////////////////////////////////////////////////////////////////////////////////////// + /* + register the tasks you want to process and, which will be + called by ExecuteTasks() member function. The registration is done by filling + a std::map where key_type is int and task_type + is std::function by default (when using GenericSampler alias template). + The template parameter must take a pointer to this class or derived class as first argument, + and a reference to a std::map as second argument. + It is convenient to use a lambda expression in the place of the template argument. + For example if we want to register the simple function, + //< + void myfunction() {std::cout << "hello World" << std::endl;} + //> + ,and the MultiPartTask() template function member of this class , then + we can do in the main function as follow : + + sampler.RegisterTask( + [&](TSampler* s, std::map >& task_list) + { + task_list[0]=std::bind(myfunction); + task_list[1]=std::bind(&U::template MultiPartTask<5>, s); + }); + + To communicate with the Host derived class via callback, three methods from the host class are callable (only + after binding these methods in the GenericSampler::InitTask() ) + + */ + template + void RegisterTask(RegistrationManager manage) + { + manage(this,fTaskList); + LOG(DEBUG)<<"Current Number of registered tasks = "< fTaskList; // to handle Task list + + + // automatically enable or disable the call of policy function members for binding of host functions. + // this template functions use SFINAE to detect the existence of the policy function signature. + template = 0 > + void BindingSendPart(){} + template = 0 > + void BindingSendPart() + { + source_type::BindSendPart(std::bind(&base_GenericSampler::SendPart,this,std::placeholders::_1) ); + } + + template = 0 > + void BindingGetSocketNumber(){} + template = 0 > + void BindingGetSocketNumber() + { + source_type::BindGetSocketNumber(std::bind(&base_GenericSampler::GetSocketNumber,this) ); + } + + template = 0 > + void BindingGetCurrentIndex(){} + template = 0 > + void BindingGetCurrentIndex() + { + source_type::BindGetCurrentIndex(std::bind(&base_GenericSampler::GetCurrentIndex,this) ); + } }; #include "GenericSampler.tpl" diff --git a/fairmq/devices/GenericSampler.tpl b/fairmq/devices/GenericSampler.tpl index 42790c51..ba61f5c1 100644 --- a/fairmq/devices/GenericSampler.tpl +++ b/fairmq/devices/GenericSampler.tpl @@ -5,72 +5,82 @@ * Created on November 24, 2014, 3:59 PM */ -template -GenericSampler::GenericSampler() - : fNumEvents(0) +template +base_GenericSampler::base_GenericSampler() + : fOutChanName("data-out") + , fNumEvents(0) + , fCurrentIdx(0) , fEventRate(1) , fEventCounter(0) , fContinuous(false) - , fInputFile() - , fParFile() - , fBranch() { } -template -GenericSampler::~GenericSampler() +template +base_GenericSampler::~base_GenericSampler() { } -template -void GenericSampler::SetTransport(FairMQTransportFactory* factory) +template +void base_GenericSampler::SetTransport(FairMQTransportFactory* factory) { FairMQDevice::SetTransport(factory); - // OutputPolicy::SetTransport(factory); } -template -void GenericSampler::InitTask() +template +void base_GenericSampler::InitTask() { - SamplerPolicy::InitSampler(); - fNumEvents = SamplerPolicy::GetNumberOfEvent(); + BindingSendPart(); + BindingGetSocketNumber(); + BindingGetCurrentIndex(); + + source_type::InitSampler(); + fNumEvents = source_type::GetNumberOfEvent(); } -template -void GenericSampler::Run() + + + +template +void base_GenericSampler::Run() { // boost::thread resetEventCounter(boost::bind(&GenericSampler::ResetEventCounter, this)); int sentMsgs = 0; - + boost::timer::auto_cpu_timer timer; LOG(INFO) << "Number of events to process: " << fNumEvents; - + do { - for (int64_t eventNr = 0; eventNr < fNumEvents; ++eventNr) + for (fCurrentIdx = 0; fCurrentIdx < fNumEvents; fCurrentIdx++) { - //fSamplerTask->SetEventIndex(eventNr); - FairMQMessage* msg = fTransportFactory->CreateMessage(); - OutputPolicy::SetMessage(msg); - fChannels["data-out"].at(0).Send(OutputPolicy::SerializeMsg(SamplerPolicy::GetDataBranch(eventNr))); - ++sentMsgs; - - if (msg) + for(auto& p : fChannels[fOutChanName]) { - msg->CloseMessage(); - } + FairMQMessage* msg = fTransportFactory->CreateMessage(); + serialization_type::SetMessage(msg); + source_type::SetIndex(fCurrentIdx); + ExecuteTasks(); + p.Send(serialization_type::SerializeMsg(source_type::GetOutData())); + if (msg) + msg->CloseMessage(); + sentMsgs++; - // Optional event rate limiting - // --fEventCounter; - // while (fEventCounter == 0) { - // boost::this_thread::sleep(boost::posix_time::milliseconds(1)); - // } - - if (GetCurrentState() != RUNNING) - { - break; + if(fChannels[fOutChanName].size()>1) + fCurrentIdx++; + + // Optional event rate limiting + // --fEventCounter; + // while (fEventCounter == 0) { + // boost::this_thread::sleep(boost::posix_time::milliseconds(1)); + // } + + if (GetCurrentState() != RUNNING) + break; } + // if more than one socket, remove the last incrementation + if(fChannels[fOutChanName].size()>1) + fCurrentIdx--; } } while ( GetCurrentState() == RUNNING && fContinuous ); @@ -80,23 +90,43 @@ void GenericSampler::Run() LOG(INFO) << "Sent " << sentMsgs << " messages!"; } -/* -template -void GenericSampler::SendPart() -{ - fChannels["data-out"].at(0).Send(OutputPolicy::GetMessage(), "snd-more"); - OutputPolicy::CloseMessage(); -} -*/ -template -void GenericSampler::SetContinuous(bool flag) +template +void base_GenericSampler::SendPart(int socketIdx) +{ + fCurrentIdx++; + if(fCurrentIdxCreateMessage(); + serialization_type::SetMessage(msg); + source_type::SetIndex(fCurrentIdx); + fChannels[fOutChanName].at(socketIdx).Send(serialization_type::SerializeMsg(source_type::GetOutData()), "snd-more"); + if (msg) + msg->CloseMessage(); + } +} + + +template +int base_GenericSampler::GetSocketNumber() const +{ + return fChannels.at(fOutChanName).size(); +} + +template +int base_GenericSampler::GetCurrentIndex() const +{ + return fCurrentIdx; +} + +template +void base_GenericSampler::SetContinuous(bool flag) { fContinuous = flag; } -template -void GenericSampler::ResetEventCounter() +template +void base_GenericSampler::ResetEventCounter() { while (GetCurrentState() == RUNNING) { @@ -114,44 +144,8 @@ void GenericSampler::ResetEventCounter() LOG(DEBUG) << ">>>>>>> stopping resetEventCounter <<<<<<<"; } -template -void GenericSampler::SetProperty(const int key, const std::string& value) -{ - switch (key) - { - case InputFile: - fInputFile = value; - break; - case ParFile: - fParFile = value; - break; - case Branch: - fBranch = value; - break; - default: - FairMQDevice::SetProperty(key, value); - break; - } -} - -template -std::string GenericSampler::GetProperty(const int key, const std::string& default_/*= ""*/) -{ - switch (key) - { - case InputFile: - return fInputFile; - case ParFile: - return fParFile; - case Branch: - return fBranch; - default: - return FairMQDevice::GetProperty(key, default_); - } -} - -template -void GenericSampler::SetProperty(const int key, const int value) +template +void base_GenericSampler::SetProperty(const int key, const int value) { switch (key) { @@ -164,8 +158,8 @@ void GenericSampler::SetProperty(const int key, cons } } -template -int GenericSampler::GetProperty(const int key, const int default_/*= 0*/) +template +int base_GenericSampler::GetProperty(const int key, const int default_/*= 0*/) { switch (key) { @@ -175,3 +169,35 @@ int GenericSampler::GetProperty(const int key, const return FairMQDevice::GetProperty(key, default_); } } + +template +void base_GenericSampler::SetProperty(const int key, const std::string& value) +{ + switch (key) + { + case OutChannelName: + fOutChanName = value; + break; + default: + FairMQDevice::SetProperty(key, value); + break; + } +} + +template +std::string base_GenericSampler::GetProperty(const int key, const std::string& default_) +{ + switch (key) + { + case OutChannelName: + return fOutChanName; + default: + return FairMQDevice::GetProperty(key, default_); + } +} + + + +template +using GenericSampler = base_GenericSampler >; +typedef std::map > SamplerTasksMap; diff --git a/fairmq/options/FairMQParser.cxx b/fairmq/options/FairMQParser.cxx index 329d8a5f..c56fd24a 100644 --- a/fairmq/options/FairMQParser.cxx +++ b/fairmq/options/FairMQParser.cxx @@ -14,7 +14,7 @@ #include "FairMQParser.h" #include "FairMQLogger.h" - +#include // WARNING : pragma commands to hide boost (1.54.0) warning // TODO : remove these pragma commands when boost will fix this issue in future release #pragma clang diagnostic push @@ -188,4 +188,22 @@ FairMQMap JSON::UserParser(std::stringstream& input, const std::string& deviceId return ptreeToMQMap(pt, deviceId, rootNode,"json"); } + +//////////////////////////////////////////////////////////////////////////// +FairMQMap XML::UserParser(const std::string& filename, const std::string& deviceId, const std::string& rootNode) +{ + boost::property_tree::ptree pt; + boost::property_tree::read_xml(filename, pt); + return ptreeToMQMap(pt,deviceId,rootNode,"xml"); +} + +FairMQMap XML::UserParser(std::stringstream& input, const std::string& deviceId, const std::string& rootNode) +{ + boost::property_tree::ptree pt; + boost::property_tree::read_xml(input, pt); + return ptreeToMQMap(pt,deviceId,rootNode,"xml"); +} + + + } // end FairMQParser namespace \ No newline at end of file diff --git a/fairmq/options/FairMQParser.h b/fairmq/options/FairMQParser.h index 71cda2a5..66460507 100644 --- a/fairmq/options/FairMQParser.h +++ b/fairmq/options/FairMQParser.h @@ -32,6 +32,12 @@ struct JSON FairMQMap UserParser(std::stringstream& input, const std::string& deviceId, const std::string& rootNode = "fairMQOptions"); }; +struct XML +{ + FairMQMap UserParser(const std::string& filename, const std::string& deviceId, const std::string& root_node="fairMQOptions"); + FairMQMap UserParser(std::stringstream& input, const std::string& deviceId, const std::string& rootNode="fairMQOptions"); +}; + } // FairMQParser namespace #endif /* FAIRMQPARSER_H */ diff --git a/fairmq/options/FairMQProgOptions.cxx b/fairmq/options/FairMQProgOptions.cxx index 98b39ce4..e38d325d 100644 --- a/fairmq/options/FairMQProgOptions.cxx +++ b/fairmq/options/FairMQProgOptions.cxx @@ -19,10 +19,11 @@ FairMQProgOptions::FairMQProgOptions() : FairProgOptions() , fMQParserOptions("MQ-Device parser options") + , fMQOptionsInCmd("MQ-Device options") + , fMQOptionsInCfg("MQ-Device options") , fMQtree() , fFairMQmap() { - InitOptionDescription(); } FairMQProgOptions::~FairMQProgOptions() @@ -30,53 +31,62 @@ FairMQProgOptions::~FairMQProgOptions() } int FairMQProgOptions::ParseAll(const int argc, char** argv, bool AllowUnregistered) -{ - // before parsing, define cmdline and optionally cfgfile description, - // and also what is visible for the user - AddToCmdLineOptions(fGenericDesc); - AddToCmdLineOptions(fMQParserOptions); - - // if config file option enabled then id non required in cmdline but required in configfile - // else required in cmdline - if (fUseConfigFile) - { - fCmdline_options.add_options() - ("id", po::value< std::string >(), "Device ID"); - fConfig_file_options.add_options() - ("id", po::value< std::string >()->required(), "Device ID"); - } - else - { - fCmdline_options.add_options() - ("id", po::value< std::string >()->required(), "Device ID"); - } - - fVisible_options.add_options() - ("id", po::value< std::string >()->required(), "Device ID (required value)"); - - // parse command line +{ + // init description + InitOptionDescription(); + // parse command line options if (ParseCmdLine(argc,argv,fCmdline_options,fvarmap,AllowUnregistered)) { return 1; } - // if txt/INI configuration file enabled then parse it - if (fUseConfigFile && !fConfigFile.empty()) + // if txt/INI configuration file enabled then parse it as well + if (fUseConfigFile) { - AddToCfgFileOptions(fMQParserOptions,false); - - if (ParseCfgFile(fConfigFile, fConfig_file_options, fvarmap, AllowUnregistered)) + // check if file exist + if (fs::exists(fConfigFile)) { + if (ParseCfgFile(fConfigFile.string(), fConfig_file_options, fvarmap, AllowUnregistered)) + return 1; + } + else + { + LOG(ERROR)<<"config file '"<< fConfigFile <<"' not found"; return 1; } } - + // set log level before printing (default is 0 = DEBUG level) int verbose=GetValue("verbose"); SET_LOGGER_LEVEL(verbose); PrintOptions(); - + + // check if one of required MQ config option is there + auto parserOption_shptr = fMQParserOptions.options(); + bool option_exists=false; + std::vector MQParserKeys; + for(const auto& p : parserOption_shptr) + { + MQParserKeys.push_back( p->canonical_display_name() ); + if( fvarmap.count( p->canonical_display_name() ) ) + { + option_exists=true; + break; + } + } + + if(!option_exists) + { + LOG(ERROR)<<"Required option to configure the MQ device is not there."; + LOG(ERROR)<<"Please provide the value of one of the following key:"; + for(const auto& p : MQParserKeys) + { + LOG(ERROR)< >()->multitoken(), "XML input as command line string.") - ("config-xml-file", po::value< std::string >(), "XML input as file.") - ("config-json-string", po::value< std::vector >()->multitoken(), "JSON input as command line string.") - ("config-json-file", po::value< std::string >(), "JSON input as file.") + // Id required in command line if config txt file not enabled + if (fUseConfigFile) + { + fMQOptionsInCmd.add_options() + ("id", po::value< std::string >(), "Device ID (required argument)") + ("io-threads", po::value()->default_value(1), "io threads number"); - // ("ini.config.string", po::value< std::vector >()->multitoken(), "INI input as command line string.") - // ("ini.config.file", po::value< std::string >(), "INI input as file.") - ; + fMQOptionsInCfg.add_options() + ("id", po::value< std::string >()->required(), "Device ID (required argument)") + ("io-threads", po::value()->default_value(1), "io threads number"); + } + else + { + fMQOptionsInCmd.add_options() + ("id", po::value< std::string >()->required(), "Device ID (required argument)") + ("io-threads", po::value()->default_value(1), "io threads number"); + } + + fMQParserOptions.add_options() + ("config-xml-string", po::value< std::vector >()->multitoken(), "XML input as command line string.") + ("config-xml-file", po::value< std::string >(), "XML input as file.") + ("config-json-string", po::value< std::vector >()->multitoken(), "JSON input as command line string.") + ("config-json-file", po::value< std::string >(), "JSON input as file."); + + + AddToCmdLineOptions(fGenericDesc); + AddToCmdLineOptions(fMQOptionsInCmd); + AddToCmdLineOptions(fMQParserOptions); + + if (fUseConfigFile) + { + AddToCfgFileOptions(fMQOptionsInCfg,false); + AddToCfgFileOptions(fMQParserOptions,false); + } + } \ No newline at end of file diff --git a/fairmq/options/FairMQProgOptions.h b/fairmq/options/FairMQProgOptions.h index 970dbe2d..8ac2f07c 100644 --- a/fairmq/options/FairMQProgOptions.h +++ b/fairmq/options/FairMQProgOptions.h @@ -74,6 +74,8 @@ public: protected: po::options_description fMQParserOptions; + po::options_description fMQOptionsInCfg; + po::options_description fMQOptionsInCmd; pt::ptree fMQtree; FairMQMap fFairMQmap; diff --git a/fairmq/options/FairProgOptions.cxx b/fairmq/options/FairProgOptions.cxx index 707a1630..38d76231 100644 --- a/fairmq/options/FairProgOptions.cxx +++ b/fairmq/options/FairProgOptions.cxx @@ -64,6 +64,10 @@ int FairProgOptions::AddToCmdLineOptions(const po::options_description& optdesc, 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(); + fConfig_file_options.add(optdesc); if(visible) fVisible_options.add(optdesc); @@ -82,8 +86,9 @@ void FairProgOptions::UseConfigFile(const std::string& filename) fUseConfigFile = true; if (filename.empty()) { - fCmdline_options.add_options() - ("config,c", po::value(&fConfigFile)->required(), "Path to configuration file"); + fConfigDesc.add_options() + ("config,c", po::value(&fConfigFile)->required(), "Path to configuration file (required argument)"); + AddToCmdLineOptions(fConfigDesc); } else { @@ -464,6 +469,7 @@ FairProgOptions::VarValInfo_t FairProgOptions::Get_variable_value_info(const po: if(auto q = boost::any_cast(&value)) { std::string val_str = (*q).string(); + //std::string val_str = (*q).filename().generic_string(); return std::make_tuple(val_str,std::string(" [Type=boost::filesystem::path]"),defaulted_val,empty_val); } diff --git a/fairmq/options/FairProgOptions.h b/fairmq/options/FairProgOptions.h index 7ed7438b..cca7cda3 100644 --- a/fairmq/options/FairProgOptions.h +++ b/fairmq/options/FairProgOptions.h @@ -62,6 +62,7 @@ std::ostream& operator<<(std::ostream& os, const std::vector& v) } namespace po = boost::program_options; +namespace fs = boost::filesystem; class FairProgOptions { @@ -87,12 +88,6 @@ public: { val = fvarmap[key].as(); } - else - { - LOG(ERROR) << "Key '"<< key <<"' not found in boost variable map"; - LOG(INFO) << "Command line / txt config file options are the following : "; - this->PrintHelp(); - } } catch(std::exception& e) { @@ -144,7 +139,7 @@ protected: int fVerboseLvl; bool fUseConfigFile; - std::string fConfigFile; + boost::filesystem::path fConfigFile; virtual int NotifySwitchOption(); // UpadateVarMap() and replace() --> helper functions to modify the value of variable map after calling po::store diff --git a/fairmq/options/ProgOptionTest/lib/FairMQParserExample.cxx b/fairmq/options/ProgOptionTest/lib/FairMQParserExample.cxx index 3fdca457..4df42dc1 100644 --- a/fairmq/options/ProgOptionTest/lib/FairMQParserExample.cxx +++ b/fairmq/options/ProgOptionTest/lib/FairMQParserExample.cxx @@ -13,29 +13,6 @@ namespace FairMQParser { - - //////////////////////////////////////////////////////////////////////////// - //----------- filename version - FairMQMap XML::UserParser(const std::string& filename, const std::string& device_id, const std::string& root_node) - { - boost::property_tree::ptree pt; - boost::property_tree::read_xml(filename, pt); - return ptreeToMQMap(pt,device_id,root_node,"xml"); - } - - - - //----------- stringstream version - FairMQMap XML::UserParser(std::stringstream& input_ss, const std::string& device_id, const std::string& root_node) - { - boost::property_tree::ptree pt; - boost::property_tree::read_xml(input_ss, pt); - return ptreeToMQMap(pt,device_id,root_node,"xml"); - } - - - - // other xml examples //////////////////////////////////////////////////////////////////////////// boost::property_tree::ptree MQXML2::UserParser(const std::string& filename) diff --git a/fairmq/options/ProgOptionTest/lib/FairMQParserExample.h b/fairmq/options/ProgOptionTest/lib/FairMQParserExample.h index cefeb281..be20ab06 100644 --- a/fairmq/options/ProgOptionTest/lib/FairMQParserExample.h +++ b/fairmq/options/ProgOptionTest/lib/FairMQParserExample.h @@ -27,15 +27,7 @@ namespace FairMQParser //////////////////////////////////////////////////////////////////////////// /////////////////////////////////// XML //////////////////////////////////// //////////////////////////////////////////////////////////////////////////// - - // xml example 1 - //////////////////////////////////////////////////////////////////////////// - struct XML - { - FairMQMap UserParser(const std::string& filename, const std::string& device_id, const std::string& root_node="fairMQOptions"); - FairMQMap UserParser(std::stringstream& input_ss, const std::string& device_id, const std::string& root_node="fairMQOptions"); - }; - + // xml example 2 //////////////////////////////////////////////////////////////////////////// struct MQXML2 diff --git a/fairmq/tools/FairMQTools.h b/fairmq/tools/FairMQTools.h index d649731b..b8138aa5 100644 --- a/fairmq/tools/FairMQTools.h +++ b/fairmq/tools/FairMQTools.h @@ -14,6 +14,7 @@ #include #include #include +#include using namespace std; @@ -58,6 +59,85 @@ int getHostIPs(map& addressMap) return 0; } + + +// below are SFINAE template functions to check for function member signatures of class +namespace details +{ + /////////////////////////////////////////////////////////////////////////// + // test, at compile time, whether T has BindSendPart member function with returned type R and argument ...Args type + template + struct has_BindSendPart:std::false_type{}; + + template + struct has_BindSendPart + ().BindSendPart(std::declval()...)), R >::value + || std::is_same::value + >::type + >:std::true_type{}; + + /////////////////////////////////////////////////////////////////////////// + // test, at compile time, whether T has BindGetSocketNumber member function with returned type R and argument ...Args type + template + struct has_BindGetSocketNumber:std::false_type{}; + + template + struct has_BindGetSocketNumber + ().BindGetSocketNumber(std::declval()...)), R >::value + || std::is_same::value + >::type + >:std::true_type{}; + + /////////////////////////////////////////////////////////////////////////// + // test, at compile time, whether T has BindGetCurrentIndex member function with returned type R and argument ...Args type + template + struct has_BindGetCurrentIndex:std::false_type{}; + + template + struct has_BindGetCurrentIndex + ().BindGetCurrentIndex(std::declval()...)), R >::value + || std::is_same::value + >::type + >:std::true_type{}; + +}// end namespace details + +/////////////////////////////////////////////////////////////////////////// +// Alias template of the above structs +template +using has_BindSendPart = std::integral_constant::value>; + +template +using has_BindGetSocketNumber = std::integral_constant::value>; + +template +using has_BindGetCurrentIndex = std::integral_constant::value>; + +// enable_if Alias template +template +using enable_if_has_BindSendPart = typename std::enable_if::value,int>::type; +template +using enable_if_hasNot_BindSendPart = typename std::enable_if::value,int>::type; + +template +using enable_if_has_BindGetSocketNumber = typename std::enable_if::value,int>::type; +template +using enable_if_hasNot_BindGetSocketNumber = typename std::enable_if::value,int>::type; + +template +using enable_if_has_BindGetCurrentIndex = typename std::enable_if::value,int>::type; +template +using enable_if_hasNot_BindGetCurrentIndex = typename std::enable_if::value,int>::type; + } // namespace tools } // namespace FairMQ