artdaq  v3_09_06
xmlrpc_commander.cc
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 #include <cstdint>
18 #include <iostream>
19 #include <limits>
20 #include <memory>
21 #include <stdexcept>
22 #include "artdaq/DAQdata/Globals.hh"
23 #define TRACE_NAME (app_name + "_xmlrpc_commander").c_str()
24 #include "tracemf.h"
25 
26 #include <netinet/in.h>
27 #include <sys/socket.h>
28 #include <cerrno>
29 #include <cstring>
30 #include <exception>
31 #include "artdaq-core/Utilities/ExceptionHandler.hh"
32 
33 #include "canvas/Persistency/Provenance/RunID.h"
34 #include "fhiclcpp/make_ParameterSet.h"
35 
36 #include "artdaq/ExternalComms/xmlrpc_commander.hh"
37 //#include "artdaq/Application/LoadParameterSet.hh"
38 
39 namespace {
43 class env_wrap
44 {
45 public:
46  env_wrap() { xmlrpc_env_init(&this->env_c); };
47  ~env_wrap() { xmlrpc_env_clean(&this->env_c); };
48  xmlrpc_env env_c;
49 private:
50  env_wrap(env_wrap const&) = delete;
51  env_wrap(env_wrap&&) = delete;
52  env_wrap& operator=(env_wrap const&) = delete;
53  env_wrap& operator=(env_wrap&&) = delete;
54 };
55 } // namespace
56 static xmlrpc_c::paramList
57 pListFromXmlrpcArray(xmlrpc_value* const arrayP)
58 {
59  env_wrap env;
60  XMLRPC_ASSERT_ARRAY_OK(arrayP);
61  unsigned int const arraySize = xmlrpc_array_size(&env.env_c, arrayP);
62  assert(!env.env_c.fault_occurred);
63  xmlrpc_c::paramList paramList(arraySize);
64  for (unsigned int i = 0; i < arraySize; ++i)
65  {
66  xmlrpc_value* arrayItemP;
67  xmlrpc_array_read_item(&env.env_c, arrayP, i, &arrayItemP);
68  assert(!env.env_c.fault_occurred);
69  paramList.add(xmlrpc_c::value(arrayItemP));
70  xmlrpc_DECREF(arrayItemP);
71  }
72  return paramList;
73 }
74 static xmlrpc_value*
75 c_executeMethod(xmlrpc_env* const envP,
76  xmlrpc_value* const paramArrayP,
77  void* const methodPtr,
78  void* const callInfoPtr)
79 {
80  auto* const methodP(static_cast<xmlrpc_c::method*>(methodPtr));
81  xmlrpc_c::paramList const paramList(pListFromXmlrpcArray(paramArrayP));
82  auto* const callInfoP(static_cast<xmlrpc_c::callInfo*>(callInfoPtr));
83  xmlrpc_value* retval;
84  retval = nullptr; // silence used-before-set warning
85  try
86  {
87  xmlrpc_c::value result;
88  try
89  {
90  auto* const method2P(dynamic_cast<xmlrpc_c::method2*>(methodP));
91  if (method2P != nullptr)
92  {
93  method2P->execute(paramList, callInfoP, &result);
94  }
95  else
96  {
97  methodP->execute(paramList, &result);
98  }
99  }
100  catch (xmlrpc_c::fault const& fault)
101  {
102  xmlrpc_env_set_fault(envP, fault.getCode(),
103  fault.getDescription().c_str());
104  }
105  if (envP->fault_occurred == 0)
106  {
107  if (result.isInstantiated())
108  {
109  retval = result.cValue();
110  }
111  else
112  {
113  girerr::throwf(
114  "Xmlrpc-c user's xmlrpc_c::method object's "
115  "'execute method' failed to set the RPC result "
116  "value.");
117  }
118  }
119  }
120  catch (std::exception const& e)
121  {
122  xmlrpc_faultf(envP,
123  "Unexpected error executing code for "
124  "particular method, detected by Xmlrpc-c "
125  "method registry code. Method did not "
126  "fail; rather, it did not complete at all. %s",
127  e.what());
128  }
129  catch (...)
130  {
131  xmlrpc_env_set_fault(envP, XMLRPC_INTERNAL_ERROR,
132  "Unexpected error executing code for "
133  "particular method, detected by Xmlrpc-c "
134  "method registry code. Method did not "
135  "fail; rather, it did not complete at all.");
136  }
137  return retval;
138 }
139 
140 namespace artdaq {
147 std::string exception_msg(const std::runtime_error& er,
148  const std::string& helpText = "execute request")
149 {
150  std::string msg("Exception when trying to ");
151  msg.append(helpText);
152  msg.append(": ");
153  msg.append(er.what()); //std::string(er.what ()).substr (2);
154  if (msg[msg.size() - 1] == '\n')
155  {
156  msg.erase(msg.size() - 1);
157  }
158  return msg;
159 }
160 
167 std::string exception_msg(const art::Exception& er,
168  const std::string& helpText)
169 {
170  std::string msg("Exception when trying to ");
171  msg.append(helpText);
172  msg.append(": ");
173  msg.append(er.what());
174  if (msg[msg.size() - 1] == '\n')
175  {
176  msg.erase(msg.size() - 1);
177  }
178  return msg;
179 }
180 
187 std::string exception_msg(const cet::exception& er,
188  const std::string& helpText)
189 {
190  std::string msg("Exception when trying to ");
191  msg.append(helpText);
192  msg.append(": ");
193  msg.append(er.what());
194  if (msg[msg.size() - 1] == '\n')
195  {
196  msg.erase(msg.size() - 1);
197  }
198  return msg;
199 }
200 
207 std::string exception_msg(const boost::exception& er,
208  const std::string& helpText)
209 {
210  std::string msg("Exception when trying to ");
211  msg.append(helpText);
212  msg.append(": ");
213  msg.append(boost::diagnostic_information(er));
214  if (msg[msg.size() - 1] == '\n') msg.erase(msg.size() - 1);
215  return msg;
216 }
223 std::string exception_msg(const std::exception& er,
224  const std::string& helpText)
225 {
226  std::string msg("Exception when trying to ");
227  msg.append(helpText);
228  msg.append(": ");
229  msg.append(er.what());
230  if (msg[msg.size() - 1] == '\n') msg.erase(msg.size() - 1);
231  return msg;
232 }
233 
240 std::string exception_msg(const std::string& erText,
241  const std::string& helpText)
242 {
243  std::string msg("Exception when trying to ");
244  msg.append(helpText);
245  msg.append(": ");
246  msg.append(erText);
247  if (msg[msg.size() - 1] == '\n')
248  {
249  msg.erase(msg.size() - 1);
250  }
251  return msg;
252 }
253 
271 class cmd_ : public xmlrpc_c::method
272 {
273 public:
274  // Can't seem to initialize "_signature" and "_help" in the initialization list...
281  cmd_(xmlrpc_commander& c, const std::string& signature, const std::string& description)
282  : _c(c)
283  {
284  _signature = signature;
285  _help = description;
286  }
287 
293  void execute(const xmlrpc_c::paramList& paramList, xmlrpc_c::value* retvalP) final;
294 
295 protected:
297 
303  virtual bool execute_(const xmlrpc_c::paramList&, xmlrpc_c::value* retvalP) = 0;
304 
314  template<typename T>
315  T getParam(const xmlrpc_c::paramList& paramList, int index);
316 
340  template<typename T>
341  T getParam(const xmlrpc_c::paramList& paramList, int index, T default_value);
342 };
343 
344 // Users are only allowed to call getParam for predefined types; see
345 // template specializations below this default function
346 
347 template<typename T>
348 T cmd_::getParam(const xmlrpc_c::paramList& /*unused*/, int /*unused*/)
349 {
350  throw cet::exception("cmd_") << "Error in cmd_::getParam(): value type not supported" << std::endl; // NOLINT(cert-err60-cpp)
351 }
352 
361 template<>
362 uint64_t cmd_::getParam<uint64_t>(const xmlrpc_c::paramList& paramList, int index)
363 {
364  TLOG(TLVL_TRACE) << "Getting parameter " << index << " from list as uint64_t.";
365  try
366  {
367  TLOG(TLVL_TRACE) << "Param value: " << paramList.getI8(index);
368  return static_cast<uint64_t>(paramList.getI8(index));
369  }
370  catch (...)
371  {
372  TLOG(TLVL_TRACE) << "Param value (int): " << paramList.getInt(index);
373  return static_cast<uint64_t>(paramList.getInt(index));
374  }
375 }
376 
385 template<>
386 uint32_t cmd_::getParam<uint32_t>(const xmlrpc_c::paramList& paramList, int index)
387 {
388  TLOG(TLVL_TRACE) << "Getting parameter " << index << " from list as uint32_t.";
389  TLOG(TLVL_TRACE) << "Param value: " << paramList.getInt(index);
390  return static_cast<uint32_t>(paramList.getInt(index));
391 }
392 
401 template<>
402 std::string cmd_::getParam<std::string>(const xmlrpc_c::paramList& paramList, int index)
403 {
404  TLOG(TLVL_TRACE) << "Getting parameter " << index << " from list as string.";
405  TLOG(TLVL_TRACE) << "Param value: " << paramList.getString(index);
406  return static_cast<std::string>(paramList.getString(index));
407 }
408 
417 template<>
418 art::RunID cmd_::getParam<art::RunID>(const xmlrpc_c::paramList& paramList, int index)
419 {
420  TLOG(TLVL_TRACE) << "Getting parameter " << index << " from list as Run Number.";
421  art::RunNumber_t run_number;
422  try
423  {
424  TLOG(TLVL_TRACE) << "Param value: " << paramList.getInt(index);
425  run_number = art::RunNumber_t(paramList.getInt(index));
426  }
427  catch (...)
428  {
429  TLOG(TLVL_TRACE) << "Parameter is not an int. Trying string...";
430 
431  auto runNumber = paramList.getString(index);
432  TLOG(TLVL_TRACE) << "Got run number string " << runNumber;
433  run_number = art::RunNumber_t(std::stoi(runNumber));
434  }
435 
436  art::RunID run_id(run_number);
437  return run_id;
438 }
439 
448 template<>
449 fhicl::ParameterSet cmd_::getParam<fhicl::ParameterSet>(const xmlrpc_c::paramList& paramList, int index)
450 {
451  TLOG(TLVL_TRACE) << "Getting parameter " << index << " from list as ParameterSet.";
452  TLOG(TLVL_TRACE) << "Param value: " << paramList.getString(index);
453  std::string configString = std::string(paramList.getString(index));
454  TLOG(TLVL_DEBUG) << "Loading Parameter Set from string: " << configString << std::endl;
455  fhicl::ParameterSet pset;
456 
457  try
458  {
459  fhicl::make_ParameterSet(configString, pset);
460  }
461  catch (const fhicl::exception& e)
462  {
463  if (getenv("FHICL_FILE_PATH") == nullptr)
464  {
465  std::cerr << "INFO: environment variable FHICL_FILE_PATH was not set. Using \".\"\n";
466  setenv("FHICL_FILE_PATH", ".", 0);
467  }
468  cet::filepath_lookup_after1 lookup_policy("FHICL_FILE_PATH");
469  fhicl::make_ParameterSet(configString, lookup_policy, pset);
470  }
471 
472  TLOG(TLVL_INFO) << "Parameter Set Loaded." << std::endl;
473  return pset;
474 }
475 
476 template<typename T>
477 T cmd_::getParam(const xmlrpc_c::paramList& paramList, int index,
478  T default_value)
479 {
480  T val = default_value;
481 
482  if (static_cast<unsigned>(index) < paramList.size())
483  {
484  val = getParam<T>(paramList, index);
485  }
486  return val;
487 }
488 
489 void cmd_::execute(const xmlrpc_c::paramList& paramList, xmlrpc_c::value* const retvalP)
490 {
491  TLOG(TLVL_TRACE) << "Received Request to " << _help << ", attempting to get lock";
492  std::unique_lock<std::timed_mutex> lk(_c.mutex_, std::defer_lock);
493  lk.try_lock_for(std::chrono::milliseconds(250));
494 
495  if (lk.owns_lock())
496  {
497  try
498  {
499  // JCF, 9/4/14
500 
501  // Assuming the execute_ function returns true, then if the
502  // retvalP argument was untouched, assign it the string
503  // "Success"
504 
505  // See
506  // http://xmlrpc-c.sourceforge.net/doc/libxmlrpc++.html#isinstantiated
507  // for more on the concept of instantiation in xmlrpc_c::value objects
508 
509  if (execute_(paramList, retvalP))
510  {
511  if (!retvalP->isInstantiated())
512  {
513  *retvalP = xmlrpc_c::value_string("Success");
514  }
515  }
516  else
517  {
518  std::string problemReport = _c._commandable.report("transition_status");
519  *retvalP = xmlrpc_c::value_string(problemReport);
520  }
521  }
522  catch (std::runtime_error& er)
523  {
524  std::string msg = exception_msg(er, _help);
525  *retvalP = xmlrpc_c::value_string(msg);
526  TLOG(TLVL_ERROR) << msg;
527  }
528  catch (art::Exception& er)
529  {
530  std::string msg = exception_msg(er, _help);
531  *retvalP = xmlrpc_c::value_string(msg);
532  TLOG(TLVL_ERROR) << msg;
533  }
534  catch (cet::exception& er)
535  {
536  std::string msg = exception_msg(er, _help);
537  *retvalP = xmlrpc_c::value_string(msg);
538  TLOG(TLVL_ERROR) << msg;
539  }
540  catch (boost::exception& er)
541  {
542  std::string msg = exception_msg(er, _help);
543  *retvalP = xmlrpc_c::value_string(msg);
544  TLOG(TLVL_ERROR) << msg;
545  }
546  catch (std::exception& er)
547  {
548  std::string msg = exception_msg(er, _help);
549  *retvalP = xmlrpc_c::value_string(msg);
550  TLOG(TLVL_ERROR) << msg;
551  }
552  catch (...)
553  {
554  std::string msg = exception_msg("Unknown exception (not from std, boost, cet, or art)", _help);
555  *retvalP = xmlrpc_c::value_string(msg);
556  TLOG(TLVL_ERROR) << msg;
557  }
558 
559  lk.unlock();
560  }
561  else
562  {
563  TLOG(TLVL_ERROR) << "Unable to get lock while trying to " << _help << ", returning busy";
564  *retvalP = xmlrpc_c::value_string("busy");
565  }
566 }
567 
569 
570 // JCF, 9/5/14
571 
572 // The three "init" transitions all take a FHiCL parameter list, and
573 // optionally a timeout and a timestamp; thus we can kill three birds
574 // with one stone in the GENERATE_INIT_TRANSITION macro
575 
576 #define GENERATE_INIT_TRANSITION(NAME, CALL, DESCRIPTION) \
577  \
578  class NAME##_ : public cmd_ \
579  { \
580  public: \
581  \
584  explicit NAME##_(xmlrpc_commander& c) : cmd_(c, "s:sII", DESCRIPTION) {} \
585  \
586  \
587  static const uint64_t defaultTimeout = 45; \
588  \
589  static const uint64_t defaultTimestamp = std::numeric_limits<const uint64_t>::max(); \
590  \
591  private: \
592  bool execute_(const xmlrpc_c::paramList& paramList, xmlrpc_c::value* const retvalP) \
593  { \
594  fhicl::ParameterSet ps; \
595  try \
596  { \
597  ps = getParam<fhicl::ParameterSet>(paramList, 0); \
598  } \
599  catch (...) \
600  { \
601  *retvalP = xmlrpc_c::value_string("Error: The " #NAME " message requires a single argument that is a string containing the initialization ParameterSet"); \
602  return true; \
603  } \
604  \
605  return _c._commandable.CALL(ps, \
606  getParam<uint64_t>(paramList, 1, defaultTimeout), \
607  getParam<uint64_t>(paramList, 2, defaultTimestamp)); \
608  } \
609  };
610 
611 GENERATE_INIT_TRANSITION(init, initialize, "initialize the program")
612 
613 GENERATE_INIT_TRANSITION(soft_init, soft_initialize, "initialize software components in the program")
614 
615 GENERATE_INIT_TRANSITION(reinit, reinitialize, "re-initialize the program")
616 
617 #undef GENERATE_INIT_TRANSITION
618 
620 
624 class start_ : public cmd_
625 {
626 public:
632  : cmd_(c, "s:iII", "start the run")
633  {}
634 
636  static const uint64_t defaultTimeout = 45;
638  static const uint64_t defaultTimestamp = std::numeric_limits<const uint64_t>::max();
639 
640 private:
641  bool execute_(xmlrpc_c::paramList const& paramList, xmlrpc_c::value* const retvalP) override
642  {
643  try
644  {
645  getParam<art::RunID>(paramList, 0);
646  }
647  catch (...)
648  {
649  *retvalP = xmlrpc_c::value_string("Error: The start message requires the run number as an argument.");
650  return true;
651  }
652 
653  return _c._commandable.start(getParam<art::RunID>(paramList, 0),
654  getParam<uint64_t>(paramList, 1, defaultTimeout),
655  getParam<uint64_t>(paramList, 2, defaultTimestamp));
656  }
657 };
658 
660 
661 // JCF, 9/5/14
662 
663 // "pause", "resume" and "stop" all take an optional timeout and
664 // timestamp parameter, so we can generate them all with the
665 // GENERATE_TIMEOUT_TIMESTAMP_TRANSITION macro
666 
667 #define GENERATE_TIMEOUT_TIMESTAMP_TRANSITION(NAME, CALL, DESCRIPTION, TIMEOUT) \
668  \
669  class NAME##_ : public cmd_ \
670  { \
671  public: \
672  \
674  NAME##_(xmlrpc_commander& c) : cmd_(c, "s:II", DESCRIPTION) {} \
675  \
676  \
677  static const uint64_t defaultTimeout = TIMEOUT; \
678  \
679  static const uint64_t defaultTimestamp = std::numeric_limits<const uint64_t>::max(); \
680  \
681  private: \
682  bool execute_(const xmlrpc_c::paramList& paramList, xmlrpc_c::value* const) \
683  { \
684  return _c._commandable.CALL(getParam<uint64_t>(paramList, 0, defaultTimeout), \
685  getParam<uint64_t>(paramList, 1, defaultTimestamp)); \
686  } \
687  };
688 
689 GENERATE_TIMEOUT_TIMESTAMP_TRANSITION(pause, pause, "pause the program", 45)
690 
691 GENERATE_TIMEOUT_TIMESTAMP_TRANSITION(resume, resume, "resume the program", 45)
692 
693 GENERATE_TIMEOUT_TIMESTAMP_TRANSITION(stop, stop, "stop the program", 45)
694 
695 #undef GENERATE_TIMEOUT_TIMESTAMP_TRANSITION
696 
700 class shutdown_ : public cmd_
701 {
702 public:
708  : cmd_(c, "s:i", "shutdown the program")
709  {}
710 
712  static const uint64_t defaultTimeout = 45;
713 
714 private:
715  bool execute_(const xmlrpc_c::paramList& paramList, xmlrpc_c::value* const /*retvalP*/) override
716  {
717  auto ret = _c._commandable.shutdown(getParam<uint64_t>(paramList, 0, defaultTimeout));
718 
719 #if 1
720  if (_c.server)
721  {
722  _c.server->terminate();
723  }
724 #endif
725 
726  return ret;
727  }
728 };
729 
733 class status_ : public cmd_
734 {
735 public:
741  : cmd_(c, "s:n", "report the current state")
742  {}
743 
744 private:
745  bool execute_(xmlrpc_c::paramList const& /*unused*/, xmlrpc_c::value* const retvalP) override
746  {
747  *retvalP = xmlrpc_c::value_string(_c._commandable.status());
748  return true;
749  }
750 };
751 
755 class report_ : public cmd_
756 {
757 public:
763  : cmd_(c, "s:s", "report statistics")
764  {}
765 
766 private:
767  bool execute_(xmlrpc_c::paramList const& paramList, xmlrpc_c::value* const retvalP) override
768  {
769  try
770  {
771  getParam<std::string>(paramList, 0);
772  }
773  catch (...)
774  {
775  *retvalP = xmlrpc_c::value_string("Error: The report message requires a single argument that selects the type of statistics to be reported.");
776  return true;
777  }
778 
779  *retvalP = xmlrpc_c::value_string(_c._commandable.report(getParam<std::string>(paramList, 0)));
780  return true;
781  }
782 };
783 
787 class legal_commands_ : public cmd_
788 {
789 public:
795  : cmd_(c, "s:n", "return the currently legal commands")
796  {}
797 
798 private:
799  bool execute_(xmlrpc_c::paramList const& /*unused*/, xmlrpc_c::value* const retvalP) override
800  {
801  std::vector<std::string> cmdList = _c._commandable.legal_commands();
802  std::string resultString;
803 
804  for (auto& cmd : cmdList)
805  {
806  resultString.append(cmd + " ");
807  if (cmd == "shutdown")
808  {
809  resultString.append(" reset");
810  }
811  }
812  *retvalP = xmlrpc_c::value_string(resultString);
813 
814  return true;
815  }
816 };
817 
821 class register_monitor_ : public cmd_
822 {
823 public:
829  : cmd_(c, "s:s", "Get notified of a new monitor")
830  {}
831 
832 private:
833  bool execute_(xmlrpc_c::paramList const& paramList, xmlrpc_c::value* const retvalP) override
834  {
835  try
836  {
837  getParam<fhicl::ParameterSet>(paramList, 0);
838  }
839  catch (...)
840  {
841  *retvalP = xmlrpc_c::value_string("Error: The register_monitor command expects a string representing the FHiCL definition of a Transfer plugin");
842  return true;
843  }
844 
845  *retvalP = xmlrpc_c::value_string(_c._commandable.register_monitor(getParam<fhicl::ParameterSet>(paramList, 0)));
846  return true;
847  }
848 };
849 
853 class unregister_monitor_ : public cmd_
854 {
855 public:
861  : cmd_(c, "s:s", "Remove a monitor")
862  {}
863 
864 private:
865  bool execute_(xmlrpc_c::paramList const& paramList, xmlrpc_c::value* const retvalP) override
866  {
867  try
868  {
869  getParam<std::string>(paramList, 0);
870  }
871  catch (...)
872  {
873  *retvalP = xmlrpc_c::value_string("Error: The unregister_monitor command expects a string representing the label of the monitor to be removed");
874  return true;
875  }
876 
877  *retvalP = xmlrpc_c::value_string(_c._commandable.unregister_monitor(getParam<std::string>(paramList, 0)));
878  return true;
879  }
880 };
881 
885 class trace_set_ : public cmd_
886 {
887 public:
893  : cmd_(c, "s:ssI", "Set TRACE mask")
894  {}
895 
896 private:
897  bool execute_(xmlrpc_c::paramList const& paramList, xmlrpc_c::value* const retvalP) override
898  {
899  try
900  {
901  getParam<std::string>(paramList, 0);
902  getParam<std::string>(paramList, 1);
903  getParam<std::string>(paramList, 2);
904  }
905  catch (...)
906  {
907  *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");
908  return true;
909  }
910 
911  return _c._commandable.do_trace_set(getParam<std::string>(paramList, 0), getParam<std::string>(paramList, 1), getParam<std::string>(paramList, 2));
912  }
913 };
914 
918 class trace_get_ : public cmd_
919 {
920 public:
926  : cmd_(c, "s:s", "Get TRACE mask")
927  {}
928 
929 private:
930  bool execute_(xmlrpc_c::paramList const& paramList, xmlrpc_c::value* const retvalP) override
931  {
932  try
933  {
934  getParam<std::string>(paramList, 0);
935  }
936  catch (...)
937  {
938  *retvalP = xmlrpc_c::value_string("Error: The trace_get command expects a name (ALL for all)");
939  return true;
940  }
941 
942  *retvalP = xmlrpc_c::value_string(_c._commandable.do_trace_get(getParam<std::string>(paramList, 0)));
943  return true;
944  }
945 };
946 
950 class meta_command_ : public cmd_
951 {
952 public:
958  : cmd_(c, "s:ss", "Run custom command")
959  {}
960 
961 private:
962  bool execute_(xmlrpc_c::paramList const& paramList, xmlrpc_c::value* const retvalP) override
963  {
964  try
965  {
966  getParam<std::string>(paramList, 0);
967  getParam<std::string>(paramList, 1);
968  }
969  catch (...)
970  {
971  *retvalP = xmlrpc_c::value_string("Error: The meta_command command expects a string command and a string argument");
972  return true;
973  }
974 
975  return _c._commandable.do_meta_command(getParam<std::string>(paramList, 0), getParam<std::string>(paramList, 1));
976  }
977 };
978 
982 class rollover_subrun_ : public cmd_
983 {
984 public:
990  : cmd_(c, "s:Ii", "create a new subrun")
991  {}
992 
993  static const uint64_t defaultSequenceID = 0xFFFFFFFFFFFFFFFF;
994  static const uint32_t defaultSubrunNumber = 1;
995 
996 private:
997  bool execute_(const xmlrpc_c::paramList& paramList, xmlrpc_c::value* const /*retvalP*/) override
998  {
999  auto ret = _c._commandable.do_rollover_subrun(getParam<uint64_t>(paramList, 0, defaultSequenceID), getParam<uint32_t>(paramList, 1, defaultSubrunNumber));
1000  return ret;
1001  }
1002 };
1003 
1008 {
1009 public:
1015  : cmd_(c, "s:ss", "Add an entry to the configuration archive list")
1016  {}
1017 
1018 private:
1019  bool execute_(xmlrpc_c::paramList const& paramList, xmlrpc_c::value* const retvalP) override
1020  {
1021  try
1022  {
1023  getParam<std::string>(paramList, 0);
1024  getParam<std::string>(paramList, 1);
1025  }
1026  catch (...)
1027  {
1028  *retvalP = xmlrpc_c::value_string("Error: The add_config_archive_entry command expects a string key and a string value");
1029  return true;
1030  }
1031 
1032  return _c._commandable.do_add_config_archive_entry(getParam<std::string>(paramList, 0), getParam<std::string>(paramList, 1));
1033  }
1034 };
1035 
1040 {
1041 public:
1047  : cmd_(c, "s:n", "Clear the configuration archive list")
1048  {}
1049 
1050 private:
1051  bool execute_(xmlrpc_c::paramList const& /*unused*/, xmlrpc_c::value* const /*retvalP*/) override
1052  {
1054  }
1055 };
1056 
1057 // JCF, 9/4/14
1058 
1059 // Not sure if anyone was planning to resurrect this code by changing
1060 // the preprocessor decision; as such, I'll leave it in for now...
1061 
1062 #if 0
1063  class shutdown_ : public xmlrpc_c::registry::shutdown
1064  {
1065  public:
1066  shutdown_(xmlrpc_c::serverAbyss *server) : _server(server) {}
1067 
1068  virtual void doit(const std::string& paramString, void*) const
1069  {
1070  TLOG(TLVL_INFO) << "A shutdown command was sent "
1071  << "with parameter "
1072  << paramString << "\"";
1073  _server->terminate();
1074  }
1075  private:
1076  xmlrpc_c::serverAbyss *_server;
1077  };
1078 #endif
1079 
1080 xmlrpc_commander::xmlrpc_commander(const fhicl::ParameterSet& ps, artdaq::Commandable& commandable)
1081  : CommanderInterface(ps, commandable)
1082  , port_(ps.get<int>("id", 0))
1083  , serverUrl_(ps.get<std::string>("server_url", ""))
1084  , server(nullptr)
1085 {
1086  if (serverUrl_.empty())
1087  {
1088  char hostname[HOST_NAME_MAX];
1089  gethostname(hostname, HOST_NAME_MAX);
1090  serverUrl_ = std::string(hostname);
1091  }
1092  if (serverUrl_.find("http") == std::string::npos)
1093  {
1094  serverUrl_ = "http://" + serverUrl_;
1095  }
1096  if (serverUrl_.find(std::to_string(port_)) == std::string::npos && serverUrl_.find(':', 7) == std::string::npos)
1097  {
1098  serverUrl_ = serverUrl_ + ":" + std::to_string(port_);
1099  }
1100  if (serverUrl_.find("RPC2") == std::string::npos)
1101  {
1102  serverUrl_ = serverUrl_ + "/RPC2";
1103  }
1104  TLOG(TLVL_INFO) << "XMLRPC COMMANDER CONSTRUCTOR: Port: " << port_ << ", Server Url: " << serverUrl_;
1105 }
1106 
1108 {
1109  //std::cout << "XMLRPC_COMMANDER RUN_SERVER CALLED!" << std::endl;
1110  xmlrpc_c::registry registry;
1111  struct xmlrpc_method_info3 methodInfo;
1112  memset(&methodInfo, 0, sizeof(methodInfo));
1113 
1114  /*#define register_method(m) \
1115  // xmlrpc_c::methodPtr const ptr_ ## m(new m ## _(*this));\
1116  registry.addMethod ("daq." #m, ptr_ ## m) */
1117 #define register_method(m) register_method2(m, 0x400000)
1118 
1119  xmlrpc_env env; // xmlrpc_env_init(&env);
1120  xmlrpc_registry*** c_registryPPP;
1121  c_registryPPP = reinterpret_cast<xmlrpc_registry***>(reinterpret_cast<char*>(&registry) + sizeof(girmem::autoObject)); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast,cppcoreguidelines-pro-bounds-pointer-arithmetic)
1122 
1123 #define register_method2(m, ss) \
1124  xmlrpc_c::method* ptr_##m(dynamic_cast<xmlrpc_c::method*>(new m##_(*this))); \
1125  std::string m##signature = ptr_##m->signature(), m##help = ptr_##m->help(); \
1126  methodInfo.methodName = "daq." #m; \
1127  methodInfo.methodFunction = &c_executeMethod; \
1128  methodInfo.serverInfo = ptr_##m; \
1129  methodInfo.stackSize = ss; \
1130  methodInfo.signatureString = &m##signature[0]; \
1131  methodInfo.help = &m##help[0]; \
1132  xmlrpc_env_init(&env); \
1133  xmlrpc_registry_add_method3(&env, **c_registryPPP, &methodInfo); \
1134  if (env.fault_occurred) throw(girerr::error(env.fault_string)); \
1135  xmlrpc_env_clean(&env)
1136 
1137  register_method2(init, 0x200000);
1138  register_method(soft_init);
1139  register_method(reinit);
1140  register_method(start);
1141  register_method(status);
1142  register_method(report);
1143  register_method(stop);
1144  register_method(pause);
1145  register_method(resume);
1146  register_method(register_monitor);
1147  register_method(unregister_monitor);
1148  register_method(legal_commands);
1149  register_method(trace_set);
1150  register_method(trace_get);
1151  register_method(meta_command);
1152  register_method(rollover_subrun);
1153  register_method(add_config_archive_entry);
1154  register_method(clear_config_archive);
1155 
1156  register_method(shutdown);
1157 
1158  // alias "daq.reset" to the internal shutdown transition
1159  xmlrpc_c::methodPtr const ptr_reset(new shutdown_(*this));
1160  registry.addMethod("daq.reset", ptr_reset);
1161 
1162 #undef register_method
1163 
1164  // JCF, 6/3/15
1165 
1166  // In the following code, I configure a socket to have the
1167  // SO_REUSEADDR option so that once an artdaq process closes, the
1168  // port it was communicating on becomes immediately available
1169  // (desirable if, say, the DAQ program is terminated and then
1170  // immediately restarted)
1171 
1172  // Much of the following code is cribbed from
1173  // http://fossies.org/linux/freeswitch/libs/xmlrpc-c/src/cpp/test/server_abyss.cpp
1174 
1175  // Below, "0" is the default protocol (in this case, given the IPv4
1176  // Protocol Family (PF_INET) and the SOCK_STREAM communication
1177  // method)
1178 
1179  XMLRPC_SOCKET socket_file_descriptor = socket(PF_INET, SOCK_STREAM, 0);
1180 
1181  if (socket_file_descriptor < 0)
1182  {
1183  throw cet::exception("xmlrpc_commander::run") << "Problem with the socket() call; C-style errno == " << errno << " (" << strerror(errno) << ")"; // NOLINT(cert-err60-cpp)
1184  }
1185 
1186  int enable = 1;
1187  int retval = setsockopt(socket_file_descriptor,
1188  SOL_SOCKET, SO_REUSEADDR,
1189  &enable, sizeof(int));
1190 
1191  if (retval < 0)
1192  {
1193  throw cet::exception("xmlrpc_commander::run") << "Problem with the call to setsockopt(); C-style errno == " << errno << " (" << strerror(errno) << ")"; // NOLINT(cert-err60-cpp)
1194  }
1195 
1196  struct sockaddr_in sockAddr;
1197 
1198  sockAddr.sin_family = AF_INET;
1199  sockAddr.sin_port = htons(port_);
1200  sockAddr.sin_addr.s_addr = 0;
1201 
1202  retval = bind(socket_file_descriptor,
1203  reinterpret_cast<struct sockaddr*>(&sockAddr), // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)
1204  sizeof(sockAddr));
1205 
1206  if (retval != 0)
1207  {
1208  close(socket_file_descriptor);
1209  throw cet::exception("xmlrpc_commander::run") << "Problem with the bind() call; C-style errno == " << errno << " (" << strerror(errno) << ")"; // NOLINT(cert-err60-cpp)
1210  }
1211 
1212  server = std::make_unique<xmlrpc_c::serverAbyss>(xmlrpc_c::serverAbyss::constrOpt().registryP(&registry).socketFd(socket_file_descriptor));
1213 
1214 #if 0
1215  xmlrpc_c::serverAbyss::shutdown shutdown_obj(&server);
1216  registry.setShutdown(&shutdown_obj);
1217 #endif
1218 
1219  TLOG(TLVL_DEBUG) << "running server";
1220 
1221  // JCF, 6/3/15
1222 
1223  // Use a catch block to clean up (i.e., close the socket). An
1224  // opportunity for RAII, although all control paths are limited to
1225  // this section of the file...
1226 
1227  try
1228  {
1229  running_ = true;
1230  server->run();
1231  running_ = false;
1232  }
1233  catch (...)
1234  {
1235  TLOG(TLVL_WARNING) << "server threw an exception; closing the socket and rethrowing";
1236  running_ = false;
1237  close(socket_file_descriptor);
1238  throw;
1239  }
1240 
1241  close(socket_file_descriptor);
1242  TLOG(TLVL_DEBUG) << "server terminated";
1243 }
1244 catch (...)
1245 {
1246  throw;
1247 }
1248 
1249 std::string xmlrpc_commander::send_command_(const std::string& command)
1250 {
1251  if (serverUrl_.empty())
1252  {
1253  std::stringstream errmsg;
1254  errmsg << "Problem attempting " << command << " XML-RPC call: No server URL set!";
1255  ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
1256  }
1257  xmlrpc_c::clientSimple myClient;
1258  xmlrpc_c::value result;
1259 
1260  try
1261  {
1262  myClient.call(serverUrl_, "daq." + command, "", &result);
1263  }
1264  catch (...)
1265  {
1266  std::stringstream errmsg;
1267  errmsg << "Problem attempting " << command << " XML-RPC call on host " << serverUrl_
1268  << "; possible causes are malformed FHiCL or nonexistent process at requested port";
1269  ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
1270  }
1271 
1272  return xmlrpc_c::value_string(result);
1273 }
1274 
1275 std::string xmlrpc_commander::send_command_(const std::string& command, const std::string& arg)
1276 {
1277  if (serverUrl_.empty())
1278  {
1279  std::stringstream errmsg;
1280  errmsg << "Problem attempting " << command << " XML-RPC call: No server URL set!";
1281  ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
1282  }
1283  xmlrpc_c::clientSimple myClient;
1284  xmlrpc_c::value result;
1285 
1286  try
1287  {
1288  myClient.call(serverUrl_, "daq." + command, "s", &result, arg.c_str());
1289  }
1290  catch (...)
1291  {
1292  std::stringstream errmsg;
1293  errmsg << "Problem attempting " << command << " XML-RPC call on host " << serverUrl_
1294  << "; possible causes are malformed FHiCL or nonexistent process at requested port";
1295  ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
1296  }
1297 
1298  return xmlrpc_c::value_string(result);
1299 }
1300 
1301 std::string xmlrpc_commander::send_command_(const std::string& command, const fhicl::ParameterSet& pset, uint64_t timestamp, uint64_t timeout)
1302 {
1303  if (serverUrl_.empty())
1304  {
1305  std::stringstream errmsg;
1306  errmsg << "Problem attempting " << command << " XML-RPC call: No server URL set!";
1307  ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
1308  }
1309  xmlrpc_c::clientSimple myClient;
1310  xmlrpc_c::value result;
1311 
1312  try
1313  {
1314  myClient.call(serverUrl_, "daq." + command, "sII", &result, pset.to_string().c_str(), timestamp, timeout);
1315  }
1316  catch (...)
1317  {
1318  std::stringstream errmsg;
1319  errmsg << "Problem attempting " << command << " XML-RPC call on host " << serverUrl_
1320  << "; possible causes are malformed FHiCL or nonexistent process at requested port";
1321  ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
1322  }
1323 
1324  return xmlrpc_c::value_string(result);
1325 }
1326 
1327 std::string artdaq::xmlrpc_commander::send_command_(const std::string& command, uint64_t a, uint64_t b)
1328 {
1329  if (serverUrl_.empty())
1330  {
1331  std::stringstream errmsg;
1332  errmsg << "Problem attempting " << command << " XML-RPC call: No server URL set!";
1333  ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
1334  }
1335  xmlrpc_c::clientSimple myClient;
1336  xmlrpc_c::value result;
1337 
1338  try
1339  {
1340  myClient.call(serverUrl_, "daq." + command, "II", &result, a, b);
1341  }
1342  catch (...)
1343  {
1344  std::stringstream errmsg;
1345  errmsg << "Problem attempting " << command << " XML-RPC call on host " << serverUrl_
1346  << "; possible causes are malformed FHiCL or nonexistent process at requested port";
1347  ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
1348  }
1349 
1350  return xmlrpc_c::value_string(result);
1351 }
1352 
1353 std::string artdaq::xmlrpc_commander::send_command_(const std::string& command, uint64_t a, uint32_t b)
1354 {
1355  if (serverUrl_.empty())
1356  {
1357  std::stringstream errmsg;
1358  errmsg << "Problem attempting " << command << " XML-RPC call: No server URL set!";
1359  ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
1360  }
1361  xmlrpc_c::clientSimple myClient;
1362  xmlrpc_c::value result;
1363 
1364  try
1365  {
1366  myClient.call(serverUrl_, "daq." + command, "Ii", &result, a, b);
1367  }
1368  catch (...)
1369  {
1370  std::stringstream errmsg;
1371  errmsg << "Problem attempting " << command << " XML-RPC call on host " << serverUrl_
1372  << "; possible causes are malformed FHiCL or nonexistent process at requested port";
1373  ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
1374  }
1375 
1376  return xmlrpc_c::value_string(result);
1377 }
1378 
1379 std::string artdaq::xmlrpc_commander::send_command_(const std::string& command, art::RunID r, uint64_t a, uint64_t b)
1380 {
1381  if (serverUrl_.empty())
1382  {
1383  std::stringstream errmsg;
1384  errmsg << "Problem attempting " << command << " XML-RPC call: No server URL set!";
1385  ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
1386  }
1387  xmlrpc_c::clientSimple myClient;
1388  xmlrpc_c::value result;
1389 
1390  try
1391  {
1392  myClient.call(serverUrl_, "daq." + command, "iII", &result, r.run(), a, b);
1393  }
1394  catch (...)
1395  {
1396  std::stringstream errmsg;
1397  errmsg << "Problem attempting " << command << " XML-RPC call on host " << serverUrl_
1398  << "; possible causes are malformed FHiCL or nonexistent process at requested port";
1399  ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
1400  }
1401 
1402  return xmlrpc_c::value_string(result);
1403 }
1404 
1405 std::string artdaq::xmlrpc_commander::send_command_(const std::string& command, uint64_t arg1)
1406 {
1407  if (serverUrl_.empty())
1408  {
1409  std::stringstream errmsg;
1410  errmsg << "Problem attempting " << command << " XML-RPC call: No server URL set!";
1411  ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
1412  }
1413  xmlrpc_c::clientSimple myClient;
1414  xmlrpc_c::value result;
1415 
1416  try
1417  {
1418  myClient.call(serverUrl_, "daq." + command, "I", &result, arg1);
1419  }
1420  catch (...)
1421  {
1422  std::stringstream errmsg;
1423  errmsg << "Problem attempting " << command << " XML-RPC call on host " << serverUrl_
1424  << "; possible causes are malformed FHiCL or nonexistent process at requested port";
1425  ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
1426  }
1427 
1428  return xmlrpc_c::value_string(result);
1429 }
1430 
1431 std::string artdaq::xmlrpc_commander::send_command_(const std::string& command, const std::string& arg1, const std::string& arg2)
1432 {
1433  if (serverUrl_.empty())
1434  {
1435  std::stringstream errmsg;
1436  errmsg << "Problem attempting " << command << " XML-RPC call: No server URL set!";
1437  ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
1438  }
1439  xmlrpc_c::clientSimple myClient;
1440  xmlrpc_c::value result;
1441 
1442  try
1443  {
1444  myClient.call(serverUrl_, "daq." + command, "ss", &result, arg1.c_str(), arg2.c_str());
1445  }
1446  catch (...)
1447  {
1448  std::stringstream errmsg;
1449  errmsg << "Problem attempting " << command << " XML-RPC call on host " << serverUrl_
1450  << "; possible causes are malformed FHiCL or nonexistent process at requested port";
1451  ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
1452  }
1453 
1454  return xmlrpc_c::value_string(result);
1455 }
1456 
1457 std::string artdaq::xmlrpc_commander::send_command_(const std::string& command, const std::string& arg1, const std::string& arg2, const std::string& arg3)
1458 {
1459  if (serverUrl_.empty())
1460  {
1461  std::stringstream errmsg;
1462  errmsg << "Problem attempting " << command << " XML-RPC call: No server URL set!";
1463  ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
1464  }
1465  xmlrpc_c::clientSimple myClient;
1466  xmlrpc_c::value result;
1467 
1468  try
1469  {
1470  myClient.call(serverUrl_, "daq." + command, "sss", &result, arg1.c_str(), arg2.c_str(), arg3.c_str());
1471  }
1472  catch (...)
1473  {
1474  std::stringstream errmsg;
1475  errmsg << "Problem attempting " << command << " XML-RPC call on host " << serverUrl_
1476  << "; possible causes are bad arguments or nonexistent process at requested port";
1477  ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
1478  }
1479 
1480  return xmlrpc_c::value_string(result);
1481 }
1482 
1483 std::string xmlrpc_commander::send_register_monitor(std::string const& monitor_fhicl)
1484 {
1485  return send_command_("register_monitor", monitor_fhicl);
1486 }
1487 std::string xmlrpc_commander::send_unregister_monitor(std::string const& monitor_label)
1488 {
1489  return send_command_("unregister_monitor", monitor_label);
1490 }
1491 std::string artdaq::xmlrpc_commander::send_init(fhicl::ParameterSet const& ps, uint64_t timeout, uint64_t timestamp)
1492 {
1493  return send_command_("init", ps, timeout, timestamp);
1494 }
1495 std::string artdaq::xmlrpc_commander::send_soft_init(fhicl::ParameterSet const& ps, uint64_t timeout, uint64_t timestamp)
1496 {
1497  return send_command_("soft_init", ps, timeout, timestamp);
1498 }
1499 std::string xmlrpc_commander::send_reinit(fhicl::ParameterSet const& ps, uint64_t timeout, uint64_t timestamp)
1500 {
1501  return send_command_("reinit", ps, timeout, timestamp);
1502 }
1503 std::string xmlrpc_commander::send_start(art::RunID run, uint64_t timeout, uint64_t timestamp)
1504 {
1505  return send_command_("start", run, timeout, timestamp);
1506 }
1507 std::string xmlrpc_commander::send_pause(uint64_t timeout, uint64_t timestamp)
1508 {
1509  return send_command_("pause", timeout, timestamp);
1510 }
1511 std::string xmlrpc_commander::send_resume(uint64_t timeout, uint64_t timestamp)
1512 {
1513  return send_command_("resume", timeout, timestamp);
1514 }
1515 std::string xmlrpc_commander::send_stop(uint64_t timeout, uint64_t timestamp)
1516 {
1517  return send_command_("stop", timeout, timestamp);
1518 }
1519 std::string xmlrpc_commander::send_shutdown(uint64_t timeout)
1520 {
1521  return send_command_("shutdown", timeout);
1522 }
1524 {
1525  return send_command_("status");
1526 }
1527 std::string xmlrpc_commander::send_report(std::string const& what)
1528 {
1529  return send_command_("report", what);
1530 }
1532 {
1533  return send_command_("legal_commands");
1534 }
1535 std::string xmlrpc_commander::send_trace_get(std::string const& name)
1536 {
1537  return send_command_("trace_get", name);
1538 }
1539 std::string xmlrpc_commander::send_trace_set(std::string const& name, std::string const& type, std::string const& mask)
1540 {
1541  return send_command_("trace_set", name, type, mask);
1542 }
1543 std::string xmlrpc_commander::send_meta_command(std::string const& command, std::string const& arg)
1544 {
1545  return send_command_("meta_command", command, arg);
1546 }
1547 std::string xmlrpc_commander::send_rollover_subrun(uint64_t when, uint32_t sr)
1548 {
1549  return send_command_("rollover_subrun", when, sr);
1550 }
1551 } // namespace artdaq
1552 
1553 DEFINE_ARTDAQ_COMMANDER(artdaq::xmlrpc_commander)
virtual bool do_add_config_archive_entry(std::string const &, std::string const &)
Add the specified key-value pair to the configuration archive list.
Definition: Commandable.cc:538
This interface defines the functions used to transfer data between artdaq applications.
cmd_(xmlrpc_commander &c, const std::string &signature, const std::string &description)
cmd_ Constructor
static const uint64_t defaultTimeout
virtual std::string report(std::string const &) const
Default report implementation returns current report_string.
Definition: Commandable.hh:124
Commandable is the base class for all artdaq components which implement the artdaq state machine...
Definition: Commandable.hh:20
legal_commands_(xmlrpc_commander &c)
legal_commands_ Constructor
virtual bool do_clear_config_archive()
Clears the configuration archive list.
Definition: Commandable.cc:544
Command class representing a start transition.
rollover_subrun_(xmlrpc_commander &c)
shutdown_ Constructor
xmlrpc_commander(const fhicl::ParameterSet &ps, artdaq::Commandable &commandable)
xmlrpc_commander Constructor
std::string send_trace_set(std::string const &name, std::string const &type, std::string const &mask) override
Send an send_trace_msgfacility_set command over XMLRPC
status_ Command class
std::string send_register_monitor(std::string const &monitor_fhicl) override
Send a register_monitor command over XMLRPC
std::string send_init(fhicl::ParameterSet const &ps, uint64_t timeout, uint64_t timestamp) override
Send an init command over XMLRPC
std::string send_meta_command(std::string const &command, std::string const &argument) override
Send an send_meta_command command over XMLRPC
report_ Command class
std::string send_stop(uint64_t timeout, uint64_t timestamp) override
Send a stop command over XMLRPC
virtual std::string clear_config_archive()
Using the transport mechanism, send a clear_config_archive command
virtual std::string unregister_monitor(std::string const &)
Perform the unregister_monitor action.
Definition: Commandable.hh:153
meta_command_ Command class
std::string send_status() override
Send a status command over XMLRPC
std::string send_legal_commands() override
Send a legal_commands command over XMLRPC
The xmlrpc_commander class serves as the XMLRPC server run in each artdaq application.
static const uint64_t defaultTimestamp
static const uint32_t defaultSubrunNumber
Default subrun number for command.
The &quot;cmd_&quot; class serves as the base class for all artdaq&#39;s XML-RPC commands.
trace_set_(xmlrpc_commander &c)
unregister_monitor_ Constructor
shutdown_ Command class
void run_server() override
Run the XMLRPC server.
meta_command_(xmlrpc_commander &c)
meta_command_ Constructor
std::unique_ptr< xmlrpc_c::serverAbyss > server
XMLRPC server.
std::string status() const
Returns the current state of the Commandable.
Definition: Commandable.cc:299
std::string send_shutdown(uint64_t timeout) override
Send a shutdown command over XMLRPC
std::string send_reinit(fhicl::ParameterSet const &ps, uint64_t timeout, uint64_t timestamp) override
Send a reinit command over XMLRPC
std::string exception_msg(const std::runtime_error &er, const std::string &helpText="execute request")
Write an exception message.
static const uint64_t defaultSequenceID
Default Sequence ID for command.
add_config_archive_entry_(xmlrpc_commander &c)
add_config_archive_entry_ Constructor
std::string send_trace_get(std::string const &name) override
Send an send_trace_get command over XMLRPC
virtual std::string register_monitor(fhicl::ParameterSet const &)
Perform the register_monitor action.
Definition: Commandable.hh:142
virtual bool do_trace_set(std::string const &name, std::string const &type, std::string const &mask_in_string_form)
Set the given TRACE mask for the given TRACE name.
Definition: Commandable.cc:472
register_monitor_ Command class
add_config_archive_entry_ Command class
legal_commands_ Command class
std::string send_pause(uint64_t timeout, uint64_t timestamp) override
Send a pause command over XMLRPC
artdaq::Commandable & _commandable
Reference to the Commandable that this Commander Commands.
xmlrpc_commander & _c
The xmlrpc_commander instance that the command will be sent to.
std::string send_start(art::RunID runNumber, uint64_t timeout, uint64_t timestamp) override
Send a start command over XMLRPC
clear_config_archive_ Command class
trace_get_ Command class
virtual std::string add_config_archive_entry(std::string const &key, std::string const &value)
Using the transport mechanism, send an add_config_archive_entry command
void execute(const xmlrpc_c::paramList &paramList, xmlrpc_c::value *retvalP) final
Execute trhe command with the given parameters.
status_(xmlrpc_commander &c)
status_ Constructor
clear_config_archive_(xmlrpc_commander &c)
clear_config_archive_ Constructor
Wrapper for XMLRPC environment construction/destruction
std::timed_mutex mutex_
XMLRPC mutex.
register_monitor_(xmlrpc_commander &c)
register_monitor_ Constructor
static const uint64_t defaultTimeout
std::string send_rollover_subrun(uint64_t when, uint32_t sr) override
Send a send_rollover_subrun command over XMLRPC
unregister_monitor_(xmlrpc_commander &c)
unregister_monitor_ Constructor
virtual bool execute_(const xmlrpc_c::paramList &, xmlrpc_c::value *retvalP)=0
&quot;execute_&quot; is a wrapper function around the call to the commandable object&#39;s function ...
shutdown_(xmlrpc_commander &c)
shutdown_ Constructor
std::vector< std::string > legal_commands() const
Get the legal transition commands from the current state.
Definition: Commandable.cc:312
std::string send_soft_init(fhicl::ParameterSet const &ps, uint64_t timeout, uint64_t timestamp) override
Send a soft_init command over XMLRPC
rollover_subrun_ Command class
std::string send_resume(uint64_t timeout, uint64_t timestamp) override
Send a resume command over XMLRPC
std::string send_unregister_monitor(std::string const &monitor_label) override
Send an unregister_monitor command over XMLRPC
std::string send_report(std::string const &what) override
Send a report command over XMLRPC
bool start(art::RunID id, uint64_t timeout, uint64_t timestamp)
Processes the start transition.
Definition: Commandable.cc:62
report_(xmlrpc_commander &c)
report_ Constructor
trace_set_ Command class
start_(xmlrpc_commander &c)
start_ Command (cmd_ derived class) Constructor
virtual std::string do_trace_get(std::string const &name)
Get the TRACE mask for the given TRACE name If name is &quot;ALL&quot;, then all TRACE masks will be printed...
Definition: Commandable.cc:435
virtual bool do_meta_command(std::string const &cmd, std::string const &args)
Run a module-defined command with the given parameter string.
Definition: Commandable.cc:525
trace_get_(xmlrpc_commander &c)
trace_msgfacility_set_ Constructor
std::atomic< bool > running_
Whether the server is running and able to respond to requests.
virtual bool do_rollover_subrun(uint64_t eventNum, uint32_t subrunNum)
Perform the rollover_subrun transition.
Definition: Commandable.cc:531
unregister_monitor_ Command class
T getParam(const xmlrpc_c::paramList &paramList, int index)
Get a parameter from the parameter list.
bool shutdown(uint64_t timeout)
Processes the shutdown transition.
Definition: Commandable.cc:181