DUNE-DAQ
DUNE Trigger and Data Acquisition software
Loading...
Searching...
No Matches
dunedaq::utilities::TimestampEstimatorTimeSync Class Reference

TimestampEstimatorTimeSync is an implementation of TimestampEstimatorBase that uses TimeSync messages from an input queue to estimate the current timestamp. More...

#include <TimestampEstimatorTimeSync.hpp>

Inheritance diagram for dunedaq::utilities::TimestampEstimatorTimeSync:
[legend]
Collaboration diagram for dunedaq::utilities::TimestampEstimatorTimeSync:
[legend]

Classes

struct  TimeSyncPoint
 

Public Member Functions

 TimestampEstimatorTimeSync (uint32_t run_number, uint64_t clock_frequency_hz)
 
 TimestampEstimatorTimeSync (uint64_t clock_frequency_hz)
 
virtual ~TimestampEstimatorTimeSync ()
 
uint64_t get_timestamp_estimate () const override
 Returns the current timestamp estimate or a special value if no valid timestamp is available.
 
std::chrono::microseconds get_wait_estimate (uint64_t ts) const override
 
void add_timestamp_datapoint (uint64_t daq_time, uint64_t system_time)
 
template<class T >
void timesync_callback (const T &tsync)
 
uint64_t get_received_timesync_count () const
 
- Public Member Functions inherited from dunedaq::utilities::TimestampEstimatorBase
virtual ~TimestampEstimatorBase ()=default
 
WaitStatus wait_for_valid_timestamp (std::atomic< bool > &continue_flag)
 
WaitStatus wait_for_valid_timestamp (std::atomic< bool > &continue_flag, uint64_t &last_seen_ts)
 Waits for a valid timestamp to become available. Returns a status value that indicates whether a valid timestamp is available or not.
 
WaitStatus wait_for_requested_timestamp (uint64_t ts, std::atomic< bool > &continue_flag)
 
WaitStatus wait_for_requested_timestamp (uint64_t ts, std::atomic< bool > &continue_flag, uint64_t &last_seen_ts)
 

Private Attributes

std::atomic< TimeSyncPointm_current_timestamp_estimate
 
uint64_t m_clock_frequency_hz
 
uint64_t m_most_recent_daq_time { s_invalid_ts }
 
uint64_t m_most_recent_system_time
 
std::mutex m_datapoint_mutex
 
uint32_t m_run_number { 0 }
 
std::atomic< uint64_t > m_received_timesync_count
 
uint32_t m_current_process_id
 

Additional Inherited Members

- Public Types inherited from dunedaq::utilities::TimestampEstimatorBase
enum  WaitStatus { kFinished , kInterrupted }
 
- Static Public Attributes inherited from dunedaq::utilities::TimestampEstimatorBase
static constexpr uint64_t s_invalid_ts = std::numeric_limits<uint64_t>::max()
 

Detailed Description

TimestampEstimatorTimeSync is an implementation of TimestampEstimatorBase that uses TimeSync messages from an input queue to estimate the current timestamp.

Definition at line 36 of file TimestampEstimatorTimeSync.hpp.

Constructor & Destructor Documentation

◆ TimestampEstimatorTimeSync() [1/2]

dunedaq::utilities::TimestampEstimatorTimeSync::TimestampEstimatorTimeSync ( uint32_t run_number,
uint64_t clock_frequency_hz )

Definition at line 21 of file TimestampEstimatorTimeSync.cpp.

23 : TimestampEstimatorTimeSync(clock_frequency_hz)
24{
25 m_run_number = run_number;
26}
TimestampEstimatorTimeSync(uint32_t run_number, uint64_t clock_frequency_hz)

◆ TimestampEstimatorTimeSync() [2/2]

dunedaq::utilities::TimestampEstimatorTimeSync::TimestampEstimatorTimeSync ( uint64_t clock_frequency_hz)
explicit

Definition at line 28 of file TimestampEstimatorTimeSync.cpp.

◆ ~TimestampEstimatorTimeSync()

dunedaq::utilities::TimestampEstimatorTimeSync::~TimestampEstimatorTimeSync ( )
virtual

Definition at line 39 of file TimestampEstimatorTimeSync.cpp.

39{}

Member Function Documentation

◆ add_timestamp_datapoint()

void dunedaq::utilities::TimestampEstimatorTimeSync::add_timestamp_datapoint ( uint64_t daq_time,
uint64_t system_time )

Definition at line 77 of file TimestampEstimatorTimeSync.cpp.

