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 return boost::lexical_cast<uint64_t>(paramList.getInt(index));
00298 }
00299
00308 template <>
00309 std::string cmd_::getParam<std::string>(const xmlrpc_c::paramList& paramList, int index)
00310 {
00311 return static_cast<std::string>(paramList.getString(index));
00312 }
00313
00322 template <>
00323 art::RunID cmd_::getParam<art::RunID>(const xmlrpc_c::paramList& paramList, int index)
00324 {
00325 std::string run_number_string = paramList.getString(index);
00326 art::RunNumber_t run_number =
00327 boost::lexical_cast<art::RunNumber_t>(run_number_string);
00328 art::RunID run_id(run_number);
00329
00330 return run_id;
00331 }
00332
00341 template <>
00342 fhicl::ParameterSet cmd_::getParam<fhicl::ParameterSet>(const xmlrpc_c::paramList& paramList, int index)
00343 {
00344 std::string configString = std::string(paramList.getString(index).c_str());
00345 TLOG(TLVL_DEBUG) << "Loading Parameter Set from string: " << configString << std::endl;
00346 fhicl::ParameterSet pset;
00347
00348 try
00349 {
00350 fhicl::make_ParameterSet(configString, pset);
00351 }
00352 catch (fhicl::exception e)
00353 {
00354 if (getenv("FHICL_FILE_PATH") == nullptr)
00355 {
00356 std::cerr << "INFO: environment variable FHICL_FILE_PATH was not set. Using \".\"\n";
00357 setenv("FHICL_FILE_PATH", ".", 0);
00358 }
00359 cet::filepath_lookup_after1 lookup_policy("FHICL_FILE_PATH");
00360 fhicl::make_ParameterSet(configString, lookup_policy, pset);
00361 }
00362
00363 TLOG(TLVL_INFO) << "Parameter Set Loaded." << std::endl;
00364 return pset;
00365 }
00366
00367 template <typename T>
00368 T cmd_::getParam(const xmlrpc_c::paramList& paramList, int index,
00369 T default_value)
00370 {
00371 T val = default_value;
00372
00373 try
00374 {
00375 val = getParam<T>(paramList, index);
00376 }
00377 catch (const cet::exception& exception)
00378 {
00379 throw exception;
00380 }
00381 catch (...) {}
00382
00383 return val;
00384 }
00385
00386 void cmd_::execute(const xmlrpc_c::paramList& paramList, xmlrpc_c::value* const retvalP)
00387 {
00388 std::unique_lock<std::timed_mutex> lk(_c.mutex_, std::chrono::milliseconds(250));
00389 if (lk.owns_lock())
00390 {
00391 try
00392 {
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403 if (execute_(paramList, retvalP))
00404 {
00405 if (!retvalP->isInstantiated())
00406 {
00407 *retvalP = xmlrpc_c::value_string("Success");
00408 }
00409 }
00410 else
00411 {
00412 std::string problemReport = _c._commandable.report("transition_status");
00413 *retvalP = xmlrpc_c::value_string(problemReport);
00414 }
00415 }
00416 catch (std::runtime_error& er)
00417 {
00418 std::string msg = exception_msg(er, _help);
00419 *retvalP = xmlrpc_c::value_string(msg);
00420 TLOG(TLVL_ERROR) << msg ;
00421 }
00422 catch (art::Exception& er)
00423 {
00424 std::string msg = exception_msg(er, _help);
00425 *retvalP = xmlrpc_c::value_string(msg);
00426 TLOG(TLVL_ERROR) << msg ;
00427 }
00428 catch (cet::exception& er)
00429 {
00430 std::string msg = exception_msg(er, _help);
00431 *retvalP = xmlrpc_c::value_string(msg);
00432 TLOG(TLVL_ERROR) << msg ;
00433 }
00434 catch (...)
00435 {
00436 std::string msg = exception_msg("Unknown exception", _help);
00437 *retvalP = xmlrpc_c::value_string(msg);
00438 TLOG(TLVL_ERROR) << msg ;
00439 }
00440 }
00441 else
00442 {
00443 *retvalP = xmlrpc_c::value_string("busy");
00444 }
00445 }
00446
00447
00449
00450
00451
00452
00453
00454
00455
00456 #define GENERATE_INIT_TRANSITION(NAME, CALL, DESCRIPTION) \
00457 \
00458 class NAME ## _: public cmd_ { \
00459 \
00460 public: \
00461 \
00464 explicit NAME ## _(xmlrpc_commander& c): \
00465 cmd_(c, "s:sii", DESCRIPTION) {} \
00466 \
00467 \
00468 static const uint64_t defaultTimeout = 45; \
00469 \
00470 static const uint64_t defaultTimestamp = std::numeric_limits<const uint64_t>::max(); \
00471 \
00472 private: \
00473 bool execute_(const xmlrpc_c::paramList& paramList, xmlrpc_c::value* const retvalP ) { \
00474 fhicl::ParameterSet ps; \
00475 try { \
00476 ps = getParam<fhicl::ParameterSet>(paramList, 0); \
00477 } catch (...) { \
00478 *retvalP = xmlrpc_c::value_string ("The "#NAME" message requires a single argument that is a string containing the initialization ParameterSet"); \
00479 return true; \
00480 } \
00481 \
00482 return _c._commandable.CALL(ps, \
00483 getParam<uint64_t>(paramList, 1, defaultTimeout), \
00484 getParam<uint64_t>(paramList, 2, defaultTimestamp) \
00485 ); \
00486 } \
00487 };
00488
00489 GENERATE_INIT_TRANSITION(init, initialize, "initialize the program")
00490
00491 GENERATE_INIT_TRANSITION(soft_init, soft_initialize, "initialize software components in the program")
00492
00493 GENERATE_INIT_TRANSITION(reinit, reinitialize, "re-initialize the program")
00494
00495 #undef GENERATE_INIT_TRANSITION
00496
00498
00502 class start_ : public cmd_
00503 {
00504 public:
00509 explicit start_(xmlrpc_commander& c) :
00510 cmd_(c, "s:iii", "start the run")
00511 {}
00512
00514 static const uint64_t defaultTimeout = 45;
00516 static const uint64_t defaultTimestamp = std::numeric_limits<const uint64_t>::max();
00517
00518 private:
00519
00520 bool execute_(xmlrpc_c::paramList const& paramList, xmlrpc_c::value* const retvalP) override
00521 {
00522 try
00523 {
00524 getParam<art::RunID>(paramList, 0);
00525 }
00526 catch (...)
00527 {
00528 *retvalP = xmlrpc_c::value_string("The start message requires the run number as an argument.");
00529 return true;
00530 }
00531
00532 return _c._commandable.start(getParam<art::RunID>(paramList, 0),
00533 getParam<uint64_t>(paramList, 1, defaultTimeout),
00534 getParam<uint64_t>(paramList, 2, defaultTimestamp)
00535 );
00536 }
00537 };
00538
00539
00541
00542
00543
00544
00545
00546
00547
00548 #define GENERATE_TIMEOUT_TIMESTAMP_TRANSITION(NAME, CALL, DESCRIPTION, TIMEOUT) \
00549 \
00550 class NAME ## _: public cmd_ { \
00551 \
00552 public: \
00553 \
00555 NAME ## _(xmlrpc_commander& c): \
00556 cmd_(c, "s:ii", DESCRIPTION) {} \
00557 \
00558 \
00559 static const uint64_t defaultTimeout = TIMEOUT ; \
00560 \
00561 static const uint64_t defaultTimestamp = std::numeric_limits<const uint64_t>::max(); \
00562 \
00563 private: \
00564 \
00565 bool execute_ (const xmlrpc_c::paramList& paramList , xmlrpc_c::value* const ) { \
00566 \
00567 return _c._commandable.CALL( getParam<uint64_t>(paramList, 0, defaultTimeout), \
00568 getParam<uint64_t>(paramList, 1, defaultTimestamp) \
00569 ); \
00570 } \
00571 };
00572
00573 GENERATE_TIMEOUT_TIMESTAMP_TRANSITION(pause, pause, "pause the program", 45)
00574
00575 GENERATE_TIMEOUT_TIMESTAMP_TRANSITION(resume, resume, "resume the program", 45)
00576
00577 GENERATE_TIMEOUT_TIMESTAMP_TRANSITION(stop, stop, "stop the program", 45)
00578
00579 #undef GENERATE_TIMEOUT_TIMESTAMP_TRANSITION
00580
00581
00585 class shutdown_ : public cmd_
00586 {
00587 public:
00592 shutdown_(xmlrpc_commander& c) :
00593 cmd_(c, "s:i", "shutdown the program")
00594 {}
00595
00597 static const uint64_t defaultTimeout = 45;
00598
00599 private:
00600
00601 bool execute_(const xmlrpc_c::paramList& paramList, xmlrpc_c::value* const)
00602 {
00603 auto ret = _c._commandable.shutdown(getParam<uint64_t>(paramList, 0, defaultTimeout));
00604
00605 #if 1
00606 if (_c.server) _c.server->terminate();
00607 #endif
00608
00609 return ret;
00610 }
00611 };
00612
00613
00617 class status_ : public cmd_
00618 {
00619 public:
00624 status_(xmlrpc_commander& c) :
00625 cmd_(c, "s:n", "report the current state")
00626 {}
00627
00628 private:
00629
00630 bool execute_(xmlrpc_c::paramList const&, xmlrpc_c::value* const retvalP)
00631 {
00632 *retvalP = xmlrpc_c::value_string(_c._commandable.status());
00633 return true;
00634 }
00635 };
00636
00637
00641 class report_ : public cmd_
00642 {
00643 public:
00648 report_(xmlrpc_commander& c) :
00649 cmd_(c, "s:s", "report statistics")
00650 {}
00651
00652 private:
00653 bool execute_(xmlrpc_c::paramList const& paramList, xmlrpc_c::value* const retvalP)
00654 {
00655 try
00656 {
00657 getParam<std::string>(paramList, 0);
00658 }
00659 catch (...)
00660 {
00661 *retvalP = xmlrpc_c::value_string("The report message requires a single argument that selects the type of statistics to be reported.");
00662 return true;
00663 }
00664
00665 *retvalP = xmlrpc_c::value_string(_c._commandable.report(getParam<std::string>(paramList, 0)));
00666 return true;
00667 }
00668 };
00669
00673 class legal_commands_ : public cmd_
00674 {
00675 public:
00680 legal_commands_(xmlrpc_commander& c) :
00681 cmd_(c, "s:n", "return the currently legal commands")
00682 {}
00683
00684 private:
00685 bool execute_(xmlrpc_c::paramList const&, xmlrpc_c::value* const retvalP)
00686 {
00687 std::vector<std::string> cmdList = _c._commandable.legal_commands();
00688 std::string resultString;
00689
00690 for (auto& cmd : cmdList)
00691 {
00692 resultString.append(cmd + " ");
00693 if (cmd == "shutdown")
00694 {
00695 resultString.append(" reset");
00696 }
00697 }
00698 *retvalP = xmlrpc_c::value_string(resultString);
00699
00700 return true;
00701 }
00702 };
00703
00707 class register_monitor_ : public cmd_
00708 {
00709 public:
00714 register_monitor_(xmlrpc_commander& c) :
00715 cmd_(c, "s:s", "Get notified of a new monitor")
00716 {}
00717
00718 private:
00719 bool execute_(xmlrpc_c::paramList const& paramList, xmlrpc_c::value* const retvalP)
00720 {
00721 try
00722 {
00723 getParam<fhicl::ParameterSet>(paramList, 0);
00724 }
00725 catch (...)
00726 {
00727 *retvalP = xmlrpc_c::value_string("The register_monitor command expects a string representing the FHiCL definition of a Transfer plugin");
00728 return true;
00729 }
00730
00731 *retvalP = xmlrpc_c::value_string(_c._commandable.register_monitor(getParam<fhicl::ParameterSet>(paramList, 0)));
00732 return true;
00733 }
00734 };
00735
00739 class unregister_monitor_ : public cmd_
00740 {
00741 public:
00746 unregister_monitor_(xmlrpc_commander& c) :
00747 cmd_(c, "s:s", "Remove a monitor")
00748 {}
00749
00750 private:
00751 bool execute_(xmlrpc_c::paramList const& paramList, xmlrpc_c::value* const retvalP)
00752 {
00753 try
00754 {
00755 getParam<std::string>(paramList, 0);
00756 }
00757 catch (...)
00758 {
00759 *retvalP = xmlrpc_c::value_string("The unregister_monitor command expects a string representing the label of the monitor to be removed");
00760 return true;
00761 }
00762
00763 *retvalP = xmlrpc_c::value_string(_c._commandable.unregister_monitor(getParam<std::string>(paramList, 0)));
00764 return true;
00765 }
00766 };
00767
00768
00772 class trace_set_ : public cmd_
00773 {
00774 public:
00779 trace_set_(xmlrpc_commander& c) :
00780 cmd_(c, "s:ssi", "Set TRACE mask")
00781 {}
00782
00783 private:
00784 bool execute_(xmlrpc_c::paramList const& paramList, xmlrpc_c::value* const retvalP)
00785 {
00786 try
00787 {
00788 getParam<std::string>(paramList, 0);
00789 getParam<std::string>(paramList, 1);
00790 getParam<uint64_t>(paramList, 2);
00791 }
00792 catch (...)
00793 {
00794 *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");
00795 return true;
00796 }
00797
00798 return _c._commandable.do_trace_set(getParam<std::string>(paramList, 0), getParam<std::string>(paramList, 1), getParam<uint64_t>(paramList, 2));
00799 }
00800 };
00801
00805 class trace_get_ : public cmd_
00806 {
00807 public:
00812 trace_get_(xmlrpc_commander& c) :
00813 cmd_(c, "s:s", "Get TRACE mask")
00814 {}
00815
00816 private:
00817 bool execute_(xmlrpc_c::paramList const& paramList, xmlrpc_c::value* const retvalP)
00818 {
00819 try
00820 {
00821 getParam<std::string>(paramList, 0);
00822 }
00823 catch (...)
00824 {
00825 *retvalP = xmlrpc_c::value_string("The trace_msgfacility_set command expects a name (ALL for all)");
00826 return true;
00827 }
00828
00829 *retvalP = xmlrpc_c::value_string(_c._commandable.do_trace_get(getParam<std::string>(paramList, 0)));
00830 return true;
00831 }
00832 };
00833
00837 class meta_command_ : public cmd_
00838 {
00839 public:
00844 meta_command_(xmlrpc_commander& c) :
00845 cmd_(c, "s:ss", "Run custom command")
00846 {}
00847
00848 private:
00849 bool execute_(xmlrpc_c::paramList const& paramList, xmlrpc_c::value* const retvalP)
00850 {
00851 try
00852 {
00853 getParam<std::string>(paramList, 0);
00854 getParam<std::string>(paramList, 1);
00855 }
00856 catch (...)
00857 {
00858 *retvalP = xmlrpc_c::value_string("The meta_command command expects a string command and a string argument");
00859 return true;
00860 }
00861
00862 return _c._commandable.do_meta_command(getParam<std::string>(paramList, 0), getParam<std::string>(paramList, 1));
00863 }
00864 };
00865
00866
00867
00868
00869
00870
00871 #if 0
00872 class shutdown_ : public xmlrpc_c::registry::shutdown
00873 {
00874 public:
00875 shutdown_(xmlrpc_c::serverAbyss *server) : _server(server) {}
00876
00877 virtual void doit(const std::string& paramString, void*) const
00878 {
00879 TLOG(TLVL_INFO) << "A shutdown command was sent "
00880 << "with parameter "
00881 << paramString << "\"" ;
00882 _server->terminate();
00883 }
00884 private:
00885 xmlrpc_c::serverAbyss *_server;
00886 };
00887 #endif
00888
00889
00890
00891 xmlrpc_commander::xmlrpc_commander(fhicl::ParameterSet ps, artdaq::Commandable& commandable)
00892 : CommanderInterface(ps, commandable)
00893 , port_(ps.get<int>("id", 0))
00894 , serverUrl_(ps.get<std::string>("server_url", ""))
00895 , server(nullptr)
00896 {
00897
00898 }
00899
00900 void xmlrpc_commander::run_server() try
00901 {
00902
00903 xmlrpc_c::registry registry;
00904 struct xmlrpc_method_info3 methodInfo;
00905 memset(&methodInfo, 0, sizeof(methodInfo));
00906
00907
00908
00909
00910 #define register_method(m) register_method2(m,0x400000)
00911
00912 xmlrpc_env env;
00913 xmlrpc_registry ***c_registryPPP;
00914 c_registryPPP = (xmlrpc_registry ***)(((char*)®istry) + sizeof(girmem::autoObject));
00915
00916 #define register_method2(m,ss) \
00917 xmlrpc_c::method * ptr_ ## m(dynamic_cast<xmlrpc_c::method *>(new m ## _(*this))); \
00918 methodInfo.methodName = "daq." #m; \
00919 methodInfo.methodFunction = &c_executeMethod; \
00920 methodInfo.serverInfo = ptr_ ## m; \
00921 methodInfo.stackSize = ss; \
00922 methodInfo.signatureString = ptr_ ## m ->signature().c_str(); \
00923 methodInfo.help = ptr_ ## m ->help().c_str(); \
00924 xmlrpc_env_init(&env); \
00925 xmlrpc_registry_add_method3(&env,**c_registryPPP,&methodInfo); \
00926 if(env.fault_occurred)throw(girerr::error(env.fault_string)); \
00927 xmlrpc_env_clean(&env)
00928
00929 register_method2(init, 0x200000);
00930 register_method(soft_init);
00931 register_method(reinit);
00932 register_method(start);
00933 register_method(status);
00934 register_method(report);
00935 register_method(stop);
00936 register_method(pause);
00937 register_method(resume);
00938 register_method(register_monitor);
00939 register_method(unregister_monitor);
00940 register_method(legal_commands);
00941 register_method(trace_set);
00942 register_method(trace_get);
00943 register_method(meta_command);
00944
00945 register_method(shutdown);
00946
00947
00948 xmlrpc_c::methodPtr const ptr_reset(new shutdown_(*this));
00949 registry.addMethod("daq.reset", ptr_reset);
00950
00951 #undef register_method
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968 XMLRPC_SOCKET socket_file_descriptor = socket(PF_INET, SOCK_STREAM, 0);
00969
00970 if (socket_file_descriptor < 0)
00971 {
00972 throw cet::exception("xmlrpc_commander::run") <<
00973 "Problem with the socket() call; C-style errno == " <<
00974 errno << " (" << strerror(errno) << ")";
00975 }
00976
00977 int enable = 1;
00978 int retval = setsockopt(socket_file_descriptor,
00979 SOL_SOCKET, SO_REUSEADDR,
00980 &enable, sizeof(int));
00981
00982 if (retval < 0)
00983 {
00984 throw cet::exception("xmlrpc_commander::run") <<
00985 "Problem with the call to setsockopt(); C-style errno == " <<
00986 errno << " (" << strerror(errno) << ")";
00987 }
00988
00989 struct sockaddr_in sockAddr;
00990
00991 sockAddr.sin_family = AF_INET;
00992 sockAddr.sin_port = htons(port_);
00993 sockAddr.sin_addr.s_addr = 0;
00994
00995 retval = bind(socket_file_descriptor,
00996 reinterpret_cast<struct sockaddr*>(&sockAddr),
00997 sizeof(sockAddr));
00998
00999 if (retval != 0)
01000 {
01001 close(socket_file_descriptor);
01002 throw cet::exception("xmlrpc_commander::run") <<
01003 "Problem with the bind() call; C-style errno == " <<
01004 errno << " (" << strerror(errno) << ")";
01005 }
01006
01007 server.reset(new xmlrpc_c::serverAbyss(xmlrpc_c::serverAbyss::constrOpt().registryP(®istry).socketFd(socket_file_descriptor)));
01008
01009 #if 0
01010 xmlrpc_c::serverAbyss::shutdown shutdown_obj(&server);
01011 registry.setShutdown(&shutdown_obj);
01012 #endif
01013
01014 TLOG(TLVL_DEBUG) << "running server" ;
01015
01016
01017
01018
01019
01020
01021
01022 try
01023 {
01024 server->run();
01025 }
01026 catch (...)
01027 {
01028 TLOG(TLVL_WARNING) << "server threw an exception; closing the socket and rethrowing" ;
01029 close(socket_file_descriptor);
01030 throw;
01031 }
01032
01033 close(socket_file_descriptor);
01034 TLOG(TLVL_DEBUG) << "server terminated" ;
01035 }
01036 catch (...)
01037 {
01038 throw;
01039 }
01040
01041
01042 std::string xmlrpc_commander::send_register_monitor(std::string monitor_fhicl)
01043 {
01044 if (serverUrl_ == "")
01045 {
01046 std::stringstream errmsg;
01047 errmsg << "Problem attempting XML-RPC call: No server URL set!";
01048 ExceptionHandler(ExceptionHandlerRethrow::yes,
01049 errmsg.str());
01050
01051 }
01052 xmlrpc_c::clientSimple myClient;
01053 xmlrpc_c::value result;
01054
01055 try
01056 {
01057 myClient.call(serverUrl_, "daq.register_monitor", "s", &result, monitor_fhicl.c_str());
01058 }
01059 catch (...)
01060 {
01061 std::stringstream errmsg;
01062 errmsg << "Problem attempting XML-RPC call on host " << serverUrl_
01063 << "; possible causes are malformed FHiCL or nonexistent process at requested port";
01064 ExceptionHandler(ExceptionHandlerRethrow::yes,
01065 errmsg.str());
01066 }
01067
01068 return xmlrpc_c::value_string(result);
01069 }
01070
01071 std::string xmlrpc_commander::send_unregister_monitor(std::string monitor_label)
01072 {
01073 if (serverUrl_ == "")
01074 {
01075 std::stringstream errmsg;
01076 errmsg << "Problem attempting XML-RPC call: No server URL set!";
01077 ExceptionHandler(ExceptionHandlerRethrow::yes,
01078 errmsg.str());
01079
01080 }
01081
01082 xmlrpc_c::clientSimple myClient;
01083 xmlrpc_c::value result;
01084
01085 try
01086 {
01087 myClient.call(serverUrl_, "daq.unregister_monitor", "s", &result, monitor_label.c_str());
01088 }
01089 catch (...)
01090 {
01091 std::stringstream errmsg;
01092 errmsg << "Problem attempting to unregister monitor via XML-RPC call on host " << serverUrl_
01093 << "; possible causes are that the monitor label \""
01094 << monitor_label
01095 << "\" is unrecognized by contacted process or process at requested port doesn't exist";
01096 ExceptionHandler(ExceptionHandlerRethrow::no, errmsg.str());
01097 }
01098
01099 return xmlrpc_c::value_string(result);
01100
01101 }
01102 }
01103
01104 DEFINE_ARTDAQ_COMMANDER(artdaq::xmlrpc_commander)