6 #pragma GCC diagnostic push
7 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
8 #include <xmlrpc-c/base.hpp>
9 #include <xmlrpc-c/registry.hpp>
10 #include <xmlrpc-c/server_abyss.hpp>
11 #include <xmlrpc-c/girerr.hpp>
12 #pragma GCC diagnostic pop
19 #include <sys/socket.h>
20 #include <netinet/in.h>
24 #include "canvas/Persistency/Provenance/RunID.h"
26 #include "artdaq/ExternalComms/xmlrpc_commander.hh"
27 #include "artdaq/DAQdata/Globals.hh"
28 #include "fhiclcpp/make_ParameterSet.h"
39 const std::string& helpText =
"execute request")
41 std::string msg(
"Exception when trying to ");
44 msg.append(er.what());
45 if (msg[msg.size() - 1] ==
'\n') msg.erase(msg.size() - 1);
56 const std::string& helpText)
58 std::string msg(
"Exception when trying to ");
61 msg.append(er.what());
62 if (msg[msg.size() - 1] ==
'\n') msg.erase(msg.size() - 1);
73 const std::string& helpText)
75 std::string msg(
"Exception when trying to ");
78 msg.append(er.what());
79 if (msg[msg.size() - 1] ==
'\n') msg.erase(msg.size() - 1);
90 const std::string& helpText)
92 std::string msg(
"Exception when trying to ");
96 if (msg[msg.size() - 1] ==
'\n') msg.erase(msg.size() - 1);
118 class cmd_ :
public xmlrpc_c::method
131 _signature = signature;
140 void execute(
const xmlrpc_c::paramList& paramList, xmlrpc_c::value*
const retvalP)
final;
151 virtual bool execute_(
const xmlrpc_c::paramList&, xmlrpc_c::value*
const retvalP) = 0;
162 template <
typename T>
163 T
getParam(
const xmlrpc_c::paramList& paramList,
int index);
188 template <
typename T>
189 T
getParam(
const xmlrpc_c::paramList& paramList,
int index, T default_value);
195 template <
typename T>
198 throw cet::exception(
"cmd_") <<
"Error in cmd_::getParam(): value type not supported" << std::endl;
210 uint64_t cmd_::getParam<uint64_t>(
const xmlrpc_c::paramList& paramList,
int index)
212 return boost::lexical_cast<uint64_t>(paramList.getInt(index));
224 std::string cmd_::getParam<std::string>(
const xmlrpc_c::paramList& paramList,
int index)
226 return static_cast<std::string
>(paramList.getString(index));
238 art::RunID cmd_::getParam<art::RunID>(
const xmlrpc_c::paramList& paramList,
int index)
240 std::string run_number_string = paramList.getString(index);
241 art::RunNumber_t run_number =
242 boost::lexical_cast<art::RunNumber_t>(run_number_string);
243 art::RunID run_id(run_number);
257 fhicl::ParameterSet cmd_::getParam<fhicl::ParameterSet>(
const xmlrpc_c::paramList& paramList,
int index)
259 std::string configString = paramList.getString(index);
260 fhicl::ParameterSet pset;
261 fhicl::make_ParameterSet(configString, pset);
266 template <
typename T>
270 T val = default_value;
274 val = getParam<T>(paramList, index);
276 catch (
const cet::exception& exception)
285 void cmd_::execute(
const xmlrpc_c::paramList& paramList, xmlrpc_c::value*
const retvalP)
287 std::unique_lock<std::mutex> lk(
_c.
mutex_, std::try_to_lock);
304 if (!retvalP->isInstantiated())
306 *retvalP = xmlrpc_c::value_string(
"Success");
312 *retvalP = xmlrpc_c::value_string(problemReport);
315 catch (std::runtime_error& er)
318 *retvalP = xmlrpc_c::value_string(msg);
319 TLOG_ERROR(
"XMLRPC_Commander") << msg << TLOG_ENDL;
321 catch (art::Exception& er)
324 *retvalP = xmlrpc_c::value_string(msg);
325 TLOG_ERROR(
"XMLRPC_Commander") << msg << TLOG_ENDL;
327 catch (cet::exception& er)
330 *retvalP = xmlrpc_c::value_string(msg);
331 TLOG_ERROR(
"XMLRPC_Commander") << msg << TLOG_ENDL;
336 *retvalP = xmlrpc_c::value_string(msg);
337 TLOG_ERROR(
"XMLRPC_Commander") << msg << TLOG_ENDL;
342 *retvalP = xmlrpc_c::value_string(
"busy");
355 #define GENERATE_INIT_TRANSITION(NAME, CALL, DESCRIPTION) \
357 class NAME ## _: public cmd_ { \
363 explicit NAME ## _(xmlrpc_commander& c): \
364 cmd_(c, "s:sii", DESCRIPTION) {} \
367 static const uint64_t defaultTimeout = 45; \
369 static const uint64_t defaultTimestamp = std::numeric_limits<const uint64_t>::max(); \
372 bool execute_(const xmlrpc_c::paramList& paramList, xmlrpc_c::value* const retvalP ) { \
375 getParam<fhicl::ParameterSet>(paramList, 0); \
377 *retvalP = xmlrpc_c::value_string ("The "#NAME" message requires a single argument that is a string containing the initialization ParameterSet"); \
381 return _c._commandable.CALL( getParam<fhicl::ParameterSet>(paramList, 0), \
382 getParam<uint64_t>(paramList, 1, defaultTimeout), \
383 getParam<uint64_t>(paramList, 2, defaultTimestamp) \
388 GENERATE_INIT_TRANSITION(init, initialize,
"initialize the program")
390 GENERATE_INIT_TRANSITION(soft_init, soft_initialize, "initialize software components in the program")
392 GENERATE_INIT_TRANSITION(reinit, reinitialize, "re-initialize the program")
394 #undef GENERATE_INIT_TRANSITION
409 cmd_(c,
"s:iii",
"start the run") {}
418 bool execute_(xmlrpc_c::paramList
const& paramList, xmlrpc_c::value*
const retvalP)
override
422 getParam<art::RunID>(paramList, 0);
426 *retvalP = xmlrpc_c::value_string(
"The start message requires the run number as an argument.");
446 #define GENERATE_TIMEOUT_TIMESTAMP_TRANSITION(NAME, CALL, DESCRIPTION, TIMEOUT) \
448 class NAME ## _: public cmd_ { \
453 NAME ## _(xmlrpc_commander& c): \
454 cmd_(c, "s:ii", DESCRIPTION) {} \
457 static const uint64_t defaultTimeout = TIMEOUT ; \
459 static const uint64_t defaultTimestamp = std::numeric_limits<const uint64_t>::max(); \
463 bool execute_ (const xmlrpc_c::paramList& paramList , xmlrpc_c::value* const ) { \
465 return _c._commandable.CALL( getParam<uint64_t>(paramList, 0, defaultTimeout), \
466 getParam<uint64_t>(paramList, 1, defaultTimestamp) \
471 GENERATE_TIMEOUT_TIMESTAMP_TRANSITION(pause, pause,
"pause the program", 45)
473 GENERATE_TIMEOUT_TIMESTAMP_TRANSITION(resume, resume, "resume the program", 45)
475 GENERATE_TIMEOUT_TIMESTAMP_TRANSITION(stop, stop, "stop the program", 45)
477 #undef GENERATE_TIMEOUT_TIMESTAMP_TRANSITION
491 cmd_(c,
"s:i",
"shutdown the program") {}
498 bool execute_(
const xmlrpc_c::paramList& paramList, xmlrpc_c::value*
const)
516 cmd_(c,
"s:n",
"report the current state") {}
520 bool execute_(xmlrpc_c::paramList
const&, xmlrpc_c::value*
const retvalP)
539 cmd_(c,
"s:s",
"report statistics") {}
542 bool execute_(xmlrpc_c::paramList
const& paramList, xmlrpc_c::value*
const retvalP)
546 getParam<std::string>(paramList, 0);
550 *retvalP = xmlrpc_c::value_string(
"The report message requires a single argument that selects the type of statistics to be reported.");
571 cmd_(c,
"s:s",
"reset statistics") {}
574 bool execute_(xmlrpc_c::paramList
const& paramList, xmlrpc_c::value*
const retvalP)
578 getParam<std::string>(paramList, 0);
582 *retvalP = xmlrpc_c::value_string(
"The reset_stats message requires a single argument that selects the type of statistics to be reported.");
601 cmd_(c,
"s:n",
"return the currently legal commands") {}
604 bool execute_(xmlrpc_c::paramList
const&, xmlrpc_c::value*
const retvalP)
607 std::string resultString;
609 for (
auto& cmd : cmdList)
611 resultString.append(cmd +
" ");
612 if (cmd ==
"shutdown")
614 resultString.append(
" reset");
617 *retvalP = xmlrpc_c::value_string(resultString);
634 cmd_(c,
"s:s",
"Get notified of a new monitor") {}
637 bool execute_(xmlrpc_c::paramList
const& paramList, xmlrpc_c::value*
const retvalP)
641 getParam<fhicl::ParameterSet>(paramList, 0);
645 *retvalP = xmlrpc_c::value_string(
"The register_monitor command expects a string representing the FHiCL definition of a Transfer plugin");
665 cmd_(c,
"s:s",
"Remove a monitor") {}
668 bool execute_(xmlrpc_c::paramList
const& paramList, xmlrpc_c::value*
const retvalP)
672 getParam<std::string>(paramList, 0);
676 *retvalP = xmlrpc_c::value_string(
"The unregister_monitor command expects a string representing the label of the monitor to be removed");
692 class shutdown_ :
public xmlrpc_c::registry::shutdown {
694 shutdown_(xmlrpc_c::serverAbyss *server) : _server(server) {}
696 virtual void doit(
const std::string& paramString,
void*)
const {
697 TLOG_INFO(
"XMLRPC_Commander") <<
"A shutdown command was sent "
699 << paramString <<
"\"" << TLOG_ENDL;
700 _server->terminate();
703 xmlrpc_c::serverAbyss *_server;
711 , _commandable(commandable) {}
715 xmlrpc_c::registry registry;
717 #define register_method(m) \
718 xmlrpc_c::methodPtr const ptr_ ## m(new m ## _(*this));\
719 registry.addMethod ("daq." #m, ptr_ ## m);
721 register_method(init);
722 register_method(soft_init);
723 register_method(reinit);
724 register_method(start);
725 register_method(status);
726 register_method(report);
727 register_method(stop);
728 register_method(pause);
729 register_method(resume);
730 register_method(reset_stats);
731 register_method(register_monitor);
732 register_method(unregister_monitor);
733 register_method(legal_commands);
735 register_method(shutdown);
738 xmlrpc_c::methodPtr
const ptr_reset(
new shutdown_(*
this));
739 registry.addMethod(
"daq.reset", ptr_reset);
741 #undef register_method
758 XMLRPC_SOCKET socket_file_descriptor = socket(PF_INET, SOCK_STREAM, 0);
760 if (socket_file_descriptor < 0)
762 throw cet::exception(
"xmlrpc_commander::run") <<
763 "Problem with the socket() call; C-style errno == " <<
764 errno <<
" (" << strerror(errno) <<
")";
768 int retval = setsockopt(socket_file_descriptor,
769 SOL_SOCKET, SO_REUSEADDR,
770 &enable,
sizeof(
int));
774 throw cet::exception(
"xmlrpc_commander::run") <<
775 "Problem with the call to setsockopt(); C-style errno == " <<
776 errno <<
" (" << strerror(errno) <<
")";
779 struct sockaddr_in sockAddr;
781 sockAddr.sin_family = AF_INET;
782 sockAddr.sin_port = htons(_port);
783 sockAddr.sin_addr.s_addr = 0;
785 retval = bind(socket_file_descriptor,
786 reinterpret_cast<struct sockaddr*>(&sockAddr),
791 close(socket_file_descriptor);
792 throw cet::exception(
"xmlrpc_commander::run") <<
793 "Problem with the bind() call; C-style errno == " <<
794 errno <<
" (" << strerror(errno) <<
")";
797 xmlrpc_c::serverAbyss server(xmlrpc_c::serverAbyss::constrOpt().registryP(®istry).socketFd(socket_file_descriptor));
801 registry.setShutdown(&shutdown_obj);
804 TLOG_DEBUG(
"XMLRPC_Commander") <<
"running server" << TLOG_ENDL;
818 TLOG_WARNING(
"XMLRPC_Commander") <<
"server threw an exception; closing the socket and rethrowing" << TLOG_ENDL;
819 close(socket_file_descriptor);
823 close(socket_file_descriptor);
824 TLOG_DEBUG(
"XMLRPC_Commander") <<
"server terminated" << TLOG_ENDL;
cmd_(xmlrpc_commander &c, const std::string &signature, const std::string &description)
cmd_ Constructor
static const uint64_t defaultTimeout
virtual std::string report(std::string const &) const
Default report implementation returns current report_string.
Commandable is the base class for all artdaq components which implement the artdaq state machine...
legal_commands_(xmlrpc_commander &c)
legal_commands_ Constructor
Command class representing a start transition.
virtual std::string unregister_monitor(std::string const &)
Perform the unregister_monitor action.
The xmlrpc_commander class serves as the XMLRPC server run in each artdaq application.
static const uint64_t defaultTimestamp
The "cmd_" class serves as the base class for all artdaq's XML-RPC commands.
std::string status() const
Returns the current state of the Commandable.
std::string exception_msg(const std::runtime_error &er, const std::string &helpText="execute request")
Write an exception message.
virtual std::string register_monitor(fhicl::ParameterSet const &)
Perform the register_monitor action.
register_monitor_ Command class
virtual bool reset_stats(std::string const &which)
Virutal function which resets statistics.
legal_commands_ Command class
xmlrpc_commander & _c
The xmlrpc_commander instance that the command will be sent to.
status_(xmlrpc_commander &c)
status_ Constructor
virtual bool execute_(const xmlrpc_c::paramList &, xmlrpc_c::value *const retvalP)=0
"execute_" is a wrapper function around the call to the commandable object's function ...
register_monitor_(xmlrpc_commander &c)
register_monitor_ Constructor
static const uint64_t defaultTimeout
unregister_monitor_(xmlrpc_commander &c)
unregister_monitor_ Constructor
void execute(const xmlrpc_c::paramList ¶mList, xmlrpc_c::value *const retvalP) final
Execute trhe command with the given parameters.
shutdown_(xmlrpc_commander &c)
shutdown_ Constructor
reset_stats_(xmlrpc_commander &c)
reset_stats_ Constructor
artdaq::Commandable & _commandable
The artdaq::Commandable object that this xmlrpc_commander sends commands to.
std::vector< std::string > legal_commands() const
Get the legal transition commands from the current state.
bool start(art::RunID id, uint64_t timeout, uint64_t timestamp)
Processes the start transition.
reset_stats_ Command class
report_(xmlrpc_commander &c)
report_ Constructor
xmlrpc_commander(int port, artdaq::Commandable &commandable)
xmlrpc_commander Constructor
start_(xmlrpc_commander &c)
start_ Command (cmd_ derived class) Constructor
void run()
Run the XMLRPC server.
std::mutex mutex_
XMLRPC mutex.
unregister_monitor_ Command class
T getParam(const xmlrpc_c::paramList ¶mList, int index)
Get a parameter from the parameter list.
bool shutdown(uint64_t timeout)
Processes the shutdown transition.