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
00767
00768
00769
00770
00771
00772 #if 0
00773 class shutdown_ : public xmlrpc_c::registry::shutdown
00774 {
00775 public:
00776 shutdown_(xmlrpc_c::serverAbyss *server) : _server(server) {}
00777
00778 virtual void doit(const std::string& paramString, void*) const
00779 {
00780 TLOG(TLVL_INFO) << "A shutdown command was sent "
00781 << "with parameter "
00782 << paramString << "\"" << TLOG_ENDL;
00783 _server->terminate();
00784 }
00785 private:
00786 xmlrpc_c::serverAbyss *_server;
00787 };
00788 #endif
00789
00790
00791
00792 xmlrpc_commander::xmlrpc_commander(fhicl::ParameterSet ps, artdaq::Commandable& commandable)
00793 : CommanderInterface(ps, commandable)
00794 , port_(ps.get<int>("id", 0))
00795 , serverUrl_(ps.get<std::string>("server_url", ""))
00796 , server(nullptr)
00797 {
00798
00799 }
00800
00801 void xmlrpc_commander::run_server() try
00802 {
00803
00804 xmlrpc_c::registry registry;
00805 struct xmlrpc_method_info3 methodInfo;
00806 memset(&methodInfo, 0, sizeof(methodInfo));
00807
00808
00809
00810
00811 #define register_method(m) register_method2(m,0x200000)
00812
00813 xmlrpc_env env;
00814 xmlrpc_registry ***c_registryPPP;
00815 c_registryPPP = (xmlrpc_registry ***)(((char*)®istry) + sizeof(girmem::autoObject));
00816
00817 #define register_method2(m,ss) \
00818 xmlrpc_c::method * ptr_ ## m(dynamic_cast<xmlrpc_c::method *>(new m ## _(*this))); \
00819 methodInfo.methodName = "daq." #m; \
00820 methodInfo.methodFunction = &c_executeMethod; \
00821 methodInfo.serverInfo = ptr_ ## m; \
00822 methodInfo.stackSize = ss; \
00823 methodInfo.signatureString = ptr_ ## m ->signature().c_str(); \
00824 methodInfo.help = ptr_ ## m ->help().c_str(); \
00825 xmlrpc_env_init(&env); \
00826 xmlrpc_registry_add_method3(&env,**c_registryPPP,&methodInfo); \
00827 if(env.fault_occurred)throw(girerr::error(env.fault_string)); \
00828 xmlrpc_env_clean(&env)
00829
00830 register_method2(init, 0x200000);
00831 register_method(soft_init);
00832 register_method(reinit);
00833 register_method(start);
00834 register_method(status);
00835 register_method(report);
00836 register_method(stop);
00837 register_method(pause);
00838 register_method(resume);
00839 register_method(register_monitor);
00840 register_method(unregister_monitor);
00841 register_method(legal_commands);
00842
00843 register_method(shutdown);
00844
00845
00846 xmlrpc_c::methodPtr const ptr_reset(new shutdown_(*this));
00847 registry.addMethod("daq.reset", ptr_reset);
00848
00849 #undef register_method
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866 XMLRPC_SOCKET socket_file_descriptor = socket(PF_INET, SOCK_STREAM, 0);
00867
00868 if (socket_file_descriptor < 0)
00869 {
00870 throw cet::exception("xmlrpc_commander::run") <<
00871 "Problem with the socket() call; C-style errno == " <<
00872 errno << " (" << strerror(errno) << ")";
00873 }
00874
00875 int enable = 1;
00876 int retval = setsockopt(socket_file_descriptor,
00877 SOL_SOCKET, SO_REUSEADDR,
00878 &enable, sizeof(int));
00879
00880 if (retval < 0)
00881 {
00882 throw cet::exception("xmlrpc_commander::run") <<
00883 "Problem with the call to setsockopt(); C-style errno == " <<
00884 errno << " (" << strerror(errno) << ")";
00885 }
00886
00887 struct sockaddr_in sockAddr;
00888
00889 sockAddr.sin_family = AF_INET;
00890 sockAddr.sin_port = htons(port_);
00891 sockAddr.sin_addr.s_addr = 0;
00892
00893 retval = bind(socket_file_descriptor,
00894 reinterpret_cast<struct sockaddr*>(&sockAddr),
00895 sizeof(sockAddr));
00896
00897 if (retval != 0)
00898 {
00899 close(socket_file_descriptor);
00900 throw cet::exception("xmlrpc_commander::run") <<
00901 "Problem with the bind() call; C-style errno == " <<
00902 errno << " (" << strerror(errno) << ")";
00903 }
00904
00905 server.reset(new xmlrpc_c::serverAbyss(xmlrpc_c::serverAbyss::constrOpt().registryP(®istry).socketFd(socket_file_descriptor)));
00906
00907 #if 0
00908 xmlrpc_c::serverAbyss::shutdown shutdown_obj(&server);
00909 registry.setShutdown(&shutdown_obj);
00910 #endif
00911
00912 TLOG(TLVL_DEBUG) << "running server" << TLOG_ENDL;
00913
00914
00915
00916
00917
00918
00919
00920 try
00921 {
00922 server->run();
00923 }
00924 catch (...)
00925 {
00926 TLOG(TLVL_WARNING) << "server threw an exception; closing the socket and rethrowing" << TLOG_ENDL;
00927 close(socket_file_descriptor);
00928 throw;
00929 }
00930
00931 close(socket_file_descriptor);
00932 TLOG(TLVL_DEBUG) << "server terminated" << TLOG_ENDL;
00933 }
00934 catch (...)
00935 {
00936 throw;
00937 }
00938
00939
00940 std::string xmlrpc_commander::send_register_monitor(std::string monitor_fhicl)
00941 {
00942 if (serverUrl_ == "")
00943 {
00944 std::stringstream errmsg;
00945 errmsg << "Problem attempting XML-RPC call: No server URL set!";
00946 ExceptionHandler(ExceptionHandlerRethrow::yes,
00947 errmsg.str());
00948
00949 }
00950 xmlrpc_c::clientSimple myClient;
00951 xmlrpc_c::value result;
00952
00953 try
00954 {
00955 myClient.call(serverUrl_, "daq.register_monitor", "s", &result, monitor_fhicl.c_str());
00956 }
00957 catch (...)
00958 {
00959 std::stringstream errmsg;
00960 errmsg << "Problem attempting XML-RPC call on host " << serverUrl_
00961 << "; possible causes are malformed FHiCL or nonexistent process at requested port";
00962 ExceptionHandler(ExceptionHandlerRethrow::yes,
00963 errmsg.str());
00964 }
00965
00966 return xmlrpc_c::value_string(result);
00967 }
00968
00969 std::string xmlrpc_commander::send_unregister_monitor(std::string monitor_label)
00970 {
00971 if (serverUrl_ == "")
00972 {
00973 std::stringstream errmsg;
00974 errmsg << "Problem attempting XML-RPC call: No server URL set!";
00975 ExceptionHandler(ExceptionHandlerRethrow::yes,
00976 errmsg.str());
00977
00978 }
00979
00980 xmlrpc_c::clientSimple myClient;
00981 xmlrpc_c::value result;
00982
00983 try
00984 {
00985 myClient.call(serverUrl_, "daq.unregister_monitor", "s", &result, monitor_label.c_str());
00986 }
00987 catch (...)
00988 {
00989 std::stringstream errmsg;
00990 errmsg << "Problem attempting to unregister monitor via XML-RPC call on host " << serverUrl_
00991 << "; possible causes are that the monitor label \""
00992 << monitor_label
00993 << "\" is unrecognized by contacted process or process at requested port doesn't exist";
00994 ExceptionHandler(ExceptionHandlerRethrow::no, errmsg.str());
00995 }
00996
00997 return xmlrpc_c::value_string(result);
00998
00999 }
01000 }
01001
01002 DEFINE_ARTDAQ_COMMANDER(artdaq::xmlrpc_commander)