78{
79 using namespace std::chrono;
80
81 std::scoped_lock<std::mutex> lk(m_datapoint_mutex);
82
83 // First, update the latest timestamp
84 TimeSyncPoint estimate = m_current_timestamp_estimate.load();
85 auto diff = static_cast<int64_t>(estimate.daq_time - daq_time);
86 TLOG_DEBUG(TLVL_TIME_SYNC_PROPERTIES) << "Got a TimeSync timestamp = " << daq_time
87 << ", system time = " << system_time << " when current timestamp estimate was "
88 << estimate.daq_time << ". diff=" << diff;
89
91 m_most_recent_daq_time = daq_time;
92 m_most_recent_system_time = system_time;
93 }
94
96 // Update the current timestamp estimate, based on the most recently-read TimeSync
97 using namespace std::chrono;
98
99 auto time_now =
100 static_cast<uint64_t>(duration_cast<microseconds>(system_clock::now().time_since_epoch()).count()); // NOLINT
101 auto steady_time_now = steady_clock::now();
102
103 // (PAR 2021-07-22) We only want to _increase_ our timestamp
104 // estimate, not _decrease_ it, so we only attempt the update if
105 // our system time is later than the latest time sync's system
106 // time. We can get TimeSync messages from the "future" if
107 // they're coming from another host whose clock is not exactly
108 // synchronized with ours: that's fine, but if the discrepancy
109 // is large, then badness could happen, so emit a warning
110
111 if (time_now < m_most_recent_system_time - 10000) {
112 ers::warning(EarlyTimeSync(ERS_HERE, m_most_recent_system_time - time_now));
113 }
114
115 if (time_now > m_most_recent_system_time) {
116
117 auto delta_time = time_now - m_most_recent_system_time;
119 << "Time diff between current system and latest TimeSync system time [us]: " << delta_time;
120
121 // Warn user if current system time is more than 1s ahead of latest TimeSync system time. This could be a sign of
122 // an issue, e.g. machine times out of sync
123 if (delta_time > 1'000'000)
124 ers::warning(LateTimeSync(ERS_HERE, delta_time));
125
126 const uint64_t new_timestamp = m_most_recent_daq_time + delta_time * m_clock_frequency_hz / 1000000; // NOLINT
127
128 // Don't ever decrease the timestamp; just wait until enough
129 // time passes that we want to increase it
130 if (estimate.daq_time == s_invalid_ts || new_timestamp >= estimate.daq_time) {
132 << "Storing new timestamp estimate of " << new_timestamp << " ticks (..." << std::fixed
133 << std::setprecision(8)
134 << (static_cast<double>(new_timestamp % (m_clock_frequency_hz * 1000)) /
135 static_cast<double>(m_clock_frequency_hz))
136 << " sec), mrt.daq_time is " << m_most_recent_daq_time << " ticks (..."
137 << (static_cast<double>(m_most_recent_daq_time % (m_clock_frequency_hz * 1000)) /
138 static_cast<double>(m_clock_frequency_hz))
139 << " sec), delta_time is " << delta_time << " usec, clock_freq is " << m_clock_frequency_hz << " Hz";
140 m_current_timestamp_estimate.store(TimeSyncPoint{ new_timestamp, steady_time_now });
141 } else {
142 TLOG_DEBUG(TLVL_TIME_SYNC_NOTES) << "Not updating timestamp estimate backwards from "
143 << m_current_timestamp_estimate.load().daq_time << " to " << new_timestamp;
144 }
145 }
146 }
147}
#define ERS_HERE
#define TLOG_DEBUG(lvl,...)
Definition Logging.hpp:112
void warning(const Issue &issue)
Definition ers.hpp:115

◆ get_received_timesync_count()

uint64_t dunedaq::utilities::TimestampEstimatorTimeSync::get_received_timesync_count ( ) const
inline

Definition at line 54 of file TimestampEstimatorTimeSync.hpp.

54{ return m_received_timesync_count.load(); } // NOLINT(build/unsigned)

◆ get_timestamp_estimate()

uint64_t dunedaq::utilities::TimestampEstimatorTimeSync::get_timestamp_estimate ( ) const
overridevirtual

Returns the current timestamp estimate or a special value if no valid timestamp is available.

Returns
the current estimated timestamp (in units of DUNE Timing System ticks) or s_invalid_ts if no valid timestamp is currently available

Implements dunedaq::utilities::TimestampEstimatorBase.

Definition at line 47 of file TimestampEstimatorTimeSync.cpp.

