Skip to content

Source · fairmq/

DeviceRunner.cxxsource

Described in Configuration and properties, Devices, Plugins and control, custom-controller: control from code, Command-line options, Your first device, Logging.

fairmq/DeviceRunner.cxx207 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 Licence (LGPL) version 3,             *6 *                  copied verbatim in the file "LICENSE"                       *7 ********************************************************************************/8 9#include "DeviceRunner.h"10 11#include <fairmq/tools/Strings.h>12#include <fairmq/tools/Version.h>13#include <fairmq/Version.h>14 15#include <fairlogger/Logger.h>16 17#include <exception>18 19using namespace std;20using namespace fair::mq;21 22DeviceRunner::DeviceRunner(int argc, char*const* argv, bool printLogo)23    : fRawCmdLineArgs(tools::ToStrVector(argc, argv, false))24    , fDevice(nullptr)25    , fPluginManager(fRawCmdLineArgs)26    , fPrintLogo(printLogo)27{}28 29bool DeviceRunner::HandleGeneralOptions(const fair::mq::ProgOptions& config, bool printLogo)30{31    if (config.Count("help")) {32        config.PrintHelp();33        return false;34    }35 36    if (config.Count("print-options")) {37        config.PrintOptionsRaw();38        return false;39    }40 41    if (config.Count("print-channels") || config.Count("version")) {42        fair::Logger::SetConsoleSeverity("nolog");43    } else {44        string severity = config.GetProperty<string>("severity");45        string logFile = config.GetProperty<string>("log-to-file");46        string logFileSeverity = config.GetProperty<string>("file-severity");47        bool color = config.GetProperty<bool>("color");48 49        string verbosity = config.GetProperty<string>("verbosity");50        fair::Logger::SetVerbosity(verbosity);51 52        if (!logFile.empty()) {53            fair::Logger::InitFileSink(logFileSeverity, logFile);54            fair::Logger::SetConsoleSeverity("nolog");55        } else {56            fair::Logger::SetConsoleColor(color);57            auto envFairMQSeverity = getenv("FAIRMQ_SEVERITY");58            if (envFairMQSeverity) {59                severity = envFairMQSeverity;60            }61            if (!severity.empty()) {62                fair::Logger::SetConsoleSeverity(severity);63            }64        }65 66        if (printLogo) {67            LOG(info) << endl68                      << "      ______      _    _______  _________ " << endl69                      << "     / ____/___ _(_)_______   |/  /_  __ \\    version "70                      << FAIRMQ_GIT_VERSION << endl71                      << "    / /_  / __ `/ / ___/__  /|_/ /_  / / /    build " << FAIRMQ_BUILD_TYPE72                      << endl73                      << "   / __/ / /_/ / / /    _  /  / / / /_/ /     " << FAIRMQ_REPO_URL << endl74                      << R"(  /_/    \__,_/_/_/     /_/  /_/  \___\_\     )" << FAIRMQ_LICENSE75                      << "  © " << FAIRMQ_COPYRIGHT << endl;76        }77    }78 79    return true;80}81 82void DeviceRunner::SubscribeForConfigChange()83{84    fConfig.Subscribe<bool>("device-runner", [](const std::string& key, const bool val) {85        if (key == "color") {86            fair::Logger::SetConsoleColor(val);87        }88    });89    fConfig.Subscribe<string>("device-runner", [&](const std::string& key, const std::string& val) {90        if (key == "severity") {91            fair::Logger::SetConsoleSeverity(val);92        } else if (key == "file-severity") {93            fair::Logger::SetFileSeverity(val);94        } else if (key == "verbosity") {95            fair::Logger::SetVerbosity(val);96        } else if (key == "log-to-file") {97            string fileSeverity = fConfig.GetProperty<string>("file-severity");98            fair::Logger::InitFileSink(fileSeverity, val);99        }100    });101}102void DeviceRunner::UnsubscribeFromConfigChange()103{104    fConfig.Unsubscribe<bool>("device-runner");105    fConfig.Unsubscribe<string>("device-runner");106}107 108auto DeviceRunner::Run() -> int109{110    fPluginManager.LoadPlugin("s:config");111 112    ////// CALL HOOK ///////113    fEvents.Emit<hooks::LoadPlugins>(*this);114    ////////////////////////115 116    // Load builtin plugins last117    fPluginManager.LoadPlugin("s:control");118 119    ////// CALL HOOK ///////120    fEvents.Emit<hooks::SetCustomCmdLineOptions>(*this);121    ////////////////////////122 123    fPluginManager.ForEachPluginProgOptions([&](boost::program_options::options_description options) {124        fConfig.AddToCmdLineOptions(options);125    });126    fConfig.AddToCmdLineOptions(PluginManager::ProgramOptions());127 128    ////// CALL HOOK ///////129    fEvents.Emit<hooks::ModifyRawCmdLineArgs>(*this);130    ////////////////////////131 132    fConfig.ParseAll(fRawCmdLineArgs, true);133 134    if (!HandleGeneralOptions(fConfig, fPrintLogo)) {135        return 0;136    }137 138    fConfig.Notify();139 140    // handle configuration updates (for general options)141    SubscribeForConfigChange();142 143    ////// CALL HOOK ///////144    fEvents.Emit<hooks::InstantiateDevice>(*this);145    ////////////////////////146 147    if (!fDevice) {148        LOG(error) << "getDevice(): no valid device provided. Exiting.";149        return 1;150    }151 152    fDevice->SetRawCmdLineArgs(fRawCmdLineArgs);153 154    // Handle --print-channels155    fDevice->RegisterChannelEndpoints();156    if (fConfig.Count("print-channels")) {157        fDevice->PrintRegisteredChannels();158        fDevice->ChangeStateOrThrow(fair::mq::Transition::End);159        return 0;160    }161 162    // Handle --version163    if (fConfig.Count("version")) {164        LOGV(info, verylow) << "FairMQ version: " << FAIRMQ_GIT_VERSION;165        LOGV(info, verylow) << "User device version: " << fDevice->GetVersion();166        fDevice->ChangeStateOrThrow(fair::mq::Transition::End);167        return 0;168    }169 170    LOG(debug) << "PID: " << getpid();171 172    // Configure device173    fDevice->SetConfig(fConfig);174 175    // Initialize plugin services176    fPluginManager.EmplacePluginServices(fConfig, *fDevice);177 178    // Instantiate and run plugins179    fPluginManager.InstantiatePlugins();180 181    // Log IDLE configuration182    fConfig.PrintOptions();183 184    // Run the device185    fDevice->RunStateMachine();186 187    // Wait for control plugin to release device control188    fPluginManager.WaitForPluginsToReleaseDeviceControl();189 190    // stop handling configuration updates (for general options)191    UnsubscribeFromConfigChange();192 193    return 0;194}195 196auto DeviceRunner::RunWithExceptionHandlers() -> int197{198    try {199        return Run();200    } catch (exception& e) {201        LOG(error) << "Uncaught exception reached the top of DeviceRunner: " << e.what();202        return 1;203    } catch (...) {204        LOG(error) << "Uncaught exception reached the top of DeviceRunner.";205        return 1;206    }207}