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 "xmlrpc_commander"
00022 #include "tracemf.h"
00023
00024 #include "artdaq-core/Utilities/ExceptionHandler.hh"
00025 #include <sys/socket.h>
00026 #include <netinet/in.h>
00027 #include <errno.h>
00028 #include <cstring>
00029 #include <exception>
00030
00031 #include "canvas/Persistency/Provenance/RunID.h"
00032 #include "fhiclcpp/make_ParameterSet.h"
00033
00034 #include "artdaq/ExternalComms/xmlrpc_commander.hh"
00035 #include "artdaq/DAQdata/Globals.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
00903
00904
00905
00906
00907
00908 #if 0
00909 class shutdown_ : public xmlrpc_c::registry::shutdown
00910 {
00911 public:
00912 shutdown_(xmlrpc_c::serverAbyss *server) : _server(server) {}
00913
00914 virtual void doit(const std::string& paramString, void*) const
00915 {
00916 TLOG(TLVL_INFO) << "A shutdown command was sent "
00917 << "with parameter "
00918 << paramString << "\"" ;
00919 _server->terminate();
00920 }
00921 private:
00922 xmlrpc_c::serverAbyss *_server;
00923 };
00924 #endif
00925
00926
00927
00928 xmlrpc_commander::xmlrpc_commander(fhicl::ParameterSet ps, artdaq::Commandable& commandable)
00929 : CommanderInterface(ps, commandable)
00930 , port_(ps.get<int>("id", 0))
00931 , serverUrl_(ps.get<std::string>("server_url", ""))
00932 , server(nullptr)
00933 {
00934
00935 }
00936
00937 void xmlrpc_commander::run_server() try
00938 {
00939
00940 xmlrpc_c::registry registry;
00941 struct xmlrpc_method_info3 methodInfo;
00942 memset(&methodInfo, 0, sizeof(methodInfo));
00943
00944
00945
00946
00947 #define register_method(m) register_method2(m,0x400000)
00948
00949 xmlrpc_env env;
00950 xmlrpc_registry ***c_registryPPP;
00951 c_registryPPP = (xmlrpc_registry ***)(((char*)®istry) + sizeof(girmem::autoObject));
00952
00953 #define register_method2(m,ss) \
00954 xmlrpc_c::method * ptr_ ## m(dynamic_cast<xmlrpc_c::method *>(new m ## _(*this))); \
00955 methodInfo.methodName = "daq." #m; \
00956 methodInfo.methodFunction = &c_executeMethod; \
00957 methodInfo.serverInfo = ptr_ ## m; \
00958 methodInfo.stackSize = ss; \
00959 methodInfo.signatureString = ptr_ ## m ->signature().c_str(); \
00960 methodInfo.help = ptr_ ## m ->help().c_str(); \
00961 xmlrpc_env_init(&env); \
00962 xmlrpc_registry_add_method3(&env,**c_registryPPP,&methodInfo); \
00963 if(env.fault_occurred)throw(girerr::error(env.fault_string)); \
00964 xmlrpc_env_clean(&env)
00965
00966 register_method2(init, 0x200000);
00967 register_method(soft_init);
00968 register_method(reinit);
00969 register_method(start);
00970 register_method(status);
00971 register_method(report);
00972 register_method(stop);
00973 register_method(pause);
00974 register_method(resume);
00975 register_method(register_monitor);
00976 register_method(unregister_monitor);
00977 register_method(legal_commands);
00978 register_method(trace_set);
00979 register_method(trace_get);
00980 register_method(meta_command);
00981 register_method(rollover_subrun);
00982
00983 register_method(shutdown);
00984
00985
00986 xmlrpc_c::methodPtr const ptr_reset(new shutdown_(*this));
00987 registry.addMethod("daq.reset", ptr_reset);
00988
00989 #undef register_method
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006 XMLRPC_SOCKET socket_file_descriptor = socket(PF_INET, SOCK_STREAM, 0);
01007
01008 if (socket_file_descriptor < 0)
01009 {
01010 throw cet::exception("xmlrpc_commander::run") <<
01011 "Problem with the socket() call; C-style errno == " <<
01012 errno << " (" << strerror(errno) << ")";
01013 }
01014
01015 int enable = 1;
01016 int retval = setsockopt(socket_file_descriptor,
01017 SOL_SOCKET, SO_REUSEADDR,
01018 &enable, sizeof(int));
01019
01020 if (retval < 0)
01021 {
01022 throw cet::exception("xmlrpc_commander::run") <<
01023 "Problem with the call to setsockopt(); C-style errno == " <<
01024 errno << " (" << strerror(errno) << ")";
01025 }
01026
01027 struct sockaddr_in sockAddr;
01028
01029 sockAddr.sin_family = AF_INET;
01030 sockAddr.sin_port = htons(port_);
01031 sockAddr.sin_addr.s_addr = 0;
01032
01033 retval = bind(socket_file_descriptor,
01034 reinterpret_cast<struct sockaddr*>(&sockAddr),
01035 sizeof(sockAddr));
01036
01037 if (retval != 0)
01038 {
01039 close(socket_file_descriptor);
01040 throw cet::exception("xmlrpc_commander::run") <<
01041 "Problem with the bind() call; C-style errno == " <<
01042 errno << " (" << strerror(errno) << ")";
01043 }
01044
01045 server.reset(new xmlrpc_c::serverAbyss(xmlrpc_c::serverAbyss::constrOpt().registryP(®istry).socketFd(socket_file_descriptor)));
01046
01047 #if 0
01048 xmlrpc_c::serverAbyss::shutdown shutdown_obj(&server);
01049 registry.setShutdown(&shutdown_obj);
01050 #endif
01051
01052 TLOG(TLVL_DEBUG) << "running server" ;
01053
01054
01055
01056
01057
01058
01059
01060 try
01061 {
01062 server->run();
01063 }
01064 catch (...)
01065 {
01066 TLOG(TLVL_WARNING) << "server threw an exception; closing the socket and rethrowing" ;
01067 close(socket_file_descriptor);
01068 throw;
01069 }
01070
01071 close(socket_file_descriptor);
01072 TLOG(TLVL_DEBUG) << "server terminated" ;
01073 }
01074 catch (...)
01075 {
01076 throw;
01077 }
01078
01079
01080 std::string xmlrpc_commander::send_register_monitor(std::string monitor_fhicl)
01081 {
01082 if (serverUrl_ == "")
01083 {
01084 std::stringstream errmsg;
01085 errmsg << "Problem attempting XML-RPC call: No server URL set!";
01086 ExceptionHandler(ExceptionHandlerRethrow::yes,
01087 errmsg.str());
01088
01089 }
01090 xmlrpc_c::clientSimple myClient;
01091 xmlrpc_c::value result;
01092
01093 try
01094 {
01095 myClient.call(serverUrl_, "daq.register_monitor", "s", &result, monitor_fhicl.c_str());
01096 }
01097 catch (...)
01098 {
01099 std::stringstream errmsg;
01100 errmsg << "Problem attempting XML-RPC call on host " << serverUrl_
01101 << "; possible causes are malformed FHiCL or nonexistent process at requested port";
01102 ExceptionHandler(ExceptionHandlerRethrow::yes,
01103 errmsg.str());
01104 }
01105
01106 return xmlrpc_c::value_string(result);
01107 }
01108
01109 std::string xmlrpc_commander::send_unregister_monitor(std::string monitor_label)
01110 {
01111 if (serverUrl_ == "")
01112 {
01113 std::stringstream errmsg;
01114 errmsg << "Problem attempting XML-RPC call: No server URL set!";
01115 ExceptionHandler(ExceptionHandlerRethrow::yes,
01116 errmsg.str());
01117
01118 }
01119
01120 xmlrpc_c::clientSimple myClient;
01121 xmlrpc_c::value result;
01122
01123 try
01124 {
01125 myClient.call(serverUrl_, "daq.unregister_monitor", "s", &result, monitor_label.c_str());
01126 }
01127 catch (...)
01128 {
01129 std::stringstream errmsg;
01130 errmsg << "Problem attempting to unregister monitor via XML-RPC call on host " << serverUrl_
01131 << "; possible causes are that the monitor label \""
01132 << monitor_label
01133 << "\" is unrecognized by contacted process or process at requested port doesn't exist";
01134 ExceptionHandler(ExceptionHandlerRethrow::no, errmsg.str());
01135 }
01136
01137 return xmlrpc_c::value_string(result);
01138
01139 }
01140 }
01141
01142 DEFINE_ARTDAQ_COMMANDER(artdaq::xmlrpc_commander)