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