4 * Babeltrace - CTF writer: Validation of trace, stream class, and event class
6 * Copyright 2016-2018 Philippe Proulx <pproulx@efficios.com>
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 #define BT_LOG_TAG "CTF-WRITER-VALIDATION"
30 #include <babeltrace2/ctf-writer/object.h>
32 #include "common/babeltrace.h"
34 #include "assert-pre.h"
35 #include "event-class.h"
36 #include "field-types.h"
37 #include "field-types.h"
39 #include "stream-class.h"
41 #include "validation.h"
45 * This function resolves and validates the field types of an event
46 * class. Only `event_context_type` and `event_payload_type` are
47 * resolved and validated; the other field types are used as eventual
50 * All parameters are owned by the caller.
53 int validate_event_class_types(struct bt_ctf_private_value
*environment
,
54 struct bt_ctf_field_type_common
*packet_header_type
,
55 struct bt_ctf_field_type_common
*packet_context_type
,
56 struct bt_ctf_field_type_common
*event_header_type
,
57 struct bt_ctf_field_type_common
*stream_event_ctx_type
,
58 struct bt_ctf_field_type_common
*event_context_type
,
59 struct bt_ctf_field_type_common
*event_payload_type
)
63 BT_LOGV("Validating event class field types: "
64 "packet-header-ft-addr=%p, "
65 "packet-context-ft-addr=%p, "
66 "event-header-ft-addr=%p, "
67 "stream-event-context-ft-addr=%p, "
68 "event-context-ft-addr=%p, "
69 "event-payload-ft-addr=%p",
70 packet_header_type
, packet_context_type
, event_header_type
,
71 stream_event_ctx_type
, event_context_type
, event_payload_type
);
73 /* Resolve sequence type lengths and variant type tags first */
74 ret
= bt_ctf_resolve_types(environment
, packet_header_type
,
75 packet_context_type
, event_header_type
, stream_event_ctx_type
,
76 event_context_type
, event_payload_type
,
77 BT_CTF_RESOLVE_FLAG_EVENT_CONTEXT
|
78 BT_CTF_RESOLVE_FLAG_EVENT_PAYLOAD
);
80 BT_LOGW("Cannot resolve event class field types: ret=%d",
85 /* Validate field types individually */
86 if (event_context_type
) {
87 ret
= bt_ctf_field_type_common_validate(event_context_type
);
89 BT_LOGW("Invalid event class's context field type: "
95 if (event_payload_type
) {
96 ret
= bt_ctf_field_type_common_validate(event_payload_type
);
98 BT_LOGW("Invalid event class's payload field type: "
109 * This function resolves and validates the field types of a stream
110 * class. Only `packet_context_type`, `event_header_type`, and
111 * `stream_event_ctx_type` are resolved and validated; the other field
112 * type is used as an eventual resolving target.
114 * All parameters are owned by the caller.
117 int validate_stream_class_types(struct bt_ctf_private_value
*environment
,
118 struct bt_ctf_field_type_common
*packet_header_type
,
119 struct bt_ctf_field_type_common
*packet_context_type
,
120 struct bt_ctf_field_type_common
*event_header_type
,
121 struct bt_ctf_field_type_common
*stream_event_ctx_type
)
125 BT_LOGV("Validating stream class field types: "
126 "packet-header-ft-addr=%p, "
127 "packet-context-ft-addr=%p, "
128 "event-header-ft-addr=%p, "
129 "stream-event-context-ft-addr=%p",
130 packet_header_type
, packet_context_type
, event_header_type
,
131 stream_event_ctx_type
);
133 /* Resolve sequence type lengths and variant type tags first */
134 ret
= bt_ctf_resolve_types(environment
, packet_header_type
,
135 packet_context_type
, event_header_type
, stream_event_ctx_type
,
137 BT_CTF_RESOLVE_FLAG_PACKET_CONTEXT
|
138 BT_CTF_RESOLVE_FLAG_EVENT_HEADER
|
139 BT_CTF_RESOLVE_FLAG_STREAM_EVENT_CTX
);
141 BT_LOGW("Cannot resolve stream class field types: ret=%d",
146 /* Validate field types individually */
147 if (packet_context_type
) {
148 ret
= bt_ctf_field_type_common_validate(packet_context_type
);
150 BT_LOGW("Invalid stream class's packet context field type: "
156 if (event_header_type
) {
157 ret
= bt_ctf_field_type_common_validate(event_header_type
);
159 BT_LOGW("Invalid stream class's event header field type: "
165 if (stream_event_ctx_type
) {
166 ret
= bt_ctf_field_type_common_validate(
167 stream_event_ctx_type
);
169 BT_LOGW("Invalid stream class's event context field type: "
180 * This function resolves and validates the field types of a trace.
182 * All parameters are owned by the caller.
185 int validate_trace_types(struct bt_ctf_private_value
*environment
,
186 struct bt_ctf_field_type_common
*packet_header_type
)
190 BT_LOGV("Validating event class field types: "
191 "packet-header-ft-addr=%p", packet_header_type
);
193 /* Resolve sequence type lengths and variant type tags first */
194 ret
= bt_ctf_resolve_types(environment
, packet_header_type
,
195 NULL
, NULL
, NULL
, NULL
, NULL
,
196 BT_CTF_RESOLVE_FLAG_PACKET_HEADER
);
198 BT_LOGW("Cannot resolve trace field types: ret=%d",
203 /* Validate field types individually */
204 if (packet_header_type
) {
205 ret
= bt_ctf_field_type_common_validate(packet_header_type
);
207 BT_LOGW("Invalid trace's packet header field type: "
218 * Checks whether or not `field_type` contains a variant or a sequence
219 * field type, recursively. Returns 1 if it's the case.
221 * `field_type` is owned by the caller.
224 int field_type_contains_sequence_or_variant_ft(struct bt_ctf_field_type_common
*type
)
227 enum bt_ctf_field_type_id type_id
= bt_ctf_field_type_common_get_type_id(type
);
230 case BT_CTF_FIELD_TYPE_ID_SEQUENCE
:
231 case BT_CTF_FIELD_TYPE_ID_VARIANT
:
234 case BT_CTF_FIELD_TYPE_ID_ARRAY
:
235 case BT_CTF_FIELD_TYPE_ID_STRUCT
:
238 int field_count
= bt_ctf_field_type_common_get_field_count(type
);
240 if (field_count
< 0) {
245 for (i
= 0; i
< field_count
; ++i
) {
246 struct bt_ctf_field_type_common
*child_type
=
247 bt_ctf_field_type_common_borrow_field_at_index(
250 ret
= field_type_contains_sequence_or_variant_ft(
267 int bt_ctf_validate_class_types(struct bt_ctf_private_value
*environment
,
268 struct bt_ctf_field_type_common
*packet_header_type
,
269 struct bt_ctf_field_type_common
*packet_context_type
,
270 struct bt_ctf_field_type_common
*event_header_type
,
271 struct bt_ctf_field_type_common
*stream_event_ctx_type
,
272 struct bt_ctf_field_type_common
*event_context_type
,
273 struct bt_ctf_field_type_common
*event_payload_type
,
274 int trace_valid
, int stream_class_valid
, int event_class_valid
,
275 struct bt_ctf_validation_output
*output
,
276 enum bt_ctf_validation_flag validate_flags
,
277 bt_ctf_validation_flag_copy_field_type_func copy_field_type_func
)
280 int contains_seq_var
;
283 BT_LOGV("Validating field types: "
284 "packet-header-ft-addr=%p, "
285 "packet-context-ft-addr=%p, "
286 "event-header-ft-addr=%p, "
287 "stream-event-context-ft-addr=%p, "
288 "event-context-ft-addr=%p, "
289 "event-payload-ft-addr=%p, "
290 "trace-is-valid=%d, stream-class-is-valid=%d, "
291 "event-class-is-valid=%d, validation-flags=%x",
292 packet_header_type
, packet_context_type
, event_header_type
,
293 stream_event_ctx_type
, event_context_type
, event_payload_type
,
294 trace_valid
, stream_class_valid
, event_class_valid
,
295 (unsigned int) validate_flags
);
297 /* Clean output values */
298 memset(output
, 0, sizeof(*output
));
300 /* Set initial valid flags according to valid parameters */
302 output
->valid_flags
|= BT_CTF_VALIDATION_FLAG_TRACE
;
305 if (stream_class_valid
) {
306 output
->valid_flags
|= BT_CTF_VALIDATION_FLAG_STREAM
;
309 if (event_class_valid
) {
310 output
->valid_flags
|= BT_CTF_VALIDATION_FLAG_EVENT
;
313 /* Own the type parameters */
314 bt_ctf_object_get_ref(packet_header_type
);
315 bt_ctf_object_get_ref(packet_context_type
);
316 bt_ctf_object_get_ref(event_header_type
);
317 bt_ctf_object_get_ref(stream_event_ctx_type
);
318 bt_ctf_object_get_ref(event_context_type
);
319 bt_ctf_object_get_ref(event_payload_type
);
322 if ((validate_flags
& BT_CTF_VALIDATION_FLAG_TRACE
) && !trace_valid
) {
323 struct bt_ctf_field_type_common
*packet_header_type_copy
= NULL
;
325 /* Create field type copies */
326 if (packet_header_type
) {
328 field_type_contains_sequence_or_variant_ft(
330 if (contains_seq_var
< 0) {
331 ret
= contains_seq_var
;
333 } else if (!contains_seq_var
) {
334 /* No copy is needed */
335 packet_header_type_copy
= packet_header_type
;
336 bt_ctf_object_get_ref(packet_header_type_copy
);
337 goto skip_packet_header_type_copy
;
340 BT_LOGV_STR("Copying packet header field type because it contains at least one sequence or variant field type.");
341 packet_header_type_copy
=
342 copy_field_type_func(packet_header_type
);
343 if (!packet_header_type_copy
) {
345 BT_LOGE_STR("Cannot copy packet header field type.");
350 * Freeze this copy: if it's returned to the
351 * caller, it cannot be modified any way since
352 * it will be resolved.
354 bt_ctf_field_type_common_freeze(packet_header_type_copy
);
357 skip_packet_header_type_copy
:
358 /* Put original reference and move copy */
359 BT_CTF_OBJECT_MOVE_REF(packet_header_type
, packet_header_type_copy
);
361 /* Validate trace field types */
362 valid_ret
= validate_trace_types(environment
,
364 if (valid_ret
== 0) {
366 output
->valid_flags
|= BT_CTF_VALIDATION_FLAG_TRACE
;
370 /* Validate stream class */
371 if ((validate_flags
& BT_CTF_VALIDATION_FLAG_STREAM
) &&
372 !stream_class_valid
) {
373 struct bt_ctf_field_type_common
*packet_context_type_copy
= NULL
;
374 struct bt_ctf_field_type_common
*event_header_type_copy
= NULL
;
375 struct bt_ctf_field_type_common
*stream_event_ctx_type_copy
= NULL
;
377 if (packet_context_type
) {
379 field_type_contains_sequence_or_variant_ft(
380 packet_context_type
);
381 if (contains_seq_var
< 0) {
382 ret
= contains_seq_var
;
384 } else if (!contains_seq_var
) {
385 /* No copy is needed */
386 packet_context_type_copy
= packet_context_type
;
387 bt_ctf_object_get_ref(packet_context_type_copy
);
388 goto skip_packet_context_type_copy
;
391 BT_LOGV_STR("Copying packet context field type because it contains at least one sequence or variant field type.");
392 packet_context_type_copy
=
393 copy_field_type_func(packet_context_type
);
394 if (!packet_context_type_copy
) {
395 BT_LOGE_STR("Cannot copy packet context field type.");
396 goto sc_validation_error
;
400 * Freeze this copy: if it's returned to the
401 * caller, it cannot be modified any way since
402 * it will be resolved.
404 bt_ctf_field_type_common_freeze(packet_context_type_copy
);
407 skip_packet_context_type_copy
:
408 if (event_header_type
) {
410 field_type_contains_sequence_or_variant_ft(
412 if (contains_seq_var
< 0) {
413 ret
= contains_seq_var
;
415 } else if (!contains_seq_var
) {
416 /* No copy is needed */
417 event_header_type_copy
= event_header_type
;
418 bt_ctf_object_get_ref(event_header_type_copy
);
419 goto skip_event_header_type_copy
;
422 BT_LOGV_STR("Copying event header field type because it contains at least one sequence or variant field type.");
423 event_header_type_copy
=
424 copy_field_type_func(event_header_type
);
425 if (!event_header_type_copy
) {
426 BT_LOGE_STR("Cannot copy event header field type.");
427 goto sc_validation_error
;
431 * Freeze this copy: if it's returned to the
432 * caller, it cannot be modified any way since
433 * it will be resolved.
435 bt_ctf_field_type_common_freeze(event_header_type_copy
);
438 skip_event_header_type_copy
:
439 if (stream_event_ctx_type
) {
441 field_type_contains_sequence_or_variant_ft(
442 stream_event_ctx_type
);
443 if (contains_seq_var
< 0) {
444 ret
= contains_seq_var
;
446 } else if (!contains_seq_var
) {
447 /* No copy is needed */
448 stream_event_ctx_type_copy
=
449 stream_event_ctx_type
;
450 bt_ctf_object_get_ref(stream_event_ctx_type_copy
);
451 goto skip_stream_event_ctx_type_copy
;
454 BT_LOGV_STR("Copying stream event context field type because it contains at least one sequence or variant field type.");
455 stream_event_ctx_type_copy
=
456 copy_field_type_func(stream_event_ctx_type
);
457 if (!stream_event_ctx_type_copy
) {
458 BT_LOGE_STR("Cannot copy stream event context field type.");
459 goto sc_validation_error
;
463 * Freeze this copy: if it's returned to the
464 * caller, it cannot be modified any way since
465 * it will be resolved.
467 bt_ctf_field_type_common_freeze(stream_event_ctx_type_copy
);
470 skip_stream_event_ctx_type_copy
:
471 /* Put original references and move copies */
472 BT_CTF_OBJECT_MOVE_REF(packet_context_type
, packet_context_type_copy
);
473 BT_CTF_OBJECT_MOVE_REF(event_header_type
, event_header_type_copy
);
474 BT_CTF_OBJECT_MOVE_REF(stream_event_ctx_type
, stream_event_ctx_type_copy
);
476 /* Validate stream class field types */
477 valid_ret
= validate_stream_class_types(environment
,
478 packet_header_type
, packet_context_type
,
479 event_header_type
, stream_event_ctx_type
);
480 if (valid_ret
== 0) {
481 /* Stream class is valid */
482 output
->valid_flags
|= BT_CTF_VALIDATION_FLAG_STREAM
;
485 goto sc_validation_done
;
488 BT_CTF_OBJECT_PUT_REF_AND_RESET(packet_context_type_copy
);
489 BT_CTF_OBJECT_PUT_REF_AND_RESET(event_header_type_copy
);
490 BT_CTF_OBJECT_PUT_REF_AND_RESET(stream_event_ctx_type_copy
);
496 /* Validate event class */
497 if ((validate_flags
& BT_CTF_VALIDATION_FLAG_EVENT
) &&
498 !event_class_valid
) {
499 struct bt_ctf_field_type_common
*event_context_type_copy
= NULL
;
500 struct bt_ctf_field_type_common
*event_payload_type_copy
= NULL
;
502 if (event_context_type
) {
504 field_type_contains_sequence_or_variant_ft(
506 if (contains_seq_var
< 0) {
507 ret
= contains_seq_var
;
509 } else if (!contains_seq_var
) {
510 /* No copy is needed */
511 event_context_type_copy
= event_context_type
;
512 bt_ctf_object_get_ref(event_context_type_copy
);
513 goto skip_event_context_type_copy
;
516 BT_LOGV_STR("Copying event context field type because it contains at least one sequence or variant field type.");
517 event_context_type_copy
=
518 copy_field_type_func(event_context_type
);
519 if (!event_context_type_copy
) {
520 BT_LOGE_STR("Cannot copy event context field type.");
521 goto ec_validation_error
;
525 * Freeze this copy: if it's returned to the
526 * caller, it cannot be modified any way since
527 * it will be resolved.
529 bt_ctf_field_type_common_freeze(event_context_type_copy
);
532 skip_event_context_type_copy
:
533 if (event_payload_type
) {
535 field_type_contains_sequence_or_variant_ft(
537 if (contains_seq_var
< 0) {
538 ret
= contains_seq_var
;
540 } else if (!contains_seq_var
) {
541 /* No copy is needed */
542 event_payload_type_copy
= event_payload_type
;
543 bt_ctf_object_get_ref(event_payload_type_copy
);
544 goto skip_event_payload_type_copy
;
547 BT_LOGV_STR("Copying event payload field type because it contains at least one sequence or variant field type.");
548 event_payload_type_copy
=
549 copy_field_type_func(event_payload_type
);
550 if (!event_payload_type_copy
) {
551 BT_LOGE_STR("Cannot copy event payload field type.");
552 goto ec_validation_error
;
556 * Freeze this copy: if it's returned to the
557 * caller, it cannot be modified any way since
558 * it will be resolved.
560 bt_ctf_field_type_common_freeze(event_payload_type_copy
);
563 skip_event_payload_type_copy
:
564 /* Put original references and move copies */
565 BT_CTF_OBJECT_MOVE_REF(event_context_type
, event_context_type_copy
);
566 BT_CTF_OBJECT_MOVE_REF(event_payload_type
, event_payload_type_copy
);
568 /* Validate event class field types */
569 valid_ret
= validate_event_class_types(environment
,
570 packet_header_type
, packet_context_type
,
571 event_header_type
, stream_event_ctx_type
,
572 event_context_type
, event_payload_type
);
573 if (valid_ret
== 0) {
574 /* Event class is valid */
575 output
->valid_flags
|= BT_CTF_VALIDATION_FLAG_EVENT
;
578 goto ec_validation_done
;
581 BT_CTF_OBJECT_PUT_REF_AND_RESET(event_context_type_copy
);
582 BT_CTF_OBJECT_PUT_REF_AND_RESET(event_payload_type_copy
);
589 * Validation is complete. Move the field types that were used
590 * to validate (and that were possibly altered by the validation
591 * process) to the output values.
593 BT_CTF_OBJECT_MOVE_REF(output
->packet_header_type
, packet_header_type
);
594 BT_CTF_OBJECT_MOVE_REF(output
->packet_context_type
, packet_context_type
);
595 BT_CTF_OBJECT_MOVE_REF(output
->event_header_type
, event_header_type
);
596 BT_CTF_OBJECT_MOVE_REF(output
->stream_event_ctx_type
, stream_event_ctx_type
);
597 BT_CTF_OBJECT_MOVE_REF(output
->event_context_type
, event_context_type
);
598 BT_CTF_OBJECT_MOVE_REF(output
->event_payload_type
, event_payload_type
);
602 BT_CTF_OBJECT_PUT_REF_AND_RESET(packet_header_type
);
603 BT_CTF_OBJECT_PUT_REF_AND_RESET(packet_context_type
);
604 BT_CTF_OBJECT_PUT_REF_AND_RESET(event_header_type
);
605 BT_CTF_OBJECT_PUT_REF_AND_RESET(stream_event_ctx_type
);
606 BT_CTF_OBJECT_PUT_REF_AND_RESET(event_context_type
);
607 BT_CTF_OBJECT_PUT_REF_AND_RESET(event_payload_type
);
612 void bt_ctf_validation_replace_types(struct bt_ctf_trace_common
*trace
,
613 struct bt_ctf_stream_class_common
*stream_class
,
614 struct bt_ctf_event_class_common
*event_class
,
615 struct bt_ctf_validation_output
*output
,
616 enum bt_ctf_validation_flag replace_flags
)
618 if ((replace_flags
& BT_CTF_VALIDATION_FLAG_TRACE
) && trace
) {
619 bt_ctf_field_type_common_freeze(trace
->packet_header_field_type
);
620 BT_CTF_OBJECT_MOVE_REF(trace
->packet_header_field_type
,
621 output
->packet_header_type
);
624 if ((replace_flags
& BT_CTF_VALIDATION_FLAG_STREAM
) && stream_class
) {
625 bt_ctf_field_type_common_freeze(stream_class
->packet_context_field_type
);
626 bt_ctf_field_type_common_freeze(stream_class
->event_header_field_type
);
627 bt_ctf_field_type_common_freeze(stream_class
->event_context_field_type
);
628 BT_CTF_OBJECT_MOVE_REF(stream_class
->packet_context_field_type
,
629 output
->packet_context_type
);
630 BT_CTF_OBJECT_MOVE_REF(stream_class
->event_header_field_type
,
631 output
->event_header_type
);
632 BT_CTF_OBJECT_MOVE_REF(stream_class
->event_context_field_type
,
633 output
->stream_event_ctx_type
);
636 if ((replace_flags
& BT_CTF_VALIDATION_FLAG_EVENT
) && event_class
) {
637 bt_ctf_field_type_common_freeze(event_class
->context_field_type
);
638 bt_ctf_field_type_common_freeze(event_class
->payload_field_type
);
639 BT_CTF_OBJECT_MOVE_REF(event_class
->context_field_type
, output
->event_context_type
);
640 BT_CTF_OBJECT_MOVE_REF(event_class
->payload_field_type
, output
->event_payload_type
);
645 void bt_ctf_validation_output_put_types(
646 struct bt_ctf_validation_output
*output
)
648 BT_CTF_OBJECT_PUT_REF_AND_RESET(output
->packet_header_type
);
649 BT_CTF_OBJECT_PUT_REF_AND_RESET(output
->packet_context_type
);
650 BT_CTF_OBJECT_PUT_REF_AND_RESET(output
->event_header_type
);
651 BT_CTF_OBJECT_PUT_REF_AND_RESET(output
->stream_event_ctx_type
);
652 BT_CTF_OBJECT_PUT_REF_AND_RESET(output
->event_context_type
);
653 BT_CTF_OBJECT_PUT_REF_AND_RESET(output
->event_payload_type
);