ifw-daq  3.0.0-pre2
IFW Data Acquisition modules
status.cpp
Go to the documentation of this file.
1 /**
2  * @file
3  * @ingroup daq_common_libdaq
4  * @copyright
5  * (c) Copyright ESO 2023
6  * All Rights Reserved
7  * ESO (eso.org) is an Intergovernmental Organisation, and therefore special legal conditions apply.
8  */
9 #include <algorithm>
10 #include <ctime>
11 #include <daq/status.hpp>
12 #include <iomanip>
13 #include <ostream>
14 
15 #include <fmt/format.h>
16 
17 namespace daq {
18 
19 void SetAlert(std::vector<Alert>& alerts, Alert alert) {
20  auto it = find(alerts.begin(), alerts.end(), alert);
21  if (it != alerts.end()) {
22  // Replace
23  *it = std::move(alert);
24  } else {
25  // Or add
26  alerts.emplace_back(std::move(alert));
27  }
28 }
29 
30 bool ClearAlert(std::vector<Alert>& alerts, AlertId const& alert) {
31  auto it = std::remove(alerts.begin(), alerts.end(), alert);
32  if (it != alerts.end()) {
33  alerts.erase(it, alerts.end());
34  return true;
35  }
36  return false;
37 }
38 
39 Alert MakeAlert(std::string_view category, std::string key, std::string description) {
40  return Alert{{std::string(category), std::move(key)},
41  std::move(description),
42  Alert::TimePoint::clock::now()};
43 }
44 
45 Alert MakeAlert(AlertId id, std::string description) {
46  return Alert{std::move(id), std::move(description), Alert::TimePoint::clock::now()};
47 }
48 
49 AlertId MakeAlertId(std::string_view category, std::string key) {
50  return AlertId{std::string(category), std::move(key)};
51 }
52 
53 bool operator==(AlertId const& lhs, AlertId const& rhs) noexcept {
54  return lhs.key == rhs.key && lhs.category == rhs.category;
55 }
56 
57 bool operator!=(AlertId const& lhs, AlertId const& rhs) noexcept {
58  return !(lhs == rhs);
59 }
60 
61 std::ostream& operator<<(std::ostream& os, AlertId const& s) {
62  os << s.category << "-" << s.key;
63  return os;
64 }
65 
66 bool operator==(Alert const& lhs, Alert const& rhs) noexcept {
67  return lhs.id == rhs.id;
68 }
69 
70 bool operator==(Alert const& lhs, AlertId const& rhs) noexcept {
71  return lhs.id == rhs;
72 }
73 
74 bool operator==(AlertId const& lhs, Alert const& rhs) noexcept {
75  return lhs == rhs.id;
76 }
77 
78 bool operator!=(Alert const& lhs, Alert const& rhs) noexcept {
79  return !(lhs == rhs);
80 }
81 
82 std::ostream& operator<<(std::ostream& os, Alert const& alert) {
83  auto t = std::chrono::system_clock::to_time_t(alert.timestamp);
84  os << std::put_time(std::gmtime(&t), "%FT%TZ") << " (" << alert.id
85  << "): " << alert.description;
86  return os;
87 }
88 
89 std::ostream& operator<<(std::ostream& os, std::vector<Alert> const& alerts) {
90  auto count = 0u;
91  for (auto const& alert : alerts) {
92  os << "[" << count << "]: " << alert << "\n";
93  ++count;
94  }
95  return os;
96 }
97 
99  std::string id, std::string file_id, State state, bool error, TimePoint timestamp) noexcept
100  : id(std::move(id))
101  , file_id(std::move(file_id))
102  , state(state)
103  , error(error)
104  , alerts()
105  , timestamp(timestamp) {
106 }
107 
108 Status::Status(std::string id, std::string file_id) noexcept
109  : id(std::move(id))
110  , file_id(std::move(file_id))
111  , state(State::NotStarted)
112  , error(false)
113  , alerts()
114  , timestamp(TimePoint::clock::now()) {
115 }
116 
117 bool Status::operator==(Status const& rhs) const noexcept {
118  return id == rhs.id && file_id == rhs.file_id && state == rhs.state && error == rhs.error &&
119  alerts == rhs.alerts && result == rhs.result;
120 }
121 
122 bool Status::operator!=(Status const& rhs) const noexcept {
123  return !(*this == rhs);
124 }
125 
126 std::ostream& operator<<(std::ostream& os, Status const& s) {
127  os << "Status(id='" << s.id << "', file_id='" << s.file_id << "', state=" << s.state
128  << ", error=" << (s.error ? "true" : "false") << ", result='" << s.result << "')";
129  return os;
130 }
131 
133  if (m_status) {
134  m_status->DisableSignals();
135  }
136 }
137 
139  : m_status(nullptr) {
140  std::swap(m_status, other.m_status);
141 }
142 
145  // Reset this before stealing resources from other
146  Reset();
147 
148  std::swap(m_status, other.m_status);
149  return *this;
150 }
151 
153  Reset();
154 }
155 
157  if (!m_status) {
158  return;
159  }
160  // Signal
161  m_status->EnableSignals();
162  m_status->SignalChanges(true);
163 
164  m_status = nullptr;
165 }
166 
167 ObservableStatus::ObservableStatus(Status status) : m_status(std::move(status)) {
168 }
169 
170 ObservableStatus::ObservableStatus(std::string id, std::string file_id) noexcept
171  : m_status(std::move(id), std::move(file_id)) {
172 }
173 
175  if (m_status == status) {
176  return *this;
177  }
178  if (m_status.id != status.id) {
179  throw std::invalid_argument(fmt::format(
180  "Precondition not met (equality of DAQ IDs): {} != {}", m_status.id, status.id));
181  }
182  m_status = status;
183  SignalChanges();
184  return *this;
185 }
186 
187 bool ObservableStatus::operator==(ObservableStatus const& rhs) const noexcept {
188  return m_status == rhs.m_status;
189 }
190 
191 bool ObservableStatus::operator!=(ObservableStatus const& rhs) const noexcept {
192  return !(*this == rhs);
193 }
194 
195 bool ObservableStatus::operator==(Status const& rhs) const noexcept {
196  return m_status == rhs;
197 }
198 
199 bool ObservableStatus::operator!=(Status const& rhs) const noexcept {
200  return !(*this == rhs);
201 }
202 
203 std::string const& ObservableStatus::GetId() const noexcept {
204  return m_status.id;
205 }
206 
207 std::vector<Alert> const& ObservableStatus::GetAlerts() const noexcept {
208  return m_status.alerts;
209 }
210 
211 std::string const& ObservableStatus::GetFileId() const noexcept {
212  return m_status.file_id;
213 }
214 
216  return m_status.state;
217 }
218 
219 bool ObservableStatus::GetError() const noexcept {
220  return m_status.error;
221 }
222 
223 void ObservableStatus::SetState(State s, std::optional<bool> error) noexcept {
224  if (s == m_status.state) {
225  if (!error || error.value() == m_status.error) {
226  return;
227  }
228  }
229  m_status.state = s;
230  if (error.has_value()) {
231  m_status.error = *error;
232  }
233  SignalChanges();
234 }
235 
236 void ObservableStatus::SetError(bool error) noexcept {
237  if (error == m_status.error) {
238  return;
239  }
240  m_status.error = error;
241  SignalChanges();
242 }
243 
244 void ObservableStatus::SetResult(std::string result) {
245  m_status.result = std::move(result);
246  SignalChanges();
247 }
248 
250  ::daq::SetAlert(m_status.alerts, std::move(alert));
251  SignalChanges();
252 }
253 
255  if (::daq::ClearAlert(m_status.alerts, alert)) {
256  SignalChanges();
257  }
258 }
259 
260 void ObservableStatus::SignalChanges(bool force) noexcept {
261  m_status.timestamp = Status::TimePoint::clock::now();
262  try {
263  if (force || m_deferred_signals == 0) {
264  m_signal(*this);
265  }
266  } catch (...) {
267  }
268 }
269 
270 ObservableStatus::operator Status() const {
271  return m_status;
272 }
273 
274 Status const& ObservableStatus::GetStatus() const noexcept {
275  return m_status;
276 }
277 
279  assert(m_deferred_signals > 0);
280  --m_deferred_signals;
281 }
283  ++m_deferred_signals;
284 }
285 
286 std::ostream& operator<<(std::ostream& os, ObservableStatus const& s) {
287  os << "ObservableStatus(id='" << s.GetId() << "', file_id='" << s.GetFileId()
288  << "', state=" << s.GetState() << ", error=" << (s.GetError() ? "true" : "false") << ")";
289  return os;
290 }
291 
292 } // namespace daq
Defer signal changes until later time.
Definition: status.hpp:177
void Reset() noexcept
If object is valid.
Definition: status.cpp:156
DeferSignal & operator=(DeferSignal &&) noexcept
Definition: status.cpp:144
Stores data acquisition status and allows subscription to status changes.
Definition: status.hpp:165
void SignalChanges(bool forced=false) noexcept
Signal changes to observers.
Definition: status.cpp:260
State GetState() const noexcept
Definition: status.cpp:215
void SetError(bool error) noexcept
Set error flag for data acquisition.
Definition: status.cpp:236
ObservableStatus & operator=(ObservableStatus &&)=default
Status const & GetStatus() const noexcept
Connect observer that is invoked when state is modified.
Definition: status.cpp:274
void ClearAlert(AlertId const &alert)
Clear alert.
Definition: status.cpp:254
bool operator==(ObservableStatus const &rhs) const noexcept
Definition: status.cpp:187
void SetState(State s, std::optional< bool > error=std::nullopt) noexcept
Set state of data acquisition.
Definition: status.cpp:223
void DisableSignals() noexcept
Definition: status.cpp:282
void SetResult(std::string result)
Set resulting data product path.
Definition: status.cpp:244
void EnableSignals() noexcept
Definition: status.cpp:278
std::string const & GetFileId() const noexcept
Definition: status.cpp:211
bool GetError() const noexcept
Definition: status.cpp:219
bool operator!=(ObservableStatus const &rhs) const noexcept
Definition: status.cpp:191
void SetAlert(Alert alert)
Set alert.
Definition: status.cpp:249
std::vector< Alert > const & GetAlerts() const noexcept
Definition: status.cpp:207
ObservableStatus(std::string id, std::string file_id) noexcept
Construct a new object.
Definition: status.cpp:170
std::string const & GetId() const noexcept
Definition: status.cpp:203
daqif::DaqStatus & operator<<(daqif::DaqStatus &status, daq::Status const &rhs)
Convert daq::Status -> daqif::DaqStatus by populating from rhs.
Definition: conversion.cpp:18
AlertId id
Definition: status.hpp:76
AlertId MakeAlertId(std::string_view category, std::string key)
Definition: status.cpp:49
std::string key
Unique key for each alert.
Definition: status.hpp:60
std::string description
Definition: status.hpp:77
bool operator==(DaqContext const &lhs, DaqContext const &rhs) noexcept
Definition: daqContext.cpp:12
TimePoint timestamp
Definition: status.hpp:78
bool operator!=(AlertId const &lhs, AlertId const &rhs) noexcept
Definition: status.cpp:57
std::string category
Standardized category.
Definition: status.hpp:56
void SetAlert(std::vector< Alert > &alerts, Alert alert)
Set alert.
Definition: status.cpp:19
bool ClearAlert(std::vector< Alert > &alerts, AlertId const &alert)
Clear alert.
Definition: status.cpp:30
State
Observable states of the data acquisition process.
Definition: state.hpp:39
@ NotStarted
Initial state of data acquisition.
Alert MakeAlert(std::string_view category, std::string key, std::string description)
Construct alert.
Definition: status.cpp:39
Describes an active Data Acquisition alert.
Definition: status.hpp:72
Uniquely identfies an alert.
Definition: status.hpp:52
Definition: main.cpp:23
Contains declaration for Status and ObservableStatus.
Non observable status object that keeps stores status of data acquisition.
Definition: status.hpp:124
bool operator!=(Status const &rhs) const noexcept
Definition: status.cpp:122
bool operator==(Status const &rhs) const noexcept
Definition: status.cpp:117
std::chrono::time_point< std::chrono::steady_clock > TimePoint
Definition: status.hpp:125
State state
Definition: status.hpp:142
std::string id
Definition: status.hpp:140
std::string result
Path to resulting data product.
Definition: status.hpp:152
std::string file_id
Definition: status.hpp:141
bool error
Definition: status.hpp:143
std::vector< Alert > alerts
Active alerts.
Definition: status.hpp:147
Status()=default