Skip to content

Source · fairmq/

SuboptParser.cxxsource

Described in copypush: one message to several receivers, Configure channels, Channel properties.

fairmq/SuboptParser.cxx136 lines · C++GitHub ↗
1/********************************************************************************2 * Copyright (C) 2017-2021 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH  *3 *                                                                              *4 *              This software is distributed under the terms of the             *5 *              GNU Lesser General Public License (LGPL) version 3,             *6 *                  copied verbatim in the file "LICENSE"                       *7 ********************************************************************************/8 9/// @file   SuboptParser.cxx10/// @author Matthias.Richter@scieq.net11/// @since  2017-03-3012/// @brief  Parser implementation for key-value subopt format13 14#include <fairmq/SuboptParser.h>15#include <fairmq/JSONParser.h>16 17#include <fairlogger/Logger.h>18 19#include <boost/property_tree/ptree.hpp>20#include <string_view>21#include <utility>   // make_pair22#include <cstring>23 24using boost::property_tree::ptree;25using namespace std;26 27namespace fair::mq28{29 30enum channelOptionKeyIds31{32    NAME = 0,       // name of the channel33    TYPE,           // push, pull, publish, subscribe, etc34    METHOD,         // bind or connect35    ADDRESS,        // host, protocol and port address36    TRANSPORT,      //37    SNDBUFSIZE,     // size of the send queue38    RCVBUFSIZE,     // size of the receive queue39    SNDKERNELSIZE,40    RCVKERNELSIZE,41    SNDTIMEOUTMS,42    RCVTIMEOUTMS,43    LINGER,44    RATELOGGING,    // logging rate45    PORTRANGEMIN,46    PORTRANGEMAX,47    AUTOBIND,48    NUMSOCKETS,49    lastsocketkey50};51 52constexpr static const char* channelOptionKeys[] = {53    /*[NAME]          = */ "name",54    /*[TYPE]          = */ "type",55    /*[METHOD]        = */ "method",56    /*[ADDRESS]       = */ "address",57    /*[TRANSPORT]     = */ "transport",58    /*[SNDBUFSIZE]    = */ "sndBufSize",59    /*[RCVBUFSIZE]    = */ "rcvBufSize",60    /*[SNDKERNELSIZE] = */ "sndKernelSize",61    /*[RCVKERNELSIZE] = */ "rcvKernelSize",62    /*[SNDTIMEOUTMS]  = */ "sndTimeoutMs",63    /*[RCVTIMEOUTMS]  = */ "rcvTimeoutMs",64    /*[LINGER]        = */ "linger",65    /*[RATELOGGING]   = */ "rateLogging",66    /*[PORTRANGEMIN]  = */ "portRangeMin",67    /*[PORTRANGEMAX]  = */ "portRangeMax",68    /*[AUTOBIND]      = */ "autoBind",69    /*[NUMSOCKETS]    = */ "numSockets",70    nullptr71};72 73Properties SuboptParser(const vector<string>& channelConfig, const string& deviceId)74{75    ptree pt;76 77    ptree devicesArray;78    ptree deviceProperties;79 80    ptree channelsArray;81 82    for (const auto& token : channelConfig) {83        string channelName;84        ptree channelProperties;85 86        ptree socketsArray;87 88        string argString(token);89        char* subopts = &argString[0];90        char* value = nullptr;91        // Find either a : or a =. If we find the former first, we consider what is before it92        // the channel name93        char* firstSep = strpbrk(subopts, ":=");94        if (firstSep && *firstSep == ':') {95            channelName = std::string_view(subopts, firstSep - subopts);96            channelProperties.put("name", channelName);97            subopts = firstSep + 1;98        }99        while (subopts && *subopts != 0 && *subopts != ' ') {100            char* cur = subopts;101            int subopt = getsubopt(&subopts, (char**)channelOptionKeys, &value);102            if (subopt == NAME) {103                channelName = value;104                channelProperties.put("name", channelName);105            } else if (subopt == ADDRESS) {106                ptree socketProperties;107                socketProperties.put(channelOptionKeys[subopt], value);108                socketsArray.push_back(make_pair("", socketProperties));109            } else if (subopt >= 0 && value != nullptr) {110                channelProperties.put(channelOptionKeys[subopt], value);111            } else if (subopt == -1) {112                LOG(warn) << "Ignoring unknown argument in --channel-config: " << cur;113            }114        }115 116        if (!channelName.empty()) {117            channelProperties.add_child("sockets", socketsArray);118        } else {119            // TODO: what is the error policy here, should we abort?120            LOG(error) << "missing channel name in argument of option --channel-config";121        }122 123        channelsArray.push_back(make_pair("", channelProperties));124    }125 126    deviceProperties.put("id", deviceId);127    deviceProperties.add_child("channels", channelsArray);128 129    devicesArray.push_back(make_pair("", deviceProperties));130 131    pt.add_child("fairMQOptions.devices", devicesArray);132 133    return PtreeParser(pt, deviceId);134}135 136}