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