66{
70 return;
71 }
72
73
74 int recording_time_sec = 0;
75 if (cmdargs.contains("duration")) {
76 recording_time_sec = cmdargs["duration"];
77 } else {
80 }
81 if (recording_time_sec == 0) {
84 return;
85 }
86
88 [&](int duration) {
91 TLOG() <<
"Start recording for " << duration <<
" second(s)" << std::endl;
93 auto start_of_recording = std::chrono::high_resolution_clock::now();
94 auto current_time = start_of_recording;
96
97 const char* current_write_pointer = nullptr;
98 const char* start_of_buffer_pointer =
100 const char* current_end_pointer;
102
103 size_t bytes_written = 0;
104 size_t failed_writes = 0;
105
106 while (std::chrono::duration_cast<std::chrono::seconds>(current_time - start_of_recording).count() < duration) {
108 size_t considered_chunks_in_loop = 0;
109
110
111 {
114 }
116
117
118
119
123
124 current_time = std::chrono::high_resolution_clock::now();
125 continue;
126 }
128 size_t skipped_frames = 0;
129 while (reinterpret_cast<std::uintptr_t>(&(*begin)) % alignment_size) {
130 ++begin;
131 skipped_frames++;
132 if (!begin.good()) {
133
134
135 current_time = std::chrono::high_resolution_clock::now();
137 continue;
138 }
139 }
140 TLOG() <<
"Skipped " << skipped_frames <<
" frames";
141 current_write_pointer = reinterpret_cast<const char*>(&(*begin));
142 }
143
145
146
147 while (considered_chunks_in_loop < 100) {
148 auto iptr = reinterpret_cast<std::uintptr_t>(current_write_pointer);
149 if (iptr % alignment_size) {
150
151 TLOG() <<
"Error: Write pointer is not aligned";
152 }
153 bool failed_write = false;
154 if (current_write_pointer + chunk_size < current_end_pointer) {
155
156 failed_write |= !::write(
m_fd, current_write_pointer, chunk_size);
157 if (!failed_write) {
158 bytes_written += chunk_size;
159 }
160 current_write_pointer += chunk_size;
161 } else if (current_end_pointer < current_write_pointer) {
162 if (current_write_pointer + chunk_size < end_of_buffer_pointer) {
163
164 failed_write |= !::write(
m_fd, current_write_pointer, chunk_size);
165 if (!failed_write) {
166 bytes_written += chunk_size;
167 }
168 current_write_pointer += chunk_size;
169 } else {
170
171
172 fcntl(
m_fd, F_SETFL, O_CREAT | O_WRONLY);
173 failed_write |= !::write(
m_fd, current_write_pointer, end_of_buffer_pointer - current_write_pointer);
175 if (!failed_write) {
176 bytes_written += end_of_buffer_pointer - current_write_pointer;
177 }
178 current_write_pointer = start_of_buffer_pointer;
179 }
180 }
181
182 if (current_write_pointer == end_of_buffer_pointer) {
183 current_write_pointer = start_of_buffer_pointer;
184 }
185
186 if (failed_write) {
187 ++failed_writes;
189 }
190 considered_chunks_in_loop++;
191
194 start_of_buffer_pointer +
195 (((current_write_pointer - start_of_buffer_pointer) / ReadoutType::fixed_payload_size) *
196 ReadoutType::fixed_payload_size))
197 ->get_timestamp();
198 }
199 }
200 current_time = std::chrono::high_resolution_clock::now();
201 }
202
203
204 if (current_write_pointer != nullptr) {
205 const char* last_started_frame =
206 start_of_buffer_pointer +
207 (((current_write_pointer - start_of_buffer_pointer) / ReadoutType::fixed_payload_size) *
208 ReadoutType::fixed_payload_size);
209 if (last_started_frame != current_write_pointer) {
210 fcntl(
m_fd, F_SETFL, O_CREAT | O_WRONLY);
212 current_write_pointer,
213 (last_started_frame + ReadoutType::fixed_payload_size) - current_write_pointer)) {
215 } else {
216 bytes_written += (last_started_frame + ReadoutType::fixed_payload_size) - current_write_pointer;
217 }
218 }
219 }
221
223
224 TLOG() <<
"Stopped recording, wrote " << bytes_written <<
" bytes. Failed write count: " << failed_writes;
226 }, recording_time_sec);
227}
std::atomic< bool > m_recording
std::atomic< bool > m_cleanup_requested
std::atomic< uint64_t > m_next_timestamp_to_record
std::condition_variable m_cv
utilities::ReusableThread m_recording_thread
bool set_work(Function &&f, Args &&... args)
ReadoutType
Which type of readout to use for TriggerDecision and DataRequest.
void warning(const Issue &issue)