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 {
00039 class env_wrap {
00040 public:
00041 env_wrap() { xmlrpc_env_init(&this->env_c); };
00042 ~env_wrap() { xmlrpc_env_clean(&this->env_c); };
00043 xmlrpc_env env_c;
00044 };
00045 }
00046 static xmlrpc_c::paramList
00047 pListFromXmlrpcArray(xmlrpc_value * const arrayP)
00048 {
00049 env_wrap env;
00050 XMLRPC_ASSERT_ARRAY_OK(arrayP);
00051 unsigned int const arraySize = xmlrpc_array_size(&env.env_c, arrayP);
00052 assert(!env.env_c.fault_occurred);
00053 xmlrpc_c::paramList paramList(arraySize);
00054 for (unsigned int i = 0; i < arraySize; ++i) {
00055 xmlrpc_value * arrayItemP;
00056 xmlrpc_array_read_item(&env.env_c, arrayP, i, &arrayItemP);
00057 assert(!env.env_c.fault_occurred);
00058 paramList.add(xmlrpc_c::value(arrayItemP));
00059 xmlrpc_DECREF(arrayItemP);
00060 }
00061 return paramList;
00062 }
00063 static xmlrpc_value *
00064 c_executeMethod(xmlrpc_env * const envP,
00065 xmlrpc_value * const paramArrayP,
00066 void * const methodPtr,
00067 void * const callInfoPtr)
00068 {
00069 xmlrpc_c::method * const methodP(static_cast<xmlrpc_c::method *>(methodPtr));
00070 xmlrpc_c::paramList const paramList(pListFromXmlrpcArray(paramArrayP));
00071 xmlrpc_c::callInfo * const callInfoP(static_cast<xmlrpc_c::callInfo *>(callInfoPtr));
00072 xmlrpc_value * retval;
00073 retval = NULL;
00074 try {
00075 xmlrpc_c::value result;
00076 try {
00077 xmlrpc_c::method2 * const method2P(dynamic_cast<xmlrpc_c::method2 *>(methodP));
00078 if (method2P)
00079 method2P->execute(paramList, callInfoP, &result);
00080 else
00081 methodP->execute(paramList, &result);
00082 }
00083 catch (xmlrpc_c::fault const& fault) {
00084 xmlrpc_env_set_fault(envP, fault.getCode(),
00085 fault.getDescription().c_str());
00086 }
00087 if (!envP->fault_occurred) {
00088 if (result.isInstantiated())
00089 retval = result.cValue();
00090 else
00091 girerr::throwf("Xmlrpc-c user's xmlrpc_c::method object's "
00092 "'execute method' failed to set the RPC result "
00093 "value.");
00094 }
00095 }
00096 catch (std::exception const& e) {
00097 xmlrpc_faultf(envP, "Unexpected error executing code for "
00098 "particular method, detected by Xmlrpc-c "
00099 "method registry code. Method did not "
00100 "fail; rather, it did not complete at all. %s",
00101 e.what());
00102 }
00103 catch (...) {
00104 xmlrpc_env_set_fault(envP, XMLRPC_INTERNAL_ERROR,
00105 "Unexpected error executing code for "
00106 "particular method, detected by Xmlrpc-c "
00107 "method registry code. Method did not "
00108 "fail; rather, it did not complete at all.");
00109 }
00110 return retval;
00111 }
00112
00113
00114
00115 namespace artdaq
00116 {
00123 std::string exception_msg(const std::runtime_error& er,
00124 const std::string& helpText = "execute request")
00125 {
00126 std::string msg("Exception when trying to ");
00127 msg.append(helpText);
00128 msg.append(": ");
00129 msg.append(er.what());
00130 if (msg[msg.size() - 1] == '\n') msg.erase(msg.size() - 1);
00131 return msg;
00132 }
00133
00140 std::string exception_msg(const art::Exception& er,
00141 const std::string& helpText)
00142 {
00143 std::string msg("Exception when trying to ");
00144 msg.append(helpText);
00145 msg.append(": ");
00146 msg.append(er.what());
00147 if (msg[msg.size() - 1] == '\n') msg.erase(msg.size() - 1);
00148 return msg;
00149 }
00150
00157 std::string exception_msg(const cet::exception& er,
00158 const std::string& helpText)
00159 {
00160 std::string msg("Exception when trying to ");
00161 msg.append(helpText);
00162 msg.append(": ");
00163 msg.append(er.what());
00164 if (msg[msg.size() - 1] == '\n') msg.erase(msg.size() - 1);
00165 return msg;
00166 }
00167
00174 std::string exception_msg(const std::string& erText,
00175 const std::string& helpText)
00176 {
00177 std::string msg("Exception when trying to ");
00178 msg.append(helpText);
00179 msg.append(": ");
00180 msg.append(erText);
00181 if (msg[msg.size() - 1] == '\n') msg.erase(msg.size() - 1);
00182 return msg;
00183 }
00184
00185
00203 class cmd_ : public xmlrpc_c::method
00204 {
00205 public:
00206
00207
00214 cmd_(xmlrpc_commander& c, const std::string& signature, const std::string& description) : _c(c)
00215 {
00216 _signature = signature;
00217 _help = description;
00218 }
00219
00225 void execute(const xmlrpc_c::paramList& paramList, xmlrpc_c::value* const retvalP) final;
00226
00227 protected:
00228
00229 xmlrpc_commander & _c;
00230
00236 virtual bool execute_(const xmlrpc_c::paramList&, xmlrpc_c::value* const retvalP) = 0;
00237
00247 template <typename T>
00248 T getParam(const xmlrpc_c::paramList& paramList, int index);
00249
00273 template <typename T>
00274 T getParam(const xmlrpc_c::paramList& paramList, int index, T default_value);
00275 };
00276
00277
00278
00279
00280 template <typename T>
00281 T cmd_::getParam(const xmlrpc_c::paramList&, int)
00282 {
00283 throw cet::exception("cmd_") << "Error in cmd_::getParam(): value type not supported" << std::endl;
00284 }
00285
00294 template <>
00295 uint64_t cmd_::getParam<uint64_t>(const xmlrpc_c::paramList& paramList, int index)
00296 {
00297 TLOG(TLVL_TRACE) << "Getting parameter " << index << " from list as uint64_t.";
00298 TLOG(TLVL_TRACE) << "Param value: " << paramList.getString(index);
00299 return boost::lexical_cast<uint64_t>(paramList.getString(index));
00300 }
00301
00310 template <>
00311 std::string cmd_::getParam<std::string>(const xmlrpc_c::paramList& paramList, int index)
00312 {
00313 TLOG(TLVL_TRACE) << "Getting parameter " << index << " from list as string.";
00314 TLOG(TLVL_TRACE) << "Param value: " << paramList.getString(index);
00315 return static_cast<std::string>(paramList.getString(index));
00316 }
00317
00326 template <>
00327 art::RunID cmd_::getParam<art::RunID>(const xmlrpc_c::paramList& paramList, int index)
00328 {
00329 TLOG(TLVL_TRACE) << "Getting parameter " << index << " from list as Run Number.";
00330 TLOG(TLVL_TRACE) << "Param value: " << paramList.getString(index);
00331 std::string run_number_string = paramList.getString(index);
00332 art::RunNumber_t run_number =
00333 boost::lexical_cast<art::RunNumber_t>(run_number_string);
00334 art::RunID run_id(run_number);
00335
00336 return run_id;
00337 }
00338
00347 template <>
00348 fhicl::ParameterSet cmd_::getParam<fhicl::ParameterSet>(const xmlrpc_c::paramList& paramList, int index)
00349 {
00350 TLOG(TLVL_TRACE) << "Getting parameter " << index << " from list as ParameterSet.";
00351 TLOG(TLVL_TRACE) << "Param value: " << paramList.getString(index);
00352 std::string configString = std::string(paramList.getString(index).c_str());
00353 TLOG(TLVL_DEBUG) << "Loading Parameter Set from string: " << configString << std::endl;
00354 fhicl::ParameterSet pset;
00355
00356 try
00357 {
00358 fhicl::make_ParameterSet(configString, pset);
00359 }
00360 catch (fhicl::exception e)
00361 {
00362 if (getenv("FHICL_FILE_PATH") == nullptr)
00363 {
00364 std::cerr << "INFO: environment variable FHICL_FILE_PATH was not set. Using \".\"\n";
00365 setenv("FHICL_FILE_PATH", ".", 0);
00366 }
00367 cet::filepath_lookup_after1 lookup_policy("FHICL_FILE_PATH");
00368 fhicl::make_ParameterSet(configString, lookup_policy, pset);
00369 }
00370
00371 TLOG(TLVL_INFO) << "Parameter Set Loaded." << std::endl;
00372 return pset;
00373 }
00374
00375 template <typename T>
00376 T cmd_::getParam(const xmlrpc_c::paramList& paramList, int index,
00377 T default_value)
00378 {
00379 T val = default_value;
00380
00381 try
00382 {
00383 val = getParam<T>(paramList, index);
00384 }
00385 catch (const cet::exception& exception)
00386 {
00387 throw exception;
00388 }
00389 catch (...) {}
00390
00391 return val;
00392 }
00393
00394 void cmd_::execute(const xmlrpc_c::paramList& paramList, xmlrpc_c::value* const retvalP)
00395 {
00396 std::unique_lock<std::timed_mutex> lk(_c.mutex_, std::chrono::milliseconds(250));
00397 if (lk.owns_lock())
00398 {
00399 try
00400 {
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411 if (execute_(paramList, retvalP))
00412 {
00413 if (!retvalP->isInstantiated())
00414 {
00415 *retvalP = xmlrpc_c::value_string("Success");
00416 }
00417 }
00418 else
00419 {
00420 std::string problemReport = _c._commandable.report("transition_status");
00421 *retvalP = xmlrpc_c::value_string(problemReport);
00422 }
00423 }
00424 catch (std::runtime_error& er)
00425 {
00426 std::string msg = exception_msg(er, _help);
00427 *retvalP = xmlrpc_c::value_string(msg);
00428 TLOG(TLVL_ERROR) << msg ;
00429 }
00430 catch (art::Exception& er)
00431 {
00432 std::string msg = exception_msg(er, _help);
00433 *retvalP = xmlrpc_c::value_string(msg);
00434 TLOG(TLVL_ERROR) << msg ;
00435 }
00436 catch (cet::exception& er)
00437 {
00438 std::string msg = exception_msg(er, _help);
00439 *retvalP = xmlrpc_c::value_string(msg);
00440 TLOG(TLVL_ERROR) << msg ;
00441 }
00442 catch (...)
00443 {
00444 std::string msg = exception_msg("Unknown exception", _help);
00445 *retvalP = xmlrpc_c::value_string(msg);
00446 TLOG(TLVL_ERROR) << msg ;
00447 }
00448 }
00449 else
00450 {
00451 *retvalP = xmlrpc_c::value_string("busy");
00452 }
00453 }
00454
00455
00457
00458
00459
00460
00461
00462
00463
00464 #define GENERATE_INIT_TRANSITION(NAME, CALL, DESCRIPTION) \
00465 \
00466 class NAME ## _: public cmd_ { \
00467 \
00468 public: \
00469 \
00472 explicit NAME ## _(xmlrpc_commander& c): \
00473 cmd_(c, "s:sii", DESCRIPTION) {} \
00474 \
00475 \
00476 static const uint64_t defaultTimeout = 45; \
00477 \
00478 static const uint64_t defaultTimestamp = std::numeric_limits<const uint64_t>::max(); \
00479 \
00480 private: \
00481 bool execute_(const xmlrpc_c::paramList& paramList, xmlrpc_c::value* const retvalP ) { \
00482 fhicl::ParameterSet ps; \
00483 try { \
00484 ps = getParam<fhicl::ParameterSet>(paramList, 0); \
00485 } catch (...) { \
00486 *retvalP = xmlrpc_c::value_string ("The "#NAME" message requires a single argument that is a string containing the initialization ParameterSet"); \
00487 return true; \
00488 } \
00489 \
00490 return _c._commandable.CALL(ps, \
00491 getParam<uint64_t>(paramList, 1, defaultTimeout), \
00492 getParam<uint64_t>(paramList, 2, defaultTimestamp) \
00493 ); \
00494 } \
00495 };
00496
00497 GENERATE_INIT_TRANSITION(init, initialize, "initialize the program")
00498
00499 GENERATE_INIT_TRANSITION(soft_init, soft_initialize, "initialize software components in the program")
00500
00501 GENERATE_INIT_TRANSITION(reinit, reinitialize, "re-initialize the program")
00502
00503 #undef GENERATE_INIT_TRANSITION
00504
00506
00510 class start_ : public cmd_
00511 {
00512 public:
00517 explicit start_(xmlrpc_commander& c) :
00518 cmd_(c, "s:iii", "start the run")
00519 {}
00520
00522 static const uint64_t defaultTimeout = 45;
00524 static const uint64_t defaultTimestamp = std::numeric_limits<const uint64_t>::max();
00525
00526 private:
00527
00528 bool execute_(xmlrpc_c::paramList const& paramList, xmlrpc_c::value* const retvalP) override
00529 {
00530 try
00531 {
00532 getParam<art::RunID>(paramList, 0);
00533 }
00534 catch (...)
00535 {
00536 *retvalP = xmlrpc_c::value_string("The start message requires the run number as an argument.");
00537 return true;
00538 }
00539
00540 return _c._commandable.start(getParam<art::RunID>(paramList, 0),
00541 getParam<uint64_t>(paramList, 1, defaultTimeout),
00542 getParam<uint64_t>(paramList, 2, defaultTimestamp)
00543 );
00544 }
00545 };
00546
00547
00549
00550
00551
00552
00553
00554
00555
00556 #define GENERATE_TIMEOUT_TIMESTAMP_TRANSITION(NAME, CALL, DESCRIPTION, TIMEOUT) \
00557 \
00558 class NAME ## _: public cmd_ { \
00559 \
00560 public: \
00561 \
00563 NAME ## _(xmlrpc_commander& c): \
00564 cmd_(c, "s:ii", DESCRIPTION) {} \
00565 \
00566 \
00567 static const uint64_t defaultTimeout = TIMEOUT ; \
00568 \
00569 static const uint64_t defaultTimestamp = std::numeric_limits<const uint64_t>::max(); \
00570 \
00571 private: \
00572 \
00573 bool execute_ (const xmlrpc_c::paramList& paramList , xmlrpc_c::value* const ) { \
00574 \
00575 return _c._commandable.CALL( getParam<uint64_t>(paramList, 0, defaultTimeout), \
00576 getParam<uint64_t>(paramList, 1, defaultTimestamp) \
00577 ); \
00578 } \
00579 };
00580
00581 GENERATE_TIMEOUT_TIMESTAMP_TRANSITION(pause, pause, "pause the program", 45)
00582
00583 GENERATE_TIMEOUT_TIMESTAMP_TRANSITION(resume, resume, "resume the program", 45)
00584
00585 GENERATE_TIMEOUT_TIMESTAMP_TRANSITION(stop, stop, "stop the program", 45)
00586
00587 #undef GENERATE_TIMEOUT_TIMESTAMP_TRANSITION
00588
00589
00593 class shutdown_ : public cmd_
00594 {
00595 public:
00600 shutdown_(xmlrpc_commander& c) :
00601 cmd_(c, "s:i", "shutdown the program")
00602 {}
00603
00605 static const uint64_t defaultTimeout = 45;
00606
00607 private:
00608
00609 bool execute_(const xmlrpc_c::paramList& paramList, xmlrpc_c::value* const)
00610 {
00611 auto ret = _c._commandable.shutdown(getParam<uint64_t>(paramList, 0, defaultTimeout));
00612
00613 #if 1
00614 if (_c.server) _c.server->terminate();
00615 #endif
00616
00617 return ret;
00618 }
00619 };
00620
00621
00625 class status_ : public cmd_
00626 {
00627 public:
00632 status_(xmlrpc_commander& c) :
00633 cmd_(c, "s:n", "report the current state")
00634 {}
00635
00636 private:
00637
00638 bool execute_(xmlrpc_c::paramList const&, xmlrpc_c::value* const retvalP)
00639 {
00640 *retvalP = xmlrpc_c::value_string(_c._commandable.status());
00641 return true;
00642 }
00643 };
00644
00645
00649 class report_ : public cmd_
00650 {
00651 public:
00656 report_(xmlrpc_commander& c) :
00657 cmd_(c, "s:s", "report statistics")
00658 {}
00659
00660 private:
00661 bool execute_(xmlrpc_c::paramList const& paramList, xmlrpc_c::value* const retvalP)
00662 {
00663 try
00664 {
00665 getParam<std::string>(paramList, 0);
00666 }
00667 catch (...)
00668 {
00669 *retvalP = xmlrpc_c::value_string("The report message requires a single argument that selects the type of statistics to be reported.");
00670 return true;
00671 }
00672
00673 *retvalP = xmlrpc_c::value_string(_c._commandable.report(getParam<std::string>(paramList, 0)));
00674 return true;
00675 }
00676 };
00677
00681 class legal_commands_ : public cmd_
00682 {
00683 public:
00688 legal_commands_(xmlrpc_commander& c) :
00689 cmd_(c, "s:n", "return the currently legal commands")
00690 {}
00691
00692 private:
00693 bool execute_(xmlrpc_c::paramList const&, xmlrpc_c::value* const retvalP)
00694 {
00695 std::vector<std::string> cmdList = _c._commandable.legal_commands();
00696 std::string resultString;
00697
00698 for (auto& cmd : cmdList)
00699 {
00700 resultString.append(cmd + " ");
00701 if (cmd == "shutdown")
00702 {
00703 resultString.append(" reset");
00704 }
00705 }
00706 *retvalP = xmlrpc_c::value_string(resultString);
00707
00708 return true;
00709 }
00710 };
00711
00715 class register_monitor_ : public cmd_
00716 {
00717 public:
00722 register_monitor_(xmlrpc_commander& c) :
00723 cmd_(c, "s:s", "Get notified of a new monitor")
00724 {}
00725
00726 private:
00727 bool execute_(xmlrpc_c::paramList const& paramList, xmlrpc_c::value* const retvalP)
00728 {
00729 try
00730 {
00731 getParam<fhicl::ParameterSet>(paramList, 0);
00732 }
00733 catch (...)
00734 {
00735 *retvalP = xmlrpc_c::value_string("The register_monitor command expects a string representing the FHiCL definition of a Transfer plugin");
00736 return true;
00737 }
00738
00739 *retvalP = xmlrpc_c::value_string(_c._commandable.register_monitor(getParam<fhicl::ParameterSet>(paramList, 0)));
00740 return true;
00741 }
00742 };
00743
00747 class unregister_monitor_ : public cmd_
00748 {
00749 public:
00754 unregister_monitor_(xmlrpc_commander& c) :
00755 cmd_(c, "s:s", "Remove a monitor")
00756 {}
00757
00758 private:
00759 bool execute_(xmlrpc_c::paramList const& paramList, xmlrpc_c::value* const retvalP)
00760 {
00761 try
00762 {
00763 getParam<std::string>(paramList, 0);
00764 }
00765 catch (...)
00766 {
00767 *retvalP = xmlrpc_c::value_string("The unregister_monitor command expects a string representing the label of the monitor to be removed");
00768 return true;
00769 }
00770
00771 *retvalP = xmlrpc_c::value_string(_c._commandable.unregister_monitor(getParam<std::string>(paramList, 0)));
00772 return true;
00773 }
00774 };
00775
00776
00780 class trace_set_ : public cmd_
00781 {
00782 public:
00787 trace_set_(xmlrpc_commander& c) :
00788 cmd_(c, "s:ssi", "Set TRACE mask")
00789 {}
00790
00791 private:
00792 bool execute_(xmlrpc_c::paramList const& paramList, xmlrpc_c::value* const retvalP)
00793 {
00794 try
00795 {
00796 getParam<std::string>(paramList, 0);
00797 getParam<std::string>(paramList, 1);
00798 getParam<uint64_t>(paramList, 2);
00799 }
00800 catch (...)
00801 {
00802 *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");
00803 return true;
00804 }
00805
00806 return _c._commandable.do_trace_set(getParam<std::string>(paramList, 0), getParam<std::string>(paramList, 1), getParam<uint64_t>(paramList, 2));
00807 }
00808 };
00809
00813 class trace_get_ : public cmd_
00814 {
00815 public:
00820 trace_get_(xmlrpc_commander& c) :
00821 cmd_(c, "s:s", "Get TRACE mask")
00822 {}
00823
00824 private:
00825 bool execute_(xmlrpc_c::paramList const& paramList, xmlrpc_c::value* const retvalP)
00826 {
00827 try
00828 {
00829 getParam<std::string>(paramList, 0);
00830 }
00831 catch (...)
00832 {
00833 *retvalP = xmlrpc_c::value_string("The trace_msgfacility_set command expects a name (ALL for all)");
00834 return true;
00835 }
00836
00837 *retvalP = xmlrpc_c::value_string(_c._commandable.do_trace_get(getParam<std::string>(paramList, 0)));
00838 return true;
00839 }
00840 };
00841
00845 class meta_command_ : public cmd_
00846 {
00847 public:
00852 meta_command_(xmlrpc_commander& c) :
00853 cmd_(c, "s:ss", "Run custom command")
00854 {}
00855
00856 private:
00857 bool execute_(xmlrpc_c::paramList const& paramList, xmlrpc_c::value* const retvalP)
00858 {
00859 try
00860 {
00861 getParam<std::string>(paramList, 0);
00862 getParam<std::string>(paramList, 1);
00863 }
00864 catch (...)
00865 {
00866 *retvalP = xmlrpc_c::value_string("The meta_command command expects a string command and a string argument");
00867 return true;
00868 }
00869
00870 return _c._commandable.do_meta_command(getParam<std::string>(paramList, 0), getParam<std::string>(paramList, 1));
00871 }
00872 };
00873
00877 class rollover_subrun_ : public cmd_
00878 {
00879 public:
00884 rollover_subrun_(xmlrpc_commander& c) :
00885 cmd_(c, "s:i", "create a new subrun")
00886 {}
00887
00889 static const uint64_t defaultSequenceID = 0xFFFFFFFFFFFFFFFF;
00890
00891 private:
00892
00893 bool execute_(const xmlrpc_c::paramList& paramList, xmlrpc_c::value* const)
00894 {
00895 auto ret = _c._commandable.do_rollover_subrun(getParam<uint64_t>(paramList, 0, defaultSequenceID));
00896 return ret;
00897 }
00898 };
00899
00900
00901
00902
00903
00904
00905 #if 0
00906 class shutdown_ : public xmlrpc_c::registry::shutdown
00907 {
00908 public:
00909 shutdown_(xmlrpc_c::serverAbyss *server) : _server(server) {}
00910
00911 virtual void doit(const std::string& paramString, void*) const
00912 {
00913 TLOG(TLVL_INFO) << "A shutdown command was sent "
00914 << "with parameter "
00915 << paramString << "\"" ;
00916 _server->terminate();
00917 }
00918 private:
00919 xmlrpc_c::serverAbyss *_server;
00920 };
00921 #endif
00922
00923
00924
00925 xmlrpc_commander::xmlrpc_commander(fhicl::ParameterSet ps, artdaq::Commandable& commandable)
00926 : CommanderInterface(ps, commandable)
00927 , port_(ps.get<int>("id", 0))
00928 , serverUrl_(ps.get<std::string>("server_url", ""))
00929 , server(nullptr)
00930 {
00931
00932 }
00933
00934 void xmlrpc_commander::run_server() try
00935 {
00936
00937 xmlrpc_c::registry registry;
00938 struct xmlrpc_method_info3 methodInfo;
00939 memset(&methodInfo, 0, sizeof(methodInfo));
00940
00941
00942
00943
00944 #define register_method(m) register_method2(m,0x400000)
00945
00946 xmlrpc_env env;
00947 xmlrpc_registry ***c_registryPPP;
00948 c_registryPPP = (xmlrpc_registry ***)(((char*)®istry) + sizeof(girmem::autoObject));
00949
00950 #define register_method2(m,ss) \
00951 xmlrpc_c::method * ptr_ ## m(dynamic_cast<xmlrpc_c::method *>(new m ## _(*this))); \
00952 methodInfo.methodName = "daq." #m; \
00953 methodInfo.methodFunction = &c_executeMethod; \
00954 methodInfo.serverInfo = ptr_ ## m; \
00955 methodInfo.stackSize = ss; \
00956 methodInfo.signatureString = ptr_ ## m ->signature().c_str(); \
00957 methodInfo.help = ptr_ ## m ->help().c_str(); \
00958 xmlrpc_env_init(&env); \
00959 xmlrpc_registry_add_method3(&env,**c_registryPPP,&methodInfo); \
00960 if(env.fault_occurred)throw(girerr::error(env.fault_string)); \
00961 xmlrpc_env_clean(&env)
00962
00963 register_method2(init, 0x200000);
00964 register_method(soft_init);
00965 register_method(reinit);
00966 register_method(start);
00967 register_method(status);
00968 register_method(report);
00969 register_method(stop);
00970 register_method(pause);
00971 register_method(resume);
00972 register_method(register_monitor);
00973 register_method(unregister_monitor);
00974 register_method(legal_commands);
00975 register_method(trace_set);
00976 register_method(trace_get);
00977 register_method(meta_command);
00978 register_method(rollover_subrun);
00979
00980 register_method(shutdown);
00981
00982
00983 xmlrpc_c::methodPtr const ptr_reset(new shutdown_(*this));
00984 registry.addMethod("daq.reset", ptr_reset);
00985
00986 #undef register_method
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003 XMLRPC_SOCKET socket_file_descriptor = socket(PF_INET, SOCK_STREAM, 0);
01004
01005 if (socket_file_descriptor < 0)
01006 {
01007 throw cet::exception("xmlrpc_commander::run") <<
01008 "Problem with the socket() call; C-style errno == " <<
01009 errno << " (" << strerror(errno) << ")";
01010 }
01011
01012 int enable = 1;
01013 int retval = setsockopt(socket_file_descriptor,
01014 SOL_SOCKET, SO_REUSEADDR,
01015 &enable, sizeof(int));
01016
01017 if (retval < 0)
01018 {
01019 throw cet::exception("xmlrpc_commander::run") <<
01020 "Problem with the call to setsockopt(); C-style errno == " <<
01021 errno << " (" << strerror(errno) << ")";
01022 }
01023
01024 struct sockaddr_in sockAddr;
01025
01026 sockAddr.sin_family = AF_INET;
01027 sockAddr.sin_port = htons(port_);
01028 sockAddr.sin_addr.s_addr = 0;
01029
01030 retval = bind(socket_file_descriptor,
01031 reinterpret_cast<struct sockaddr*>(&sockAddr),
01032 sizeof(sockAddr));
01033
01034 if (retval != 0)
01035 {
01036 close(socket_file_descriptor);
01037 throw cet::exception("xmlrpc_commander::run") <<
01038 "Problem with the bind() call; C-style errno == " <<
01039 errno << " (" << strerror(errno) << ")";
01040 }
01041
01042 server.reset(new xmlrpc_c::serverAbyss(xmlrpc_c::serverAbyss::constrOpt().registryP(®istry).socketFd(socket_file_descriptor)));
01043
01044 #if 0
01045 xmlrpc_c::serverAbyss::shutdown shutdown_obj(&server);
01046 registry.setShutdown(&shutdown_obj);
01047 #endif
01048
01049 TLOG(TLVL_DEBUG) << "running server" ;
01050
01051
01052
01053
01054
01055
01056
01057 try
01058 {
01059 server->run();
01060 }
01061 catch (...)
01062 {
01063 TLOG(TLVL_WARNING) << "server threw an exception; closing the socket and rethrowing" ;
01064 close(socket_file_descriptor);
01065 throw;
01066 }
01067
01068 close(socket_file_descriptor);
01069 TLOG(TLVL_DEBUG) << "server terminated" ;
01070 }
01071 catch (...)
01072 {
01073 throw;
01074 }
01075
01076
01077 std::string xmlrpc_commander::send_register_monitor(std::string monitor_fhicl)
01078 {
01079 if (serverUrl_ == "")
01080 {
01081 std::stringstream errmsg;
01082 errmsg << "Problem attempting XML-RPC call: No server URL set!";
01083 ExceptionHandler(ExceptionHandlerRethrow::yes,
01084 errmsg.str());
01085
01086 }
01087 xmlrpc_c::clientSimple myClient;
01088 xmlrpc_c::value result;
01089
01090 try
01091 {
01092 myClient.call(serverUrl_, "daq.register_monitor", "s", &result, monitor_fhicl.c_str());
01093 }
01094 catch (...)
01095 {
01096 std::stringstream errmsg;
01097 errmsg << "Problem attempting XML-RPC call on host " << serverUrl_
01098 << "; possible causes are malformed FHiCL or nonexistent process at requested port";
01099 ExceptionHandler(ExceptionHandlerRethrow::yes,
01100 errmsg.str());
01101 }
01102
01103 return xmlrpc_c::value_string(result);
01104 }
01105
01106 std::string xmlrpc_commander::send_unregister_monitor(std::string monitor_label)
01107 {
01108 if (serverUrl_ == "")
01109 {
01110 std::stringstream errmsg;
01111 errmsg << "Problem attempting XML-RPC call: No server URL set!";
01112 ExceptionHandler(ExceptionHandlerRethrow::yes,
01113 errmsg.str());
01114
01115 }
01116
01117 xmlrpc_c::clientSimple myClient;
01118 xmlrpc_c::value result;
01119
01120 try
01121 {
01122 myClient.call(serverUrl_, "daq.unregister_monitor", "s", &result, monitor_label.c_str());
01123 }
01124 catch (...)
01125 {
01126 std::stringstream errmsg;
01127 errmsg << "Problem attempting to unregister monitor via XML-RPC call on host " << serverUrl_
01128 << "; possible causes are that the monitor label \""
01129 << monitor_label
01130 << "\" is unrecognized by contacted process or process at requested port doesn't exist";
01131 ExceptionHandler(ExceptionHandlerRethrow::no, errmsg.str());
01132 }
01133
01134 return xmlrpc_c::value_string(result);
01135
01136 }
01137 }
01138
01139 DEFINE_ARTDAQ_COMMANDER(artdaq::xmlrpc_commander)