LCOV - code coverage report
Current view: top level - artdaq/ExternalComms - xmlrpc_commander.cc (source / functions) Coverage Total Hit
Test: artdaq.info.cleaned Lines: 0.0 % 610 0
Test Date: 2026-10-29 00:35:58 Functions: 0.0 % 117 0

            Line data    Source code
       1              : /* DarkSide 50 DAQ program
       2              :  * This file add the xmlrpc commander as a client to the SC
       3              :  * Author: Alessandro Razeto <Alessandro.Razeto@ge.infn.it>
       4              :  */
       5              : 
       6              : #pragma GCC diagnostic push
       7              : #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
       8              : #define _LIBCPP_ENABLE_CXX17_REMOVED_FEATURES 1
       9              : #include <memory>
      10              : #include <xmlrpc-c/base.hpp>
      11              : #include <xmlrpc-c/client_simple.hpp>
      12              : #include <xmlrpc-c/girerr.hpp>
      13              : #include <xmlrpc-c/registry.hpp>
      14              : #include <xmlrpc-c/server_abyss.hpp>
      15              : #undef _LIBCPP_ENABLE_CXX17_REMOVED_FEATURES
      16              : #pragma GCC diagnostic pop
      17              : 
      18              : #include "TRACE/tracemf.h"
      19              : #include "artdaq/DAQdata/Globals.hh"
      20              : #define TRACE_NAME (app_name + "_xmlrpc_commander").c_str()
      21              : 
      22              : #include "artdaq/ExternalComms/CommanderInterface.hh"
      23              : 
      24              : #include "artdaq-core/Utilities/ExceptionHandler.hh"
      25              : 
      26              : #include <netinet/in.h>
      27              : #include <sys/socket.h>
      28              : #include <cerrno>
      29              : #include <cstdint>
      30              : #include <cstring>
      31              : #include <exception>
      32              : #include <iostream>
      33              : #include <limits>
      34              : #include <memory>
      35              : #include <mutex>
      36              : #include <stdexcept>
      37              : 
      38              : namespace artdaq {
      39              : 
      40              : /**
      41              :  * \brief The xmlrpc_commander class serves as the XMLRPC server run in each artdaq application
      42              :  */
      43              : class xmlrpc_commander : public CommanderInterface
      44              : {
      45              : public:
      46              :         /**
      47              :          * \brief xmlrpc_commander Constructor
      48              :          * \param ps ParameterSet used for configuring xmlrpc_commander
      49              :          * \param commandable artdaq::Commandable object to send transition commands to
      50              :          *
      51              :          * \verbatim
      52              :           xmlrpc_commander accepts the following Parameters:
      53              :            id: For XMLRPC, the ID should be the port to listen on
      54              :            server_url: When sending, location of XMLRPC server
      55              :          * \endverbatim
      56              :          */
      57              :         xmlrpc_commander(const fhicl::ParameterSet& ps, artdaq::Commandable& commandable);
      58              : 
      59              :         /**
      60              :          * \brief Run the XMLRPC server
      61              :          */
      62              :         void run_server() override;
      63              : 
      64              :         /// <summary>
      65              :         /// Send a register_monitor command over XMLRPC
      66              :         /// </summary>
      67              :         /// <param name="monitor_fhicl">FHiCL string contianing monitor configuration</param>
      68              :         /// <returns>Return status from XMLRPC</returns>
      69              :         std::string send_register_monitor(std::string const& monitor_fhicl) override;
      70              : 
      71              :         /// <summary>
      72              :         /// Send an unregister_monitor command over XMLRPC
      73              :         /// </summary>
      74              :         /// <param name="monitor_label">Label of the monitor to unregister</param>
      75              :         /// <returns>Return status from XMLRPC</returns>
      76              :         std::string send_unregister_monitor(std::string const& monitor_label) override;
      77              : 
      78              :         /// <summary>
      79              :         /// Send an init command over XMLRPC
      80              :         ///
      81              :         /// The init command is accepted by all artdaq processes that are in the booted state.
      82              :         /// It expects a ParameterSet for configuration, a timeout, and a timestamp.
      83              :         /// </summary>
      84              :         /// <param name="ps">ParameterSet received with the init command</param>
      85              :         /// <param name="timeout">Timeout for the command</param>
      86              :         /// <param name="timestamp">Timestamp of the command</param>
      87              :         /// <returns>Command result: "SUCCESS" if succeeded</returns>
      88              :         std::string send_init(fhicl::ParameterSet const& ps, uint64_t timeout, uint64_t timestamp) override;
      89              : 
      90              :         /// <summary>
      91              :         /// Send a soft_init command over XMLRPC
      92              :         ///
      93              :         /// The soft_init command is accepted by all artdaq processes that are in the booted state.
      94              :         /// It expects a ParameterSet for configuration, a timeout, and a timestamp.
      95              :         /// </summary>
      96              :         /// <param name="ps">ParameterSet received with the soft_init command</param>
      97              :         /// <param name="timeout">Timeout for the command</param>
      98              :         /// <param name="timestamp">Timestamp of the command</param>
      99              :         /// <returns>Command result: "SUCCESS" if succeeded</returns>
     100              :         std::string send_soft_init(fhicl::ParameterSet const& ps, uint64_t timeout, uint64_t timestamp) override;
     101              : 
     102              :         /// <summary>
     103              :         /// Send a reinit command over XMLRPC
     104              :         ///
     105              :         /// The reinit command is accepted by all artdaq processes.
     106              :         /// It expects a ParameterSet for configuration, a timeout, and a timestamp.
     107              :         /// </summary>
     108              :         /// <param name="ps">ParameterSet received with the reinit command</param>
     109              :         /// <param name="timeout">Timeout for the command</param>
     110              :         /// <param name="timestamp">Timestamp of the command</param>
     111              :         /// <returns>Command result: "SUCCESS" if succeeded</returns>
     112              :         std::string send_reinit(fhicl::ParameterSet const& ps, uint64_t timeout, uint64_t timestamp) override;
     113              : 
     114              :         /// <summary>
     115              :         /// Send a start command over XMLRPC
     116              :         ///
     117              :         /// The start command starts a Run using the given run number.
     118              :         /// This command also accepts a timeout parameter and a timestamp parameter.
     119              :         /// </summary>
     120              :         /// <param name="runNumber">Run number of the new run</param>
     121              :         /// <param name="timeout">Timeout for the command</param>
     122              :         /// <param name="timestamp">Timestamp of the command</param>
     123              :         /// <returns>Command result: "SUCCESS" if succeeded</returns>
     124              :         std::string send_start(art::RunID runNumber, uint64_t timeout, uint64_t timestamp) override;
     125              : 
     126              :         /// <summary>
     127              :         /// Send a pause command over XMLRPC
     128              :         ///
     129              :         /// The pause command pauses a Run. When the run resumes, the subrun number will be incremented.
     130              :         /// This command accepts a timeout parameter and a timestamp parameter.
     131              :         /// </summary>
     132              :         /// <param name="timeout">Timeout for the command</param>
     133              :         /// <param name="timestamp">Timestamp of the command</param>
     134              :         /// <returns>Command result: "SUCCESS" if succeeded</returns>
     135              :         std::string send_pause(uint64_t timeout, uint64_t timestamp) override;
     136              : 
     137              :         /// <summary>
     138              :         /// Send a resume command over XMLRPC
     139              :         ///
     140              :         /// The resume command resumes a paused Run. When the run resumes, the subrun number will be incremented.
     141              :         /// This command accepts a timeout parameter and a timestamp parameter.
     142              :         /// </summary>
     143              :         /// <param name="timeout">Timeout for the command</param>
     144              :         /// <param name="timestamp">Timestamp of the command</param>
     145              :         /// <returns>Command result: "SUCCESS" if succeeded</returns>
     146              :         std::string send_resume(uint64_t timeout, uint64_t timestamp) override;
     147              : 
     148              :         /// <summary>
     149              :         /// Send a stop command over XMLRPC
     150              :         ///
     151              :         /// The stop command stops the current Run.
     152              :         /// This command accepts a timeout parameter and a timestamp parameter.
     153              :         /// </summary>
     154              :         /// <param name="timeout">Timeout for the command</param>
     155              :         /// <param name="timestamp">Timestamp of the command</param>
     156              :         /// <returns>Command result: "SUCCESS" if succeeded</returns>
     157              :         std::string send_stop(uint64_t timeout, uint64_t timestamp) override;
     158              : 
     159              :         /// <summary>
     160              :         /// Send a shutdown command over XMLRPC
     161              :         ///
     162              :         /// The shutdown command shuts down the artdaq process.
     163              :         /// This command accepts a timeout parameter.
     164              :         /// </summary>
     165              :         /// <param name="timeout">Timeout for the command</param>
     166              :         /// <returns>Command result: "SUCCESS" if succeeded</returns>
     167              :         std::string send_shutdown(uint64_t timeout) override;
     168              : 
     169              :         /// <summary>
     170              :         /// Send a status command over XMLRPC
     171              :         ///
     172              :         /// The status command returns the current status of the artdaq process.
     173              :         /// </summary>
     174              :         /// <returns>Command result: current status of the artdaq process</returns>
     175              :         std::string send_status() override;
     176              : 
     177              :         /// <summary>
     178              :         /// Send a report command over XMLRPC
     179              :         ///
     180              :         /// The report command returns the current value of the requested reportable quantity.
     181              :         /// </summary>
     182              :         /// <param name="what">Reportable quantity to request</param>
     183              :         /// <returns>Command result: current value of the requested reportable quantity</returns>
     184              :         std::string send_report(std::string const& what) override;
     185              : 
     186              :         /// <summary>
     187              :         /// Send a legal_commands command over XMLRPC
     188              :         ///
     189              :         /// This will query the artdaq process, and it will return the list of allowed transition commands from its current state.
     190              :         /// </summary>
     191              :         /// <returns>Command result: a list of allowed transition commands from its current state</returns>
     192              :         std::string send_legal_commands() override;
     193              : 
     194              :         /// <summary>
     195              :         /// Send an send_trace_get command over XMLRPC
     196              :         ///
     197              :         /// This will cause the receiver to get the TRACE level masks for the given name
     198              :         /// Use name == "ALL" to get ALL names
     199              :         /// </summary>
     200              :         /// <param name="name">TRACE name to get the mask for ("ALL" to get all names)</param>
     201              :         /// <returns>Command result: "SUCCESS" if succeeded</returns>
     202              :         std::string send_trace_get(std::string const& name) override;
     203              : 
     204              :         /// <summary>
     205              :         /// Send an send_trace_msgfacility_set command over XMLRPC
     206              :         ///
     207              :         /// This will cause the receiver to set the given TRACE level mask for the given name to the given mask.
     208              :         /// Only the first character of the mask selection will be parsed, dial 'M' for Memory, or 'S' for Slow.
     209              :         /// Use name == "ALL" to set ALL names
     210              :         ///
     211              :         /// EXAMPLE: xmlrpc http://localhost:5235/RPC2 daq.trace_msgfacility_set TraceLock i8/$((0x1234)) # Use Bash to convert hex to dec
     212              :         /// </summary>
     213              :         /// <param name="name">TRACE name to set ("ALL" for all TRACE names)</param>
     214              :         /// <param name="type">Type of mask to set ('M', 'S', or 'T')</param>
     215              :         /// <param name="mask">64-bit mask, in string form</param>
     216              :         /// <returns>Command result: "SUCCESS" if succeeded</returns>
     217              :         std::string send_trace_set(std::string const& name, std::string const& type, std::string const& mask) override;
     218              : 
     219              :         /// <summary>
     220              :         /// Send an send_meta_command command over XMLRPC
     221              :         ///
     222              :         /// This will cause the receiver to run the given command with the given argument in user code
     223              :         /// </summary>
     224              :         /// <param name="command">Command name to send</param>
     225              :         /// <param name="argument">Argument for command</param>
     226              :         /// <returns>Command result: "SUCCESS" if succeeded</returns>
     227              :         std::string send_meta_command(std::string const& command, std::string const& argument) override;
     228              : 
     229              :         /// <summary>
     230              :         /// Send a send_rollover_subrun command over XMLRPC
     231              :         ///
     232              :         /// This will cause the receiver to rollover the subrun number at the given event. (Event with seqID == boundary will be in new subrun.)
     233              :         /// Should be sent to all EventBuilders before the given event is processed.
     234              :         /// </summary>
     235              :         /// <param name="when">Sequence ID of new subrun</param>
     236              :         /// <param name="sr">Subrun number of the new subrun</param>
     237              :         /// <returns>Command result: "SUCCESS" if succeeded</returns>
     238              :         std::string send_rollover_subrun(uint64_t when, uint32_t sr) override;
     239              : 
     240              : private:
     241              :         xmlrpc_commander(const xmlrpc_commander&) = delete;
     242              : 
     243              :         xmlrpc_commander(xmlrpc_commander&&) = delete;
     244              :         xmlrpc_commander& operator=(xmlrpc_commander const&) = delete;
     245              :         xmlrpc_commander& operator=(xmlrpc_commander&&) = delete;
     246              : 
     247              :         int port_;
     248              :         std::string serverUrl_;
     249              : 
     250              :         std::string send_command_(const std::string& command);
     251              :         std::string send_command_(const std::string& command, const std::string& arg);
     252              :         std::string send_command_(const std::string& command, const fhicl::ParameterSet& pset, uint64_t timestamp, uint64_t timeout);
     253              :         std::string send_command_(const std::string& command, uint64_t a, uint64_t b);
     254              :         std::string send_command_(const std::string& command, uint64_t a, uint32_t b);
     255              :         std::string send_command_(const std::string& command, art::RunID r, uint64_t a, uint64_t b);
     256              :         std::string send_command_(const std::string&, uint64_t);
     257              :         std::string send_command_(const std::string&, const std::string&, const std::string&);
     258              :         std::string send_command_(const std::string&, const std::string&, const std::string&, const std::string&);
     259              : 
     260              : public:
     261              :         std::timed_mutex mutex_;                        ///< XMLRPC mutex
     262              :         std::unique_ptr<xmlrpc_c::serverAbyss> server;  ///< XMLRPC server
     263              : };
     264              : 
     265              : }  // namespace artdaq
     266              : 
     267              : namespace {
     268              : /// <summary>
     269              : /// Wrapper for XMLRPC environment construction/destruction
     270              : /// </summary>
     271              : class env_wrap
     272              : {
     273              : public:
     274            0 :         env_wrap() { xmlrpc_env_init(&this->env_c); };
     275            0 :         ~env_wrap() { xmlrpc_env_clean(&this->env_c); };
     276              :         xmlrpc_env env_c;  ///< XMLRPC Environment
     277              : private:
     278              :         env_wrap(env_wrap const&) = delete;
     279              :         env_wrap(env_wrap&&) = delete;
     280              :         env_wrap& operator=(env_wrap const&) = delete;
     281              :         env_wrap& operator=(env_wrap&&) = delete;
     282              : };
     283              : }  // namespace
     284              : static xmlrpc_c::paramList
     285            0 : pListFromXmlrpcArray(xmlrpc_value* const arrayP)
     286              : {
     287            0 :         env_wrap env;
     288            0 :         XMLRPC_ASSERT_ARRAY_OK(arrayP);
     289            0 :         unsigned int const arraySize = xmlrpc_array_size(&env.env_c, arrayP);
     290            0 :         assert(!env.env_c.fault_occurred);
     291            0 :         xmlrpc_c::paramList paramList(arraySize);
     292            0 :         for (unsigned int i = 0; i < arraySize; ++i)
     293              :         {
     294              :                 xmlrpc_value* arrayItemP;
     295            0 :                 xmlrpc_array_read_item(&env.env_c, arrayP, i, &arrayItemP);
     296            0 :                 assert(!env.env_c.fault_occurred);
     297            0 :                 paramList.add(xmlrpc_c::value(arrayItemP));
     298            0 :                 xmlrpc_DECREF(arrayItemP);
     299              :         }
     300            0 :         return paramList;
     301            0 : }
     302              : static xmlrpc_value*
     303            0 : c_executeMethod(xmlrpc_env* const envP,
     304              :                 xmlrpc_value* const paramArrayP,
     305              :                 void* const methodPtr,
     306              :                 void* const callInfoPtr)
     307              : {
     308            0 :         auto* const methodP(static_cast<xmlrpc_c::method*>(methodPtr));
     309            0 :         xmlrpc_c::paramList const paramList(pListFromXmlrpcArray(paramArrayP));
     310            0 :         auto* const callInfoP(static_cast<xmlrpc_c::callInfo*>(callInfoPtr));
     311              :         xmlrpc_value* retval;
     312            0 :         retval = nullptr;  // silence used-before-set warning
     313              :         try
     314              :         {
     315            0 :                 xmlrpc_c::value result;
     316              :                 try
     317              :                 {
     318            0 :                         auto* const method2P(dynamic_cast<xmlrpc_c::method2*>(methodP));
     319            0 :                         if (method2P != nullptr)
     320              :                         {
     321            0 :                                 method2P->execute(paramList, callInfoP, &result);
     322              :                         }
     323              :                         else
     324              :                         {
     325            0 :                                 methodP->execute(paramList, &result);
     326              :                         }
     327              :                 }
     328            0 :                 catch (xmlrpc_c::fault const& fault)
     329              :                 {
     330            0 :                         xmlrpc_env_set_fault(envP, fault.getCode(),
     331            0 :                                              fault.getDescription().c_str());
     332            0 :                 }
     333            0 :                 if (envP->fault_occurred == 0)
     334              :                 {
     335            0 :                         if (result.isInstantiated())
     336              :                         {
     337            0 :                                 retval = result.cValue();
     338              :                         }
     339              :                         else
     340              :                         {
     341            0 :                                 girerr::throwf(
     342              :                                     "Xmlrpc-c user's xmlrpc_c::method object's "
     343              :                                     "'execute method' failed to set the RPC result "
     344              :                                     "value.");
     345              :                         }
     346              :                 }
     347            0 :         }
     348            0 :         catch (std::exception const& e)
     349              :         {
     350            0 :                 xmlrpc_faultf(envP,
     351              :                               "Unexpected error executing code for "
     352              :                               "particular method, detected by Xmlrpc-c "
     353              :                               "method registry code.  Method did not "
     354              :                               "fail; rather, it did not complete at all.  %s",
     355            0 :                               e.what());
     356            0 :         }
     357            0 :         catch (...)
     358              :         {
     359            0 :                 xmlrpc_env_set_fault(envP, XMLRPC_INTERNAL_ERROR,
     360              :                                      "Unexpected error executing code for "
     361              :                                      "particular method, detected by Xmlrpc-c "
     362              :                                      "method registry code.  Method did not "
     363              :                                      "fail; rather, it did not complete at all.");
     364            0 :         }
     365            0 :         return retval;
     366            0 : }
     367              : 
     368              : namespace artdaq {
     369              : /**
     370              :  * \brief Write an exception message
     371              :  * \param er A std::runtime_error to print
     372              :  * \param helpText Additional information about the exception context. Default: "execute request"
     373              :  * \return Exception message
     374              :  */
     375            0 : std::string exception_msg(const std::runtime_error& er,
     376              :                           const std::string& helpText = "execute request")
     377              : {
     378            0 :         std::string msg("Exception when trying to ");
     379            0 :         msg.append(helpText);
     380            0 :         msg.append(": ");
     381            0 :         msg.append(er.what());  // std::string(er.what ()).substr (2);
     382            0 :         if (msg[msg.size() - 1] == '\n')
     383              :         {
     384            0 :                 msg.erase(msg.size() - 1);
     385              :         }
     386            0 :         return msg;
     387            0 : }
     388              : 
     389              : /**
     390              :  * \brief Write an exception message
     391              :  * \param er An art::Exception to print
     392              :  * \param helpText Additional information abou the exception context
     393              :  * \return Exception message
     394              :  */
     395            0 : std::string exception_msg(const art::Exception& er,
     396              :                           const std::string& helpText)
     397              : {
     398            0 :         std::string msg("Exception when trying to ");
     399            0 :         msg.append(helpText);
     400            0 :         msg.append(": ");
     401            0 :         msg.append(er.what());
     402            0 :         if (msg[msg.size() - 1] == '\n')
     403              :         {
     404            0 :                 msg.erase(msg.size() - 1);
     405              :         }
     406            0 :         return msg;
     407            0 : }
     408              : 
     409              : /**
     410              :  * \brief Write an exception message
     411              :  * \param er A cet::exception to print
     412              :  * \param helpText Additional information abou the exception context
     413              :  * \return Exception message
     414              :  */
     415            0 : std::string exception_msg(const cet::exception& er,
     416              :                           const std::string& helpText)
     417              : {
     418            0 :         std::string msg("Exception when trying to ");
     419            0 :         msg.append(helpText);
     420            0 :         msg.append(": ");
     421            0 :         msg.append(er.what());
     422            0 :         if (msg[msg.size() - 1] == '\n')
     423              :         {
     424            0 :                 msg.erase(msg.size() - 1);
     425              :         }
     426            0 :         return msg;
     427            0 : }
     428              : 
     429              : /**
     430              :  * \brief Write an exception message
     431              :  * \param er A boost::exception to print
     432              :  * \param helpText Additional information abou the exception context
     433              :  * \return Exception message
     434              :  */
     435            0 : std::string exception_msg(const boost::exception& er,
     436              :                           const std::string& helpText)
     437              : {
     438            0 :         std::string msg("Exception when trying to ");
     439            0 :         msg.append(helpText);
     440            0 :         msg.append(": ");
     441            0 :         msg.append(boost::diagnostic_information(er));
     442            0 :         if (msg[msg.size() - 1] == '\n') msg.erase(msg.size() - 1);
     443            0 :         return msg;
     444            0 : }
     445              : /**
     446              :  * \brief Write an exception message
     447              :  * \param er A std::exception to print
     448              :  * \param helpText Additional information abou the exception context
     449              :  * \return Exception message
     450              :  */
     451            0 : std::string exception_msg(const std::exception& er,
     452              :                           const std::string& helpText)
     453              : {
     454            0 :         std::string msg("Exception when trying to ");
     455            0 :         msg.append(helpText);
     456            0 :         msg.append(": ");
     457            0 :         msg.append(er.what());
     458            0 :         if (msg[msg.size() - 1] == '\n') msg.erase(msg.size() - 1);
     459            0 :         return msg;
     460            0 : }
     461              : 
     462              : /**
     463              :  * \brief Write an exception message
     464              :  * \param erText A std::string to print
     465              :  * \param helpText Additional information abou the exception context
     466              :  * \return Exception message
     467              :  */
     468            0 : std::string exception_msg(const std::string& erText,
     469              :                           const std::string& helpText)
     470              : {
     471            0 :         std::string msg("Exception when trying to ");
     472            0 :         msg.append(helpText);
     473            0 :         msg.append(": ");
     474            0 :         msg.append(erText);
     475            0 :         if (msg[msg.size() - 1] == '\n')
     476              :         {
     477            0 :                 msg.erase(msg.size() - 1);
     478              :         }
     479            0 :         return msg;
     480            0 : }
     481              : 
     482              : /**
     483              :  * \brief The "cmd_" class serves as the base class for all artdaq's XML-RPC commands.
     484              :  *
     485              :  * JCF, 9/5/14
     486              :  *
     487              :  * The "cmd_" class serves as the base class for all artdaq's
     488              :  * XML-RPC commands, all of which use the code in the "execute()"
     489              :  * function; each specific command type deriving from cmd_ is
     490              :  * implemented in the execute_() function which execute() calls
     491              :  * (notice the underscore), and optionally sets the retvalP
     492              :  * parameter
     493              :  *
     494              :  * cmd_ contains a set of template functions, getParam<T>(), which
     495              :  * are designed to prevent implementors of derived classes from
     496              :  * having to worry about interfacing directly with xmlrpc_c's
     497              :  * parameter-getting functionality
     498              :  */
     499              : class cmd_ : public xmlrpc_c::method
     500              : {
     501              : public:
     502              :         // Can't seem to initialize "_signature" and "_help" in the initialization list...
     503              :         /**
     504              :          * \brief cmd_ Constructor
     505              :          * \param c xmlrpc_commander instance
     506              :          * \param signature  Signature of the command
     507              :          * \param description Description of the command
     508              :          */
     509            0 :         cmd_(xmlrpc_commander& c, const std::string& signature, const std::string& description)
     510            0 :             : _c(c)
     511              :         {
     512            0 :                 _signature = signature;
     513            0 :                 _help = description;
     514            0 :         }
     515              : 
     516              :         /**
     517              :          * \brief Execute trhe command with the given parameters
     518              :          * \param paramList List of parameters for the command (i.e. a fhicl string for init transitions)
     519              :          * \param retvalP Pointer to the return value (usually a string describing result of command)
     520              :          */
     521              :         void execute(const xmlrpc_c::paramList& paramList, xmlrpc_c::value* retvalP) final;
     522              : 
     523              : protected:
     524              :         xmlrpc_commander& _c;  ///< The xmlrpc_commander instance that the command will be sent to
     525              : 
     526              :         /**
     527              :          * \brief "execute_" is a wrapper function around the call to the commandable object's function
     528              :          * \param retvalP Pointer to the return value (usually a string describing result of command)
     529              :          * \return Whether the command succeeded
     530              :          */
     531              :         virtual bool execute_(const xmlrpc_c::paramList&, xmlrpc_c::value* retvalP) = 0;
     532              : 
     533              :         /**
     534              :          * \brief Get a parameter from the parameter list
     535              :          * \tparam T Type of the parameter
     536              :          * \param paramList The parameter list
     537              :          * \param index Index of the parameter in the parameter list
     538              :          * \return The requested parameter
     539              :          *
     540              :          * Template specilization is used to provide valid overloads
     541              :          */
     542              :         template<typename T>
     543              :         T getParam(const xmlrpc_c::paramList& paramList, int index);
     544              : 
     545              :         /**
     546              :          * \brief Get a parameter from the parameter list, returning a default value if not found at specified location
     547              :          * \tparam T Type of the parameter
     548              :          * \param paramList The parameter list
     549              :          * \param index Index of the parameter in the parameter list
     550              :          * \param default_value Default value to return if exception retrieving parameter
     551              :          * \return The requested parameter, or the default value if there was an exception retrieving the parameter
     552              :          *
     553              :          * JCF, 9/5/14
     554              :          *
     555              :          * Here, if getParam throws an exception due to a lack of an
     556              :          * existing parameter, swallow the exception and return the
     557              :          * default value passed to the function
     558              :          *
     559              :          * Surprisingly, if an invalid index is supplied, although getParam
     560              :          * throws an exception that exception is neither xmlrpc_c's
     561              :          * girerr:error nor boost::bad_lexical_cast. Although it's less than
     562              :          * ideal, we'll swallow almost all exceptions in the call to
     563              :          * getParam, as an invalid index value simply means the user wishes
     564              :          * to employ the default_value. I say "almost" because the only
     565              :          * exception we don't swallow here is if an invalid parameter type
     566              :          * "T" was supplied
     567              :          */
     568              :         template<typename T>
     569              :         T getParam(const xmlrpc_c::paramList& paramList, int index, T default_value);
     570              : };
     571              : 
     572              : // Users are only allowed to call getParam for predefined types; see
     573              : // template specializations below this default function
     574              : 
     575              : template<typename T>
     576              : T cmd_::getParam(const xmlrpc_c::paramList& /*unused*/, int /*unused*/)
     577              : {
     578              :         TLOG(TLVL_ERROR) << "Error in cmd_::getParam(): value type not supported";
     579              :         throw cet::exception("cmd_") << "Error in cmd_::getParam(): value type not supported" << std::endl;  // NOLINT(cert-err60-cpp)
     580              : }
     581              : 
     582              : /**
     583              :  * \brief Get a parameter from the parameter list
     584              :  * \param paramList The parameter list
     585              :  * \param index Index of the parameter in the parameter list
     586              :  * \return The requested parameter
     587              :  *
     588              :  * This specialized cmd_getParam for the uint64_t type
     589              :  */
     590              : template<>
     591            0 : uint64_t cmd_::getParam<uint64_t>(const xmlrpc_c::paramList& paramList, int index)
     592              : {
     593            0 :         TLOG(TLVL_DEBUG + 33) << "Getting parameter " << index << " from list as uint64_t.";
     594              :         try
     595              :         {
     596            0 :                 TLOG(TLVL_DEBUG + 33) << "Param value: " << paramList.getI8(index);
     597            0 :                 return static_cast<uint64_t>(paramList.getI8(index));
     598              :         }
     599            0 :         catch (...)
     600              :         {
     601            0 :                 TLOG(TLVL_DEBUG + 33) << "Param value (int): " << paramList.getInt(index);
     602            0 :                 return static_cast<uint64_t>(paramList.getInt(index));
     603            0 :         }
     604              : }
     605              : 
     606              : /**
     607              :  * \brief Get a parameter from the parameter list
     608              :  * \param paramList The parameter list
     609              :  * \param index Index of the parameter in the parameter list
     610              :  * \return The requested parameter
     611              :  *
     612              :  * This specialized cmd_getParam for the uint64_t type
     613              :  */
     614              : template<>
     615            0 : uint32_t cmd_::getParam<uint32_t>(const xmlrpc_c::paramList& paramList, int index)
     616              : {
     617            0 :         TLOG(TLVL_DEBUG + 33) << "Getting parameter " << index << " from list as uint32_t.";
     618            0 :         TLOG(TLVL_DEBUG + 33) << "Param value: " << paramList.getInt(index);
     619            0 :         return static_cast<uint32_t>(paramList.getInt(index));
     620              : }
     621              : 
     622              : /**
     623              :  * \brief Get a parameter from the parameter list
     624              :  * \param paramList The parameter list
     625              :  * \param index Index of the parameter in the parameter list
     626              :  * \return The requested parameter
     627              :  *
     628              :  * This specialized cmd_getParam for the std::string type
     629              :  */
     630              : template<>
     631            0 : std::string cmd_::getParam<std::string>(const xmlrpc_c::paramList& paramList, int index)
     632              : {
     633            0 :         TLOG(TLVL_DEBUG + 33) << "Getting parameter " << index << " from list as string.";
     634            0 :         TLOG(TLVL_DEBUG + 33) << "Param value: " << paramList.getString(index);
     635            0 :         return static_cast<std::string>(paramList.getString(index));
     636              : }
     637              : 
     638              : /**
     639              :  * \brief Get a parameter from the parameter list
     640              :  * \param paramList The parameter list
     641              :  * \param index Index of the parameter in the parameter list
     642              :  * \return The requested parameter
     643              :  *
     644              :  * This specialized cmd_getParam for the art::RunID type
     645              :  */
     646              : template<>
     647            0 : art::RunID cmd_::getParam<art::RunID>(const xmlrpc_c::paramList& paramList, int index)
     648              : {
     649            0 :         TLOG(TLVL_DEBUG + 33) << "Getting parameter " << index << " from list as Run Number.";
     650              :         art::RunNumber_t run_number;
     651              :         try
     652              :         {
     653            0 :                 TLOG(TLVL_DEBUG + 33) << "Param value: " << paramList.getInt(index);
     654            0 :                 run_number = art::RunNumber_t(paramList.getInt(index));
     655              :         }
     656            0 :         catch (...)
     657              :         {
     658            0 :                 TLOG(TLVL_DEBUG + 33) << "Parameter is not an int. Trying string...";
     659              : 
     660            0 :                 auto runNumber = paramList.getString(index);
     661            0 :                 TLOG(TLVL_DEBUG + 33) << "Got run number string " << runNumber;
     662            0 :                 run_number = art::RunNumber_t(std::stoi(runNumber));
     663            0 :         }
     664              : 
     665            0 :         art::RunID run_id(run_number);
     666            0 :         return run_id;
     667              : }
     668              : 
     669              : /**
     670              :  * \brief Get a parameter from the parameter list
     671              :  * \param paramList The parameter list
     672              :  * \param index Index of the parameter in the parameter list
     673              :  * \return The requested parameter
     674              :  *
     675              :  * This specialized cmd_getParam for the fhicl::ParameterSet type
     676              :  */
     677              : template<>
     678            0 : fhicl::ParameterSet cmd_::getParam<fhicl::ParameterSet>(const xmlrpc_c::paramList& paramList, int index)
     679              : {
     680            0 :         TLOG(TLVL_DEBUG + 33) << "Getting parameter " << index << " from list as ParameterSet.";
     681            0 :         TLOG(TLVL_DEBUG + 33) << "Param value: " << paramList.getString(index);
     682            0 :         std::string configString = std::string(paramList.getString(index));
     683            0 :         TLOG(TLVL_DEBUG + 32) << "Loading Parameter Set from string: " << configString << std::endl;
     684            0 :         fhicl::ParameterSet pset;
     685              : 
     686              :         try
     687              :         {
     688            0 :                 pset = fhicl::ParameterSet::make(configString);
     689              :         }
     690            0 :         catch (const fhicl::exception& e)
     691              :         {
     692            0 :                 if (getenv("FHICL_FILE_PATH") == nullptr)
     693              :                 {
     694            0 :                         TLOG(TLVL_ERROR) << "INFO: environment variable FHICL_FILE_PATH was not set. Using \".\"";
     695            0 :                         std::cerr << "INFO: environment variable FHICL_FILE_PATH was not set. Using \".\"" << std::endl;
     696            0 :                         setenv("FHICL_FILE_PATH", ".", 0);
     697              :                 }
     698            0 :                 cet::filepath_lookup_after1 lookup_policy("FHICL_FILE_PATH");
     699            0 :                 pset = fhicl::ParameterSet::make(configString, lookup_policy);
     700            0 :         }
     701              : 
     702            0 :         TLOG(TLVL_INFO) << "Parameter Set Loaded." << std::endl;
     703            0 :         return pset;
     704            0 : }
     705              : 
     706              : template<typename T>
     707            0 : T cmd_::getParam(const xmlrpc_c::paramList& paramList, int index,
     708              :                  T default_value)
     709              : {
     710            0 :         T val = default_value;
     711              : 
     712            0 :         if (static_cast<unsigned>(index) < paramList.size())
     713              :         {
     714            0 :                 val = getParam<T>(paramList, index);
     715              :         }
     716            0 :         return val;
     717              : }
     718              : 
     719            0 : void cmd_::execute(const xmlrpc_c::paramList& paramList, xmlrpc_c::value* const retvalP)
     720              : {
     721            0 :         TLOG(TLVL_DEBUG + 33) << "Received Request to " << _help << ", attempting to get lock";
     722            0 :         std::unique_lock<std::timed_mutex> lk(_c.mutex_, std::defer_lock);
     723            0 :         auto ret = lk.try_lock_for(std::chrono::milliseconds(250));
     724              : 
     725            0 :         if (ret && lk.owns_lock())
     726              :         {
     727              :                 try
     728              :                 {
     729              :                         // JCF, 9/4/14
     730              : 
     731              :                         // Assuming the execute_ function returns true, then if the
     732              :                         // retvalP argument was untouched, assign it the string
     733              :                         // "Success"
     734              : 
     735              :                         // See
     736              :                         // http://xmlrpc-c.sourceforge.net/doc/libxmlrpc++.html#isinstantiated
     737              :                         // for more on the concept of instantiation in xmlrpc_c::value objects
     738              : 
     739            0 :                         if (execute_(paramList, retvalP))
     740              :                         {
     741            0 :                                 if (!retvalP->isInstantiated())
     742              :                                 {
     743            0 :                                         *retvalP = xmlrpc_c::value_string("Success");
     744              :                                 }
     745              :                         }
     746              :                         else
     747              :                         {
     748            0 :                                 std::string problemReport = _c._commandable.report("transition_status");
     749            0 :                                 *retvalP = xmlrpc_c::value_string(problemReport);
     750            0 :                         }
     751              :                 }
     752            0 :                 catch (std::runtime_error& er)
     753              :                 {
     754            0 :                         std::string msg = exception_msg(er, _help);
     755            0 :                         *retvalP = xmlrpc_c::value_string(msg);
     756            0 :                         TLOG(TLVL_ERROR) << msg;
     757            0 :                 }
     758            0 :                 catch (art::Exception& er)
     759              :                 {
     760            0 :                         std::string msg = exception_msg(er, _help);
     761            0 :                         *retvalP = xmlrpc_c::value_string(msg);
     762            0 :                         TLOG(TLVL_ERROR) << msg;
     763            0 :                 }
     764            0 :                 catch (cet::exception& er)
     765              :                 {
     766            0 :                         std::string msg = exception_msg(er, _help);
     767            0 :                         *retvalP = xmlrpc_c::value_string(msg);
     768            0 :                         TLOG(TLVL_ERROR) << msg;
     769            0 :                 }
     770            0 :                 catch (boost::exception& er)
     771              :                 {
     772            0 :                         std::string msg = exception_msg(er, _help);
     773            0 :                         *retvalP = xmlrpc_c::value_string(msg);
     774            0 :                         TLOG(TLVL_ERROR) << msg;
     775            0 :                 }
     776            0 :                 catch (std::exception& er)
     777              :                 {
     778            0 :                         std::string msg = exception_msg(er, _help);
     779            0 :                         *retvalP = xmlrpc_c::value_string(msg);
     780            0 :                         TLOG(TLVL_ERROR) << msg;
     781            0 :                 }
     782            0 :                 catch (...)
     783              :                 {
     784            0 :                         std::string msg = exception_msg("Unknown exception (not from std, boost, cet, or art)", _help);
     785            0 :                         *retvalP = xmlrpc_c::value_string(msg);
     786            0 :                         TLOG(TLVL_ERROR) << msg;
     787            0 :                 }
     788              : 
     789            0 :                 lk.unlock();
     790              :         }
     791              :         else
     792              :         {
     793            0 :                 TLOG(TLVL_ERROR) << "Unable to get lock while trying to " << _help << ", returning busy";
     794            0 :                 *retvalP = xmlrpc_c::value_string("busy");
     795              :         }
     796            0 : }
     797              : 
     798              : //////////////////////////////////////////////////////////////////////
     799              : 
     800              : // JCF, 9/5/14
     801              : 
     802              : // The three "init" transitions all take a FHiCL parameter list, and
     803              : // optionally a timeout and a timestamp; thus we can kill three birds
     804              : // with one stone in the GENERATE_INIT_TRANSITION macro
     805              : 
     806              : #define GENERATE_INIT_TRANSITION(NAME, CALL, DESCRIPTION)                                                                                                                 \
     807              :         /** Command class representing an init transition */                                                                                                                  \
     808              :         class NAME##_ : public cmd_                                                                                                                                           \
     809              :         {                                                                                                                                                                     \
     810              :         public:                                                                                                                                                               \
     811              :                 /** Command class Constructor                                                                                                                                     \
     812              :                  * \param c xmlrpc_commander to send parsed command to                                                                                                            \
     813              :                  */                                                                                                                                                               \
     814              :                 explicit NAME##_(xmlrpc_commander& c) : cmd_(c, "s:sII", DESCRIPTION)                                                                                             \
     815              :                 {}                                                                                                                                                                \
     816              :                                                                                                                                                                           \
     817              :                 /** Default timeout for command */                                                                                                                                \
     818              :                 static const uint64_t defaultTimeout = 45;                                                                                                                        \
     819              :                 /** Default timestamp for Command */                                                                                                                              \
     820              :                 static const uint64_t defaultTimestamp = std::numeric_limits<const uint64_t>::max();                                                                              \
     821              :                                                                                                                                                                           \
     822              :         private:                                                                                                                                                              \
     823              :                 bool execute_(const xmlrpc_c::paramList& paramList, xmlrpc_c::value* const retvalP)                                                                               \
     824              :                 {                                                                                                                                                                 \
     825              :                         fhicl::ParameterSet ps;                                                                                                                                       \
     826              :                         try                                                                                                                                                           \
     827              :                         {                                                                                                                                                             \
     828              :                                 ps = getParam<fhicl::ParameterSet>(paramList, 0);                                                                                                         \
     829              :                         }                                                                                                                                                             \
     830              :                         catch (...)                                                                                                                                                   \
     831              :                         {                                                                                                                                                             \
     832              :                                 *retvalP = xmlrpc_c::value_string("Error: The " #NAME " message requires a single argument that is a string containing the initialization ParameterSet"); \
     833              :                                 return true;                                                                                                                                              \
     834              :                         }                                                                                                                                                             \
     835              :                                                                                                                                                                           \
     836              :                         return _c._commandable.CALL(ps,                                                                                                                               \
     837              :                                                     getParam<uint64_t>(paramList, 1, defaultTimeout),                                                                                 \
     838              :                                                     getParam<uint64_t>(paramList, 2, defaultTimestamp));                                                                              \
     839              :                 }                                                                                                                                                                 \
     840              :         };
     841              : 
     842            0 : GENERATE_INIT_TRANSITION(init, initialize, "initialize the program")
     843              : 
     844            0 : GENERATE_INIT_TRANSITION(soft_init, soft_initialize, "initialize software components in the program")
     845              : 
     846            0 : GENERATE_INIT_TRANSITION(reinit, reinitialize, "re-initialize the program")
     847              : 
     848              : #undef GENERATE_INIT_TRANSITION
     849              : 
     850              : //////////////////////////////////////////////////////////////////////
     851              : 
     852              : /**
     853              :  * \brief Command class representing a start transition
     854              :  */
     855              : class start_ : public cmd_
     856              : {
     857              : public:
     858              :         /**
     859              :          * \brief start_ Command (cmd_ derived class) Constructor
     860              :          * \param c xmlrpc_commander instance to command
     861              :          */
     862            0 :         explicit start_(xmlrpc_commander& c)
     863            0 :             : cmd_(c, "s:iII", "start the run")
     864            0 :         {}
     865              : 
     866              :         /** Default timeout for command */
     867              :         static const uint64_t defaultTimeout = 45;
     868              :         /** Default timestamp for Command */
     869              :         static const uint64_t defaultTimestamp = std::numeric_limits<const uint64_t>::max();
     870              : 
     871              : private:
     872            0 :         bool execute_(xmlrpc_c::paramList const& paramList, xmlrpc_c::value* const retvalP) override
     873              :         {
     874              :                 try
     875              :                 {
     876            0 :                         getParam<art::RunID>(paramList, 0);
     877              :                 }
     878            0 :                 catch (...)
     879              :                 {
     880            0 :                         *retvalP = xmlrpc_c::value_string("Error: The start message requires the run number as an argument.");
     881            0 :                         return true;
     882            0 :                 }
     883              : 
     884            0 :                 return _c._commandable.start(getParam<art::RunID>(paramList, 0),
     885              :                                              getParam<uint64_t>(paramList, 1, defaultTimeout),
     886            0 :                                              getParam<uint64_t>(paramList, 2, defaultTimestamp));
     887              :         }
     888              : };
     889              : 
     890              : //////////////////////////////////////////////////////////////////////
     891              : 
     892              : // JCF, 9/5/14
     893              : 
     894              : // "pause", "resume" and "stop" all take an optional timeout and
     895              : // timestamp parameter, so we can generate them all with the
     896              : // GENERATE_TIMEOUT_TIMESTAMP_TRANSITION macro
     897              : 
     898              : #define GENERATE_TIMEOUT_TIMESTAMP_TRANSITION(NAME, CALL, DESCRIPTION, TIMEOUT)              \
     899              :         /** NAME ## _ Command class */                                                           \
     900              :         class NAME##_ : public cmd_                                                              \
     901              :         {                                                                                        \
     902              :         public:                                                                                  \
     903              :                 /** NAME ## _ Constructor                                                            \
     904              :                     \param c xmlrpc_commander to send transition commands to */                      \
     905              :                 NAME##_(xmlrpc_commander& c) : cmd_(c, "s:II", DESCRIPTION)                          \
     906              :                 {}                                                                                   \
     907              :                                                                                              \
     908              :                 /** Default timeout for command */                                                   \
     909              :                 static const uint64_t defaultTimeout = TIMEOUT;                                      \
     910              :                 /** Default timestamp for Command */                                                 \
     911              :                 static const uint64_t defaultTimestamp = std::numeric_limits<const uint64_t>::max(); \
     912              :                                                                                              \
     913              :         private:                                                                                 \
     914              :                 bool execute_(const xmlrpc_c::paramList& paramList, xmlrpc_c::value* const)          \
     915              :                 {                                                                                    \
     916              :                         return _c._commandable.CALL(getParam<uint64_t>(paramList, 0, defaultTimeout),    \
     917              :                                                     getParam<uint64_t>(paramList, 1, defaultTimestamp)); \
     918              :                 }                                                                                    \
     919              :         };
     920              : 
     921            0 : GENERATE_TIMEOUT_TIMESTAMP_TRANSITION(pause, pause, "pause the program", 45)
     922              : 
     923            0 : GENERATE_TIMEOUT_TIMESTAMP_TRANSITION(resume, resume, "resume the program", 45)
     924              : 
     925            0 : GENERATE_TIMEOUT_TIMESTAMP_TRANSITION(stop, stop, "stop the program", 45)
     926              : 
     927              : #undef GENERATE_TIMEOUT_TIMESTAMP_TRANSITION
     928              : 
     929              : /**
     930              :  * \brief shutdown_ Command class
     931              :  */
     932              : class shutdown_ : public cmd_
     933              : {
     934              : public:
     935              :         /**
     936              :          * \brief shutdown_ Constructor
     937              :          * \param c xmlrpc_commander to send transition commands to
     938              :          */
     939            0 :         shutdown_(xmlrpc_commander& c)
     940            0 :             : cmd_(c, "s:i", "shutdown the program")
     941            0 :         {}
     942              : 
     943              :         /** Default timeout for command */
     944              :         static const uint64_t defaultTimeout = 45;
     945              : 
     946              : private:
     947            0 :         bool execute_(const xmlrpc_c::paramList& paramList, xmlrpc_c::value* const /*retvalP*/) override
     948              :         {
     949            0 :                 auto ret = _c._commandable.shutdown(getParam<uint64_t>(paramList, 0, defaultTimeout));
     950              : 
     951              : #if 1
     952            0 :                 if (_c.server)
     953              :                 {
     954            0 :                         _c.server->terminate();
     955              :                 }
     956              : #endif
     957              : 
     958            0 :                 return ret;
     959              :         }
     960              : };
     961              : 
     962              : /**
     963              :  * \brief status_ Command class
     964              :  */
     965              : class status_ : public cmd_
     966              : {
     967              : public:
     968              :         /**
     969              :          * \brief status_ Constructor
     970              :          * \param c xmlrpc_commander to send transition commands to
     971              :          */
     972            0 :         status_(xmlrpc_commander& c)
     973            0 :             : cmd_(c, "s:n", "report the current state")
     974            0 :         {}
     975              : 
     976              : private:
     977            0 :         bool execute_(xmlrpc_c::paramList const& /*unused*/, xmlrpc_c::value* const retvalP) override
     978              :         {
     979            0 :                 *retvalP = xmlrpc_c::value_string(_c._commandable.status());
     980            0 :                 return true;
     981              :         }
     982              : };
     983              : 
     984              : /**
     985              :  * \brief report_ Command class
     986              :  */
     987              : class report_ : public cmd_
     988              : {
     989              : public:
     990              :         /**
     991              :          * \brief report_ Constructor
     992              :          * \param c xmlrpc_commander to send transition commands to
     993              :          */
     994            0 :         report_(xmlrpc_commander& c)
     995            0 :             : cmd_(c, "s:s", "report statistics")
     996            0 :         {}
     997              : 
     998              : private:
     999            0 :         bool execute_(xmlrpc_c::paramList const& paramList, xmlrpc_c::value* const retvalP) override
    1000              :         {
    1001              :                 try
    1002              :                 {
    1003            0 :                         getParam<std::string>(paramList, 0);
    1004              :                 }
    1005            0 :                 catch (...)
    1006              :                 {
    1007            0 :                         *retvalP = xmlrpc_c::value_string("Error: The report message requires a single argument that selects the type of statistics to be reported.");
    1008            0 :                         return true;
    1009            0 :                 }
    1010              : 
    1011            0 :                 *retvalP = xmlrpc_c::value_string(_c._commandable.report(getParam<std::string>(paramList, 0)));
    1012            0 :                 return true;
    1013              :         }
    1014              : };
    1015              : 
    1016              : /**
    1017              :  * \brief legal_commands_ Command class
    1018              :  */
    1019              : class legal_commands_ : public cmd_
    1020              : {
    1021              : public:
    1022              :         /**
    1023              :          * \brief legal_commands_ Constructor
    1024              :          * \param c xmlrpc_commander to send transition commands to
    1025              :          */
    1026            0 :         legal_commands_(xmlrpc_commander& c)
    1027            0 :             : cmd_(c, "s:n", "return the currently legal commands")
    1028            0 :         {}
    1029              : 
    1030              : private:
    1031            0 :         bool execute_(xmlrpc_c::paramList const& /*unused*/, xmlrpc_c::value* const retvalP) override
    1032              :         {
    1033            0 :                 std::vector<std::string> cmdList = _c._commandable.legal_commands();
    1034            0 :                 std::string resultString;
    1035              : 
    1036            0 :                 for (auto& cmd : cmdList)
    1037              :                 {
    1038            0 :                         resultString.append(cmd + " ");
    1039            0 :                         if (cmd == "shutdown")
    1040              :                         {
    1041            0 :                                 resultString.append(" reset");
    1042              :                         }
    1043              :                 }
    1044            0 :                 *retvalP = xmlrpc_c::value_string(resultString);
    1045              : 
    1046            0 :                 return true;
    1047            0 :         }
    1048              : };
    1049              : 
    1050              : /**
    1051              :  * \brief register_monitor_ Command class
    1052              :  */
    1053              : class register_monitor_ : public cmd_
    1054              : {
    1055              : public:
    1056              :         /**
    1057              :          * \brief register_monitor_ Constructor
    1058              :          * \param c xmlrpc_commander to send transition commands to
    1059              :          */
    1060            0 :         register_monitor_(xmlrpc_commander& c)
    1061            0 :             : cmd_(c, "s:s", "Get notified of a new monitor")
    1062            0 :         {}
    1063              : 
    1064              : private:
    1065            0 :         bool execute_(xmlrpc_c::paramList const& paramList, xmlrpc_c::value* const retvalP) override
    1066              :         {
    1067              :                 try
    1068              :                 {
    1069            0 :                         getParam<fhicl::ParameterSet>(paramList, 0);
    1070              :                 }
    1071            0 :                 catch (...)
    1072              :                 {
    1073            0 :                         *retvalP = xmlrpc_c::value_string("Error: The register_monitor command expects a string representing the FHiCL definition of a Transfer plugin");
    1074            0 :                         return true;
    1075            0 :                 }
    1076              : 
    1077            0 :                 *retvalP = xmlrpc_c::value_string(_c._commandable.register_monitor(getParam<fhicl::ParameterSet>(paramList, 0)));
    1078            0 :                 return true;
    1079              :         }
    1080              : };
    1081              : 
    1082              : /**
    1083              :  * \brief unregister_monitor_ Command class
    1084              :  */
    1085              : class unregister_monitor_ : public cmd_
    1086              : {
    1087              : public:
    1088              :         /**
    1089              :          * \brief unregister_monitor_ Constructor
    1090              :          * \param c xmlrpc_commander to send transition commands to
    1091              :          */
    1092            0 :         unregister_monitor_(xmlrpc_commander& c)
    1093            0 :             : cmd_(c, "s:s", "Remove a monitor")
    1094            0 :         {}
    1095              : 
    1096              : private:
    1097            0 :         bool execute_(xmlrpc_c::paramList const& paramList, xmlrpc_c::value* const retvalP) override
    1098              :         {
    1099              :                 try
    1100              :                 {
    1101            0 :                         getParam<std::string>(paramList, 0);
    1102              :                 }
    1103            0 :                 catch (...)
    1104              :                 {
    1105            0 :                         *retvalP = xmlrpc_c::value_string("Error: The unregister_monitor command expects a string representing the label of the monitor to be removed");
    1106            0 :                         return true;
    1107            0 :                 }
    1108              : 
    1109            0 :                 *retvalP = xmlrpc_c::value_string(_c._commandable.unregister_monitor(getParam<std::string>(paramList, 0)));
    1110            0 :                 return true;
    1111              :         }
    1112              : };
    1113              : 
    1114              : /**
    1115              :  * \brief trace_set_ Command class
    1116              :  */
    1117              : class trace_set_ : public cmd_
    1118              : {
    1119              : public:
    1120              :         /**
    1121              :          * \brief unregister_monitor_ Constructor
    1122              :          * \param c xmlrpc_commander to send transition commands to
    1123              :          */
    1124            0 :         trace_set_(xmlrpc_commander& c)
    1125            0 :             : cmd_(c, "s:ssI", "Set TRACE mask")
    1126            0 :         {}
    1127              : 
    1128              : private:
    1129            0 :         bool execute_(xmlrpc_c::paramList const& paramList, xmlrpc_c::value* const retvalP) override
    1130              :         {
    1131              :                 try
    1132              :                 {
    1133            0 :                         getParam<std::string>(paramList, 0);
    1134            0 :                         getParam<std::string>(paramList, 1);
    1135            0 :                         getParam<std::string>(paramList, 2);
    1136              :                 }
    1137            0 :                 catch (...)
    1138              :                 {
    1139            0 :                         *retvalP = xmlrpc_c::value_string("Error: The trace_set command expects a name (ALL for all), a mask type (M, S , or T), and a mask");
    1140            0 :                         return true;
    1141            0 :                 }
    1142              : 
    1143            0 :                 return _c._commandable.do_trace_set(getParam<std::string>(paramList, 0), getParam<std::string>(paramList, 1), getParam<std::string>(paramList, 2));
    1144              :         }
    1145              : };
    1146              : 
    1147              : /**
    1148              :  * \brief trace_get_ Command class
    1149              :  */
    1150              : class trace_get_ : public cmd_
    1151              : {
    1152              : public:
    1153              :         /**
    1154              :          * \brief trace_msgfacility_set_ Constructor
    1155              :          * \param c xmlrpc_commander to send transition commands to
    1156              :          */
    1157            0 :         trace_get_(xmlrpc_commander& c)
    1158            0 :             : cmd_(c, "s:s", "Get TRACE mask")
    1159            0 :         {}
    1160              : 
    1161              : private:
    1162            0 :         bool execute_(xmlrpc_c::paramList const& paramList, xmlrpc_c::value* const retvalP) override
    1163              :         {
    1164              :                 try
    1165              :                 {
    1166            0 :                         getParam<std::string>(paramList, 0);
    1167              :                 }
    1168            0 :                 catch (...)
    1169              :                 {
    1170            0 :                         *retvalP = xmlrpc_c::value_string("Error: The trace_get command expects a name (ALL for all)");
    1171            0 :                         return true;
    1172            0 :                 }
    1173              : 
    1174            0 :                 *retvalP = xmlrpc_c::value_string(_c._commandable.do_trace_get(getParam<std::string>(paramList, 0)));
    1175            0 :                 return true;
    1176              :         }
    1177              : };
    1178              : 
    1179              : /**
    1180              :  * \brief meta_command_ Command class
    1181              :  */
    1182              : class meta_command_ : public cmd_
    1183              : {
    1184              : public:
    1185              :         /**
    1186              :          * \brief meta_command_ Constructor
    1187              :          * \param c xmlrpc_commander to send transition commands to
    1188              :          */
    1189            0 :         meta_command_(xmlrpc_commander& c)
    1190            0 :             : cmd_(c, "s:ss", "Run custom command")
    1191            0 :         {}
    1192              : 
    1193              : private:
    1194            0 :         bool execute_(xmlrpc_c::paramList const& paramList, xmlrpc_c::value* const retvalP) override
    1195              :         {
    1196              :                 try
    1197              :                 {
    1198            0 :                         getParam<std::string>(paramList, 0);
    1199            0 :                         getParam<std::string>(paramList, 1);
    1200              :                 }
    1201            0 :                 catch (...)
    1202              :                 {
    1203            0 :                         *retvalP = xmlrpc_c::value_string("Error: The meta_command command expects a string command and a string argument");
    1204            0 :                         return true;
    1205            0 :                 }
    1206              : 
    1207            0 :                 return _c._commandable.do_meta_command(getParam<std::string>(paramList, 0), getParam<std::string>(paramList, 1));
    1208              :         }
    1209              : };
    1210              : 
    1211              : /**
    1212              :  * \brief rollover_subrun_ Command class
    1213              :  */
    1214              : class rollover_subrun_ : public cmd_
    1215              : {
    1216              : public:
    1217              :         /**
    1218              :          * \brief shutdown_ Constructor
    1219              :          * \param c xmlrpc_commander to send transition commands to
    1220              :          */
    1221            0 :         rollover_subrun_(xmlrpc_commander& c)
    1222            0 :             : cmd_(c, "s:Ii", "create a new subrun")
    1223            0 :         {}
    1224              : 
    1225              :         static const uint64_t defaultSequenceID = 0xFFFFFFFFFFFFFFFF;  ///< Default Sequence ID for command
    1226              :         static const uint32_t defaultSubrunNumber = 1;                 ///< Default subrun number for command
    1227              : 
    1228              : private:
    1229            0 :         bool execute_(const xmlrpc_c::paramList& paramList, xmlrpc_c::value* const /*retvalP*/) override
    1230              :         {
    1231            0 :                 auto ret = _c._commandable.do_rollover_subrun(getParam<uint64_t>(paramList, 0, defaultSequenceID), getParam<uint32_t>(paramList, 1, defaultSubrunNumber));
    1232            0 :                 return ret;
    1233              :         }
    1234              : };
    1235              : 
    1236              : /**
    1237              :  * \brief add_config_archive_entry_ Command class
    1238              :  */
    1239              : class add_config_archive_entry_ : public cmd_
    1240              : {
    1241              : public:
    1242              :         /**
    1243              :          * \brief add_config_archive_entry_ Constructor
    1244              :          * \param c xmlrpc_commander to send transition commands to
    1245              :          */
    1246            0 :         add_config_archive_entry_(xmlrpc_commander& c)
    1247            0 :             : cmd_(c, "s:ss", "Add an entry to the configuration archive list")
    1248            0 :         {}
    1249              : 
    1250              : private:
    1251            0 :         bool execute_(xmlrpc_c::paramList const& paramList, xmlrpc_c::value* const retvalP) override
    1252              :         {
    1253              :                 try
    1254              :                 {
    1255            0 :                         getParam<std::string>(paramList, 0);
    1256            0 :                         getParam<std::string>(paramList, 1);
    1257              :                 }
    1258            0 :                 catch (...)
    1259              :                 {
    1260            0 :                         *retvalP = xmlrpc_c::value_string("Error: The add_config_archive_entry command expects a string key and a string value");
    1261            0 :                         return true;
    1262            0 :                 }
    1263              : 
    1264            0 :                 return _c._commandable.do_add_config_archive_entry(getParam<std::string>(paramList, 0), getParam<std::string>(paramList, 1));
    1265              :         }
    1266              : };
    1267              : 
    1268              : /**
    1269              :  * \brief clear_config_archive_ Command class
    1270              :  */
    1271              : class clear_config_archive_ : public cmd_
    1272              : {
    1273              : public:
    1274              :         /**
    1275              :          * \brief clear_config_archive_ Constructor
    1276              :          * \param c xmlrpc_commander to send transition commands to
    1277              :          */
    1278            0 :         clear_config_archive_(xmlrpc_commander& c)
    1279            0 :             : cmd_(c, "s:n", "Clear the configuration archive list")
    1280            0 :         {}
    1281              : 
    1282              : private:
    1283            0 :         bool execute_(xmlrpc_c::paramList const& /*unused*/, xmlrpc_c::value* const /*retvalP*/) override
    1284              :         {
    1285            0 :                 return _c._commandable.do_clear_config_archive();
    1286              :         }
    1287              : };
    1288              : 
    1289              : // JCF, 9/4/14
    1290              : 
    1291              : // Not sure if anyone was planning to resurrect this code by changing
    1292              : // the preprocessor decision; as such, I'll leave it in for now...
    1293              : 
    1294              : #if 0
    1295              :         class shutdown_ : public xmlrpc_c::registry::shutdown
    1296              :         {
    1297              :         public:
    1298              :                 shutdown_(xmlrpc_c::serverAbyss *server) : _server(server) {}
    1299              : 
    1300              :                 virtual void doit(const std::string& paramString, void*) const
    1301              :                 {
    1302              :                         TLOG(TLVL_INFO) << "A shutdown command was sent "
    1303              :                                 << "with parameter "
    1304              :                                 << paramString << "\"";
    1305              :                         _server->terminate();
    1306              :                 }
    1307              :         private:
    1308              :                 xmlrpc_c::serverAbyss *_server;
    1309              :         };
    1310              : #endif
    1311              : 
    1312            0 : xmlrpc_commander::xmlrpc_commander(const fhicl::ParameterSet& ps, artdaq::Commandable& commandable)
    1313              :     : CommanderInterface(ps, commandable)
    1314            0 :     , port_(ps.get<int>("id", 0))
    1315            0 :     , serverUrl_(ps.get<std::string>("server_url", ""))
    1316            0 :     , server(nullptr)
    1317              : {
    1318            0 :         if (serverUrl_.empty())
    1319              :         {
    1320              :                 char hostname[HOST_NAME_MAX];
    1321            0 :                 gethostname(hostname, HOST_NAME_MAX);
    1322            0 :                 serverUrl_ = std::string(hostname);
    1323              :         }
    1324            0 :         if (serverUrl_.find("http") == std::string::npos)
    1325              :         {
    1326            0 :                 serverUrl_ = "http://" + serverUrl_;
    1327              :         }
    1328            0 :         if (serverUrl_.find(std::to_string(port_)) == std::string::npos && serverUrl_.find(':', 7) == std::string::npos)
    1329              :         {
    1330            0 :                 serverUrl_ = serverUrl_ + ":" + std::to_string(port_);
    1331              :         }
    1332            0 :         if (serverUrl_.find("RPC2") == std::string::npos)
    1333              :         {
    1334            0 :                 serverUrl_ = serverUrl_ + "/RPC2";
    1335              :         }
    1336            0 :         TLOG(TLVL_INFO) << "XMLRPC COMMANDER CONSTRUCTOR: Port: " << port_ << ", Server Url: " << serverUrl_;
    1337            0 : }
    1338              : 
    1339            0 : void xmlrpc_commander::run_server()
    1340              : try
    1341              : {
    1342              :         // std::cout << "XMLRPC_COMMANDER RUN_SERVER CALLED!" << std::endl;
    1343            0 :         xmlrpc_c::registry registry;
    1344              :         struct xmlrpc_method_info3 methodInfo;
    1345            0 :         memset(&methodInfo, 0, sizeof(methodInfo));
    1346              : 
    1347              :         /*#define register_method(m) \
    1348              :             //  xmlrpc_c::methodPtr const ptr_ ## m(new m ## _(*this));\
    1349              :                registry.addMethod ("daq." #m, ptr_ ## m) */
    1350              : #define register_method(m) register_method2(m, 0x400000)
    1351              : 
    1352              :         xmlrpc_env env;  // xmlrpc_env_init(&env);
    1353              :         xmlrpc_registry*** c_registryPPP;
    1354            0 :         c_registryPPP = reinterpret_cast<xmlrpc_registry***>(reinterpret_cast<char*>(&registry) + sizeof(girmem::autoObject));  // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast,cppcoreguidelines-pro-bounds-pointer-arithmetic)
    1355              : 
    1356              : #define register_method2(m, ss)                                                  \
    1357              :         xmlrpc_c::method* ptr_##m(dynamic_cast<xmlrpc_c::method*>(new m##_(*this))); \
    1358              :         std::string m##signature = ptr_##m->signature(), m##help = ptr_##m->help();  \
    1359              :         methodInfo.methodName = "daq." #m;                                           \
    1360              :         methodInfo.methodFunction = &c_executeMethod;                                \
    1361              :         methodInfo.serverInfo = ptr_##m;                                             \
    1362              :         methodInfo.stackSize = ss;                                                   \
    1363              :         methodInfo.signatureString = &m##signature[0];                               \
    1364              :         methodInfo.help = &m##help[0];                                               \
    1365              :         xmlrpc_env_init(&env);                                                       \
    1366              :         xmlrpc_registry_add_method3(&env, **c_registryPPP, &methodInfo);             \
    1367              :         if (env.fault_occurred) throw(girerr::error(env.fault_string));              \
    1368              :         xmlrpc_env_clean(&env)
    1369              : 
    1370              : #define unregister_method(m) delete ptr_##m;
    1371              : 
    1372            0 :         register_method2(init, 0x200000);
    1373            0 :         register_method(soft_init);
    1374            0 :         register_method(reinit);
    1375            0 :         register_method(start);
    1376            0 :         register_method(status);
    1377            0 :         register_method(report);
    1378            0 :         register_method(stop);
    1379            0 :         register_method(pause);
    1380            0 :         register_method(resume);
    1381            0 :         register_method(register_monitor);
    1382            0 :         register_method(unregister_monitor);
    1383            0 :         register_method(legal_commands);
    1384            0 :         register_method(trace_set);
    1385            0 :         register_method(trace_get);
    1386            0 :         register_method(meta_command);
    1387            0 :         register_method(rollover_subrun);
    1388            0 :         register_method(add_config_archive_entry);
    1389            0 :         register_method(clear_config_archive);
    1390              : 
    1391            0 :         register_method(shutdown);
    1392              : 
    1393              :         // alias "daq.reset" to the internal shutdown transition
    1394            0 :         xmlrpc_c::methodPtr const ptr_reset(new shutdown_(*this));
    1395            0 :         registry.addMethod("daq.reset", ptr_reset);
    1396              : 
    1397              : #undef register_method
    1398              : 
    1399              :         // JCF, 6/3/15
    1400              : 
    1401              :         // In the following code, I configure a socket to have the
    1402              :         // SO_REUSEADDR option so that once an artdaq process closes, the
    1403              :         // port it was communicating on becomes immediately available
    1404              :         // (desirable if, say, the DAQ program is terminated and then
    1405              :         // immediately restarted)
    1406              : 
    1407              :         // Much of the following code is cribbed from
    1408              :         // http://fossies.org/linux/freeswitch/libs/xmlrpc-c/src/cpp/test/server_abyss.cpp
    1409              : 
    1410              :         // Below, "0" is the default protocol (in this case, given the IPv4
    1411              :         // Protocol Family (PF_INET) and the SOCK_STREAM communication
    1412              :         // method)
    1413              : 
    1414            0 :         XMLRPC_SOCKET socket_file_descriptor = socket(PF_INET, SOCK_STREAM, 0);
    1415              : 
    1416            0 :         if (socket_file_descriptor < 0)
    1417              :         {
    1418            0 :                 TLOG(TLVL_ERROR) << "Problem with the socket() call; C-style errno == " << errno << " (" << strerror(errno) << ")";
    1419            0 :                 throw cet::exception("xmlrpc_commander::run") << "Problem with the socket() call; C-style errno == " << errno << " (" << strerror(errno) << ")";  // NOLINT(cert-err60-cpp)
    1420              :         }
    1421              : 
    1422            0 :         int enable = 1;
    1423            0 :         int retval = setsockopt(socket_file_descriptor,
    1424              :                                 SOL_SOCKET, SO_REUSEADDR,
    1425              :                                 &enable, sizeof(int));
    1426              : 
    1427            0 :         if (retval < 0)
    1428              :         {
    1429            0 :                 TLOG(TLVL_ERROR) << "Problem with the call to setsockopt(); C-style errno == " << errno << " (" << strerror(errno) << ")";
    1430            0 :                 throw cet::exception("xmlrpc_commander::run") << "Problem with the call to setsockopt(); C-style errno == " << errno << " (" << strerror(errno) << ")";  // NOLINT(cert-err60-cpp)
    1431              :         }
    1432              : 
    1433              :         struct sockaddr_in sockAddr;
    1434              : 
    1435            0 :         sockAddr.sin_family = AF_INET;
    1436            0 :         sockAddr.sin_port = htons(port_);
    1437            0 :         sockAddr.sin_addr.s_addr = 0;
    1438              : 
    1439            0 :         retval = bind(socket_file_descriptor,
    1440              :                       reinterpret_cast<struct sockaddr*>(&sockAddr),  // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)
    1441              :                       sizeof(sockAddr));
    1442              : 
    1443            0 :         if (retval != 0)
    1444              :         {
    1445            0 :                 close(socket_file_descriptor);
    1446            0 :                 TLOG(TLVL_ERROR) << "Problem with the bind() call; C-style errno == " << errno << " (" << strerror(errno) << ")";
    1447            0 :                 throw cet::exception("xmlrpc_commander::run") << "Problem with the bind() call; C-style errno == " << errno << " (" << strerror(errno) << ")";  // NOLINT(cert-err60-cpp)
    1448              :         }
    1449              : 
    1450            0 :         server = std::make_unique<xmlrpc_c::serverAbyss>(xmlrpc_c::serverAbyss::constrOpt().registryP(&registry).socketFd(socket_file_descriptor));
    1451              : 
    1452              : #if 0
    1453              :                 xmlrpc_c::serverAbyss::shutdown shutdown_obj(&server);
    1454              :                 registry.setShutdown(&shutdown_obj);
    1455              : #endif
    1456              : 
    1457            0 :         TLOG(TLVL_DEBUG + 32) << "running server";
    1458              : 
    1459              :         // JCF, 6/3/15
    1460              : 
    1461              :         // Use a catch block to clean up (i.e., close the socket). An
    1462              :         // opportunity for RAII, although all control paths are limited to
    1463              :         // this section of the file...
    1464              : 
    1465              :         try
    1466              :         {
    1467            0 :                 running_ = true;
    1468            0 :                 server->run();
    1469            0 :                 running_ = false;
    1470              :         }
    1471            0 :         catch (...)
    1472              :         {
    1473            0 :                 TLOG(TLVL_WARNING) << "server threw an exception; closing the socket and rethrowing";
    1474            0 :                 running_ = false;
    1475            0 :                 close(socket_file_descriptor);
    1476            0 :                 throw;
    1477            0 :         }
    1478              : 
    1479            0 :         close(socket_file_descriptor);
    1480              : 
    1481            0 :         unregister_method(init);
    1482            0 :         unregister_method(soft_init);
    1483            0 :         unregister_method(reinit);
    1484            0 :         unregister_method(start);
    1485            0 :         unregister_method(status);
    1486            0 :         unregister_method(report);
    1487            0 :         unregister_method(stop);
    1488            0 :         unregister_method(pause);
    1489            0 :         unregister_method(resume);
    1490            0 :         unregister_method(register_monitor);
    1491            0 :         unregister_method(unregister_monitor);
    1492            0 :         unregister_method(legal_commands);
    1493            0 :         unregister_method(trace_set);
    1494            0 :         unregister_method(trace_get);
    1495            0 :         unregister_method(meta_command);
    1496            0 :         unregister_method(rollover_subrun);
    1497            0 :         unregister_method(add_config_archive_entry);
    1498            0 :         unregister_method(clear_config_archive);
    1499              : 
    1500            0 :         unregister_method(shutdown);
    1501              : 
    1502            0 :         TLOG(TLVL_DEBUG + 32) << "server terminated";
    1503            0 : }
    1504            0 : catch (...)
    1505              : {
    1506            0 :         throw;
    1507            0 : }
    1508              : 
    1509            0 : std::string xmlrpc_commander::send_command_(const std::string& command)
    1510              : {
    1511            0 :         if (serverUrl_.empty())
    1512              :         {
    1513            0 :                 std::stringstream errmsg;
    1514            0 :                 errmsg << "Problem attempting " << command << " XML-RPC call: No server URL set!";
    1515            0 :                 ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
    1516            0 :         }
    1517            0 :         xmlrpc_c::clientSimple myClient;
    1518            0 :         xmlrpc_c::value result;
    1519              : 
    1520              :         try
    1521              :         {
    1522            0 :                 myClient.call(serverUrl_, "daq." + command, "", &result);
    1523              :         }
    1524            0 :         catch (...)
    1525              :         {
    1526            0 :                 std::stringstream errmsg;
    1527            0 :                 errmsg << "Problem attempting " << command << " XML-RPC call on host " << serverUrl_
    1528            0 :                        << "; possible causes are malformed FHiCL or nonexistent process at requested port";
    1529            0 :                 ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
    1530            0 :         }
    1531              : 
    1532            0 :         return xmlrpc_c::value_string(result);
    1533            0 : }
    1534              : 
    1535            0 : std::string xmlrpc_commander::send_command_(const std::string& command, const std::string& arg)
    1536              : {
    1537            0 :         if (serverUrl_.empty())
    1538              :         {
    1539            0 :                 std::stringstream errmsg;
    1540            0 :                 errmsg << "Problem attempting " << command << " XML-RPC call: No server URL set!";
    1541            0 :                 ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
    1542            0 :         }
    1543            0 :         xmlrpc_c::clientSimple myClient;
    1544            0 :         xmlrpc_c::value result;
    1545              : 
    1546              :         try
    1547              :         {
    1548            0 :                 myClient.call(serverUrl_, "daq." + command, "s", &result, arg.c_str());
    1549              :         }
    1550            0 :         catch (...)
    1551              :         {
    1552            0 :                 std::stringstream errmsg;
    1553            0 :                 errmsg << "Problem attempting " << command << " XML-RPC call on host " << serverUrl_
    1554            0 :                        << "; possible causes are malformed FHiCL or nonexistent process at requested port";
    1555            0 :                 ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
    1556            0 :         }
    1557              : 
    1558            0 :         return xmlrpc_c::value_string(result);
    1559            0 : }
    1560              : 
    1561            0 : std::string xmlrpc_commander::send_command_(const std::string& command, const fhicl::ParameterSet& pset, uint64_t timestamp, uint64_t timeout)
    1562              : {
    1563            0 :         if (serverUrl_.empty())
    1564              :         {
    1565            0 :                 std::stringstream errmsg;
    1566            0 :                 errmsg << "Problem attempting " << command << " XML-RPC call: No server URL set!";
    1567            0 :                 ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
    1568            0 :         }
    1569            0 :         xmlrpc_c::clientSimple myClient;
    1570            0 :         xmlrpc_c::value result;
    1571              : 
    1572              :         try
    1573              :         {
    1574            0 :                 myClient.call(serverUrl_, "daq." + command, "sII", &result, pset.to_string().c_str(), timestamp, timeout);
    1575              :         }
    1576            0 :         catch (...)
    1577              :         {
    1578            0 :                 std::stringstream errmsg;
    1579            0 :                 errmsg << "Problem attempting " << command << " XML-RPC call on host " << serverUrl_
    1580            0 :                        << "; possible causes are malformed FHiCL or nonexistent process at requested port";
    1581            0 :                 ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
    1582            0 :         }
    1583              : 
    1584            0 :         return xmlrpc_c::value_string(result);
    1585            0 : }
    1586              : 
    1587            0 : std::string artdaq::xmlrpc_commander::send_command_(const std::string& command, uint64_t a, uint64_t b)
    1588              : {
    1589            0 :         if (serverUrl_.empty())
    1590              :         {
    1591            0 :                 std::stringstream errmsg;
    1592            0 :                 errmsg << "Problem attempting " << command << " XML-RPC call: No server URL set!";
    1593            0 :                 ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
    1594            0 :         }
    1595            0 :         xmlrpc_c::clientSimple myClient;
    1596            0 :         xmlrpc_c::value result;
    1597              : 
    1598              :         try
    1599              :         {
    1600            0 :                 myClient.call(serverUrl_, "daq." + command, "II", &result, a, b);
    1601              :         }
    1602            0 :         catch (...)
    1603              :         {
    1604            0 :                 std::stringstream errmsg;
    1605            0 :                 errmsg << "Problem attempting " << command << " XML-RPC call on host " << serverUrl_
    1606            0 :                        << "; possible causes are malformed FHiCL or nonexistent process at requested port";
    1607            0 :                 ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
    1608            0 :         }
    1609              : 
    1610            0 :         return xmlrpc_c::value_string(result);
    1611            0 : }
    1612              : 
    1613            0 : std::string artdaq::xmlrpc_commander::send_command_(const std::string& command, uint64_t a, uint32_t b)
    1614              : {
    1615            0 :         if (serverUrl_.empty())
    1616              :         {
    1617            0 :                 std::stringstream errmsg;
    1618            0 :                 errmsg << "Problem attempting " << command << " XML-RPC call: No server URL set!";
    1619            0 :                 ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
    1620            0 :         }
    1621            0 :         xmlrpc_c::clientSimple myClient;
    1622            0 :         xmlrpc_c::value result;
    1623              : 
    1624              :         try
    1625              :         {
    1626            0 :                 myClient.call(serverUrl_, "daq." + command, "Ii", &result, a, b);
    1627              :         }
    1628            0 :         catch (...)
    1629              :         {
    1630            0 :                 std::stringstream errmsg;
    1631            0 :                 errmsg << "Problem attempting " << command << " XML-RPC call on host " << serverUrl_
    1632            0 :                        << "; possible causes are malformed FHiCL or nonexistent process at requested port";
    1633            0 :                 ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
    1634            0 :         }
    1635              : 
    1636            0 :         return xmlrpc_c::value_string(result);
    1637            0 : }
    1638              : 
    1639            0 : std::string artdaq::xmlrpc_commander::send_command_(const std::string& command, art::RunID r, uint64_t a, uint64_t b)
    1640              : {
    1641            0 :         if (serverUrl_.empty())
    1642              :         {
    1643            0 :                 std::stringstream errmsg;
    1644            0 :                 errmsg << "Problem attempting " << command << " XML-RPC call: No server URL set!";
    1645            0 :                 ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
    1646            0 :         }
    1647            0 :         xmlrpc_c::clientSimple myClient;
    1648            0 :         xmlrpc_c::value result;
    1649              : 
    1650              :         try
    1651              :         {
    1652            0 :                 myClient.call(serverUrl_, "daq." + command, "iII", &result, r.run(), a, b);
    1653              :         }
    1654            0 :         catch (...)
    1655              :         {
    1656            0 :                 std::stringstream errmsg;
    1657            0 :                 errmsg << "Problem attempting " << command << " XML-RPC call on host " << serverUrl_
    1658            0 :                        << "; possible causes are malformed FHiCL or nonexistent process at requested port";
    1659            0 :                 ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
    1660            0 :         }
    1661              : 
    1662            0 :         return xmlrpc_c::value_string(result);
    1663            0 : }
    1664              : 
    1665            0 : std::string artdaq::xmlrpc_commander::send_command_(const std::string& command, uint64_t arg1)
    1666              : {
    1667            0 :         if (serverUrl_.empty())
    1668              :         {
    1669            0 :                 std::stringstream errmsg;
    1670            0 :                 errmsg << "Problem attempting " << command << " XML-RPC call: No server URL set!";
    1671            0 :                 ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
    1672            0 :         }
    1673            0 :         xmlrpc_c::clientSimple myClient;
    1674            0 :         xmlrpc_c::value result;
    1675              : 
    1676              :         try
    1677              :         {
    1678            0 :                 myClient.call(serverUrl_, "daq." + command, "I", &result, arg1);
    1679              :         }
    1680            0 :         catch (...)
    1681              :         {
    1682            0 :                 std::stringstream errmsg;
    1683            0 :                 errmsg << "Problem attempting " << command << " XML-RPC call on host " << serverUrl_
    1684            0 :                        << "; possible causes are malformed FHiCL or nonexistent process at requested port";
    1685            0 :                 ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
    1686            0 :         }
    1687              : 
    1688            0 :         return xmlrpc_c::value_string(result);
    1689            0 : }
    1690              : 
    1691            0 : std::string artdaq::xmlrpc_commander::send_command_(const std::string& command, const std::string& arg1, const std::string& arg2)
    1692              : {
    1693            0 :         if (serverUrl_.empty())
    1694              :         {
    1695            0 :                 std::stringstream errmsg;
    1696            0 :                 errmsg << "Problem attempting " << command << " XML-RPC call: No server URL set!";
    1697            0 :                 ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
    1698            0 :         }
    1699            0 :         xmlrpc_c::clientSimple myClient;
    1700            0 :         xmlrpc_c::value result;
    1701              : 
    1702              :         try
    1703              :         {
    1704            0 :                 myClient.call(serverUrl_, "daq." + command, "ss", &result, arg1.c_str(), arg2.c_str());
    1705              :         }
    1706            0 :         catch (...)
    1707              :         {
    1708            0 :                 std::stringstream errmsg;
    1709            0 :                 errmsg << "Problem attempting " << command << " XML-RPC call on host " << serverUrl_
    1710            0 :                        << "; possible causes are malformed FHiCL or nonexistent process at requested port";
    1711            0 :                 ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
    1712            0 :         }
    1713              : 
    1714            0 :         return xmlrpc_c::value_string(result);
    1715            0 : }
    1716              : 
    1717            0 : std::string artdaq::xmlrpc_commander::send_command_(const std::string& command, const std::string& arg1, const std::string& arg2, const std::string& arg3)
    1718              : {
    1719            0 :         if (serverUrl_.empty())
    1720              :         {
    1721            0 :                 std::stringstream errmsg;
    1722            0 :                 errmsg << "Problem attempting " << command << " XML-RPC call: No server URL set!";
    1723            0 :                 ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
    1724            0 :         }
    1725            0 :         xmlrpc_c::clientSimple myClient;
    1726            0 :         xmlrpc_c::value result;
    1727              : 
    1728              :         try
    1729              :         {
    1730            0 :                 myClient.call(serverUrl_, "daq." + command, "sss", &result, arg1.c_str(), arg2.c_str(), arg3.c_str());
    1731              :         }
    1732            0 :         catch (...)
    1733              :         {
    1734            0 :                 std::stringstream errmsg;
    1735            0 :                 errmsg << "Problem attempting " << command << " XML-RPC call on host " << serverUrl_
    1736            0 :                        << "; possible causes are bad arguments or nonexistent process at requested port";
    1737            0 :                 ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
    1738            0 :         }
    1739              : 
    1740            0 :         return xmlrpc_c::value_string(result);
    1741            0 : }
    1742              : 
    1743            0 : std::string xmlrpc_commander::send_register_monitor(std::string const& monitor_fhicl)
    1744              : {
    1745            0 :         return send_command_("register_monitor", monitor_fhicl);
    1746              : }
    1747            0 : std::string xmlrpc_commander::send_unregister_monitor(std::string const& monitor_label)
    1748              : {
    1749            0 :         return send_command_("unregister_monitor", monitor_label);
    1750              : }
    1751            0 : std::string artdaq::xmlrpc_commander::send_init(fhicl::ParameterSet const& ps, uint64_t timeout, uint64_t timestamp)
    1752              : {
    1753            0 :         return send_command_("init", ps, timeout, timestamp);
    1754              : }
    1755            0 : std::string artdaq::xmlrpc_commander::send_soft_init(fhicl::ParameterSet const& ps, uint64_t timeout, uint64_t timestamp)
    1756              : {
    1757            0 :         return send_command_("soft_init", ps, timeout, timestamp);
    1758              : }
    1759            0 : std::string xmlrpc_commander::send_reinit(fhicl::ParameterSet const& ps, uint64_t timeout, uint64_t timestamp)
    1760              : {
    1761            0 :         return send_command_("reinit", ps, timeout, timestamp);
    1762              : }
    1763            0 : std::string xmlrpc_commander::send_start(art::RunID run, uint64_t timeout, uint64_t timestamp)
    1764              : {
    1765            0 :         return send_command_("start", run, timeout, timestamp);
    1766              : }
    1767            0 : std::string xmlrpc_commander::send_pause(uint64_t timeout, uint64_t timestamp)
    1768              : {
    1769            0 :         return send_command_("pause", timeout, timestamp);
    1770              : }
    1771            0 : std::string xmlrpc_commander::send_resume(uint64_t timeout, uint64_t timestamp)
    1772              : {
    1773            0 :         return send_command_("resume", timeout, timestamp);
    1774              : }
    1775            0 : std::string xmlrpc_commander::send_stop(uint64_t timeout, uint64_t timestamp)
    1776              : {
    1777            0 :         return send_command_("stop", timeout, timestamp);
    1778              : }
    1779            0 : std::string xmlrpc_commander::send_shutdown(uint64_t timeout)
    1780              : {
    1781            0 :         return send_command_("shutdown", timeout);
    1782              : }
    1783            0 : std::string xmlrpc_commander::send_status()
    1784              : {
    1785            0 :         return send_command_("status");
    1786              : }
    1787            0 : std::string xmlrpc_commander::send_report(std::string const& what)
    1788              : {
    1789            0 :         return send_command_("report", what);
    1790              : }
    1791            0 : std::string xmlrpc_commander::send_legal_commands()
    1792              : {
    1793            0 :         return send_command_("legal_commands");
    1794              : }
    1795            0 : std::string xmlrpc_commander::send_trace_get(std::string const& name)
    1796              : {
    1797            0 :         return send_command_("trace_get", name);
    1798              : }
    1799            0 : std::string xmlrpc_commander::send_trace_set(std::string const& name, std::string const& type, std::string const& mask)
    1800              : {
    1801            0 :         return send_command_("trace_set", name, type, mask);
    1802              : }
    1803            0 : std::string xmlrpc_commander::send_meta_command(std::string const& command, std::string const& arg)
    1804              : {
    1805            0 :         return send_command_("meta_command", command, arg);
    1806              : }
    1807            0 : std::string xmlrpc_commander::send_rollover_subrun(uint64_t when, uint32_t sr)
    1808              : {
    1809            0 :         return send_command_("rollover_subrun", when, sr);
    1810              : }
    1811              : }  // namespace artdaq
    1812              : 
    1813            0 : DEFINE_ARTDAQ_COMMANDER(artdaq::xmlrpc_commander)
        

Generated by: LCOV version 2.0-1