6 #pragma GCC diagnostic push
7 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
8 #define _LIBCPP_ENABLE_CXX17_REMOVED_FEATURES 1
9 #include <xmlrpc-c/base.hpp>
10 #include <xmlrpc-c/registry.hpp>
11 #include <xmlrpc-c/server_abyss.hpp>
12 #include <xmlrpc-c/girerr.hpp>
13 #include <xmlrpc-c/client_simple.hpp>
14 #undef _LIBCPP_ENABLE_CXX17_REMOVED_FEATURES
15 #pragma GCC diagnostic pop
21 #define TRACE_NAME "xmlrpc_commander"
24 #include "artdaq-core/Utilities/ExceptionHandler.hh"
25 #include <sys/socket.h>
26 #include <netinet/in.h>
31 #include "canvas/Persistency/Provenance/RunID.h"
32 #include "fhiclcpp/make_ParameterSet.h"
34 #include "artdaq/ExternalComms/xmlrpc_commander.hh"
35 #include "artdaq/DAQdata/Globals.hh"
41 env_wrap() { xmlrpc_env_init(&this->env_c); };
42 ~
env_wrap() { xmlrpc_env_clean(&this->env_c); };
46 static xmlrpc_c::paramList
47 pListFromXmlrpcArray(xmlrpc_value *
const arrayP)
50 XMLRPC_ASSERT_ARRAY_OK(arrayP);
51 unsigned int const arraySize = xmlrpc_array_size(&env.env_c, arrayP);
52 assert(!env.env_c.fault_occurred);
53 xmlrpc_c::paramList paramList(arraySize);
54 for (
unsigned int i = 0; i < arraySize; ++i) {
55 xmlrpc_value * arrayItemP;
56 xmlrpc_array_read_item(&env.env_c, arrayP, i, &arrayItemP);
57 assert(!env.env_c.fault_occurred);
58 paramList.add(xmlrpc_c::value(arrayItemP));
59 xmlrpc_DECREF(arrayItemP);
64 c_executeMethod(xmlrpc_env *
const envP,
65 xmlrpc_value *
const paramArrayP,
66 void *
const methodPtr,
67 void *
const callInfoPtr)
69 xmlrpc_c::method *
const methodP(static_cast<xmlrpc_c::method *>(methodPtr));
70 xmlrpc_c::paramList
const paramList(pListFromXmlrpcArray(paramArrayP));
71 xmlrpc_c::callInfo *
const callInfoP(static_cast<xmlrpc_c::callInfo *>(callInfoPtr));
72 xmlrpc_value * retval;
75 xmlrpc_c::value result;
77 xmlrpc_c::method2 *
const method2P(dynamic_cast<xmlrpc_c::method2 *>(methodP));
79 method2P->execute(paramList, callInfoP, &result);
81 methodP->execute(paramList, &result);
83 catch (xmlrpc_c::fault
const& fault) {
84 xmlrpc_env_set_fault(envP, fault.getCode(),
85 fault.getDescription().c_str());
87 if (!envP->fault_occurred) {
88 if (result.isInstantiated())
89 retval = result.cValue();
91 girerr::throwf(
"Xmlrpc-c user's xmlrpc_c::method object's "
92 "'execute method' failed to set the RPC result "
96 catch (std::exception
const& e) {
97 xmlrpc_faultf(envP,
"Unexpected error executing code for "
98 "particular method, detected by Xmlrpc-c "
99 "method registry code. Method did not "
100 "fail; rather, it did not complete at all. %s",
104 xmlrpc_env_set_fault(envP, XMLRPC_INTERNAL_ERROR,
105 "Unexpected error executing code for "
106 "particular method, detected by Xmlrpc-c "
107 "method registry code. Method did not "
108 "fail; rather, it did not complete at all.");
124 const std::string& helpText =
"execute request")
126 std::string msg(
"Exception when trying to ");
127 msg.append(helpText);
129 msg.append(er.what());
130 if (msg[msg.size() - 1] ==
'\n') msg.erase(msg.size() - 1);
141 const std::string& helpText)
143 std::string msg(
"Exception when trying to ");
144 msg.append(helpText);
146 msg.append(er.what());
147 if (msg[msg.size() - 1] ==
'\n') msg.erase(msg.size() - 1);
158 const std::string& helpText)
160 std::string msg(
"Exception when trying to ");
161 msg.append(helpText);
163 msg.append(er.what());
164 if (msg[msg.size() - 1] ==
'\n') msg.erase(msg.size() - 1);
175 const std::string& helpText)
177 std::string msg(
"Exception when trying to ");
178 msg.append(helpText);
181 if (msg[msg.size() - 1] ==
'\n') msg.erase(msg.size() - 1);
203 class cmd_ :
public xmlrpc_c::method
216 _signature = signature;
225 void execute(
const xmlrpc_c::paramList& paramList, xmlrpc_c::value*
const retvalP)
final;
236 virtual bool execute_(
const xmlrpc_c::paramList&, xmlrpc_c::value*
const retvalP) = 0;
247 template <
typename T>
248 T
getParam(
const xmlrpc_c::paramList& paramList,
int index);
273 template <
typename T>
274 T
getParam(
const xmlrpc_c::paramList& paramList,
int index, T default_value);
280 template <
typename T>
283 throw cet::exception(
"cmd_") <<
"Error in cmd_::getParam(): value type not supported" << std::endl;
295 uint64_t cmd_::getParam<uint64_t>(
const xmlrpc_c::paramList& paramList,
int index)
297 TLOG(TLVL_TRACE) <<
"Getting parameter " << index <<
" from list as uint64_t.";
298 TLOG(TLVL_TRACE) <<
"Param value: " << paramList.getString(index);
299 return boost::lexical_cast<uint64_t>(paramList.getString(index));
311 std::string cmd_::getParam<std::string>(
const xmlrpc_c::paramList& paramList,
int index)
313 TLOG(TLVL_TRACE) <<
"Getting parameter " << index <<
" from list as string.";
314 TLOG(TLVL_TRACE) <<
"Param value: " << paramList.getString(index);
315 return static_cast<std::string
>(paramList.getString(index));
327 art::RunID cmd_::getParam<art::RunID>(
const xmlrpc_c::paramList& paramList,
int index)
329 TLOG(TLVL_TRACE) <<
"Getting parameter " << index <<
" from list as Run Number.";
330 TLOG(TLVL_TRACE) <<
"Param value: " << paramList.getString(index);
331 std::string run_number_string = paramList.getString(index);
332 art::RunNumber_t run_number =
333 boost::lexical_cast<art::RunNumber_t>(run_number_string);
334 art::RunID run_id(run_number);
348 fhicl::ParameterSet cmd_::getParam<fhicl::ParameterSet>(
const xmlrpc_c::paramList& paramList,
int index)
350 TLOG(TLVL_TRACE) <<
"Getting parameter " << index <<
" from list as ParameterSet.";
351 TLOG(TLVL_TRACE) <<
"Param value: " << paramList.getString(index);
352 std::string configString = std::string(paramList.getString(index).c_str());
353 TLOG(TLVL_DEBUG) <<
"Loading Parameter Set from string: " << configString << std::endl;
354 fhicl::ParameterSet pset;
358 fhicl::make_ParameterSet(configString, pset);
360 catch (fhicl::exception e)
362 if (getenv(
"FHICL_FILE_PATH") ==
nullptr)
364 std::cerr <<
"INFO: environment variable FHICL_FILE_PATH was not set. Using \".\"\n";
365 setenv(
"FHICL_FILE_PATH",
".", 0);
367 cet::filepath_lookup_after1 lookup_policy(
"FHICL_FILE_PATH");
368 fhicl::make_ParameterSet(configString, lookup_policy, pset);
371 TLOG(TLVL_INFO) <<
"Parameter Set Loaded." << std::endl;
375 template <
typename T>
379 T val = default_value;
383 val = getParam<T>(paramList, index);
385 catch (
const cet::exception& exception)
394 void cmd_::execute(
const xmlrpc_c::paramList& paramList, xmlrpc_c::value*
const retvalP)
396 std::unique_lock<std::timed_mutex> lk(
_c.
mutex_, std::chrono::milliseconds(250));
413 if (!retvalP->isInstantiated())
415 *retvalP = xmlrpc_c::value_string(
"Success");
421 *retvalP = xmlrpc_c::value_string(problemReport);
424 catch (std::runtime_error& er)
427 *retvalP = xmlrpc_c::value_string(msg);
428 TLOG(TLVL_ERROR) << msg ;
430 catch (art::Exception& er)
433 *retvalP = xmlrpc_c::value_string(msg);
434 TLOG(TLVL_ERROR) << msg ;
436 catch (cet::exception& er)
439 *retvalP = xmlrpc_c::value_string(msg);
440 TLOG(TLVL_ERROR) << msg ;
445 *retvalP = xmlrpc_c::value_string(msg);
446 TLOG(TLVL_ERROR) << msg ;
451 *retvalP = xmlrpc_c::value_string(
"busy");
464 #define GENERATE_INIT_TRANSITION(NAME, CALL, DESCRIPTION) \
466 class NAME ## _: public cmd_ { \
472 explicit NAME ## _(xmlrpc_commander& c): \
473 cmd_(c, "s:sii", DESCRIPTION) {} \
476 static const uint64_t defaultTimeout = 45; \
478 static const uint64_t defaultTimestamp = std::numeric_limits<const uint64_t>::max(); \
481 bool execute_(const xmlrpc_c::paramList& paramList, xmlrpc_c::value* const retvalP ) { \
482 fhicl::ParameterSet ps; \
484 ps = getParam<fhicl::ParameterSet>(paramList, 0); \
486 *retvalP = xmlrpc_c::value_string ("The "#NAME" message requires a single argument that is a string containing the initialization ParameterSet"); \
490 return _c._commandable.CALL(ps, \
491 getParam<uint64_t>(paramList, 1, defaultTimeout), \
492 getParam<uint64_t>(paramList, 2, defaultTimestamp) \
497 GENERATE_INIT_TRANSITION(init, initialize,
"initialize the program")
499 GENERATE_INIT_TRANSITION(soft_init, soft_initialize, "initialize software components in the program")
501 GENERATE_INIT_TRANSITION(reinit, reinitialize, "re-initialize the program")
503 #undef GENERATE_INIT_TRANSITION
518 cmd_(c,
"s:iii",
"start the run")
528 bool execute_(xmlrpc_c::paramList
const& paramList, xmlrpc_c::value*
const retvalP)
override
532 getParam<art::RunID>(paramList, 0);
536 *retvalP = xmlrpc_c::value_string(
"The start message requires the run number as an argument.");
556 #define GENERATE_TIMEOUT_TIMESTAMP_TRANSITION(NAME, CALL, DESCRIPTION, TIMEOUT) \
558 class NAME ## _: public cmd_ { \
563 NAME ## _(xmlrpc_commander& c): \
564 cmd_(c, "s:ii", DESCRIPTION) {} \
567 static const uint64_t defaultTimeout = TIMEOUT ; \
569 static const uint64_t defaultTimestamp = std::numeric_limits<const uint64_t>::max(); \
573 bool execute_ (const xmlrpc_c::paramList& paramList , xmlrpc_c::value* const ) { \
575 return _c._commandable.CALL( getParam<uint64_t>(paramList, 0, defaultTimeout), \
576 getParam<uint64_t>(paramList, 1, defaultTimestamp) \
581 GENERATE_TIMEOUT_TIMESTAMP_TRANSITION(pause, pause,
"pause the program", 45)
583 GENERATE_TIMEOUT_TIMESTAMP_TRANSITION(resume, resume, "resume the program", 45)
585 GENERATE_TIMEOUT_TIMESTAMP_TRANSITION(stop, stop, "stop the program", 45)
587 #undef GENERATE_TIMEOUT_TIMESTAMP_TRANSITION
601 cmd_(c,
"s:i",
"shutdown the program")
609 bool execute_(
const xmlrpc_c::paramList& paramList, xmlrpc_c::value*
const)
633 cmd_(c,
"s:n",
"report the current state")
638 bool execute_(xmlrpc_c::paramList
const&, xmlrpc_c::value*
const retvalP)
657 cmd_(c,
"s:s",
"report statistics")
661 bool execute_(xmlrpc_c::paramList
const& paramList, xmlrpc_c::value*
const retvalP)
665 getParam<std::string>(paramList, 0);
669 *retvalP = xmlrpc_c::value_string(
"The report message requires a single argument that selects the type of statistics to be reported.");
689 cmd_(c,
"s:n",
"return the currently legal commands")
693 bool execute_(xmlrpc_c::paramList
const&, xmlrpc_c::value*
const retvalP)
696 std::string resultString;
698 for (
auto& cmd : cmdList)
700 resultString.append(cmd +
" ");
701 if (cmd ==
"shutdown")
703 resultString.append(
" reset");
706 *retvalP = xmlrpc_c::value_string(resultString);
723 cmd_(c,
"s:s",
"Get notified of a new monitor")
727 bool execute_(xmlrpc_c::paramList
const& paramList, xmlrpc_c::value*
const retvalP)
731 getParam<fhicl::ParameterSet>(paramList, 0);
735 *retvalP = xmlrpc_c::value_string(
"The register_monitor command expects a string representing the FHiCL definition of a Transfer plugin");
755 cmd_(c,
"s:s",
"Remove a monitor")
759 bool execute_(xmlrpc_c::paramList
const& paramList, xmlrpc_c::value*
const retvalP)
763 getParam<std::string>(paramList, 0);
767 *retvalP = xmlrpc_c::value_string(
"The unregister_monitor command expects a string representing the label of the monitor to be removed");
788 cmd_(c,
"s:ssi",
"Set TRACE mask")
792 bool execute_(xmlrpc_c::paramList
const& paramList, xmlrpc_c::value*
const retvalP)
796 getParam<std::string>(paramList, 0);
797 getParam<std::string>(paramList, 1);
798 getParam<uint64_t>(paramList, 2);
802 *retvalP = xmlrpc_c::value_string(
"The trace_set command expects a mask type (M, S , or T), a name (ALL for all) and a mask");
806 return _c.
_commandable.
do_trace_set(getParam<std::string>(paramList, 0), getParam<std::string>(paramList, 1), getParam<uint64_t>(paramList, 2));
821 cmd_(c,
"s:s",
"Get TRACE mask")
825 bool execute_(xmlrpc_c::paramList
const& paramList, xmlrpc_c::value*
const retvalP)
829 getParam<std::string>(paramList, 0);
833 *retvalP = xmlrpc_c::value_string(
"The trace_msgfacility_set command expects a name (ALL for all)");
853 cmd_(c,
"s:ss",
"Run custom command")
857 bool execute_(xmlrpc_c::paramList
const& paramList, xmlrpc_c::value*
const retvalP)
861 getParam<std::string>(paramList, 0);
862 getParam<std::string>(paramList, 1);
866 *retvalP = xmlrpc_c::value_string(
"The meta_command command expects a string command and a string argument");
885 cmd_(c,
"s:i",
"create a new subrun")
893 bool execute_(
const xmlrpc_c::paramList& paramList, xmlrpc_c::value*
const)
906 class shutdown_ :
public xmlrpc_c::registry::shutdown
909 shutdown_(xmlrpc_c::serverAbyss *server) : _server(server) {}
911 virtual void doit(
const std::string& paramString,
void*)
const
913 TLOG(TLVL_INFO) <<
"A shutdown command was sent "
915 << paramString <<
"\"" ;
916 _server->terminate();
919 xmlrpc_c::serverAbyss *_server;
927 , port_(ps.get<int>(
"id", 0))
928 , serverUrl_(ps.get<std::string>(
"server_url",
""))
937 xmlrpc_c::registry registry;
938 struct xmlrpc_method_info3 methodInfo;
939 memset(&methodInfo, 0,
sizeof(methodInfo));
944 #define register_method(m) register_method2(m,0x400000)
947 xmlrpc_registry ***c_registryPPP;
948 c_registryPPP = (xmlrpc_registry ***)(((
char*)®istry) +
sizeof(girmem::autoObject));
950 #define register_method2(m,ss) \
951 xmlrpc_c::method * ptr_ ## m(dynamic_cast<xmlrpc_c::method *>(new m ## _(*this))); \
952 methodInfo.methodName = "daq." #m; \
953 methodInfo.methodFunction = &c_executeMethod; \
954 methodInfo.serverInfo = ptr_ ## m; \
955 methodInfo.stackSize = ss; \
956 methodInfo.signatureString = ptr_ ## m ->signature().c_str(); \
957 methodInfo.help = ptr_ ## m ->help().c_str(); \
958 xmlrpc_env_init(&env); \
959 xmlrpc_registry_add_method3(&env,**c_registryPPP,&methodInfo); \
960 if(env.fault_occurred)throw(girerr::error(env.fault_string)); \
961 xmlrpc_env_clean(&env)
963 register_method2(init, 0x200000);
964 register_method(soft_init);
965 register_method(reinit);
966 register_method(start);
967 register_method(status);
968 register_method(report);
969 register_method(stop);
970 register_method(pause);
971 register_method(resume);
972 register_method(register_monitor);
973 register_method(unregister_monitor);
974 register_method(legal_commands);
975 register_method(trace_set);
976 register_method(trace_get);
977 register_method(meta_command);
978 register_method(rollover_subrun);
980 register_method(shutdown);
983 xmlrpc_c::methodPtr
const ptr_reset(
new shutdown_(*
this));
984 registry.addMethod(
"daq.reset", ptr_reset);
986 #undef register_method
1003 XMLRPC_SOCKET socket_file_descriptor = socket(PF_INET, SOCK_STREAM, 0);
1005 if (socket_file_descriptor < 0)
1007 throw cet::exception(
"xmlrpc_commander::run") <<
1008 "Problem with the socket() call; C-style errno == " <<
1009 errno <<
" (" << strerror(errno) <<
")";
1013 int retval = setsockopt(socket_file_descriptor,
1014 SOL_SOCKET, SO_REUSEADDR,
1015 &enable,
sizeof(
int));
1019 throw cet::exception(
"xmlrpc_commander::run") <<
1020 "Problem with the call to setsockopt(); C-style errno == " <<
1021 errno <<
" (" << strerror(errno) <<
")";
1024 struct sockaddr_in sockAddr;
1026 sockAddr.sin_family = AF_INET;
1027 sockAddr.sin_port = htons(port_);
1028 sockAddr.sin_addr.s_addr = 0;
1030 retval = bind(socket_file_descriptor,
1031 reinterpret_cast<struct sockaddr*>(&sockAddr),
1036 close(socket_file_descriptor);
1037 throw cet::exception(
"xmlrpc_commander::run") <<
1038 "Problem with the bind() call; C-style errno == " <<
1039 errno <<
" (" << strerror(errno) <<
")";
1042 server.reset(
new xmlrpc_c::serverAbyss(xmlrpc_c::serverAbyss::constrOpt().registryP(®istry).socketFd(socket_file_descriptor)));
1045 xmlrpc_c::serverAbyss::shutdown shutdown_obj(&
server);
1046 registry.setShutdown(&shutdown_obj);
1049 TLOG(TLVL_DEBUG) <<
"running server" ;
1063 TLOG(TLVL_WARNING) <<
"server threw an exception; closing the socket and rethrowing" ;
1064 close(socket_file_descriptor);
1068 close(socket_file_descriptor);
1069 TLOG(TLVL_DEBUG) <<
"server terminated" ;
1079 if (serverUrl_ ==
"")
1081 std::stringstream errmsg;
1082 errmsg <<
"Problem attempting XML-RPC call: No server URL set!";
1083 ExceptionHandler(ExceptionHandlerRethrow::yes,
1087 xmlrpc_c::clientSimple myClient;
1088 xmlrpc_c::value result;
1092 myClient.call(serverUrl_,
"daq.register_monitor",
"s", &result, monitor_fhicl.c_str());
1096 std::stringstream errmsg;
1097 errmsg <<
"Problem attempting XML-RPC call on host " << serverUrl_
1098 <<
"; possible causes are malformed FHiCL or nonexistent process at requested port";
1099 ExceptionHandler(ExceptionHandlerRethrow::yes,
1103 return xmlrpc_c::value_string(result);
1108 if (serverUrl_ ==
"")
1110 std::stringstream errmsg;
1111 errmsg <<
"Problem attempting XML-RPC call: No server URL set!";
1112 ExceptionHandler(ExceptionHandlerRethrow::yes,
1117 xmlrpc_c::clientSimple myClient;
1118 xmlrpc_c::value result;
1122 myClient.call(serverUrl_,
"daq.unregister_monitor",
"s", &result, monitor_label.c_str());
1126 std::stringstream errmsg;
1127 errmsg <<
"Problem attempting to unregister monitor via XML-RPC call on host " << serverUrl_
1128 <<
"; possible causes are that the monitor label \""
1130 <<
"\" is unrecognized by contacted process or process at requested port doesn't exist";
1131 ExceptionHandler(ExceptionHandlerRethrow::no, errmsg.str());
1134 return xmlrpc_c::value_string(result);
This interface defines the functions used to transfer data between artdaq applications.
cmd_(xmlrpc_commander &c, const std::string &signature, const std::string &description)
cmd_ Constructor
static const uint64_t defaultTimeout
std::string send_unregister_monitor(std::string monitor_label) override
Send an unregister_monitor command over XMLRPC
std::string send_register_monitor(std::string monitor_fhicl) override
Send a register_monitor command over XMLRPC
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
xmlrpc_commander(fhicl::ParameterSet ps, artdaq::Commandable &commandable)
xmlrpc_commander Constructor
Command class representing a start transition.
rollover_subrun_(xmlrpc_commander &c)
shutdown_ Constructor
virtual bool do_trace_set(std::string const &, std::string const &, uint64_t)
Set the given TRACE mask for the given trace name.
virtual std::string do_trace_get(std::string const &)
Get the TRACE mask for the given trace name.
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.
trace_set_(xmlrpc_commander &c)
unregister_monitor_ Constructor
void run_server() override
Run the XMLRPC server.
std::unique_ptr< xmlrpc_c::serverAbyss > server
XMLRPC server.
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.
static const uint64_t defaultSequenceID
virtual std::string register_monitor(fhicl::ParameterSet const &)
Perform the register_monitor action.
register_monitor_ Command class
legal_commands_ Command class
artdaq::Commandable & _commandable
Reference to the Commandable that this Commander Commands.
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 ...
std::timed_mutex mutex_
XMLRPC mutex.
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
virtual bool do_meta_command(std::string const &, std::string const &)
Run a module-defined command with the given parameter string.
virtual bool do_rollover_subrun(uint64_t eventNum)
Perform the rollover_subrun transition.
std::vector< std::string > legal_commands() const
Get the legal transition commands from the current state.
rollover_subrun_ Command class
bool start(art::RunID id, uint64_t timeout, uint64_t timestamp)
Processes the start transition.
report_(xmlrpc_commander &c)
report_ Constructor
start_(xmlrpc_commander &c)
start_ Command (cmd_ derived class) Constructor
trace_get_(xmlrpc_commander &c)
trace_msgfacility_set_ Constructor
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.