diff --git a/fairmq/CMakeLists.txt b/fairmq/CMakeLists.txt index 9bc6b1f0..cd460e6d 100644 --- a/fairmq/CMakeLists.txt +++ b/fairmq/CMakeLists.txt @@ -94,6 +94,7 @@ Set(SRCS "options/FairProgOptions.cxx" "options/FairMQProgOptions.cxx" "options/FairMQParser.cxx" + "options/FairMQSuboptParser.cxx" ) If(NANOMSG_FOUND) diff --git a/fairmq/options/FairMQSuboptParser.cxx b/fairmq/options/FairMQSuboptParser.cxx new file mode 100644 index 00000000..4f6f0521 --- /dev/null +++ b/fairmq/options/FairMQSuboptParser.cxx @@ -0,0 +1,70 @@ +/******************************************************************************** + * Copyright (C) 2017 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH * + * * + * This software is distributed under the terms of the * + * GNU Lesser General Public License version 3 (LGPL) version 3, * + * copied verbatim in the file "LICENSE" * + ********************************************************************************/ + +/// @file FairMQSuboptParser.cxx +/// @author Matthias.Richter@scieq.net +/// @since 2017-03-30 +/// @brief Parser implementation for key-value subopt format + +#include "FairMQSuboptParser.h" +#include +#include + +using boost::property_tree::ptree; + +namespace FairMQParser +{ + +constexpr const char* SUBOPT::channelOptionKeys[]; + +FairMQMap SUBOPT::UserParser(const po::variables_map& omap, const std::string& deviceId, const std::string& rootNode) +{ + std::string nodeKey = rootNode + ".device"; + ptree pt; + + pt.put(nodeKey + ".id", deviceId.c_str()); + nodeKey += ".channels"; + + // parsing of channel properties is the only implemented method right now + if (omap.count(OptionKeyChannelConfig) > 0) { + std::map channelProperties; + auto tokens = omap[OptionKeyChannelConfig].as>(); + for (auto token : tokens) { + std::map::iterator channelProperty = channelProperties.end(); + ptree socketProperty; + std::string channelName; + std::string argString(token); + char* subopts = &argString[0]; + char* value = nullptr; + while (subopts && *subopts != 0 && *subopts != ' ') { + char* saved = subopts; + int subopt=getsubopt(&subopts, (char**)channelOptionKeys, &value); + if (subopt == NAME) { + channelName = value; + channelProperties[channelName].put("name", channelName); + } else + if (subopt>=0 && value != nullptr) { + socketProperty.put(channelOptionKeys[subopt], value); + } + } + if (channelName != "") { + channelProperties[channelName].add_child("sockets.socket", socketProperty); + } else { + // TODO: what is the error policy here, should we abort? + LOG(ERROR) << "missing channel name in argument of option --channel-config"; + } + } + for (auto channelProperty : channelProperties) { + pt.add_child(nodeKey + ".channel", channelProperty.second); + } + } + + return ptreeToMQMap(pt, deviceId, rootNode); +} + +} // namespace FairMQMap diff --git a/fairmq/options/FairMQSuboptParser.h b/fairmq/options/FairMQSuboptParser.h new file mode 100644 index 00000000..d5463e53 --- /dev/null +++ b/fairmq/options/FairMQSuboptParser.h @@ -0,0 +1,71 @@ +/******************************************************************************** + * Copyright (C) 2017 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH * + * * + * This software is distributed under the terms of the * + * GNU Lesser General Public License version 3 (LGPL) version 3, * + * copied verbatim in the file "LICENSE" * + ********************************************************************************/ + +/// @file FairMQSuboptParser.h +/// @author Matthias.Richter@scieq.net +/// @since 2017-03-30 +/// @brief Parser implementation for key-value subopt format + +#include "FairMQParser.h" // for FairMQMap +#include +#include + +namespace po = boost::program_options; + +namespace FairMQParser +{ +/** + * A parser implementation for FairMQ channel properties. + * The parser handles a comma separated key=value list format by using the + * getsubopt function of the standard library. + * + * The option key '--channel-config' can be used with the list of key/value + * pairs like e.g. + *
+ * --channel-config name=output,type=push,method=bind
+ * 
+ * + * The FairMQ option parser defines a 'UserParser' function for different + * formats. Currently it is strictly parsing channel options, but in general + * the concept is extensible by renaming UserParser to ChannelPropertyParser + * and introducing additional parser functions. + */ +struct SUBOPT { + enum channelOptionKeyIds { + NAME = 0, // name of the channel + TYPE, // push, pull, publish, subscribe, etc + METHOD, // bind or connect + ADDRESS, // host, protocol and port address + TRANSPORT, // + SNDBUFSIZE, // size of the send queue + RCVBUFSIZE, // size of the receive queue + SNDKERNELSIZE, + RCVKERNELSIZE, + RATELOGGING, // logging rate + lastsocketkey + }; + + constexpr static const char *channelOptionKeys[] = { + /*[NAME] = */ "name", + /*[TYPE] = */ "type", + /*[METHOD] = */ "method", + /*[ADDRESS] = */ "address", + /*[TRANSPORT] = */ "transport", + /*[SNDBUFSIZE] = */ "sndBufSize", + /*[RCVBUFSIZE] = */ "rcvBufSize", + /*[SNDKERNELSIZE] = */ "sndKernelSize", + /*[RCVKERNELSIZE] = */ "rcvKernelSize", + /*[RATELOGGING] = */ "rateLogging", + nullptr + }; + + constexpr static const char* OptionKeyChannelConfig = "channel-config"; + + FairMQMap UserParser(const po::variables_map& omap, const std::string& deviceId, const std::string& rootNode = "fairMQOptions"); +}; +}