X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=formats%2Fctf%2Fir%2Ftrace.c;h=fb897dabeea5e91ab804c9c1c4a06dcfde75dc21;hb=4ed90fb3c1b2f7912d65b905d960274ce3738e0d;hp=1ad37bec5ee85b5d7e7c65d885580d29b9726806;hpb=884cd6c32dddeb5e9fa8d0255992956112381123;p=babeltrace.git diff --git a/formats/ctf/ir/trace.c b/formats/ctf/ir/trace.c index 1ad37bec..fb897dab 100644 --- a/formats/ctf/ir/trace.c +++ b/formats/ctf/ir/trace.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #define DEFAULT_IDENTIFIER_SIZE 128 @@ -44,13 +45,6 @@ void bt_ctf_trace_destroy(struct bt_ctf_ref *ref); static int init_trace_packet_header(struct bt_ctf_trace *trace); -static -const char * const reserved_keywords_str[] = {"align", "callsite", - "const", "char", "clock", "double", "enum", "env", "event", - "floating_point", "float", "integer", "int", "long", "short", "signed", - "stream", "string", "struct", "trace", "typealias", "typedef", - "unsigned", "variant", "void" "_Bool", "_Complex", "_Imaginary"}; - static const unsigned int field_type_aliases_alignments[] = { [FIELD_TYPE_ALIAS_UINT5_T] = 1, @@ -69,10 +63,6 @@ const unsigned int field_type_aliases_sizes[] = { [FIELD_TYPE_ALIAS_UINT64_T] = 64, }; -static GHashTable *reserved_keywords_set; -static int init_done; -static int global_data_refcount; - struct bt_ctf_trace *bt_ctf_trace_create(void) { struct bt_ctf_trace *trace = NULL; @@ -137,8 +127,7 @@ void bt_ctf_trace_destroy(struct bt_ctf_ref *ref) g_ptr_array_free(trace->stream_classes, TRUE); } - bt_ctf_field_type_put(trace->trace_packet_header_type); - bt_ctf_field_put(trace->trace_packet_header); + bt_ctf_field_type_put(trace->packet_header_type); g_free(trace); } @@ -154,14 +143,7 @@ struct bt_ctf_stream *bt_ctf_trace_create_stream(struct bt_ctf_trace *trace, goto error; } - ret = bt_ctf_stream_class_set_byte_order(stream_class, - trace->byte_order == LITTLE_ENDIAN ? - BT_CTF_BYTE_ORDER_LITTLE_ENDIAN : BT_CTF_BYTE_ORDER_BIG_ENDIAN); - if (ret) { - goto error; - } - - stream = bt_ctf_stream_create(stream_class); + stream = bt_ctf_stream_create(stream_class, trace); if (!stream) { goto error; } @@ -177,7 +159,7 @@ struct bt_ctf_stream *bt_ctf_trace_create_stream(struct bt_ctf_trace *trace, if (stream_id < 0) { /* Try to assign a new stream id */ - if (bt_ctf_stream_class_set_id(stream->stream_class, + if (_bt_ctf_stream_class_set_id(stream->stream_class, trace->next_stream_id++)) { goto error; } @@ -196,9 +178,25 @@ struct bt_ctf_stream *bt_ctf_trace_create_stream(struct bt_ctf_trace *trace, bt_ctf_stream_get(stream); g_ptr_array_add(trace->streams, stream); + + /* + * Freeze the trace and its packet header. + * + * All field type byte orders set as "native" byte ordering can now be + * safely set to trace's own endianness, including the stream class'. + */ + bt_ctf_field_type_set_native_byte_order(trace->packet_header_type, + trace->byte_order); + ret = bt_ctf_stream_class_set_byte_order(stream_class, + trace->byte_order == LITTLE_ENDIAN ? + BT_CTF_BYTE_ORDER_LITTLE_ENDIAN : BT_CTF_BYTE_ORDER_BIG_ENDIAN); + if (ret) { + goto error; + } + + bt_ctf_stream_class_freeze(stream_class); trace->frozen = 1; return stream; - error: bt_ctf_stream_put(stream); return NULL; @@ -212,7 +210,7 @@ int bt_ctf_trace_add_environment_field(struct bt_ctf_trace *trace, char *escaped_value = NULL; int ret = 0; - if (!trace || !name || !value || validate_identifier(name)) { + if (!trace || !name || !value || bt_ctf_validate_identifier(name)) { ret = -1; goto error; } @@ -228,6 +226,7 @@ int bt_ctf_trace_add_environment_field(struct bt_ctf_trace *trace, goto error; } + var->type = BT_ENVIRONMENT_FIELD_TYPE_STRING; escaped_value = g_strescape(value, NULL); if (!escaped_value) { ret = -1; @@ -235,9 +234,9 @@ int bt_ctf_trace_add_environment_field(struct bt_ctf_trace *trace, } var->name = g_string_new(name); - var->value = g_string_new(escaped_value); + var->value.string = g_string_new(escaped_value); g_free(escaped_value); - if (!var->name || !var->value) { + if (!var->name || !var->value.string) { ret = -1; goto error; } @@ -250,14 +249,141 @@ error: g_string_free(var->name, TRUE); } - if (var && var->value) { - g_string_free(var->value, TRUE); + if (var && var->value.string) { + g_string_free(var->value.string, TRUE); + } + + g_free(var); + return ret; +} + +int bt_ctf_trace_add_environment_field_integer(struct bt_ctf_trace *trace, + const char *name, + int64_t value) +{ + struct environment_variable *var = NULL; + int ret = 0; + + if (!trace || !name) { + ret = -1; + goto error; + } + + var = g_new0(struct environment_variable, 1); + if (!var) { + ret = -1; + goto error; + } + + var->type = BT_ENVIRONMENT_FIELD_TYPE_INTEGER; + var->name = g_string_new(name); + var->value.integer = value; + if (!var->name) { + ret = -1; + goto error; + } + + g_ptr_array_add(trace->environment, var); + return ret; + +error: + if (var && var->name) { + g_string_free(var->name, TRUE); } g_free(var); return ret; } +int bt_ctf_trace_get_environment_field_count(struct bt_ctf_trace *trace) +{ + int ret = 0; + + if (!trace) { + ret = -1; + goto end; + } + + ret = trace->environment->len; +end: + return ret; +} + +enum bt_environment_field_type +bt_ctf_trace_get_environment_field_type(struct bt_ctf_trace *trace, int index) +{ + struct environment_variable *var; + enum bt_environment_field_type type = BT_ENVIRONMENT_FIELD_TYPE_UNKNOWN; + + if (!trace || index < 0 || index >= trace->environment->len) { + goto end; + } + + var = g_ptr_array_index(trace->environment, index); + type = var->type; +end: + return type; +} + +const char * +bt_ctf_trace_get_environment_field_name(struct bt_ctf_trace *trace, + int index) +{ + struct environment_variable *var; + const char *ret = NULL; + + if (!trace || index < 0 || index >= trace->environment->len) { + goto end; + } + + var = g_ptr_array_index(trace->environment, index); + ret = var->name->str; +end: + return ret; +} + +const char * +bt_ctf_trace_get_environment_field_value_string(struct bt_ctf_trace *trace, + int index) +{ + struct environment_variable *var; + const char *ret = NULL; + + if (!trace || index < 0 || index >= trace->environment->len) { + goto end; + } + + var = g_ptr_array_index(trace->environment, index); + if (var->type != BT_ENVIRONMENT_FIELD_TYPE_STRING) { + goto end; + } + ret = var->value.string->str; +end: + return ret; +} + +int +bt_ctf_trace_get_environment_field_value_integer(struct bt_ctf_trace *trace, + int index, int64_t *value) +{ + struct environment_variable *var; + int ret = 0; + + if (!trace || !value || index < 0 || index >= trace->environment->len) { + ret = -1; + goto end; + } + + var = g_ptr_array_index(trace->environment, index); + if (var->type != BT_ENVIRONMENT_FIELD_TYPE_INTEGER) { + ret = -1; + goto end; + } + *value = var->value.integer; +end: + return ret; +} + int bt_ctf_trace_add_clock(struct bt_ctf_trace *trace, struct bt_ctf_clock *clock) { @@ -354,7 +480,7 @@ int append_trace_metadata(struct bt_ctf_trace *trace, g_string_append(context->string, "\tpacket.header := "); context->current_indentation_level++; g_string_assign(context->field_name, ""); - ret = bt_ctf_field_type_serialize(trace->trace_packet_header_type, + ret = bt_ctf_field_type_serialize(trace->packet_header_type, context); if (ret) { goto end; @@ -370,8 +496,18 @@ static void append_env_field_metadata(struct environment_variable *var, struct metadata_context *context) { - g_string_append_printf(context->string, "\t%s = \"%s\";\n", - var->name->str, var->value->str); + switch (var->type) { + case BT_ENVIRONMENT_FIELD_TYPE_STRING: + g_string_append_printf(context->string, "\t%s = \"%s\";\n", + var->name->str, var->value.string->str); + break; + case BT_ENVIRONMENT_FIELD_TYPE_INTEGER: + g_string_append_printf(context->string, "\t%s = %" PRId64 ";\n", + var->name->str, var->value.integer); + break; + default: + assert(0); + } } static @@ -431,6 +567,28 @@ end: return metadata; } +enum bt_ctf_byte_order bt_ctf_trace_get_byte_order(struct bt_ctf_trace *trace) +{ + enum bt_ctf_byte_order ret = BT_CTF_BYTE_ORDER_UNKNOWN; + + if (!trace) { + goto end; + } + + switch (trace->byte_order) { + case BIG_ENDIAN: + ret = BT_CTF_BYTE_ORDER_BIG_ENDIAN; + break; + case LITTLE_ENDIAN: + ret = BT_CTF_BYTE_ORDER_LITTLE_ENDIAN; + break; + default: + break; + } +end: + return ret; +} + int bt_ctf_trace_set_byte_order(struct bt_ctf_trace *trace, enum bt_ctf_byte_order byte_order) { @@ -444,7 +602,16 @@ int bt_ctf_trace_set_byte_order(struct bt_ctf_trace *trace, switch (byte_order) { case BT_CTF_BYTE_ORDER_NATIVE: - internal_byte_order = (G_BYTE_ORDER == G_LITTLE_ENDIAN) ? + /* + * This doesn't make sense since the CTF specification defines + * the "native" byte order as "the byte order described in the + * trace description". However, this behavior had been + * implemented as part of v1.2 and is kept to maintain + * compatibility. + * + * This may be changed on a major version bump only. + */ + internal_byte_order = (G_BYTE_ORDER == G_LITTLE_ENDIAN) ? LITTLE_ENDIAN : BIG_ENDIAN; break; case BT_CTF_BYTE_ORDER_LITTLE_ENDIAN: @@ -460,66 +627,67 @@ int bt_ctf_trace_set_byte_order(struct bt_ctf_trace *trace, } trace->byte_order = internal_byte_order; - if (trace->trace_packet_header_type || - trace->trace_packet_header) { - init_trace_packet_header(trace); - } end: return ret; } -void bt_ctf_trace_get(struct bt_ctf_trace *trace) +struct bt_ctf_field_type *bt_ctf_trace_get_packet_header_type( + struct bt_ctf_trace *trace) { - if (!trace) { - return; - } - - bt_ctf_ref_get(&trace->ref_count); -} + struct bt_ctf_field_type *field_type = NULL; -void bt_ctf_trace_put(struct bt_ctf_trace *trace) -{ if (!trace) { - return; + goto end; } - bt_ctf_ref_put(&trace->ref_count, bt_ctf_trace_destroy); + bt_ctf_field_type_get(trace->packet_header_type); + field_type = trace->packet_header_type; +end: + return field_type; } -BT_HIDDEN -int validate_identifier(const char *input_string) +int bt_ctf_trace_set_packet_header_type(struct bt_ctf_trace *trace, + struct bt_ctf_field_type *packet_header_type) { int ret = 0; - char *string = NULL; - char *save_ptr, *token; - if (!input_string || input_string[0] == '\0') { + if (!trace || !packet_header_type || trace->frozen) { ret = -1; goto end; } - string = strdup(input_string); - if (!string) { + /* packet_header_type must be a structure */ + if (bt_ctf_field_type_get_type_id(packet_header_type) != + CTF_TYPE_STRUCT) { ret = -1; goto end; } - token = strtok_r(string, " ", &save_ptr); - while (token) { - if (g_hash_table_lookup_extended(reserved_keywords_set, - GINT_TO_POINTER(g_quark_from_string(token)), - NULL, NULL)) { - ret = -1; - goto end; - } - - token = strtok_r(NULL, " ", &save_ptr); - } + bt_ctf_field_type_get(packet_header_type); + bt_ctf_field_type_put(trace->packet_header_type); + trace->packet_header_type = packet_header_type; end: - free(string); return ret; } +void bt_ctf_trace_get(struct bt_ctf_trace *trace) +{ + if (!trace) { + return; + } + + bt_ctf_ref_get(&trace->ref_count); +} + +void bt_ctf_trace_put(struct bt_ctf_trace *trace) +{ + if (!trace) { + return; + } + + bt_ctf_ref_put(&trace->ref_count, bt_ctf_trace_destroy); +} + BT_HIDDEN struct bt_ctf_field_type *get_field_type(enum field_type_alias alias) { @@ -540,10 +708,8 @@ struct bt_ctf_field_type *get_field_type(enum field_type_alias alias) static int init_trace_packet_header(struct bt_ctf_trace *trace) { - size_t i; int ret = 0; - struct bt_ctf_field *trace_packet_header = NULL, - *magic = NULL, *uuid_array = NULL; + struct bt_ctf_field *magic = NULL, *uuid_array = NULL; struct bt_ctf_field_type *_uint32_t = get_field_type(FIELD_TYPE_ALIAS_UINT32_T); struct bt_ctf_field_type *_uint8_t = @@ -558,14 +724,6 @@ int init_trace_packet_header(struct bt_ctf_trace *trace) goto end; } - ret = bt_ctf_field_type_set_byte_order(_uint32_t, - (trace->byte_order == LITTLE_ENDIAN ? - BT_CTF_BYTE_ORDER_LITTLE_ENDIAN : - BT_CTF_BYTE_ORDER_BIG_ENDIAN)); - if (ret) { - goto end; - } - ret = bt_ctf_field_type_structure_add_field(trace_packet_header_type, _uint32_t, "magic"); if (ret) { @@ -584,45 +742,18 @@ int init_trace_packet_header(struct bt_ctf_trace *trace) goto end; } - trace_packet_header = bt_ctf_field_create(trace_packet_header_type); - if (!trace_packet_header) { - ret = -1; - goto end; - } - - magic = bt_ctf_field_structure_get_field(trace_packet_header, "magic"); - ret = bt_ctf_field_unsigned_integer_set_value(magic, 0xC1FC1FC1); + ret = bt_ctf_trace_set_packet_header_type(trace, + trace_packet_header_type); if (ret) { goto end; } - - uuid_array = bt_ctf_field_structure_get_field(trace_packet_header, - "uuid"); - for (i = 0; i < 16; i++) { - struct bt_ctf_field *uuid_element = - bt_ctf_field_array_get_field(uuid_array, i); - ret = bt_ctf_field_unsigned_integer_set_value(uuid_element, - trace->uuid[i]); - bt_ctf_field_put(uuid_element); - if (ret) { - goto end; - } - } - - bt_ctf_field_type_put(trace->trace_packet_header_type); - bt_ctf_field_put(trace->trace_packet_header); - trace->trace_packet_header_type = trace_packet_header_type; - trace->trace_packet_header = trace_packet_header; end: bt_ctf_field_type_put(uuid_array_type); bt_ctf_field_type_put(_uint32_t); bt_ctf_field_type_put(_uint8_t); bt_ctf_field_put(magic); bt_ctf_field_put(uuid_array); - if (ret) { - bt_ctf_field_type_put(trace_packet_header_type); - bt_ctf_field_put(trace_packet_header); - } + bt_ctf_field_type_put(trace_packet_header_type); return ret; } @@ -631,37 +762,8 @@ static void environment_variable_destroy(struct environment_variable *var) { g_string_free(var->name, TRUE); - g_string_free(var->value, TRUE); - g_free(var); -} - -static __attribute__((constructor)) -void trace_init(void) -{ - size_t i; - const size_t reserved_keywords_count = - sizeof(reserved_keywords_str) / sizeof(char *); - - global_data_refcount++; - if (init_done) { - return; - } - - reserved_keywords_set = g_hash_table_new(g_direct_hash, g_direct_equal); - for (i = 0; i < reserved_keywords_count; i++) { - gpointer quark = GINT_TO_POINTER(g_quark_from_string( - reserved_keywords_str[i])); - - g_hash_table_insert(reserved_keywords_set, quark, quark); - } - - init_done = 1; -} - -static __attribute__((destructor)) -void trace_finalize(void) -{ - if (--global_data_refcount == 0) { - g_hash_table_destroy(reserved_keywords_set); + if (var->type == BT_ENVIRONMENT_FIELD_TYPE_STRING) { + g_string_free(var->value.string, TRUE); } + g_free(var); }