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