/******************************************************************************** * Copyright (C) 2014-2018 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: FairMQParser.cxx * Author: winckler * * Created on May 14, 2015, 5:01 PM */ #include "FairMQParser.h" #include "FairMQLogger.h" #include #include #include using namespace std; namespace fair { namespace mq { namespace parser { // TODO : add key-value map parameter for replacing/updating values from keys // function that convert property tree (given the json structure) to FairMQChannelMap FairMQChannelMap ptreeToMQMap(const boost::property_tree::ptree& pt, const string& id, const string& rootNode) { if (id == "") { throw ParserError("no device ID provided. Provide with `--id` cmd option"); } // Create fair mq map FairMQChannelMap channelMap; // boost::property_tree::json_parser::write_json(std::cout, pt); // Helper::PrintDeviceList(pt.get_child(rootNode)); // Extract value from boost::property_tree Helper::DeviceParser(pt.get_child(rootNode), channelMap, id); if (channelMap.empty()) { LOG(warn) << "---- No channel keys found for " << id; LOG(warn) << "---- Check the JSON inputs and/or command line inputs"; } return channelMap; } FairMQChannelMap JSON::UserParser(const string& filename, const string& deviceId, const string& rootNode) { boost::property_tree::ptree pt; boost::property_tree::read_json(filename, pt); return ptreeToMQMap(pt, deviceId, rootNode); } namespace Helper { void PrintDeviceList(const boost::property_tree::ptree& tree) { string deviceIdKey; // do a first loop just to print the device-id in json input for (const auto& p : tree) { if (p.first == "devices") { for (const auto& q : p.second.get_child("")) { string key = q.second.get("key", ""); if (key != "") { deviceIdKey = key; LOG(debug) << "Found config for device key '" << deviceIdKey << "' in JSON input"; } else { deviceIdKey = q.second.get("id"); LOG(debug) << "Found config for device id '" << deviceIdKey << "' in JSON input"; } } } } } void DeviceParser(const boost::property_tree::ptree& tree, FairMQChannelMap& channelMap, const string& deviceId) { string deviceIdKey; // For each node in fairMQOptions for (const auto& p : tree) { if (p.first == "devices") { for (const auto& q : p.second) { // check if key is provided, otherwise use id string key = q.second.get("key", ""); if (key != "") { deviceIdKey = key; // LOG(debug) << "Found config for device key '" << deviceIdKey << "' in JSON input"; } else { deviceIdKey = q.second.get("id"); // LOG(debug) << "Found config for device id '" << deviceIdKey << "' in JSON input"; } // if not correct device id, do not fill MQMap if (deviceId != deviceIdKey) { continue; } LOG(debug) << "Found following channels for device ID '" << deviceId << "' :"; ChannelParser(q.second, channelMap); } } } } void ChannelParser(const boost::property_tree::ptree& tree, FairMQChannelMap& channelMap) { string channelKey; for (const auto& p : tree) { if (p.first == "channels") { for (const auto& q : p.second) { channelKey = q.second.get("name"); int numSockets = q.second.get("numSockets", 0); // try to get common properties to use for all subChannels FairMQChannel commonChannel; commonChannel.UpdateType(q.second.get("type", commonChannel.GetType())); commonChannel.UpdateMethod(q.second.get("method", commonChannel.GetMethod())); commonChannel.UpdateAddress(q.second.get("address", commonChannel.GetAddress())); commonChannel.UpdateTransport(q.second.get("transport", commonChannel.GetTransportName())); commonChannel.UpdateSndBufSize(q.second.get("sndBufSize", commonChannel.GetSndBufSize())); commonChannel.UpdateRcvBufSize(q.second.get("rcvBufSize", commonChannel.GetRcvBufSize())); commonChannel.UpdateSndKernelSize(q.second.get("sndKernelSize", commonChannel.GetSndKernelSize())); commonChannel.UpdateRcvKernelSize(q.second.get("rcvKernelSize", commonChannel.GetRcvKernelSize())); commonChannel.UpdateLinger(q.second.get("linger", commonChannel.GetLinger())); commonChannel.UpdateRateLogging(q.second.get("rateLogging", commonChannel.GetRateLogging())); // temporary FairMQChannel container vector channelList; if (numSockets > 0) { LOG(debug) << "" << channelKey << ":"; LOG(debug) << "\tnumSockets of " << numSockets << " specified,"; LOG(debug) << "\tapplying common settings to each:"; LOG(debug) << "\ttype = " << commonChannel.GetType(); LOG(debug) << "\tmethod = " << commonChannel.GetMethod(); LOG(debug) << "\taddress = " << commonChannel.GetAddress(); LOG(debug) << "\ttransport = " << commonChannel.GetTransportName(); LOG(debug) << "\tsndBufSize = " << commonChannel.GetSndBufSize(); LOG(debug) << "\trcvBufSize = " << commonChannel.GetRcvBufSize(); LOG(debug) << "\tsndKernelSize = " << commonChannel.GetSndKernelSize(); LOG(debug) << "\trcvKernelSize = " << commonChannel.GetRcvKernelSize(); LOG(debug) << "\tlinger = " << commonChannel.GetLinger(); LOG(debug) << "\trateLogging = " << commonChannel.GetRateLogging(); for (int i = 0; i < numSockets; ++i) { FairMQChannel channel(commonChannel); channelList.push_back(channel); } } else { SocketParser(q.second.get_child(""), channelList, channelKey, commonChannel); } channelMap.insert(make_pair(channelKey, move(channelList))); } } } } void SocketParser(const boost::property_tree::ptree& tree, vector& channelList, const string& channelName, const FairMQChannel& commonChannel) { // for each socket in channel int socketCounter = 0; for (const auto& p : tree) { if (p.first == "sockets") { for (const auto& q : p.second) { // create new channel and apply setting from the common channel FairMQChannel channel(commonChannel); // if the socket field specifies or overrides something from the common channel, apply those settings channel.UpdateType(q.second.get("type", channel.GetType())); channel.UpdateMethod(q.second.get("method", channel.GetMethod())); channel.UpdateAddress(q.second.get("address", channel.GetAddress())); channel.UpdateTransport(q.second.get("transport", channel.GetTransportName())); channel.UpdateSndBufSize(q.second.get("sndBufSize", channel.GetSndBufSize())); channel.UpdateRcvBufSize(q.second.get("rcvBufSize", channel.GetRcvBufSize())); channel.UpdateSndKernelSize(q.second.get("sndKernelSize", channel.GetSndKernelSize())); channel.UpdateRcvKernelSize(q.second.get("rcvKernelSize", channel.GetRcvKernelSize())); channel.UpdateLinger(q.second.get("linger", channel.GetLinger())); channel.UpdateRateLogging(q.second.get("rateLogging", channel.GetRateLogging())); LOG(debug) << "" << channelName << "[" << socketCounter << "]:"; LOG(debug) << "\ttype = " << channel.GetType(); LOG(debug) << "\tmethod = " << channel.GetMethod(); LOG(debug) << "\taddress = " << channel.GetAddress(); LOG(debug) << "\ttransport = " << channel.GetTransportName(); LOG(debug) << "\tsndBufSize = " << channel.GetSndBufSize(); LOG(debug) << "\trcvBufSize = " << channel.GetRcvBufSize(); LOG(debug) << "\tsndKernelSize = " << channel.GetSndKernelSize(); LOG(debug) << "\trcvKernelSize = " << channel.GetRcvKernelSize(); LOG(debug) << "\tlinger = " << channel.GetLinger(); LOG(debug) << "\trateLogging = " << channel.GetRateLogging(); channelList.push_back(channel); ++socketCounter; } } } // end socket loop if (socketCounter) { LOG(debug) << "Found " << socketCounter << " socket(s) in channel."; } else { LOG(debug) << "" << channelName << ":"; LOG(debug) << "\tNo sockets specified,"; LOG(debug) << "\tapplying common settings to the channel:"; FairMQChannel channel(commonChannel); LOG(debug) << "\ttype = " << channel.GetType(); LOG(debug) << "\tmethod = " << channel.GetMethod(); LOG(debug) << "\taddress = " << channel.GetAddress(); LOG(debug) << "\ttransport = " << channel.GetTransportName(); LOG(debug) << "\tsndBufSize = " << channel.GetSndBufSize(); LOG(debug) << "\trcvBufSize = " << channel.GetRcvBufSize(); LOG(debug) << "\tsndKernelSize = " << channel.GetSndKernelSize(); LOG(debug) << "\trcvKernelSize = " << channel.GetRcvKernelSize(); LOG(debug) << "\tlinger = " << channel.GetLinger(); LOG(debug) << "\trateLogging = " << channel.GetRateLogging(); channelList.push_back(channel); } } } // Helper namespace } // namespace parser } // namespace mq } // namespace fair