Commit | Line | Data |
---|---|---|
15fe47e0 | 1 | /* |
0235b0db | 2 | * SPDX-License-Identifier: MIT |
15fe47e0 | 3 | * |
0235b0db | 4 | * Copyright 2019 Philippe Proulx <pproulx@efficios.com> |
15fe47e0 PP |
5 | */ |
6 | ||
c802cacb | 7 | #include <glib.h> |
c802cacb SM |
8 | #include <stdio.h> |
9 | ||
10 | #include <babeltrace2/babeltrace.h> | |
11 | ||
578e048b | 12 | #include "common/assert.h" |
3c20ac12 | 13 | #include "cpp-common/vendor/fmt/format.h" |
578e048b | 14 | #include "ctfser/ctfser.h" |
c802cacb | 15 | |
ce67f561 | 16 | #include "plugins/common/param-validation/param-validation.h" |
15fe47e0 | 17 | |
087cd0f5 | 18 | #include "fs-sink-ctf-meta.hpp" |
c802cacb SM |
19 | #include "fs-sink-stream.hpp" |
20 | #include "fs-sink-trace.hpp" | |
21 | #include "fs-sink.hpp" | |
c802cacb | 22 | #include "translate-trace-ir-to-ctf-ir.hpp" |
15fe47e0 | 23 | |
4164020e | 24 | static const char * const in_port_name = "in"; |
15fe47e0 | 25 | |
4164020e SM |
26 | static bt_component_class_initialize_method_status |
27 | ensure_output_dir_exists(struct fs_sink_comp *fs_sink) | |
15fe47e0 | 28 | { |
4164020e SM |
29 | bt_component_class_initialize_method_status status = |
30 | BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_OK; | |
31 | int ret; | |
32 | ||
33 | ret = g_mkdir_with_parents(fs_sink->output_dir_path->str, 0755); | |
34 | if (ret) { | |
3c20ac12 SM |
35 | BT_CPPLOGE_ERRNO_APPEND_CAUSE_SPEC( |
36 | fs_sink->logger, "Cannot create directories for output directory", | |
37 | ": output-dir-path=\"{}\"", fs_sink->output_dir_path->str); | |
4164020e SM |
38 | status = BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_ERROR; |
39 | goto end; | |
40 | } | |
15fe47e0 PP |
41 | |
42 | end: | |
4164020e | 43 | return status; |
15fe47e0 PP |
44 | } |
45 | ||
087cd0f5 | 46 | static bt_param_validation_map_value_entry_descr fs_sink_params_descr[] = { |
88730e42 SM |
47 | {"path", BT_PARAM_VALIDATION_MAP_VALUE_ENTRY_MANDATORY, |
48 | bt_param_validation_value_descr::makeString()}, | |
49 | {"assume-single-trace", BT_PARAM_VALIDATION_MAP_VALUE_ENTRY_OPTIONAL, | |
50 | bt_param_validation_value_descr::makeBool()}, | |
51 | {"ignore-discarded-events", BT_PARAM_VALIDATION_MAP_VALUE_ENTRY_OPTIONAL, | |
52 | bt_param_validation_value_descr::makeBool()}, | |
53 | {"ignore-discarded-packets", BT_PARAM_VALIDATION_MAP_VALUE_ENTRY_OPTIONAL, | |
54 | bt_param_validation_value_descr::makeBool()}, | |
55 | {"quiet", BT_PARAM_VALIDATION_MAP_VALUE_ENTRY_OPTIONAL, | |
56 | bt_param_validation_value_descr::makeBool()}, | |
4164020e SM |
57 | BT_PARAM_VALIDATION_MAP_VALUE_ENTRY_END}; |
58 | ||
59 | static bt_component_class_initialize_method_status configure_component(struct fs_sink_comp *fs_sink, | |
60 | const bt_value *params) | |
15fe47e0 | 61 | { |
4164020e SM |
62 | bt_component_class_initialize_method_status status; |
63 | const bt_value *value; | |
64 | enum bt_param_validation_status validation_status; | |
65 | gchar *validation_error; | |
66 | ||
67 | validation_status = | |
68 | bt_param_validation_validate(params, fs_sink_params_descr, &validation_error); | |
69 | if (validation_status == BT_PARAM_VALIDATION_STATUS_VALIDATION_ERROR) { | |
70 | status = BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_ERROR; | |
3c20ac12 | 71 | BT_CPPLOGE_APPEND_CAUSE_SPEC(fs_sink->logger, "{}", validation_error); |
4164020e SM |
72 | goto end; |
73 | } else if (validation_status == BT_PARAM_VALIDATION_STATUS_MEMORY_ERROR) { | |
74 | status = BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_MEMORY_ERROR; | |
75 | goto end; | |
76 | } | |
77 | ||
78 | value = bt_value_map_borrow_entry_value_const(params, "path"); | |
79 | g_string_assign(fs_sink->output_dir_path, bt_value_string_get(value)); | |
80 | ||
81 | value = bt_value_map_borrow_entry_value_const(params, "assume-single-trace"); | |
82 | if (value) { | |
83 | fs_sink->assume_single_trace = (bool) bt_value_bool_get(value); | |
84 | } | |
85 | ||
86 | value = bt_value_map_borrow_entry_value_const(params, "ignore-discarded-events"); | |
87 | if (value) { | |
88 | fs_sink->ignore_discarded_events = (bool) bt_value_bool_get(value); | |
89 | } | |
90 | ||
91 | value = bt_value_map_borrow_entry_value_const(params, "ignore-discarded-packets"); | |
92 | if (value) { | |
93 | fs_sink->ignore_discarded_packets = (bool) bt_value_bool_get(value); | |
94 | } | |
95 | ||
96 | value = bt_value_map_borrow_entry_value_const(params, "quiet"); | |
97 | if (value) { | |
98 | fs_sink->quiet = (bool) bt_value_bool_get(value); | |
99 | } | |
100 | ||
101 | status = BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_OK; | |
ce67f561 | 102 | |
15fe47e0 | 103 | end: |
4164020e SM |
104 | g_free(validation_error); |
105 | return status; | |
15fe47e0 PP |
106 | } |
107 | ||
4164020e | 108 | static void destroy_fs_sink_comp(struct fs_sink_comp *fs_sink) |
15fe47e0 | 109 | { |
4164020e SM |
110 | if (!fs_sink) { |
111 | goto end; | |
112 | } | |
15fe47e0 | 113 | |
4164020e SM |
114 | if (fs_sink->output_dir_path) { |
115 | g_string_free(fs_sink->output_dir_path, TRUE); | |
116 | fs_sink->output_dir_path = NULL; | |
117 | } | |
15fe47e0 | 118 | |
4164020e SM |
119 | if (fs_sink->traces) { |
120 | g_hash_table_destroy(fs_sink->traces); | |
121 | fs_sink->traces = NULL; | |
122 | } | |
15fe47e0 | 123 | |
4164020e | 124 | BT_MESSAGE_ITERATOR_PUT_REF_AND_RESET(fs_sink->upstream_iter); |
150640e8 | 125 | delete fs_sink; |
15fe47e0 PP |
126 | |
127 | end: | |
4164020e | 128 | return; |
15fe47e0 PP |
129 | } |
130 | ||
5bcd9f04 SM |
131 | bt_component_class_initialize_method_status ctf_fs_sink_init(bt_self_component_sink *self_comp_sink, |
132 | bt_self_component_sink_configuration *, | |
133 | const bt_value *params, void *) | |
15fe47e0 | 134 | { |
4164020e SM |
135 | bt_component_class_initialize_method_status status; |
136 | bt_self_component_add_port_status add_port_status; | |
137 | struct fs_sink_comp *fs_sink = NULL; | |
138 | bt_self_component *self_comp = bt_self_component_sink_as_self_component(self_comp_sink); | |
4164020e | 139 | |
3c20ac12 | 140 | fs_sink = new fs_sink_comp {bt2::SelfSinkComponent {self_comp_sink}}; |
4164020e SM |
141 | fs_sink->output_dir_path = g_string_new(NULL); |
142 | status = configure_component(fs_sink, params); | |
143 | if (status != BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_OK) { | |
144 | /* configure_component() logs errors */ | |
145 | goto end; | |
146 | } | |
147 | ||
148 | if (fs_sink->assume_single_trace && | |
149 | g_file_test(fs_sink->output_dir_path->str, G_FILE_TEST_EXISTS)) { | |
3c20ac12 SM |
150 | BT_CPPLOGE_APPEND_CAUSE_SPEC( |
151 | fs_sink->logger, "Single trace mode, but output path exists: output-path=\"{}\"", | |
152 | fs_sink->output_dir_path->str); | |
4164020e SM |
153 | status = BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_ERROR; |
154 | goto end; | |
155 | } | |
156 | ||
157 | status = ensure_output_dir_exists(fs_sink); | |
158 | if (status != BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_OK) { | |
159 | /* ensure_output_dir_exists() logs errors */ | |
160 | goto end; | |
161 | } | |
162 | ||
163 | fs_sink->traces = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, | |
164 | (GDestroyNotify) fs_sink_trace_destroy); | |
165 | if (!fs_sink->traces) { | |
3c20ac12 | 166 | BT_CPPLOGE_APPEND_CAUSE_SPEC(fs_sink->logger, "Failed to allocate one GHashTable."); |
4164020e SM |
167 | status = BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_MEMORY_ERROR; |
168 | goto end; | |
169 | } | |
170 | ||
171 | add_port_status = | |
172 | bt_self_component_sink_add_input_port(self_comp_sink, in_port_name, NULL, NULL); | |
173 | if (add_port_status != BT_SELF_COMPONENT_ADD_PORT_STATUS_OK) { | |
174 | status = (bt_component_class_initialize_method_status) add_port_status; | |
3c20ac12 | 175 | BT_CPPLOGE_APPEND_CAUSE_SPEC(fs_sink->logger, "Failed to add input port."); |
4164020e SM |
176 | goto end; |
177 | } | |
178 | ||
179 | bt_self_component_set_data(self_comp, fs_sink); | |
15fe47e0 PP |
180 | |
181 | end: | |
4164020e SM |
182 | if (status != BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_OK) { |
183 | destroy_fs_sink_comp(fs_sink); | |
184 | } | |
15fe47e0 | 185 | |
4164020e | 186 | return status; |
15fe47e0 PP |
187 | } |
188 | ||
4164020e SM |
189 | static inline struct fs_sink_stream *borrow_stream(struct fs_sink_comp *fs_sink, |
190 | const bt_stream *ir_stream) | |
15fe47e0 | 191 | { |
4164020e SM |
192 | const bt_trace *ir_trace = bt_stream_borrow_trace_const(ir_stream); |
193 | struct fs_sink_trace *trace; | |
194 | struct fs_sink_stream *stream = NULL; | |
195 | ||
196 | trace = (fs_sink_trace *) g_hash_table_lookup(fs_sink->traces, ir_trace); | |
197 | if (G_UNLIKELY(!trace)) { | |
198 | if (fs_sink->assume_single_trace && g_hash_table_size(fs_sink->traces) > 0) { | |
3c20ac12 SM |
199 | BT_CPPLOGE_APPEND_CAUSE_SPEC(fs_sink->logger, |
200 | "Single trace mode, but getting more than one trace: " | |
201 | "stream-name=\"{}\"", | |
202 | bt2c::maybeNull(bt_stream_get_name(ir_stream))); | |
4164020e SM |
203 | goto end; |
204 | } | |
205 | ||
206 | trace = fs_sink_trace_create(fs_sink, ir_trace); | |
207 | if (!trace) { | |
208 | goto end; | |
209 | } | |
210 | } | |
211 | ||
212 | stream = (fs_sink_stream *) g_hash_table_lookup(trace->streams, ir_stream); | |
213 | if (G_UNLIKELY(!stream)) { | |
214 | stream = fs_sink_stream_create(trace, ir_stream); | |
215 | if (!stream) { | |
216 | goto end; | |
217 | } | |
218 | } | |
15fe47e0 PP |
219 | |
220 | end: | |
4164020e | 221 | return stream; |
15fe47e0 PP |
222 | } |
223 | ||
4164020e SM |
224 | static inline bt_component_class_sink_consume_method_status |
225 | handle_event_msg(struct fs_sink_comp *fs_sink, const bt_message *msg) | |
15fe47e0 | 226 | { |
4164020e SM |
227 | int ret; |
228 | bt_component_class_sink_consume_method_status status = | |
229 | BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_OK; | |
230 | const bt_event *ir_event = bt_message_event_borrow_event_const(msg); | |
231 | const bt_stream *ir_stream = bt_event_borrow_stream_const(ir_event); | |
232 | struct fs_sink_stream *stream; | |
233 | struct fs_sink_ctf_event_class *ec = NULL; | |
234 | const bt_clock_snapshot *cs = NULL; | |
235 | ||
236 | stream = borrow_stream(fs_sink, ir_stream); | |
237 | if (G_UNLIKELY(!stream)) { | |
3c20ac12 | 238 | BT_CPPLOGE_APPEND_CAUSE_SPEC(fs_sink->logger, "Failed to borrow stream."); |
4164020e SM |
239 | status = BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_ERROR; |
240 | goto end; | |
241 | } | |
242 | ||
243 | ret = try_translate_event_class_trace_ir_to_ctf_ir(fs_sink, stream->sc, | |
244 | bt_event_borrow_class_const(ir_event), &ec); | |
245 | if (ret) { | |
3c20ac12 | 246 | BT_CPPLOGE_APPEND_CAUSE_SPEC(fs_sink->logger, "Failed to translate event class to CTF IR."); |
4164020e SM |
247 | status = BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_ERROR; |
248 | goto end; | |
249 | } | |
250 | ||
251 | BT_ASSERT_DBG(ec); | |
252 | ||
253 | if (stream->sc->default_clock_class) { | |
254 | cs = bt_message_event_borrow_default_clock_snapshot_const(msg); | |
255 | } | |
256 | ||
257 | /* | |
258 | * If this event's stream does not support packets, then we | |
259 | * lazily create artificial packets. | |
260 | * | |
261 | * The size of an artificial packet is arbitrarily at least | |
262 | * 4 MiB (it usually is greater because we close it when | |
263 | * comes the time to write a new event and the packet's content | |
264 | * size is >= 4 MiB), except the last one which can be smaller. | |
265 | */ | |
266 | if (G_UNLIKELY(!stream->sc->has_packets)) { | |
267 | if (stream->packet_state.is_open && | |
268 | bt_ctfser_get_offset_in_current_packet_bits(&stream->ctfser) / 8 >= 4 * 1024 * 1024) { | |
269 | /* | |
270 | * Stream's current packet is larger than 4 MiB: | |
271 | * close it. A new packet will be opened just | |
272 | * below. | |
273 | */ | |
274 | ret = fs_sink_stream_close_packet(stream, NULL); | |
275 | if (ret) { | |
3c20ac12 | 276 | BT_CPPLOGE_APPEND_CAUSE_SPEC(fs_sink->logger, "Failed to close packet."); |
4164020e SM |
277 | status = BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_ERROR; |
278 | goto end; | |
279 | } | |
280 | } | |
281 | ||
282 | if (!stream->packet_state.is_open) { | |
283 | /* Stream's packet is not currently opened: open it */ | |
284 | ret = fs_sink_stream_open_packet(stream, NULL, NULL); | |
285 | if (ret) { | |
3c20ac12 | 286 | BT_CPPLOGE_APPEND_CAUSE_SPEC(fs_sink->logger, "Failed to open packet."); |
4164020e SM |
287 | status = BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_ERROR; |
288 | goto end; | |
289 | } | |
290 | } | |
291 | } | |
292 | ||
293 | BT_ASSERT_DBG(stream->packet_state.is_open); | |
294 | ret = fs_sink_stream_write_event(stream, cs, ir_event, ec); | |
295 | if (G_UNLIKELY(ret)) { | |
3c20ac12 | 296 | BT_CPPLOGE_APPEND_CAUSE_SPEC(fs_sink->logger, "Failed to write event."); |
4164020e SM |
297 | status = BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_ERROR; |
298 | goto end; | |
299 | } | |
15fe47e0 PP |
300 | |
301 | end: | |
4164020e | 302 | return status; |
15fe47e0 PP |
303 | } |
304 | ||
4164020e SM |
305 | static inline bt_component_class_sink_consume_method_status |
306 | handle_packet_beginning_msg(struct fs_sink_comp *fs_sink, const bt_message *msg) | |
15fe47e0 | 307 | { |
4164020e SM |
308 | int ret; |
309 | bt_component_class_sink_consume_method_status status = | |
310 | BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_OK; | |
311 | const bt_packet *ir_packet = bt_message_packet_beginning_borrow_packet_const(msg); | |
312 | const bt_stream *ir_stream = bt_packet_borrow_stream_const(ir_packet); | |
313 | struct fs_sink_stream *stream; | |
314 | const bt_clock_snapshot *cs = NULL; | |
315 | ||
316 | stream = borrow_stream(fs_sink, ir_stream); | |
317 | if (G_UNLIKELY(!stream)) { | |
3c20ac12 | 318 | BT_CPPLOGE_APPEND_CAUSE_SPEC(fs_sink->logger, "Failed to borrow stream."); |
4164020e SM |
319 | status = BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_ERROR; |
320 | goto end; | |
321 | } | |
322 | ||
323 | if (stream->sc->packets_have_ts_begin) { | |
324 | cs = bt_message_packet_beginning_borrow_default_clock_snapshot_const(msg); | |
325 | BT_ASSERT(cs); | |
326 | } | |
327 | ||
328 | /* | |
329 | * If we previously received a discarded events message with | |
330 | * a time range, make sure that its beginning time matches what's | |
331 | * expected for CTF 1.8, that is: | |
332 | * | |
333 | * * Its beginning time is the previous packet's end | |
334 | * time (or the current packet's beginning time if | |
335 | * this is the first packet). | |
336 | * | |
337 | * We check this here instead of in handle_packet_end_msg() | |
338 | * because we want to catch any incompatible message as early as | |
339 | * possible to report the error. | |
340 | * | |
341 | * Validation of the discarded events message's end time is | |
342 | * performed in handle_packet_end_msg(). | |
343 | */ | |
344 | if (stream->discarded_events_state.in_range) { | |
345 | uint64_t expected_cs; | |
346 | ||
347 | /* | |
348 | * `stream->discarded_events_state.in_range` is only set | |
349 | * when the stream class's discarded events have a time | |
350 | * range. | |
351 | * | |
352 | * It is required that the packet beginning and end | |
353 | * messages for this stream class have times when | |
354 | * discarded events have a time range. | |
355 | */ | |
356 | BT_ASSERT(stream->sc->discarded_events_has_ts); | |
357 | BT_ASSERT(stream->sc->packets_have_ts_begin); | |
358 | BT_ASSERT(stream->sc->packets_have_ts_end); | |
359 | ||
360 | if (stream->prev_packet_state.end_cs == UINT64_C(-1)) { | |
361 | /* We're opening the first packet */ | |
362 | expected_cs = bt_clock_snapshot_get_value(cs); | |
363 | } else { | |
364 | expected_cs = stream->prev_packet_state.end_cs; | |
365 | } | |
366 | ||
367 | if (stream->discarded_events_state.beginning_cs != expected_cs) { | |
3c20ac12 SM |
368 | BT_CPPLOGE_APPEND_CAUSE_SPEC( |
369 | fs_sink->logger, | |
370 | "Incompatible discarded events message: " | |
371 | "unexpected beginning time: " | |
372 | "beginning-cs-val={}, " | |
373 | "expected-beginning-cs-val={}, " | |
374 | "stream-id={}, stream-name=\"{}\", " | |
375 | "trace-name=\"{}\", path=\"{}/{}\"", | |
376 | stream->discarded_events_state.beginning_cs, expected_cs, | |
377 | bt_stream_get_id(ir_stream), bt2c::maybeNull(bt_stream_get_name(ir_stream)), | |
378 | bt2c::maybeNull(bt_trace_get_name(bt_stream_borrow_trace_const(ir_stream))), | |
379 | stream->trace->path->str, stream->file_name->str); | |
4164020e SM |
380 | status = BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_ERROR; |
381 | goto end; | |
382 | } | |
383 | } | |
384 | ||
385 | /* | |
386 | * If we previously received a discarded packets message with a | |
387 | * time range, make sure that its beginning and end times match | |
388 | * what's expected for CTF 1.8, that is: | |
389 | * | |
390 | * * Its beginning time is the previous packet's end time. | |
391 | * | |
392 | * * Its end time is the current packet's beginning time. | |
393 | */ | |
394 | if (stream->discarded_packets_state.in_range) { | |
395 | uint64_t expected_end_cs; | |
396 | ||
397 | /* | |
398 | * `stream->discarded_packets_state.in_range` is only | |
399 | * set when the stream class's discarded packets have a | |
400 | * time range. | |
401 | * | |
402 | * It is required that the packet beginning and end | |
403 | * messages for this stream class have times when | |
404 | * discarded packets have a time range. | |
405 | */ | |
406 | BT_ASSERT(stream->sc->discarded_packets_has_ts); | |
407 | BT_ASSERT(stream->sc->packets_have_ts_begin); | |
408 | BT_ASSERT(stream->sc->packets_have_ts_end); | |
409 | ||
410 | /* | |
411 | * It is not supported to have a discarded packets | |
412 | * message _before_ the first packet: we cannot validate | |
413 | * that its beginning time is compatible with CTF 1.8 in | |
414 | * this case. | |
415 | */ | |
416 | if (stream->prev_packet_state.end_cs == UINT64_C(-1)) { | |
3c20ac12 SM |
417 | BT_CPPLOGE_APPEND_CAUSE_SPEC( |
418 | fs_sink->logger, | |
419 | "Incompatible discarded packets message " | |
420 | "occurring before the stream's first packet: " | |
421 | "stream-id={}, stream-name=\"{}\", " | |
422 | "trace-name=\"{}\", path=\"{}/{}\"", | |
423 | bt_stream_get_id(ir_stream), bt2c::maybeNull(bt_stream_get_name(ir_stream)), | |
424 | bt2c::maybeNull(bt_trace_get_name(bt_stream_borrow_trace_const(ir_stream))), | |
425 | stream->trace->path->str, stream->file_name->str); | |
4164020e SM |
426 | status = BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_ERROR; |
427 | goto end; | |
428 | } | |
429 | ||
430 | if (stream->discarded_packets_state.beginning_cs != stream->prev_packet_state.end_cs) { | |
3c20ac12 SM |
431 | BT_CPPLOGE_APPEND_CAUSE_SPEC( |
432 | fs_sink->logger, | |
433 | "Incompatible discarded packets message: " | |
434 | "unexpected beginning time: " | |
435 | "beginning-cs-val={}, " | |
436 | "expected-beginning-cs-val={}, " | |
437 | "stream-id={}, stream-name=\"{}\", " | |
438 | "trace-name=\"{}\", path=\"{}/{}\"", | |
439 | stream->discarded_packets_state.beginning_cs, stream->prev_packet_state.end_cs, | |
440 | bt_stream_get_id(ir_stream), bt2c::maybeNull(bt_stream_get_name(ir_stream)), | |
441 | bt2c::maybeNull(bt_trace_get_name(bt_stream_borrow_trace_const(ir_stream))), | |
442 | stream->trace->path->str, stream->file_name->str); | |
4164020e SM |
443 | status = BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_ERROR; |
444 | goto end; | |
445 | } | |
446 | ||
447 | expected_end_cs = bt_clock_snapshot_get_value(cs); | |
448 | ||
449 | if (stream->discarded_packets_state.end_cs != expected_end_cs) { | |
3c20ac12 SM |
450 | BT_CPPLOGE_APPEND_CAUSE_SPEC( |
451 | fs_sink->logger, | |
452 | "Incompatible discarded packets message: " | |
453 | "unexpected end time: " | |
454 | "end-cs-val={}, " | |
455 | "expected-end-cs-val={}, " | |
456 | "stream-id={}, stream-name=\"{}\", " | |
457 | "trace-name=\"{}\", path=\"{}/{}\"", | |
458 | stream->discarded_packets_state.end_cs, expected_end_cs, | |
459 | bt_stream_get_id(ir_stream), bt2c::maybeNull(bt_stream_get_name(ir_stream)), | |
460 | bt2c::maybeNull(bt_trace_get_name(bt_stream_borrow_trace_const(ir_stream))), | |
461 | stream->trace->path->str, stream->file_name->str); | |
4164020e SM |
462 | status = BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_ERROR; |
463 | goto end; | |
464 | } | |
465 | } | |
466 | ||
467 | /* | |
468 | * We're not in a discarded packets time range anymore since we | |
469 | * require that the discarded packets time ranges go from one | |
470 | * packet's end time to the next packet's beginning time, and | |
471 | * we're handling a packet beginning message here. | |
472 | */ | |
473 | stream->discarded_packets_state.in_range = false; | |
474 | ||
475 | ret = fs_sink_stream_open_packet(stream, cs, ir_packet); | |
476 | if (ret) { | |
3c20ac12 | 477 | BT_CPPLOGE_APPEND_CAUSE_SPEC(fs_sink->logger, "Failed to open packet."); |
4164020e SM |
478 | status = BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_ERROR; |
479 | goto end; | |
480 | } | |
15fe47e0 PP |
481 | |
482 | end: | |
4164020e | 483 | return status; |
15fe47e0 PP |
484 | } |
485 | ||
4164020e SM |
486 | static inline bt_component_class_sink_consume_method_status |
487 | handle_packet_end_msg(struct fs_sink_comp *fs_sink, const bt_message *msg) | |
15fe47e0 | 488 | { |
4164020e SM |
489 | int ret; |
490 | bt_component_class_sink_consume_method_status status = | |
491 | BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_OK; | |
492 | const bt_packet *ir_packet = bt_message_packet_end_borrow_packet_const(msg); | |
493 | const bt_stream *ir_stream = bt_packet_borrow_stream_const(ir_packet); | |
494 | struct fs_sink_stream *stream; | |
495 | const bt_clock_snapshot *cs = NULL; | |
496 | ||
497 | stream = borrow_stream(fs_sink, ir_stream); | |
498 | if (G_UNLIKELY(!stream)) { | |
3c20ac12 | 499 | BT_CPPLOGE_APPEND_CAUSE_SPEC(fs_sink->logger, "Failed to borrow stream."); |
4164020e SM |
500 | status = BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_ERROR; |
501 | goto end; | |
502 | } | |
503 | ||
504 | if (stream->sc->packets_have_ts_end) { | |
505 | cs = bt_message_packet_end_borrow_default_clock_snapshot_const(msg); | |
506 | BT_ASSERT(cs); | |
507 | } | |
508 | ||
509 | /* | |
510 | * If we previously received a discarded events message with | |
511 | * a time range, make sure that its end time matches what's | |
512 | * expected for CTF 1.8, that is: | |
513 | * | |
514 | * * Its end time is the current packet's end time. | |
515 | * | |
516 | * Validation of the discarded events message's beginning time | |
517 | * is performed in handle_packet_beginning_msg(). | |
518 | */ | |
519 | if (stream->discarded_events_state.in_range) { | |
520 | uint64_t expected_cs; | |
521 | ||
522 | /* | |
523 | * `stream->discarded_events_state.in_range` is only set | |
524 | * when the stream class's discarded events have a time | |
525 | * range. | |
526 | * | |
527 | * It is required that the packet beginning and end | |
528 | * messages for this stream class have times when | |
529 | * discarded events have a time range. | |
530 | */ | |
531 | BT_ASSERT(stream->sc->discarded_events_has_ts); | |
532 | BT_ASSERT(stream->sc->packets_have_ts_begin); | |
533 | BT_ASSERT(stream->sc->packets_have_ts_end); | |
534 | ||
535 | expected_cs = bt_clock_snapshot_get_value(cs); | |
536 | ||
537 | if (stream->discarded_events_state.end_cs != expected_cs) { | |
3c20ac12 SM |
538 | BT_CPPLOGE_APPEND_CAUSE_SPEC( |
539 | fs_sink->logger, | |
540 | "Incompatible discarded events message: " | |
541 | "unexpected end time: " | |
542 | "end-cs-val={}, " | |
543 | "expected-end-cs-val={}, " | |
544 | "stream-id={}, stream-name=\"{}\", " | |
545 | "trace-name=\"{}\", path=\"{}/{}\"", | |
546 | stream->discarded_events_state.end_cs, expected_cs, bt_stream_get_id(ir_stream), | |
547 | bt2c::maybeNull(bt_stream_get_name(ir_stream)), | |
548 | bt2c::maybeNull(bt_trace_get_name(bt_stream_borrow_trace_const(ir_stream))), | |
549 | stream->trace->path->str, stream->file_name->str); | |
4164020e SM |
550 | status = BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_ERROR; |
551 | goto end; | |
552 | } | |
553 | } | |
554 | ||
555 | ret = fs_sink_stream_close_packet(stream, cs); | |
556 | if (ret) { | |
3c20ac12 | 557 | BT_CPPLOGE_APPEND_CAUSE_SPEC(fs_sink->logger, "Failed to close packet."); |
4164020e SM |
558 | status = BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_ERROR; |
559 | goto end; | |
560 | } | |
561 | ||
562 | /* | |
563 | * We're not in a discarded events time range anymore since we | |
564 | * require that the discarded events time ranges go from one | |
565 | * packet's end time to the next packet's end time, and we're | |
566 | * handling a packet end message here. | |
567 | */ | |
568 | stream->discarded_events_state.in_range = false; | |
15fe47e0 PP |
569 | |
570 | end: | |
4164020e | 571 | return status; |
15fe47e0 PP |
572 | } |
573 | ||
4164020e SM |
574 | static inline bt_component_class_sink_consume_method_status |
575 | handle_stream_beginning_msg(struct fs_sink_comp *fs_sink, const bt_message *msg) | |
15fe47e0 | 576 | { |
4164020e SM |
577 | bt_component_class_sink_consume_method_status status = |
578 | BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_OK; | |
579 | const bt_stream *ir_stream = bt_message_stream_beginning_borrow_stream_const(msg); | |
580 | const bt_stream_class *ir_sc = bt_stream_borrow_class_const(ir_stream); | |
581 | struct fs_sink_stream *stream; | |
582 | bool packets_have_beginning_end_cs = | |
583 | bt_stream_class_packets_have_beginning_default_clock_snapshot(ir_sc) && | |
584 | bt_stream_class_packets_have_end_default_clock_snapshot(ir_sc); | |
585 | ||
586 | /* | |
587 | * Not supported: discarded events or discarded packets support | |
588 | * without packets support. Packets are the way to know where | |
589 | * discarded events/packets occurred in CTF 1.8. | |
590 | */ | |
591 | if (!bt_stream_class_supports_packets(ir_sc)) { | |
592 | BT_ASSERT(!bt_stream_class_supports_discarded_packets(ir_sc)); | |
593 | ||
594 | if (!fs_sink->ignore_discarded_events && bt_stream_class_supports_discarded_events(ir_sc)) { | |
3c20ac12 SM |
595 | BT_CPPLOGE_APPEND_CAUSE_SPEC(fs_sink->logger, |
596 | "Unsupported stream: " | |
597 | "stream does not support packets, " | |
598 | "but supports discarded events: " | |
599 | "stream-addr={}, " | |
600 | "stream-id={}, " | |
601 | "stream-name=\"{}\"", | |
602 | fmt::ptr(ir_stream), bt_stream_get_id(ir_stream), | |
603 | bt2c::maybeNull(bt_stream_get_name(ir_stream))); | |
4164020e SM |
604 | status = BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_ERROR; |
605 | goto end; | |
606 | } | |
607 | } | |
608 | ||
609 | /* | |
610 | * Not supported: discarded events with default clock snapshots, | |
611 | * but packet beginning/end without default clock snapshot. | |
612 | */ | |
613 | if (!fs_sink->ignore_discarded_events && | |
614 | bt_stream_class_discarded_events_have_default_clock_snapshots(ir_sc) && | |
615 | !packets_have_beginning_end_cs) { | |
3c20ac12 SM |
616 | BT_CPPLOGE_APPEND_CAUSE_SPEC(fs_sink->logger, |
617 | "Unsupported stream: discarded events have " | |
618 | "default clock snapshots, but packets have no " | |
619 | "beginning and/or end default clock snapshots: " | |
620 | "stream-addr={}, " | |
621 | "stream-id={}, " | |
622 | "stream-name=\"{}\"", | |
623 | fmt::ptr(ir_stream), bt_stream_get_id(ir_stream), | |
624 | bt2c::maybeNull(bt_stream_get_name(ir_stream))); | |
4164020e SM |
625 | status = BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_ERROR; |
626 | goto end; | |
627 | } | |
628 | ||
629 | /* | |
630 | * Not supported: discarded packets with default clock | |
631 | * snapshots, but packet beginning/end without default clock | |
632 | * snapshot. | |
633 | */ | |
634 | if (!fs_sink->ignore_discarded_packets && | |
635 | bt_stream_class_discarded_packets_have_default_clock_snapshots(ir_sc) && | |
636 | !packets_have_beginning_end_cs) { | |
3c20ac12 SM |
637 | BT_CPPLOGE_APPEND_CAUSE_SPEC(fs_sink->logger, |
638 | "Unsupported stream: discarded packets have " | |
639 | "default clock snapshots, but packets have no " | |
640 | "beginning and/or end default clock snapshots: " | |
641 | "stream-addr={}, " | |
642 | "stream-id={}, " | |
643 | "stream-name=\"{}\"", | |
644 | fmt::ptr(ir_stream), bt_stream_get_id(ir_stream), | |
645 | bt2c::maybeNull(bt_stream_get_name(ir_stream))); | |
4164020e SM |
646 | status = BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_ERROR; |
647 | goto end; | |
648 | } | |
649 | ||
650 | stream = borrow_stream(fs_sink, ir_stream); | |
651 | if (!stream) { | |
3c20ac12 | 652 | BT_CPPLOGE_APPEND_CAUSE_SPEC(fs_sink->logger, "Failed to borrow stream."); |
4164020e SM |
653 | status = BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_ERROR; |
654 | goto end; | |
655 | } | |
656 | ||
3c20ac12 SM |
657 | BT_CPPLOGI_SPEC(fs_sink->logger, |
658 | "Created new, empty stream file: " | |
659 | "stream-id={}, stream-name=\"{}\", " | |
660 | "trace-name=\"{}\", path=\"{}/{}\"", | |
661 | bt_stream_get_id(ir_stream), bt2c::maybeNull(bt_stream_get_name(ir_stream)), | |
662 | bt2c::maybeNull(bt_trace_get_name(bt_stream_borrow_trace_const(ir_stream))), | |
663 | stream->trace->path->str, stream->file_name->str); | |
15fe47e0 PP |
664 | |
665 | end: | |
4164020e | 666 | return status; |
15fe47e0 PP |
667 | } |
668 | ||
4164020e SM |
669 | static inline bt_component_class_sink_consume_method_status |
670 | handle_stream_end_msg(struct fs_sink_comp *fs_sink, const bt_message *msg) | |
15fe47e0 | 671 | { |
4164020e SM |
672 | bt_component_class_sink_consume_method_status status = |
673 | BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_OK; | |
674 | const bt_stream *ir_stream = bt_message_stream_end_borrow_stream_const(msg); | |
675 | struct fs_sink_stream *stream; | |
676 | ||
677 | stream = borrow_stream(fs_sink, ir_stream); | |
678 | if (!stream) { | |
3c20ac12 | 679 | BT_CPPLOGE_APPEND_CAUSE_SPEC(fs_sink->logger, "Failed to borrow stream."); |
4164020e SM |
680 | status = BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_ERROR; |
681 | goto end; | |
682 | } | |
683 | ||
684 | if (G_UNLIKELY(!stream->sc->has_packets && stream->packet_state.is_open)) { | |
685 | /* Close stream's current artificial packet */ | |
686 | int ret = fs_sink_stream_close_packet(stream, NULL); | |
687 | ||
688 | if (ret) { | |
3c20ac12 | 689 | BT_CPPLOGE_APPEND_CAUSE_SPEC(fs_sink->logger, "Failed to close packet."); |
4164020e SM |
690 | status = BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_ERROR; |
691 | goto end; | |
692 | } | |
693 | } | |
694 | ||
3c20ac12 SM |
695 | BT_CPPLOGI_SPEC(fs_sink->logger, |
696 | "Closing stream file: " | |
697 | "stream-id={}, stream-name=\"{}\", " | |
698 | "trace-name=\"{}\", path=\"{}/{}\"", | |
699 | bt_stream_get_id(ir_stream), bt2c::maybeNull(bt_stream_get_name(ir_stream)), | |
700 | bt2c::maybeNull(bt_trace_get_name(bt_stream_borrow_trace_const(ir_stream))), | |
701 | stream->trace->path->str, stream->file_name->str); | |
4164020e SM |
702 | |
703 | /* | |
704 | * This destroys the stream object and frees all its resources, | |
705 | * closing the stream file. | |
706 | */ | |
707 | g_hash_table_remove(stream->trace->streams, ir_stream); | |
15fe47e0 PP |
708 | |
709 | end: | |
4164020e | 710 | return status; |
15fe47e0 PP |
711 | } |
712 | ||
4164020e SM |
713 | static inline bt_component_class_sink_consume_method_status |
714 | handle_discarded_events_msg(struct fs_sink_comp *fs_sink, const bt_message *msg) | |
15fe47e0 | 715 | { |
4164020e SM |
716 | bt_component_class_sink_consume_method_status status = |
717 | BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_OK; | |
718 | const bt_stream *ir_stream = bt_message_discarded_events_borrow_stream_const(msg); | |
719 | struct fs_sink_stream *stream; | |
720 | const bt_clock_snapshot *cs = NULL; | |
721 | bt_property_availability avail; | |
722 | uint64_t count; | |
723 | ||
724 | stream = borrow_stream(fs_sink, ir_stream); | |
725 | if (!stream) { | |
3c20ac12 | 726 | BT_CPPLOGE_APPEND_CAUSE_SPEC(fs_sink->logger, "Failed to borrow stream."); |
4164020e SM |
727 | status = BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_ERROR; |
728 | goto end; | |
729 | } | |
730 | ||
731 | if (fs_sink->ignore_discarded_events) { | |
3c20ac12 SM |
732 | BT_CPPLOGI_SPEC(fs_sink->logger, |
733 | "Ignoring discarded events message: " | |
734 | "stream-id={}, stream-name=\"{}\", " | |
735 | "trace-name=\"{}\", path=\"{}/{}\"", | |
736 | bt_stream_get_id(ir_stream), bt2c::maybeNull(bt_stream_get_name(ir_stream)), | |
737 | bt2c::maybeNull(bt_trace_get_name(bt_stream_borrow_trace_const(ir_stream))), | |
738 | stream->trace->path->str, stream->file_name->str); | |
4164020e SM |
739 | goto end; |
740 | } | |
741 | ||
742 | if (stream->discarded_events_state.in_range) { | |
3c20ac12 SM |
743 | BT_CPPLOGE_APPEND_CAUSE_SPEC( |
744 | fs_sink->logger, | |
745 | "Unsupported contiguous discarded events message: " | |
746 | "stream-id={}, stream-name=\"{}\", " | |
747 | "trace-name=\"{}\", path=\"{}/{}\"", | |
748 | bt_stream_get_id(ir_stream), bt2c::maybeNull(bt_stream_get_name(ir_stream)), | |
749 | bt2c::maybeNull(bt_trace_get_name(bt_stream_borrow_trace_const(ir_stream))), | |
750 | stream->trace->path->str, stream->file_name->str); | |
4164020e SM |
751 | status = BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_ERROR; |
752 | goto end; | |
753 | } | |
754 | ||
755 | /* | |
756 | * If we're currently in an opened packet (got a packet | |
757 | * beginning message, but no packet end message yet), we do not | |
758 | * support having a discarded events message with a time range | |
759 | * because we require that the discarded events message's time | |
760 | * range go from a packet's end time to the next packet's end | |
761 | * time. | |
762 | */ | |
763 | if (stream->packet_state.is_open && stream->sc->discarded_events_has_ts) { | |
3c20ac12 SM |
764 | BT_CPPLOGE_APPEND_CAUSE_SPEC( |
765 | fs_sink->logger, | |
766 | "Unsupported discarded events message with " | |
767 | "default clock snapshots occurring within a packet: " | |
768 | "stream-id={}, stream-name=\"{}\", " | |
769 | "trace-name=\"{}\", path=\"{}/{}\"", | |
770 | bt_stream_get_id(ir_stream), bt2c::maybeNull(bt_stream_get_name(ir_stream)), | |
771 | bt2c::maybeNull(bt_trace_get_name(bt_stream_borrow_trace_const(ir_stream))), | |
772 | stream->trace->path->str, stream->file_name->str); | |
4164020e SM |
773 | status = BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_ERROR; |
774 | goto end; | |
775 | } | |
776 | ||
777 | if (stream->sc->discarded_events_has_ts) { | |
778 | /* | |
779 | * Make the stream's state be in the time range of a | |
780 | * discarded events message since we have the message's | |
781 | * time range (`stream->sc->discarded_events_has_ts`). | |
782 | */ | |
783 | stream->discarded_events_state.in_range = true; | |
784 | ||
785 | /* | |
786 | * The clock snapshot values will be validated when | |
787 | * handling the next packet beginning and end messages | |
788 | * (next calls to handle_packet_beginning_msg() and | |
789 | * handle_packet_end_msg()). | |
790 | */ | |
791 | cs = bt_message_discarded_events_borrow_beginning_default_clock_snapshot_const(msg); | |
792 | BT_ASSERT(cs); | |
793 | stream->discarded_events_state.beginning_cs = bt_clock_snapshot_get_value(cs); | |
794 | cs = bt_message_discarded_events_borrow_end_default_clock_snapshot_const(msg); | |
795 | BT_ASSERT(cs); | |
796 | stream->discarded_events_state.end_cs = bt_clock_snapshot_get_value(cs); | |
797 | } | |
798 | ||
799 | avail = bt_message_discarded_events_get_count(msg, &count); | |
800 | if (avail != BT_PROPERTY_AVAILABILITY_AVAILABLE) { | |
801 | /* | |
802 | * There's no specific count of discarded events: set it | |
803 | * to 1 so that we know that we at least discarded | |
804 | * something. | |
805 | */ | |
806 | count = 1; | |
807 | } | |
808 | ||
809 | stream->packet_state.discarded_events_counter += count; | |
15fe47e0 PP |
810 | |
811 | end: | |
4164020e | 812 | return status; |
15fe47e0 PP |
813 | } |
814 | ||
4164020e SM |
815 | static inline bt_component_class_sink_consume_method_status |
816 | handle_discarded_packets_msg(struct fs_sink_comp *fs_sink, const bt_message *msg) | |
15fe47e0 | 817 | { |
4164020e SM |
818 | bt_component_class_sink_consume_method_status status = |
819 | BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_OK; | |
820 | const bt_stream *ir_stream = bt_message_discarded_packets_borrow_stream_const(msg); | |
821 | struct fs_sink_stream *stream; | |
822 | const bt_clock_snapshot *cs = NULL; | |
823 | bt_property_availability avail; | |
824 | uint64_t count; | |
825 | ||
826 | stream = borrow_stream(fs_sink, ir_stream); | |
827 | if (!stream) { | |
3c20ac12 | 828 | BT_CPPLOGE_APPEND_CAUSE_SPEC(fs_sink->logger, "Failed to borrow stream."); |
4164020e SM |
829 | status = BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_ERROR; |
830 | goto end; | |
831 | } | |
832 | ||
833 | if (fs_sink->ignore_discarded_packets) { | |
3c20ac12 SM |
834 | BT_CPPLOGI_SPEC(fs_sink->logger, |
835 | "Ignoring discarded packets message: " | |
836 | "stream-id={}, stream-name=\"{}\", " | |
837 | "trace-name=\"{}\", path=\"{}/{}\"", | |
838 | bt_stream_get_id(ir_stream), bt2c::maybeNull(bt_stream_get_name(ir_stream)), | |
839 | bt2c::maybeNull(bt_trace_get_name(bt_stream_borrow_trace_const(ir_stream))), | |
840 | stream->trace->path->str, stream->file_name->str); | |
4164020e SM |
841 | goto end; |
842 | } | |
843 | ||
844 | if (stream->discarded_packets_state.in_range) { | |
3c20ac12 SM |
845 | BT_CPPLOGE_APPEND_CAUSE_SPEC( |
846 | fs_sink->logger, | |
847 | "Unsupported contiguous discarded packets message: " | |
848 | "stream-id={}, stream-name=\"{}\", " | |
849 | "trace-name=\"{}\", path=\"{}/{}\"", | |
850 | bt_stream_get_id(ir_stream), bt2c::maybeNull(bt_stream_get_name(ir_stream)), | |
851 | bt2c::maybeNull(bt_trace_get_name(bt_stream_borrow_trace_const(ir_stream))), | |
852 | stream->trace->path->str, stream->file_name->str); | |
4164020e SM |
853 | status = BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_ERROR; |
854 | goto end; | |
855 | } | |
856 | ||
857 | /* | |
858 | * Discarded packets messages are guaranteed to occur between | |
859 | * packets. | |
860 | */ | |
861 | BT_ASSERT(!stream->packet_state.is_open); | |
862 | ||
863 | if (stream->sc->discarded_packets_has_ts) { | |
864 | /* | |
865 | * Make the stream's state be in the time range of a | |
866 | * discarded packets message since we have the message's | |
867 | * time range (`stream->sc->discarded_packets_has_ts`). | |
868 | */ | |
869 | stream->discarded_packets_state.in_range = true; | |
870 | ||
871 | /* | |
872 | * The clock snapshot values will be validated when | |
873 | * handling the next packet beginning message (next call | |
874 | * to handle_packet_beginning_msg()). | |
875 | */ | |
876 | cs = bt_message_discarded_packets_borrow_beginning_default_clock_snapshot_const(msg); | |
877 | BT_ASSERT(cs); | |
878 | stream->discarded_packets_state.beginning_cs = bt_clock_snapshot_get_value(cs); | |
879 | cs = bt_message_discarded_packets_borrow_end_default_clock_snapshot_const(msg); | |
880 | BT_ASSERT(cs); | |
881 | stream->discarded_packets_state.end_cs = bt_clock_snapshot_get_value(cs); | |
882 | } | |
883 | ||
884 | avail = bt_message_discarded_packets_get_count(msg, &count); | |
885 | if (avail != BT_PROPERTY_AVAILABILITY_AVAILABLE) { | |
886 | /* | |
887 | * There's no specific count of discarded packets: set | |
888 | * it to 1 so that we know that we at least discarded | |
889 | * something. | |
890 | */ | |
891 | count = 1; | |
892 | } | |
893 | ||
894 | stream->packet_state.seq_num += count; | |
15fe47e0 PP |
895 | |
896 | end: | |
4164020e | 897 | return status; |
15fe47e0 PP |
898 | } |
899 | ||
4164020e | 900 | static inline void put_messages(bt_message_array_const msgs, uint64_t count) |
15fe47e0 | 901 | { |
4164020e | 902 | uint64_t i; |
15fe47e0 | 903 | |
4164020e SM |
904 | for (i = 0; i < count; i++) { |
905 | BT_MESSAGE_PUT_REF_AND_RESET(msgs[i]); | |
906 | } | |
15fe47e0 PP |
907 | } |
908 | ||
4164020e | 909 | bt_component_class_sink_consume_method_status ctf_fs_sink_consume(bt_self_component_sink *self_comp) |
15fe47e0 | 910 | { |
4164020e SM |
911 | bt_component_class_sink_consume_method_status status = |
912 | BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_OK; | |
913 | struct fs_sink_comp *fs_sink; | |
914 | bt_message_iterator_next_status next_status; | |
915 | uint64_t msg_count = 0; | |
916 | bt_message_array_const msgs; | |
917 | ||
918 | fs_sink = (fs_sink_comp *) bt_self_component_get_data( | |
919 | bt_self_component_sink_as_self_component(self_comp)); | |
920 | BT_ASSERT_DBG(fs_sink); | |
921 | BT_ASSERT_DBG(fs_sink->upstream_iter); | |
922 | ||
923 | /* Consume messages */ | |
924 | next_status = bt_message_iterator_next(fs_sink->upstream_iter, &msgs, &msg_count); | |
925 | if (next_status < 0) { | |
926 | status = (bt_component_class_sink_consume_method_status) next_status; | |
3c20ac12 SM |
927 | BT_CPPLOGE_APPEND_CAUSE_SPEC(fs_sink->logger, |
928 | "Failed to get next message from upstream iterator."); | |
4164020e SM |
929 | goto end; |
930 | } | |
931 | ||
932 | switch (next_status) { | |
933 | case BT_MESSAGE_ITERATOR_NEXT_STATUS_OK: | |
934 | { | |
935 | uint64_t i; | |
936 | ||
937 | for (i = 0; i < msg_count; i++) { | |
938 | const bt_message *msg = msgs[i]; | |
939 | ||
940 | BT_ASSERT_DBG(msg); | |
941 | ||
942 | switch (bt_message_get_type(msg)) { | |
943 | case BT_MESSAGE_TYPE_EVENT: | |
944 | status = handle_event_msg(fs_sink, msg); | |
945 | break; | |
946 | case BT_MESSAGE_TYPE_PACKET_BEGINNING: | |
947 | status = handle_packet_beginning_msg(fs_sink, msg); | |
948 | break; | |
949 | case BT_MESSAGE_TYPE_PACKET_END: | |
950 | status = handle_packet_end_msg(fs_sink, msg); | |
951 | break; | |
952 | case BT_MESSAGE_TYPE_MESSAGE_ITERATOR_INACTIVITY: | |
953 | /* Ignore */ | |
3c20ac12 SM |
954 | BT_CPPLOGD_STR_SPEC(fs_sink->logger, |
955 | "Ignoring message iterator inactivity message."); | |
4164020e SM |
956 | break; |
957 | case BT_MESSAGE_TYPE_STREAM_BEGINNING: | |
958 | status = handle_stream_beginning_msg(fs_sink, msg); | |
959 | break; | |
960 | case BT_MESSAGE_TYPE_STREAM_END: | |
961 | status = handle_stream_end_msg(fs_sink, msg); | |
962 | break; | |
963 | case BT_MESSAGE_TYPE_DISCARDED_EVENTS: | |
964 | status = handle_discarded_events_msg(fs_sink, msg); | |
965 | break; | |
966 | case BT_MESSAGE_TYPE_DISCARDED_PACKETS: | |
967 | status = handle_discarded_packets_msg(fs_sink, msg); | |
968 | break; | |
969 | default: | |
970 | bt_common_abort(); | |
971 | } | |
972 | ||
973 | BT_MESSAGE_PUT_REF_AND_RESET(msgs[i]); | |
974 | ||
975 | if (status != BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_OK) { | |
3c20ac12 SM |
976 | BT_CPPLOGE_APPEND_CAUSE_SPEC(fs_sink->logger, |
977 | "Failed to handle message: " | |
978 | "generated CTF traces could be incomplete: " | |
979 | "output-dir-path=\"{}\"", | |
980 | fs_sink->output_dir_path->str); | |
4164020e SM |
981 | goto error; |
982 | } | |
983 | } | |
984 | ||
985 | break; | |
986 | } | |
987 | case BT_MESSAGE_ITERATOR_NEXT_STATUS_AGAIN: | |
988 | status = BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_AGAIN; | |
989 | break; | |
990 | case BT_MESSAGE_ITERATOR_NEXT_STATUS_END: | |
991 | /* TODO: Finalize all traces (should already be done?) */ | |
992 | status = BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_END; | |
993 | break; | |
994 | default: | |
995 | break; | |
996 | } | |
997 | ||
998 | goto end; | |
15fe47e0 PP |
999 | |
1000 | error: | |
4164020e SM |
1001 | BT_ASSERT(status != BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_OK); |
1002 | put_messages(msgs, msg_count); | |
15fe47e0 PP |
1003 | |
1004 | end: | |
4164020e | 1005 | return status; |
15fe47e0 PP |
1006 | } |
1007 | ||
e803df70 | 1008 | bt_component_class_sink_graph_is_configured_method_status |
4164020e | 1009 | ctf_fs_sink_graph_is_configured(bt_self_component_sink *self_comp) |
15fe47e0 | 1010 | { |
4164020e SM |
1011 | bt_component_class_sink_graph_is_configured_method_status status; |
1012 | bt_message_iterator_create_from_sink_component_status msg_iter_status; | |
1013 | fs_sink_comp *fs_sink = (fs_sink_comp *) bt_self_component_get_data( | |
1014 | bt_self_component_sink_as_self_component(self_comp)); | |
1015 | ||
1016 | msg_iter_status = bt_message_iterator_create_from_sink_component( | |
1017 | self_comp, bt_self_component_sink_borrow_input_port_by_name(self_comp, in_port_name), | |
1018 | &fs_sink->upstream_iter); | |
1019 | if (msg_iter_status != BT_MESSAGE_ITERATOR_CREATE_FROM_SINK_COMPONENT_STATUS_OK) { | |
1020 | status = (bt_component_class_sink_graph_is_configured_method_status) msg_iter_status; | |
3c20ac12 | 1021 | BT_CPPLOGE_APPEND_CAUSE_SPEC(fs_sink->logger, "Failed to create upstream iterator."); |
4164020e SM |
1022 | goto end; |
1023 | } | |
1024 | ||
1025 | status = BT_COMPONENT_CLASS_SINK_GRAPH_IS_CONFIGURED_METHOD_STATUS_OK; | |
15fe47e0 | 1026 | end: |
4164020e | 1027 | return status; |
15fe47e0 PP |
1028 | } |
1029 | ||
15fe47e0 PP |
1030 | void ctf_fs_sink_finalize(bt_self_component_sink *self_comp) |
1031 | { | |
4164020e SM |
1032 | fs_sink_comp *fs_sink = (fs_sink_comp *) bt_self_component_get_data( |
1033 | bt_self_component_sink_as_self_component(self_comp)); | |
15fe47e0 | 1034 | |
4164020e | 1035 | destroy_fs_sink_comp(fs_sink); |
15fe47e0 | 1036 | } |