X-Git-Url: http://git.efficios.com/?p=babeltrace.git;a=blobdiff_plain;f=lib%2Fctf-writer%2Fvalidation.c;fp=lib%2Fctf-writer%2Fvalidation.c;h=0000000000000000000000000000000000000000;hp=97a279aa9683e8d590a8586c3f24c9a23ae44841;hb=67d2ce028c96b6a3b3614b393d8928663bce4490;hpb=172e6876abbb70d0323a500e6b44f90641fbe2fb diff --git a/lib/ctf-writer/validation.c b/lib/ctf-writer/validation.c deleted file mode 100644 index 97a279aa..00000000 --- a/lib/ctf-writer/validation.c +++ /dev/null @@ -1,652 +0,0 @@ -/* - * validation.c - * - * Babeltrace - CTF writer: Validation of trace, stream class, and event class - * - * Copyright 2016-2018 Philippe Proulx - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#define BT_LOG_TAG "CTF-WRITER-VALIDATION" -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * This function resolves and validates the field types of an event - * class. Only `event_context_type` and `event_payload_type` are - * resolved and validated; the other field types are used as eventual - * resolving targets. - * - * All parameters are owned by the caller. - */ -static -int validate_event_class_types(struct bt_ctf_private_value *environment, - struct bt_ctf_field_type_common *packet_header_type, - struct bt_ctf_field_type_common *packet_context_type, - struct bt_ctf_field_type_common *event_header_type, - struct bt_ctf_field_type_common *stream_event_ctx_type, - struct bt_ctf_field_type_common *event_context_type, - struct bt_ctf_field_type_common *event_payload_type) -{ - int ret = 0; - - BT_LOGV("Validating event class field types: " - "packet-header-ft-addr=%p, " - "packet-context-ft-addr=%p, " - "event-header-ft-addr=%p, " - "stream-event-context-ft-addr=%p, " - "event-context-ft-addr=%p, " - "event-payload-ft-addr=%p", - packet_header_type, packet_context_type, event_header_type, - stream_event_ctx_type, event_context_type, event_payload_type); - - /* Resolve sequence type lengths and variant type tags first */ - ret = bt_ctf_resolve_types(environment, packet_header_type, - packet_context_type, event_header_type, stream_event_ctx_type, - event_context_type, event_payload_type, - BT_CTF_RESOLVE_FLAG_EVENT_CONTEXT | - BT_CTF_RESOLVE_FLAG_EVENT_PAYLOAD); - if (ret) { - BT_LOGW("Cannot resolve event class field types: ret=%d", - ret); - goto end; - } - - /* Validate field types individually */ - if (event_context_type) { - ret = bt_ctf_field_type_common_validate(event_context_type); - if (ret) { - BT_LOGW("Invalid event class's context field type: " - "ret=%d", ret); - goto end; - } - } - - if (event_payload_type) { - ret = bt_ctf_field_type_common_validate(event_payload_type); - if (ret) { - BT_LOGW("Invalid event class's payload field type: " - "ret=%d", ret); - goto end; - } - } - -end: - return ret; -} - -/* - * This function resolves and validates the field types of a stream - * class. Only `packet_context_type`, `event_header_type`, and - * `stream_event_ctx_type` are resolved and validated; the other field - * type is used as an eventual resolving target. - * - * All parameters are owned by the caller. - */ -static -int validate_stream_class_types(struct bt_ctf_private_value *environment, - struct bt_ctf_field_type_common *packet_header_type, - struct bt_ctf_field_type_common *packet_context_type, - struct bt_ctf_field_type_common *event_header_type, - struct bt_ctf_field_type_common *stream_event_ctx_type) -{ - int ret = 0; - - BT_LOGV("Validating stream class field types: " - "packet-header-ft-addr=%p, " - "packet-context-ft-addr=%p, " - "event-header-ft-addr=%p, " - "stream-event-context-ft-addr=%p", - packet_header_type, packet_context_type, event_header_type, - stream_event_ctx_type); - - /* Resolve sequence type lengths and variant type tags first */ - ret = bt_ctf_resolve_types(environment, packet_header_type, - packet_context_type, event_header_type, stream_event_ctx_type, - NULL, NULL, - BT_CTF_RESOLVE_FLAG_PACKET_CONTEXT | - BT_CTF_RESOLVE_FLAG_EVENT_HEADER | - BT_CTF_RESOLVE_FLAG_STREAM_EVENT_CTX); - if (ret) { - BT_LOGW("Cannot resolve stream class field types: ret=%d", - ret); - goto end; - } - - /* Validate field types individually */ - if (packet_context_type) { - ret = bt_ctf_field_type_common_validate(packet_context_type); - if (ret) { - BT_LOGW("Invalid stream class's packet context field type: " - "ret=%d", ret); - goto end; - } - } - - if (event_header_type) { - ret = bt_ctf_field_type_common_validate(event_header_type); - if (ret) { - BT_LOGW("Invalid stream class's event header field type: " - "ret=%d", ret); - goto end; - } - } - - if (stream_event_ctx_type) { - ret = bt_ctf_field_type_common_validate( - stream_event_ctx_type); - if (ret) { - BT_LOGW("Invalid stream class's event context field type: " - "ret=%d", ret); - goto end; - } - } - -end: - return ret; -} - -/* - * This function resolves and validates the field types of a trace. - * - * All parameters are owned by the caller. - */ -static -int validate_trace_types(struct bt_ctf_private_value *environment, - struct bt_ctf_field_type_common *packet_header_type) -{ - int ret = 0; - - BT_LOGV("Validating event class field types: " - "packet-header-ft-addr=%p", packet_header_type); - - /* Resolve sequence type lengths and variant type tags first */ - ret = bt_ctf_resolve_types(environment, packet_header_type, - NULL, NULL, NULL, NULL, NULL, - BT_CTF_RESOLVE_FLAG_PACKET_HEADER); - if (ret) { - BT_LOGW("Cannot resolve trace field types: ret=%d", - ret); - goto end; - } - - /* Validate field types individually */ - if (packet_header_type) { - ret = bt_ctf_field_type_common_validate(packet_header_type); - if (ret) { - BT_LOGW("Invalid trace's packet header field type: " - "ret=%d", ret); - goto end; - } - } - -end: - return ret; -} - -/* - * Checks whether or not `field_type` contains a variant or a sequence - * field type, recursively. Returns 1 if it's the case. - * - * `field_type` is owned by the caller. - */ -static -int field_type_contains_sequence_or_variant_ft(struct bt_ctf_field_type_common *type) -{ - int ret = 0; - enum bt_ctf_field_type_id type_id = bt_ctf_field_type_common_get_type_id(type); - - switch (type_id) { - case BT_CTF_FIELD_TYPE_ID_SEQUENCE: - case BT_CTF_FIELD_TYPE_ID_VARIANT: - ret = 1; - goto end; - case BT_CTF_FIELD_TYPE_ID_ARRAY: - case BT_CTF_FIELD_TYPE_ID_STRUCT: - { - int i; - int field_count = bt_ctf_field_type_common_get_field_count(type); - - if (field_count < 0) { - ret = -1; - goto end; - } - - for (i = 0; i < field_count; ++i) { - struct bt_ctf_field_type_common *child_type = - bt_ctf_field_type_common_borrow_field_at_index( - type, i); - - ret = field_type_contains_sequence_or_variant_ft( - child_type); - if (ret != 0) { - goto end; - } - } - break; - } - default: - break; - } - -end: - return ret; -} - -BT_HIDDEN -int bt_ctf_validate_class_types(struct bt_ctf_private_value *environment, - struct bt_ctf_field_type_common *packet_header_type, - struct bt_ctf_field_type_common *packet_context_type, - struct bt_ctf_field_type_common *event_header_type, - struct bt_ctf_field_type_common *stream_event_ctx_type, - struct bt_ctf_field_type_common *event_context_type, - struct bt_ctf_field_type_common *event_payload_type, - int trace_valid, int stream_class_valid, int event_class_valid, - struct bt_ctf_validation_output *output, - enum bt_ctf_validation_flag validate_flags, - bt_ctf_validation_flag_copy_field_type_func copy_field_type_func) -{ - int ret = 0; - int contains_seq_var; - int valid_ret; - - BT_LOGV("Validating field types: " - "packet-header-ft-addr=%p, " - "packet-context-ft-addr=%p, " - "event-header-ft-addr=%p, " - "stream-event-context-ft-addr=%p, " - "event-context-ft-addr=%p, " - "event-payload-ft-addr=%p, " - "trace-is-valid=%d, stream-class-is-valid=%d, " - "event-class-is-valid=%d, validation-flags=%x", - packet_header_type, packet_context_type, event_header_type, - stream_event_ctx_type, event_context_type, event_payload_type, - trace_valid, stream_class_valid, event_class_valid, - (unsigned int) validate_flags); - - /* Clean output values */ - memset(output, 0, sizeof(*output)); - - /* Set initial valid flags according to valid parameters */ - if (trace_valid) { - output->valid_flags |= BT_CTF_VALIDATION_FLAG_TRACE; - } - - if (stream_class_valid) { - output->valid_flags |= BT_CTF_VALIDATION_FLAG_STREAM; - } - - if (event_class_valid) { - output->valid_flags |= BT_CTF_VALIDATION_FLAG_EVENT; - } - - /* Own the type parameters */ - bt_ctf_object_get_ref(packet_header_type); - bt_ctf_object_get_ref(packet_context_type); - bt_ctf_object_get_ref(event_header_type); - bt_ctf_object_get_ref(stream_event_ctx_type); - bt_ctf_object_get_ref(event_context_type); - bt_ctf_object_get_ref(event_payload_type); - - /* Validate trace */ - if ((validate_flags & BT_CTF_VALIDATION_FLAG_TRACE) && !trace_valid) { - struct bt_ctf_field_type_common *packet_header_type_copy = NULL; - - /* Create field type copies */ - if (packet_header_type) { - contains_seq_var = - field_type_contains_sequence_or_variant_ft( - packet_header_type); - if (contains_seq_var < 0) { - ret = contains_seq_var; - goto error; - } else if (!contains_seq_var) { - /* No copy is needed */ - packet_header_type_copy = packet_header_type; - bt_ctf_object_get_ref(packet_header_type_copy); - goto skip_packet_header_type_copy; - } - - BT_LOGV_STR("Copying packet header field type because it contains at least one sequence or variant field type."); - packet_header_type_copy = - copy_field_type_func(packet_header_type); - if (!packet_header_type_copy) { - ret = -1; - BT_LOGE_STR("Cannot copy packet header field type."); - goto error; - } - - /* - * Freeze this copy: if it's returned to the - * caller, it cannot be modified any way since - * it will be resolved. - */ - bt_ctf_field_type_common_freeze(packet_header_type_copy); - } - -skip_packet_header_type_copy: - /* Put original reference and move copy */ - BT_CTF_OBJECT_MOVE_REF(packet_header_type, packet_header_type_copy); - - /* Validate trace field types */ - valid_ret = validate_trace_types(environment, - packet_header_type); - if (valid_ret == 0) { - /* Trace is valid */ - output->valid_flags |= BT_CTF_VALIDATION_FLAG_TRACE; - } - } - - /* Validate stream class */ - if ((validate_flags & BT_CTF_VALIDATION_FLAG_STREAM) && - !stream_class_valid) { - struct bt_ctf_field_type_common *packet_context_type_copy = NULL; - struct bt_ctf_field_type_common *event_header_type_copy = NULL; - struct bt_ctf_field_type_common *stream_event_ctx_type_copy = NULL; - - if (packet_context_type) { - contains_seq_var = - field_type_contains_sequence_or_variant_ft( - packet_context_type); - if (contains_seq_var < 0) { - ret = contains_seq_var; - goto error; - } else if (!contains_seq_var) { - /* No copy is needed */ - packet_context_type_copy = packet_context_type; - bt_ctf_object_get_ref(packet_context_type_copy); - goto skip_packet_context_type_copy; - } - - BT_LOGV_STR("Copying packet context field type because it contains at least one sequence or variant field type."); - packet_context_type_copy = - copy_field_type_func(packet_context_type); - if (!packet_context_type_copy) { - BT_LOGE_STR("Cannot copy packet context field type."); - goto sc_validation_error; - } - - /* - * Freeze this copy: if it's returned to the - * caller, it cannot be modified any way since - * it will be resolved. - */ - bt_ctf_field_type_common_freeze(packet_context_type_copy); - } - -skip_packet_context_type_copy: - if (event_header_type) { - contains_seq_var = - field_type_contains_sequence_or_variant_ft( - event_header_type); - if (contains_seq_var < 0) { - ret = contains_seq_var; - goto error; - } else if (!contains_seq_var) { - /* No copy is needed */ - event_header_type_copy = event_header_type; - bt_ctf_object_get_ref(event_header_type_copy); - goto skip_event_header_type_copy; - } - - BT_LOGV_STR("Copying event header field type because it contains at least one sequence or variant field type."); - event_header_type_copy = - copy_field_type_func(event_header_type); - if (!event_header_type_copy) { - BT_LOGE_STR("Cannot copy event header field type."); - goto sc_validation_error; - } - - /* - * Freeze this copy: if it's returned to the - * caller, it cannot be modified any way since - * it will be resolved. - */ - bt_ctf_field_type_common_freeze(event_header_type_copy); - } - -skip_event_header_type_copy: - if (stream_event_ctx_type) { - contains_seq_var = - field_type_contains_sequence_or_variant_ft( - stream_event_ctx_type); - if (contains_seq_var < 0) { - ret = contains_seq_var; - goto error; - } else if (!contains_seq_var) { - /* No copy is needed */ - stream_event_ctx_type_copy = - stream_event_ctx_type; - bt_ctf_object_get_ref(stream_event_ctx_type_copy); - goto skip_stream_event_ctx_type_copy; - } - - BT_LOGV_STR("Copying stream event context field type because it contains at least one sequence or variant field type."); - stream_event_ctx_type_copy = - copy_field_type_func(stream_event_ctx_type); - if (!stream_event_ctx_type_copy) { - BT_LOGE_STR("Cannot copy stream event context field type."); - goto sc_validation_error; - } - - /* - * Freeze this copy: if it's returned to the - * caller, it cannot be modified any way since - * it will be resolved. - */ - bt_ctf_field_type_common_freeze(stream_event_ctx_type_copy); - } - -skip_stream_event_ctx_type_copy: - /* Put original references and move copies */ - BT_CTF_OBJECT_MOVE_REF(packet_context_type, packet_context_type_copy); - BT_CTF_OBJECT_MOVE_REF(event_header_type, event_header_type_copy); - BT_CTF_OBJECT_MOVE_REF(stream_event_ctx_type, stream_event_ctx_type_copy); - - /* Validate stream class field types */ - valid_ret = validate_stream_class_types(environment, - packet_header_type, packet_context_type, - event_header_type, stream_event_ctx_type); - if (valid_ret == 0) { - /* Stream class is valid */ - output->valid_flags |= BT_CTF_VALIDATION_FLAG_STREAM; - } - - goto sc_validation_done; - -sc_validation_error: - BT_CTF_OBJECT_PUT_REF_AND_RESET(packet_context_type_copy); - BT_CTF_OBJECT_PUT_REF_AND_RESET(event_header_type_copy); - BT_CTF_OBJECT_PUT_REF_AND_RESET(stream_event_ctx_type_copy); - ret = -1; - goto error; - } - -sc_validation_done: - /* Validate event class */ - if ((validate_flags & BT_CTF_VALIDATION_FLAG_EVENT) && - !event_class_valid) { - struct bt_ctf_field_type_common *event_context_type_copy = NULL; - struct bt_ctf_field_type_common *event_payload_type_copy = NULL; - - if (event_context_type) { - contains_seq_var = - field_type_contains_sequence_or_variant_ft( - event_context_type); - if (contains_seq_var < 0) { - ret = contains_seq_var; - goto error; - } else if (!contains_seq_var) { - /* No copy is needed */ - event_context_type_copy = event_context_type; - bt_ctf_object_get_ref(event_context_type_copy); - goto skip_event_context_type_copy; - } - - BT_LOGV_STR("Copying event context field type because it contains at least one sequence or variant field type."); - event_context_type_copy = - copy_field_type_func(event_context_type); - if (!event_context_type_copy) { - BT_LOGE_STR("Cannot copy event context field type."); - goto ec_validation_error; - } - - /* - * Freeze this copy: if it's returned to the - * caller, it cannot be modified any way since - * it will be resolved. - */ - bt_ctf_field_type_common_freeze(event_context_type_copy); - } - -skip_event_context_type_copy: - if (event_payload_type) { - contains_seq_var = - field_type_contains_sequence_or_variant_ft( - event_payload_type); - if (contains_seq_var < 0) { - ret = contains_seq_var; - goto error; - } else if (!contains_seq_var) { - /* No copy is needed */ - event_payload_type_copy = event_payload_type; - bt_ctf_object_get_ref(event_payload_type_copy); - goto skip_event_payload_type_copy; - } - - BT_LOGV_STR("Copying event payload field type because it contains at least one sequence or variant field type."); - event_payload_type_copy = - copy_field_type_func(event_payload_type); - if (!event_payload_type_copy) { - BT_LOGE_STR("Cannot copy event payload field type."); - goto ec_validation_error; - } - - /* - * Freeze this copy: if it's returned to the - * caller, it cannot be modified any way since - * it will be resolved. - */ - bt_ctf_field_type_common_freeze(event_payload_type_copy); - } - -skip_event_payload_type_copy: - /* Put original references and move copies */ - BT_CTF_OBJECT_MOVE_REF(event_context_type, event_context_type_copy); - BT_CTF_OBJECT_MOVE_REF(event_payload_type, event_payload_type_copy); - - /* Validate event class field types */ - valid_ret = validate_event_class_types(environment, - packet_header_type, packet_context_type, - event_header_type, stream_event_ctx_type, - event_context_type, event_payload_type); - if (valid_ret == 0) { - /* Event class is valid */ - output->valid_flags |= BT_CTF_VALIDATION_FLAG_EVENT; - } - - goto ec_validation_done; - -ec_validation_error: - BT_CTF_OBJECT_PUT_REF_AND_RESET(event_context_type_copy); - BT_CTF_OBJECT_PUT_REF_AND_RESET(event_payload_type_copy); - ret = -1; - goto error; - } - -ec_validation_done: - /* - * Validation is complete. Move the field types that were used - * to validate (and that were possibly altered by the validation - * process) to the output values. - */ - BT_CTF_OBJECT_MOVE_REF(output->packet_header_type, packet_header_type); - BT_CTF_OBJECT_MOVE_REF(output->packet_context_type, packet_context_type); - BT_CTF_OBJECT_MOVE_REF(output->event_header_type, event_header_type); - BT_CTF_OBJECT_MOVE_REF(output->stream_event_ctx_type, stream_event_ctx_type); - BT_CTF_OBJECT_MOVE_REF(output->event_context_type, event_context_type); - BT_CTF_OBJECT_MOVE_REF(output->event_payload_type, event_payload_type); - return ret; - -error: - BT_CTF_OBJECT_PUT_REF_AND_RESET(packet_header_type); - BT_CTF_OBJECT_PUT_REF_AND_RESET(packet_context_type); - BT_CTF_OBJECT_PUT_REF_AND_RESET(event_header_type); - BT_CTF_OBJECT_PUT_REF_AND_RESET(stream_event_ctx_type); - BT_CTF_OBJECT_PUT_REF_AND_RESET(event_context_type); - BT_CTF_OBJECT_PUT_REF_AND_RESET(event_payload_type); - return ret; -} - -BT_HIDDEN -void bt_ctf_validation_replace_types(struct bt_ctf_trace_common *trace, - struct bt_ctf_stream_class_common *stream_class, - struct bt_ctf_event_class_common *event_class, - struct bt_ctf_validation_output *output, - enum bt_ctf_validation_flag replace_flags) -{ - if ((replace_flags & BT_CTF_VALIDATION_FLAG_TRACE) && trace) { - bt_ctf_field_type_common_freeze(trace->packet_header_field_type); - BT_CTF_OBJECT_MOVE_REF(trace->packet_header_field_type, - output->packet_header_type); - } - - if ((replace_flags & BT_CTF_VALIDATION_FLAG_STREAM) && stream_class) { - bt_ctf_field_type_common_freeze(stream_class->packet_context_field_type); - bt_ctf_field_type_common_freeze(stream_class->event_header_field_type); - bt_ctf_field_type_common_freeze(stream_class->event_context_field_type); - BT_CTF_OBJECT_MOVE_REF(stream_class->packet_context_field_type, - output->packet_context_type); - BT_CTF_OBJECT_MOVE_REF(stream_class->event_header_field_type, - output->event_header_type); - BT_CTF_OBJECT_MOVE_REF(stream_class->event_context_field_type, - output->stream_event_ctx_type); - } - - if ((replace_flags & BT_CTF_VALIDATION_FLAG_EVENT) && event_class) { - bt_ctf_field_type_common_freeze(event_class->context_field_type); - bt_ctf_field_type_common_freeze(event_class->payload_field_type); - BT_CTF_OBJECT_MOVE_REF(event_class->context_field_type, output->event_context_type); - BT_CTF_OBJECT_MOVE_REF(event_class->payload_field_type, output->event_payload_type); - } -} - -BT_HIDDEN -void bt_ctf_validation_output_put_types( - struct bt_ctf_validation_output *output) -{ - BT_CTF_OBJECT_PUT_REF_AND_RESET(output->packet_header_type); - BT_CTF_OBJECT_PUT_REF_AND_RESET(output->packet_context_type); - BT_CTF_OBJECT_PUT_REF_AND_RESET(output->event_header_type); - BT_CTF_OBJECT_PUT_REF_AND_RESET(output->stream_event_ctx_type); - BT_CTF_OBJECT_PUT_REF_AND_RESET(output->event_context_type); - BT_CTF_OBJECT_PUT_REF_AND_RESET(output->event_payload_type); -}