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 % 607 0
Test Date: 2025-09-04 00:45:34 Functions: 0.0 % 114 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              :         throw cet::exception("cmd_") << "Error in cmd_::getParam(): value type not supported" << std::endl;  // NOLINT(cert-err60-cpp)
     579              : }
     580              : 
     581              : /**
     582              :  * \brief Get a parameter from the parameter list
     583              :  * \param paramList The parameter list
     584              :  * \param index Index of the parameter in the parameter list
     585              :  * \return The requested parameter
     586              :  *
     587              :  * This specialized cmd_getParam for the uint64_t type
     588              :  */
     589              : template<>
     590            0 : uint64_t cmd_::getParam<uint64_t>(const xmlrpc_c::paramList& paramList, int index)
     591              : {
     592            0 :         TLOG(TLVL_DEBUG + 33) << "Getting parameter " << index << " from list as uint64_t.";
     593              :         try
     594              :         {
     595            0 :                 TLOG(TLVL_DEBUG + 33) << "Param value: " << paramList.getI8(index);
     596            0 :                 return static_cast<uint64_t>(paramList.getI8(index));
     597              :         }
     598            0 :         catch (...)
     599              :         {
     600            0 :                 TLOG(TLVL_DEBUG + 33) << "Param value (int): " << paramList.getInt(index);
     601            0 :                 return static_cast<uint64_t>(paramList.getInt(index));
     602            0 :         }
     603              : }
     604              : 
     605              : /**
     606              :  * \brief Get a parameter from the parameter list
     607              :  * \param paramList The parameter list
     608              :  * \param index Index of the parameter in the parameter list
     609              :  * \return The requested parameter
     610              :  *
     611              :  * This specialized cmd_getParam for the uint64_t type
     612              :  */
     613              : template<>
     614            0 : uint32_t cmd_::getParam<uint32_t>(const xmlrpc_c::paramList& paramList, int index)
     615              : {
     616            0 :         TLOG(TLVL_DEBUG + 33) << "Getting parameter " << index << " from list as uint32_t.";
     617            0 :         TLOG(TLVL_DEBUG + 33) << "Param value: " << paramList.getInt(index);
     618            0 :         return static_cast<uint32_t>(paramList.getInt(index));
     619              : }
     620              : 
     621              : /**
     622              :  * \brief Get a parameter from the parameter list
     623              :  * \param paramList The parameter list
     624              :  * \param index Index of the parameter in the parameter list
     625              :  * \return The requested parameter
     626              :  *
     627              :  * This specialized cmd_getParam for the std::string type
     628              :  */
     629              : template<>
     630            0 : std::string cmd_::getParam<std::string>(const xmlrpc_c::paramList& paramList, int index)
     631              : {
     632            0 :         TLOG(TLVL_DEBUG + 33) << "Getting parameter " << index << " from list as string.";
     633            0 :         TLOG(TLVL_DEBUG + 33) << "Param value: " << paramList.getString(index);
     634            0 :         return static_cast<std::string>(paramList.getString(index));
     635              : }
     636              : 
     637              : /**
     638              :  * \brief Get a parameter from the parameter list
     639              :  * \param paramList The parameter list
     640              :  * \param index Index of the parameter in the parameter list
     641              :  * \return The requested parameter
     642              :  *
     643              :  * This specialized cmd_getParam for the art::RunID type
     644              :  */
     645              : template<>
     646            0 : art::RunID cmd_::getParam<art::RunID>(const xmlrpc_c::paramList& paramList, int index)
     647              : {
     648            0 :         TLOG(TLVL_DEBUG + 33) << "Getting parameter " << index << " from list as Run Number.";
     649              :         art::RunNumber_t run_number;
     650              :         try
     651              :         {
     652            0 :                 TLOG(TLVL_DEBUG + 33) << "Param value: " << paramList.getInt(index);
     653            0 :                 run_number = art::RunNumber_t(paramList.getInt(index));
     654              :         }
     655            0 :         catch (...)
     656              :         {
     657            0 :                 TLOG(TLVL_DEBUG + 33) << "Parameter is not an int. Trying string...";
     658              : 
     659            0 :                 auto runNumber = paramList.getString(index);
     660            0 :                 TLOG(TLVL_DEBUG + 33) << "Got run number string " << runNumber;
     661            0 :                 run_number = art::RunNumber_t(std::stoi(runNumber));
     662            0 :         }
     663              : 
     664            0 :         art::RunID run_id(run_number);
     665            0 :         return run_id;
     666              : }
     667              : 
     668              : /**
     669              :  * \brief Get a parameter from the parameter list
     670              :  * \param paramList The parameter list
     671              :  * \param index Index of the parameter in the parameter list
     672              :  * \return The requested parameter
     673              :  *
     674              :  * This specialized cmd_getParam for the fhicl::ParameterSet type
     675              :  */
     676              : template<>
     677            0 : fhicl::ParameterSet cmd_::getParam<fhicl::ParameterSet>(const xmlrpc_c::paramList& paramList, int index)
     678              : {
     679            0 :         TLOG(TLVL_DEBUG + 33) << "Getting parameter " << index << " from list as ParameterSet.";
     680            0 :         TLOG(TLVL_DEBUG + 33) << "Param value: " << paramList.getString(index);
     681            0 :         std::string configString = std::string(paramList.getString(index));
     682            0 :         TLOG(TLVL_DEBUG + 32) << "Loading Parameter Set from string: " << configString << std::endl;
     683            0 :         fhicl::ParameterSet pset;
     684              : 
     685              :         try
     686              :         {
     687            0 :                 pset = fhicl::ParameterSet::make(configString);
     688              :         }
     689            0 :         catch (const fhicl::exception& e)
     690              :         {
     691            0 :                 if (getenv("FHICL_FILE_PATH") == nullptr)
     692              :                 {
     693            0 :                         TLOG(TLVL_ERROR) << "INFO: environment variable FHICL_FILE_PATH was not set. Using \".\"";
     694            0 :                         std::cerr << "INFO: environment variable FHICL_FILE_PATH was not set. Using \".\"" << std::endl;
     695            0 :                         setenv("FHICL_FILE_PATH", ".", 0);
     696              :                 }
     697            0 :                 cet::filepath_lookup_after1 lookup_policy("FHICL_FILE_PATH");
     698            0 :                 pset = fhicl::ParameterSet::make(configString, lookup_policy);
     699            0 :         }
     700              : 
     701            0 :         TLOG(TLVL_INFO) << "Parameter Set Loaded." << std::endl;
     702            0 :         return pset;
     703            0 : }
     704              : 
     705              : template<typename T>
     706            0 : T cmd_::getParam(const xmlrpc_c::paramList& paramList, int index,
     707              :                  T default_value)
     708              : {
     709            0 :         T val = default_value;
     710              : 
     711            0 :         if (static_cast<unsigned>(index) < paramList.size())
     712              :         {
     713            0 :                 val = getParam<T>(paramList, index);
     714              :         }
     715            0 :         return val;
     716              : }
     717              : 
     718            0 : void cmd_::execute(const xmlrpc_c::paramList& paramList, xmlrpc_c::value* const retvalP)
     719              : {
     720            0 :         TLOG(TLVL_DEBUG + 33) << "Received Request to " << _help << ", attempting to get lock";
     721            0 :         std::unique_lock<std::timed_mutex> lk(_c.mutex_, std::defer_lock);
     722            0 :         auto ret = lk.try_lock_for(std::chrono::milliseconds(250));
     723              : 
     724            0 :         if (ret && lk.owns_lock())
     725              :         {
     726              :                 try
     727              :                 {
     728              :                         // JCF, 9/4/14
     729              : 
     730              :                         // Assuming the execute_ function returns true, then if the
     731              :                         // retvalP argument was untouched, assign it the string
     732              :                         // "Success"
     733              : 
     734              :                         // See
     735              :                         // http://xmlrpc-c.sourceforge.net/doc/libxmlrpc++.html#isinstantiated
     736              :                         // for more on the concept of instantiation in xmlrpc_c::value objects
     737              : 
     738            0 :                         if (execute_(paramList, retvalP))
     739              :                         {
     740            0 :                                 if (!retvalP->isInstantiated())
     741              :                                 {
     742            0 :                                         *retvalP = xmlrpc_c::value_string("Success");
     743              :                                 }
     744              :                         }
     745              :                         else
     746              :                         {
     747            0 :                                 std::string problemReport = _c._commandable.report("transition_status");
     748            0 :                                 *retvalP = xmlrpc_c::value_string(problemReport);
     749            0 :                         }
     750              :                 }
     751            0 :                 catch (std::runtime_error& er)
     752              :                 {
     753            0 :                         std::string msg = exception_msg(er, _help);
     754            0 :                         *retvalP = xmlrpc_c::value_string(msg);
     755            0 :                         TLOG(TLVL_ERROR) << msg;
     756            0 :                 }
     757            0 :                 catch (art::Exception& er)
     758              :                 {
     759            0 :                         std::string msg = exception_msg(er, _help);
     760            0 :                         *retvalP = xmlrpc_c::value_string(msg);
     761            0 :                         TLOG(TLVL_ERROR) << msg;
     762            0 :                 }
     763            0 :                 catch (cet::exception& er)
     764              :                 {
     765            0 :                         std::string msg = exception_msg(er, _help);
     766            0 :                         *retvalP = xmlrpc_c::value_string(msg);
     767            0 :                         TLOG(TLVL_ERROR) << msg;
     768            0 :                 }
     769            0 :                 catch (boost::exception& er)
     770              :                 {
     771            0 :                         std::string msg = exception_msg(er, _help);
     772            0 :                         *retvalP = xmlrpc_c::value_string(msg);
     773            0 :                         TLOG(TLVL_ERROR) << msg;
     774            0 :                 }
     775            0 :                 catch (std::exception& er)
     776              :                 {
     777            0 :                         std::string msg = exception_msg(er, _help);
     778            0 :                         *retvalP = xmlrpc_c::value_string(msg);
     779            0 :                         TLOG(TLVL_ERROR) << msg;
     780            0 :                 }
     781            0 :                 catch (...)
     782              :                 {
     783            0 :                         std::string msg = exception_msg("Unknown exception (not from std, boost, cet, or art)", _help);
     784            0 :                         *retvalP = xmlrpc_c::value_string(msg);
     785            0 :                         TLOG(TLVL_ERROR) << msg;
     786            0 :                 }
     787              : 
     788            0 :                 lk.unlock();
     789              :         }
     790              :         else
     791              :         {
     792            0 :                 TLOG(TLVL_ERROR) << "Unable to get lock while trying to " << _help << ", returning busy";
     793            0 :                 *retvalP = xmlrpc_c::value_string("busy");
     794              :         }
     795            0 : }
     796              : 
     797              : //////////////////////////////////////////////////////////////////////
     798              : 
     799              : // JCF, 9/5/14
     800              : 
     801              : // The three "init" transitions all take a FHiCL parameter list, and
     802              : // optionally a timeout and a timestamp; thus we can kill three birds
     803              : // with one stone in the GENERATE_INIT_TRANSITION macro
     804              : 
     805              : #define GENERATE_INIT_TRANSITION(NAME, CALL, DESCRIPTION)                                                                                                                 \
     806              :         /** Command class representing an init transition */                                                                                                                  \
     807              :         class NAME##_ : public cmd_                                                                                                                                           \
     808              :         {                                                                                                                                                                     \
     809              :         public:                                                                                                                                                               \
     810              :                 /** Command class Constructor                                                                                                                                     \
     811              :                  * \param c xmlrpc_commander to send parsed command to                                                                                                            \
     812              :                  */                                                                                                                                                               \
     813              :                 explicit NAME##_(xmlrpc_commander& c) : cmd_(c, "s:sII", DESCRIPTION)                                                                                             \
     814              :                 {}                                                                                                                                                                \
     815              :                                                                                                                                                                           \
     816              :                 /** Default timeout for command */                                                                                                                                \
     817              :                 static const uint64_t defaultTimeout = 45;                                                                                                                        \
     818              :                 /** Default timestamp for Command */                                                                                                                              \
     819              :                 static const uint64_t defaultTimestamp = std::numeric_limits<const uint64_t>::max();                                                                              \
     820              :                                                                                                                                                                           \
     821              :         private:                                                                                                                                                              \
     822              :                 bool execute_(const xmlrpc_c::paramList& paramList, xmlrpc_c::value* const retvalP)                                                                               \
     823              :                 {                                                                                                                                                                 \
     824              :                         fhicl::ParameterSet ps;                                                                                                                                       \
     825              :                         try                                                                                                                                                           \
     826              :                         {                                                                                                                                                             \
     827              :                                 ps = getParam<fhicl::ParameterSet>(paramList, 0);                                                                                                         \
     828              :                         }                                                                                                                                                             \
     829              :                         catch (...)                                                                                                                                                   \
     830              :                         {                                                                                                                                                             \
     831              :                                 *retvalP = xmlrpc_c::value_string("Error: The " #NAME " message requires a single argument that is a string containing the initialization ParameterSet"); \
     832              :                                 return true;                                                                                                                                              \
     833              :                         }                                                                                                                                                             \
     834              :                                                                                                                                                                           \
     835              :                         return _c._commandable.CALL(ps,                                                                                                                               \
     836              :                                                     getParam<uint64_t>(paramList, 1, defaultTimeout),                                                                                 \
     837              :                                                     getParam<uint64_t>(paramList, 2, defaultTimestamp));                                                                              \
     838              :                 }                                                                                                                                                                 \
     839              :         };
     840              : 
     841            0 : GENERATE_INIT_TRANSITION(init, initialize, "initialize the program")
     842              : 
     843            0 : GENERATE_INIT_TRANSITION(soft_init, soft_initialize, "initialize software components in the program")
     844              : 
     845            0 : GENERATE_INIT_TRANSITION(reinit, reinitialize, "re-initialize the program")
     846              : 
     847              : #undef GENERATE_INIT_TRANSITION
     848              : 
     849              : //////////////////////////////////////////////////////////////////////
     850              : 
     851              : /**
     852              :  * \brief Command class representing a start transition
     853              :  */
     854              : class start_ : public cmd_
     855              : {
     856              : public:
     857              :         /**
     858              :          * \brief start_ Command (cmd_ derived class) Constructor
     859              :          * \param c xmlrpc_commander instance to command
     860              :          */
     861            0 :         explicit start_(xmlrpc_commander& c)
     862            0 :             : cmd_(c, "s:iII", "start the run")
     863            0 :         {}
     864              : 
     865              :         /** Default timeout for command */
     866              :         static const uint64_t defaultTimeout = 45;
     867              :         /** Default timestamp for Command */
     868              :         static const uint64_t defaultTimestamp = std::numeric_limits<const uint64_t>::max();
     869              : 
     870              : private:
     871            0 :         bool execute_(xmlrpc_c::paramList const& paramList, xmlrpc_c::value* const retvalP) override
     872              :         {
     873              :                 try
     874              :                 {
     875            0 :                         getParam<art::RunID>(paramList, 0);
     876              :                 }
     877            0 :                 catch (...)
     878              :                 {
     879            0 :                         *retvalP = xmlrpc_c::value_string("Error: The start message requires the run number as an argument.");
     880            0 :                         return true;
     881            0 :                 }
     882              : 
     883            0 :                 return _c._commandable.start(getParam<art::RunID>(paramList, 0),
     884              :                                              getParam<uint64_t>(paramList, 1, defaultTimeout),
     885            0 :                                              getParam<uint64_t>(paramList, 2, defaultTimestamp));
     886              :         }
     887              : };
     888              : 
     889              : //////////////////////////////////////////////////////////////////////
     890              : 
     891              : // JCF, 9/5/14
     892              : 
     893              : // "pause", "resume" and "stop" all take an optional timeout and
     894              : // timestamp parameter, so we can generate them all with the
     895              : // GENERATE_TIMEOUT_TIMESTAMP_TRANSITION macro
     896              : 
     897              : #define GENERATE_TIMEOUT_TIMESTAMP_TRANSITION(NAME, CALL, DESCRIPTION, TIMEOUT)              \
     898              :         /** NAME ## _ Command class */                                                           \
     899              :         class NAME##_ : public cmd_                                                              \
     900              :         {                                                                                        \
     901              :         public:                                                                                  \
     902              :                 /** NAME ## _ Constructor                                                            \
     903              :                     \param c xmlrpc_commander to send transition commands to */                      \
     904              :                 NAME##_(xmlrpc_commander& c) : cmd_(c, "s:II", DESCRIPTION)                          \
     905              :                 {}                                                                                   \
     906              :                                                                                              \
     907              :                 /** Default timeout for command */                                                   \
     908              :                 static const uint64_t defaultTimeout = TIMEOUT;                                      \
     909              :                 /** Default timestamp for Command */                                                 \
     910              :                 static const uint64_t defaultTimestamp = std::numeric_limits<const uint64_t>::max(); \
     911              :                                                                                              \
     912              :         private:                                                                                 \
     913              :                 bool execute_(const xmlrpc_c::paramList& paramList, xmlrpc_c::value* const)          \
     914              :                 {                                                                                    \
     915              :                         return _c._commandable.CALL(getParam<uint64_t>(paramList, 0, defaultTimeout),    \
     916              :                                                     getParam<uint64_t>(paramList, 1, defaultTimestamp)); \
     917              :                 }                                                                                    \
     918              :         };
     919              : 
     920            0 : GENERATE_TIMEOUT_TIMESTAMP_TRANSITION(pause, pause, "pause the program", 45)
     921              : 
     922            0 : GENERATE_TIMEOUT_TIMESTAMP_TRANSITION(resume, resume, "resume the program", 45)
     923              : 
     924            0 : GENERATE_TIMEOUT_TIMESTAMP_TRANSITION(stop, stop, "stop the program", 45)
     925              : 
     926              : #undef GENERATE_TIMEOUT_TIMESTAMP_TRANSITION
     927              : 
     928              : /**
     929              :  * \brief shutdown_ Command class
     930              :  */
     931              : class shutdown_ : public cmd_
     932              : {
     933              : public:
     934              :         /**
     935              :          * \brief shutdown_ Constructor
     936              :          * \param c xmlrpc_commander to send transition commands to
     937              :          */
     938            0 :         shutdown_(xmlrpc_commander& c)
     939            0 :             : cmd_(c, "s:i", "shutdown the program")
     940            0 :         {}
     941              : 
     942              :         /** Default timeout for command */
     943              :         static const uint64_t defaultTimeout = 45;
     944              : 
     945              : private:
     946            0 :         bool execute_(const xmlrpc_c::paramList& paramList, xmlrpc_c::value* const /*retvalP*/) override
     947              :         {
     948            0 :                 auto ret = _c._commandable.shutdown(getParam<uint64_t>(paramList, 0, defaultTimeout));
     949              : 
     950              : #if 1
     951            0 :                 if (_c.server)
     952              :                 {
     953            0 :                         _c.server->terminate();
     954              :                 }
     955              : #endif
     956              : 
     957            0 :                 return ret;
     958              :         }
     959              : };
     960              : 
     961              : /**
     962              :  * \brief status_ Command class
     963              :  */
     964              : class status_ : public cmd_
     965              : {
     966              : public:
     967              :         /**
     968              :          * \brief status_ Constructor
     969              :          * \param c xmlrpc_commander to send transition commands to
     970              :          */
     971            0 :         status_(xmlrpc_commander& c)
     972            0 :             : cmd_(c, "s:n", "report the current state")
     973            0 :         {}
     974              : 
     975              : private:
     976            0 :         bool execute_(xmlrpc_c::paramList const& /*unused*/, xmlrpc_c::value* const retvalP) override
     977              :         {
     978            0 :                 *retvalP = xmlrpc_c::value_string(_c._commandable.status());
     979            0 :                 return true;
     980              :         }
     981              : };
     982              : 
     983              : /**
     984              :  * \brief report_ Command class
     985              :  */
     986              : class report_ : public cmd_
     987              : {
     988              : public:
     989              :         /**
     990              :          * \brief report_ Constructor
     991              :          * \param c xmlrpc_commander to send transition commands to
     992              :          */
     993            0 :         report_(xmlrpc_commander& c)
     994            0 :             : cmd_(c, "s:s", "report statistics")
     995            0 :         {}
     996              : 
     997              : private:
     998            0 :         bool execute_(xmlrpc_c::paramList const& paramList, xmlrpc_c::value* const retvalP) override
     999              :         {
    1000              :                 try
    1001              :                 {
    1002            0 :                         getParam<std::string>(paramList, 0);
    1003              :                 }
    1004            0 :                 catch (...)
    1005              :                 {
    1006            0 :                         *retvalP = xmlrpc_c::value_string("Error: The report message requires a single argument that selects the type of statistics to be reported.");
    1007            0 :                         return true;
    1008            0 :                 }
    1009              : 
    1010            0 :                 *retvalP = xmlrpc_c::value_string(_c._commandable.report(getParam<std::string>(paramList, 0)));
    1011            0 :                 return true;
    1012              :         }
    1013              : };
    1014              : 
    1015              : /**
    1016              :  * \brief legal_commands_ Command class
    1017              :  */
    1018              : class legal_commands_ : public cmd_
    1019              : {
    1020              : public:
    1021              :         /**
    1022              :          * \brief legal_commands_ Constructor
    1023              :          * \param c xmlrpc_commander to send transition commands to
    1024              :          */
    1025            0 :         legal_commands_(xmlrpc_commander& c)
    1026            0 :             : cmd_(c, "s:n", "return the currently legal commands")
    1027            0 :         {}
    1028              : 
    1029              : private:
    1030            0 :         bool execute_(xmlrpc_c::paramList const& /*unused*/, xmlrpc_c::value* const retvalP) override
    1031              :         {
    1032            0 :                 std::vector<std::string> cmdList = _c._commandable.legal_commands();
    1033            0 :                 std::string resultString;
    1034              : 
    1035            0 :                 for (auto& cmd : cmdList)
    1036              :                 {
    1037            0 :                         resultString.append(cmd + " ");
    1038            0 :                         if (cmd == "shutdown")
    1039              :                         {
    1040            0 :                                 resultString.append(" reset");
    1041              :                         }
    1042              :                 }
    1043            0 :                 *retvalP = xmlrpc_c::value_string(resultString);
    1044              : 
    1045            0 :                 return true;
    1046            0 :         }
    1047              : };
    1048              : 
    1049              : /**
    1050              :  * \brief register_monitor_ Command class
    1051              :  */
    1052              : class register_monitor_ : public cmd_
    1053              : {
    1054              : public:
    1055              :         /**
    1056              :          * \brief register_monitor_ Constructor
    1057              :          * \param c xmlrpc_commander to send transition commands to
    1058              :          */
    1059            0 :         register_monitor_(xmlrpc_commander& c)
    1060            0 :             : cmd_(c, "s:s", "Get notified of a new monitor")
    1061            0 :         {}
    1062              : 
    1063              : private:
    1064            0 :         bool execute_(xmlrpc_c::paramList const& paramList, xmlrpc_c::value* const retvalP) override
    1065              :         {
    1066              :                 try
    1067              :                 {
    1068            0 :                         getParam<fhicl::ParameterSet>(paramList, 0);
    1069              :                 }
    1070            0 :                 catch (...)
    1071              :                 {
    1072            0 :                         *retvalP = xmlrpc_c::value_string("Error: The register_monitor command expects a string representing the FHiCL definition of a Transfer plugin");
    1073            0 :                         return true;
    1074            0 :                 }
    1075              : 
    1076            0 :                 *retvalP = xmlrpc_c::value_string(_c._commandable.register_monitor(getParam<fhicl::ParameterSet>(paramList, 0)));
    1077            0 :                 return true;
    1078              :         }
    1079              : };
    1080              : 
    1081              : /**
    1082              :  * \brief unregister_monitor_ Command class
    1083              :  */
    1084              : class unregister_monitor_ : public cmd_
    1085              : {
    1086              : public:
    1087              :         /**
    1088              :          * \brief unregister_monitor_ Constructor
    1089              :          * \param c xmlrpc_commander to send transition commands to
    1090              :          */
    1091            0 :         unregister_monitor_(xmlrpc_commander& c)
    1092            0 :             : cmd_(c, "s:s", "Remove a monitor")
    1093            0 :         {}
    1094              : 
    1095              : private:
    1096            0 :         bool execute_(xmlrpc_c::paramList const& paramList, xmlrpc_c::value* const retvalP) override
    1097              :         {
    1098              :                 try
    1099              :                 {
    1100            0 :                         getParam<std::string>(paramList, 0);
    1101              :                 }
    1102            0 :                 catch (...)
    1103              :                 {
    1104            0 :                         *retvalP = xmlrpc_c::value_string("Error: The unregister_monitor command expects a string representing the label of the monitor to be removed");
    1105            0 :                         return true;
    1106            0 :                 }
    1107              : 
    1108            0 :                 *retvalP = xmlrpc_c::value_string(_c._commandable.unregister_monitor(getParam<std::string>(paramList, 0)));
    1109            0 :                 return true;
    1110              :         }
    1111              : };
    1112              : 
    1113              : /**
    1114              :  * \brief trace_set_ Command class
    1115              :  */
    1116              : class trace_set_ : public cmd_
    1117              : {
    1118              : public:
    1119              :         /**
    1120              :          * \brief unregister_monitor_ Constructor
    1121              :          * \param c xmlrpc_commander to send transition commands to
    1122              :          */
    1123            0 :         trace_set_(xmlrpc_commander& c)
    1124            0 :             : cmd_(c, "s:ssI", "Set TRACE mask")
    1125            0 :         {}
    1126              : 
    1127              : private:
    1128            0 :         bool execute_(xmlrpc_c::paramList const& paramList, xmlrpc_c::value* const retvalP) override
    1129              :         {
    1130              :                 try
    1131              :                 {
    1132            0 :                         getParam<std::string>(paramList, 0);
    1133            0 :                         getParam<std::string>(paramList, 1);
    1134            0 :                         getParam<std::string>(paramList, 2);
    1135              :                 }
    1136            0 :                 catch (...)
    1137              :                 {
    1138            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");
    1139            0 :                         return true;
    1140            0 :                 }
    1141              : 
    1142            0 :                 return _c._commandable.do_trace_set(getParam<std::string>(paramList, 0), getParam<std::string>(paramList, 1), getParam<std::string>(paramList, 2));
    1143              :         }
    1144              : };
    1145              : 
    1146              : /**
    1147              :  * \brief trace_get_ Command class
    1148              :  */
    1149              : class trace_get_ : public cmd_
    1150              : {
    1151              : public:
    1152              :         /**
    1153              :          * \brief trace_msgfacility_set_ Constructor
    1154              :          * \param c xmlrpc_commander to send transition commands to
    1155              :          */
    1156            0 :         trace_get_(xmlrpc_commander& c)
    1157            0 :             : cmd_(c, "s:s", "Get TRACE mask")
    1158            0 :         {}
    1159              : 
    1160              : private:
    1161            0 :         bool execute_(xmlrpc_c::paramList const& paramList, xmlrpc_c::value* const retvalP) override
    1162              :         {
    1163              :                 try
    1164              :                 {
    1165            0 :                         getParam<std::string>(paramList, 0);
    1166              :                 }
    1167            0 :                 catch (...)
    1168              :                 {
    1169            0 :                         *retvalP = xmlrpc_c::value_string("Error: The trace_get command expects a name (ALL for all)");
    1170            0 :                         return true;
    1171            0 :                 }
    1172              : 
    1173            0 :                 *retvalP = xmlrpc_c::value_string(_c._commandable.do_trace_get(getParam<std::string>(paramList, 0)));
    1174            0 :                 return true;
    1175              :         }
    1176              : };
    1177              : 
    1178              : /**
    1179              :  * \brief meta_command_ Command class
    1180              :  */
    1181              : class meta_command_ : public cmd_
    1182              : {
    1183              : public:
    1184              :         /**
    1185              :          * \brief meta_command_ Constructor
    1186              :          * \param c xmlrpc_commander to send transition commands to
    1187              :          */
    1188            0 :         meta_command_(xmlrpc_commander& c)
    1189            0 :             : cmd_(c, "s:ss", "Run custom command")
    1190            0 :         {}
    1191              : 
    1192              : private:
    1193            0 :         bool execute_(xmlrpc_c::paramList const& paramList, xmlrpc_c::value* const retvalP) override
    1194              :         {
    1195              :                 try
    1196              :                 {
    1197            0 :                         getParam<std::string>(paramList, 0);
    1198            0 :                         getParam<std::string>(paramList, 1);
    1199              :                 }
    1200            0 :                 catch (...)
    1201              :                 {
    1202            0 :                         *retvalP = xmlrpc_c::value_string("Error: The meta_command command expects a string command and a string argument");
    1203            0 :                         return true;
    1204            0 :                 }
    1205              : 
    1206            0 :                 return _c._commandable.do_meta_command(getParam<std::string>(paramList, 0), getParam<std::string>(paramList, 1));
    1207              :         }
    1208              : };
    1209              : 
    1210              : /**
    1211              :  * \brief rollover_subrun_ Command class
    1212              :  */
    1213              : class rollover_subrun_ : public cmd_
    1214              : {
    1215              : public:
    1216              :         /**
    1217              :          * \brief shutdown_ Constructor
    1218              :          * \param c xmlrpc_commander to send transition commands to
    1219              :          */
    1220            0 :         rollover_subrun_(xmlrpc_commander& c)
    1221            0 :             : cmd_(c, "s:Ii", "create a new subrun")
    1222            0 :         {}
    1223              : 
    1224              :         static const uint64_t defaultSequenceID = 0xFFFFFFFFFFFFFFFF;  ///< Default Sequence ID for command
    1225              :         static const uint32_t defaultSubrunNumber = 1;                 ///< Default subrun number for command
    1226              : 
    1227              : private:
    1228            0 :         bool execute_(const xmlrpc_c::paramList& paramList, xmlrpc_c::value* const /*retvalP*/) override
    1229              :         {
    1230            0 :                 auto ret = _c._commandable.do_rollover_subrun(getParam<uint64_t>(paramList, 0, defaultSequenceID), getParam<uint32_t>(paramList, 1, defaultSubrunNumber));
    1231            0 :                 return ret;
    1232              :         }
    1233              : };
    1234              : 
    1235              : /**
    1236              :  * \brief add_config_archive_entry_ Command class
    1237              :  */
    1238              : class add_config_archive_entry_ : public cmd_
    1239              : {
    1240              : public:
    1241              :         /**
    1242              :          * \brief add_config_archive_entry_ Constructor
    1243              :          * \param c xmlrpc_commander to send transition commands to
    1244              :          */
    1245            0 :         add_config_archive_entry_(xmlrpc_commander& c)
    1246            0 :             : cmd_(c, "s:ss", "Add an entry to the configuration archive list")
    1247            0 :         {}
    1248              : 
    1249              : private:
    1250            0 :         bool execute_(xmlrpc_c::paramList const& paramList, xmlrpc_c::value* const retvalP) override
    1251              :         {
    1252              :                 try
    1253              :                 {
    1254            0 :                         getParam<std::string>(paramList, 0);
    1255            0 :                         getParam<std::string>(paramList, 1);
    1256              :                 }
    1257            0 :                 catch (...)
    1258              :                 {
    1259            0 :                         *retvalP = xmlrpc_c::value_string("Error: The add_config_archive_entry command expects a string key and a string value");
    1260            0 :                         return true;
    1261            0 :                 }
    1262              : 
    1263            0 :                 return _c._commandable.do_add_config_archive_entry(getParam<std::string>(paramList, 0), getParam<std::string>(paramList, 1));
    1264              :         }
    1265              : };
    1266              : 
    1267              : /**
    1268              :  * \brief clear_config_archive_ Command class
    1269              :  */
    1270              : class clear_config_archive_ : public cmd_
    1271              : {
    1272              : public:
    1273              :         /**
    1274              :          * \brief clear_config_archive_ Constructor
    1275              :          * \param c xmlrpc_commander to send transition commands to
    1276              :          */
    1277            0 :         clear_config_archive_(xmlrpc_commander& c)
    1278            0 :             : cmd_(c, "s:n", "Clear the configuration archive list")
    1279            0 :         {}
    1280              : 
    1281              : private:
    1282            0 :         bool execute_(xmlrpc_c::paramList const& /*unused*/, xmlrpc_c::value* const /*retvalP*/) override
    1283              :         {
    1284            0 :                 return _c._commandable.do_clear_config_archive();
    1285              :         }
    1286              : };
    1287              : 
    1288              : // JCF, 9/4/14
    1289              : 
    1290              : // Not sure if anyone was planning to resurrect this code by changing
    1291              : // the preprocessor decision; as such, I'll leave it in for now...
    1292              : 
    1293              : #if 0
    1294              :         class shutdown_ : public xmlrpc_c::registry::shutdown
    1295              :         {
    1296              :         public:
    1297              :                 shutdown_(xmlrpc_c::serverAbyss *server) : _server(server) {}
    1298              : 
    1299              :                 virtual void doit(const std::string& paramString, void*) const
    1300              :                 {
    1301              :                         TLOG(TLVL_INFO) << "A shutdown command was sent "
    1302              :                                 << "with parameter "
    1303              :                                 << paramString << "\"";
    1304              :                         _server->terminate();
    1305              :                 }
    1306              :         private:
    1307              :                 xmlrpc_c::serverAbyss *_server;
    1308              :         };
    1309              : #endif
    1310              : 
    1311            0 : xmlrpc_commander::xmlrpc_commander(const fhicl::ParameterSet& ps, artdaq::Commandable& commandable)
    1312              :     : CommanderInterface(ps, commandable)
    1313            0 :     , port_(ps.get<int>("id", 0))
    1314            0 :     , serverUrl_(ps.get<std::string>("server_url", ""))
    1315            0 :     , server(nullptr)
    1316              : {
    1317            0 :         if (serverUrl_.empty())
    1318              :         {
    1319              :                 char hostname[HOST_NAME_MAX];
    1320            0 :                 gethostname(hostname, HOST_NAME_MAX);
    1321            0 :                 serverUrl_ = std::string(hostname);
    1322              :         }
    1323            0 :         if (serverUrl_.find("http") == std::string::npos)
    1324              :         {
    1325            0 :                 serverUrl_ = "http://" + serverUrl_;
    1326              :         }
    1327            0 :         if (serverUrl_.find(std::to_string(port_)) == std::string::npos && serverUrl_.find(':', 7) == std::string::npos)
    1328              :         {
    1329            0 :                 serverUrl_ = serverUrl_ + ":" + std::to_string(port_);
    1330              :         }
    1331            0 :         if (serverUrl_.find("RPC2") == std::string::npos)
    1332              :         {
    1333            0 :                 serverUrl_ = serverUrl_ + "/RPC2";
    1334              :         }
    1335            0 :         TLOG(TLVL_INFO) << "XMLRPC COMMANDER CONSTRUCTOR: Port: " << port_ << ", Server Url: " << serverUrl_;
    1336            0 : }
    1337              : 
    1338            0 : void xmlrpc_commander::run_server()
    1339              : try
    1340              : {
    1341              :         // std::cout << "XMLRPC_COMMANDER RUN_SERVER CALLED!" << std::endl;
    1342            0 :         xmlrpc_c::registry registry;
    1343              :         struct xmlrpc_method_info3 methodInfo;
    1344            0 :         memset(&methodInfo, 0, sizeof(methodInfo));
    1345              : 
    1346              :         /*#define register_method(m) \
    1347              :             //  xmlrpc_c::methodPtr const ptr_ ## m(new m ## _(*this));\
    1348              :                registry.addMethod ("daq." #m, ptr_ ## m) */
    1349              : #define register_method(m) register_method2(m, 0x400000)
    1350              : 
    1351              :         xmlrpc_env env;  // xmlrpc_env_init(&env);
    1352              :         xmlrpc_registry*** c_registryPPP;
    1353            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)
    1354              : 
    1355              : #define register_method2(m, ss)                                                  \
    1356              :         xmlrpc_c::method* ptr_##m(dynamic_cast<xmlrpc_c::method*>(new m##_(*this))); \
    1357              :         std::string m##signature = ptr_##m->signature(), m##help = ptr_##m->help();  \
    1358              :         methodInfo.methodName = "daq." #m;                                           \
    1359              :         methodInfo.methodFunction = &c_executeMethod;                                \
    1360              :         methodInfo.serverInfo = ptr_##m;                                             \
    1361              :         methodInfo.stackSize = ss;                                                   \
    1362              :         methodInfo.signatureString = &m##signature[0];                               \
    1363              :         methodInfo.help = &m##help[0];                                               \
    1364              :         xmlrpc_env_init(&env);                                                       \
    1365              :         xmlrpc_registry_add_method3(&env, **c_registryPPP, &methodInfo);             \
    1366              :         if (env.fault_occurred) throw(girerr::error(env.fault_string));              \
    1367              :         xmlrpc_env_clean(&env)
    1368              : 
    1369              : #define unregister_method(m) delete ptr_##m;
    1370              : 
    1371            0 :         register_method2(init, 0x200000);
    1372            0 :         register_method(soft_init);
    1373            0 :         register_method(reinit);
    1374            0 :         register_method(start);
    1375            0 :         register_method(status);
    1376            0 :         register_method(report);
    1377            0 :         register_method(stop);
    1378            0 :         register_method(pause);
    1379            0 :         register_method(resume);
    1380            0 :         register_method(register_monitor);
    1381            0 :         register_method(unregister_monitor);
    1382            0 :         register_method(legal_commands);
    1383            0 :         register_method(trace_set);
    1384            0 :         register_method(trace_get);
    1385            0 :         register_method(meta_command);
    1386            0 :         register_method(rollover_subrun);
    1387            0 :         register_method(add_config_archive_entry);
    1388            0 :         register_method(clear_config_archive);
    1389              : 
    1390            0 :         register_method(shutdown);
    1391              : 
    1392              :         // alias "daq.reset" to the internal shutdown transition
    1393            0 :         xmlrpc_c::methodPtr const ptr_reset(new shutdown_(*this));
    1394            0 :         registry.addMethod("daq.reset", ptr_reset);
    1395              : 
    1396              : #undef register_method
    1397              : 
    1398              :         // JCF, 6/3/15
    1399              : 
    1400              :         // In the following code, I configure a socket to have the
    1401              :         // SO_REUSEADDR option so that once an artdaq process closes, the
    1402              :         // port it was communicating on becomes immediately available
    1403              :         // (desirable if, say, the DAQ program is terminated and then
    1404              :         // immediately restarted)
    1405              : 
    1406              :         // Much of the following code is cribbed from
    1407              :         // http://fossies.org/linux/freeswitch/libs/xmlrpc-c/src/cpp/test/server_abyss.cpp
    1408              : 
    1409              :         // Below, "0" is the default protocol (in this case, given the IPv4
    1410              :         // Protocol Family (PF_INET) and the SOCK_STREAM communication
    1411              :         // method)
    1412              : 
    1413            0 :         XMLRPC_SOCKET socket_file_descriptor = socket(PF_INET, SOCK_STREAM, 0);
    1414              : 
    1415            0 :         if (socket_file_descriptor < 0)
    1416              :         {
    1417            0 :                 throw cet::exception("xmlrpc_commander::run") << "Problem with the socket() call; C-style errno == " << errno << " (" << strerror(errno) << ")";  // NOLINT(cert-err60-cpp)
    1418              :         }
    1419              : 
    1420            0 :         int enable = 1;
    1421            0 :         int retval = setsockopt(socket_file_descriptor,
    1422              :                                 SOL_SOCKET, SO_REUSEADDR,
    1423              :                                 &enable, sizeof(int));
    1424              : 
    1425            0 :         if (retval < 0)
    1426              :         {
    1427            0 :                 throw cet::exception("xmlrpc_commander::run") << "Problem with the call to setsockopt(); C-style errno == " << errno << " (" << strerror(errno) << ")";  // NOLINT(cert-err60-cpp)
    1428              :         }
    1429              : 
    1430              :         struct sockaddr_in sockAddr;
    1431              : 
    1432            0 :         sockAddr.sin_family = AF_INET;
    1433            0 :         sockAddr.sin_port = htons(port_);
    1434            0 :         sockAddr.sin_addr.s_addr = 0;
    1435              : 
    1436            0 :         retval = bind(socket_file_descriptor,
    1437              :                       reinterpret_cast<struct sockaddr*>(&sockAddr),  // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)
    1438              :                       sizeof(sockAddr));
    1439              : 
    1440            0 :         if (retval != 0)
    1441              :         {
    1442            0 :                 close(socket_file_descriptor);
    1443            0 :                 throw cet::exception("xmlrpc_commander::run") << "Problem with the bind() call; C-style errno == " << errno << " (" << strerror(errno) << ")";  // NOLINT(cert-err60-cpp)
    1444              :         }
    1445              : 
    1446            0 :         server = std::make_unique<xmlrpc_c::serverAbyss>(xmlrpc_c::serverAbyss::constrOpt().registryP(&registry).socketFd(socket_file_descriptor));
    1447              : 
    1448              : #if 0
    1449              :                 xmlrpc_c::serverAbyss::shutdown shutdown_obj(&server);
    1450              :                 registry.setShutdown(&shutdown_obj);
    1451              : #endif
    1452              : 
    1453            0 :         TLOG(TLVL_DEBUG + 32) << "running server";
    1454              : 
    1455              :         // JCF, 6/3/15
    1456              : 
    1457              :         // Use a catch block to clean up (i.e., close the socket). An
    1458              :         // opportunity for RAII, although all control paths are limited to
    1459              :         // this section of the file...
    1460              : 
    1461              :         try
    1462              :         {
    1463            0 :                 running_ = true;
    1464            0 :                 server->run();
    1465            0 :                 running_ = false;
    1466              :         }
    1467            0 :         catch (...)
    1468              :         {
    1469            0 :                 TLOG(TLVL_WARNING) << "server threw an exception; closing the socket and rethrowing";
    1470            0 :                 running_ = false;
    1471            0 :                 close(socket_file_descriptor);
    1472            0 :                 throw;
    1473            0 :         }
    1474              : 
    1475            0 :         close(socket_file_descriptor);
    1476              : 
    1477            0 :         unregister_method(init);
    1478            0 :         unregister_method(soft_init);
    1479            0 :         unregister_method(reinit);
    1480            0 :         unregister_method(start);
    1481            0 :         unregister_method(status);
    1482            0 :         unregister_method(report);
    1483            0 :         unregister_method(stop);
    1484            0 :         unregister_method(pause);
    1485            0 :         unregister_method(resume);
    1486            0 :         unregister_method(register_monitor);
    1487            0 :         unregister_method(unregister_monitor);
    1488            0 :         unregister_method(legal_commands);
    1489            0 :         unregister_method(trace_set);
    1490            0 :         unregister_method(trace_get);
    1491            0 :         unregister_method(meta_command);
    1492            0 :         unregister_method(rollover_subrun);
    1493            0 :         unregister_method(add_config_archive_entry);
    1494            0 :         unregister_method(clear_config_archive);
    1495              : 
    1496            0 :         unregister_method(shutdown);
    1497              : 
    1498            0 :         TLOG(TLVL_DEBUG + 32) << "server terminated";
    1499            0 : }
    1500            0 : catch (...)
    1501              : {
    1502            0 :         throw;
    1503            0 : }
    1504              : 
    1505            0 : std::string xmlrpc_commander::send_command_(const std::string& command)
    1506              : {
    1507            0 :         if (serverUrl_.empty())
    1508              :         {
    1509            0 :                 std::stringstream errmsg;
    1510            0 :                 errmsg << "Problem attempting " << command << " XML-RPC call: No server URL set!";
    1511            0 :                 ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
    1512            0 :         }
    1513            0 :         xmlrpc_c::clientSimple myClient;
    1514            0 :         xmlrpc_c::value result;
    1515              : 
    1516              :         try
    1517              :         {
    1518            0 :                 myClient.call(serverUrl_, "daq." + command, "", &result);
    1519              :         }
    1520            0 :         catch (...)
    1521              :         {
    1522            0 :                 std::stringstream errmsg;
    1523            0 :                 errmsg << "Problem attempting " << command << " XML-RPC call on host " << serverUrl_
    1524            0 :                        << "; possible causes are malformed FHiCL or nonexistent process at requested port";
    1525            0 :                 ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
    1526            0 :         }
    1527              : 
    1528            0 :         return xmlrpc_c::value_string(result);
    1529            0 : }
    1530              : 
    1531            0 : std::string xmlrpc_commander::send_command_(const std::string& command, const std::string& arg)
    1532              : {
    1533            0 :         if (serverUrl_.empty())
    1534              :         {
    1535            0 :                 std::stringstream errmsg;
    1536            0 :                 errmsg << "Problem attempting " << command << " XML-RPC call: No server URL set!";
    1537            0 :                 ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
    1538            0 :         }
    1539            0 :         xmlrpc_c::clientSimple myClient;
    1540            0 :         xmlrpc_c::value result;
    1541              : 
    1542              :         try
    1543              :         {
    1544            0 :                 myClient.call(serverUrl_, "daq." + command, "s", &result, arg.c_str());
    1545              :         }
    1546            0 :         catch (...)
    1547              :         {
    1548            0 :                 std::stringstream errmsg;
    1549            0 :                 errmsg << "Problem attempting " << command << " XML-RPC call on host " << serverUrl_
    1550            0 :                        << "; possible causes are malformed FHiCL or nonexistent process at requested port";
    1551            0 :                 ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
    1552            0 :         }
    1553              : 
    1554            0 :         return xmlrpc_c::value_string(result);
    1555            0 : }
    1556              : 
    1557            0 : std::string xmlrpc_commander::send_command_(const std::string& command, const fhicl::ParameterSet& pset, uint64_t timestamp, uint64_t timeout)
    1558              : {
    1559            0 :         if (serverUrl_.empty())
    1560              :         {
    1561            0 :                 std::stringstream errmsg;
    1562            0 :                 errmsg << "Problem attempting " << command << " XML-RPC call: No server URL set!";
    1563            0 :                 ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
    1564            0 :         }
    1565            0 :         xmlrpc_c::clientSimple myClient;
    1566            0 :         xmlrpc_c::value result;
    1567              : 
    1568              :         try
    1569              :         {
    1570            0 :                 myClient.call(serverUrl_, "daq." + command, "sII", &result, pset.to_string().c_str(), timestamp, timeout);
    1571              :         }
    1572            0 :         catch (...)
    1573              :         {
    1574            0 :                 std::stringstream errmsg;
    1575            0 :                 errmsg << "Problem attempting " << command << " XML-RPC call on host " << serverUrl_
    1576            0 :                        << "; possible causes are malformed FHiCL or nonexistent process at requested port";
    1577            0 :                 ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
    1578            0 :         }
    1579              : 
    1580            0 :         return xmlrpc_c::value_string(result);
    1581            0 : }
    1582              : 
    1583            0 : std::string artdaq::xmlrpc_commander::send_command_(const std::string& command, uint64_t a, uint64_t b)
    1584              : {
    1585            0 :         if (serverUrl_.empty())
    1586              :         {
    1587            0 :                 std::stringstream errmsg;
    1588            0 :                 errmsg << "Problem attempting " << command << " XML-RPC call: No server URL set!";
    1589            0 :                 ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
    1590            0 :         }
    1591            0 :         xmlrpc_c::clientSimple myClient;
    1592            0 :         xmlrpc_c::value result;
    1593              : 
    1594              :         try
    1595              :         {
    1596            0 :                 myClient.call(serverUrl_, "daq." + command, "II", &result, a, b);
    1597              :         }
    1598            0 :         catch (...)
    1599              :         {
    1600            0 :                 std::stringstream errmsg;
    1601            0 :                 errmsg << "Problem attempting " << command << " XML-RPC call on host " << serverUrl_
    1602            0 :                        << "; possible causes are malformed FHiCL or nonexistent process at requested port";
    1603            0 :                 ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
    1604            0 :         }
    1605              : 
    1606            0 :         return xmlrpc_c::value_string(result);
    1607            0 : }
    1608              : 
    1609            0 : std::string artdaq::xmlrpc_commander::send_command_(const std::string& command, uint64_t a, uint32_t b)
    1610              : {
    1611            0 :         if (serverUrl_.empty())
    1612              :         {
    1613            0 :                 std::stringstream errmsg;
    1614            0 :                 errmsg << "Problem attempting " << command << " XML-RPC call: No server URL set!";
    1615            0 :                 ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
    1616            0 :         }
    1617            0 :         xmlrpc_c::clientSimple myClient;
    1618            0 :         xmlrpc_c::value result;
    1619              : 
    1620              :         try
    1621              :         {
    1622            0 :                 myClient.call(serverUrl_, "daq." + command, "Ii", &result, a, b);
    1623              :         }
    1624            0 :         catch (...)
    1625              :         {
    1626            0 :                 std::stringstream errmsg;
    1627            0 :                 errmsg << "Problem attempting " << command << " XML-RPC call on host " << serverUrl_
    1628            0 :                        << "; possible causes are malformed FHiCL or nonexistent process at requested port";
    1629            0 :                 ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
    1630            0 :         }
    1631              : 
    1632            0 :         return xmlrpc_c::value_string(result);
    1633            0 : }
    1634              : 
    1635            0 : std::string artdaq::xmlrpc_commander::send_command_(const std::string& command, art::RunID r, uint64_t a, uint64_t b)
    1636              : {
    1637            0 :         if (serverUrl_.empty())
    1638              :         {
    1639            0 :                 std::stringstream errmsg;
    1640            0 :                 errmsg << "Problem attempting " << command << " XML-RPC call: No server URL set!";
    1641            0 :                 ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
    1642            0 :         }
    1643            0 :         xmlrpc_c::clientSimple myClient;
    1644            0 :         xmlrpc_c::value result;
    1645              : 
    1646              :         try
    1647              :         {
    1648            0 :                 myClient.call(serverUrl_, "daq." + command, "iII", &result, r.run(), a, b);
    1649              :         }
    1650            0 :         catch (...)
    1651              :         {
    1652            0 :                 std::stringstream errmsg;
    1653            0 :                 errmsg << "Problem attempting " << command << " XML-RPC call on host " << serverUrl_
    1654            0 :                        << "; possible causes are malformed FHiCL or nonexistent process at requested port";
    1655            0 :                 ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
    1656            0 :         }
    1657              : 
    1658            0 :         return xmlrpc_c::value_string(result);
    1659            0 : }
    1660              : 
    1661            0 : std::string artdaq::xmlrpc_commander::send_command_(const std::string& command, uint64_t arg1)
    1662              : {
    1663            0 :         if (serverUrl_.empty())
    1664              :         {
    1665            0 :                 std::stringstream errmsg;
    1666            0 :                 errmsg << "Problem attempting " << command << " XML-RPC call: No server URL set!";
    1667            0 :                 ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
    1668            0 :         }
    1669            0 :         xmlrpc_c::clientSimple myClient;
    1670            0 :         xmlrpc_c::value result;
    1671              : 
    1672              :         try
    1673              :         {
    1674            0 :                 myClient.call(serverUrl_, "daq." + command, "I", &result, arg1);
    1675              :         }
    1676            0 :         catch (...)
    1677              :         {
    1678            0 :                 std::stringstream errmsg;
    1679            0 :                 errmsg << "Problem attempting " << command << " XML-RPC call on host " << serverUrl_
    1680            0 :                        << "; possible causes are malformed FHiCL or nonexistent process at requested port";
    1681            0 :                 ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
    1682            0 :         }
    1683              : 
    1684            0 :         return xmlrpc_c::value_string(result);
    1685            0 : }
    1686              : 
    1687            0 : std::string artdaq::xmlrpc_commander::send_command_(const std::string& command, const std::string& arg1, const std::string& arg2)
    1688              : {
    1689            0 :         if (serverUrl_.empty())
    1690              :         {
    1691            0 :                 std::stringstream errmsg;
    1692            0 :                 errmsg << "Problem attempting " << command << " XML-RPC call: No server URL set!";
    1693            0 :                 ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
    1694            0 :         }
    1695            0 :         xmlrpc_c::clientSimple myClient;
    1696            0 :         xmlrpc_c::value result;
    1697              : 
    1698              :         try
    1699              :         {
    1700            0 :                 myClient.call(serverUrl_, "daq." + command, "ss", &result, arg1.c_str(), arg2.c_str());
    1701              :         }
    1702            0 :         catch (...)
    1703              :         {
    1704            0 :                 std::stringstream errmsg;
    1705            0 :                 errmsg << "Problem attempting " << command << " XML-RPC call on host " << serverUrl_
    1706            0 :                        << "; possible causes are malformed FHiCL or nonexistent process at requested port";
    1707            0 :                 ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
    1708            0 :         }
    1709              : 
    1710            0 :         return xmlrpc_c::value_string(result);
    1711            0 : }
    1712              : 
    1713            0 : std::string artdaq::xmlrpc_commander::send_command_(const std::string& command, const std::string& arg1, const std::string& arg2, const std::string& arg3)
    1714              : {
    1715            0 :         if (serverUrl_.empty())
    1716              :         {
    1717            0 :                 std::stringstream errmsg;
    1718            0 :                 errmsg << "Problem attempting " << command << " XML-RPC call: No server URL set!";
    1719            0 :                 ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
    1720            0 :         }
    1721            0 :         xmlrpc_c::clientSimple myClient;
    1722            0 :         xmlrpc_c::value result;
    1723              : 
    1724              :         try
    1725              :         {
    1726            0 :                 myClient.call(serverUrl_, "daq." + command, "sss", &result, arg1.c_str(), arg2.c_str(), arg3.c_str());
    1727              :         }
    1728            0 :         catch (...)
    1729              :         {
    1730            0 :                 std::stringstream errmsg;
    1731            0 :                 errmsg << "Problem attempting " << command << " XML-RPC call on host " << serverUrl_
    1732            0 :                        << "; possible causes are bad arguments or nonexistent process at requested port";
    1733            0 :                 ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
    1734            0 :         }
    1735              : 
    1736            0 :         return xmlrpc_c::value_string(result);
    1737            0 : }
    1738              : 
    1739            0 : std::string xmlrpc_commander::send_register_monitor(std::string const& monitor_fhicl)
    1740              : {
    1741            0 :         return send_command_("register_monitor", monitor_fhicl);
    1742              : }
    1743            0 : std::string xmlrpc_commander::send_unregister_monitor(std::string const& monitor_label)
    1744              : {
    1745            0 :         return send_command_("unregister_monitor", monitor_label);
    1746              : }
    1747            0 : std::string artdaq::xmlrpc_commander::send_init(fhicl::ParameterSet const& ps, uint64_t timeout, uint64_t timestamp)
    1748              : {
    1749            0 :         return send_command_("init", ps, timeout, timestamp);
    1750              : }
    1751            0 : std::string artdaq::xmlrpc_commander::send_soft_init(fhicl::ParameterSet const& ps, uint64_t timeout, uint64_t timestamp)
    1752              : {
    1753            0 :         return send_command_("soft_init", ps, timeout, timestamp);
    1754              : }
    1755            0 : std::string xmlrpc_commander::send_reinit(fhicl::ParameterSet const& ps, uint64_t timeout, uint64_t timestamp)
    1756              : {
    1757            0 :         return send_command_("reinit", ps, timeout, timestamp);
    1758              : }
    1759            0 : std::string xmlrpc_commander::send_start(art::RunID run, uint64_t timeout, uint64_t timestamp)
    1760              : {
    1761            0 :         return send_command_("start", run, timeout, timestamp);
    1762              : }
    1763            0 : std::string xmlrpc_commander::send_pause(uint64_t timeout, uint64_t timestamp)
    1764              : {
    1765            0 :         return send_command_("pause", timeout, timestamp);
    1766              : }
    1767            0 : std::string xmlrpc_commander::send_resume(uint64_t timeout, uint64_t timestamp)
    1768              : {
    1769            0 :         return send_command_("resume", timeout, timestamp);
    1770              : }
    1771            0 : std::string xmlrpc_commander::send_stop(uint64_t timeout, uint64_t timestamp)
    1772              : {
    1773            0 :         return send_command_("stop", timeout, timestamp);
    1774              : }
    1775            0 : std::string xmlrpc_commander::send_shutdown(uint64_t timeout)
    1776              : {
    1777            0 :         return send_command_("shutdown", timeout);
    1778              : }
    1779            0 : std::string xmlrpc_commander::send_status()
    1780              : {
    1781            0 :         return send_command_("status");
    1782              : }
    1783            0 : std::string xmlrpc_commander::send_report(std::string const& what)
    1784              : {
    1785            0 :         return send_command_("report", what);
    1786              : }
    1787            0 : std::string xmlrpc_commander::send_legal_commands()
    1788              : {
    1789            0 :         return send_command_("legal_commands");
    1790              : }
    1791            0 : std::string xmlrpc_commander::send_trace_get(std::string const& name)
    1792              : {
    1793            0 :         return send_command_("trace_get", name);
    1794              : }
    1795            0 : std::string xmlrpc_commander::send_trace_set(std::string const& name, std::string const& type, std::string const& mask)
    1796              : {
    1797            0 :         return send_command_("trace_set", name, type, mask);
    1798              : }
    1799            0 : std::string xmlrpc_commander::send_meta_command(std::string const& command, std::string const& arg)
    1800              : {
    1801            0 :         return send_command_("meta_command", command, arg);
    1802              : }
    1803            0 : std::string xmlrpc_commander::send_rollover_subrun(uint64_t when, uint32_t sr)
    1804              : {
    1805            0 :         return send_command_("rollover_subrun", when, sr);
    1806              : }
    1807              : }  // namespace artdaq
    1808              : 
    1809            0 : DEFINE_ARTDAQ_COMMANDER(artdaq::xmlrpc_commander)
        

Generated by: LCOV version 2.0-1