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