From 5a0633d70a82e15f63a006489ffa1544fa37cb90 Mon Sep 17 00:00:00 2001 From: "Matthias P. Braendli" Date: Tue, 18 Dec 2018 10:06:07 +0100 Subject: Allow user to specify TAI bulletin URLs --- doc/example.mux | 7 ++++++ src/ClockTAI.cpp | 59 +++++++++++++++++++++++++++++++++++++++----------- src/ClockTAI.h | 6 ++++- src/DabMultiplexer.cpp | 15 ++++++++++++- 4 files changed, 72 insertions(+), 15 deletions(-) diff --git a/doc/example.mux b/doc/example.mux index 1ecffaf..48a89dc 100644 --- a/doc/example.mux +++ b/doc/example.mux @@ -50,6 +50,13 @@ general { ; your file is still valid. tist false + ; The URLs used to fetch the TAI bulletin can be overridden if needed. + ; URLs are given as a pipe-separated list, and the default value is: + ;tai_clock_bulletins "https://www.ietf.org/timezones/data/leap-seconds.list|https://raw.githubusercontent.com/eggert/tz/master/leap-seconds.list" + ; + ; You may also use a file:// URL if you take care of updating the file + ; yourself and store it locally. + ; The management server is a simple TCP server that can present ; statistics data (buffers, overruns, underruns, etc) ; which can then be graphed a tool like Munin diff --git a/src/ClockTAI.cpp b/src/ClockTAI.cpp index 875fce2..7fef72b 100644 --- a/src/ClockTAI.cpp +++ b/src/ClockTAI.cpp @@ -69,8 +69,8 @@ const int64_t ntp_unix_offset = 2208988800L; // leap seconds insertion bulletin is available from the IETF and in the TZ // distribution -static array tai_urls = { - "http://www.ietf.org/timezones/data/leap-seconds.list", +static array default_tai_urls = { + "https://www.ietf.org/timezones/data/leap-seconds.list", "https://raw.githubusercontent.com/eggert/tz/master/leap-seconds.list", }; @@ -86,10 +86,25 @@ static array tai_cache_locations = { "/tmp/odr-dabmux-leap-seconds.cache", }; -ClockTAI::ClockTAI() : +ClockTAI::ClockTAI(const std::vector& bulletin_urls) : RemoteControllable("clocktai") { RC_ADD_PARAMETER(expiry, "Number of seconds until TAI Bulletin expires"); + + if (bulletin_urls.empty()) { + etiLog.level(debug) << "Initialising default TAI Bulletin URLs"; + for (const auto url : default_tai_urls) { + m_bulletin_urls.push_back(url); + } + } + else { + etiLog.level(debug) << "Initialising user-configured TAI Bulletin URLs"; + m_bulletin_urls = bulletin_urls; + } + + for (const auto url : m_bulletin_urls) { + etiLog.level(info) << "TAI Bulletin URL: '" << url << "'"; + } } int ClockTAI::get_valid_offset() @@ -97,6 +112,8 @@ int ClockTAI::get_valid_offset() int offset = 0; bool offset_valid = false; + std::unique_lock lock(m_data_mutex); + if (bulletin_is_valid()) { #if TEST etiLog.level(info) << "Bulletin already valid"; @@ -120,19 +137,22 @@ int ClockTAI::get_valid_offset() offset_valid = true; } else { - for (const auto url : tai_urls) { + for (const auto url : m_bulletin_urls) { try { - download_tai_utc_bulletin(url); #if TEST etiLog.level(info) << "Load bulletin from " << url; #endif + download_tai_utc_bulletin(url.c_str()); if (bulletin_is_valid()) { -#if TEST - etiLog.level(info) << "Bulletin from " << url << " valid"; -#endif offset = parse_ietf_bulletin(); + etiLog.level(debug) << "Loaded valid TAI Bulletin from " << + url << " giving offset=" << offset; offset_valid = true; } + else { + etiLog.level(debug) << "Skipping invalid TAI bulletin from " + << url; + } } catch (const runtime_error& e) { etiLog.level(warn) << @@ -171,12 +191,14 @@ int ClockTAI::get_valid_offset() int ClockTAI::get_offset() { using namespace std::chrono; - auto time_now = system_clock::now(); + const auto time_now = system_clock::now(); std::unique_lock lock(m_data_mutex); if (not m_offset_valid) { #ifdef TEST + // Assume we've downloaded it in the past: + m_offset = 37; // Valid in early 2017 m_offset_valid = true; @@ -185,7 +207,14 @@ int ClockTAI::get_offset() #else // First time we run we must block until we know // the offset - m_offset = get_valid_offset(); + lock.unlock(); + try { + m_offset = get_valid_offset(); + } + catch (const download_failed&) { + throw runtime_error("Unable to download TAI bulletin"); + } + lock.lock(); m_offset_valid = true; m_bulletin_download_time = system_clock::now(); #endif @@ -196,6 +225,7 @@ int ClockTAI::get_offset() if (time_now - m_bulletin_download_time > hours(24 * 31)) { // Refresh if it's older than one month. Leap seconds are // announced several months in advance + etiLog.level(debug) << "Trying to refresh TAI bulletin"; if (m_offset_future.valid()) { auto state = m_offset_future.wait_for(seconds(0)); @@ -211,8 +241,8 @@ int ClockTAI::get_offset() } catch (const download_failed&) { etiLog.level(warn) << - "TAI-UTC download failed, will retry in " + - to_string(download_retry_interval_hours) + " hour(s)"; + "TAI-UTC download failed, will retry in " << + download_retry_interval_hours << " hour(s)"; } #ifdef TEST wait_longer = false; @@ -409,6 +439,9 @@ int64_t ClockTAI::bulletin_expiry_delay() const std::atoll(expiry_data_str.c_str()) - ntp_unix_offset; if (expiry_unix > now) { +#ifdef TEST + etiLog.level(info) << "Bulletin expires in " << expiry_unix - now; +#endif return expiry_unix - now; } } @@ -516,7 +549,7 @@ int main(int argc, char **argv) { using namespace std; - ClockTAI tai; + ClockTAI tai({}); while (wait_longer) { try { diff --git a/src/ClockTAI.h b/src/ClockTAI.h index e0dc439..4436ba9 100644 --- a/src/ClockTAI.h +++ b/src/ClockTAI.h @@ -40,6 +40,8 @@ #include #include #include +#include +#include #include "RemoteControl.h" // EDI needs to know UTC-TAI, but doesn't need the CLOCK_TAI to be set. @@ -49,7 +51,7 @@ /* Loads, parses and represents TAI-UTC offset information from the IETF bulletin */ class ClockTAI : public RemoteControllable { public: - ClockTAI(); + ClockTAI(const std::vector& bulletin_urls); // Fetch the bulletin from the IETF website and return the current // TAI-UTC offset. @@ -81,6 +83,8 @@ class ClockTAI : public RemoteControllable { int m_offset = 0; int m_offset_valid = false; + std::vector m_bulletin_urls; + mutable std::stringstream m_bulletin; std::chrono::system_clock::time_point m_bulletin_download_time; diff --git a/src/DabMultiplexer.cpp b/src/DabMultiplexer.cpp index 84d9704..719e767 100644 --- a/src/DabMultiplexer.cpp +++ b/src/DabMultiplexer.cpp @@ -66,6 +66,19 @@ const unsigned short BitRateTable[64] = { 384, 384, 384 }; +static vector split_pipe_separated_string(const std::string& s) +{ + stringstream ss; + ss << s; + + string elem; + vector components; + while (getline(ss, elem, '|')) { + components.push_back(elem); + } + return components; +} + DabMultiplexer::DabMultiplexer( boost::property_tree::ptree pt) : RemoteControllable("mux"), @@ -76,7 +89,7 @@ DabMultiplexer::DabMultiplexer( currentFrame(0), ensemble(std::make_shared()), m_tai_clock_required(false), - m_clock_tai(), + m_clock_tai(split_pipe_separated_string(pt.get("general.tai_clock_bulletins", ""))), fig_carousel(ensemble) { RC_ADD_PARAMETER(frames, -- cgit v1.2.3