Skip to content

Source · fairmq/

JSONParser.cxxsource

Described in 1-n-1: sampler, processors and sink, Configure channels, Channel properties, JSON configuration.

fairmq/JSONParser.cxx193 lines · C++GitHub ↗
1/********************************************************************************2 * Copyright (C) 2014-2021 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH  *3 *                                                                              *4 *              This software is distributed under the terms of the             *5 *              GNU Lesser General Public Licence (LGPL) version 3,             *6 *                  copied verbatim in the file "LICENSE"                       *7 ********************************************************************************/8/*9 * File:   JSONParser.cxx10 * Author: winckler11 *12 * Created on May 14, 2015, 5:01 PM13 */14 15#include "JSONParser.h"16 17#include <fairlogger/Logger.h>18 19#include <boost/any.hpp>20#define BOOST_BIND_GLOBAL_PLACEHOLDERS21#include <boost/property_tree/json_parser.hpp>22#undef BOOST_BIND_GLOBAL_PLACEHOLDERS23#include <boost/property_tree/ptree.hpp>24#include <fairlogger/Logger.h>25#include <fairmq/Channel.h>26#include <fairmq/JSONParser.h>27#include <fairmq/PropertyOutput.h>28#include <fairmq/tools/Strings.h>29#include <iomanip>30 31using namespace std;32using namespace fair::mq;33using namespace tools;34using namespace boost::property_tree;35 36namespace fair::mq37{38 39Properties PtreeParser(const ptree& pt, const string& id)40{41    if (id.empty()) {42        throw ParserError("no device ID provided. Provide with `--id` cmd option");43    }44 45    // json_parser::write_json(cout, pt);46 47    return helper::DeviceParser(pt.get_child("fairMQOptions"), id);48}49 50Properties JSONParser(const string& filename, const string& deviceId)51{52    ptree pt;53    LOG(debug) << "Parsing JSON from " << filename << " ...";54    read_json(filename, pt);55    return PtreeParser(pt, deviceId);56}57 58namespace helper59{60 61Properties DeviceParser(const ptree& fairMQOptions, const string& deviceId)62{63    Properties properties;64 65    for (const auto& node : fairMQOptions) {66        if (node.first == "devices") {67            for (const auto& device : node.second) {68                // check if key is provided, otherwise use id69                string deviceIdKey = device.second.get<string>("key", device.second.get<string>("id", ""));70 71                // if not correct device id, do not fill MQMap72                if (deviceId != deviceIdKey) {73                    continue;74                }75 76                LOG(trace) << "Found following channels for device ID '" << deviceId << "' :";77                ChannelParser(device.second, properties);78            }79        }80    }81 82    return properties;83}84 85void ChannelParser(const ptree& tree, Properties& properties)86{87    for (const auto& node : tree) {88        if (node.first == "channels") {89            for (const auto& cn : node.second) {90                Properties commonProperties;91                commonProperties.emplace("type", cn.second.get<string>("type", Channel::DefaultType));92                commonProperties.emplace("method", cn.second.get<string>("method", Channel::DefaultMethod));93                commonProperties.emplace("address", cn.second.get<string>("address", Channel::DefaultAddress));94                commonProperties.emplace("transport", cn.second.get<string>("transport", Channel::DefaultTransportName));95                commonProperties.emplace("sndBufSize", cn.second.get<int>("sndBufSize", Channel::DefaultSndBufSize));96                commonProperties.emplace("rcvBufSize", cn.second.get<int>("rcvBufSize", Channel::DefaultRcvBufSize));97                commonProperties.emplace("sndKernelSize", cn.second.get<int>("sndKernelSize", Channel::DefaultSndKernelSize));98                commonProperties.emplace("rcvKernelSize", cn.second.get<int>("rcvKernelSize", Channel::DefaultRcvKernelSize));99                commonProperties.emplace("sndTimeoutMs", cn.second.get<int>("sndTimeoutMs", Channel::DefaultSndTimeoutMs));100                commonProperties.emplace("rcvTimeoutMs", cn.second.get<int>("rcvTimeoutMs", Channel::DefaultRcvTimeoutMs));101                commonProperties.emplace("linger", cn.second.get<int>("linger", Channel::DefaultLinger));102                commonProperties.emplace("rateLogging", cn.second.get<int>("rateLogging", Channel::DefaultRateLogging));103                commonProperties.emplace("portRangeMin", cn.second.get<int>("portRangeMin", Channel::DefaultPortRangeMin));104                commonProperties.emplace("portRangeMax", cn.second.get<int>("portRangeMax", Channel::DefaultPortRangeMax));105                commonProperties.emplace("autoBind", cn.second.get<bool>("autoBind", Channel::DefaultAutoBind));106 107                string name = cn.second.get<string>("name");108                int numSockets = cn.second.get<int>("numSockets", 0);109 110                if (numSockets > 0) {111                    LOG(trace) << name << ":";112                    LOG(trace) << "\tnumSockets of " << numSockets << " specified, applying common settings to each:";113 114                    for (auto& p : commonProperties) {115                        LOG(trace) << "\t" << setw(13) << left << p.first << " : " << p.second;116                    }117 118                    for (int i = 0; i < numSockets; ++i) {119                        for (const auto& p : commonProperties) {120                            properties.emplace(ToString("chans.", name, ".", i, ".", p.first), p.second);121                        }122                    }123                } else {124                    SubChannelParser(cn.second.get_child(""), properties, name, commonProperties);125                }126            }127        }128    }129}130 131void SubChannelParser(const ptree& channelTree, Properties& properties, const string& channelName, const Properties& commonProperties)132{133    // for each socket in channel134    int i = 0;135 136    for (const auto& node : channelTree) {137        if (node.first == "sockets") {138            for (const auto& sn : node.second) {139                // a sub-channel inherits relevant properties from the common channel ...140                Properties newProperties(commonProperties);141 142                // ... and adds/overwrites its own properties143                newProperties["type"] = sn.second.get<string>("type", boost::any_cast<string>(commonProperties.at("type")));144                newProperties["method"] = sn.second.get<string>("method", boost::any_cast<string>(commonProperties.at("method")));145                newProperties["address"] = sn.second.get<string>("address", boost::any_cast<string>(commonProperties.at("address")));146                newProperties["transport"] = sn.second.get<string>("transport", boost::any_cast<string>(commonProperties.at("transport")));147                newProperties["sndBufSize"] = sn.second.get<int>("sndBufSize", boost::any_cast<int>(commonProperties.at("sndBufSize")));148                newProperties["rcvBufSize"] = sn.second.get<int>("rcvBufSize", boost::any_cast<int>(commonProperties.at("rcvBufSize")));149                newProperties["sndKernelSize"] = sn.second.get<int>("sndKernelSize", boost::any_cast<int>(commonProperties.at("sndKernelSize")));150                newProperties["rcvKernelSize"] = sn.second.get<int>("rcvKernelSize", boost::any_cast<int>(commonProperties.at("rcvKernelSize")));151                newProperties["sndTimeoutMs"] = sn.second.get<int>("sndTimeoutMs", boost::any_cast<int>(commonProperties.at("sndTimeoutMs")));152                newProperties["rcvTimeoutMs"] = sn.second.get<int>("rcvTimeoutMs", boost::any_cast<int>(commonProperties.at("rcvTimeoutMs")));153                newProperties["linger"] = sn.second.get<int>("linger", boost::any_cast<int>(commonProperties.at("linger")));154                newProperties["rateLogging"] = sn.second.get<int>("rateLogging", boost::any_cast<int>(commonProperties.at("rateLogging")));155                newProperties["portRangeMin"] = sn.second.get<int>("portRangeMin", boost::any_cast<int>(commonProperties.at("portRangeMin")));156                newProperties["portRangeMax"] = sn.second.get<int>("portRangeMax", boost::any_cast<int>(commonProperties.at("portRangeMax")));157                newProperties["autoBind"] = sn.second.get<bool>("autoBind", boost::any_cast<bool>(commonProperties.at("autoBind")));158 159                LOG(trace) << "" << channelName << "[" << i << "]:";160                for (auto& p : newProperties) {161                    LOG(trace) << "\t" << setw(13) << left << p.first << " : " << p.second;162                }163 164                for (const auto& p : newProperties) {165                    properties.emplace(ToString("chans.", channelName, ".", i, ".", p.first), p.second);166                }167                ++i;168            }169        }170    }171 172    if (i > 0) {173        LOG(trace) << "Found " << i << " socket(s) in channel.";174    } else {175        // if no sockets are specified, apply common channel properties176        LOG(trace) << "" << channelName << ":";177        LOG(trace) << "\tNo sockets specified,";178        LOG(trace) << "\tapplying common settings to the channel:";179 180        Properties newProperties(commonProperties);181 182        for (auto& p : newProperties) {183            LOG(trace) << "\t" << setw(13) << left << p.first << " : " << p.second;184        }185 186        for (const auto& p : newProperties) {187            properties.emplace(ToString("chans.", channelName, ".0.", p.first), p.second);188        }189    }190}191 192} // helper namespace193} // namespace fair::mq