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(
248 int bt_ctf_validate_class_types(struct bt_ctf_private_value
*environment
,
249 struct bt_ctf_field_type_common
*packet_header_type
,
250 struct bt_ctf_field_type_common
*packet_context_type
,
251 struct bt_ctf_field_type_common
*event_header_type
,
252 struct bt_ctf_field_type_common
*stream_event_ctx_type
,
253 struct bt_ctf_field_type_common
*event_context_type
,
254 struct bt_ctf_field_type_common
*event_payload_type
,
255 int trace_valid
, int stream_class_valid
, int event_class_valid
,
256 struct bt_ctf_validation_output
*output
,
257 enum bt_ctf_validation_flag validate_flags
,
258 bt_ctf_validation_flag_copy_field_type_func copy_field_type_func
)
261 int contains_seq_var
;
264 BT_LOGT("Validating field types: "
265 "packet-header-ft-addr=%p, "
266 "packet-context-ft-addr=%p, "
267 "event-header-ft-addr=%p, "
268 "stream-event-context-ft-addr=%p, "
269 "event-context-ft-addr=%p, "
270 "event-payload-ft-addr=%p, "
271 "trace-is-valid=%d, stream-class-is-valid=%d, "
272 "event-class-is-valid=%d, validation-flags=%x",
273 packet_header_type
, packet_context_type
, event_header_type
,
274 stream_event_ctx_type
, event_context_type
, event_payload_type
,
275 trace_valid
, stream_class_valid
, event_class_valid
,
276 (unsigned int) validate_flags
);
278 /* Clean output values */
279 memset(output
, 0, sizeof(*output
));
281 /* Set initial valid flags according to valid parameters */
283 output
->valid_flags
|= BT_CTF_VALIDATION_FLAG_TRACE
;
286 if (stream_class_valid
) {
287 output
->valid_flags
|= BT_CTF_VALIDATION_FLAG_STREAM
;
290 if (event_class_valid
) {
291 output
->valid_flags
|= BT_CTF_VALIDATION_FLAG_EVENT
;
294 /* Own the type parameters */
295 bt_ctf_object_get_ref(packet_header_type
);
296 bt_ctf_object_get_ref(packet_context_type
);
297 bt_ctf_object_get_ref(event_header_type
);
298 bt_ctf_object_get_ref(stream_event_ctx_type
);
299 bt_ctf_object_get_ref(event_context_type
);
300 bt_ctf_object_get_ref(event_payload_type
);
303 if ((validate_flags
& BT_CTF_VALIDATION_FLAG_TRACE
) && !trace_valid
) {
304 struct bt_ctf_field_type_common
*packet_header_type_copy
= NULL
;
306 /* Create field type copies */
307 if (packet_header_type
) {
309 field_type_contains_sequence_or_variant_ft(
311 if (contains_seq_var
< 0) {
312 ret
= contains_seq_var
;
314 } else if (!contains_seq_var
) {
315 /* No copy is needed */
316 packet_header_type_copy
= packet_header_type
;
317 bt_ctf_object_get_ref(packet_header_type_copy
);
318 goto skip_packet_header_type_copy
;
321 BT_LOGT_STR("Copying packet header field type because it contains at least one sequence or variant field type.");
322 packet_header_type_copy
=
323 copy_field_type_func(packet_header_type
);
324 if (!packet_header_type_copy
) {
326 BT_LOGE_STR("Cannot copy packet header field type.");
331 * Freeze this copy: if it's returned to the
332 * caller, it cannot be modified any way since
333 * it will be resolved.
335 bt_ctf_field_type_common_freeze(packet_header_type_copy
);
338 skip_packet_header_type_copy
:
339 /* Put original reference and move copy */
340 BT_CTF_OBJECT_MOVE_REF(packet_header_type
, packet_header_type_copy
);
342 /* Validate trace field types */
343 valid_ret
= validate_trace_types(environment
,
345 if (valid_ret
== 0) {
347 output
->valid_flags
|= BT_CTF_VALIDATION_FLAG_TRACE
;
351 /* Validate stream class */
352 if ((validate_flags
& BT_CTF_VALIDATION_FLAG_STREAM
) &&
353 !stream_class_valid
) {
354 struct bt_ctf_field_type_common
*packet_context_type_copy
= NULL
;
355 struct bt_ctf_field_type_common
*event_header_type_copy
= NULL
;
356 struct bt_ctf_field_type_common
*stream_event_ctx_type_copy
= NULL
;
358 if (packet_context_type
) {
360 field_type_contains_sequence_or_variant_ft(
361 packet_context_type
);
362 if (contains_seq_var
< 0) {
363 ret
= contains_seq_var
;
365 } else if (!contains_seq_var
) {
366 /* No copy is needed */
367 packet_context_type_copy
= packet_context_type
;
368 bt_ctf_object_get_ref(packet_context_type_copy
);
369 goto skip_packet_context_type_copy
;
372 BT_LOGT_STR("Copying packet context field type because it contains at least one sequence or variant field type.");
373 packet_context_type_copy
=
374 copy_field_type_func(packet_context_type
);
375 if (!packet_context_type_copy
) {
376 BT_LOGE_STR("Cannot copy packet context field type.");
377 goto sc_validation_error
;
381 * Freeze this copy: if it's returned to the
382 * caller, it cannot be modified any way since
383 * it will be resolved.
385 bt_ctf_field_type_common_freeze(packet_context_type_copy
);
388 skip_packet_context_type_copy
:
389 if (event_header_type
) {
391 field_type_contains_sequence_or_variant_ft(
393 if (contains_seq_var
< 0) {
394 ret
= contains_seq_var
;
396 } else if (!contains_seq_var
) {
397 /* No copy is needed */
398 event_header_type_copy
= event_header_type
;
399 bt_ctf_object_get_ref(event_header_type_copy
);
400 goto skip_event_header_type_copy
;
403 BT_LOGT_STR("Copying event header field type because it contains at least one sequence or variant field type.");
404 event_header_type_copy
=
405 copy_field_type_func(event_header_type
);
406 if (!event_header_type_copy
) {
407 BT_LOGE_STR("Cannot copy event header field type.");
408 goto sc_validation_error
;
412 * Freeze this copy: if it's returned to the
413 * caller, it cannot be modified any way since
414 * it will be resolved.
416 bt_ctf_field_type_common_freeze(event_header_type_copy
);
419 skip_event_header_type_copy
:
420 if (stream_event_ctx_type
) {
422 field_type_contains_sequence_or_variant_ft(
423 stream_event_ctx_type
);
424 if (contains_seq_var
< 0) {
425 ret
= contains_seq_var
;
427 } else if (!contains_seq_var
) {
428 /* No copy is needed */
429 stream_event_ctx_type_copy
=
430 stream_event_ctx_type
;
431 bt_ctf_object_get_ref(stream_event_ctx_type_copy
);
432 goto skip_stream_event_ctx_type_copy
;
435 BT_LOGT_STR("Copying stream event context field type because it contains at least one sequence or variant field type.");
436 stream_event_ctx_type_copy
=
437 copy_field_type_func(stream_event_ctx_type
);
438 if (!stream_event_ctx_type_copy
) {
439 BT_LOGE_STR("Cannot copy stream event context field type.");
440 goto sc_validation_error
;
444 * Freeze this copy: if it's returned to the
445 * caller, it cannot be modified any way since
446 * it will be resolved.
448 bt_ctf_field_type_common_freeze(stream_event_ctx_type_copy
);
451 skip_stream_event_ctx_type_copy
:
452 /* Put original references and move copies */
453 BT_CTF_OBJECT_MOVE_REF(packet_context_type
, packet_context_type_copy
);
454 BT_CTF_OBJECT_MOVE_REF(event_header_type
, event_header_type_copy
);
455 BT_CTF_OBJECT_MOVE_REF(stream_event_ctx_type
, stream_event_ctx_type_copy
);
457 /* Validate stream class field types */
458 valid_ret
= validate_stream_class_types(environment
,
459 packet_header_type
, packet_context_type
,
460 event_header_type
, stream_event_ctx_type
);
461 if (valid_ret
== 0) {
462 /* Stream class is valid */
463 output
->valid_flags
|= BT_CTF_VALIDATION_FLAG_STREAM
;
466 goto sc_validation_done
;
469 BT_CTF_OBJECT_PUT_REF_AND_RESET(packet_context_type_copy
);
470 BT_CTF_OBJECT_PUT_REF_AND_RESET(event_header_type_copy
);
471 BT_CTF_OBJECT_PUT_REF_AND_RESET(stream_event_ctx_type_copy
);
477 /* Validate event class */
478 if ((validate_flags
& BT_CTF_VALIDATION_FLAG_EVENT
) &&
479 !event_class_valid
) {
480 struct bt_ctf_field_type_common
*event_context_type_copy
= NULL
;
481 struct bt_ctf_field_type_common
*event_payload_type_copy
= NULL
;
483 if (event_context_type
) {
485 field_type_contains_sequence_or_variant_ft(
487 if (contains_seq_var
< 0) {
488 ret
= contains_seq_var
;
490 } else if (!contains_seq_var
) {
491 /* No copy is needed */
492 event_context_type_copy
= event_context_type
;
493 bt_ctf_object_get_ref(event_context_type_copy
);
494 goto skip_event_context_type_copy
;
497 BT_LOGT_STR("Copying event context field type because it contains at least one sequence or variant field type.");
498 event_context_type_copy
=
499 copy_field_type_func(event_context_type
);
500 if (!event_context_type_copy
) {
501 BT_LOGE_STR("Cannot copy event context field type.");
502 goto ec_validation_error
;
506 * Freeze this copy: if it's returned to the
507 * caller, it cannot be modified any way since
508 * it will be resolved.
510 bt_ctf_field_type_common_freeze(event_context_type_copy
);
513 skip_event_context_type_copy
:
514 if (event_payload_type
) {
516 field_type_contains_sequence_or_variant_ft(
518 if (contains_seq_var
< 0) {
519 ret
= contains_seq_var
;
521 } else if (!contains_seq_var
) {
522 /* No copy is needed */
523 event_payload_type_copy
= event_payload_type
;
524 bt_ctf_object_get_ref(event_payload_type_copy
);
525 goto skip_event_payload_type_copy
;
528 BT_LOGT_STR("Copying event payload field type because it contains at least one sequence or variant field type.");
529 event_payload_type_copy
=
530 copy_field_type_func(event_payload_type
);
531 if (!event_payload_type_copy
) {
532 BT_LOGE_STR("Cannot copy event payload field type.");
533 goto ec_validation_error
;
537 * Freeze this copy: if it's returned to the
538 * caller, it cannot be modified any way since
539 * it will be resolved.
541 bt_ctf_field_type_common_freeze(event_payload_type_copy
);
544 skip_event_payload_type_copy
:
545 /* Put original references and move copies */
546 BT_CTF_OBJECT_MOVE_REF(event_context_type
, event_context_type_copy
);
547 BT_CTF_OBJECT_MOVE_REF(event_payload_type
, event_payload_type_copy
);
549 /* Validate event class field types */
550 valid_ret
= validate_event_class_types(environment
,
551 packet_header_type
, packet_context_type
,
552 event_header_type
, stream_event_ctx_type
,
553 event_context_type
, event_payload_type
);
554 if (valid_ret
== 0) {
555 /* Event class is valid */
556 output
->valid_flags
|= BT_CTF_VALIDATION_FLAG_EVENT
;
559 goto ec_validation_done
;
562 BT_CTF_OBJECT_PUT_REF_AND_RESET(event_context_type_copy
);
563 BT_CTF_OBJECT_PUT_REF_AND_RESET(event_payload_type_copy
);
570 * Validation is complete. Move the field types that were used
571 * to validate (and that were possibly altered by the validation
572 * process) to the output values.
574 BT_CTF_OBJECT_MOVE_REF(output
->packet_header_type
, packet_header_type
);
575 BT_CTF_OBJECT_MOVE_REF(output
->packet_context_type
, packet_context_type
);
576 BT_CTF_OBJECT_MOVE_REF(output
->event_header_type
, event_header_type
);
577 BT_CTF_OBJECT_MOVE_REF(output
->stream_event_ctx_type
, stream_event_ctx_type
);
578 BT_CTF_OBJECT_MOVE_REF(output
->event_context_type
, event_context_type
);
579 BT_CTF_OBJECT_MOVE_REF(output
->event_payload_type
, event_payload_type
);
583 BT_CTF_OBJECT_PUT_REF_AND_RESET(packet_header_type
);
584 BT_CTF_OBJECT_PUT_REF_AND_RESET(packet_context_type
);
585 BT_CTF_OBJECT_PUT_REF_AND_RESET(event_header_type
);
586 BT_CTF_OBJECT_PUT_REF_AND_RESET(stream_event_ctx_type
);
587 BT_CTF_OBJECT_PUT_REF_AND_RESET(event_context_type
);
588 BT_CTF_OBJECT_PUT_REF_AND_RESET(event_payload_type
);
592 void bt_ctf_validation_replace_types(struct bt_ctf_trace_common
*trace
,
593 struct bt_ctf_stream_class_common
*stream_class
,
594 struct bt_ctf_event_class_common
*event_class
,
595 struct bt_ctf_validation_output
*output
,
596 enum bt_ctf_validation_flag replace_flags
)
598 if ((replace_flags
& BT_CTF_VALIDATION_FLAG_TRACE
) && trace
) {
599 bt_ctf_field_type_common_freeze(trace
->packet_header_field_type
);
600 BT_CTF_OBJECT_MOVE_REF(trace
->packet_header_field_type
,
601 output
->packet_header_type
);
604 if ((replace_flags
& BT_CTF_VALIDATION_FLAG_STREAM
) && stream_class
) {
605 bt_ctf_field_type_common_freeze(stream_class
->packet_context_field_type
);
606 bt_ctf_field_type_common_freeze(stream_class
->event_header_field_type
);
607 bt_ctf_field_type_common_freeze(stream_class
->event_context_field_type
);
608 BT_CTF_OBJECT_MOVE_REF(stream_class
->packet_context_field_type
,
609 output
->packet_context_type
);
610 BT_CTF_OBJECT_MOVE_REF(stream_class
->event_header_field_type
,
611 output
->event_header_type
);
612 BT_CTF_OBJECT_MOVE_REF(stream_class
->event_context_field_type
,
613 output
->stream_event_ctx_type
);
616 if ((replace_flags
& BT_CTF_VALIDATION_FLAG_EVENT
) && event_class
) {
617 bt_ctf_field_type_common_freeze(event_class
->context_field_type
);
618 bt_ctf_field_type_common_freeze(event_class
->payload_field_type
);
619 BT_CTF_OBJECT_MOVE_REF(event_class
->context_field_type
, output
->event_context_type
);
620 BT_CTF_OBJECT_MOVE_REF(event_class
->payload_field_type
, output
->event_payload_type
);
624 void bt_ctf_validation_output_put_types(
625 struct bt_ctf_validation_output
*output
)
627 BT_CTF_OBJECT_PUT_REF_AND_RESET(output
->packet_header_type
);
628 BT_CTF_OBJECT_PUT_REF_AND_RESET(output
->packet_context_type
);
629 BT_CTF_OBJECT_PUT_REF_AND_RESET(output
->event_header_type
);
630 BT_CTF_OBJECT_PUT_REF_AND_RESET(output
->stream_event_ctx_type
);
631 BT_CTF_OBJECT_PUT_REF_AND_RESET(output
->event_context_type
);
632 BT_CTF_OBJECT_PUT_REF_AND_RESET(output
->event_payload_type
);