00001
00002
00003
00004
00005
00006 #pragma GCC diagnostic push
00007 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
00008 #include <xmlrpc-c/base.hpp>
00009 #include <xmlrpc-c/registry.hpp>
00010 #include <xmlrpc-c/server_abyss.hpp>
00011 #include <xmlrpc-c/girerr.hpp>
00012 #include <xmlrpc-c/client_simple.hpp>
00013 #pragma GCC diagnostic pop
00014 #include <stdexcept>
00015 #include <iostream>
00016 #include <limits>
00017 #include <memory>
00018 #include <cstdint>
00019 #define TRACE_NAME "xmlrpc_commander"
00020 #include "tracemf.h"
00021
00022 #include "artdaq-core/Utilities/ExceptionHandler.hh"
00023 #include <sys/socket.h>
00024 #include <netinet/in.h>
00025 #include <errno.h>
00026 #include <cstring>
00027 #include <exception>
00028
00029 #include "canvas/Persistency/Provenance/RunID.h"
00030 #include "fhiclcpp/make_ParameterSet.h"
00031
00032 #include "artdaq/ExternalComms/xmlrpc_commander.hh"
00033 #include "artdaq/DAQdata/Globals.hh"
00034
00035
00036 namespace {
00037 class env_wrap {
00038 public:
00039 env_wrap() { xmlrpc_env_init(&this->env_c); };
00040 ~env_wrap() { xmlrpc_env_clean(&this->env_c); };
00041 xmlrpc_env env_c;
00042 };
00043 }
00044 static xmlrpc_c::paramList
00045 pListFromXmlrpcArray(xmlrpc_value * const arrayP)
00046 {
00047 env_wrap env;
00048 XMLRPC_ASSERT_ARRAY_OK(arrayP);
00049 unsigned int const arraySize = xmlrpc_array_size(&env.env_c, arrayP);
00050 assert(!env.env_c.fault_occurred);
00051 xmlrpc_c::paramList paramList(arraySize);
00052 for (unsigned int i = 0; i < arraySize; ++i) {
00053 xmlrpc_value * arrayItemP;
00054 xmlrpc_array_read_item(&env.env_c, arrayP, i, &arrayItemP);
00055 assert(!env.env_c.fault_occurred);
00056 paramList.add(xmlrpc_c::value(arrayItemP));
00057 xmlrpc_DECREF(arrayItemP);
00058 }
00059 return paramList;
00060 }
00061 static xmlrpc_value *
00062 c_executeMethod(xmlrpc_env * const envP,
00063 xmlrpc_value * const paramArrayP,
00064 void * const methodPtr,
00065 void * const callInfoPtr)
00066 {
00067 xmlrpc_c::method * const methodP(static_cast<xmlrpc_c::method *>(methodPtr));
00068 xmlrpc_c::paramList const paramList(pListFromXmlrpcArray(paramArrayP));
00069 xmlrpc_c::callInfo * const callInfoP(static_cast<xmlrpc_c::callInfo *>(callInfoPtr));
00070 xmlrpc_value * retval;
00071 retval = NULL;
00072 try {
00073 xmlrpc_c::value result;
00074 try {
00075 xmlrpc_c::method2 * const method2P(dynamic_cast<xmlrpc_c::method2 *>(methodP));
00076 if (method2P)
00077 method2P->execute(paramList, callInfoP, &result);
00078 else
00079 methodP->execute(paramList, &result);
00080 }
00081 catch (xmlrpc_c::fault const& fault) {
00082 xmlrpc_env_set_fault(envP, fault.getCode(),
00083 fault.getDescription().c_str());
00084 }
00085 if (!envP->fault_occurred) {
00086 if (result.isInstantiated())
00087 retval = result.cValue();
00088 else
00089 girerr::throwf("Xmlrpc-c user's xmlrpc_c::method object's "
00090 "'execute method' failed to set the RPC result "
00091 "value.");
00092 }
00093 }
00094 catch (std::exception const& e) {
00095 xmlrpc_faultf(envP, "Unexpected error executing code for "
00096 "particular method, detected by Xmlrpc-c "
00097 "method registry code. Method did not "
00098 "fail; rather, it did not complete at all. %s",
00099 e.what());
00100 }
00101 catch (...) {
00102 xmlrpc_env_set_fault(envP, XMLRPC_INTERNAL_ERROR,
00103 "Unexpected error executing code for "
00104 "particular method, detected by Xmlrpc-c "
00105 "method registry code. Method did not "
00106 "fail; rather, it did not complete at all.");
00107 }
00108 return retval;
00109 }
00110
00111
00112
00113 namespace artdaq
00114 {
00121 std::string exception_msg(const std::runtime_error& er,
00122 const std::string& helpText = "execute request")
00123 {
00124 std::string msg("Exception when trying to ");
00125 msg.append(helpText);
00126 msg.append(": ");
00127 msg.append(er.what());
00128 if (msg[msg.size() - 1] == '\n') msg.erase(msg.size() - 1);
00129 return msg;
00130 }
00131
00138 std::string exception_msg(const art::Exception& er,
00139 const std::string& helpText)
00140 {
00141 std::string msg("Exception when trying to ");
00142 msg.append(helpText);
00143 msg.append(": ");
00144 msg.append(er.what());
00145 if (msg[msg.size() - 1] == '\n') msg.erase(msg.size() - 1);
00146 return msg;
00147 }
00148
00155 std::string exception_msg(const cet::exception& er,
00156 const std::string& helpText)
00157 {
00158 std::string msg("Exception when trying to ");
00159 msg.append(helpText);
00160 msg.append(": ");
00161 msg.append(er.what());
00162 if (msg[msg.size() - 1] == '\n') msg.erase(msg.size() - 1);
00163 return msg;
00164 }
00165
00172 std::string exception_msg(const std::string& erText,
00173 const std::string& helpText)
00174 {
00175 std::string msg("Exception when trying to ");
00176 msg.append(helpText);
00177 msg.append(": ");
00178 msg.append(erText);
00179 if (msg[msg.size() - 1] == '\n') msg.erase(msg.size() - 1);
00180 return msg;
00181 }
00182
00183
00201 class cmd_ : public xmlrpc_c::method
00202 {
00203 public:
00204
00205
00212 cmd_(xmlrpc_commander& c, const std::string& signature, const std::string& description) : _c(c)
00213 {
00214 _signature = signature;
00215 _help = description;
00216 }
00217
00223 void execute(const xmlrpc_c::paramList& paramList, xmlrpc_c::value* const retvalP) final;
00224
00225 protected:
00226
00227 xmlrpc_commander & _c;
00228
00234 virtual bool execute_(const xmlrpc_c::paramList&, xmlrpc_c::value* const retvalP) = 0;
00235
00245 template <typename T>
00246 T getParam(const xmlrpc_c::paramList& paramList, int index);
00247
00271 template <typename T>
00272 T getParam(const xmlrpc_c::paramList& paramList, int index, T default_value);
00273 };
00274
00275
00276
00277
00278 template <typename T>
00279 T cmd_::getParam(const xmlrpc_c::paramList&, int)
00280 {
00281 throw cet::exception("cmd_") << "Error in cmd_::getParam(): value type not supported" << std::endl;
00282 }
00283
00292 template <>
00293 uint64_t cmd_::getParam<uint64_t>(const xmlrpc_c::paramList& paramList, int index)
00294 {
00295 return boost::lexical_cast<uint64_t>(paramList.getInt(index));
00296 }
00297
00306 template <>
00307 std::string cmd_::getParam<std::string>(const xmlrpc_c::paramList& paramList, int index)
00308 {
00309 return static_cast<std::string>(paramList.getString(index));
00310 }
00311
00320 template <>
00321 art::RunID cmd_::getParam<art::RunID>(const xmlrpc_c::paramList& paramList, int index)
00322 {
00323 std::string run_number_string = paramList.getString(index);
00324 art::RunNumber_t run_number =
00325 boost::lexical_cast<art::RunNumber_t>(run_number_string);
00326 art::RunID run_id(run_number);
00327
00328 return run_id;
00329 }
00330
00339 template <>
00340 fhicl::ParameterSet cmd_::getParam<fhicl::ParameterSet>(const xmlrpc_c::paramList& paramList, int index)
00341 {
00342 std::string configString = std::string(paramList.getString(index).c_str());
00343 TLOG(TLVL_DEBUG) << "Loading Parameter Set from string: " << configString << std::endl;
00344 fhicl::ParameterSet pset;
00345
00346 try
00347 {
00348 fhicl::make_ParameterSet(configString, pset);
00349 }
00350 catch (fhicl::exception e)
00351 {
00352 if (getenv("FHICL_FILE_PATH") == nullptr)
00353 {
00354 std::cerr << "INFO: environment variable FHICL_FILE_PATH was not set. Using \".\"\n";
00355 setenv("FHICL_FILE_PATH", ".", 0);
00356 }
00357 cet::filepath_lookup_after1 lookup_policy("FHICL_FILE_PATH");
00358 fhicl::make_ParameterSet(configString, lookup_policy, pset);
00359 }
00360
00361 TLOG(TLVL_INFO) << "Parameter Set Loaded." << std::endl;
00362 return pset;
00363 }
00364
00365 template <typename T>
00366 T cmd_::getParam(const xmlrpc_c::paramList& paramList, int index,
00367 T default_value)
00368 {
00369 T val = default_value;
00370
00371 try
00372 {
00373 val = getParam<T>(paramList, index);
00374 }
00375 catch (const cet::exception& exception)
00376 {
00377 throw exception;
00378 }
00379 catch (...) {}
00380
00381 return val;
00382 }
00383
00384 void cmd_::execute(const xmlrpc_c::paramList& paramList, xmlrpc_c::value* const retvalP)
00385 {
00386 std::unique_lock<std::mutex> lk(_c.mutex_, std::try_to_lock);
00387 if (lk.owns_lock())
00388 {
00389 try
00390 {
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401 if (execute_(paramList, retvalP))
00402 {
00403 if (!retvalP->isInstantiated())
00404 {
00405 *retvalP = xmlrpc_c::value_string("Success");
00406 }
00407 }
00408 else
00409 {
00410 std::string problemReport = _c._commandable.report("transition_status");
00411 *retvalP = xmlrpc_c::value_string(problemReport);
00412 }
00413 }
00414 catch (std::runtime_error& er)
00415 {
00416 std::string msg = exception_msg(er, _help);
00417 *retvalP = xmlrpc_c::value_string(msg);
00418 TLOG(TLVL_ERROR) << msg << TLOG_ENDL;
00419 }
00420 catch (art::Exception& er)
00421 {
00422 std::string msg = exception_msg(er, _help);
00423 *retvalP = xmlrpc_c::value_string(msg);
00424 TLOG(TLVL_ERROR) << msg << TLOG_ENDL;
00425 }
00426 catch (cet::exception& er)
00427 {
00428 std::string msg = exception_msg(er, _help);
00429 *retvalP = xmlrpc_c::value_string(msg);
00430 TLOG(TLVL_ERROR) << msg << TLOG_ENDL;
00431 }
00432 catch (...)
00433 {
00434 std::string msg = exception_msg("Unknown exception", _help);
00435 *retvalP = xmlrpc_c::value_string(msg);
00436 TLOG(TLVL_ERROR) << msg << TLOG_ENDL;
00437 }
00438 }
00439 else
00440 {
00441 *retvalP = xmlrpc_c::value_string("busy");
00442 }
00443 }
00444
00445
00447
00448
00449
00450
00451
00452
00453
00454 #define GENERATE_INIT_TRANSITION(NAME, CALL, DESCRIPTION) \
00455 \
00456 class NAME ## _: public cmd_ { \
00457 \
00458 public: \
00459 \
00462 explicit NAME ## _(xmlrpc_commander& c): \
00463 cmd_(c, "s:sii", DESCRIPTION) {} \
00464 \
00465 \
00466 static const uint64_t defaultTimeout = 45; \
00467 \
00468 static const uint64_t defaultTimestamp = std::numeric_limits<const uint64_t>::max(); \
00469 \
00470 private: \
00471 bool execute_(const xmlrpc_c::paramList& paramList, xmlrpc_c::value* const retvalP ) { \
00472 fhicl::ParameterSet ps; \
00473 try { \
00474 ps = getParam<fhicl::ParameterSet>(paramList, 0); \
00475 } catch (...) { \
00476 *retvalP = xmlrpc_c::value_string ("The "#NAME" message requires a single argument that is a string containing the initialization ParameterSet"); \
00477 return true; \
00478 } \
00479 \
00480 return _c._commandable.CALL(ps, \
00481 getParam<uint64_t>(paramList, 1, defaultTimeout), \
00482 getParam<uint64_t>(paramList, 2, defaultTimestamp) \
00483 ); \
00484 } \
00485 };
00486
00487 GENERATE_INIT_TRANSITION(init, initialize, "initialize the program")
00488
00489 GENERATE_INIT_TRANSITION(soft_init, soft_initialize, "initialize software components in the program")
00490
00491 GENERATE_INIT_TRANSITION(reinit, reinitialize, "re-initialize the program")
00492
00493 #undef GENERATE_INIT_TRANSITION
00494
00496
00500 class start_ : public cmd_
00501 {
00502 public:
00507 explicit start_(xmlrpc_commander& c) :
00508 cmd_(c, "s:iii", "start the run")
00509 {}
00510
00512 static const uint64_t defaultTimeout = 45;
00514 static const uint64_t defaultTimestamp = std::numeric_limits<const uint64_t>::max();
00515
00516 private:
00517
00518 bool execute_(xmlrpc_c::paramList const& paramList, xmlrpc_c::value* const retvalP) override
00519 {
00520 try
00521 {
00522 getParam<art::RunID>(paramList, 0);
00523 }
00524 catch (...)
00525 {
00526 *retvalP = xmlrpc_c::value_string("The start message requires the run number as an argument.");
00527 return true;
00528 }
00529
00530 return _c._commandable.start(getParam<art::RunID>(paramList, 0),
00531 getParam<uint64_t>(paramList, 1, defaultTimeout),
00532 getParam<uint64_t>(paramList, 2, defaultTimestamp)
00533 );
00534 }
00535 };
00536
00537
00539
00540
00541
00542
00543
00544
00545
00546 #define GENERATE_TIMEOUT_TIMESTAMP_TRANSITION(NAME, CALL, DESCRIPTION, TIMEOUT) \
00547 \
00548 class NAME ## _: public cmd_ { \
00549 \
00550 public: \
00551 \
00553 NAME ## _(xmlrpc_commander& c): \
00554 cmd_(c, "s:ii", DESCRIPTION) {} \
00555 \
00556 \
00557 static const uint64_t defaultTimeout = TIMEOUT ; \
00558 \
00559 static const uint64_t defaultTimestamp = std::numeric_limits<const uint64_t>::max(); \
00560 \
00561 private: \
00562 \
00563 bool execute_ (const xmlrpc_c::paramList& paramList , xmlrpc_c::value* const ) { \
00564 \
00565 return _c._commandable.CALL( getParam<uint64_t>(paramList, 0, defaultTimeout), \
00566 getParam<uint64_t>(paramList, 1, defaultTimestamp) \
00567 ); \
00568 } \
00569 };
00570
00571 GENERATE_TIMEOUT_TIMESTAMP_TRANSITION(pause, pause, "pause the program", 45)
00572
00573 GENERATE_TIMEOUT_TIMESTAMP_TRANSITION(resume, resume, "resume the program", 45)
00574
00575 GENERATE_TIMEOUT_TIMESTAMP_TRANSITION(stop, stop, "stop the program", 45)
00576
00577 #undef GENERATE_TIMEOUT_TIMESTAMP_TRANSITION
00578
00579
00583 class shutdown_ : public cmd_
00584 {
00585 public:
00590 shutdown_(xmlrpc_commander& c) :
00591 cmd_(c, "s:i", "shutdown the program")
00592 {}
00593
00595 static const uint64_t defaultTimeout = 45;
00596
00597 private:
00598
00599 bool execute_(const xmlrpc_c::paramList& paramList, xmlrpc_c::value* const)
00600 {
00601 auto ret = _c._commandable.shutdown(getParam<uint64_t>(paramList, 0, defaultTimeout));
00602
00603 #if 1
00604 if (_c.server) _c.server->terminate();
00605 #endif
00606
00607 return ret;
00608 }
00609 };
00610
00611
00615 class status_ : public cmd_
00616 {
00617 public:
00622 status_(xmlrpc_commander& c) :
00623 cmd_(c, "s:n", "report the current state")
00624 {}
00625
00626 private:
00627
00628 bool execute_(xmlrpc_c::paramList const&, xmlrpc_c::value* const retvalP)
00629 {
00630 *retvalP = xmlrpc_c::value_string(_c._commandable.status());
00631 return true;
00632 }
00633 };
00634
00635
00639 class report_ : public cmd_
00640 {
00641 public:
00646 report_(xmlrpc_commander& c) :
00647 cmd_(c, "s:s", "report statistics")
00648 {}
00649
00650 private:
00651 bool execute_(xmlrpc_c::paramList const& paramList, xmlrpc_c::value* const retvalP)
00652 {
00653 try
00654 {
00655 getParam<std::string>(paramList, 0);
00656 }
00657 catch (...)
00658 {
00659 *retvalP = xmlrpc_c::value_string("The report message requires a single argument that selects the type of statistics to be reported.");
00660 return true;
00661 }
00662
00663 *retvalP = xmlrpc_c::value_string(_c._commandable.report(getParam<std::string>(paramList, 0)));
00664 return true;
00665 }
00666 };
00667
00671 class legal_commands_ : public cmd_
00672 {
00673 public:
00678 legal_commands_(xmlrpc_commander& c) :
00679 cmd_(c, "s:n", "return the currently legal commands")
00680 {}
00681
00682 private:
00683 bool execute_(xmlrpc_c::paramList const&, xmlrpc_c::value* const retvalP)
00684 {
00685 std::vector<std::string> cmdList = _c._commandable.legal_commands();
00686 std::string resultString;
00687
00688 for (auto& cmd : cmdList)
00689 {
00690 resultString.append(cmd + " ");
00691 if (cmd == "shutdown")
00692 {
00693 resultString.append(" reset");
00694 }
00695 }
00696 *retvalP = xmlrpc_c::value_string(resultString);
00697
00698 return true;
00699 }
00700 };
00701
00705 class register_monitor_ : public cmd_
00706 {
00707 public:
00712 register_monitor_(xmlrpc_commander& c) :
00713 cmd_(c, "s:s", "Get notified of a new monitor")
00714 {}
00715
00716 private:
00717 bool execute_(xmlrpc_c::paramList const& paramList, xmlrpc_c::value* const retvalP)
00718 {
00719 try
00720 {
00721 getParam<fhicl::ParameterSet>(paramList, 0);
00722 }
00723 catch (...)
00724 {
00725 *retvalP = xmlrpc_c::value_string("The register_monitor command expects a string representing the FHiCL definition of a Transfer plugin");
00726 return true;
00727 }
00728
00729 *retvalP = xmlrpc_c::value_string(_c._commandable.register_monitor(getParam<fhicl::ParameterSet>(paramList, 0)));
00730 return true;
00731 }
00732 };
00733
00737 class unregister_monitor_ : public cmd_
00738 {
00739 public:
00744 unregister_monitor_(xmlrpc_commander& c) :
00745 cmd_(c, "s:s", "Remove a monitor")
00746 {}
00747
00748 private:
00749 bool execute_(xmlrpc_c::paramList const& paramList, xmlrpc_c::value* const retvalP)
00750 {
00751 try
00752 {
00753 getParam<std::string>(paramList, 0);
00754 }
00755 catch (...)
00756 {
00757 *retvalP = xmlrpc_c::value_string("The unregister_monitor command expects a string representing the label of the monitor to be removed");
00758 return true;
00759 }
00760
00761 *retvalP = xmlrpc_c::value_string(_c._commandable.unregister_monitor(getParam<std::string>(paramList, 0)));
00762 return true;
00763 }
00764 };
00765
00766
00770 class trace_set_ : public cmd_
00771 {
00772 public:
00777 trace_set_(xmlrpc_commander& c) :
00778 cmd_(c, "s:ssi", "Set TRACE mask")
00779 {}
00780
00781 private:
00782 bool execute_(xmlrpc_c::paramList const& paramList, xmlrpc_c::value* const retvalP)
00783 {
00784 try
00785 {
00786 getParam<std::string>(paramList, 0);
00787 getParam<std::string>(paramList, 1);
00788 getParam<uint64_t>(paramList, 2);
00789 }
00790 catch (...)
00791 {
00792 *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");
00793 return true;
00794 }
00795
00796 return _c._commandable.do_trace_set(getParam<std::string>(paramList, 0), getParam<std::string>(paramList, 1), getParam<uint64_t>(paramList, 2));
00797 }
00798 };
00799
00803 class trace_get_ : public cmd_
00804 {
00805 public:
00810 trace_get_(xmlrpc_commander& c) :
00811 cmd_(c, "s:s", "Get TRACE mask")
00812 {}
00813
00814 private:
00815 bool execute_(xmlrpc_c::paramList const& paramList, xmlrpc_c::value* const retvalP)
00816 {
00817 try
00818 {
00819 getParam<std::string>(paramList, 0);
00820 }
00821 catch (...)
00822 {
00823 *retvalP = xmlrpc_c::value_string("The trace_msgfacility_set command expects a name (ALL for all)");
00824 return true;
00825 }
00826
00827 *retvalP = xmlrpc_c::value_string(_c._commandable.do_trace_get(getParam<std::string>(paramList, 0)));
00828 return true;
00829 }
00830 };
00831
00835 class meta_command_ : public cmd_
00836 {
00837 public:
00842 meta_command_(xmlrpc_commander& c) :
00843 cmd_(c, "s:ss", "Run custom command")
00844 {}
00845
00846 private:
00847 bool execute_(xmlrpc_c::paramList const& paramList, xmlrpc_c::value* const retvalP)
00848 {
00849 try
00850 {
00851 getParam<std::string>(paramList, 0);
00852 getParam<std::string>(paramList, 1);
00853 }
00854 catch (...)
00855 {
00856 *retvalP = xmlrpc_c::value_string("The meta_command command expects a string command and a string argument");
00857 return true;
00858 }
00859
00860 return _c._commandable.do_meta_command(getParam<std::string>(paramList, 0), getParam<std::string>(paramList, 1));
00861 }
00862 };
00863
00864
00865
00866
00867
00868
00869 #if 0
00870 class shutdown_ : public xmlrpc_c::registry::shutdown
00871 {
00872 public:
00873 shutdown_(xmlrpc_c::serverAbyss *server) : _server(server) {}
00874
00875 virtual void doit(const std::string& paramString, void*) const
00876 {
00877 TLOG(TLVL_INFO) << "A shutdown command was sent "
00878 << "with parameter "
00879 << paramString << "\"" << TLOG_ENDL;
00880 _server->terminate();
00881 }
00882 private:
00883 xmlrpc_c::serverAbyss *_server;
00884 };
00885 #endif
00886
00887
00888
00889 xmlrpc_commander::xmlrpc_commander(fhicl::ParameterSet ps, artdaq::Commandable& commandable)
00890 : CommanderInterface(ps, commandable)
00891 , port_(ps.get<int>("id", 0))
00892 , serverUrl_(ps.get<std::string>("server_url", ""))
00893 , server(nullptr)
00894 {
00895
00896 }
00897
00898 void xmlrpc_commander::run_server() try
00899 {
00900
00901 xmlrpc_c::registry registry;
00902 struct xmlrpc_method_info3 methodInfo;
00903 memset(&methodInfo, 0, sizeof(methodInfo));
00904
00905
00906
00907
00908 #define register_method(m) register_method2(m,0x200000)
00909
00910 xmlrpc_env env;
00911 xmlrpc_registry ***c_registryPPP;
00912 c_registryPPP = (xmlrpc_registry ***)(((char*)®istry) + sizeof(girmem::autoObject));
00913
00914 #define register_method2(m,ss) \
00915 xmlrpc_c::method * ptr_ ## m(dynamic_cast<xmlrpc_c::method *>(new m ## _(*this))); \
00916 methodInfo.methodName = "daq." #m; \
00917 methodInfo.methodFunction = &c_executeMethod; \
00918 methodInfo.serverInfo = ptr_ ## m; \
00919 methodInfo.stackSize = ss; \
00920 methodInfo.signatureString = ptr_ ## m ->signature().c_str(); \
00921 methodInfo.help = ptr_ ## m ->help().c_str(); \
00922 xmlrpc_env_init(&env); \
00923 xmlrpc_registry_add_method3(&env,**c_registryPPP,&methodInfo); \
00924 if(env.fault_occurred)throw(girerr::error(env.fault_string)); \
00925 xmlrpc_env_clean(&env)
00926
00927 register_method2(init, 0x200000);
00928 register_method(soft_init);
00929 register_method(reinit);
00930 register_method(start);
00931 register_method(status);
00932 register_method(report);
00933 register_method(stop);
00934 register_method(pause);
00935 register_method(resume);
00936 register_method(register_monitor);
00937 register_method(unregister_monitor);
00938 register_method(legal_commands);
00939 register_method(trace_set);
00940 register_method(trace_get);
00941 register_method(meta_command);
00942
00943 register_method(shutdown);
00944
00945
00946 xmlrpc_c::methodPtr const ptr_reset(new shutdown_(*this));
00947 registry.addMethod("daq.reset", ptr_reset);
00948
00949 #undef register_method
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966 XMLRPC_SOCKET socket_file_descriptor = socket(PF_INET, SOCK_STREAM, 0);
00967
00968 if (socket_file_descriptor < 0)
00969 {
00970 throw cet::exception("xmlrpc_commander::run") <<
00971 "Problem with the socket() call; C-style errno == " <<
00972 errno << " (" << strerror(errno) << ")";
00973 }
00974
00975 int enable = 1;
00976 int retval = setsockopt(socket_file_descriptor,
00977 SOL_SOCKET, SO_REUSEADDR,
00978 &enable, sizeof(int));
00979
00980 if (retval < 0)
00981 {
00982 throw cet::exception("xmlrpc_commander::run") <<
00983 "Problem with the call to setsockopt(); C-style errno == " <<
00984 errno << " (" << strerror(errno) << ")";
00985 }
00986
00987 struct sockaddr_in sockAddr;
00988
00989 sockAddr.sin_family = AF_INET;
00990 sockAddr.sin_port = htons(port_);
00991 sockAddr.sin_addr.s_addr = 0;
00992
00993 retval = bind(socket_file_descriptor,
00994 reinterpret_cast<struct sockaddr*>(&sockAddr),
00995 sizeof(sockAddr));
00996
00997 if (retval != 0)
00998 {
00999 close(socket_file_descriptor);
01000 throw cet::exception("xmlrpc_commander::run") <<
01001 "Problem with the bind() call; C-style errno == " <<
01002 errno << " (" << strerror(errno) << ")";
01003 }
01004
01005 server.reset(new xmlrpc_c::serverAbyss(xmlrpc_c::serverAbyss::constrOpt().registryP(®istry).socketFd(socket_file_descriptor)));
01006
01007 #if 0
01008 xmlrpc_c::serverAbyss::shutdown shutdown_obj(&server);
01009 registry.setShutdown(&shutdown_obj);
01010 #endif
01011
01012 TLOG(TLVL_DEBUG) << "running server" << TLOG_ENDL;
01013
01014
01015
01016
01017
01018
01019
01020 try
01021 {
01022 server->run();
01023 }
01024 catch (...)
01025 {
01026 TLOG(TLVL_WARNING) << "server threw an exception; closing the socket and rethrowing" << TLOG_ENDL;
01027 close(socket_file_descriptor);
01028 throw;
01029 }
01030
01031 close(socket_file_descriptor);
01032 TLOG(TLVL_DEBUG) << "server terminated" << TLOG_ENDL;
01033 }
01034 catch (...)
01035 {
01036 throw;
01037 }
01038
01039
01040 std::string xmlrpc_commander::send_register_monitor(std::string monitor_fhicl)
01041 {
01042 if (serverUrl_ == "")
01043 {
01044 std::stringstream errmsg;
01045 errmsg << "Problem attempting XML-RPC call: No server URL set!";
01046 ExceptionHandler(ExceptionHandlerRethrow::yes,
01047 errmsg.str());
01048
01049 }
01050 xmlrpc_c::clientSimple myClient;
01051 xmlrpc_c::value result;
01052
01053 try
01054 {
01055 myClient.call(serverUrl_, "daq.register_monitor", "s", &result, monitor_fhicl.c_str());
01056 }
01057 catch (...)
01058 {
01059 std::stringstream errmsg;
01060 errmsg << "Problem attempting XML-RPC call on host " << serverUrl_
01061 << "; possible causes are malformed FHiCL or nonexistent process at requested port";
01062 ExceptionHandler(ExceptionHandlerRethrow::yes,
01063 errmsg.str());
01064 }
01065
01066 return xmlrpc_c::value_string(result);
01067 }
01068
01069 std::string xmlrpc_commander::send_unregister_monitor(std::string monitor_label)
01070 {
01071 if (serverUrl_ == "")
01072 {
01073 std::stringstream errmsg;
01074 errmsg << "Problem attempting XML-RPC call: No server URL set!";
01075 ExceptionHandler(ExceptionHandlerRethrow::yes,
01076 errmsg.str());
01077
01078 }
01079
01080 xmlrpc_c::clientSimple myClient;
01081 xmlrpc_c::value result;
01082
01083 try
01084 {
01085 myClient.call(serverUrl_, "daq.unregister_monitor", "s", &result, monitor_label.c_str());
01086 }
01087 catch (...)
01088 {
01089 std::stringstream errmsg;
01090 errmsg << "Problem attempting to unregister monitor via XML-RPC call on host " << serverUrl_
01091 << "; possible causes are that the monitor label \""
01092 << monitor_label
01093 << "\" is unrecognized by contacted process or process at requested port doesn't exist";
01094 ExceptionHandler(ExceptionHandlerRethrow::no, errmsg.str());
01095 }
01096
01097 return xmlrpc_c::value_string(result);
01098
01099 }
01100 }
01101
01102 DEFINE_ARTDAQ_COMMANDER(artdaq::xmlrpc_commander)