RTC Toolkit 6.0.0
Loading...
Searching...
No Matches
eventRecordingUnit.hpp
Go to the documentation of this file.
1
11#ifndef RTCTK_COMPONENTFRAMEWORK_EVENTRECORDINGUNIT_HPP
12#define RTCTK_COMPONENTFRAMEWORK_EVENTRECORDINGUNIT_HPP
13
21
22#include <fmt/format.h>
23#include <numapp/numapolicies.hpp>
24#include <numapp/thread.hpp>
25#include <taiclock/taiClock.hpp>
26
27#include <cstdint>
28#include <exception>
29#include <string>
30#include <string_view>
31#include <thread>
32
34
42template <class OutputStage = std::ofstream>
44public:
45 using FilterMethod = std::function<bool(const JsonPayload&)>;
46
54 EventRecordingUnit(const std::string& comp_id,
55 const std::string& unit_id,
56 ServiceContainer& services,
57 FilterMethod input_filter = nullptr)
58 : RecordingUnit(comp_id, unit_id, "Event", services)
59 , m_event_service(services.Get<EventServiceIf>()) {
60 if (input_filter) {
61 m_input_filter = std::move(input_filter);
62 } else {
63 m_input_filter = [](const JsonPayload&) { return true; };
64 }
65
66 auto rtr_topic_path = DataPointPath(fmt::format(RTR_PATH_TOPIC_NAME, comp_id, unit_id));
67 m_topic_name = m_rtr.GetDataPoint<std::string>(rtr_topic_path);
68
69 auto oldb_topic_path = DataPointPath(fmt::format(OLDB_PATH_TOPIC_NAME, comp_id, unit_id));
70 m_oldb.CreateDataPoint<std::string>(oldb_topic_path);
71 m_oldb.SetDataPoint<std::string>(oldb_topic_path, m_topic_name);
72
73 const InfluxTagMap base_tags = {
74 {"unit_id", unit_id},
75 {"topic_name", m_topic_name},
76 };
77
78 m_samples_written_reg = m_metrics.AddCounter(
79 &m_samples_written,
81 unit_id + "/samples_written", "Samples written", base_tags, "samples_written"));
82 }
83
85 m_stop = true;
86 if (m_process_thread.joinable()) {
87 m_process_thread.join();
88 }
89 SetStopped();
90 }
91
96 void Prepare(const std::filesystem::path& file_path) override {
97 if (not IsEnabled()) {
98 return;
99 }
100
103 "EventRecorder tried to go from non-STOPPED State to PREPARING");
104
105 m_subscriber.reset();
106 m_subscriber = m_event_service.MakeSubscriber(m_topic_name);
107
108 m_file_path = file_path / (GetId() + ".jsonl");
109
110 auto policies = numapp::NumaPolicies();
111 m_process_thread =
112 numapp::MakeThread(m_unit_id.substr(0, 15), policies, [&]() { return Process(); });
113 }
114
117 void Start() override {
118 m_start = true;
119 }
120
124 std::vector<std::filesystem::path> Stop() override {
125 m_stop = true;
126 if (m_process_thread.joinable()) {
127 m_process_thread.join();
128 }
129 SetStopped();
130 std::vector<std::filesystem::path> files;
131 if (m_file_path) {
132 files.push_back(*m_file_path);
133 }
134 return files;
135 }
136
137private:
138 void Process() {
139 using namespace std::chrono_literals;
140
141 OutputStage output;
142
143 try {
144 output.open(*m_file_path, std::ios::out);
145 m_samples_written.Store(0);
146
149 "Event recorder was not in PREPARING when trying to go to IDLE");
150
151 while (m_stop == false) {
152 switch (GetState()) {
153 case State::IDLE:
154 if (m_start) {
157 "Event recorder was not in IDLE when trying to go to WAITING");
158 break;
159 }
160 std::this_thread::sleep_for(1ms);
161 break;
162 case State::WAITING:
163 if (not HasLeaders() or (HasLeaders() and HasFirstLeaderStarted())) {
164 m_subscriber->Subscribe([&](const JsonPayload& ev) {
165 if (GetState() == State::RUNNING) {
166 try {
167 if (m_input_filter(ev)) {
168 output << ev << "\n";
169 m_samples_written++;
170 }
171 } catch (...) {
172 SetFailed(std::current_exception());
173 return;
174 }
175 }
176 });
177
180 "Event recorder was not in WAITING when trying to go to RUNNING");
181 break;
182 }
183 std::this_thread::sleep_for(1ms);
184 break;
185 case State::RUNNING:
186 if (HasLeaders() and HasLastLeaderFinished()) {
189 "Event recorder was not running when trying to go to finish");
190 break;
191 }
192 std::this_thread::sleep_for(1ms);
193 break;
194 default:
195 std::this_thread::sleep_for(1ms);
196 }
197 }
198
199 m_subscriber->Unsubscribe();
200 // the actual STOPPED state will be set by the Stop function
201 m_start = false;
202 m_stop = false;
204 } catch (...) {
205 m_subscriber->Unsubscribe();
206 m_start = false;
207 m_stop = false;
208 SetFailed(std::current_exception());
210 }
211 }
212
213 EventServiceIf& m_event_service;
214 std::unique_ptr<EventSubscriberIf> m_subscriber;
215
216 FilterMethod m_input_filter;
217
218 std::string m_topic_name;
219
220 perfc::CounterI64 m_samples_written;
221 perfc::ScopedRegistration m_samples_written_reg;
222
223 std::atomic<bool> m_start = false;
224 std::atomic<bool> m_stop = false;
225 std::thread m_process_thread;
226
230 inline static constexpr std::string_view RTR_PATH_TOPIC_NAME =
231 "/{}/static/rec_units/{}/topic_name";
232
236 inline static constexpr std::string_view OLDB_PATH_TOPIC_NAME = "/{}/rec_units/{}/topic_name";
237};
238
239} // namespace rtctk::componentFramework
240
241#endif // RTCTK_COMPONENTFRAMEWORK_EVENTRECORDINGUNIT_HPP
Defines auxiliary information associated with each counter registered with ComponentMetricsIf.
Definition componentMetricsIf.hpp:48
This class provides a wrapper for a data point path.
Definition dataPointPath.hpp:76
~EventRecordingUnit() override
Definition eventRecordingUnit.hpp:84
std::function< bool(const JsonPayload &)> FilterMethod
Definition eventRecordingUnit.hpp:45
EventRecordingUnit(const std::string &comp_id, const std::string &unit_id, ServiceContainer &services, FilterMethod input_filter=nullptr)
Create a new recording unit.
Definition eventRecordingUnit.hpp:54
std::vector< std::filesystem::path > Stop() override
Stop the recording and wait for it's termination.
Definition eventRecordingUnit.hpp:124
void Prepare(const std::filesystem::path &file_path) override
Prepare the recording.
Definition eventRecordingUnit.hpp:96
void Start() override
Start the recording.
Definition eventRecordingUnit.hpp:117
Interface class for providing pub/sub facilities for JSON events.
Definition eventServiceIf.hpp:28
Helper class for passing tags in Telegraf.
Definition influxTagMap.hpp:26
bool HasLeaders()
Check if this unit is following any leaders.
Definition recordingUnit.cpp:106
OldbIf & m_oldb
Definition recordingUnit.hpp:177
RecordingUnit(const std::string &comp_id, const std::string &unit_id, const std::string &unit_type, ServiceContainer &services)
Create a new RecordingIngestion.
Definition recordingUnit.cpp:18
bool HasLastLeaderFinished()
This function is used to determine if this unit should stop recording when waiting for leaders.
Definition recordingUnit.cpp:115
bool HasFirstLeaderStarted()
This function is used to determine if this unit should start recording when waiting for leaders.
Definition recordingUnit.cpp:110
void SetFailed(const std::exception_ptr &exception)
Set the unit into failed state, with the given exception.
Definition recordingUnit.cpp:151
bool IsEnabled() const
Checks whether the Recording Unit is enabled.
Definition recordingUnit.cpp:167
std::string m_unit_id
Definition recordingUnit.hpp:175
void ResetLeaderStates()
Definition recordingUnit.cpp:120
ComponentMetricsIf & m_metrics
Definition recordingUnit.hpp:178
const std::string & GetId() const
Get the unit_it of this RecordingUnit.
Definition recordingUnit.cpp:129
RuntimeRepoIf & m_rtr
Definition recordingUnit.hpp:176
void SetStopped()
Set the Unit state to STOPPED independent of the current State.
Definition recordingUnit.cpp:158
@ STOPPED
Definition recordingUnit.hpp:52
@ WAITING
Definition recordingUnit.hpp:52
@ FINISHED
Definition recordingUnit.hpp:52
@ RUNNING
Definition recordingUnit.hpp:52
@ IDLE
Definition recordingUnit.hpp:52
@ PREPARING
Definition recordingUnit.hpp:52
State GetState() const
Get the current state of the Recording Unit.
Definition recordingUnit.cpp:163
bool SetState(State state, State precondition)
Sets the new state, only goes to new state, if expected state matches.
Definition recordingUnit.cpp:133
std::optional< std::filesystem::path > m_file_path
Definition recordingUnit.hpp:179
Container class that holds services of any type.
Definition serviceContainer.hpp:38
Header file for ComponentMetricsIf.
Framework-provided event definitions.
Low-level interface of the event service.
Provides macros and utilities for exception handling.
FitsRecorder allows to write ColumnData to into fits files in a specified directory.
Definition commandReplier.cpp:21
nlohmann::json JsonPayload
Type requirements:
Definition jsonPayload.hpp:24
FitsRecorder allows to write ColumnData to into fits files in a specified directory.
Abstract base class defining functionality common to all recording units.