2 * SPDX-License-Identifier: MIT
4 * Copyright 2016-2018 Philippe Proulx <pproulx@efficios.com>
6 * Babeltrace - CTF writer: Validation of trace, stream class, and event class
9 #define BT_LOG_TAG "CTF-WRITER/VALIDATION"
12 #include <babeltrace2-ctf-writer/object.h>
14 #include "common/macros.h"
16 #include "assert-pre.h"
17 #include "event-class.h"
18 #include "field-types.h"
19 #include "field-types.h"
21 #include "stream-class.h"
23 #include "validation.h"
27 * This function resolves and validates the field types of an event
28 * class. Only `event_context_type` and `event_payload_type` are
29 * resolved and validated; the other field types are used as eventual
32 * All parameters are owned by the caller.
35 int validate_event_class_types(struct bt_ctf_private_value
*environment
,
36 struct bt_ctf_field_type_common
*packet_header_type
,
37 struct bt_ctf_field_type_common
*packet_context_type
,
38 struct bt_ctf_field_type_common
*event_header_type
,
39 struct bt_ctf_field_type_common
*stream_event_ctx_type
,
40 struct bt_ctf_field_type_common
*event_context_type
,
41 struct bt_ctf_field_type_common
*event_payload_type
)
45 BT_LOGT("Validating event class field types: "
46 "packet-header-ft-addr=%p, "
47 "packet-context-ft-addr=%p, "
48 "event-header-ft-addr=%p, "
49 "stream-event-context-ft-addr=%p, "
50 "event-context-ft-addr=%p, "
51 "event-payload-ft-addr=%p",
52 packet_header_type
, packet_context_type
, event_header_type
,
53 stream_event_ctx_type
, event_context_type
, event_payload_type
);
55 /* Resolve sequence type lengths and variant type tags first */
56 ret
= bt_ctf_resolve_types(environment
, packet_header_type
,
57 packet_context_type
, event_header_type
, stream_event_ctx_type
,
58 event_context_type
, event_payload_type
,
59 BT_CTF_RESOLVE_FLAG_EVENT_CONTEXT
|
60 BT_CTF_RESOLVE_FLAG_EVENT_PAYLOAD
);
62 BT_LOGW("Cannot resolve event class field types: ret=%d",
67 /* Validate field types individually */
68 if (event_context_type
) {
69 ret
= bt_ctf_field_type_common_validate(event_context_type
);
71 BT_LOGW("Invalid event class's context field type: "
77 if (event_payload_type
) {
78 ret
= bt_ctf_field_type_common_validate(event_payload_type
);
80 BT_LOGW("Invalid event class's payload field type: "
91 * This function resolves and validates the field types of a stream
92 * class. Only `packet_context_type`, `event_header_type`, and
93 * `stream_event_ctx_type` are resolved and validated; the other field
94 * type is used as an eventual resolving target.
96 * All parameters are owned by the caller.
99 int validate_stream_class_types(struct bt_ctf_private_value
*environment
,
100 struct bt_ctf_field_type_common
*packet_header_type
,
101 struct bt_ctf_field_type_common
*packet_context_type
,
102 struct bt_ctf_field_type_common
*event_header_type
,
103 struct bt_ctf_field_type_common
*stream_event_ctx_type
)
107 BT_LOGT("Validating stream class field types: "
108 "packet-header-ft-addr=%p, "
109 "packet-context-ft-addr=%p, "
110 "event-header-ft-addr=%p, "
111 "stream-event-context-ft-addr=%p",
112 packet_header_type
, packet_context_type
, event_header_type
,
113 stream_event_ctx_type
);
115 /* Resolve sequence type lengths and variant type tags first */
116 ret
= bt_ctf_resolve_types(environment
, packet_header_type
,
117 packet_context_type
, event_header_type
, stream_event_ctx_type
,
119 BT_CTF_RESOLVE_FLAG_PACKET_CONTEXT
|
120 BT_CTF_RESOLVE_FLAG_EVENT_HEADER
|
121 BT_CTF_RESOLVE_FLAG_STREAM_EVENT_CTX
);
123 BT_LOGW("Cannot resolve stream class field types: ret=%d",
128 /* Validate field types individually */
129 if (packet_context_type
) {
130 ret
= bt_ctf_field_type_common_validate(packet_context_type
);
132 BT_LOGW("Invalid stream class's packet context field type: "
138 if (event_header_type
) {
139 ret
= bt_ctf_field_type_common_validate(event_header_type
);
141 BT_LOGW("Invalid stream class's event header field type: "
147 if (stream_event_ctx_type
) {
148 ret
= bt_ctf_field_type_common_validate(
149 stream_event_ctx_type
);
151 BT_LOGW("Invalid stream class's event context field type: "
162 * This function resolves and validates the field types of a trace.
164 * All parameters are owned by the caller.
167 int validate_trace_types(struct bt_ctf_private_value
*environment
,
168 struct bt_ctf_field_type_common
*packet_header_type
)
172 BT_LOGT("Validating event class field types: "
173 "packet-header-ft-addr=%p", packet_header_type
);
175 /* Resolve sequence type lengths and variant type tags first */
176 ret
= bt_ctf_resolve_types(environment
, packet_header_type
,
177 NULL
, NULL
, NULL
, NULL
, NULL
,
178 BT_CTF_RESOLVE_FLAG_PACKET_HEADER
);
180 BT_LOGW("Cannot resolve trace field types: ret=%d",
185 /* Validate field types individually */
186 if (packet_header_type
) {
187 ret
= bt_ctf_field_type_common_validate(packet_header_type
);
189 BT_LOGW("Invalid trace's packet header field type: "
200 * Checks whether or not `field_type` contains a variant or a sequence
201 * field type, recursively. Returns 1 if it's the case.
203 * `field_type` is owned by the caller.
206 int field_type_contains_sequence_or_variant_ft(struct bt_ctf_field_type_common
*type
)
209 enum bt_ctf_field_type_id type_id
= bt_ctf_field_type_common_get_type_id(type
);
212 case BT_CTF_FIELD_TYPE_ID_SEQUENCE
:
213 case BT_CTF_FIELD_TYPE_ID_VARIANT
:
216 case BT_CTF_FIELD_TYPE_ID_ARRAY
:
217 case BT_CTF_FIELD_TYPE_ID_STRUCT
:
220 int field_count
= bt_ctf_field_type_common_get_field_count(type
);
222 if (field_count
< 0) {
227 for (i
= 0; i
< field_count
; ++i
) {
228 struct bt_ctf_field_type_common
*child_type
=
229 bt_ctf_field_type_common_borrow_field_at_index(
232 ret
= field_type_contains_sequence_or_variant_ft(
249 int bt_ctf_validate_class_types(struct bt_ctf_private_value
*environment
,
250 struct bt_ctf_field_type_common
*packet_header_type
,
251 struct bt_ctf_field_type_common
*packet_context_type
,
252 struct bt_ctf_field_type_common
*event_header_type
,
253 struct bt_ctf_field_type_common
*stream_event_ctx_type
,
254 struct bt_ctf_field_type_common
*event_context_type
,
255 struct bt_ctf_field_type_common
*event_payload_type
,
256 int trace_valid
, int stream_class_valid
, int event_class_valid
,
257 struct bt_ctf_validation_output
*output
,
258 enum bt_ctf_validation_flag validate_flags
,
259 bt_ctf_validation_flag_copy_field_type_func copy_field_type_func
)
262 int contains_seq_var
;
265 BT_LOGT("Validating field types: "
266 "packet-header-ft-addr=%p, "
267 "packet-context-ft-addr=%p, "
268 "event-header-ft-addr=%p, "
269 "stream-event-context-ft-addr=%p, "
270 "event-context-ft-addr=%p, "
271 "event-payload-ft-addr=%p, "
272 "trace-is-valid=%d, stream-class-is-valid=%d, "
273 "event-class-is-valid=%d, validation-flags=%x",
274 packet_header_type
, packet_context_type
, event_header_type
,
275 stream_event_ctx_type
, event_context_type
, event_payload_type
,
276 trace_valid
, stream_class_valid
, event_class_valid
,
277 (unsigned int) validate_flags
);
279 /* Clean output values */
280 memset(output
, 0, sizeof(*output
));
282 /* Set initial valid flags according to valid parameters */
284 output
->valid_flags
|= BT_CTF_VALIDATION_FLAG_TRACE
;
287 if (stream_class_valid
) {
288 output
->valid_flags
|= BT_CTF_VALIDATION_FLAG_STREAM
;
291 if (event_class_valid
) {
292 output
->valid_flags
|= BT_CTF_VALIDATION_FLAG_EVENT
;
295 /* Own the type parameters */
296 bt_ctf_object_get_ref(packet_header_type
);
297 bt_ctf_object_get_ref(packet_context_type
);
298 bt_ctf_object_get_ref(event_header_type
);
299 bt_ctf_object_get_ref(stream_event_ctx_type
);
300 bt_ctf_object_get_ref(event_context_type
);
301 bt_ctf_object_get_ref(event_payload_type
);
304 if ((validate_flags
& BT_CTF_VALIDATION_FLAG_TRACE
) && !trace_valid
) {
305 struct bt_ctf_field_type_common
*packet_header_type_copy
= NULL
;
307 /* Create field type copies */
308 if (packet_header_type
) {
310 field_type_contains_sequence_or_variant_ft(
312 if (contains_seq_var
< 0) {
313 ret
= contains_seq_var
;
315 } else if (!contains_seq_var
) {
316 /* No copy is needed */
317 packet_header_type_copy
= packet_header_type
;
318 bt_ctf_object_get_ref(packet_header_type_copy
);
319 goto skip_packet_header_type_copy
;
322 BT_LOGT_STR("Copying packet header field type because it contains at least one sequence or variant field type.");
323 packet_header_type_copy
=
324 copy_field_type_func(packet_header_type
);
325 if (!packet_header_type_copy
) {
327 BT_LOGE_STR("Cannot copy packet header field type.");
332 * Freeze this copy: if it's returned to the
333 * caller, it cannot be modified any way since
334 * it will be resolved.
336 bt_ctf_field_type_common_freeze(packet_header_type_copy
);
339 skip_packet_header_type_copy
:
340 /* Put original reference and move copy */
341 BT_CTF_OBJECT_MOVE_REF(packet_header_type
, packet_header_type_copy
);
343 /* Validate trace field types */
344 valid_ret
= validate_trace_types(environment
,
346 if (valid_ret
== 0) {
348 output
->valid_flags
|= BT_CTF_VALIDATION_FLAG_TRACE
;
352 /* Validate stream class */
353 if ((validate_flags
& BT_CTF_VALIDATION_FLAG_STREAM
) &&
354 !stream_class_valid
) {
355 struct bt_ctf_field_type_common
*packet_context_type_copy
= NULL
;
356 struct bt_ctf_field_type_common
*event_header_type_copy
= NULL
;
357 struct bt_ctf_field_type_common
*stream_event_ctx_type_copy
= NULL
;
359 if (packet_context_type
) {
361 field_type_contains_sequence_or_variant_ft(
362 packet_context_type
);
363 if (contains_seq_var
< 0) {
364 ret
= contains_seq_var
;
366 } else if (!contains_seq_var
) {
367 /* No copy is needed */
368 packet_context_type_copy
= packet_context_type
;
369 bt_ctf_object_get_ref(packet_context_type_copy
);
370 goto skip_packet_context_type_copy
;
373 BT_LOGT_STR("Copying packet context field type because it contains at least one sequence or variant field type.");
374 packet_context_type_copy
=
375 copy_field_type_func(packet_context_type
);
376 if (!packet_context_type_copy
) {
377 BT_LOGE_STR("Cannot copy packet context field type.");
378 goto sc_validation_error
;
382 * Freeze this copy: if it's returned to the
383 * caller, it cannot be modified any way since
384 * it will be resolved.
386 bt_ctf_field_type_common_freeze(packet_context_type_copy
);
389 skip_packet_context_type_copy
:
390 if (event_header_type
) {
392 field_type_contains_sequence_or_variant_ft(
394 if (contains_seq_var
< 0) {
395 ret
= contains_seq_var
;
397 } else if (!contains_seq_var
) {
398 /* No copy is needed */
399 event_header_type_copy
= event_header_type
;
400 bt_ctf_object_get_ref(event_header_type_copy
);
401 goto skip_event_header_type_copy
;
404 BT_LOGT_STR("Copying event header field type because it contains at least one sequence or variant field type.");
405 event_header_type_copy
=
406 copy_field_type_func(event_header_type
);
407 if (!event_header_type_copy
) {
408 BT_LOGE_STR("Cannot copy event header field type.");
409 goto sc_validation_error
;
413 * Freeze this copy: if it's returned to the
414 * caller, it cannot be modified any way since
415 * it will be resolved.
417 bt_ctf_field_type_common_freeze(event_header_type_copy
);
420 skip_event_header_type_copy
:
421 if (stream_event_ctx_type
) {
423 field_type_contains_sequence_or_variant_ft(
424 stream_event_ctx_type
);
425 if (contains_seq_var
< 0) {
426 ret
= contains_seq_var
;
428 } else if (!contains_seq_var
) {
429 /* No copy is needed */
430 stream_event_ctx_type_copy
=
431 stream_event_ctx_type
;
432 bt_ctf_object_get_ref(stream_event_ctx_type_copy
);
433 goto skip_stream_event_ctx_type_copy
;
436 BT_LOGT_STR("Copying stream event context field type because it contains at least one sequence or variant field type.");
437 stream_event_ctx_type_copy
=
438 copy_field_type_func(stream_event_ctx_type
);
439 if (!stream_event_ctx_type_copy
) {
440 BT_LOGE_STR("Cannot copy stream event context field type.");
441 goto sc_validation_error
;
445 * Freeze this copy: if it's returned to the
446 * caller, it cannot be modified any way since
447 * it will be resolved.
449 bt_ctf_field_type_common_freeze(stream_event_ctx_type_copy
);
452 skip_stream_event_ctx_type_copy
:
453 /* Put original references and move copies */
454 BT_CTF_OBJECT_MOVE_REF(packet_context_type
, packet_context_type_copy
);
455 BT_CTF_OBJECT_MOVE_REF(event_header_type
, event_header_type_copy
);
456 BT_CTF_OBJECT_MOVE_REF(stream_event_ctx_type
, stream_event_ctx_type_copy
);
458 /* Validate stream class field types */
459 valid_ret
= validate_stream_class_types(environment
,
460 packet_header_type
, packet_context_type
,
461 event_header_type
, stream_event_ctx_type
);
462 if (valid_ret
== 0) {
463 /* Stream class is valid */
464 output
->valid_flags
|= BT_CTF_VALIDATION_FLAG_STREAM
;
467 goto sc_validation_done
;
470 BT_CTF_OBJECT_PUT_REF_AND_RESET(packet_context_type_copy
);
471 BT_CTF_OBJECT_PUT_REF_AND_RESET(event_header_type_copy
);
472 BT_CTF_OBJECT_PUT_REF_AND_RESET(stream_event_ctx_type_copy
);
478 /* Validate event class */
479 if ((validate_flags
& BT_CTF_VALIDATION_FLAG_EVENT
) &&
480 !event_class_valid
) {
481 struct bt_ctf_field_type_common
*event_context_type_copy
= NULL
;
482 struct bt_ctf_field_type_common
*event_payload_type_copy
= NULL
;
484 if (event_context_type
) {
486 field_type_contains_sequence_or_variant_ft(
488 if (contains_seq_var
< 0) {
489 ret
= contains_seq_var
;
491 } else if (!contains_seq_var
) {
492 /* No copy is needed */
493 event_context_type_copy
= event_context_type
;
494 bt_ctf_object_get_ref(event_context_type_copy
);
495 goto skip_event_context_type_copy
;
498 BT_LOGT_STR("Copying event context field type because it contains at least one sequence or variant field type.");
499 event_context_type_copy
=
500 copy_field_type_func(event_context_type
);
501 if (!event_context_type_copy
) {
502 BT_LOGE_STR("Cannot copy event context field type.");
503 goto ec_validation_error
;
507 * Freeze this copy: if it's returned to the
508 * caller, it cannot be modified any way since
509 * it will be resolved.
511 bt_ctf_field_type_common_freeze(event_context_type_copy
);
514 skip_event_context_type_copy
:
515 if (event_payload_type
) {
517 field_type_contains_sequence_or_variant_ft(
519 if (contains_seq_var
< 0) {
520 ret
= contains_seq_var
;
522 } else if (!contains_seq_var
) {
523 /* No copy is needed */
524 event_payload_type_copy
= event_payload_type
;
525 bt_ctf_object_get_ref(event_payload_type_copy
);
526 goto skip_event_payload_type_copy
;
529 BT_LOGT_STR("Copying event payload field type because it contains at least one sequence or variant field type.");
530 event_payload_type_copy
=
531 copy_field_type_func(event_payload_type
);
532 if (!event_payload_type_copy
) {
533 BT_LOGE_STR("Cannot copy event payload field type.");
534 goto ec_validation_error
;
538 * Freeze this copy: if it's returned to the
539 * caller, it cannot be modified any way since
540 * it will be resolved.
542 bt_ctf_field_type_common_freeze(event_payload_type_copy
);
545 skip_event_payload_type_copy
:
546 /* Put original references and move copies */
547 BT_CTF_OBJECT_MOVE_REF(event_context_type
, event_context_type_copy
);
548 BT_CTF_OBJECT_MOVE_REF(event_payload_type
, event_payload_type_copy
);
550 /* Validate event class field types */
551 valid_ret
= validate_event_class_types(environment
,
552 packet_header_type
, packet_context_type
,
553 event_header_type
, stream_event_ctx_type
,
554 event_context_type
, event_payload_type
);
555 if (valid_ret
== 0) {
556 /* Event class is valid */
557 output
->valid_flags
|= BT_CTF_VALIDATION_FLAG_EVENT
;
560 goto ec_validation_done
;
563 BT_CTF_OBJECT_PUT_REF_AND_RESET(event_context_type_copy
);
564 BT_CTF_OBJECT_PUT_REF_AND_RESET(event_payload_type_copy
);
571 * Validation is complete. Move the field types that were used
572 * to validate (and that were possibly altered by the validation
573 * process) to the output values.
575 BT_CTF_OBJECT_MOVE_REF(output
->packet_header_type
, packet_header_type
);
576 BT_CTF_OBJECT_MOVE_REF(output
->packet_context_type
, packet_context_type
);
577 BT_CTF_OBJECT_MOVE_REF(output
->event_header_type
, event_header_type
);
578 BT_CTF_OBJECT_MOVE_REF(output
->stream_event_ctx_type
, stream_event_ctx_type
);
579 BT_CTF_OBJECT_MOVE_REF(output
->event_context_type
, event_context_type
);
580 BT_CTF_OBJECT_MOVE_REF(output
->event_payload_type
, event_payload_type
);
584 BT_CTF_OBJECT_PUT_REF_AND_RESET(packet_header_type
);
585 BT_CTF_OBJECT_PUT_REF_AND_RESET(packet_context_type
);
586 BT_CTF_OBJECT_PUT_REF_AND_RESET(event_header_type
);
587 BT_CTF_OBJECT_PUT_REF_AND_RESET(stream_event_ctx_type
);
588 BT_CTF_OBJECT_PUT_REF_AND_RESET(event_context_type
);
589 BT_CTF_OBJECT_PUT_REF_AND_RESET(event_payload_type
);
594 void bt_ctf_validation_replace_types(struct bt_ctf_trace_common
*trace
,
595 struct bt_ctf_stream_class_common
*stream_class
,
596 struct bt_ctf_event_class_common
*event_class
,
597 struct bt_ctf_validation_output
*output
,
598 enum bt_ctf_validation_flag replace_flags
)
600 if ((replace_flags
& BT_CTF_VALIDATION_FLAG_TRACE
) && trace
) {
601 bt_ctf_field_type_common_freeze(trace
->packet_header_field_type
);
602 BT_CTF_OBJECT_MOVE_REF(trace
->packet_header_field_type
,
603 output
->packet_header_type
);
606 if ((replace_flags
& BT_CTF_VALIDATION_FLAG_STREAM
) && stream_class
) {
607 bt_ctf_field_type_common_freeze(stream_class
->packet_context_field_type
);
608 bt_ctf_field_type_common_freeze(stream_class
->event_header_field_type
);
609 bt_ctf_field_type_common_freeze(stream_class
->event_context_field_type
);
610 BT_CTF_OBJECT_MOVE_REF(stream_class
->packet_context_field_type
,
611 output
->packet_context_type
);
612 BT_CTF_OBJECT_MOVE_REF(stream_class
->event_header_field_type
,
613 output
->event_header_type
);
614 BT_CTF_OBJECT_MOVE_REF(stream_class
->event_context_field_type
,
615 output
->stream_event_ctx_type
);
618 if ((replace_flags
& BT_CTF_VALIDATION_FLAG_EVENT
) && event_class
) {
619 bt_ctf_field_type_common_freeze(event_class
->context_field_type
);
620 bt_ctf_field_type_common_freeze(event_class
->payload_field_type
);
621 BT_CTF_OBJECT_MOVE_REF(event_class
->context_field_type
, output
->event_context_type
);
622 BT_CTF_OBJECT_MOVE_REF(event_class
->payload_field_type
, output
->event_payload_type
);
627 void bt_ctf_validation_output_put_types(
628 struct bt_ctf_validation_output
*output
)
630 BT_CTF_OBJECT_PUT_REF_AND_RESET(output
->packet_header_type
);
631 BT_CTF_OBJECT_PUT_REF_AND_RESET(output
->packet_context_type
);
632 BT_CTF_OBJECT_PUT_REF_AND_RESET(output
->event_header_type
);
633 BT_CTF_OBJECT_PUT_REF_AND_RESET(output
->stream_event_ctx_type
);
634 BT_CTF_OBJECT_PUT_REF_AND_RESET(output
->event_context_type
);
635 BT_CTF_OBJECT_PUT_REF_AND_RESET(output
->event_payload_type
);