Rename bt_ctf_X -> bt_X, maintain backward compat. for pre-2.0 CTF writer
[babeltrace.git] / lib / ctf-ir / validation.c
1 /*
2 * validation.c
3 *
4 * Babeltrace - CTF IR: Validation of trace, stream class, and event class
5 *
6 * Copyright 2016 Philippe Proulx <pproulx@efficios.com>
7 *
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:
14 *
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
17 *
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
24 * SOFTWARE.
25 */
26
27 #define BT_LOG_TAG "VALIDATION"
28 #include <babeltrace/lib-logging-internal.h>
29
30 #include <babeltrace/ctf-ir/validation-internal.h>
31 #include <babeltrace/ctf-ir/resolve-internal.h>
32 #include <babeltrace/ctf-ir/trace-internal.h>
33 #include <babeltrace/ctf-ir/stream-class-internal.h>
34 #include <babeltrace/ctf-ir/field-types-internal.h>
35 #include <babeltrace/ctf-ir/event-class-internal.h>
36 #include <babeltrace/values.h>
37 #include <babeltrace/babeltrace-internal.h>
38 #include <babeltrace/ref.h>
39
40 /*
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
44 * resolving targets.
45 *
46 * All parameters are owned by the caller.
47 */
48 static
49 int validate_event_class_types(struct bt_value *environment,
50 struct bt_field_type *packet_header_type,
51 struct bt_field_type *packet_context_type,
52 struct bt_field_type *event_header_type,
53 struct bt_field_type *stream_event_ctx_type,
54 struct bt_field_type *event_context_type,
55 struct bt_field_type *event_payload_type)
56 {
57 int ret = 0;
58
59 BT_LOGV("Validating event class field types: "
60 "packet-header-ft-addr=%p, "
61 "packet-context-ft-addr=%p, "
62 "event-header-ft-addr=%p, "
63 "stream-event-context-ft-addr=%p, "
64 "event-context-ft-addr=%p, "
65 "event-payload-ft-addr=%p",
66 packet_header_type, packet_context_type, event_header_type,
67 stream_event_ctx_type, event_context_type, event_payload_type);
68
69 /* Resolve sequence type lengths and variant type tags first */
70 ret = bt_resolve_types(environment, packet_header_type,
71 packet_context_type, event_header_type, stream_event_ctx_type,
72 event_context_type, event_payload_type,
73 BT_RESOLVE_FLAG_EVENT_CONTEXT |
74 BT_RESOLVE_FLAG_EVENT_PAYLOAD);
75 if (ret) {
76 BT_LOGW("Cannot resolve event class field types: ret=%d",
77 ret);
78 goto end;
79 }
80
81 /* Validate field types individually */
82 if (event_context_type) {
83 ret = bt_field_type_validate(event_context_type);
84 if (ret) {
85 BT_LOGW("Invalid event class's context field type: "
86 "ret=%d", ret);
87 goto end;
88 }
89 }
90
91 if (event_payload_type) {
92 ret = bt_field_type_validate(event_payload_type);
93 if (ret) {
94 BT_LOGW("Invalid event class's payload field type: "
95 "ret=%d", ret);
96 goto end;
97 }
98 }
99
100 end:
101 return ret;
102 }
103
104 /*
105 * This function resolves and validates the field types of a stream
106 * class. Only `packet_context_type`, `event_header_type`, and
107 * `stream_event_ctx_type` are resolved and validated; the other field
108 * type is used as an eventual resolving target.
109 *
110 * All parameters are owned by the caller.
111 */
112 static
113 int validate_stream_class_types(struct bt_value *environment,
114 struct bt_field_type *packet_header_type,
115 struct bt_field_type *packet_context_type,
116 struct bt_field_type *event_header_type,
117 struct bt_field_type *stream_event_ctx_type)
118 {
119 int ret = 0;
120
121 BT_LOGV("Validating stream class field types: "
122 "packet-header-ft-addr=%p, "
123 "packet-context-ft-addr=%p, "
124 "event-header-ft-addr=%p, "
125 "stream-event-context-ft-addr=%p",
126 packet_header_type, packet_context_type, event_header_type,
127 stream_event_ctx_type);
128
129 /* Resolve sequence type lengths and variant type tags first */
130 ret = bt_resolve_types(environment, packet_header_type,
131 packet_context_type, event_header_type, stream_event_ctx_type,
132 NULL, NULL,
133 BT_RESOLVE_FLAG_PACKET_CONTEXT |
134 BT_RESOLVE_FLAG_EVENT_HEADER |
135 BT_RESOLVE_FLAG_STREAM_EVENT_CTX);
136 if (ret) {
137 BT_LOGW("Cannot resolve stream class field types: ret=%d",
138 ret);
139 goto end;
140 }
141
142 /* Validate field types individually */
143 if (packet_context_type) {
144 ret = bt_field_type_validate(packet_context_type);
145 if (ret) {
146 BT_LOGW("Invalid stream class's packet context field type: "
147 "ret=%d", ret);
148 goto end;
149 }
150 }
151
152 if (event_header_type) {
153 ret = bt_field_type_validate(event_header_type);
154 if (ret) {
155 BT_LOGW("Invalid stream class's event header field type: "
156 "ret=%d", ret);
157 goto end;
158 }
159 }
160
161 if (stream_event_ctx_type) {
162 ret = bt_field_type_validate(
163 stream_event_ctx_type);
164 if (ret) {
165 BT_LOGW("Invalid stream class's event context field type: "
166 "ret=%d", ret);
167 goto end;
168 }
169 }
170
171 end:
172 return ret;
173 }
174
175 /*
176 * This function resolves and validates the field types of a trace.
177 *
178 * All parameters are owned by the caller.
179 */
180 static
181 int validate_trace_types(struct bt_value *environment,
182 struct bt_field_type *packet_header_type)
183 {
184 int ret = 0;
185
186 BT_LOGV("Validating event class field types: "
187 "packet-header-ft-addr=%p", packet_header_type);
188
189 /* Resolve sequence type lengths and variant type tags first */
190 ret = bt_resolve_types(environment, packet_header_type,
191 NULL, NULL, NULL, NULL, NULL,
192 BT_RESOLVE_FLAG_PACKET_HEADER);
193 if (ret) {
194 BT_LOGW("Cannot resolve trace field types: ret=%d",
195 ret);
196 goto end;
197 }
198
199 /* Validate field types individually */
200 if (packet_header_type) {
201 ret = bt_field_type_validate(packet_header_type);
202 if (ret) {
203 BT_LOGW("Invalid trace's packet header field type: "
204 "ret=%d", ret);
205 goto end;
206 }
207 }
208
209 end:
210 return ret;
211 }
212
213 /*
214 * Checks whether or not `field_type` contains a variant or a sequence
215 * field type, recursively. Returns 1 if it's the case.
216 *
217 * `field_type` is owned by the caller.
218 */
219 static
220 int field_type_contains_sequence_or_variant_ft(struct bt_field_type *type)
221 {
222 int ret = 0;
223 enum bt_field_type_id type_id = bt_field_type_get_type_id(type);
224
225 switch (type_id) {
226 case BT_FIELD_TYPE_ID_SEQUENCE:
227 case BT_FIELD_TYPE_ID_VARIANT:
228 ret = 1;
229 goto end;
230 case BT_FIELD_TYPE_ID_ARRAY:
231 case BT_FIELD_TYPE_ID_STRUCT:
232 {
233 int i;
234 int field_count = bt_field_type_get_field_count(type);
235
236 if (field_count < 0) {
237 ret = -1;
238 goto end;
239 }
240
241 for (i = 0; i < field_count; ++i) {
242 struct bt_field_type *child_type =
243 bt_field_type_get_field_at_index(type, i);
244
245 ret = field_type_contains_sequence_or_variant_ft(
246 child_type);
247 BT_PUT(child_type);
248 if (ret != 0) {
249 goto end;
250 }
251 }
252 break;
253 }
254 default:
255 break;
256 }
257
258 end:
259 return ret;
260 }
261
262 BT_HIDDEN
263 int bt_validate_class_types(struct bt_value *environment,
264 struct bt_field_type *packet_header_type,
265 struct bt_field_type *packet_context_type,
266 struct bt_field_type *event_header_type,
267 struct bt_field_type *stream_event_ctx_type,
268 struct bt_field_type *event_context_type,
269 struct bt_field_type *event_payload_type,
270 int trace_valid, int stream_class_valid, int event_class_valid,
271 struct bt_validation_output *output,
272 enum bt_validation_flag validate_flags)
273 {
274 int ret = 0;
275 int contains_seq_var;
276 int valid_ret;
277
278 BT_LOGV("Validating field types: "
279 "packet-header-ft-addr=%p, "
280 "packet-context-ft-addr=%p, "
281 "event-header-ft-addr=%p, "
282 "stream-event-context-ft-addr=%p, "
283 "event-context-ft-addr=%p, "
284 "event-payload-ft-addr=%p, "
285 "trace-is-valid=%d, stream-class-is-valid=%d, "
286 "event-class-is-valid=%d, validation-flags=%x",
287 packet_header_type, packet_context_type, event_header_type,
288 stream_event_ctx_type, event_context_type, event_payload_type,
289 trace_valid, stream_class_valid, event_class_valid,
290 (unsigned int) validate_flags);
291
292 /* Clean output values */
293 memset(output, 0, sizeof(*output));
294
295 /* Set initial valid flags according to valid parameters */
296 if (trace_valid) {
297 output->valid_flags |= BT_VALIDATION_FLAG_TRACE;
298 }
299
300 if (stream_class_valid) {
301 output->valid_flags |= BT_VALIDATION_FLAG_STREAM;
302 }
303
304 if (event_class_valid) {
305 output->valid_flags |= BT_VALIDATION_FLAG_EVENT;
306 }
307
308 /* Own the type parameters */
309 bt_get(packet_header_type);
310 bt_get(packet_context_type);
311 bt_get(event_header_type);
312 bt_get(stream_event_ctx_type);
313 bt_get(event_context_type);
314 bt_get(event_payload_type);
315
316 /* Validate trace */
317 if ((validate_flags & BT_VALIDATION_FLAG_TRACE) && !trace_valid) {
318 struct bt_field_type *packet_header_type_copy = NULL;
319
320 /* Create field type copies */
321 if (packet_header_type) {
322 contains_seq_var =
323 field_type_contains_sequence_or_variant_ft(
324 packet_header_type);
325 if (contains_seq_var < 0) {
326 ret = contains_seq_var;
327 goto error;
328 } else if (!contains_seq_var) {
329 /* No copy is needed */
330 packet_header_type_copy = packet_header_type;
331 bt_get(packet_header_type_copy);
332 goto skip_packet_header_type_copy;
333 }
334
335 BT_LOGV_STR("Copying packet header field type because it contains at least one sequence or variant field type.");
336 packet_header_type_copy =
337 bt_field_type_copy(packet_header_type);
338 if (!packet_header_type_copy) {
339 ret = -1;
340 BT_LOGE_STR("Cannot copy packet header field type.");
341 goto error;
342 }
343
344 /*
345 * Freeze this copy: if it's returned to the
346 * caller, it cannot be modified any way since
347 * it will be resolved.
348 */
349 bt_field_type_freeze(packet_header_type_copy);
350 }
351
352 skip_packet_header_type_copy:
353 /* Put original reference and move copy */
354 BT_MOVE(packet_header_type, packet_header_type_copy);
355
356 /* Validate trace field types */
357 valid_ret = validate_trace_types(environment,
358 packet_header_type);
359 if (valid_ret == 0) {
360 /* Trace is valid */
361 output->valid_flags |= BT_VALIDATION_FLAG_TRACE;
362 }
363 }
364
365 /* Validate stream class */
366 if ((validate_flags & BT_VALIDATION_FLAG_STREAM) &&
367 !stream_class_valid) {
368 struct bt_field_type *packet_context_type_copy = NULL;
369 struct bt_field_type *event_header_type_copy = NULL;
370 struct bt_field_type *stream_event_ctx_type_copy = NULL;
371
372 if (packet_context_type) {
373 contains_seq_var =
374 field_type_contains_sequence_or_variant_ft(
375 packet_context_type);
376 if (contains_seq_var < 0) {
377 ret = contains_seq_var;
378 goto error;
379 } else if (!contains_seq_var) {
380 /* No copy is needed */
381 packet_context_type_copy = packet_context_type;
382 bt_get(packet_context_type_copy);
383 goto skip_packet_context_type_copy;
384 }
385
386 BT_LOGV_STR("Copying packet context field type because it contains at least one sequence or variant field type.");
387 packet_context_type_copy =
388 bt_field_type_copy(packet_context_type);
389 if (!packet_context_type_copy) {
390 BT_LOGE_STR("Cannot copy packet context field type.");
391 goto sc_validation_error;
392 }
393
394 /*
395 * Freeze this copy: if it's returned to the
396 * caller, it cannot be modified any way since
397 * it will be resolved.
398 */
399 bt_field_type_freeze(packet_context_type_copy);
400 }
401
402 skip_packet_context_type_copy:
403 if (event_header_type) {
404 contains_seq_var =
405 field_type_contains_sequence_or_variant_ft(
406 event_header_type);
407 if (contains_seq_var < 0) {
408 ret = contains_seq_var;
409 goto error;
410 } else if (!contains_seq_var) {
411 /* No copy is needed */
412 event_header_type_copy = event_header_type;
413 bt_get(event_header_type_copy);
414 goto skip_event_header_type_copy;
415 }
416
417 BT_LOGV_STR("Copying event header field type because it contains at least one sequence or variant field type.");
418 event_header_type_copy =
419 bt_field_type_copy(event_header_type);
420 if (!event_header_type_copy) {
421 BT_LOGE_STR("Cannot copy event header field type.");
422 goto sc_validation_error;
423 }
424
425 /*
426 * Freeze this copy: if it's returned to the
427 * caller, it cannot be modified any way since
428 * it will be resolved.
429 */
430 bt_field_type_freeze(event_header_type_copy);
431 }
432
433 skip_event_header_type_copy:
434 if (stream_event_ctx_type) {
435 contains_seq_var =
436 field_type_contains_sequence_or_variant_ft(
437 stream_event_ctx_type);
438 if (contains_seq_var < 0) {
439 ret = contains_seq_var;
440 goto error;
441 } else if (!contains_seq_var) {
442 /* No copy is needed */
443 stream_event_ctx_type_copy =
444 stream_event_ctx_type;
445 bt_get(stream_event_ctx_type_copy);
446 goto skip_stream_event_ctx_type_copy;
447 }
448
449 BT_LOGV_STR("Copying stream event context field type because it contains at least one sequence or variant field type.");
450 stream_event_ctx_type_copy =
451 bt_field_type_copy(stream_event_ctx_type);
452 if (!stream_event_ctx_type_copy) {
453 BT_LOGE_STR("Cannot copy stream event context field type.");
454 goto sc_validation_error;
455 }
456
457 /*
458 * Freeze this copy: if it's returned to the
459 * caller, it cannot be modified any way since
460 * it will be resolved.
461 */
462 bt_field_type_freeze(stream_event_ctx_type_copy);
463 }
464
465 skip_stream_event_ctx_type_copy:
466 /* Put original references and move copies */
467 BT_MOVE(packet_context_type, packet_context_type_copy);
468 BT_MOVE(event_header_type, event_header_type_copy);
469 BT_MOVE(stream_event_ctx_type, stream_event_ctx_type_copy);
470
471 /* Validate stream class field types */
472 valid_ret = validate_stream_class_types(environment,
473 packet_header_type, packet_context_type,
474 event_header_type, stream_event_ctx_type);
475 if (valid_ret == 0) {
476 /* Stream class is valid */
477 output->valid_flags |= BT_VALIDATION_FLAG_STREAM;
478 }
479
480 goto sc_validation_done;
481
482 sc_validation_error:
483 BT_PUT(packet_context_type_copy);
484 BT_PUT(event_header_type_copy);
485 BT_PUT(stream_event_ctx_type_copy);
486 ret = -1;
487 goto error;
488 }
489
490 sc_validation_done:
491 /* Validate event class */
492 if ((validate_flags & BT_VALIDATION_FLAG_EVENT) &&
493 !event_class_valid) {
494 struct bt_field_type *event_context_type_copy = NULL;
495 struct bt_field_type *event_payload_type_copy = NULL;
496
497 if (event_context_type) {
498 contains_seq_var =
499 field_type_contains_sequence_or_variant_ft(
500 event_context_type);
501 if (contains_seq_var < 0) {
502 ret = contains_seq_var;
503 goto error;
504 } else if (!contains_seq_var) {
505 /* No copy is needed */
506 event_context_type_copy = event_context_type;
507 bt_get(event_context_type_copy);
508 goto skip_event_context_type_copy;
509 }
510
511 BT_LOGV_STR("Copying event context field type because it contains at least one sequence or variant field type.");
512 event_context_type_copy =
513 bt_field_type_copy(event_context_type);
514 if (!event_context_type_copy) {
515 BT_LOGE_STR("Cannot copy event context field type.");
516 goto ec_validation_error;
517 }
518
519 /*
520 * Freeze this copy: if it's returned to the
521 * caller, it cannot be modified any way since
522 * it will be resolved.
523 */
524 bt_field_type_freeze(event_context_type_copy);
525 }
526
527 skip_event_context_type_copy:
528 if (event_payload_type) {
529 contains_seq_var =
530 field_type_contains_sequence_or_variant_ft(
531 event_payload_type);
532 if (contains_seq_var < 0) {
533 ret = contains_seq_var;
534 goto error;
535 } else if (!contains_seq_var) {
536 /* No copy is needed */
537 event_payload_type_copy = event_payload_type;
538 bt_get(event_payload_type_copy);
539 goto skip_event_payload_type_copy;
540 }
541
542 BT_LOGV_STR("Copying event payload field type because it contains at least one sequence or variant field type.");
543 event_payload_type_copy =
544 bt_field_type_copy(event_payload_type);
545 if (!event_payload_type_copy) {
546 BT_LOGE_STR("Cannot copy event payload field type.");
547 goto ec_validation_error;
548 }
549
550 /*
551 * Freeze this copy: if it's returned to the
552 * caller, it cannot be modified any way since
553 * it will be resolved.
554 */
555 bt_field_type_freeze(event_payload_type_copy);
556 }
557
558 skip_event_payload_type_copy:
559 /* Put original references and move copies */
560 BT_MOVE(event_context_type, event_context_type_copy);
561 BT_MOVE(event_payload_type, event_payload_type_copy);
562
563 /* Validate event class field types */
564 valid_ret = validate_event_class_types(environment,
565 packet_header_type, packet_context_type,
566 event_header_type, stream_event_ctx_type,
567 event_context_type, event_payload_type);
568 if (valid_ret == 0) {
569 /* Event class is valid */
570 output->valid_flags |= BT_VALIDATION_FLAG_EVENT;
571 }
572
573 goto ec_validation_done;
574
575 ec_validation_error:
576 BT_PUT(event_context_type_copy);
577 BT_PUT(event_payload_type_copy);
578 ret = -1;
579 goto error;
580 }
581
582 ec_validation_done:
583 /*
584 * Validation is complete. Move the field types that were used
585 * to validate (and that were possibly altered by the validation
586 * process) to the output values.
587 */
588 BT_MOVE(output->packet_header_type, packet_header_type);
589 BT_MOVE(output->packet_context_type, packet_context_type);
590 BT_MOVE(output->event_header_type, event_header_type);
591 BT_MOVE(output->stream_event_ctx_type, stream_event_ctx_type);
592 BT_MOVE(output->event_context_type, event_context_type);
593 BT_MOVE(output->event_payload_type, event_payload_type);
594 return ret;
595
596 error:
597 BT_PUT(packet_header_type);
598 BT_PUT(packet_context_type);
599 BT_PUT(event_header_type);
600 BT_PUT(stream_event_ctx_type);
601 BT_PUT(event_context_type);
602 BT_PUT(event_payload_type);
603 return ret;
604 }
605
606 BT_HIDDEN
607 void bt_validation_replace_types(struct bt_trace *trace,
608 struct bt_stream_class *stream_class,
609 struct bt_event_class *event_class,
610 struct bt_validation_output *output,
611 enum bt_validation_flag replace_flags)
612 {
613 if ((replace_flags & BT_VALIDATION_FLAG_TRACE) && trace) {
614 bt_field_type_freeze(trace->packet_header_type);
615 BT_MOVE(trace->packet_header_type, output->packet_header_type);
616 }
617
618 if ((replace_flags & BT_VALIDATION_FLAG_STREAM) && stream_class) {
619 bt_field_type_freeze(stream_class->packet_context_type);
620 bt_field_type_freeze(stream_class->event_header_type);
621 bt_field_type_freeze(stream_class->event_context_type);
622 BT_MOVE(stream_class->packet_context_type,
623 output->packet_context_type);
624 BT_MOVE(stream_class->event_header_type,
625 output->event_header_type);
626 BT_MOVE(stream_class->event_context_type,
627 output->stream_event_ctx_type);
628 }
629
630 if ((replace_flags & BT_VALIDATION_FLAG_EVENT) && event_class) {
631 bt_field_type_freeze(event_class->context);
632 bt_field_type_freeze(event_class->fields);
633 BT_MOVE(event_class->context, output->event_context_type);
634 BT_MOVE(event_class->fields, output->event_payload_type);
635 }
636 }
637
638 BT_HIDDEN
639 void bt_validation_output_put_types(
640 struct bt_validation_output *output)
641 {
642 BT_PUT(output->packet_header_type);
643 BT_PUT(output->packet_context_type);
644 BT_PUT(output->event_header_type);
645 BT_PUT(output->stream_event_ctx_type);
646 BT_PUT(output->event_context_type);
647 BT_PUT(output->event_payload_type);
648 }
This page took 0.043377 seconds and 4 git commands to generate.