From 18ac7c4644add4db18bcb7cd7cb3560cffe846b3 Mon Sep 17 00:00:00 2001 From: "Matthias P. Braendli" Date: Fri, 14 Feb 2014 21:37:04 +0100 Subject: restart RC if it did a fault --- src/DabMux.cpp | 8 +++++++- src/ParserConfigfile.cpp | 12 +++++------ src/ParserConfigfile.h | 2 +- src/RemoteControl.cpp | 35 +++++++++++++++++++++++++------- src/RemoteControl.h | 52 ++++++++++++++++++++++++++++++++++++++---------- src/utils.cpp | 7 ++++++- 6 files changed, 89 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/DabMux.cpp b/src/DabMux.cpp index ca82889..ca5bd08 100644 --- a/src/DabMux.cpp +++ b/src/DabMux.cpp @@ -340,7 +340,7 @@ int main(int argc, char *argv[]) string conf_file = argv[2]; parse_configfile(conf_file, outputs, ensemble, &enableTist, &FICL, - &factumAnalyzer, &limit, rc, &statsserverport); + &factumAnalyzer, &limit, &rc, &statsserverport); } catch (runtime_error &e) { @@ -1812,6 +1812,12 @@ int main(int argc, char *argv[]) } } #endif + + /* Check every six seconds if the remote control is still working */ + if (rc && fc->FCT == 249 && rc->fault_detected()) { + etiLog.level(warn) << "Detected Remote Control fault, restarting it"; + rc->restart(); + } } EXIT: diff --git a/src/ParserConfigfile.cpp b/src/ParserConfigfile.cpp index 9f62bdd..74d9588 100644 --- a/src/ParserConfigfile.cpp +++ b/src/ParserConfigfile.cpp @@ -127,7 +127,7 @@ void parse_configfile(string configuration_file, unsigned* FICL, bool* factumAnalyzer, unsigned long* limit, - BaseRemoteController* rc, + BaseRemoteController** rc, int* statsServerPort ) { @@ -174,10 +174,10 @@ void parse_configfile(string configuration_file, int telnetport = pt_rc.get("telnetport", 0); if (telnetport != 0) { - rc = new RemoteControllerTelnet(telnetport); + *rc = new RemoteControllerTelnet(telnetport); } else { - rc = new RemoteControllerDummy(); + *rc = new RemoteControllerDummy(); } /******************** READ ENSEMBLE PARAMETERS *************/ @@ -240,7 +240,7 @@ void parse_configfile(string configuration_file, ptree pt_service = it->second; DabService* service = new DabService(serviceuid); ensemble->services.push_back(service); - service->enrol_at(*rc); + service->enrol_at(**rc); int success = -5; @@ -312,7 +312,7 @@ void parse_configfile(string configuration_file, try { setup_subchannel_from_ptree(subchan, it->second, ensemble, - subchanuid, rc); + subchanuid, *rc); } catch (runtime_error &e) { etiLog.log(error, @@ -380,7 +380,7 @@ void parse_configfile(string configuration_file, DabComponent* component = new DabComponent(componentuid); - component->enrol_at(*rc); + component->enrol_at(**rc); component->serviceId = service->id; component->subchId = subchannel->id; diff --git a/src/ParserConfigfile.h b/src/ParserConfigfile.h index f987542..5c8546f 100644 --- a/src/ParserConfigfile.h +++ b/src/ParserConfigfile.h @@ -40,7 +40,7 @@ void parse_configfile(std::string configuration_file, unsigned* FICL, bool* factumAnalyzer, unsigned long* limit, - BaseRemoteController* rc, + BaseRemoteController** rc, int* statsServerPort); void setup_subchannel_from_ptree(dabSubchannel* subchan, diff --git a/src/RemoteControl.cpp b/src/RemoteControl.cpp index fb1aa7e..3ce3310 100644 --- a/src/RemoteControl.cpp +++ b/src/RemoteControl.cpp @@ -26,16 +26,38 @@ #include #include #include +#include #include "Log.h" #include "RemoteControl.h" using boost::asio::ip::tcp; -void -RemoteControllerTelnet::process(long) + +void RemoteControllerTelnet::restart() +{ + m_restarter_thread = boost::thread(&RemoteControllerTelnet::restart_thread, + this, 0); +} + +// This runs in a separate thread, because +// it would take too long to be done in the main loop +// thread. +void RemoteControllerTelnet::restart_thread(long) +{ + m_running = false; + + if (m_port) { + m_child_thread.interrupt(); + m_child_thread.join(); + } + + m_child_thread = boost::thread(&RemoteControllerTelnet::process, this, 0); +} + +void RemoteControllerTelnet::process(long) { - m_welcome = "CRC-DABMUX Remote Control CLI\nWrite 'help' for help.\n**********\n"; + m_welcome = "ODR-DabMux Remote Control CLI\nWrite 'help' for help.\n**********\n"; m_prompt = "> "; std::string in_message; @@ -97,11 +119,11 @@ RemoteControllerTelnet::process(long) catch (std::exception& e) { etiLog.level(error) << "Remote control caught exception: " << e.what(); + m_fault = true; } } -void -RemoteControllerTelnet::dispatch_command(tcp::socket& socket, string command) +void RemoteControllerTelnet::dispatch_command(tcp::socket& socket, string command) { vector cmd = tokenise_(command); @@ -214,8 +236,7 @@ RemoteControllerTelnet::dispatch_command(tcp::socket& socket, string command) } } -void -RemoteControllerTelnet::reply(tcp::socket& socket, string message) +void RemoteControllerTelnet::reply(tcp::socket& socket, string message) { boost::system::error_code ignored_error; stringstream ss; diff --git a/src/RemoteControl.h b/src/RemoteControl.h index e76ba68..c0fec8d 100644 --- a/src/RemoteControl.h +++ b/src/RemoteControl.h @@ -67,11 +67,23 @@ class ParameterError : public std::exception class RemoteControllable; -/* Remote controllers (that recieve orders from the user) must implement BaseRemoteController */ +/* Remote controllers (that recieve orders from the user) + * must implement BaseRemoteController + */ class BaseRemoteController { public: /* Add a new controllable under this controller's command */ virtual void enrol(RemoteControllable* controllable) = 0; + + /* When this returns one, the remote controller cannot be + * used anymore, and must be restarted by dabmux + */ + virtual bool fault_detected() = 0; + + /* In case of a fault, the remote controller can be + * restarted. + */ + virtual void restart() = 0; }; /* Objects that support remote control must implement the following class */ @@ -125,33 +137,41 @@ class RemoteControllable { class RemoteControllerTelnet : public BaseRemoteController { public: RemoteControllerTelnet() - : m_running(false), m_port(0) {} + : m_running(false), m_fault(false), + m_port(0) {} RemoteControllerTelnet(int port) - : m_running(true), m_port(port), + : m_running(false), m_fault(false), + m_port(port), m_child_thread(&RemoteControllerTelnet::process, this, 0) {} ~RemoteControllerTelnet() { m_running = false; + m_fault = false; if (m_port) { m_child_thread.interrupt(); m_child_thread.join(); } } - void process(long); - - void dispatch_command(tcp::socket& socket, string command); - - void reply(tcp::socket& socket, string message); - void enrol(RemoteControllable* controllable) { m_cohort.push_back(controllable); } + virtual bool fault_detected() { return m_fault; }; + + virtual void restart(); private: + void restart_thread(long); + + void process(long); + + void dispatch_command(tcp::socket& socket, string command); + + void reply(tcp::socket& socket, string message); + RemoteControllerTelnet& operator=(const RemoteControllerTelnet& other); RemoteControllerTelnet(const RemoteControllerTelnet& other); @@ -192,7 +212,8 @@ class RemoteControllerTelnet : public BaseRemoteController { list< vector > allparams; list params = controllable->get_supported_parameters(); - for (list::iterator it = params.begin(); it != params.end(); ++it) { + for (list::iterator it = params.begin(); + it != params.end(); ++it) { vector item; item.push_back(*it); item.push_back(controllable->get_parameter(*it)); @@ -213,6 +234,11 @@ class RemoteControllerTelnet : public BaseRemoteController { } bool m_running; + + /* This is set to true if a fault occurred */ + bool m_fault; + boost::thread m_restarter_thread; + boost::thread m_child_thread; /* This controller commands the controllables in the cohort */ @@ -225,11 +251,15 @@ class RemoteControllerTelnet : public BaseRemoteController { }; -/* The Dummy remote controller does nothing +/* The Dummy remote controller does nothing, and never fails */ class RemoteControllerDummy : public BaseRemoteController { public: void enrol(RemoteControllable* controllable) {}; + + bool fault_detected() { return false; }; + + virtual void restart() {}; }; #endif diff --git a/src/utils.cpp b/src/utils.cpp index 8422782..1cbd9d5 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -306,8 +306,13 @@ void printOutputs(vector& outputs) etiLog.log(info, "Output %i", index); etiLog.level(info) << " protocol: " << (*output)->outputProto; + etiLog.level(info) << " name: " << - (*output)->outputName; + (*output)->outputName.c_str(); + // Daboutputfile mangles with outputName, inserting \0 to + // cut the string in several parts. That doesn't work + // with stl strings. Thats why the .c_str() + ++index; } } -- cgit v1.2.3