65{
69 return;
70 }
71
72
73 int recording_time_sec = 0;
74 if (cmdargs.contains("duration")) {
75 recording_time_sec = cmdargs["duration"];
76 } else {
79 }
80 if (recording_time_sec == 0) {
83 return;
84 }
85
87 [&](int duration) {
90 TLOG() <<
"Start recording for " << duration <<
" second(s)" << std::endl;
92 auto start_of_recording = std::chrono::high_resolution_clock::now();
93 auto current_time = start_of_recording;
95
96 const char* current_write_pointer = nullptr;
97 const char* start_of_buffer_pointer =
99 const char* current_end_pointer;
101
102 size_t bytes_written = 0;
103 size_t failed_writes = 0;
104
105 while (std::chrono::duration_cast<std::chrono::seconds>(current_time - start_of_recording).count() < duration) {
107 size_t considered_chunks_in_loop = 0;
108
109
110 {
113 }
115
116
117
118
122
123 current_time = std::chrono::high_resolution_clock::now();
124 continue;
125 }
127 size_t skipped_frames = 0;
128 while (reinterpret_cast<std::uintptr_t>(&(*begin)) % alignment_size) {
129 ++begin;
130 skipped_frames++;
131 if (!begin.good()) {
132
133
134 current_time = std::chrono::high_resolution_clock::now();
136 continue;
137 }
138 }
139 TLOG() <<
"Skipped " << skipped_frames <<
" frames";
140 current_write_pointer = reinterpret_cast<const char*>(&(*begin));
141 }
142
144
145
146 while (considered_chunks_in_loop < 100) {
147 auto iptr = reinterpret_cast<std::uintptr_t>(current_write_pointer);
148 if (iptr % alignment_size) {
149
150 TLOG() <<
"Error: Write pointer is not aligned";
151 }
152 bool failed_write = false;
153 if (current_write_pointer + chunk_size < current_end_pointer) {
154
155 failed_write |= !::write(
m_fd, current_write_pointer, chunk_size);
156 if (!failed_write) {
157 bytes_written += chunk_size;
158 }
159 current_write_pointer += chunk_size;
160 } else if (current_end_pointer < current_write_pointer) {
161 if (current_write_pointer + chunk_size < end_of_buffer_pointer) {
162
163 failed_write |= !::write(
m_fd, current_write_pointer, chunk_size);
164 if (!failed_write) {
165 bytes_written += chunk_size;
166 }
167 current_write_pointer += chunk_size;
168 } else {
169
170
171 fcntl(
m_fd, F_SETFL, O_CREAT | O_WRONLY);
172 failed_write |= !::write(
m_fd, current_write_pointer, end_of_buffer_pointer - current_write_pointer);
174 if (!failed_write) {
175 bytes_written += end_of_buffer_pointer - current_write_pointer;
176 }
177 current_write_pointer = start_of_buffer_pointer;
178 }
179 }
180
181 if (current_write_pointer == end_of_buffer_pointer) {
182 current_write_pointer = start_of_buffer_pointer;
183 }
184
185 if (failed_write) {
186 ++failed_writes;
188 }
189 considered_chunks_in_loop++;
190
193 start_of_buffer_pointer +
194 (((current_write_pointer - start_of_buffer_pointer) / ReadoutType::fixed_payload_size) *
195 ReadoutType::fixed_payload_size))
196 ->get_timestamp();
197 }
198 }
199 current_time = std::chrono::high_resolution_clock::now();
200 }
201
202
203 if (current_write_pointer != nullptr) {
204 const char* last_started_frame =
205 start_of_buffer_pointer +
206 (((current_write_pointer - start_of_buffer_pointer) / ReadoutType::fixed_payload_size) *
207 ReadoutType::fixed_payload_size);
208 if (last_started_frame != current_write_pointer) {
209 fcntl(
m_fd, F_SETFL, O_CREAT | O_WRONLY);
211 current_write_pointer,
212 (last_started_frame + ReadoutType::fixed_payload_size) - current_write_pointer)) {
214 } else {
215 bytes_written += (last_started_frame + ReadoutType::fixed_payload_size) - current_write_pointer;
216 }
217 }
218 }
220
222
223 TLOG() <<
"Stopped recording, wrote " << bytes_written <<
" bytes. Failed write count: " << failed_writes;
225 }, recording_time_sec);
226}
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)