artdaq  3.13.00
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 
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 
44 {
45 public:
57  xmlrpc_commander(const fhicl::ParameterSet& ps, artdaq::Commandable& commandable);
58 
62  void run_server() override;
63 
69  std::string send_register_monitor(std::string const& monitor_fhicl) override;
70 
76  std::string send_unregister_monitor(std::string const& monitor_label) override;
77 
88  std::string send_init(fhicl::ParameterSet const& ps, uint64_t timeout, uint64_t timestamp) override;
89 
100  std::string send_soft_init(fhicl::ParameterSet const& ps, uint64_t timeout, uint64_t timestamp) override;
101 
112  std::string send_reinit(fhicl::ParameterSet const& ps, uint64_t timeout, uint64_t timestamp) override;
113 
124  std::string send_start(art::RunID runNumber, uint64_t timeout, uint64_t timestamp) override;
125 
135  std::string send_pause(uint64_t timeout, uint64_t timestamp) override;
136 
146  std::string send_resume(uint64_t timeout, uint64_t timestamp) override;
147 
157  std::string send_stop(uint64_t timeout, uint64_t timestamp) override;
158 
167  std::string send_shutdown(uint64_t timeout) override;
168 
175  std::string send_status() override;
176 
184  std::string send_report(std::string const& what) override;
185 
192  std::string send_legal_commands() override;
193 
202  std::string send_trace_get(std::string const& name) override;
203 
217  std::string send_trace_set(std::string const& name, std::string const& type, std::string const& mask) override;
218 
227  std::string send_meta_command(std::string const& command, std::string const& argument) override;
228 
238  std::string send_rollover_subrun(uint64_t when, uint32_t sr) override;
239 
240 private:
241  xmlrpc_commander(const xmlrpc_commander&) = delete;
242 
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_;
262  std::unique_ptr<xmlrpc_c::serverAbyss> server;
263 };
264 
265 } // namespace artdaq
266 
267 namespace {
271 class env_wrap
272 {
273 public:
274  env_wrap() { xmlrpc_env_init(&this->env_c); };
275  ~env_wrap() { xmlrpc_env_clean(&this->env_c); };
276  xmlrpc_env env_c;
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 pListFromXmlrpcArray(xmlrpc_value* const arrayP)
286 {
287  env_wrap env;
288  XMLRPC_ASSERT_ARRAY_OK(arrayP);
289  unsigned int const arraySize = xmlrpc_array_size(&env.env_c, arrayP);
290  assert(!env.env_c.fault_occurred);
291  xmlrpc_c::paramList paramList(arraySize);
292  for (unsigned int i = 0; i < arraySize; ++i)
293  {
294  xmlrpc_value* arrayItemP;
295  xmlrpc_array_read_item(&env.env_c, arrayP, i, &arrayItemP);
296  assert(!env.env_c.fault_occurred);
297  paramList.add(xmlrpc_c::value(arrayItemP));
298  xmlrpc_DECREF(arrayItemP);
299  }
300  return paramList;
301 }
302 static xmlrpc_value*
303 c_executeMethod(xmlrpc_env* const envP,
304  xmlrpc_value* const paramArrayP,
305  void* const methodPtr,
306  void* const callInfoPtr)
307 {
308  auto* const methodP(static_cast<xmlrpc_c::method*>(methodPtr));
309  xmlrpc_c::paramList const paramList(pListFromXmlrpcArray(paramArrayP));
310  auto* const callInfoP(static_cast<xmlrpc_c::callInfo*>(callInfoPtr));
311  xmlrpc_value* retval;
312  retval = nullptr; // silence used-before-set warning
313  try
314  {
315  xmlrpc_c::value result;
316  try
317  {
318  auto* const method2P(dynamic_cast<xmlrpc_c::method2*>(methodP));
319  if (method2P != nullptr)
320  {
321  method2P->execute(paramList, callInfoP, &result);
322  }
323  else
324  {
325  methodP->execute(paramList, &result);
326  }
327  }
328  catch (xmlrpc_c::fault const& fault)
329  {
330  xmlrpc_env_set_fault(envP, fault.getCode(),
331  fault.getDescription().c_str());
332  }
333  if (envP->fault_occurred == 0)
334  {
335  if (result.isInstantiated())
336  {
337  retval = result.cValue();
338  }
339  else
340  {
341  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  }
348  catch (std::exception const& e)
349  {
350  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  e.what());
356  }
357  catch (...)
358  {
359  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  }
365  return retval;
366 }
367 
368 namespace artdaq {
375 std::string exception_msg(const std::runtime_error& er,
376  const std::string& helpText = "execute request")
377 {
378  std::string msg("Exception when trying to ");
379  msg.append(helpText);
380  msg.append(": ");
381  msg.append(er.what()); // std::string(er.what ()).substr (2);
382  if (msg[msg.size() - 1] == '\n')
383  {
384  msg.erase(msg.size() - 1);
385  }
386  return msg;
387 }
388 
395 std::string exception_msg(const art::Exception& er,
396  const std::string& helpText)
397 {
398  std::string msg("Exception when trying to ");
399  msg.append(helpText);
400  msg.append(": ");
401  msg.append(er.what());
402  if (msg[msg.size() - 1] == '\n')
403  {
404  msg.erase(msg.size() - 1);
405  }
406  return msg;
407 }
408 
415 std::string exception_msg(const cet::exception& er,
416  const std::string& helpText)
417 {
418  std::string msg("Exception when trying to ");
419  msg.append(helpText);
420  msg.append(": ");
421  msg.append(er.what());
422  if (msg[msg.size() - 1] == '\n')
423  {
424  msg.erase(msg.size() - 1);
425  }
426  return msg;
427 }
428 
435 std::string exception_msg(const boost::exception& er,
436  const std::string& helpText)
437 {
438  std::string msg("Exception when trying to ");
439  msg.append(helpText);
440  msg.append(": ");
441  msg.append(boost::diagnostic_information(er));
442  if (msg[msg.size() - 1] == '\n') msg.erase(msg.size() - 1);
443  return msg;
444 }
451 std::string exception_msg(const std::exception& er,
452  const std::string& helpText)
453 {
454  std::string msg("Exception when trying to ");
455  msg.append(helpText);
456  msg.append(": ");
457  msg.append(er.what());
458  if (msg[msg.size() - 1] == '\n') msg.erase(msg.size() - 1);
459  return msg;
460 }
461 
468 std::string exception_msg(const std::string& erText,
469  const std::string& helpText)
470 {
471  std::string msg("Exception when trying to ");
472  msg.append(helpText);
473  msg.append(": ");
474  msg.append(erText);
475  if (msg[msg.size() - 1] == '\n')
476  {
477  msg.erase(msg.size() - 1);
478  }
479  return msg;
480 }
481 
499 class cmd_ : public xmlrpc_c::method
500 {
501 public:
502  // Can't seem to initialize "_signature" and "_help" in the initialization list...
509  cmd_(xmlrpc_commander& c, const std::string& signature, const std::string& description)
510  : _c(c)
511  {
512  _signature = signature;
513  _help = description;
514  }
515 
521  void execute(const xmlrpc_c::paramList& paramList, xmlrpc_c::value* retvalP) final;
522 
523 protected:
525 
531  virtual bool execute_(const xmlrpc_c::paramList&, xmlrpc_c::value* retvalP) = 0;
532 
542  template<typename T>
543  T getParam(const xmlrpc_c::paramList& paramList, int index);
544 
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 
589 template<>
590 uint64_t cmd_::getParam<uint64_t>(const xmlrpc_c::paramList& paramList, int index)
591 {
592  TLOG(TLVL_DEBUG + 33) << "Getting parameter " << index << " from list as uint64_t.";
593  try
594  {
595  TLOG(TLVL_DEBUG + 33) << "Param value: " << paramList.getI8(index);
596  return static_cast<uint64_t>(paramList.getI8(index));
597  }
598  catch (...)
599  {
600  TLOG(TLVL_DEBUG + 33) << "Param value (int): " << paramList.getInt(index);
601  return static_cast<uint64_t>(paramList.getInt(index));
602  }
603 }
604 
613 template<>
614 uint32_t cmd_::getParam<uint32_t>(const xmlrpc_c::paramList& paramList, int index)
615 {
616  TLOG(TLVL_DEBUG + 33) << "Getting parameter " << index << " from list as uint32_t.";
617  TLOG(TLVL_DEBUG + 33) << "Param value: " << paramList.getInt(index);
618  return static_cast<uint32_t>(paramList.getInt(index));
619 }
620 
629 template<>
630 std::string cmd_::getParam<std::string>(const xmlrpc_c::paramList& paramList, int index)
631 {
632  TLOG(TLVL_DEBUG + 33) << "Getting parameter " << index << " from list as string.";
633  TLOG(TLVL_DEBUG + 33) << "Param value: " << paramList.getString(index);
634  return static_cast<std::string>(paramList.getString(index));
635 }
636 
645 template<>
646 art::RunID cmd_::getParam<art::RunID>(const xmlrpc_c::paramList& paramList, int index)
647 {
648  TLOG(TLVL_DEBUG + 33) << "Getting parameter " << index << " from list as Run Number.";
649  art::RunNumber_t run_number;
650  try
651  {
652  TLOG(TLVL_DEBUG + 33) << "Param value: " << paramList.getInt(index);
653  run_number = art::RunNumber_t(paramList.getInt(index));
654  }
655  catch (...)
656  {
657  TLOG(TLVL_DEBUG + 33) << "Parameter is not an int. Trying string...";
658 
659  auto runNumber = paramList.getString(index);
660  TLOG(TLVL_DEBUG + 33) << "Got run number string " << runNumber;
661  run_number = art::RunNumber_t(std::stoi(runNumber));
662  }
663 
664  art::RunID run_id(run_number);
665  return run_id;
666 }
667 
676 template<>
677 fhicl::ParameterSet cmd_::getParam<fhicl::ParameterSet>(const xmlrpc_c::paramList& paramList, int index)
678 {
679  TLOG(TLVL_DEBUG + 33) << "Getting parameter " << index << " from list as ParameterSet.";
680  TLOG(TLVL_DEBUG + 33) << "Param value: " << paramList.getString(index);
681  std::string configString = std::string(paramList.getString(index));
682  TLOG(TLVL_DEBUG + 32) << "Loading Parameter Set from string: " << configString << std::endl;
683  fhicl::ParameterSet pset;
684 
685  try
686  {
687  pset = fhicl::ParameterSet::make(configString);
688  }
689  catch (const fhicl::exception& e)
690  {
691  if (getenv("FHICL_FILE_PATH") == nullptr)
692  {
693  TLOG(TLVL_ERROR) << "INFO: environment variable FHICL_FILE_PATH was not set. Using \".\"";
694  std::cerr << "INFO: environment variable FHICL_FILE_PATH was not set. Using \".\"" << std::endl;
695  setenv("FHICL_FILE_PATH", ".", 0);
696  }
697  cet::filepath_lookup_after1 lookup_policy("FHICL_FILE_PATH");
698  pset = fhicl::ParameterSet::make(configString, lookup_policy);
699  }
700 
701  TLOG(TLVL_INFO) << "Parameter Set Loaded." << std::endl;
702  return pset;
703 }
704 
705 template<typename T>
706 T cmd_::getParam(const xmlrpc_c::paramList& paramList, int index,
707  T default_value)
708 {
709  T val = default_value;
710 
711  if (static_cast<unsigned>(index) < paramList.size())
712  {
713  val = getParam<T>(paramList, index);
714  }
715  return val;
716 }
717 
718 void cmd_::execute(const xmlrpc_c::paramList& paramList, xmlrpc_c::value* const retvalP)
719 {
720  TLOG(TLVL_DEBUG + 33) << "Received Request to " << _help << ", attempting to get lock";
721  std::unique_lock<std::timed_mutex> lk(_c.mutex_, std::defer_lock);
722  auto ret = lk.try_lock_for(std::chrono::milliseconds(250));
723 
724  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  if (execute_(paramList, retvalP))
739  {
740  if (!retvalP->isInstantiated())
741  {
742  *retvalP = xmlrpc_c::value_string("Success");
743  }
744  }
745  else
746  {
747  std::string problemReport = _c._commandable.report("transition_status");
748  *retvalP = xmlrpc_c::value_string(problemReport);
749  }
750  }
751  catch (std::runtime_error& er)
752  {
753  std::string msg = exception_msg(er, _help);
754  *retvalP = xmlrpc_c::value_string(msg);
755  TLOG(TLVL_ERROR) << msg;
756  }
757  catch (art::Exception& er)
758  {
759  std::string msg = exception_msg(er, _help);
760  *retvalP = xmlrpc_c::value_string(msg);
761  TLOG(TLVL_ERROR) << msg;
762  }
763  catch (cet::exception& er)
764  {
765  std::string msg = exception_msg(er, _help);
766  *retvalP = xmlrpc_c::value_string(msg);
767  TLOG(TLVL_ERROR) << msg;
768  }
769  catch (boost::exception& er)
770  {
771  std::string msg = exception_msg(er, _help);
772  *retvalP = xmlrpc_c::value_string(msg);
773  TLOG(TLVL_ERROR) << msg;
774  }
775  catch (std::exception& er)
776  {
777  std::string msg = exception_msg(er, _help);
778  *retvalP = xmlrpc_c::value_string(msg);
779  TLOG(TLVL_ERROR) << msg;
780  }
781  catch (...)
782  {
783  std::string msg = exception_msg("Unknown exception (not from std, boost, cet, or art)", _help);
784  *retvalP = xmlrpc_c::value_string(msg);
785  TLOG(TLVL_ERROR) << msg;
786  }
787 
788  lk.unlock();
789  }
790  else
791  {
792  TLOG(TLVL_ERROR) << "Unable to get lock while trying to " << _help << ", returning busy";
793  *retvalP = xmlrpc_c::value_string("busy");
794  }
795 }
796 
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  \
807  class NAME##_ : public cmd_ \
808  { \
809  public: \
810  \
813  explicit NAME##_(xmlrpc_commander& c) : cmd_(c, "s:sII", DESCRIPTION) \
814  {} \
815  \
816  \
817  static const uint64_t defaultTimeout = 45; \
818  \
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 GENERATE_INIT_TRANSITION(init, initialize, "initialize the program")
842 
843 GENERATE_INIT_TRANSITION(soft_init, soft_initialize, "initialize software components in the program")
844 
845 GENERATE_INIT_TRANSITION(reinit, reinitialize, "re-initialize the program")
846 
847 #undef GENERATE_INIT_TRANSITION
848 
850 
854 class start_ : public cmd_
855 {
856 public:
862  : cmd_(c, "s:iII", "start the run")
863  {}
864 
866  static const uint64_t defaultTimeout = 45;
868  static const uint64_t defaultTimestamp = std::numeric_limits<const uint64_t>::max();
869 
870 private:
871  bool execute_(xmlrpc_c::paramList const& paramList, xmlrpc_c::value* const retvalP) override
872  {
873  try
874  {
875  getParam<art::RunID>(paramList, 0);
876  }
877  catch (...)
878  {
879  *retvalP = xmlrpc_c::value_string("Error: The start message requires the run number as an argument.");
880  return true;
881  }
882 
883  return _c._commandable.start(getParam<art::RunID>(paramList, 0),
884  getParam<uint64_t>(paramList, 1, defaultTimeout),
885  getParam<uint64_t>(paramList, 2, defaultTimestamp));
886  }
887 };
888 
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  \
899  class NAME##_ : public cmd_ \
900  { \
901  public: \
902  \
904  NAME##_(xmlrpc_commander& c) : cmd_(c, "s:II", DESCRIPTION) \
905  {} \
906  \
907  \
908  static const uint64_t defaultTimeout = TIMEOUT; \
909  \
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 GENERATE_TIMEOUT_TIMESTAMP_TRANSITION(pause, pause, "pause the program", 45)
921 
922 GENERATE_TIMEOUT_TIMESTAMP_TRANSITION(resume, resume, "resume the program", 45)
923 
924 GENERATE_TIMEOUT_TIMESTAMP_TRANSITION(stop, stop, "stop the program", 45)
925 
926 #undef GENERATE_TIMEOUT_TIMESTAMP_TRANSITION
927 
931 class shutdown_ : public cmd_
932 {
933 public:
939  : cmd_(c, "s:i", "shutdown the program")
940  {}
941 
943  static const uint64_t defaultTimeout = 45;
944 
945 private:
946  bool execute_(const xmlrpc_c::paramList& paramList, xmlrpc_c::value* const /*retvalP*/) override
947  {
948  auto ret = _c._commandable.shutdown(getParam<uint64_t>(paramList, 0, defaultTimeout));
949 
950 #if 1
951  if (_c.server)
952  {
953  _c.server->terminate();
954  }
955 #endif
956 
957  return ret;
958  }
959 };
960 
964 class status_ : public cmd_
965 {
966 public:
972  : cmd_(c, "s:n", "report the current state")
973  {}
974 
975 private:
976  bool execute_(xmlrpc_c::paramList const& /*unused*/, xmlrpc_c::value* const retvalP) override
977  {
978  *retvalP = xmlrpc_c::value_string(_c._commandable.status());
979  return true;
980  }
981 };
982 
986 class report_ : public cmd_
987 {
988 public:
994  : cmd_(c, "s:s", "report statistics")
995  {}
996 
997 private:
998  bool execute_(xmlrpc_c::paramList const& paramList, xmlrpc_c::value* const retvalP) override
999  {
1000  try
1001  {
1002  getParam<std::string>(paramList, 0);
1003  }
1004  catch (...)
1005  {
1006  *retvalP = xmlrpc_c::value_string("Error: The report message requires a single argument that selects the type of statistics to be reported.");
1007  return true;
1008  }
1009 
1010  *retvalP = xmlrpc_c::value_string(_c._commandable.report(getParam<std::string>(paramList, 0)));
1011  return true;
1012  }
1013 };
1014 
1018 class legal_commands_ : public cmd_
1019 {
1020 public:
1026  : cmd_(c, "s:n", "return the currently legal commands")
1027  {}
1028 
1029 private:
1030  bool execute_(xmlrpc_c::paramList const& /*unused*/, xmlrpc_c::value* const retvalP) override
1031  {
1032  std::vector<std::string> cmdList = _c._commandable.legal_commands();
1033  std::string resultString;
1034 
1035  for (auto& cmd : cmdList)
1036  {
1037  resultString.append(cmd + " ");
1038  if (cmd == "shutdown")
1039  {
1040  resultString.append(" reset");
1041  }
1042  }
1043  *retvalP = xmlrpc_c::value_string(resultString);
1044 
1045  return true;
1046  }
1047 };
1048 
1052 class register_monitor_ : public cmd_
1053 {
1054 public:
1060  : cmd_(c, "s:s", "Get notified of a new monitor")
1061  {}
1062 
1063 private:
1064  bool execute_(xmlrpc_c::paramList const& paramList, xmlrpc_c::value* const retvalP) override
1065  {
1066  try
1067  {
1068  getParam<fhicl::ParameterSet>(paramList, 0);
1069  }
1070  catch (...)
1071  {
1072  *retvalP = xmlrpc_c::value_string("Error: The register_monitor command expects a string representing the FHiCL definition of a Transfer plugin");
1073  return true;
1074  }
1075 
1076  *retvalP = xmlrpc_c::value_string(_c._commandable.register_monitor(getParam<fhicl::ParameterSet>(paramList, 0)));
1077  return true;
1078  }
1079 };
1080 
1085 {
1086 public:
1092  : cmd_(c, "s:s", "Remove a monitor")
1093  {}
1094 
1095 private:
1096  bool execute_(xmlrpc_c::paramList const& paramList, xmlrpc_c::value* const retvalP) override
1097  {
1098  try
1099  {
1100  getParam<std::string>(paramList, 0);
1101  }
1102  catch (...)
1103  {
1104  *retvalP = xmlrpc_c::value_string("Error: The unregister_monitor command expects a string representing the label of the monitor to be removed");
1105  return true;
1106  }
1107 
1108  *retvalP = xmlrpc_c::value_string(_c._commandable.unregister_monitor(getParam<std::string>(paramList, 0)));
1109  return true;
1110  }
1111 };
1112 
1116 class trace_set_ : public cmd_
1117 {
1118 public:
1124  : cmd_(c, "s:ssI", "Set TRACE mask")
1125  {}
1126 
1127 private:
1128  bool execute_(xmlrpc_c::paramList const& paramList, xmlrpc_c::value* const retvalP) override
1129  {
1130  try
1131  {
1132  getParam<std::string>(paramList, 0);
1133  getParam<std::string>(paramList, 1);
1134  getParam<std::string>(paramList, 2);
1135  }
1136  catch (...)
1137  {
1138  *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  return true;
1140  }
1141 
1142  return _c._commandable.do_trace_set(getParam<std::string>(paramList, 0), getParam<std::string>(paramList, 1), getParam<std::string>(paramList, 2));
1143  }
1144 };
1145 
1149 class trace_get_ : public cmd_
1150 {
1151 public:
1157  : cmd_(c, "s:s", "Get TRACE mask")
1158  {}
1159 
1160 private:
1161  bool execute_(xmlrpc_c::paramList const& paramList, xmlrpc_c::value* const retvalP) override
1162  {
1163  try
1164  {
1165  getParam<std::string>(paramList, 0);
1166  }
1167  catch (...)
1168  {
1169  *retvalP = xmlrpc_c::value_string("Error: The trace_get command expects a name (ALL for all)");
1170  return true;
1171  }
1172 
1173  *retvalP = xmlrpc_c::value_string(_c._commandable.do_trace_get(getParam<std::string>(paramList, 0)));
1174  return true;
1175  }
1176 };
1177 
1181 class meta_command_ : public cmd_
1182 {
1183 public:
1189  : cmd_(c, "s:ss", "Run custom command")
1190  {}
1191 
1192 private:
1193  bool execute_(xmlrpc_c::paramList const& paramList, xmlrpc_c::value* const retvalP) override
1194  {
1195  try
1196  {
1197  getParam<std::string>(paramList, 0);
1198  getParam<std::string>(paramList, 1);
1199  }
1200  catch (...)
1201  {
1202  *retvalP = xmlrpc_c::value_string("Error: The meta_command command expects a string command and a string argument");
1203  return true;
1204  }
1205 
1206  return _c._commandable.do_meta_command(getParam<std::string>(paramList, 0), getParam<std::string>(paramList, 1));
1207  }
1208 };
1209 
1213 class rollover_subrun_ : public cmd_
1214 {
1215 public:
1221  : cmd_(c, "s:Ii", "create a new subrun")
1222  {}
1223 
1224  static const uint64_t defaultSequenceID = 0xFFFFFFFFFFFFFFFF;
1225  static const uint32_t defaultSubrunNumber = 1;
1226 
1227 private:
1228  bool execute_(const xmlrpc_c::paramList& paramList, xmlrpc_c::value* const /*retvalP*/) override
1229  {
1230  auto ret = _c._commandable.do_rollover_subrun(getParam<uint64_t>(paramList, 0, defaultSequenceID), getParam<uint32_t>(paramList, 1, defaultSubrunNumber));
1231  return ret;
1232  }
1233 };
1234 
1239 {
1240 public:
1246  : cmd_(c, "s:ss", "Add an entry to the configuration archive list")
1247  {}
1248 
1249 private:
1250  bool execute_(xmlrpc_c::paramList const& paramList, xmlrpc_c::value* const retvalP) override
1251  {
1252  try
1253  {
1254  getParam<std::string>(paramList, 0);
1255  getParam<std::string>(paramList, 1);
1256  }
1257  catch (...)
1258  {
1259  *retvalP = xmlrpc_c::value_string("Error: The add_config_archive_entry command expects a string key and a string value");
1260  return true;
1261  }
1262 
1263  return _c._commandable.do_add_config_archive_entry(getParam<std::string>(paramList, 0), getParam<std::string>(paramList, 1));
1264  }
1265 };
1266 
1271 {
1272 public:
1278  : cmd_(c, "s:n", "Clear the configuration archive list")
1279  {}
1280 
1281 private:
1282  bool execute_(xmlrpc_c::paramList const& /*unused*/, xmlrpc_c::value* const /*retvalP*/) override
1283  {
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 xmlrpc_commander::xmlrpc_commander(const fhicl::ParameterSet& ps, artdaq::Commandable& commandable)
1312  : CommanderInterface(ps, commandable)
1313  , port_(ps.get<int>("id", 0))
1314  , serverUrl_(ps.get<std::string>("server_url", ""))
1315  , server(nullptr)
1316 {
1317  if (serverUrl_.empty())
1318  {
1319  char hostname[HOST_NAME_MAX];
1320  gethostname(hostname, HOST_NAME_MAX);
1321  serverUrl_ = std::string(hostname);
1322  }
1323  if (serverUrl_.find("http") == std::string::npos)
1324  {
1325  serverUrl_ = "http://" + serverUrl_;
1326  }
1327  if (serverUrl_.find(std::to_string(port_)) == std::string::npos && serverUrl_.find(':', 7) == std::string::npos)
1328  {
1329  serverUrl_ = serverUrl_ + ":" + std::to_string(port_);
1330  }
1331  if (serverUrl_.find("RPC2") == std::string::npos)
1332  {
1333  serverUrl_ = serverUrl_ + "/RPC2";
1334  }
1335  TLOG(TLVL_INFO) << "XMLRPC COMMANDER CONSTRUCTOR: Port: " << port_ << ", Server Url: " << serverUrl_;
1336 }
1337 
1339 try
1340 {
1341  // std::cout << "XMLRPC_COMMANDER RUN_SERVER CALLED!" << std::endl;
1342  xmlrpc_c::registry registry;
1343  struct xmlrpc_method_info3 methodInfo;
1344  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  c_registryPPP = reinterpret_cast<xmlrpc_registry***>(reinterpret_cast<char*>(&registry) + 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  register_method2(init, 0x200000);
1372  register_method(soft_init);
1373  register_method(reinit);
1374  register_method(start);
1375  register_method(status);
1376  register_method(report);
1377  register_method(stop);
1378  register_method(pause);
1379  register_method(resume);
1380  register_method(register_monitor);
1381  register_method(unregister_monitor);
1382  register_method(legal_commands);
1383  register_method(trace_set);
1384  register_method(trace_get);
1385  register_method(meta_command);
1386  register_method(rollover_subrun);
1387  register_method(add_config_archive_entry);
1388  register_method(clear_config_archive);
1389 
1390  register_method(shutdown);
1391 
1392  // alias "daq.reset" to the internal shutdown transition
1393  xmlrpc_c::methodPtr const ptr_reset(new shutdown_(*this));
1394  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  XMLRPC_SOCKET socket_file_descriptor = socket(PF_INET, SOCK_STREAM, 0);
1414 
1415  if (socket_file_descriptor < 0)
1416  {
1417  throw cet::exception("xmlrpc_commander::run") << "Problem with the socket() call; C-style errno == " << errno << " (" << strerror(errno) << ")"; // NOLINT(cert-err60-cpp)
1418  }
1419 
1420  int enable = 1;
1421  int retval = setsockopt(socket_file_descriptor,
1422  SOL_SOCKET, SO_REUSEADDR,
1423  &enable, sizeof(int));
1424 
1425  if (retval < 0)
1426  {
1427  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  sockAddr.sin_family = AF_INET;
1433  sockAddr.sin_port = htons(port_);
1434  sockAddr.sin_addr.s_addr = 0;
1435 
1436  retval = bind(socket_file_descriptor,
1437  reinterpret_cast<struct sockaddr*>(&sockAddr), // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)
1438  sizeof(sockAddr));
1439 
1440  if (retval != 0)
1441  {
1442  close(socket_file_descriptor);
1443  throw cet::exception("xmlrpc_commander::run") << "Problem with the bind() call; C-style errno == " << errno << " (" << strerror(errno) << ")"; // NOLINT(cert-err60-cpp)
1444  }
1445 
1446  server = std::make_unique<xmlrpc_c::serverAbyss>(xmlrpc_c::serverAbyss::constrOpt().registryP(&registry).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  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  running_ = true;
1464  server->run();
1465  running_ = false;
1466  }
1467  catch (...)
1468  {
1469  TLOG(TLVL_WARNING) << "server threw an exception; closing the socket and rethrowing";
1470  running_ = false;
1471  close(socket_file_descriptor);
1472  throw;
1473  }
1474 
1475  close(socket_file_descriptor);
1476 
1477  unregister_method(init);
1478  unregister_method(soft_init);
1479  unregister_method(reinit);
1480  unregister_method(start);
1481  unregister_method(status);
1482  unregister_method(report);
1483  unregister_method(stop);
1484  unregister_method(pause);
1485  unregister_method(resume);
1486  unregister_method(register_monitor);
1487  unregister_method(unregister_monitor);
1488  unregister_method(legal_commands);
1489  unregister_method(trace_set);
1490  unregister_method(trace_get);
1491  unregister_method(meta_command);
1492  unregister_method(rollover_subrun);
1493  unregister_method(add_config_archive_entry);
1494  unregister_method(clear_config_archive);
1495 
1496  unregister_method(shutdown);
1497 
1498  TLOG(TLVL_DEBUG + 32) << "server terminated";
1499 }
1500 catch (...)
1501 {
1502  throw;
1503 }
1504 
1505 std::string xmlrpc_commander::send_command_(const std::string& command)
1506 {
1507  if (serverUrl_.empty())
1508  {
1509  std::stringstream errmsg;
1510  errmsg << "Problem attempting " << command << " XML-RPC call: No server URL set!";
1511  ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
1512  }
1513  xmlrpc_c::clientSimple myClient;
1514  xmlrpc_c::value result;
1515 
1516  try
1517  {
1518  myClient.call(serverUrl_, "daq." + command, "", &result);
1519  }
1520  catch (...)
1521  {
1522  std::stringstream errmsg;
1523  errmsg << "Problem attempting " << command << " XML-RPC call on host " << serverUrl_
1524  << "; possible causes are malformed FHiCL or nonexistent process at requested port";
1525  ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
1526  }
1527 
1528  return xmlrpc_c::value_string(result);
1529 }
1530 
1531 std::string xmlrpc_commander::send_command_(const std::string& command, const std::string& arg)
1532 {
1533  if (serverUrl_.empty())
1534  {
1535  std::stringstream errmsg;
1536  errmsg << "Problem attempting " << command << " XML-RPC call: No server URL set!";
1537  ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
1538  }
1539  xmlrpc_c::clientSimple myClient;
1540  xmlrpc_c::value result;
1541 
1542  try
1543  {
1544  myClient.call(serverUrl_, "daq." + command, "s", &result, arg.c_str());
1545  }
1546  catch (...)
1547  {
1548  std::stringstream errmsg;
1549  errmsg << "Problem attempting " << command << " XML-RPC call on host " << serverUrl_
1550  << "; possible causes are malformed FHiCL or nonexistent process at requested port";
1551  ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
1552  }
1553 
1554  return xmlrpc_c::value_string(result);
1555 }
1556 
1557 std::string xmlrpc_commander::send_command_(const std::string& command, const fhicl::ParameterSet& pset, uint64_t timestamp, uint64_t timeout)
1558 {
1559  if (serverUrl_.empty())
1560  {
1561  std::stringstream errmsg;
1562  errmsg << "Problem attempting " << command << " XML-RPC call: No server URL set!";
1563  ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
1564  }
1565  xmlrpc_c::clientSimple myClient;
1566  xmlrpc_c::value result;
1567 
1568  try
1569  {
1570  myClient.call(serverUrl_, "daq." + command, "sII", &result, pset.to_string().c_str(), timestamp, timeout);
1571  }
1572  catch (...)
1573  {
1574  std::stringstream errmsg;
1575  errmsg << "Problem attempting " << command << " XML-RPC call on host " << serverUrl_
1576  << "; possible causes are malformed FHiCL or nonexistent process at requested port";
1577  ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
1578  }
1579 
1580  return xmlrpc_c::value_string(result);
1581 }
1582 
1583 std::string artdaq::xmlrpc_commander::send_command_(const std::string& command, uint64_t a, uint64_t b)
1584 {
1585  if (serverUrl_.empty())
1586  {
1587  std::stringstream errmsg;
1588  errmsg << "Problem attempting " << command << " XML-RPC call: No server URL set!";
1589  ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
1590  }
1591  xmlrpc_c::clientSimple myClient;
1592  xmlrpc_c::value result;
1593 
1594  try
1595  {
1596  myClient.call(serverUrl_, "daq." + command, "II", &result, a, b);
1597  }
1598  catch (...)
1599  {
1600  std::stringstream errmsg;
1601  errmsg << "Problem attempting " << command << " XML-RPC call on host " << serverUrl_
1602  << "; possible causes are malformed FHiCL or nonexistent process at requested port";
1603  ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
1604  }
1605 
1606  return xmlrpc_c::value_string(result);
1607 }
1608 
1609 std::string artdaq::xmlrpc_commander::send_command_(const std::string& command, uint64_t a, uint32_t b)
1610 {
1611  if (serverUrl_.empty())
1612  {
1613  std::stringstream errmsg;
1614  errmsg << "Problem attempting " << command << " XML-RPC call: No server URL set!";
1615  ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
1616  }
1617  xmlrpc_c::clientSimple myClient;
1618  xmlrpc_c::value result;
1619 
1620  try
1621  {
1622  myClient.call(serverUrl_, "daq." + command, "Ii", &result, a, b);
1623  }
1624  catch (...)
1625  {
1626  std::stringstream errmsg;
1627  errmsg << "Problem attempting " << command << " XML-RPC call on host " << serverUrl_
1628  << "; possible causes are malformed FHiCL or nonexistent process at requested port";
1629  ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
1630  }
1631 
1632  return xmlrpc_c::value_string(result);
1633 }
1634 
1635 std::string artdaq::xmlrpc_commander::send_command_(const std::string& command, art::RunID r, uint64_t a, uint64_t b)
1636 {
1637  if (serverUrl_.empty())
1638  {
1639  std::stringstream errmsg;
1640  errmsg << "Problem attempting " << command << " XML-RPC call: No server URL set!";
1641  ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
1642  }
1643  xmlrpc_c::clientSimple myClient;
1644  xmlrpc_c::value result;
1645 
1646  try
1647  {
1648  myClient.call(serverUrl_, "daq." + command, "iII", &result, r.run(), a, b);
1649  }
1650  catch (...)
1651  {
1652  std::stringstream errmsg;
1653  errmsg << "Problem attempting " << command << " XML-RPC call on host " << serverUrl_
1654  << "; possible causes are malformed FHiCL or nonexistent process at requested port";
1655  ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
1656  }
1657 
1658  return xmlrpc_c::value_string(result);
1659 }
1660 
1661 std::string artdaq::xmlrpc_commander::send_command_(const std::string& command, uint64_t arg1)
1662 {
1663  if (serverUrl_.empty())
1664  {
1665  std::stringstream errmsg;
1666  errmsg << "Problem attempting " << command << " XML-RPC call: No server URL set!";
1667  ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
1668  }
1669  xmlrpc_c::clientSimple myClient;
1670  xmlrpc_c::value result;
1671 
1672  try
1673  {
1674  myClient.call(serverUrl_, "daq." + command, "I", &result, arg1);
1675  }
1676  catch (...)
1677  {
1678  std::stringstream errmsg;
1679  errmsg << "Problem attempting " << command << " XML-RPC call on host " << serverUrl_
1680  << "; possible causes are malformed FHiCL or nonexistent process at requested port";
1681  ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
1682  }
1683 
1684  return xmlrpc_c::value_string(result);
1685 }
1686 
1687 std::string artdaq::xmlrpc_commander::send_command_(const std::string& command, const std::string& arg1, const std::string& arg2)
1688 {
1689  if (serverUrl_.empty())
1690  {
1691  std::stringstream errmsg;
1692  errmsg << "Problem attempting " << command << " XML-RPC call: No server URL set!";
1693  ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
1694  }
1695  xmlrpc_c::clientSimple myClient;
1696  xmlrpc_c::value result;
1697 
1698  try
1699  {
1700  myClient.call(serverUrl_, "daq." + command, "ss", &result, arg1.c_str(), arg2.c_str());
1701  }
1702  catch (...)
1703  {
1704  std::stringstream errmsg;
1705  errmsg << "Problem attempting " << command << " XML-RPC call on host " << serverUrl_
1706  << "; possible causes are malformed FHiCL or nonexistent process at requested port";
1707  ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
1708  }
1709 
1710  return xmlrpc_c::value_string(result);
1711 }
1712 
1713 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  if (serverUrl_.empty())
1716  {
1717  std::stringstream errmsg;
1718  errmsg << "Problem attempting " << command << " XML-RPC call: No server URL set!";
1719  ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
1720  }
1721  xmlrpc_c::clientSimple myClient;
1722  xmlrpc_c::value result;
1723 
1724  try
1725  {
1726  myClient.call(serverUrl_, "daq." + command, "sss", &result, arg1.c_str(), arg2.c_str(), arg3.c_str());
1727  }
1728  catch (...)
1729  {
1730  std::stringstream errmsg;
1731  errmsg << "Problem attempting " << command << " XML-RPC call on host " << serverUrl_
1732  << "; possible causes are bad arguments or nonexistent process at requested port";
1733  ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
1734  }
1735 
1736  return xmlrpc_c::value_string(result);
1737 }
1738 
1739 std::string xmlrpc_commander::send_register_monitor(std::string const& monitor_fhicl)
1740 {
1741  return send_command_("register_monitor", monitor_fhicl);
1742 }
1743 std::string xmlrpc_commander::send_unregister_monitor(std::string const& monitor_label)
1744 {
1745  return send_command_("unregister_monitor", monitor_label);
1746 }
1747 std::string artdaq::xmlrpc_commander::send_init(fhicl::ParameterSet const& ps, uint64_t timeout, uint64_t timestamp)
1748 {
1749  return send_command_("init", ps, timeout, timestamp);
1750 }
1751 std::string artdaq::xmlrpc_commander::send_soft_init(fhicl::ParameterSet const& ps, uint64_t timeout, uint64_t timestamp)
1752 {
1753  return send_command_("soft_init", ps, timeout, timestamp);
1754 }
1755 std::string xmlrpc_commander::send_reinit(fhicl::ParameterSet const& ps, uint64_t timeout, uint64_t timestamp)
1756 {
1757  return send_command_("reinit", ps, timeout, timestamp);
1758 }
1759 std::string xmlrpc_commander::send_start(art::RunID run, uint64_t timeout, uint64_t timestamp)
1760 {
1761  return send_command_("start", run, timeout, timestamp);
1762 }
1763 std::string xmlrpc_commander::send_pause(uint64_t timeout, uint64_t timestamp)
1764 {
1765  return send_command_("pause", timeout, timestamp);
1766 }
1767 std::string xmlrpc_commander::send_resume(uint64_t timeout, uint64_t timestamp)
1768 {
1769  return send_command_("resume", timeout, timestamp);
1770 }
1771 std::string xmlrpc_commander::send_stop(uint64_t timeout, uint64_t timestamp)
1772 {
1773  return send_command_("stop", timeout, timestamp);
1774 }
1775 std::string xmlrpc_commander::send_shutdown(uint64_t timeout)
1776 {
1777  return send_command_("shutdown", timeout);
1778 }
1780 {
1781  return send_command_("status");
1782 }
1783 std::string xmlrpc_commander::send_report(std::string const& what)
1784 {
1785  return send_command_("report", what);
1786 }
1788 {
1789  return send_command_("legal_commands");
1790 }
1791 std::string xmlrpc_commander::send_trace_get(std::string const& name)
1792 {
1793  return send_command_("trace_get", name);
1794 }
1795 std::string xmlrpc_commander::send_trace_set(std::string const& name, std::string const& type, std::string const& mask)
1796 {
1797  return send_command_("trace_set", name, type, mask);
1798 }
1799 std::string xmlrpc_commander::send_meta_command(std::string const& command, std::string const& arg)
1800 {
1801  return send_command_("meta_command", command, arg);
1802 }
1803 std::string xmlrpc_commander::send_rollover_subrun(uint64_t when, uint32_t sr)
1804 {
1805  return send_command_("rollover_subrun", when, sr);
1806 }
1807 } // namespace artdaq
1808 
1809 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:539
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:126
Commandable is the base class for all artdaq components which implement the artdaq state machine...
Definition: Commandable.hh:22
legal_commands_(xmlrpc_commander &c)
legal_commands_ Constructor
virtual bool do_clear_config_archive()
Clears the configuration archive list.
Definition: Commandable.cc:545
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:155
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:300
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:144
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:473
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:313
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:63
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:436
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:526
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:532
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:182