48{
49 using namespace std::chrono;
50
51 TimeSyncPoint estimate = m_current_timestamp_estimate.load();
52 // 27-May-2025, KAB: added check if a valid timestamp is available and, if not, return early
53 // with the special value that indicates that none is available.
54 if (estimate.daq_time == s_invalid_ts) {
55 return estimate.daq_time;
56 }
57
58 auto delta_time_us = duration_cast<microseconds>(steady_clock::now() - estimate.system_time).count();
59
60 const uint64_t new_timestamp = estimate.daq_time + delta_time_us * m_clock_frequency_hz / 1000000; // NOLINT
61
62 return new_timestamp;
63}

◆ get_wait_estimate()

std::chrono::microseconds dunedaq::utilities::TimestampEstimatorTimeSync::get_wait_estimate ( uint64_t ts) const
overridevirtual

Implements dunedaq::utilities::TimestampEstimatorBase.

Definition at line 66 of file TimestampEstimatorTimeSync.cpp.

67{
69 if (now > ts)
70 return std::chrono::microseconds(0);
71 auto diff = ts - now;
72 return std::chrono::microseconds(static_cast<std::chrono::microseconds::rep>(
73 static_cast<double>(diff) * 1000000. / static_cast<double>(m_clock_frequency_hz)));
74}
uint64_t get_timestamp_estimate() const override
Returns the current timestamp estimate or a special value if no valid timestamp is available.
static int64_t now()
PDS Frame with unphysical timestamp detected with ts

◆ timesync_callback()

template<class T >
void dunedaq::utilities::TimestampEstimatorTimeSync::timesync_callback ( const T & tsync)

Definition at line 7 of file TimestampEstimatorTimeSync.hxx.

8{
10 TLOG_DEBUG(TLVL_TIME_SYNC_PROPERTIES) << "Got a TimeSync run=" << tsync.run_number << " local run=" << m_run_number
11 << " seqno=" << tsync.sequence_number << " source_pid=" << tsync.source_pid;
12 if (tsync.run_number == m_run_number && tsync.source_pid != m_current_process_id) {
13 add_timestamp_datapoint(tsync.daq_time, tsync.system_time);
14 } else {
15 TLOG_DEBUG(0) << "Discarded TimeSync message from run " << tsync.run_number << " during run " << m_run_number
16 << " with pid " << tsync.source_pid << " and timestamp " << tsync.daq_time;
17 }
18}
void add_timestamp_datapoint(uint64_t daq_time, uint64_t system_time)

Member Data Documentation

◆ m_clock_frequency_hz

uint64_t dunedaq::utilities::TimestampEstimatorTimeSync::m_clock_frequency_hz
private

Definition at line 65 of file TimestampEstimatorTimeSync.hpp.

◆ m_current_process_id

uint32_t dunedaq::utilities::TimestampEstimatorTimeSync::m_current_process_id
private

Definition at line 71 of file TimestampEstimatorTimeSync.hpp.

◆ m_current_timestamp_estimate

std::atomic<TimeSyncPoint> dunedaq::utilities::TimestampEstimatorTimeSync::m_current_timestamp_estimate
private

Definition at line 63 of file TimestampEstimatorTimeSync.hpp.

◆ m_datapoint_mutex

std::mutex dunedaq::utilities::TimestampEstimatorTimeSync::m_datapoint_mutex
private

Definition at line 68 of file TimestampEstimatorTimeSync.hpp.

◆ m_most_recent_daq_time

uint64_t dunedaq::utilities::TimestampEstimatorTimeSync::m_most_recent_daq_time { s_invalid_ts }
private

Definition at line 66 of file TimestampEstimatorTimeSync.hpp.

66{ s_invalid_ts }; // NOLINT(build/unsigned)

◆ m_most_recent_system_time

uint64_t dunedaq::utilities::TimestampEstimatorTimeSync::m_most_recent_system_time
private

Definition at line 67 of file TimestampEstimatorTimeSync.hpp.

◆ m_received_timesync_count

std::atomic<uint64_t> dunedaq::utilities::TimestampEstimatorTimeSync::m_received_timesync_count
private

Definition at line 70 of file TimestampEstimatorTimeSync.hpp.

◆ m_run_number

uint32_t dunedaq::utilities::TimestampEstimatorTimeSync::m_run_number { 0 }
private

Definition at line 69 of file TimestampEstimatorTimeSync.hpp.

69{ 0 }; // NOLINT(build/unsigned)

The documentation for this class was generated from the following files: