00001
00002
00003
00004
00005
00006 #pragma GCC diagnostic push
00007 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
00008 #define _LIBCPP_ENABLE_CXX17_REMOVED_FEATURES 1
00009 #include <xmlrpc-c/base.hpp>
00010 #include <xmlrpc-c/registry.hpp>
00011 #include <xmlrpc-c/server_abyss.hpp>
00012 #include <xmlrpc-c/girerr.hpp>
00013 #include <xmlrpc-c/client_simple.hpp>
00014 #undef _LIBCPP_ENABLE_CXX17_REMOVED_FEATURES
00015 #pragma GCC diagnostic pop
00016 #include <stdexcept>
00017 #include <iostream>
00018 #include <limits>
00019 #include <memory>
00020 #include <cstdint>
00021 #define TRACE_NAME (app_name + "_xmlrpc_commander").c_str()
00022 #include "artdaq/DAQdata/Globals.hh"
00023 #include "tracemf.h"
00024
00025 #include "artdaq-core/Utilities/ExceptionHandler.hh"
00026 #include <sys/socket.h>
00027 #include <netinet/in.h>
00028 #include <errno.h>
00029 #include <cstring>
00030 #include <exception>
00031
00032 #include "canvas/Persistency/Provenance/RunID.h"
00033 #include "fhiclcpp/make_ParameterSet.h"
00034
00035 #include "artdaq/ExternalComms/xmlrpc_commander.hh"
00036
00037
00038 namespace {
00042 class env_wrap {
00043 public:
00044 env_wrap() { xmlrpc_env_init(&this->env_c); };
00045 ~env_wrap() { xmlrpc_env_clean(&this->env_c); };
00046 xmlrpc_env env_c;
00047 };
00048 }
00049 static xmlrpc_c::paramList
00050 pListFromXmlrpcArray(xmlrpc_value * const arrayP)
00051 {
00052 env_wrap env;
00053 XMLRPC_ASSERT_ARRAY_OK(arrayP);
00054 unsigned int const arraySize = xmlrpc_array_size(&env.env_c, arrayP);
00055 assert(!env.env_c.fault_occurred);
00056 xmlrpc_c::paramList paramList(arraySize);
00057 for (unsigned int i = 0; i < arraySize; ++i) {
00058 xmlrpc_value * arrayItemP;
00059 xmlrpc_array_read_item(&env.env_c, arrayP, i, &arrayItemP);
00060 assert(!env.env_c.fault_occurred);
00061 paramList.add(xmlrpc_c::value(arrayItemP));
00062 xmlrpc_DECREF(arrayItemP);
00063 }
00064 return paramList;
00065 }
00066 static xmlrpc_value *
00067 c_executeMethod(xmlrpc_env * const envP,
00068 xmlrpc_value * const paramArrayP,
00069 void * const methodPtr,
00070 void * const callInfoPtr)
00071 {
00072 xmlrpc_c::method * const methodP(static_cast<xmlrpc_c::method *>(methodPtr));
00073 xmlrpc_c::paramList const paramList(pListFromXmlrpcArray(paramArrayP));
00074 xmlrpc_c::callInfo * const callInfoP(static_cast<xmlrpc_c::callInfo *>(callInfoPtr));
00075 xmlrpc_value * retval;
00076 retval = NULL;
00077 try {
00078 xmlrpc_c::value result;
00079 try {
00080 xmlrpc_c::method2 * const method2P(dynamic_cast<xmlrpc_c::method2 *>(methodP));
00081 if (method2P)
00082 method2P->execute(paramList, callInfoP, &result);
00083 else
00084 methodP->execute(paramList, &result);
00085 }
00086 catch (xmlrpc_c::fault const& fault) {
00087 xmlrpc_env_set_fault(envP, fault.getCode(),
00088 fault.getDescription().c_str());
00089 }
00090 if (!envP->fault_occurred) {
00091 if (result.isInstantiated())
00092 retval = result.cValue();
00093 else
00094 girerr::throwf("Xmlrpc-c user's xmlrpc_c::method object's "
00095 "'execute method' failed to set the RPC result "
00096 "value.");
00097 }
00098 }
00099 catch (std::exception const& e) {
00100 xmlrpc_faultf(envP, "Unexpected error executing code for "
00101 "particular method, detected by Xmlrpc-c "
00102 "method registry code. Method did not "
00103 "fail; rather, it did not complete at all. %s",
00104 e.what());
00105 }
00106 catch (...) {
00107 xmlrpc_env_set_fault(envP, XMLRPC_INTERNAL_ERROR,
00108 "Unexpected error executing code for "
00109 "particular method, detected by Xmlrpc-c "
00110 "method registry code. Method did not "
00111 "fail; rather, it did not complete at all.");
00112 }
00113 return retval;
00114 }
00115
00116
00117
00118 namespace artdaq
00119 {
00126 std::string exception_msg(const std::runtime_error& er,
00127 const std::string& helpText = "execute request")
00128 {
00129 std::string msg("Exception when trying to ");
00130 msg.append(helpText);
00131 msg.append(": ");
00132 msg.append(er.what());
00133 if (msg[msg.size() - 1] == '\n') msg.erase(msg.size() - 1);
00134 return msg;
00135 }
00136
00143 std::string exception_msg(const art::Exception& er,
00144 const std::string& helpText)
00145 {
00146 std::string msg("Exception when trying to ");
00147 msg.append(helpText);
00148 msg.append(": ");
00149 msg.append(er.what());
00150 if (msg[msg.size() - 1] == '\n') msg.erase(msg.size() - 1);
00151 return msg;
00152 }
00153
00160 std::string exception_msg(const cet::exception& er,
00161 const std::string& helpText)
00162 {
00163 std::string msg("Exception when trying to ");
00164 msg.append(helpText);
00165 msg.append(": ");
00166 msg.append(er.what());
00167 if (msg[msg.size() - 1] == '\n') msg.erase(msg.size() - 1);
00168 return msg;
00169 }
00170
00177 std::string exception_msg(const std::string& erText,
00178 const std::string& helpText)
00179 {
00180 std::string msg("Exception when trying to ");
00181 msg.append(helpText);
00182 msg.append(": ");
00183 msg.append(erText);
00184 if (msg[msg.size() - 1] == '\n') msg.erase(msg.size() - 1);
00185 return msg;
00186 }
00187
00188
00206 class cmd_ : public xmlrpc_c::method
00207 {
00208 public:
00209
00210
00217 cmd_(xmlrpc_commander& c, const std::string& signature, const std::string& description) : _c(c)
00218 {
00219 _signature = signature;
00220 _help = description;
00221 }
00222
00228 void execute(const xmlrpc_c::paramList& paramList, xmlrpc_c::value* const retvalP) final;
00229
00230 protected:
00231
00232 xmlrpc_commander & _c;
00233
00239 virtual bool execute_(const xmlrpc_c::paramList&, xmlrpc_c::value* const retvalP) = 0;
00240
00250 template <typename T>
00251 T getParam(const xmlrpc_c::paramList& paramList, int index);
00252
00276 template <typename T>
00277 T getParam(const xmlrpc_c::paramList& paramList, int index, T default_value);
00278 };
00279
00280
00281
00282
00283 template <typename T>
00284 T cmd_::getParam(const xmlrpc_c::paramList&, int)
00285 {
00286 throw cet::exception("cmd_") << "Error in cmd_::getParam(): value type not supported" << std::endl;
00287 }
00288
00297 template <>
00298 uint64_t cmd_::getParam<uint64_t>(const xmlrpc_c::paramList& paramList, int index)
00299 {
00300 TLOG(TLVL_TRACE) << "Getting parameter " << index << " from list as uint64_t.";
00301 TLOG(TLVL_TRACE) << "Param value: " << paramList.getString(index);
00302 return boost::lexical_cast<uint64_t>(paramList.getString(index));
00303 }
00304
00313 template <>
00314 std::string cmd_::getParam<std::string>(const xmlrpc_c::paramList& paramList, int index)
00315 {
00316 TLOG(TLVL_TRACE) << "Getting parameter " << index << " from list as string.";
00317 TLOG(TLVL_TRACE) << "Param value: " << paramList.getString(index);
00318 return static_cast<std::string>(paramList.getString(index));
00319 }
00320
00329 template <>
00330 art::RunID cmd_::getParam<art::RunID>(const xmlrpc_c::paramList& paramList, int index)
00331 {
00332 TLOG(TLVL_TRACE) << "Getting parameter " << index << " from list as Run Number.";
00333 TLOG(TLVL_TRACE) << "Param value: " << paramList.getString(index);
00334 std::string run_number_string = paramList.getString(index);
00335 art::RunNumber_t run_number =
00336 boost::lexical_cast<art::RunNumber_t>(run_number_string);
00337 art::RunID run_id(run_number);
00338
00339 return run_id;
00340 }
00341
00350 template <>
00351 fhicl::ParameterSet cmd_::getParam<fhicl::ParameterSet>(const xmlrpc_c::paramList& paramList, int index)
00352 {
00353 TLOG(TLVL_TRACE) << "Getting parameter " << index << " from list as ParameterSet.";
00354 TLOG(TLVL_TRACE) << "Param value: " << paramList.getString(index);
00355 std::string configString = std::string(paramList.getString(index).c_str());
00356 TLOG(TLVL_DEBUG) << "Loading Parameter Set from string: " << configString << std::endl;
00357 fhicl::ParameterSet pset;
00358
00359 try
00360 {
00361 fhicl::make_ParameterSet(configString, pset);
00362 }
00363 catch (fhicl::exception e)
00364 {
00365 if (getenv("FHICL_FILE_PATH") == nullptr)
00366 {
00367 std::cerr << "INFO: environment variable FHICL_FILE_PATH was not set. Using \".\"\n";
00368 setenv("FHICL_FILE_PATH", ".", 0);
00369 }
00370 cet::filepath_lookup_after1 lookup_policy("FHICL_FILE_PATH");
00371 fhicl::make_ParameterSet(configString, lookup_policy, pset);
00372 }
00373
00374 TLOG(TLVL_INFO) << "Parameter Set Loaded." << std::endl;
00375 return pset;
00376 }
00377
00378 template <typename T>
00379 T cmd_::getParam(const xmlrpc_c::paramList& paramList, int index,
00380 T default_value)
00381 {
00382 T val = default_value;
00383
00384 try
00385 {
00386 val = getParam<T>(paramList, index);
00387 }
00388 catch (const cet::exception& exception)
00389 {
00390 throw exception;
00391 }
00392 catch (...) {}
00393
00394 return val;
00395 }
00396
00397 void cmd_::execute(const xmlrpc_c::paramList& paramList, xmlrpc_c::value* const retvalP)
00398 {
00399 std::unique_lock<std::timed_mutex> lk(_c.mutex_, std::chrono::milliseconds(250));
00400 if (lk.owns_lock())
00401 {
00402 try
00403 {
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414 if (execute_(paramList, retvalP))
00415 {
00416 if (!retvalP->isInstantiated())
00417 {
00418 *retvalP = xmlrpc_c::value_string("Success");
00419 }
00420 }
00421 else
00422 {
00423 std::string problemReport = _c._commandable.report("transition_status");
00424 *retvalP = xmlrpc_c::value_string(problemReport);
00425 }
00426 }
00427 catch (std::runtime_error& er)
00428 {
00429 std::string msg = exception_msg(er, _help);
00430 *retvalP = xmlrpc_c::value_string(msg);
00431 TLOG(TLVL_ERROR) << msg;
00432 }
00433 catch (art::Exception& er)
00434 {
00435 std::string msg = exception_msg(er, _help);
00436 *retvalP = xmlrpc_c::value_string(msg);
00437 TLOG(TLVL_ERROR) << msg;
00438 }
00439 catch (cet::exception& er)
00440 {
00441 std::string msg = exception_msg(er, _help);
00442 *retvalP = xmlrpc_c::value_string(msg);
00443 TLOG(TLVL_ERROR) << msg;
00444 }
00445 catch (...)
00446 {
00447 std::string msg = exception_msg("Unknown exception", _help);
00448 *retvalP = xmlrpc_c::value_string(msg);
00449 TLOG(TLVL_ERROR) << msg;
00450 }
00451 }
00452 else
00453 {
00454 *retvalP = xmlrpc_c::value_string("busy");
00455 }
00456 }
00457
00458
00460
00461
00462
00463
00464
00465
00466
00467 #define GENERATE_INIT_TRANSITION(NAME, CALL, DESCRIPTION) \
00468 \
00469 class NAME ## _: public cmd_ { \
00470 \
00471 public: \
00472 \
00475 explicit NAME ## _(xmlrpc_commander& c): \
00476 cmd_(c, "s:sii", DESCRIPTION) {} \
00477 \
00478 \
00479 static const uint64_t defaultTimeout = 45; \
00480 \
00481 static const uint64_t defaultTimestamp = std::numeric_limits<const uint64_t>::max(); \
00482 \
00483 private: \
00484 bool execute_(const xmlrpc_c::paramList& paramList, xmlrpc_c::value* const retvalP ) { \
00485 fhicl::ParameterSet ps; \
00486 try { \
00487 ps = getParam<fhicl::ParameterSet>(paramList, 0); \
00488 } catch (...) { \
00489 *retvalP = xmlrpc_c::value_string ("The "#NAME" message requires a single argument that is a string containing the initialization ParameterSet"); \
00490 return true; \
00491 } \
00492 \
00493 return _c._commandable.CALL(ps, \
00494 getParam<uint64_t>(paramList, 1, defaultTimeout), \
00495 getParam<uint64_t>(paramList, 2, defaultTimestamp) \
00496 ); \
00497 } \
00498 };
00499
00500 GENERATE_INIT_TRANSITION(init, initialize, "initialize the program")
00501
00502 GENERATE_INIT_TRANSITION(soft_init, soft_initialize, "initialize software components in the program")
00503
00504 GENERATE_INIT_TRANSITION(reinit, reinitialize, "re-initialize the program")
00505
00506 #undef GENERATE_INIT_TRANSITION
00507
00509
00513 class start_ : public cmd_
00514 {
00515 public:
00520 explicit start_(xmlrpc_commander& c) :
00521 cmd_(c, "s:iii", "start the run")
00522 {}
00523
00525 static const uint64_t defaultTimeout = 45;
00527 static const uint64_t defaultTimestamp = std::numeric_limits<const uint64_t>::max();
00528
00529 private:
00530
00531 bool execute_(xmlrpc_c::paramList const& paramList, xmlrpc_c::value* const retvalP) override
00532 {
00533 try
00534 {
00535 getParam<art::RunID>(paramList, 0);
00536 }
00537 catch (...)
00538 {
00539 *retvalP = xmlrpc_c::value_string("The start message requires the run number as an argument.");
00540 return true;
00541 }
00542
00543 return _c._commandable.start(getParam<art::RunID>(paramList, 0),
00544 getParam<uint64_t>(paramList, 1, defaultTimeout),
00545 getParam<uint64_t>(paramList, 2, defaultTimestamp)
00546 );
00547 }
00548 };
00549
00550
00552
00553
00554
00555
00556
00557
00558
00559 #define GENERATE_TIMEOUT_TIMESTAMP_TRANSITION(NAME, CALL, DESCRIPTION, TIMEOUT) \
00560 \
00561 class NAME ## _: public cmd_ { \
00562 \
00563 public: \
00564 \
00566 NAME ## _(xmlrpc_commander& c): \
00567 cmd_(c, "s:ii", DESCRIPTION) {} \
00568 \
00569 \
00570 static const uint64_t defaultTimeout = TIMEOUT ; \
00571 \
00572 static const uint64_t defaultTimestamp = std::numeric_limits<const uint64_t>::max(); \
00573 \
00574 private: \
00575 \
00576 bool execute_ (const xmlrpc_c::paramList& paramList , xmlrpc_c::value* const ) { \
00577 \
00578 return _c._commandable.CALL( getParam<uint64_t>(paramList, 0, defaultTimeout), \
00579 getParam<uint64_t>(paramList, 1, defaultTimestamp) \
00580 ); \
00581 } \
00582 };
00583
00584 GENERATE_TIMEOUT_TIMESTAMP_TRANSITION(pause, pause, "pause the program", 45)
00585
00586 GENERATE_TIMEOUT_TIMESTAMP_TRANSITION(resume, resume, "resume the program", 45)
00587
00588 GENERATE_TIMEOUT_TIMESTAMP_TRANSITION(stop, stop, "stop the program", 45)
00589
00590 #undef GENERATE_TIMEOUT_TIMESTAMP_TRANSITION
00591
00592
00596 class shutdown_ : public cmd_
00597 {
00598 public:
00603 shutdown_(xmlrpc_commander& c) :
00604 cmd_(c, "s:i", "shutdown the program")
00605 {}
00606
00608 static const uint64_t defaultTimeout = 45;
00609
00610 private:
00611
00612 bool execute_(const xmlrpc_c::paramList& paramList, xmlrpc_c::value* const)
00613 {
00614 auto ret = _c._commandable.shutdown(getParam<uint64_t>(paramList, 0, defaultTimeout));
00615
00616 #if 1
00617 if (_c.server) _c.server->terminate();
00618 #endif
00619
00620 return ret;
00621 }
00622 };
00623
00624
00628 class status_ : public cmd_
00629 {
00630 public:
00635 status_(xmlrpc_commander& c) :
00636 cmd_(c, "s:n", "report the current state")
00637 {}
00638
00639 private:
00640
00641 bool execute_(xmlrpc_c::paramList const&, xmlrpc_c::value* const retvalP)
00642 {
00643 *retvalP = xmlrpc_c::value_string(_c._commandable.status());
00644 return true;
00645 }
00646 };
00647
00648
00652 class report_ : public cmd_
00653 {
00654 public:
00659 report_(xmlrpc_commander& c) :
00660 cmd_(c, "s:s", "report statistics")
00661 {}
00662
00663 private:
00664 bool execute_(xmlrpc_c::paramList const& paramList, xmlrpc_c::value* const retvalP)
00665 {
00666 try
00667 {
00668 getParam<std::string>(paramList, 0);
00669 }
00670 catch (...)
00671 {
00672 *retvalP = xmlrpc_c::value_string("The report message requires a single argument that selects the type of statistics to be reported.");
00673 return true;
00674 }
00675
00676 *retvalP = xmlrpc_c::value_string(_c._commandable.report(getParam<std::string>(paramList, 0)));
00677 return true;
00678 }
00679 };
00680
00684 class legal_commands_ : public cmd_
00685 {
00686 public:
00691 legal_commands_(xmlrpc_commander& c) :
00692 cmd_(c, "s:n", "return the currently legal commands")
00693 {}
00694
00695 private:
00696 bool execute_(xmlrpc_c::paramList const&, xmlrpc_c::value* const retvalP)
00697 {
00698 std::vector<std::string> cmdList = _c._commandable.legal_commands();
00699 std::string resultString;
00700
00701 for (auto& cmd : cmdList)
00702 {
00703 resultString.append(cmd + " ");
00704 if (cmd == "shutdown")
00705 {
00706 resultString.append(" reset");
00707 }
00708 }
00709 *retvalP = xmlrpc_c::value_string(resultString);
00710
00711 return true;
00712 }
00713 };
00714
00718 class register_monitor_ : public cmd_
00719 {
00720 public:
00725 register_monitor_(xmlrpc_commander& c) :
00726 cmd_(c, "s:s", "Get notified of a new monitor")
00727 {}
00728
00729 private:
00730 bool execute_(xmlrpc_c::paramList const& paramList, xmlrpc_c::value* const retvalP)
00731 {
00732 try
00733 {
00734 getParam<fhicl::ParameterSet>(paramList, 0);
00735 }
00736 catch (...)
00737 {
00738 *retvalP = xmlrpc_c::value_string("The register_monitor command expects a string representing the FHiCL definition of a Transfer plugin");
00739 return true;
00740 }
00741
00742 *retvalP = xmlrpc_c::value_string(_c._commandable.register_monitor(getParam<fhicl::ParameterSet>(paramList, 0)));
00743 return true;
00744 }
00745 };
00746
00750 class unregister_monitor_ : public cmd_
00751 {
00752 public:
00757 unregister_monitor_(xmlrpc_commander& c) :
00758 cmd_(c, "s:s", "Remove a monitor")
00759 {}
00760
00761 private:
00762 bool execute_(xmlrpc_c::paramList const& paramList, xmlrpc_c::value* const retvalP)
00763 {
00764 try
00765 {
00766 getParam<std::string>(paramList, 0);
00767 }
00768 catch (...)
00769 {
00770 *retvalP = xmlrpc_c::value_string("The unregister_monitor command expects a string representing the label of the monitor to be removed");
00771 return true;
00772 }
00773
00774 *retvalP = xmlrpc_c::value_string(_c._commandable.unregister_monitor(getParam<std::string>(paramList, 0)));
00775 return true;
00776 }
00777 };
00778
00779
00783 class trace_set_ : public cmd_
00784 {
00785 public:
00790 trace_set_(xmlrpc_commander& c) :
00791 cmd_(c, "s:ssi", "Set TRACE mask")
00792 {}
00793
00794 private:
00795 bool execute_(xmlrpc_c::paramList const& paramList, xmlrpc_c::value* const retvalP)
00796 {
00797 try
00798 {
00799 getParam<std::string>(paramList, 0);
00800 getParam<std::string>(paramList, 1);
00801 getParam<uint64_t>(paramList, 2);
00802 }
00803 catch (...)
00804 {
00805 *retvalP = xmlrpc_c::value_string("The trace_set command expects a mask type (M, S , or T), a name (ALL for all) and a mask");
00806 return true;
00807 }
00808
00809 return _c._commandable.do_trace_set(getParam<std::string>(paramList, 0), getParam<std::string>(paramList, 1), getParam<uint64_t>(paramList, 2));
00810 }
00811 };
00812
00816 class trace_get_ : public cmd_
00817 {
00818 public:
00823 trace_get_(xmlrpc_commander& c) :
00824 cmd_(c, "s:s", "Get TRACE mask")
00825 {}
00826
00827 private:
00828 bool execute_(xmlrpc_c::paramList const& paramList, xmlrpc_c::value* const retvalP)
00829 {
00830 try
00831 {
00832 getParam<std::string>(paramList, 0);
00833 }
00834 catch (...)
00835 {
00836 *retvalP = xmlrpc_c::value_string("The trace_msgfacility_set command expects a name (ALL for all)");
00837 return true;
00838 }
00839
00840 *retvalP = xmlrpc_c::value_string(_c._commandable.do_trace_get(getParam<std::string>(paramList, 0)));
00841 return true;
00842 }
00843 };
00844
00848 class meta_command_ : public cmd_
00849 {
00850 public:
00855 meta_command_(xmlrpc_commander& c) :
00856 cmd_(c, "s:ss", "Run custom command")
00857 {}
00858
00859 private:
00860 bool execute_(xmlrpc_c::paramList const& paramList, xmlrpc_c::value* const retvalP)
00861 {
00862 try
00863 {
00864 getParam<std::string>(paramList, 0);
00865 getParam<std::string>(paramList, 1);
00866 }
00867 catch (...)
00868 {
00869 *retvalP = xmlrpc_c::value_string("The meta_command command expects a string command and a string argument");
00870 return true;
00871 }
00872
00873 return _c._commandable.do_meta_command(getParam<std::string>(paramList, 0), getParam<std::string>(paramList, 1));
00874 }
00875 };
00876
00880 class rollover_subrun_ : public cmd_
00881 {
00882 public:
00887 rollover_subrun_(xmlrpc_commander& c) :
00888 cmd_(c, "s:i", "create a new subrun")
00889 {}
00890
00892 static const uint64_t defaultSequenceID = 0xFFFFFFFFFFFFFFFF;
00893
00894 private:
00895
00896 bool execute_(const xmlrpc_c::paramList& paramList, xmlrpc_c::value* const)
00897 {
00898 auto ret = _c._commandable.do_rollover_subrun(getParam<uint64_t>(paramList, 0, defaultSequenceID));
00899 return ret;
00900 }
00901 };
00902
00906 class add_config_archive_entry_ : public cmd_
00907 {
00908 public:
00913 add_config_archive_entry_(xmlrpc_commander& c) :
00914 cmd_(c, "s:ss", "Add an entry to the configuration archive list")
00915 {}
00916
00917 private:
00918 bool execute_(xmlrpc_c::paramList const& paramList, xmlrpc_c::value* const retvalP)
00919 {
00920 try
00921 {
00922 getParam<std::string>(paramList, 0);
00923 getParam<std::string>(paramList, 1);
00924 }
00925 catch (...)
00926 {
00927 *retvalP = xmlrpc_c::value_string("The add_config_archive_entry command expects a string key and a string value");
00928 return true;
00929 }
00930
00931 return _c._commandable.do_add_config_archive_entry(getParam<std::string>(paramList, 0), getParam<std::string>(paramList, 1));
00932 }
00933 };
00934
00938 class clear_config_archive_ : public cmd_
00939 {
00940 public:
00945 clear_config_archive_(xmlrpc_commander& c) :
00946 cmd_(c, "s:n", "Clear the configuration archive list")
00947 {}
00948
00949 private:
00950 bool execute_(xmlrpc_c::paramList const&, xmlrpc_c::value* const)
00951 {
00952 return _c._commandable.do_clear_config_archive();
00953 }
00954 };
00955
00956
00957
00958
00959
00960
00961 #if 0
00962 class shutdown_ : public xmlrpc_c::registry::shutdown
00963 {
00964 public:
00965 shutdown_(xmlrpc_c::serverAbyss *server) : _server(server) {}
00966
00967 virtual void doit(const std::string& paramString, void*) const
00968 {
00969 TLOG(TLVL_INFO) << "A shutdown command was sent "
00970 << "with parameter "
00971 << paramString << "\"";
00972 _server->terminate();
00973 }
00974 private:
00975 xmlrpc_c::serverAbyss *_server;
00976 };
00977 #endif
00978
00979
00980
00981 xmlrpc_commander::xmlrpc_commander(fhicl::ParameterSet ps, artdaq::Commandable& commandable)
00982 : CommanderInterface(ps, commandable)
00983 , port_(ps.get<int>("id", 0))
00984 , serverUrl_(ps.get<std::string>("server_url", ""))
00985 , server(nullptr)
00986 {
00987 TLOG(TLVL_INFO) << "XMLRPC COMMANDER CONSTRUCTOR: Port: " << port_ << ", Server Url: " << serverUrl_;
00988 if (serverUrl_.find("http") == std::string::npos)
00989 {
00990 serverUrl_ = "http://" + serverUrl_;
00991 }
00992 if (serverUrl_.find(std::to_string(port_)) == std::string::npos && serverUrl_.find(':', 7) == std::string::npos)
00993 {
00994 serverUrl_ = serverUrl_ + ":" + std::to_string(port_);
00995 }
00996 if (serverUrl_.find("RPC2") == std::string::npos)
00997 {
00998 serverUrl_ = serverUrl_ + "/RPC2";
00999 }
01000 TLOG(TLVL_INFO) << "XMLRPC COMMANDER CONSTRUCTOR: Port: " << port_ << ", Server Url: " << serverUrl_;
01001
01002 }
01003
01004 void xmlrpc_commander::run_server() try
01005 {
01006
01007 xmlrpc_c::registry registry;
01008 struct xmlrpc_method_info3 methodInfo;
01009 memset(&methodInfo, 0, sizeof(methodInfo));
01010
01011
01012
01013
01014 #define register_method(m) register_method2(m,0x400000)
01015
01016 xmlrpc_env env;
01017 xmlrpc_registry ***c_registryPPP;
01018 c_registryPPP = (xmlrpc_registry ***)(((char*)®istry) + sizeof(girmem::autoObject));
01019
01020 #define register_method2(m,ss) \
01021 xmlrpc_c::method* ptr_ ## m(dynamic_cast<xmlrpc_c::method*>(new m ## _(*this))); \
01022 std::string m##signature = ptr_ ## m->signature(), m##help = ptr_ ## m->help(); \
01023 methodInfo.methodName = "daq." #m; \
01024 methodInfo.methodFunction = &c_executeMethod; \
01025 methodInfo.serverInfo = ptr_ ## m; \
01026 methodInfo.stackSize = ss; \
01027 methodInfo.signatureString = &m##signature[0]; \
01028 methodInfo.help = &m##help[0]; \
01029 xmlrpc_env_init(&env); \
01030 xmlrpc_registry_add_method3(&env,**c_registryPPP,&methodInfo); \
01031 if(env.fault_occurred)throw(girerr::error(env.fault_string)); \
01032 xmlrpc_env_clean(&env)
01033
01034 register_method2(init, 0x200000);
01035 register_method(soft_init);
01036 register_method(reinit);
01037 register_method(start);
01038 register_method(status);
01039 register_method(report);
01040 register_method(stop);
01041 register_method(pause);
01042 register_method(resume);
01043 register_method(register_monitor);
01044 register_method(unregister_monitor);
01045 register_method(legal_commands);
01046 register_method(trace_set);
01047 register_method(trace_get);
01048 register_method(meta_command);
01049 register_method(rollover_subrun);
01050 register_method(add_config_archive_entry);
01051 register_method(clear_config_archive);
01052
01053 register_method(shutdown);
01054
01055
01056 xmlrpc_c::methodPtr const ptr_reset(new shutdown_(*this));
01057 registry.addMethod("daq.reset", ptr_reset);
01058
01059 #undef register_method
01060
01061
01062
01063
01064
01065
01066
01067
01068
01069
01070
01071
01072
01073
01074
01075
01076 XMLRPC_SOCKET socket_file_descriptor = socket(PF_INET, SOCK_STREAM, 0);
01077
01078 if (socket_file_descriptor < 0)
01079 {
01080 throw cet::exception("xmlrpc_commander::run") <<
01081 "Problem with the socket() call; C-style errno == " <<
01082 errno << " (" << strerror(errno) << ")";
01083 }
01084
01085 int enable = 1;
01086 int retval = setsockopt(socket_file_descriptor,
01087 SOL_SOCKET, SO_REUSEADDR,
01088 &enable, sizeof(int));
01089
01090 if (retval < 0)
01091 {
01092 throw cet::exception("xmlrpc_commander::run") <<
01093 "Problem with the call to setsockopt(); C-style errno == " <<
01094 errno << " (" << strerror(errno) << ")";
01095 }
01096
01097 struct sockaddr_in sockAddr;
01098
01099 sockAddr.sin_family = AF_INET;
01100 sockAddr.sin_port = htons(port_);
01101 sockAddr.sin_addr.s_addr = 0;
01102
01103 retval = bind(socket_file_descriptor,
01104 reinterpret_cast<struct sockaddr*>(&sockAddr),
01105 sizeof(sockAddr));
01106
01107 if (retval != 0)
01108 {
01109 close(socket_file_descriptor);
01110 throw cet::exception("xmlrpc_commander::run") <<
01111 "Problem with the bind() call; C-style errno == " <<
01112 errno << " (" << strerror(errno) << ")";
01113 }
01114
01115 server.reset(new xmlrpc_c::serverAbyss(xmlrpc_c::serverAbyss::constrOpt().registryP(®istry).socketFd(socket_file_descriptor)));
01116
01117 #if 0
01118 xmlrpc_c::serverAbyss::shutdown shutdown_obj(&server);
01119 registry.setShutdown(&shutdown_obj);
01120 #endif
01121
01122 TLOG(TLVL_DEBUG) << "running server";
01123
01124
01125
01126
01127
01128
01129
01130 try
01131 {
01132 running_ = true;
01133 server->run();
01134 running_ = false;
01135 }
01136 catch (...)
01137 {
01138 TLOG(TLVL_WARNING) << "server threw an exception; closing the socket and rethrowing";
01139 running_ = false;
01140 close(socket_file_descriptor);
01141 throw;
01142 }
01143
01144 close(socket_file_descriptor);
01145 TLOG(TLVL_DEBUG) << "server terminated";
01146 }
01147 catch (...)
01148 {
01149 throw;
01150 }
01151
01152 std::string xmlrpc_commander::send_command_(std::string command)
01153 {
01154 if (serverUrl_ == "")
01155 {
01156 std::stringstream errmsg;
01157 errmsg << "Problem attempting " << command << " XML-RPC call: No server URL set!";
01158 ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
01159
01160 }
01161 xmlrpc_c::clientSimple myClient;
01162 xmlrpc_c::value result;
01163
01164 try
01165 {
01166 myClient.call(serverUrl_, "daq." + command, "", &result);
01167 }
01168 catch (...)
01169 {
01170 std::stringstream errmsg;
01171 errmsg << "Problem attempting " << command << " XML-RPC call on host " << serverUrl_
01172 << "; possible causes are malformed FHiCL or nonexistent process at requested port";
01173 ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
01174 }
01175
01176 return xmlrpc_c::value_string(result);
01177 }
01178
01179 std::string xmlrpc_commander::send_command_(std::string command, std::string arg)
01180 {
01181 if (serverUrl_ == "")
01182 {
01183 std::stringstream errmsg;
01184 errmsg << "Problem attempting " << command << " XML-RPC call: No server URL set!";
01185 ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
01186
01187 }
01188 xmlrpc_c::clientSimple myClient;
01189 xmlrpc_c::value result;
01190
01191 try
01192 {
01193 myClient.call(serverUrl_, "daq." + command, "s", &result, arg.c_str());
01194 }
01195 catch (...)
01196 {
01197 std::stringstream errmsg;
01198 errmsg << "Problem attempting " << command << " XML-RPC call on host " << serverUrl_
01199 << "; possible causes are malformed FHiCL or nonexistent process at requested port";
01200 ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
01201 }
01202
01203 return xmlrpc_c::value_string(result);
01204 }
01205
01206 std::string xmlrpc_commander::send_command_(std::string command, fhicl::ParameterSet pset, uint64_t timestamp, uint64_t timeout)
01207 {
01208 if (serverUrl_ == "")
01209 {
01210 std::stringstream errmsg;
01211 errmsg << "Problem attempting " << command << " XML-RPC call: No server URL set!";
01212 ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
01213
01214 }
01215 xmlrpc_c::clientSimple myClient;
01216 xmlrpc_c::value result;
01217
01218 try
01219 {
01220 myClient.call(serverUrl_, "daq." + command, "sii", &result, pset.to_string().c_str(), timestamp, timeout);
01221 }
01222 catch (...)
01223 {
01224 std::stringstream errmsg;
01225 errmsg << "Problem attempting " << command << " XML-RPC call on host " << serverUrl_
01226 << "; possible causes are malformed FHiCL or nonexistent process at requested port";
01227 ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
01228 }
01229
01230 return xmlrpc_c::value_string(result);
01231 }
01232
01233 std::string artdaq::xmlrpc_commander::send_command_(std::string command, uint64_t a, uint64_t b)
01234 {
01235 if (serverUrl_ == "")
01236 {
01237 std::stringstream errmsg;
01238 errmsg << "Problem attempting " << command << " XML-RPC call: No server URL set!";
01239 ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
01240
01241 }
01242 xmlrpc_c::clientSimple myClient;
01243 xmlrpc_c::value result;
01244
01245 try
01246 {
01247 myClient.call(serverUrl_, "daq." + command, "ii", &result, a,b);
01248 }
01249 catch (...)
01250 {
01251 std::stringstream errmsg;
01252 errmsg << "Problem attempting " << command << " XML-RPC call on host " << serverUrl_
01253 << "; possible causes are malformed FHiCL or nonexistent process at requested port";
01254 ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
01255 }
01256
01257 return xmlrpc_c::value_string(result);
01258 }
01259
01260 std::string artdaq::xmlrpc_commander::send_command_(std::string command, art::RunID r, uint64_t a, uint64_t b)
01261 {
01262 if (serverUrl_ == "")
01263 {
01264 std::stringstream errmsg;
01265 errmsg << "Problem attempting " << command << " XML-RPC call: No server URL set!";
01266 ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
01267
01268 }
01269 xmlrpc_c::clientSimple myClient;
01270 xmlrpc_c::value result;
01271
01272 try
01273 {
01274 myClient.call(serverUrl_, "daq." + command, "iii", &result, r, a, b);
01275 }
01276 catch (...)
01277 {
01278 std::stringstream errmsg;
01279 errmsg << "Problem attempting " << command << " XML-RPC call on host " << serverUrl_
01280 << "; possible causes are malformed FHiCL or nonexistent process at requested port";
01281 ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
01282 }
01283
01284 return xmlrpc_c::value_string(result);
01285 }
01286
01287 std::string artdaq::xmlrpc_commander::send_command_(std::string command, uint64_t arg1)
01288 {
01289 if (serverUrl_ == "")
01290 {
01291 std::stringstream errmsg;
01292 errmsg << "Problem attempting " << command << " XML-RPC call: No server URL set!";
01293 ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
01294
01295 }
01296 xmlrpc_c::clientSimple myClient;
01297 xmlrpc_c::value result;
01298
01299 try
01300 {
01301 myClient.call(serverUrl_, "daq." + command, "i", &result, arg1);
01302 }
01303 catch (...)
01304 {
01305 std::stringstream errmsg;
01306 errmsg << "Problem attempting " << command << " XML-RPC call on host " << serverUrl_
01307 << "; possible causes are malformed FHiCL or nonexistent process at requested port";
01308 ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
01309 }
01310
01311 return xmlrpc_c::value_string(result);
01312 }
01313
01314 std::string artdaq::xmlrpc_commander::send_command_(std::string command, std::string arg1, std::string arg2)
01315 {
01316 if (serverUrl_ == "")
01317 {
01318 std::stringstream errmsg;
01319 errmsg << "Problem attempting " << command << " XML-RPC call: No server URL set!";
01320 ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
01321
01322 }
01323 xmlrpc_c::clientSimple myClient;
01324 xmlrpc_c::value result;
01325
01326 try
01327 {
01328 myClient.call(serverUrl_, "daq." + command, "ss", &result, arg1.c_str(), arg2.c_str());
01329 }
01330 catch (...)
01331 {
01332 std::stringstream errmsg;
01333 errmsg << "Problem attempting " << command << " XML-RPC call on host " << serverUrl_
01334 << "; possible causes are malformed FHiCL or nonexistent process at requested port";
01335 ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
01336 }
01337
01338 return xmlrpc_c::value_string(result);
01339 }
01340
01341 std::string artdaq::xmlrpc_commander::send_command_(std::string command, std::string arg1, std::string arg2, uint64_t arg3)
01342 {
01343 if (serverUrl_ == "")
01344 {
01345 std::stringstream errmsg;
01346 errmsg << "Problem attempting " << command << " XML-RPC call: No server URL set!";
01347 ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
01348
01349 }
01350 xmlrpc_c::clientSimple myClient;
01351 xmlrpc_c::value result;
01352
01353 try
01354 {
01355 myClient.call(serverUrl_, "daq." + command, "ssi", &result, arg1.c_str(), arg2.c_str(), arg3);
01356 }
01357 catch (...)
01358 {
01359 std::stringstream errmsg;
01360 errmsg << "Problem attempting " << command << " XML-RPC call on host " << serverUrl_
01361 << "; possible causes are malformed FHiCL or nonexistent process at requested port";
01362 ExceptionHandler(ExceptionHandlerRethrow::yes, errmsg.str());
01363 }
01364
01365 return xmlrpc_c::value_string(result);
01366 }
01367
01368 std::string xmlrpc_commander::send_register_monitor(std::string monitor_fhicl)
01369 {
01370 return send_command_("register_monitor", monitor_fhicl);
01371 }
01372 std::string xmlrpc_commander::send_unregister_monitor(std::string monitor_label)
01373 {
01374 return send_command_("unregister_monitor", monitor_label);
01375 }
01376 std::string artdaq::xmlrpc_commander::send_init(fhicl::ParameterSet ps, uint64_t a, uint64_t b)
01377 {
01378 return send_command_("init", ps, a, b);
01379 }
01380 std::string artdaq::xmlrpc_commander::send_soft_init(fhicl::ParameterSet ps, uint64_t a, uint64_t b)
01381 {
01382 return send_command_("soft_init", ps, a, b);
01383 }
01384 std::string xmlrpc_commander::send_reinit(fhicl::ParameterSet ps, uint64_t a, uint64_t b)
01385 {
01386 return send_command_("reinit", ps, a, b);
01387 }
01388 std::string xmlrpc_commander::send_start(art::RunID r, uint64_t a, uint64_t b)
01389 {
01390 return send_command_("start", r, a, b);
01391 }
01392 std::string xmlrpc_commander::send_pause(uint64_t a, uint64_t b)
01393 {
01394 return send_command_("pause", a, b);
01395 }
01396 std::string xmlrpc_commander::send_resume(uint64_t a, uint64_t b)
01397 {
01398 return send_command_("resume", a, b);
01399 }
01400 std::string xmlrpc_commander::send_stop(uint64_t a, uint64_t b)
01401 {
01402 return send_command_("stop", a, b);
01403 }
01404 std::string xmlrpc_commander::send_shutdown(uint64_t a)
01405 {
01406 return send_command_("shutdown", a);
01407 }
01408 std::string xmlrpc_commander::send_status()
01409 {
01410 return send_command_("status");
01411 }
01412 std::string xmlrpc_commander::send_report(std::string what)
01413 {
01414 return send_command_("report", what);
01415 }
01416 std::string xmlrpc_commander::send_legal_commands()
01417 {
01418 return send_command_("legal_commands");
01419 }
01420 std::string xmlrpc_commander::send_trace_get(std::string name)
01421 {
01422 return send_command_("trace_get", name);
01423 }
01424 std::string xmlrpc_commander::send_trace_set(std::string name, std::string which, uint64_t mask)
01425 {
01426 return send_command_("trace_set", name, which, mask);
01427 }
01428 std::string xmlrpc_commander::send_meta_command(std::string command, std::string arg)
01429 {
01430 return send_command_("meta_command", command, arg);
01431 }
01432 std::string xmlrpc_commander::send_rollover_subrun(uint64_t when)
01433 {
01434 return send_command_("rollover_subrun", when);
01435 }
01436 }
01437
01438 DEFINE_ARTDAQ_COMMANDER(artdaq::xmlrpc_commander)