ifw-daq  3.0.0-pre2
IFW Data Acquisition modules
status.hpp
Go to the documentation of this file.
1 /**
2  * @file
3  * @ingroup daq_common_libdaq
4  * @copyright 2022 ESO - European Southern Observatory
5  *
6  * @brief Contains declaration for Status and ObservableStatus
7  */
8 #ifndef OCM_DAQ_DAQ_STATUS_HPP_
9 #define OCM_DAQ_DAQ_STATUS_HPP_
10 
11 #include <chrono>
12 #include <iosfwd>
13 #include <string>
14 #include <vector>
15 
16 #include <boost/signals2/signal.hpp>
17 
18 #include "dpPart.hpp"
19 #include "state.hpp"
20 #include <daq/fits/keyword.hpp>
21 
22 namespace daq {
23 
24 namespace alert {
25 
26 /**
27  * Request
28  *
29  * Key: request-name + source-name
30  */
31 constexpr std::string_view REQUEST = "request";
32 
33 /**
34  * Failure during rsync source copy.
35  * Key: local file path
36  */
37 constexpr std::string_view TRANSFERRING_RSYNC = "transferring.rsync";
38 
39 /**
40  * Merging failed.
41  * Key: "" (nothing)
42  *
43  * Warning/alert during merging.
44  * Key: warning-id (e.g. "primary_hdu_resize")
45  */
46 constexpr std::string_view MERGING_MERGE = "merging.merge";
47 } // namespace alert
48 
49 /**
50  * Uniquely identfies an alert.
51  */
52 struct AlertId {
53  /**
54  * Standardized category
55  */
56  std::string category;
57  /**
58  * Unique key for each alert
59  */
60  std::string key;
61 };
62 
63 bool operator==(AlertId const& lhs, AlertId const& rhs) noexcept;
64 bool operator!=(AlertId const& lhs, AlertId const& rhs) noexcept;
65 std::ostream& operator<<(std::ostream& os, AlertId const& s);
66 
67 /**
68  * Describes an active Data Acquisition alert.
69  *
70  * category and key make up the unique identifier of an alert.
71  */
72 struct Alert {
73  using Clock = std::chrono::system_clock;
74  using TimePoint = Clock::time_point;
75 
77  std::string description;
79 };
80 
81 /**
82  * Construct alert
83  */
84 Alert MakeAlert(std::string_view category, std::string key, std::string description);
85 Alert MakeAlert(AlertId id, std::string description);
86 AlertId MakeAlertId(std::string_view category, std::string key);
87 
88 /**
89  * Comparison operator for Alert.
90  * @returns true if category and key both compares equal between lhs and rhs (description .
91  */
92 bool operator==(Alert const& lhs, Alert const& rhs) noexcept;
93 bool operator==(Alert const& lhs, AlertId const& rhs) noexcept;
94 bool operator==(AlertId const& lhs, Alert const& rhs) noexcept;
95 bool operator!=(Alert const& lhs, Alert const& rhs) noexcept;
96 
97 std::ostream& operator<<(std::ostream& os, Alert const& s);
98 std::ostream& operator<<(std::ostream& os, std::vector<Alert> const& s);
99 
100 /**
101  * Set alert.
102  * @param alerts Container of alert to modify.
103  * @param alert to set.
104  * @relatesalso Status
105  */
106 void SetAlert(std::vector<Alert>& alerts, Alert alert);
107 
108 /**
109  * Clear alert.
110  * @param alerts Container of alert to modify.
111  * @param alert to set.
112  * @returns true if there was an alert to clear, false otherwise.
113  * @relatesalso Status
114  */
115 bool ClearAlert(std::vector<Alert>& alerts, AlertId const& alert);
116 
117 /**
118  * Non observable status object that keeps stores status of data acquisition.
119  *
120  * It is also planned to be serializable to allow crash recovery from persistent storage.
121  *
122  * @ingroup daq_common_libdaq
123  */
124 struct Status {
125  using TimePoint = std::chrono::time_point<std::chrono::steady_clock>;
126 
127  Status() = default;
128  explicit Status(std::string id, std::string file_id) noexcept;
129  Status(
130  std::string id, std::string file_id, State state, bool error, TimePoint timestamp) noexcept;
131 
132  Status(Status&&) = default;
133  Status(Status const&) = default;
134  Status& operator=(Status&&) = default;
135  Status& operator=(Status const&) = default;
136 
137  bool operator==(Status const& rhs) const noexcept;
138  bool operator!=(Status const& rhs) const noexcept;
139 
140  std::string id;
141  std::string file_id;
143  bool error = false;
144  /**
145  * Active alerts
146  */
147  std::vector<Alert> alerts;
148 
149  /**
150  * Path to resulting data product.
151  */
152  std::string result;
154 };
155 
156 std::ostream& operator<<(std::ostream& os, Status const& s);
157 
158 /**
159  * Stores data acquisition status and allows subscription to status changes.
160  *
161  * DaqController instances will update ObservableStatus as changes occur.
162  *
163  * @ingroup daq_common_libdaq
164  */
166 public:
167  /**
168  * Defer signal changes until later time.
169  *
170  * This is mainly usedful to allow making multiple changes with only one signal being emitted.
171  *
172  * Effects:
173  * - Blocks sending signals until Deferrer expires (destroyed or manually reset).
174  * - When a deferrer is expired a signal will be emitted (if there are multiple deferrers each
175  * will emit a signal).
176  */
177  class DeferSignal {
178  public:
179  DeferSignal() = default;
180  DeferSignal(ObservableStatus* status);
181  ~DeferSignal() noexcept;
182  DeferSignal(DeferSignal&&) noexcept;
183  DeferSignal& operator=(DeferSignal&&) noexcept;
184  /**
185  * If object is valid
186  */
187  void Reset() noexcept;
188 
189  /**
190  * @returns true if object is valid.
191  */
192  bool IsValid() const noexcept {
193  return m_status != nullptr;
194  }
195 
196  private:
197  ObservableStatus* m_status = nullptr;
198  };
199 
200  /**
201  * Construct a new object
202  *
203  * @param id Data acquisition identifier.
204  */
205  explicit ObservableStatus(std::string id, std::string file_id) noexcept;
206  explicit ObservableStatus(Status status);
211 
212  bool operator==(ObservableStatus const& rhs) const noexcept;
213  bool operator!=(ObservableStatus const& rhs) const noexcept;
214 
215  bool operator==(Status const& rhs) const noexcept;
216  bool operator!=(Status const& rhs) const noexcept;
217 
218  /**
219  * Assign new status where the new status refers to the same DAQ.
220  *
221  * @param status New status to assign from.
222  * @throws std::invalid_argument if status.id is not equal to this->id.
223  */
224  ObservableStatus& operator=(Status const& status);
225 
226  ///@name Accessors
227  ///@{
228  /**
229  * @return Data acquisition identifier
230  */
231  std::string const& GetId() const noexcept;
232 
233  /**
234  * @return OLAS file id
235  */
236  std::string const& GetFileId() const noexcept;
237 
238  /**
239  * @return Data acquisition state
240  */
241  State GetState() const noexcept;
242 
243  /**
244  * @return Data acquisition error flag.
245  */
246  bool GetError() const noexcept;
247 
248  std::vector<Alert> const& GetAlerts() const noexcept;
249  ///@}
250 
251  ///@name Modifiers
252  ///@{
253  /**
254  * Set state of data acquisition.
255  *
256  * @param s New state
257  * @param error Optional new error flag value.
258  *
259  * @post Connected observers have been signalled.
260  */
261  void SetState(State s, std::optional<bool> error = std::nullopt) noexcept;
262 
263  /**
264  * Set error flag for data acquisition.
265  *
266  * @param error New error flag status.
267  *
268  * @post Connected observers have been signalled.
269  */
270  void SetError(bool error) noexcept;
271 
272  /**
273  * Set resulting data product path.
274  *
275  * @param result
276  */
277  void SetResult(std::string result);
278 
279  /**
280  * Set alert
281  *
282  * @note An existing alert with same ID will be overwritten.
283  *
284  * @param alert to set.
285  */
286  void SetAlert(Alert alert);
287 
288  /**
289  * Clear alert
290  *
291  * @param alert to clear.
292  */
293  void ClearAlert(AlertId const& alert);
294 
295  /**
296  * Connect observer that is invoked when state is modified.
297  *
298  * @param o Observer callable invoked on status changes (state or file changes)
299  * Observer must be invocable with signature `void(ObservableStatus const&)`.
300  *
301  * @return signal connection object that can be used to disconnect observer:
302  *
303  * @code
304  * auto c = status.ConnectObserver([](ObservableStatus const& s){});
305  * // later the connection object can be used to disconnect
306  * c.disconnect();
307  * @endcode
308  */
309  using Signal = boost::signals2::signal<void(ObservableStatus const&)>;
310  template <class Observer>
311  boost::signals2::connection ConnectObserver(Observer o) {
312  return m_signal.connect(std::move(o));
313  }
314  boost::signals2::connection ConnectStatus(Signal::slot_type const& slot) {
315  return m_signal.connect(slot);
316  }
317  /**
318  * Allow implicit conversion to non-observable status.
319  */
320  operator Status() const;
321  Status const& GetStatus() const noexcept;
322  ///@}
323 protected:
324  friend class DeferSignal;
325  /// Signal changes to observers
326  void SignalChanges(bool forced = false) noexcept;
327 
328  void EnableSignals() noexcept;
329  void DisableSignals() noexcept;
330 
331 private:
332  Status m_status;
333  // const Status should also be observable.
334  mutable Signal m_signal;
335  /**
336  * If positive there are instances of DeferSignal blocking signals
337  */
338  unsigned m_deferred_signals = 0;
339 };
340 
341 std::ostream& operator<<(std::ostream& os, ObservableStatus const& s);
342 
343 } // namespace daq
344 #endif // #ifndef OCM_DAQ_DAQ_STATUS_HPP_
Defer signal changes until later time.
Definition: status.hpp:177
void Reset() noexcept
If object is valid.
Definition: status.cpp:156
bool IsValid() const noexcept
Definition: status.hpp:192
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
boost::signals2::connection ConnectObserver(Observer o)
Connect observer that is invoked when state is modified.
Definition: status.hpp:311
State GetState() const noexcept
Definition: status.cpp:215
ObservableStatus(ObservableStatus const &)=delete
void SetError(bool error) noexcept
Set error flag for data acquisition.
Definition: status.cpp:236
ObservableStatus & operator=(ObservableStatus &&)=default
boost::signals2::signal< void(ObservableStatus const &)> Signal
Connect observer that is invoked when state is modified.
Definition: status.hpp:309
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
ObservableStatus(ObservableStatus &&)=default
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 & operator=(ObservableStatus const &)=delete
boost::signals2::connection ConnectStatus(Signal::slot_type const &slot)
Connect observer that is invoked when state is modified.
Definition: status.hpp:314
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
Contains declaration for DpPart.
Contains data structure for FITS keywords.
Declares daq::State and related functions.
constexpr std::string_view REQUEST
Request.
Definition: status.hpp:31
constexpr std::string_view TRANSFERRING_RSYNC
Failure during rsync source copy.
Definition: status.hpp:37
constexpr std::string_view MERGING_MERGE
Merging failed.
Definition: status.hpp:46
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.
Clock::time_point TimePoint
Definition: status.hpp:74
std::chrono::system_clock Clock
Definition: status.hpp:73
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
Non observable status object that keeps stores status of data acquisition.
Definition: status.hpp:124
Status & operator=(Status const &)=default
bool operator!=(Status const &rhs) const noexcept
Definition: status.cpp:122
Status & operator=(Status &&)=default
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
Status(Status const &)=default
Status(Status &&)=default
std::vector< Alert > alerts
Active alerts.
Definition: status.hpp:147
TimePoint timestamp
Definition: status.hpp:153
Status()=default