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