/******************************************************************************** * Copyright (C) 2014-2021 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH * * * * This software is distributed under the terms of the * * GNU Lesser General Public Licence (LGPL) version 3, * * copied verbatim in the file "LICENSE" * ********************************************************************************/ /* * File: JSONParser.cxx * Author: winckler * * Created on May 14, 2015, 5:01 PM */ #include "JSONParser.h" #include #include #define BOOST_BIND_GLOBAL_PLACEHOLDERS #include #undef BOOST_BIND_GLOBAL_PLACEHOLDERS #include #include #include #include #include #include #include using namespace std; using namespace fair::mq; using namespace fair::mq::tools; using namespace boost::property_tree; namespace fair::mq { fair::mq::Properties PtreeParser(const ptree& pt, const string& id) { if (id.empty()) { throw ParserError("no device ID provided. Provide with `--id` cmd option"); } // json_parser::write_json(cout, pt); return helper::DeviceParser(pt.get_child("fairMQOptions"), id); } fair::mq::Properties JSONParser(const string& filename, const string& deviceId) { ptree pt; LOG(debug) << "Parsing JSON from " << filename << " ..."; read_json(filename, pt); return PtreeParser(pt, deviceId); } namespace helper { fair::mq::Properties DeviceParser(const ptree& fairMQOptions, const string& deviceId) { fair::mq::Properties properties; for (const auto& node : fairMQOptions) { if (node.first == "devices") { for (const auto& device : node.second) { // check if key is provided, otherwise use id string deviceIdKey = device.second.get("key", device.second.get("id", "")); // if not correct device id, do not fill MQMap if (deviceId != deviceIdKey) { continue; } LOG(trace) << "Found following channels for device ID '" << deviceId << "' :"; ChannelParser(device.second, properties); } } } return properties; } void ChannelParser(const ptree& tree, fair::mq::Properties& properties) { for (const auto& node : tree) { if (node.first == "channels") { for (const auto& cn : node.second) { fair::mq::Properties commonProperties; commonProperties.emplace("type", cn.second.get("type", FairMQChannel::DefaultType)); commonProperties.emplace("method", cn.second.get("method", FairMQChannel::DefaultMethod)); commonProperties.emplace("address", cn.second.get("address", FairMQChannel::DefaultAddress)); commonProperties.emplace("transport", cn.second.get("transport", FairMQChannel::DefaultTransportName)); commonProperties.emplace("sndBufSize", cn.second.get("sndBufSize", FairMQChannel::DefaultSndBufSize)); commonProperties.emplace("rcvBufSize", cn.second.get("rcvBufSize", FairMQChannel::DefaultRcvBufSize)); commonProperties.emplace("sndKernelSize", cn.second.get("sndKernelSize", FairMQChannel::DefaultSndKernelSize)); commonProperties.emplace("rcvKernelSize", cn.second.get("rcvKernelSize", FairMQChannel::DefaultRcvKernelSize)); commonProperties.emplace("linger", cn.second.get("linger", FairMQChannel::DefaultLinger)); commonProperties.emplace("rateLogging", cn.second.get("rateLogging", FairMQChannel::DefaultRateLogging)); commonProperties.emplace("portRangeMin", cn.second.get("portRangeMin", FairMQChannel::DefaultPortRangeMin)); commonProperties.emplace("portRangeMax", cn.second.get("portRangeMax", FairMQChannel::DefaultPortRangeMax)); commonProperties.emplace("autoBind", cn.second.get("autoBind", FairMQChannel::DefaultAutoBind)); string name = cn.second.get("name"); int numSockets = cn.second.get("numSockets", 0); if (numSockets > 0) { LOG(trace) << name << ":"; LOG(trace) << "\tnumSockets of " << numSockets << " specified, applying common settings to each:"; for (auto& p : commonProperties) { LOG(trace) << "\t" << setw(13) << left << p.first << " : " << p.second; } for (int i = 0; i < numSockets; ++i) { for (const auto& p : commonProperties) { properties.emplace(ToString("chans.", name, ".", i, ".", p.first), p.second); } } } else { SubChannelParser(cn.second.get_child(""), properties, name, commonProperties); } } } } } void SubChannelParser(const ptree& channelTree, fair::mq::Properties& properties, const string& channelName, const fair::mq::Properties& commonProperties) { // for each socket in channel int i = 0; for (const auto& node : channelTree) { if (node.first == "sockets") { for (const auto& sn : node.second) { // a sub-channel inherits relevant properties from the common channel ... fair::mq::Properties newProperties(commonProperties); // ... and adds/overwrites its own properties newProperties["type"] = sn.second.get("type", boost::any_cast(commonProperties.at("type"))); newProperties["method"] = sn.second.get("method", boost::any_cast(commonProperties.at("method"))); newProperties["address"] = sn.second.get("address", boost::any_cast(commonProperties.at("address"))); newProperties["transport"] = sn.second.get("transport", boost::any_cast(commonProperties.at("transport"))); newProperties["sndBufSize"] = sn.second.get("sndBufSize", boost::any_cast(commonProperties.at("sndBufSize"))); newProperties["rcvBufSize"] = sn.second.get("rcvBufSize", boost::any_cast(commonProperties.at("rcvBufSize"))); newProperties["sndKernelSize"] = sn.second.get("sndKernelSize", boost::any_cast(commonProperties.at("sndKernelSize"))); newProperties["rcvKernelSize"] = sn.second.get("rcvKernelSize", boost::any_cast(commonProperties.at("rcvKernelSize"))); newProperties["linger"] = sn.second.get("linger", boost::any_cast(commonProperties.at("linger"))); newProperties["rateLogging"] = sn.second.get("rateLogging", boost::any_cast(commonProperties.at("rateLogging"))); newProperties["portRangeMin"] = sn.second.get("portRangeMin", boost::any_cast(commonProperties.at("portRangeMin"))); newProperties["portRangeMax"] = sn.second.get("portRangeMax", boost::any_cast(commonProperties.at("portRangeMax"))); newProperties["autoBind"] = sn.second.get("autoBind", boost::any_cast(commonProperties.at("autoBind"))); LOG(trace) << "" << channelName << "[" << i << "]:"; for (auto& p : newProperties) { LOG(trace) << "\t" << setw(13) << left << p.first << " : " << p.second; } for (const auto& p : newProperties) { properties.emplace(ToString("chans.", channelName, ".", i, ".", p.first), p.second); } ++i; } } } if (i > 0) { LOG(trace) << "Found " << i << " socket(s) in channel."; } else { // if no sockets are specified, apply common channel properties LOG(trace) << "" << channelName << ":"; LOG(trace) << "\tNo sockets specified,"; LOG(trace) << "\tapplying common settings to the channel:"; fair::mq::Properties newProperties(commonProperties); for (auto& p : newProperties) { LOG(trace) << "\t" << setw(13) << left << p.first << " : " << p.second; } for (const auto& p : newProperties) { properties.emplace(ToString("chans.", channelName, ".0.", p.first), p.second); } } } } // helper namespace } // namespace fair::mq