From 21d54ff7296ff33c11b9f7b788417a11e702f0d0 Mon Sep 17 00:00:00 2001 From: "Matthias P. Braendli" Date: Wed, 31 Jan 2018 04:39:16 +0100 Subject: Add TAI bulletin expiry to RC and to munin --- src/ClockTAI.cpp | 49 +++++++++++++++++++++++++++++++++++++++++++++++-- src/ClockTAI.h | 22 ++++++++++++++++++++-- src/DabMultiplexer.cpp | 7 +++++++ src/DabMultiplexer.h | 7 +++++-- 4 files changed, 79 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/ClockTAI.cpp b/src/ClockTAI.cpp index 8c01127..c481841 100644 --- a/src/ClockTAI.cpp +++ b/src/ClockTAI.cpp @@ -76,6 +76,12 @@ static const char* tai_tz_url = static const char* tai_ietf_cache_file = "/tmp/odr-dabmux-leap-seconds.cache"; +ClockTAI::ClockTAI() : + RemoteControllable("clocktai") +{ + RC_ADD_PARAMETER(expiry, "Number of seconds until TAI Bulletin expires"); +} + int ClockTAI::get_valid_offset() { int offset = 0; @@ -152,6 +158,8 @@ int ClockTAI::get_offset() using namespace std::chrono; auto time_now = system_clock::now(); + std::unique_lock lock(m_data_mutex); + if (not m_offset_valid) { #ifdef TEST m_offset = 37; // Valid in early 2017 @@ -352,6 +360,11 @@ void ClockTAI::update_cache(const char* cache_filename) } bool ClockTAI::bulletin_is_valid() +{ + return bulletin_expiry_delay() > 0; +} + +int64_t ClockTAI::bulletin_expiry_delay() const { // The bulletin contains one line that specifies an expiration date // in NTP time. If that point in time is in the future, we consider @@ -380,10 +393,12 @@ bool ClockTAI::bulletin_is_valid() const int64_t expiry_unix = std::atol(expiry_data_str.c_str()) - ntp_unix_offset; - return expiry_unix > now; + if (expiry_unix > now) { + return expiry_unix - now; + } } } - return false; + return -1; } void ClockTAI::download_tai_utc_bulletin(const char* url) @@ -418,6 +433,36 @@ void ClockTAI::download_tai_utc_bulletin(const char* url) #endif // HAVE_CURL } +void ClockTAI::set_parameter(const string& parameter, const string& value) +{ + if (parameter == "expiry") { + throw ParameterError("Parameter '" + parameter + + "' is not read-only in controllable " + get_rc_name()); + } + else { + throw ParameterError("Parameter '" + parameter + + "' is not exported by controllable " + get_rc_name()); + } +} + +const string ClockTAI::get_parameter(const string& parameter) const +{ + if (parameter == "expiry") { + std::unique_lock lock(m_data_mutex); + int64_t expiry = bulletin_expiry_delay(); + if (expiry > 0) { + return to_string(expiry); + } + else { + return "Bulletin expired or invalid!"; + } + } + else { + throw ParameterError("Parameter '" + parameter + + "' is not exported by controllable " + get_rc_name()); + } +} + #if 0 // Example testing code void debug_tai_clk() diff --git a/src/ClockTAI.h b/src/ClockTAI.h index 4ee4072..ac4978c 100644 --- a/src/ClockTAI.h +++ b/src/ClockTAI.h @@ -39,14 +39,18 @@ #include #include #include +#include +#include "RemoteControl.h" // EDI needs to know UTC-TAI, but doesn't need the CLOCK_TAI to be set. // We can keep this code, maybe for future use #define SUPPORT_SETTING_CLOCK_TAI 0 /* Loads, parses and represents TAI-UTC offset information from the IETF bulletin */ -class ClockTAI { +class ClockTAI : public RemoteControllable { public: + ClockTAI(); + // Fetch the bulletin from the IETF website and return the current // TAI-UTC offset. // Throws runtime_error on failure. @@ -70,11 +74,14 @@ class ClockTAI { // Download of new bulletin is done asynchronously std::future m_offset_future; + // Protect all data members, as RC functions are in another thread + mutable std::mutex m_data_mutex; + // The currently used TAI-UTC offset int m_offset; int m_offset_valid = false; - std::stringstream m_bulletin; + mutable std::stringstream m_bulletin; std::chrono::system_clock::time_point m_bulletin_download_time; // Load bulletin into m_bulletin from the cache file @@ -87,6 +94,10 @@ class ClockTAI { // true if the bulletin is valid. bool bulletin_is_valid(void); + // In how much time will the bulletin expire? + // returns a value in seconds, or -1 if it is expired or invalid + int64_t bulletin_expiry_delay(void) const; + // Load bulletin into m_bulletin from the URL void download_tai_utc_bulletin(const char* url); @@ -99,5 +110,12 @@ class ClockTAI { // static callback wrapper for cURL static size_t fill_bulletin_cb( char *ptr, size_t size, size_t nmemb, void *ctx); + + /* Remote control */ + virtual void set_parameter(const std::string& parameter, + const std::string& value); + + /* Getting a parameter always returns a string. */ + virtual const std::string get_parameter(const std::string& parameter) const; }; diff --git a/src/DabMultiplexer.cpp b/src/DabMultiplexer.cpp index 8265b34..f452685 100644 --- a/src/DabMultiplexer.cpp +++ b/src/DabMultiplexer.cpp @@ -81,6 +81,13 @@ DabMultiplexer::DabMultiplexer( { RC_ADD_PARAMETER(frames, "Show number of frames generated [read-only]"); + + rcs.enrol(&m_clock_tai); +} + +DabMultiplexer::~DabMultiplexer() +{ + rcs.remove_controllable(&m_clock_tai); } void DabMultiplexer::set_edi_config(const edi_configuration_t& new_edi_conf) diff --git a/src/DabMultiplexer.h b/src/DabMultiplexer.h index 80b3ab9..499e023 100644 --- a/src/DabMultiplexer.h +++ b/src/DabMultiplexer.h @@ -54,8 +54,11 @@ class DabMultiplexer : public RemoteControllable { public: - DabMultiplexer( - boost::property_tree::ptree pt); + DabMultiplexer(boost::property_tree::ptree pt); + DabMultiplexer(const DabMultiplexer& other) = delete; + DabMultiplexer& operator=(const DabMultiplexer& other) = delete; + ~DabMultiplexer(); + void prepare(bool require_tai_clock); unsigned long getCurrentFrame() { return currentFrame; } -- cgit v1.2.3