DUNE-DAQ
DUNE Trigger and Data Acquisition software
Toggle main menu visibility
Loading...
Searching...
No Matches
dunedaq
sourcecode
utilities
src
TimestampEstimatorTimeSync.cpp
Go to the documentation of this file.
1
8
9
#include "
utilities/TimestampEstimatorTimeSync.hpp
"
10
#include "
utilities/Issues.hpp
"
11
12
#include "
logging/Logging.hpp
"
13
14
#include <memory>
15
#include <unistd.h>
16
17
#define TRACE_NAME "TimestampEstimatorTimeSync"
// NOLINT
18
19
namespace
dunedaq::utilities
{
20
21
TimestampEstimatorTimeSync::TimestampEstimatorTimeSync
(uint32_t run_number,
// NOLINT(build/unsigned)
22
uint64_t clock_frequency_hz)
// NOLINT(build/unsigned)
23
:
TimestampEstimatorTimeSync
(clock_frequency_hz)
24
{
25
m_run_number
= run_number;
26
}
27
28
TimestampEstimatorTimeSync::TimestampEstimatorTimeSync
(uint64_t clock_frequency_hz)
// NOLINT(build/unsigned)
29
:
m_current_timestamp_estimate
(
TimeSyncPoint
{
s_invalid_ts
,
std
::chrono::time_point<
std
::chrono::steady_clock>() })
30
,
m_clock_frequency_hz
(clock_frequency_hz)
31
,
m_most_recent_daq_time
(
s_invalid_ts
)
32
,
m_most_recent_system_time
(0)
33
,
m_run_number
(0)
34
,
m_received_timesync_count
(0)
35
{
36
}
37
38
TimestampEstimatorTimeSync::~TimestampEstimatorTimeSync
() {}
39
45
uint64_t
// NOLINT(build/unsigned)
46
TimestampEstimatorTimeSync::get_timestamp_estimate
()
const
47
{
48
using namespace
std::chrono;
49
50
TimeSyncPoint
estimate =
m_current_timestamp_estimate
.load();
51
// 27-May-2025, KAB: added check if a valid timestamp is available and, if not, return early
52
// with the special value that indicates that none is available.
53
if
(estimate.
daq_time
==
s_invalid_ts
) {
54
return
estimate.
daq_time
;
55
}
56
57
auto
delta_time_us = duration_cast<microseconds>(steady_clock::now() - estimate.
system_time
).count();
58
59
const
uint64_t new_timestamp = estimate.
daq_time
+ delta_time_us *
m_clock_frequency_hz
/ 1000000;
// NOLINT
60
61
return
new_timestamp;
62
}
63
64
std::chrono::microseconds
65
TimestampEstimatorTimeSync::get_wait_estimate
(uint64_t ts)
const
// NOLINT(build/unsigned)
66
{
67
auto
now
=
get_timestamp_estimate
();
68
if
(
now
> ts)
69
return
std::chrono::microseconds(0);
70
auto
diff = ts -
now
;
71
return
std::chrono::microseconds(
static_cast<
std::chrono::microseconds::rep
>
(
72
static_cast<
double
>
(diff) * 1000000. /
static_cast<
double
>
(
m_clock_frequency_hz
)));
73
}
74
75
void
76
TimestampEstimatorTimeSync::add_timestamp_datapoint
(uint64_t daq_time, uint64_t system_time)
// NOLINT(build/unsigned)
77
{
78
using namespace
std::chrono;
79
80
std::scoped_lock<std::mutex> lk(
m_datapoint_mutex
);
81
82
// First, update the latest timestamp
83
TimeSyncPoint
estimate =
m_current_timestamp_estimate
.load();
84
auto
diff =
static_cast<
int64_t
>
(estimate.
daq_time
- daq_time);
85
TLOG_DEBUG
(
TLVL_TIME_SYNC_PROPERTIES
) <<
"Got a TimeSync timestamp = "
<< daq_time
86
<<
", system time = "
<< system_time <<
" when current timestamp estimate was "
87
<< estimate.
daq_time
<<
". diff="
<< diff;
88
89
if
(
m_most_recent_daq_time
==
s_invalid_ts
|| daq_time >
m_most_recent_daq_time
) {
90
m_most_recent_daq_time
= daq_time;
91
m_most_recent_system_time
= system_time;
92
}
93
94
if
(
m_most_recent_daq_time
!=
s_invalid_ts
) {
95
// Update the current timestamp estimate, based on the most recently-read TimeSync
96
using namespace
std::chrono;
97
98
auto
time_now =
99
static_cast<
uint64_t
>
(duration_cast<microseconds>(system_clock::now().time_since_epoch()).count());
// NOLINT
100
auto
steady_time_now = steady_clock::now();
101
102
// (PAR 2021-07-22) We only want to _increase_ our timestamp
103
// estimate, not _decrease_ it, so we only attempt the update if
104
// our system time is later than the latest time sync's system
105
// time. We can get TimeSync messages from the "future" if
106
// they're coming from another host whose clock is not exactly
107
// synchronized with ours: that's fine, but if the discrepancy
108
// is large, then badness could happen, so emit a warning
109
110
if
(time_now <
m_most_recent_system_time
- 10000) {
111
ers::warning
(EarlyTimeSync(
ERS_HERE
,
m_most_recent_system_time
- time_now));
112
}
113
114
if
(time_now >
m_most_recent_system_time
) {
115
116
auto
delta_time = time_now -
m_most_recent_system_time
;
117
TLOG_DEBUG
(
TLVL_TIME_SYNC_PROPERTIES
)
118
<<
"Time diff between current system and latest TimeSync system time [us]: "
<< delta_time;
119
120
// Warn user if current system time is more than 1s ahead of latest TimeSync system time. This could be a sign of
121
// an issue, e.g. machine times out of sync
122
if
(delta_time > 1'000'000)
123
ers::warning
(LateTimeSync(
ERS_HERE
, delta_time));
124
125
const
uint64_t new_timestamp =
m_most_recent_daq_time
+ delta_time *
m_clock_frequency_hz
/ 1000000;
// NOLINT
126
127
// Don't ever decrease the timestamp; just wait until enough
128
// time passes that we want to increase it
129
if
(estimate.
daq_time
==
s_invalid_ts
|| new_timestamp >= estimate.
daq_time
) {
130
TLOG_DEBUG
(
TLVL_TIME_SYNC_NEW_ESTIMATE
)
131
<<
"Storing new timestamp estimate of "
<< new_timestamp <<
" ticks (..."
<< std::fixed
132
<< std::setprecision(8)
133
<< (
static_cast<
double
>
(new_timestamp % (
m_clock_frequency_hz
* 1000)) /
134
static_cast<
double
>
(
m_clock_frequency_hz
))
135
<<
" sec), mrt.daq_time is "
<<
m_most_recent_daq_time
<<
" ticks (..."
136
<< (
static_cast<
double
>
(
m_most_recent_daq_time
% (
m_clock_frequency_hz
* 1000)) /
137
static_cast<
double
>
(
m_clock_frequency_hz
))
138
<<
" sec), delta_time is "
<< delta_time <<
" usec, clock_freq is "
<<
m_clock_frequency_hz
<<
" Hz"
;
139
m_current_timestamp_estimate
.store(
TimeSyncPoint
{ new_timestamp, steady_time_now });
140
}
else
{
141
TLOG_DEBUG
(
TLVL_TIME_SYNC_NOTES
) <<
"Not updating timestamp estimate backwards from "
142
<<
m_current_timestamp_estimate
.load().daq_time <<
" to "
<< new_timestamp;
143
}
144
}
145
}
146
}
147
148
}
// namespace dunedaq::utilities
ERS_HERE
#define ERS_HERE
Definition
LocalContext.hpp:141
TimestampEstimatorTimeSync.hpp
dunedaq::utilities::TimestampEstimatorBase::s_invalid_ts
static constexpr uint64_t s_invalid_ts
Definition
TimestampEstimatorBase.hpp:28
dunedaq::utilities::TimestampEstimatorTimeSync::m_most_recent_daq_time
uint64_t m_most_recent_daq_time
Definition
TimestampEstimatorTimeSync.hpp:66
dunedaq::utilities::TimestampEstimatorTimeSync::add_timestamp_datapoint
void add_timestamp_datapoint(uint64_t daq_time, uint64_t system_time)
Definition
TimestampEstimatorTimeSync.cpp:76
dunedaq::utilities::TimestampEstimatorTimeSync::m_clock_frequency_hz
uint64_t m_clock_frequency_hz
Definition
TimestampEstimatorTimeSync.hpp:65
dunedaq::utilities::TimestampEstimatorTimeSync::get_timestamp_estimate
uint64_t get_timestamp_estimate() const override
Returns the current timestamp estimate or a special value if no valid timestamp is available.
Definition
TimestampEstimatorTimeSync.cpp:46
dunedaq::utilities::TimestampEstimatorTimeSync::get_wait_estimate
std::chrono::microseconds get_wait_estimate(uint64_t ts) const override
Definition
TimestampEstimatorTimeSync.cpp:65
dunedaq::utilities::TimestampEstimatorTimeSync::m_received_timesync_count
std::atomic< uint64_t > m_received_timesync_count
Definition
TimestampEstimatorTimeSync.hpp:70
dunedaq::utilities::TimestampEstimatorTimeSync::m_datapoint_mutex
std::mutex m_datapoint_mutex
Definition
TimestampEstimatorTimeSync.hpp:68
dunedaq::utilities::TimestampEstimatorTimeSync::~TimestampEstimatorTimeSync
virtual ~TimestampEstimatorTimeSync()
Definition
TimestampEstimatorTimeSync.cpp:38
dunedaq::utilities::TimestampEstimatorTimeSync::m_current_timestamp_estimate
std::atomic< TimeSyncPoint > m_current_timestamp_estimate
Definition
TimestampEstimatorTimeSync.hpp:63
dunedaq::utilities::TimestampEstimatorTimeSync::TimestampEstimatorTimeSync
TimestampEstimatorTimeSync(uint32_t run_number, uint64_t clock_frequency_hz)
Definition
TimestampEstimatorTimeSync.cpp:21
dunedaq::utilities::TimestampEstimatorTimeSync::m_most_recent_system_time
uint64_t m_most_recent_system_time
Definition
TimestampEstimatorTimeSync.hpp:67
dunedaq::utilities::TimestampEstimatorTimeSync::m_run_number
uint32_t m_run_number
Definition
TimestampEstimatorTimeSync.hpp:69
now
static int64_t now()
Definition
kafka_opmon_consumer.cxx:44
Logging.hpp
TLOG_DEBUG
#define TLOG_DEBUG(lvl,...)
Definition
Logging.hpp:112
dunedaq::utilities
Definition
TimestampEstimatorTimeSync.hxx:3
dunedaq::utilities::TLVL_TIME_SYNC_PROPERTIES
@ TLVL_TIME_SYNC_PROPERTIES
Definition
TimestampEstimatorTimeSync.hpp:26
dunedaq::utilities::TLVL_TIME_SYNC_NOTES
@ TLVL_TIME_SYNC_NOTES
Definition
TimestampEstimatorTimeSync.hpp:27
dunedaq::utilities::TLVL_TIME_SYNC_NEW_ESTIMATE
@ TLVL_TIME_SYNC_NEW_ESTIMATE
Definition
TimestampEstimatorTimeSync.hpp:28
ers::warning
void warning(const Issue &issue)
Definition
ers.hpp:126
std
Definition
SchemaUtils.hpp:118
dunedaq::utilities::TimestampEstimatorTimeSync::TimeSyncPoint
Definition
TimestampEstimatorTimeSync.hpp:58
dunedaq::utilities::TimestampEstimatorTimeSync::TimeSyncPoint::daq_time
uint64_t daq_time
Definition
TimestampEstimatorTimeSync.hpp:59
dunedaq::utilities::TimestampEstimatorTimeSync::TimeSyncPoint::system_time
std::chrono::time_point< std::chrono::steady_clock > system_time
Definition
TimestampEstimatorTimeSync.hpp:60
Issues.hpp
Generated on
for DUNE-DAQ by
1.17.0