sink.text.pretty: print discarded events/packets warning
[babeltrace.git] / lib / ctf-writer / stream-class.c
CommitLineData
3dca2276
PP
1/*
2 * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
3 * Copyright 2017-2018 Philippe Proulx <pproulx@efficios.com>
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 */
23
24#define BT_LOG_TAG "CTF-WRITER-STREAM-CLASS"
25#include <babeltrace/lib-logging-internal.h>
26
27#include <babeltrace/ref.h>
28#include <babeltrace/ctf-writer/writer-internal.h>
29#include <babeltrace/ctf-writer/stream-class-internal.h>
30#include <babeltrace/ctf-writer/field-types-internal.h>
31#include <babeltrace/ctf-writer/event-internal.h>
32#include <babeltrace/ctf-writer/event.h>
33#include <babeltrace/ctf-writer/trace.h>
34#include <babeltrace/compiler-internal.h>
35#include <babeltrace/assert-internal.h>
36#include <babeltrace/assert-pre-internal.h>
37#include <inttypes.h>
38
39static
40int init_event_header(struct bt_ctf_stream_class *stream_class)
41{
42 int ret = 0;
43 struct bt_ctf_field_type *event_header_type =
44 bt_ctf_field_type_structure_create();
45 struct bt_ctf_field_type *_uint32_t =
46 get_field_type(FIELD_TYPE_ALIAS_UINT32_T);
47 struct bt_ctf_field_type *_uint64_t =
48 get_field_type(FIELD_TYPE_ALIAS_UINT64_T);
49
50 if (!event_header_type) {
51 BT_LOGE_STR("Cannot create empty structure field type.");
52 ret = -1;
53 goto end;
54 }
55
56 ret = bt_ctf_field_type_structure_add_field(event_header_type,
57 _uint32_t, "id");
58 if (ret) {
59 BT_LOGE_STR("Cannot add `id` field to event header field type.");
60 goto end;
61 }
62
63 ret = bt_ctf_field_type_structure_add_field(event_header_type,
64 _uint64_t, "timestamp");
65 if (ret) {
66 BT_LOGE_STR("Cannot add `timestamp` field to event header field type.");
67 goto end;
68 }
69
70 bt_put(stream_class->common.event_header_field_type);
71 stream_class->common.event_header_field_type =
72 (void *) event_header_type;
73 event_header_type = NULL;
74
75end:
76 if (ret) {
77 bt_put(event_header_type);
78 }
79
80 bt_put(_uint32_t);
81 bt_put(_uint64_t);
82 return ret;
83}
84
85static
86int init_packet_context(struct bt_ctf_stream_class *stream_class)
87{
88 int ret = 0;
89 struct bt_ctf_field_type *packet_context_type =
90 bt_ctf_field_type_structure_create();
91 struct bt_ctf_field_type *_uint64_t =
92 get_field_type(FIELD_TYPE_ALIAS_UINT64_T);
93 struct bt_ctf_field_type *ts_begin_end_uint64_t;
94
95 if (!packet_context_type) {
96 BT_LOGE_STR("Cannot create empty structure field type.");
97 ret = -1;
98 goto end;
99 }
100
101 ts_begin_end_uint64_t = bt_ctf_field_type_copy(_uint64_t);
102 if (!ts_begin_end_uint64_t) {
103 BT_LOGE_STR("Cannot copy integer field type for `timestamp_begin` and `timestamp_end` fields.");
104 ret = -1;
105 goto end;
106 }
107
108 /*
109 * We create a stream packet context as proposed in the CTF
110 * specification.
111 */
112 ret = bt_ctf_field_type_structure_add_field(packet_context_type,
113 ts_begin_end_uint64_t, "timestamp_begin");
114 if (ret) {
115 BT_LOGE_STR("Cannot add `timestamp_begin` field to event header field type.");
116 goto end;
117 }
118
119 ret = bt_ctf_field_type_structure_add_field(packet_context_type,
120 ts_begin_end_uint64_t, "timestamp_end");
121 if (ret) {
122 BT_LOGE_STR("Cannot add `timestamp_end` field to event header field type.");
123 goto end;
124 }
125
126 ret = bt_ctf_field_type_structure_add_field(packet_context_type,
127 _uint64_t, "content_size");
128 if (ret) {
129 BT_LOGE_STR("Cannot add `content_size` field to event header field type.");
130 goto end;
131 }
132
133 ret = bt_ctf_field_type_structure_add_field(packet_context_type,
134 _uint64_t, "packet_size");
135 if (ret) {
136 BT_LOGE_STR("Cannot add `packet_size` field to event header field type.");
137 goto end;
138 }
139
140 ret = bt_ctf_field_type_structure_add_field(packet_context_type,
141 _uint64_t, "events_discarded");
142 if (ret) {
143 BT_LOGE_STR("Cannot add `events_discarded` field to event header field type.");
144 goto end;
145 }
146
147 bt_put(stream_class->common.packet_context_field_type);
148 stream_class->common.packet_context_field_type =
149 (void *) packet_context_type;
150 packet_context_type = NULL;
151
152end:
153 if (ret) {
154 bt_put(packet_context_type);
155 goto end;
156 }
157
158 bt_put(_uint64_t);
159 bt_put(ts_begin_end_uint64_t);
160 return ret;
161}
162
163static
164void bt_ctf_stream_class_destroy(struct bt_object *obj)
165{
166 struct bt_ctf_stream_class *stream_class;
167
168 stream_class = (void *) obj;
169 BT_LOGD("Destroying CTF writer stream class: addr=%p, name=\"%s\", id=%" PRId64,
170 stream_class, bt_ctf_stream_class_get_name(stream_class),
171 bt_ctf_stream_class_get_id(stream_class));
172 bt_stream_class_common_finalize(BT_TO_COMMON(stream_class));
173 bt_put(stream_class->clock);
174 g_free(stream_class);
175}
176
177struct bt_ctf_stream_class *bt_ctf_stream_class_create(const char *name)
178{
179 struct bt_ctf_stream_class *stream_class;
180 int ret;
181
182 BT_LOGD("Creating CTF writer stream class object: name=\"%s\"", name);
183 stream_class = g_new0(struct bt_ctf_stream_class, 1);
184 if (!stream_class) {
185 BT_LOGE_STR("Failed to allocate one CTF writer stream class.");
186 goto error;
187 }
188
189 ret = bt_stream_class_common_initialize(BT_TO_COMMON(stream_class),
190 name, bt_ctf_stream_class_destroy);
191 if (ret) {
192 /* bt_stream_class_common_initialize() logs errors */
193 goto error;
194 }
195
196 ret = init_event_header(stream_class);
197 if (ret) {
198 BT_LOGE_STR("Cannot initialize stream class's event header field type.");
199 goto error;
200 }
201
202 ret = init_packet_context(stream_class);
203 if (ret) {
204 BT_LOGE_STR("Cannot initialize stream class's packet context field type.");
205 goto error;
206 }
207
208 BT_LOGD("Created CTF writer stream class object: addr=%p, name=\"%s\"",
209 stream_class, name);
210 return stream_class;
211
212error:
213 BT_PUT(stream_class);
214 return stream_class;
215}
216
217static
218int try_map_clock_class(struct bt_ctf_stream_class *stream_class,
219 struct bt_ctf_field_type *parent_ft, const char *field_name)
220{
221 struct bt_ctf_clock_class *mapped_clock_class = NULL;
222 int ret = 0;
223 struct bt_ctf_field_type *ft =
224 bt_ctf_field_type_structure_get_field_type_by_name(parent_ft,
225 field_name);
226
227 BT_ASSERT(stream_class->clock);
228
229 if (!ft) {
230 /* Field does not exist: not an error */
231 goto end;
232 }
233
234 BT_ASSERT(((struct bt_field_type_common *) ft)->id ==
5a547eb3 235 BT_FIELD_TYPE_ID_INTEGER);
3dca2276
PP
236 mapped_clock_class =
237 bt_ctf_field_type_integer_get_mapped_clock_class(ft);
238 if (!mapped_clock_class) {
239 struct bt_ctf_field_type *ft_copy;
240
241 if (!stream_class->clock) {
242 BT_LOGW("Cannot automatically set field's type mapped clock class: stream class's clock is not set: "
243 "stream-class-addr=%p, stream-class-name=\"%s\", "
244 "stream-class-id=%" PRId64 ", ft-addr=%p",
245 stream_class,
246 bt_ctf_stream_class_get_name(stream_class),
247 bt_ctf_stream_class_get_id(stream_class), ft);
248 ret = -1;
249 goto end;
250 }
251
252 ft_copy = bt_ctf_field_type_copy(ft);
253 if (!ft_copy) {
254 BT_LOGE("Failed to copy integer field type: ft-addr=%p",
255 ft);
256 }
257
258 ret = bt_field_type_common_integer_set_mapped_clock_class_no_check_frozen(
259 (void *) ft_copy,
260 BT_TO_COMMON(stream_class->clock->clock_class));
261 BT_ASSERT(ret == 0);
262
263 ret = bt_field_type_common_structure_replace_field(
264 (void *) parent_ft, field_name, (void *) ft_copy);
265 bt_put(ft_copy);
266 BT_LOGV("Automatically mapped field type to stream class's clock class: "
267 "stream-class-addr=%p, stream-class-name=\"%s\", "
268 "stream-class-id=%" PRId64 ", ft-addr=%p, "
269 "ft-copy-addr=%p",
270 stream_class,
271 bt_ctf_stream_class_get_name(stream_class),
272 bt_ctf_stream_class_get_id(stream_class), ft, ft_copy);
273 }
274
275end:
276 bt_put(ft);
277 bt_put(mapped_clock_class);
278 return ret;
279}
280
281BT_HIDDEN
282int bt_ctf_stream_class_map_clock_class(
283 struct bt_ctf_stream_class *stream_class,
284 struct bt_ctf_field_type *packet_context_type,
285 struct bt_ctf_field_type *event_header_type)
286{
287 int ret = 0;
288
289 BT_ASSERT(stream_class);
290
291 if (!stream_class->clock) {
292 /* No clock class to map to */
293 goto end;
294 }
295
296 if (packet_context_type) {
297 if (try_map_clock_class(stream_class, packet_context_type,
298 "timestamp_begin")) {
299 BT_LOGE_STR("Cannot automatically set stream class's packet context field type's `timestamp_begin` field's mapped clock class.");
300 ret = -1;
301 goto end;
302 }
303
304 if (try_map_clock_class(stream_class, packet_context_type,
305 "timestamp_end")) {
306 BT_LOGE_STR("Cannot automatically set stream class's packet context field type's `timestamp_end` field's mapped clock class.");
307 ret = -1;
308 goto end;
309 }
310 }
311
312 if (event_header_type) {
313 if (try_map_clock_class(stream_class, event_header_type,
314 "timestamp")) {
315 BT_LOGE_STR("Cannot automatically set stream class's event header field type's `timestamp` field's mapped clock class.");
316 ret = -1;
317 goto end;
318 }
319 }
320
321end:
322 return ret;
323}
324
325struct bt_ctf_clock *bt_ctf_stream_class_get_clock(
326 struct bt_ctf_stream_class *stream_class)
327{
328 struct bt_ctf_clock *clock = NULL;
329
330 if (!stream_class) {
331 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
332 goto end;
333 }
334
335 if (!stream_class->clock) {
336 BT_LOGV("Stream class has no clock: "
337 "addr=%p, name=\"%s\", id=%" PRId64,
338 stream_class,
339 bt_ctf_stream_class_get_name(stream_class),
340 bt_ctf_stream_class_get_id(stream_class));
341 goto end;
342 }
343
344 clock = bt_get(stream_class->clock);
345
346end:
347 return clock;
348}
349
350int bt_ctf_stream_class_set_clock(
351 struct bt_ctf_stream_class *stream_class,
352 struct bt_ctf_clock *clock)
353{
354 int ret = 0;
355
356 if (!stream_class || !clock) {
357 BT_LOGW("Invalid parameter: stream class or clock is NULL: "
358 "stream-class-addr=%p, clock-addr=%p",
359 stream_class, clock);
360 ret = -1;
361 goto end;
362 }
363
364 if (stream_class->common.frozen) {
365 BT_LOGW("Invalid parameter: stream class is frozen: "
366 "addr=%p, name=\"%s\", id=%" PRId64,
367 stream_class,
368 bt_ctf_stream_class_get_name(stream_class),
369 bt_ctf_stream_class_get_id(stream_class));
370 ret = -1;
371 goto end;
372 }
373
374 /* Replace the current clock of this stream class. */
375 bt_put(stream_class->clock);
376 stream_class->clock = bt_get(clock);
377 BT_LOGV("Set stream class's clock: "
378 "addr=%p, name=\"%s\", id=%" PRId64 ", "
379 "clock-addr=%p, clock-name=\"%s\"",
380 stream_class,
381 bt_ctf_stream_class_get_name(stream_class),
382 bt_ctf_stream_class_get_id(stream_class),
383 stream_class->clock,
384 bt_ctf_clock_get_name(stream_class->clock));
385
386end:
387 return ret;
388}
389
390BT_HIDDEN
391int bt_ctf_stream_class_serialize(struct bt_ctf_stream_class *stream_class,
392 struct metadata_context *context)
393{
394 int ret = 0;
395 size_t i;
396 struct bt_ctf_trace *trace;
397 struct bt_ctf_field_type *packet_header_type = NULL;
398
399 BT_LOGD("Serializing stream class's metadata: "
400 "stream-class-addr=%p, stream-class-name=\"%s\", "
401 "stream-class-id=%" PRId64 ", metadata-context-addr=%p",
402 stream_class,
403 bt_ctf_stream_class_get_name(stream_class),
404 bt_ctf_stream_class_get_id(stream_class), context);
405 g_string_assign(context->field_name, "");
406 context->current_indentation_level = 1;
407 if (!stream_class->common.id_set) {
408 BT_LOGW_STR("Stream class's ID is not set.");
409 ret = -1;
410 goto end;
411 }
412
413 g_string_append(context->string, "stream {\n");
414
415 /*
416 * The reference to the trace is only borrowed since the
417 * serialization of the stream class might have been triggered
418 * by the trace's destruction. In such a case, the trace's
419 * reference count would, unexepectedly, go through the sequence
420 * 1 -> 0 -> 1 -> 0 -> ..., provoking an endless loop of destruction
421 * and serialization.
422 */
423 trace = BT_FROM_COMMON(bt_stream_class_common_borrow_trace(
424 BT_TO_COMMON(stream_class)));
425 BT_ASSERT(trace);
426 packet_header_type = bt_ctf_trace_get_packet_header_field_type(trace);
427 trace = NULL;
428 if (packet_header_type) {
429 struct bt_ctf_field_type *stream_id_type;
430
431 stream_id_type =
432 bt_ctf_field_type_structure_get_field_type_by_name(
433 packet_header_type, "stream_id");
434 if (stream_id_type) {
435 /*
436 * Only set the stream's id if the trace's packet header
437 * contains a stream_id field. This field is only
438 * needed if the trace contains only one stream
439 * class.
440 */
441 g_string_append_printf(context->string,
442 "\tid = %" PRId64 ";\n",
443 stream_class->common.id);
444 }
445 bt_put(stream_id_type);
446 }
447 if (stream_class->common.event_header_field_type) {
448 BT_LOGD_STR("Serializing stream class's event header field type's metadata.");
449 g_string_append(context->string, "\tevent.header := ");
450 ret = bt_ctf_field_type_serialize_recursive(
451 (void *) stream_class->common.event_header_field_type,
452 context);
453 if (ret) {
454 BT_LOGW("Cannot serialize stream class's event header field type's metadata: "
455 "ret=%d", ret);
456 goto end;
457 }
458 g_string_append(context->string, ";");
459 }
460
461
462 if (stream_class->common.packet_context_field_type) {
463 BT_LOGD_STR("Serializing stream class's packet context field type's metadata.");
464 g_string_append(context->string, "\n\n\tpacket.context := ");
465 ret = bt_ctf_field_type_serialize_recursive(
466 (void *) stream_class->common.packet_context_field_type,
467 context);
468 if (ret) {
469 BT_LOGW("Cannot serialize stream class's packet context field type's metadata: "
470 "ret=%d", ret);
471 goto end;
472 }
473 g_string_append(context->string, ";");
474 }
475
476 if (stream_class->common.event_context_field_type) {
477 BT_LOGD_STR("Serializing stream class's event context field type's metadata.");
478 g_string_append(context->string, "\n\n\tevent.context := ");
479 ret = bt_ctf_field_type_serialize_recursive(
480 (void *) stream_class->common.event_context_field_type,
481 context);
482 if (ret) {
483 BT_LOGW("Cannot serialize stream class's event context field type's metadata: "
484 "ret=%d", ret);
485 goto end;
486 }
487 g_string_append(context->string, ";");
488 }
489
490 g_string_append(context->string, "\n};\n\n");
491
492 for (i = 0; i < stream_class->common.event_classes->len; i++) {
493 struct bt_ctf_event_class *event_class =
494 stream_class->common.event_classes->pdata[i];
495
496 ret = bt_ctf_event_class_serialize(event_class, context);
497 if (ret) {
498 BT_LOGW("Cannot serialize event class's metadata: "
499 "event-class-addr=%p, event-class-name=\"%s\", "
500 "event-class-id=%" PRId64,
501 event_class,
502 bt_ctf_event_class_get_name(event_class),
503 bt_ctf_event_class_get_id(event_class));
504 goto end;
505 }
506 }
507
508end:
509 bt_put(packet_header_type);
510 context->current_indentation_level = 0;
511 return ret;
512}
513
514struct bt_ctf_trace *bt_ctf_stream_class_get_trace(
515 struct bt_ctf_stream_class *stream_class)
516{
094ff7c0 517 return bt_get(bt_stream_class_common_borrow_trace(
3dca2276
PP
518 BT_TO_COMMON(stream_class)));
519}
520
521const char *bt_ctf_stream_class_get_name(
522 struct bt_ctf_stream_class *stream_class)
523{
524 return bt_stream_class_common_get_name(BT_TO_COMMON(stream_class));
525}
526
527int bt_ctf_stream_class_set_name(
528 struct bt_ctf_stream_class *stream_class, const char *name)
529{
530 return bt_stream_class_common_set_name(BT_TO_COMMON(stream_class),
531 name);
532}
533
534int64_t bt_ctf_stream_class_get_id(
535 struct bt_ctf_stream_class *stream_class)
536{
537 return bt_stream_class_common_get_id(BT_TO_COMMON(stream_class));
538}
539
540int bt_ctf_stream_class_set_id(
541 struct bt_ctf_stream_class *stream_class, uint64_t id)
542{
543 return bt_stream_class_common_set_id(BT_TO_COMMON(stream_class), id);
544}
545
546struct bt_ctf_field_type *bt_ctf_stream_class_get_packet_context_type(
547 struct bt_ctf_stream_class *stream_class)
548{
094ff7c0
PP
549 return bt_get(
550 bt_stream_class_common_borrow_packet_context_field_type(
3dca2276
PP
551 BT_TO_COMMON(stream_class)));
552}
553
554int bt_ctf_stream_class_set_packet_context_type(
555 struct bt_ctf_stream_class *stream_class,
556 struct bt_ctf_field_type *packet_context_type)
557{
558 return bt_stream_class_common_set_packet_context_field_type(
559 BT_TO_COMMON(stream_class), (void *) packet_context_type);
560}
561
562struct bt_ctf_field_type *
563bt_ctf_stream_class_get_event_header_type(
564 struct bt_ctf_stream_class *stream_class)
565{
094ff7c0
PP
566 return bt_get(
567 bt_stream_class_common_borrow_event_header_field_type(
3dca2276
PP
568 BT_TO_COMMON(stream_class)));
569}
570
571int bt_ctf_stream_class_set_event_header_type(
572 struct bt_ctf_stream_class *stream_class,
573 struct bt_ctf_field_type *event_header_type)
574{
575 return bt_stream_class_common_set_event_header_field_type(
576 BT_TO_COMMON(stream_class), (void *) event_header_type);
577}
578
579struct bt_ctf_field_type *
580bt_ctf_stream_class_get_event_context_type(
581 struct bt_ctf_stream_class *stream_class)
582{
094ff7c0
PP
583 return bt_get(
584 bt_stream_class_common_borrow_event_context_field_type(
3dca2276
PP
585 BT_TO_COMMON(stream_class)));
586}
587
588int bt_ctf_stream_class_set_event_context_type(
589 struct bt_ctf_stream_class *stream_class,
590 struct bt_ctf_field_type *event_context_type)
591{
592 return bt_stream_class_common_set_event_context_field_type(
593 BT_TO_COMMON(stream_class), (void *) event_context_type);
594}
595
596int64_t bt_ctf_stream_class_get_event_class_count(
597 struct bt_ctf_stream_class *stream_class)
598{
599 return bt_stream_class_common_get_event_class_count(
600 BT_TO_COMMON(stream_class));
601}
602
603struct bt_ctf_event_class *bt_ctf_stream_class_get_event_class_by_index(
604 struct bt_ctf_stream_class *stream_class, uint64_t index)
605{
094ff7c0
PP
606 return bt_get(
607 bt_stream_class_common_borrow_event_class_by_index(
3dca2276
PP
608 BT_TO_COMMON(stream_class), index));
609}
610
611struct bt_ctf_event_class *bt_ctf_stream_class_get_event_class_by_id(
612 struct bt_ctf_stream_class *stream_class, uint64_t id)
613{
094ff7c0
PP
614 return bt_get(
615 bt_stream_class_common_borrow_event_class_by_id(
3dca2276
PP
616 BT_TO_COMMON(stream_class), id));
617}
618
619int bt_ctf_stream_class_add_event_class(
620 struct bt_ctf_stream_class *stream_class,
621 struct bt_ctf_event_class *event_class)
622{
623 return bt_stream_class_common_add_event_class(
624 BT_TO_COMMON(stream_class), BT_TO_COMMON(event_class),
625 (bt_validation_flag_copy_field_type_func) bt_ctf_field_type_copy);
626}
This page took 0.045473 seconds and 4 git commands to generate.