4 * Babeltrace - CTF IR: Validation of trace, stream class, and event class
6 * Copyright 2016 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 #include <babeltrace/ctf-ir/validation-internal.h>
28 #include <babeltrace/ctf-ir/resolve-internal.h>
29 #include <babeltrace/ctf-ir/trace-internal.h>
30 #include <babeltrace/ctf-ir/stream-class-internal.h>
31 #include <babeltrace/ctf-ir/field-types-internal.h>
32 #include <babeltrace/ctf-ir/event-class-internal.h>
33 #include <babeltrace/values.h>
34 #include <babeltrace/babeltrace-internal.h>
35 #include <babeltrace/ref.h>
37 #define _printf_error(fmt, args...) \
38 printf_verbose("[validation] " fmt, ## args)
41 * This function resolves and validates the field types of an event
42 * class. Only `event_context_type` and `event_payload_type` are
43 * resolved and validated; the other field types are used as eventual
46 * All parameters are owned by the caller.
49 int validate_event_class_types(struct bt_value
*environment
,
50 struct bt_ctf_field_type
*packet_header_type
,
51 struct bt_ctf_field_type
*packet_context_type
,
52 struct bt_ctf_field_type
*event_header_type
,
53 struct bt_ctf_field_type
*stream_event_ctx_type
,
54 struct bt_ctf_field_type
*event_context_type
,
55 struct bt_ctf_field_type
*event_payload_type
)
59 /* Resolve sequence type lengths and variant type tags first */
60 ret
= bt_ctf_resolve_types(environment
, packet_header_type
,
61 packet_context_type
, event_header_type
, stream_event_ctx_type
,
62 event_context_type
, event_payload_type
,
63 BT_CTF_RESOLVE_FLAG_EVENT_CONTEXT
|
64 BT_CTF_RESOLVE_FLAG_EVENT_PAYLOAD
);
66 _printf_error("Cannot resolve event class types\n");
70 /* Validate field types individually */
71 if (event_context_type
) {
72 ret
= bt_ctf_field_type_validate(event_context_type
);
74 _printf_error("Invalid event context type\n");
79 if (event_payload_type
) {
80 ret
= bt_ctf_field_type_validate(event_payload_type
);
82 _printf_error("Invalid event payload type\n");
92 * This function resolves and validates the field types of a stream
93 * class. Only `packet_context_type`, `event_header_type`, and
94 * `stream_event_ctx_type` are resolved and validated; the other field
95 * type is used as an eventual resolving target.
97 * All parameters are owned by the caller.
100 int validate_stream_class_types(struct bt_value
*environment
,
101 struct bt_ctf_field_type
*packet_header_type
,
102 struct bt_ctf_field_type
*packet_context_type
,
103 struct bt_ctf_field_type
*event_header_type
,
104 struct bt_ctf_field_type
*stream_event_ctx_type
)
108 /* Resolve sequence type lengths and variant type tags first */
109 ret
= bt_ctf_resolve_types(environment
, packet_header_type
,
110 packet_context_type
, event_header_type
, stream_event_ctx_type
,
112 BT_CTF_RESOLVE_FLAG_PACKET_CONTEXT
|
113 BT_CTF_RESOLVE_FLAG_EVENT_HEADER
|
114 BT_CTF_RESOLVE_FLAG_STREAM_EVENT_CTX
);
116 _printf_error("Cannot resolve stream class types\n");
120 /* Validate field types individually */
121 if (packet_context_type
) {
122 ret
= bt_ctf_field_type_validate(packet_context_type
);
124 _printf_error("Invalid stream packet context type\n");
129 if (event_header_type
) {
130 ret
= bt_ctf_field_type_validate(event_header_type
);
132 _printf_error("Invalid stream event header type\n");
137 if (stream_event_ctx_type
) {
138 ret
= bt_ctf_field_type_validate(
139 stream_event_ctx_type
);
141 _printf_error("Invalid stream event context type\n");
151 * This function resolves and validates the field types of a trace.
153 * All parameters are owned by the caller.
156 int validate_trace_types(struct bt_value
*environment
,
157 struct bt_ctf_field_type
*packet_header_type
)
161 /* Resolve sequence type lengths and variant type tags first */
162 ret
= bt_ctf_resolve_types(environment
, packet_header_type
,
163 NULL
, NULL
, NULL
, NULL
, NULL
,
164 BT_CTF_RESOLVE_FLAG_PACKET_HEADER
);
166 _printf_error("Cannot resolve trace types\n");
170 /* Validate field types individually */
171 if (packet_header_type
) {
172 ret
= bt_ctf_field_type_validate(packet_header_type
);
174 _printf_error("Invalid trace packet header type\n");
184 * Checks whether or not `field_type` contains a variant or a sequence
185 * field type, recursively. Returns 1 if it's the case.
187 * `field_type` is owned by the caller.
190 int field_type_contains_sequence_or_variant_ft(struct bt_ctf_field_type
*type
)
193 enum bt_ctf_type_id type_id
= bt_ctf_field_type_get_type_id(type
);
196 case BT_CTF_TYPE_ID_SEQUENCE
:
197 case BT_CTF_TYPE_ID_VARIANT
:
200 case BT_CTF_TYPE_ID_ARRAY
:
201 case BT_CTF_TYPE_ID_STRUCT
:
204 int field_count
= bt_ctf_field_type_get_field_count(type
);
206 if (field_count
< 0) {
211 for (i
= 0; i
< field_count
; ++i
) {
212 struct bt_ctf_field_type
*child_type
=
213 bt_ctf_field_type_get_field_at_index(type
, i
);
215 ret
= field_type_contains_sequence_or_variant_ft(
233 int bt_ctf_validate_class_types(struct bt_value
*environment
,
234 struct bt_ctf_field_type
*packet_header_type
,
235 struct bt_ctf_field_type
*packet_context_type
,
236 struct bt_ctf_field_type
*event_header_type
,
237 struct bt_ctf_field_type
*stream_event_ctx_type
,
238 struct bt_ctf_field_type
*event_context_type
,
239 struct bt_ctf_field_type
*event_payload_type
,
240 int trace_valid
, int stream_class_valid
, int event_class_valid
,
241 struct bt_ctf_validation_output
*output
,
242 enum bt_ctf_validation_flag validate_flags
)
245 int contains_seq_var
;
248 /* Clean output values */
249 memset(output
, 0, sizeof(*output
));
251 /* Set initial valid flags according to valid parameters */
253 output
->valid_flags
|= BT_CTF_VALIDATION_FLAG_TRACE
;
256 if (stream_class_valid
) {
257 output
->valid_flags
|= BT_CTF_VALIDATION_FLAG_STREAM
;
260 if (event_class_valid
) {
261 output
->valid_flags
|= BT_CTF_VALIDATION_FLAG_EVENT
;
264 /* Own the type parameters */
265 bt_get(packet_header_type
);
266 bt_get(packet_context_type
);
267 bt_get(event_header_type
);
268 bt_get(stream_event_ctx_type
);
269 bt_get(event_context_type
);
270 bt_get(event_payload_type
);
273 if ((validate_flags
& BT_CTF_VALIDATION_FLAG_TRACE
) && !trace_valid
) {
274 struct bt_ctf_field_type
*packet_header_type_copy
= NULL
;
276 /* Create field type copies */
277 if (packet_header_type
) {
279 field_type_contains_sequence_or_variant_ft(
281 if (contains_seq_var
< 0) {
282 ret
= contains_seq_var
;
284 } else if (!contains_seq_var
) {
285 /* No copy is needed */
286 packet_header_type_copy
= packet_header_type
;
287 bt_get(packet_header_type_copy
);
288 goto skip_packet_header_type_copy
;
291 packet_header_type_copy
=
292 bt_ctf_field_type_copy(packet_header_type
);
293 if (!packet_header_type_copy
) {
295 _printf_error("Cannot copy packet header type\n");
300 * Freeze this copy: if it's returned to the
301 * caller, it cannot be modified any way since
302 * it will be resolved.
304 bt_ctf_field_type_freeze(packet_header_type_copy
);
307 skip_packet_header_type_copy
:
308 /* Put original reference and move copy */
309 BT_MOVE(packet_header_type
, packet_header_type_copy
);
311 /* Validate trace field types */
312 valid_ret
= validate_trace_types(environment
,
316 output
->valid_flags
|= BT_CTF_VALIDATION_FLAG_TRACE
;
320 /* Validate stream class */
321 if ((validate_flags
& BT_CTF_VALIDATION_FLAG_STREAM
) &&
322 !stream_class_valid
) {
323 struct bt_ctf_field_type
*packet_context_type_copy
= NULL
;
324 struct bt_ctf_field_type
*event_header_type_copy
= NULL
;
325 struct bt_ctf_field_type
*stream_event_ctx_type_copy
= NULL
;
327 if (packet_context_type
) {
329 field_type_contains_sequence_or_variant_ft(
330 packet_context_type
);
331 if (contains_seq_var
< 0) {
332 ret
= contains_seq_var
;
334 } else if (!contains_seq_var
) {
335 /* No copy is needed */
336 packet_context_type_copy
= packet_context_type
;
337 bt_get(packet_context_type_copy
);
338 goto skip_packet_context_type_copy
;
341 packet_context_type_copy
=
342 bt_ctf_field_type_copy(packet_context_type
);
343 if (!packet_context_type_copy
) {
344 _printf_error("Cannot copy packet context type\n");
345 goto sc_validation_error
;
349 * Freeze this copy: if it's returned to the
350 * caller, it cannot be modified any way since
351 * it will be resolved.
353 bt_ctf_field_type_freeze(packet_context_type_copy
);
356 skip_packet_context_type_copy
:
357 if (event_header_type
) {
359 field_type_contains_sequence_or_variant_ft(
361 if (contains_seq_var
< 0) {
362 ret
= contains_seq_var
;
364 } else if (!contains_seq_var
) {
365 /* No copy is needed */
366 event_header_type_copy
= event_header_type
;
367 bt_get(event_header_type_copy
);
368 goto skip_event_header_type_copy
;
371 event_header_type_copy
=
372 bt_ctf_field_type_copy(event_header_type
);
373 if (!event_header_type_copy
) {
374 _printf_error("Cannot copy event header type\n");
375 goto sc_validation_error
;
379 * Freeze this copy: if it's returned to the
380 * caller, it cannot be modified any way since
381 * it will be resolved.
383 bt_ctf_field_type_freeze(event_header_type_copy
);
386 skip_event_header_type_copy
:
387 if (stream_event_ctx_type
) {
389 field_type_contains_sequence_or_variant_ft(
390 stream_event_ctx_type
);
391 if (contains_seq_var
< 0) {
392 ret
= contains_seq_var
;
394 } else if (!contains_seq_var
) {
395 /* No copy is needed */
396 stream_event_ctx_type_copy
=
397 stream_event_ctx_type
;
398 bt_get(stream_event_ctx_type_copy
);
399 goto skip_stream_event_ctx_type_copy
;
402 stream_event_ctx_type_copy
=
403 bt_ctf_field_type_copy(stream_event_ctx_type
);
404 if (!stream_event_ctx_type_copy
) {
405 _printf_error("Cannot copy stream event context type\n");
406 goto sc_validation_error
;
410 * Freeze this copy: if it's returned to the
411 * caller, it cannot be modified any way since
412 * it will be resolved.
414 bt_ctf_field_type_freeze(stream_event_ctx_type_copy
);
417 skip_stream_event_ctx_type_copy
:
418 /* Put original references and move copies */
419 BT_MOVE(packet_context_type
, packet_context_type_copy
);
420 BT_MOVE(event_header_type
, event_header_type_copy
);
421 BT_MOVE(stream_event_ctx_type
, stream_event_ctx_type_copy
);
423 /* Validate stream class field types */
424 valid_ret
= validate_stream_class_types(environment
,
425 packet_header_type
, packet_context_type
,
426 event_header_type
, stream_event_ctx_type
);
428 /* Stream class is valid */
429 output
->valid_flags
|= BT_CTF_VALIDATION_FLAG_STREAM
;
432 goto sc_validation_done
;
435 BT_PUT(packet_context_type_copy
);
436 BT_PUT(event_header_type_copy
);
437 BT_PUT(stream_event_ctx_type_copy
);
443 /* Validate event class */
444 if ((validate_flags
& BT_CTF_VALIDATION_FLAG_EVENT
) &&
445 !event_class_valid
) {
446 struct bt_ctf_field_type
*event_context_type_copy
= NULL
;
447 struct bt_ctf_field_type
*event_payload_type_copy
= NULL
;
449 if (event_context_type
) {
451 field_type_contains_sequence_or_variant_ft(
453 if (contains_seq_var
< 0) {
454 ret
= contains_seq_var
;
456 } else if (!contains_seq_var
) {
457 /* No copy is needed */
458 event_context_type_copy
= event_context_type
;
459 bt_get(event_context_type_copy
);
460 goto skip_event_context_type_copy
;
463 event_context_type_copy
=
464 bt_ctf_field_type_copy(event_context_type
);
465 if (!event_context_type_copy
) {
466 _printf_error("Cannot copy event context type\n");
467 goto ec_validation_error
;
471 * Freeze this copy: if it's returned to the
472 * caller, it cannot be modified any way since
473 * it will be resolved.
475 bt_ctf_field_type_freeze(event_context_type_copy
);
478 skip_event_context_type_copy
:
479 if (event_payload_type
) {
481 field_type_contains_sequence_or_variant_ft(
483 if (contains_seq_var
< 0) {
484 ret
= contains_seq_var
;
486 } else if (!contains_seq_var
) {
487 /* No copy is needed */
488 event_payload_type_copy
= event_payload_type
;
489 bt_get(event_payload_type_copy
);
490 goto skip_event_payload_type_copy
;
493 event_payload_type_copy
=
494 bt_ctf_field_type_copy(event_payload_type
);
495 if (!event_payload_type_copy
) {
496 _printf_error("Cannot copy event payload type\n");
497 goto ec_validation_error
;
501 * Freeze this copy: if it's returned to the
502 * caller, it cannot be modified any way since
503 * it will be resolved.
505 bt_ctf_field_type_freeze(event_payload_type_copy
);
508 skip_event_payload_type_copy
:
509 /* Put original references and move copies */
510 BT_MOVE(event_context_type
, event_context_type_copy
);
511 BT_MOVE(event_payload_type
, event_payload_type_copy
);
513 /* Validate event class field types */
514 valid_ret
= validate_event_class_types(environment
,
515 packet_header_type
, packet_context_type
,
516 event_header_type
, stream_event_ctx_type
,
517 event_context_type
, event_payload_type
);
519 /* Event class is valid */
520 output
->valid_flags
|= BT_CTF_VALIDATION_FLAG_EVENT
;
523 goto ec_validation_done
;
526 BT_PUT(event_context_type_copy
);
527 BT_PUT(event_payload_type_copy
);
534 * Validation is complete. Move the field types that were used
535 * to validate (and that were possibly altered by the validation
536 * process) to the output values.
538 BT_MOVE(output
->packet_header_type
, packet_header_type
);
539 BT_MOVE(output
->packet_context_type
, packet_context_type
);
540 BT_MOVE(output
->event_header_type
, event_header_type
);
541 BT_MOVE(output
->stream_event_ctx_type
, stream_event_ctx_type
);
542 BT_MOVE(output
->event_context_type
, event_context_type
);
543 BT_MOVE(output
->event_payload_type
, event_payload_type
);
548 BT_PUT(packet_header_type
);
549 BT_PUT(packet_context_type
);
550 BT_PUT(event_header_type
);
551 BT_PUT(stream_event_ctx_type
);
552 BT_PUT(event_context_type
);
553 BT_PUT(event_payload_type
);
559 void bt_ctf_validation_replace_types(struct bt_ctf_trace
*trace
,
560 struct bt_ctf_stream_class
*stream_class
,
561 struct bt_ctf_event_class
*event_class
,
562 struct bt_ctf_validation_output
*output
,
563 enum bt_ctf_validation_flag replace_flags
)
565 if ((replace_flags
& BT_CTF_VALIDATION_FLAG_TRACE
) && trace
) {
566 bt_ctf_field_type_freeze(trace
->packet_header_type
);
567 BT_MOVE(trace
->packet_header_type
, output
->packet_header_type
);
570 if ((replace_flags
& BT_CTF_VALIDATION_FLAG_STREAM
) && stream_class
) {
571 bt_ctf_field_type_freeze(stream_class
->packet_context_type
);
572 bt_ctf_field_type_freeze(stream_class
->event_header_type
);
573 bt_ctf_field_type_freeze(stream_class
->event_context_type
);
574 BT_MOVE(stream_class
->packet_context_type
,
575 output
->packet_context_type
);
576 BT_MOVE(stream_class
->event_header_type
,
577 output
->event_header_type
);
578 BT_MOVE(stream_class
->event_context_type
,
579 output
->stream_event_ctx_type
);
582 if ((replace_flags
& BT_CTF_VALIDATION_FLAG_EVENT
) && event_class
) {
583 bt_ctf_field_type_freeze(event_class
->context
);
584 bt_ctf_field_type_freeze(event_class
->fields
);
585 BT_MOVE(event_class
->context
, output
->event_context_type
);
586 BT_MOVE(event_class
->fields
, output
->event_payload_type
);
591 void bt_ctf_validation_output_put_types(
592 struct bt_ctf_validation_output
*output
)
594 BT_PUT(output
->packet_header_type
);
595 BT_PUT(output
->packet_context_type
);
596 BT_PUT(output
->event_header_type
);
597 BT_PUT(output
->stream_event_ctx_type
);
598 BT_PUT(output
->event_context_type
);
599 BT_PUT(output
->event_payload_type
);