Source · fairmq/
JSONParser.cxxsource
Described in 1-n-1: sampler, processors and sink, Configure channels, Channel properties, JSON configuration.
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