cpp-common/bt2c/fmt.hpp: use `wise_enum::string_type` in `EnableIfIsWiseEnum` definition
[babeltrace.git] / src / ctf-writer / validation.c
1 /*
2 * SPDX-License-Identifier: MIT
3 *
4 * Copyright 2016-2018 Philippe Proulx <pproulx@efficios.com>
5 *
6 * Babeltrace - CTF writer: Validation of trace, stream class, and event class
7 */
8
9 #define BT_LOG_TAG "CTF-WRITER/VALIDATION"
10 #include "logging.h"
11
12 #include <babeltrace2-ctf-writer/object.h>
13
14 #include "common/macros.h"
15
16 #include "assert-pre.h"
17 #include "event-class.h"
18 #include "field-types.h"
19 #include "field-types.h"
20 #include "resolve.h"
21 #include "stream-class.h"
22 #include "trace.h"
23 #include "validation.h"
24 #include "values.h"
25
26 /*
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
30 * resolving targets.
31 *
32 * All parameters are owned by the caller.
33 */
34 static
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)
42 {
43 int ret = 0;
44
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);
54
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);
61 if (ret) {
62 BT_LOGW("Cannot resolve event class field types: ret=%d",
63 ret);
64 goto end;
65 }
66
67 /* Validate field types individually */
68 if (event_context_type) {
69 ret = bt_ctf_field_type_common_validate(event_context_type);
70 if (ret) {
71 BT_LOGW("Invalid event class's context field type: "
72 "ret=%d", ret);
73 goto end;
74 }
75 }
76
77 if (event_payload_type) {
78 ret = bt_ctf_field_type_common_validate(event_payload_type);
79 if (ret) {
80 BT_LOGW("Invalid event class's payload field type: "
81 "ret=%d", ret);
82 goto end;
83 }
84 }
85
86 end:
87 return ret;
88 }
89
90 /*
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.
95 *
96 * All parameters are owned by the caller.
97 */
98 static
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)
104 {
105 int ret = 0;
106
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);
114
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,
118 NULL, NULL,
119 BT_CTF_RESOLVE_FLAG_PACKET_CONTEXT |
120 BT_CTF_RESOLVE_FLAG_EVENT_HEADER |
121 BT_CTF_RESOLVE_FLAG_STREAM_EVENT_CTX);
122 if (ret) {
123 BT_LOGW("Cannot resolve stream class field types: ret=%d",
124 ret);
125 goto end;
126 }
127
128 /* Validate field types individually */
129 if (packet_context_type) {
130 ret = bt_ctf_field_type_common_validate(packet_context_type);
131 if (ret) {
132 BT_LOGW("Invalid stream class's packet context field type: "
133 "ret=%d", ret);
134 goto end;
135 }
136 }
137
138 if (event_header_type) {
139 ret = bt_ctf_field_type_common_validate(event_header_type);
140 if (ret) {
141 BT_LOGW("Invalid stream class's event header field type: "
142 "ret=%d", ret);
143 goto end;
144 }
145 }
146
147 if (stream_event_ctx_type) {
148 ret = bt_ctf_field_type_common_validate(
149 stream_event_ctx_type);
150 if (ret) {
151 BT_LOGW("Invalid stream class's event context field type: "
152 "ret=%d", ret);
153 goto end;
154 }
155 }
156
157 end:
158 return ret;
159 }
160
161 /*
162 * This function resolves and validates the field types of a trace.
163 *
164 * All parameters are owned by the caller.
165 */
166 static
167 int validate_trace_types(struct bt_ctf_private_value *environment,
168 struct bt_ctf_field_type_common *packet_header_type)
169 {
170 int ret = 0;
171
172 BT_LOGT("Validating event class field types: "
173 "packet-header-ft-addr=%p", packet_header_type);
174
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);
179 if (ret) {
180 BT_LOGW("Cannot resolve trace field types: ret=%d",
181 ret);
182 goto end;
183 }
184
185 /* Validate field types individually */
186 if (packet_header_type) {
187 ret = bt_ctf_field_type_common_validate(packet_header_type);
188 if (ret) {
189 BT_LOGW("Invalid trace's packet header field type: "
190 "ret=%d", ret);
191 goto end;
192 }
193 }
194
195 end:
196 return ret;
197 }
198
199 /*
200 * Checks whether or not `field_type` contains a variant or a sequence
201 * field type, recursively. Returns 1 if it's the case.
202 *
203 * `field_type` is owned by the caller.
204 */
205 static
206 int field_type_contains_sequence_or_variant_ft(struct bt_ctf_field_type_common *type)
207 {
208 int ret = 0;
209 enum bt_ctf_field_type_id type_id = bt_ctf_field_type_common_get_type_id(type);
210
211 switch (type_id) {
212 case BT_CTF_FIELD_TYPE_ID_SEQUENCE:
213 case BT_CTF_FIELD_TYPE_ID_VARIANT:
214 ret = 1;
215 goto end;
216 case BT_CTF_FIELD_TYPE_ID_ARRAY:
217 case BT_CTF_FIELD_TYPE_ID_STRUCT:
218 {
219 int i;
220 int field_count = bt_ctf_field_type_common_get_field_count(type);
221
222 if (field_count < 0) {
223 ret = -1;
224 goto end;
225 }
226
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(
230 type, i);
231
232 ret = field_type_contains_sequence_or_variant_ft(
233 child_type);
234 if (ret != 0) {
235 goto end;
236 }
237 }
238 break;
239 }
240 default:
241 break;
242 }
243
244 end:
245 return ret;
246 }
247
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)
259 {
260 int ret = 0;
261 int contains_seq_var;
262 int valid_ret;
263
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);
277
278 /* Clean output values */
279 memset(output, 0, sizeof(*output));
280
281 /* Set initial valid flags according to valid parameters */
282 if (trace_valid) {
283 output->valid_flags |= BT_CTF_VALIDATION_FLAG_TRACE;
284 }
285
286 if (stream_class_valid) {
287 output->valid_flags |= BT_CTF_VALIDATION_FLAG_STREAM;
288 }
289
290 if (event_class_valid) {
291 output->valid_flags |= BT_CTF_VALIDATION_FLAG_EVENT;
292 }
293
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);
301
302 /* Validate trace */
303 if ((validate_flags & BT_CTF_VALIDATION_FLAG_TRACE) && !trace_valid) {
304 struct bt_ctf_field_type_common *packet_header_type_copy = NULL;
305
306 /* Create field type copies */
307 if (packet_header_type) {
308 contains_seq_var =
309 field_type_contains_sequence_or_variant_ft(
310 packet_header_type);
311 if (contains_seq_var < 0) {
312 ret = contains_seq_var;
313 goto error;
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;
319 }
320
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) {
325 ret = -1;
326 BT_LOGE_STR("Cannot copy packet header field type.");
327 goto error;
328 }
329
330 /*
331 * Freeze this copy: if it's returned to the
332 * caller, it cannot be modified any way since
333 * it will be resolved.
334 */
335 bt_ctf_field_type_common_freeze(packet_header_type_copy);
336 }
337
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);
341
342 /* Validate trace field types */
343 valid_ret = validate_trace_types(environment,
344 packet_header_type);
345 if (valid_ret == 0) {
346 /* Trace is valid */
347 output->valid_flags |= BT_CTF_VALIDATION_FLAG_TRACE;
348 }
349 }
350
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;
357
358 if (packet_context_type) {
359 contains_seq_var =
360 field_type_contains_sequence_or_variant_ft(
361 packet_context_type);
362 if (contains_seq_var < 0) {
363 ret = contains_seq_var;
364 goto error;
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;
370 }
371
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;
378 }
379
380 /*
381 * Freeze this copy: if it's returned to the
382 * caller, it cannot be modified any way since
383 * it will be resolved.
384 */
385 bt_ctf_field_type_common_freeze(packet_context_type_copy);
386 }
387
388 skip_packet_context_type_copy:
389 if (event_header_type) {
390 contains_seq_var =
391 field_type_contains_sequence_or_variant_ft(
392 event_header_type);
393 if (contains_seq_var < 0) {
394 ret = contains_seq_var;
395 goto error;
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;
401 }
402
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;
409 }
410
411 /*
412 * Freeze this copy: if it's returned to the
413 * caller, it cannot be modified any way since
414 * it will be resolved.
415 */
416 bt_ctf_field_type_common_freeze(event_header_type_copy);
417 }
418
419 skip_event_header_type_copy:
420 if (stream_event_ctx_type) {
421 contains_seq_var =
422 field_type_contains_sequence_or_variant_ft(
423 stream_event_ctx_type);
424 if (contains_seq_var < 0) {
425 ret = contains_seq_var;
426 goto error;
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;
433 }
434
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;
441 }
442
443 /*
444 * Freeze this copy: if it's returned to the
445 * caller, it cannot be modified any way since
446 * it will be resolved.
447 */
448 bt_ctf_field_type_common_freeze(stream_event_ctx_type_copy);
449 }
450
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);
456
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;
464 }
465
466 goto sc_validation_done;
467
468 sc_validation_error:
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);
472 ret = -1;
473 goto error;
474 }
475
476 sc_validation_done:
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;
482
483 if (event_context_type) {
484 contains_seq_var =
485 field_type_contains_sequence_or_variant_ft(
486 event_context_type);
487 if (contains_seq_var < 0) {
488 ret = contains_seq_var;
489 goto error;
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;
495 }
496
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;
503 }
504
505 /*
506 * Freeze this copy: if it's returned to the
507 * caller, it cannot be modified any way since
508 * it will be resolved.
509 */
510 bt_ctf_field_type_common_freeze(event_context_type_copy);
511 }
512
513 skip_event_context_type_copy:
514 if (event_payload_type) {
515 contains_seq_var =
516 field_type_contains_sequence_or_variant_ft(
517 event_payload_type);
518 if (contains_seq_var < 0) {
519 ret = contains_seq_var;
520 goto error;
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;
526 }
527
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;
534 }
535
536 /*
537 * Freeze this copy: if it's returned to the
538 * caller, it cannot be modified any way since
539 * it will be resolved.
540 */
541 bt_ctf_field_type_common_freeze(event_payload_type_copy);
542 }
543
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);
548
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;
557 }
558
559 goto ec_validation_done;
560
561 ec_validation_error:
562 BT_CTF_OBJECT_PUT_REF_AND_RESET(event_context_type_copy);
563 BT_CTF_OBJECT_PUT_REF_AND_RESET(event_payload_type_copy);
564 ret = -1;
565 goto error;
566 }
567
568 ec_validation_done:
569 /*
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.
573 */
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);
580 return ret;
581
582 error:
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);
589 return ret;
590 }
591
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)
597 {
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);
602 }
603
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);
614 }
615
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);
621 }
622 }
623
624 void bt_ctf_validation_output_put_types(
625 struct bt_ctf_validation_output *output)
626 {
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);
633 }
This page took 0.041739 seconds and 5 git commands to generate.