X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=formats%2Fctf%2Fir%2Ftrace.c;h=dfb815514f55a145fa2c10ea2a3c7f3c090a4079;hb=835b2d10c5c80ebad6427ba3794d712dd44ef145;hp=660a2ed5c6abf438687345aa0083b3dbb6667f71;hpb=738537a613441515daf93e778beb7148014b1493;p=babeltrace.git diff --git a/formats/ctf/ir/trace.c b/formats/ctf/ir/trace.c index 660a2ed5..dfb81551 100644 --- a/formats/ctf/ir/trace.c +++ b/formats/ctf/ir/trace.c @@ -37,7 +37,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -46,6 +48,11 @@ #define DEFAULT_IDENTIFIER_SIZE 128 #define DEFAULT_METADATA_STRING_SIZE 4096 +struct listener_wrapper { + bt_ctf_listener_cb listener; + void *data; +}; + static void bt_ctf_trace_destroy(struct bt_object *obj); static @@ -104,6 +111,12 @@ struct bt_ctf_trace *bt_ctf_trace_create(void) goto error; } + trace->listeners = g_ptr_array_new_with_free_func( + (GDestroyNotify) g_free); + if (!trace->listeners) { + goto error; + } + return trace; error: @@ -111,6 +124,38 @@ error: return trace; } +const char *bt_ctf_trace_get_name(struct bt_ctf_trace *trace) +{ + const char *name = NULL; + + if (!trace || !trace->name) { + goto end; + } + + name = trace->name->str; +end: + return name; +} + +int bt_ctf_trace_set_name(struct bt_ctf_trace *trace, const char *name) +{ + int ret = 0; + + if (!trace || !name || trace->frozen) { + ret = -1; + goto end; + } + + trace->name = trace->name ? g_string_assign(trace->name, name) : + g_string_new(name); + if (!trace->name) { + ret = -1; + goto end; + } +end: + return ret; +} + void bt_ctf_trace_destroy(struct bt_object *obj) { struct bt_ctf_trace *trace; @@ -120,6 +165,10 @@ void bt_ctf_trace_destroy(struct bt_object *obj) bt_ctf_attributes_destroy(trace->environment); } + if (trace->name) { + g_string_free(trace->name, TRUE); + } + if (trace->clocks) { g_ptr_array_free(trace->clocks, TRUE); } @@ -132,45 +181,12 @@ void bt_ctf_trace_destroy(struct bt_object *obj) g_ptr_array_free(trace->stream_classes, TRUE); } - bt_put(trace->packet_header_type); - g_free(trace); -} - -struct bt_ctf_stream *bt_ctf_trace_create_stream(struct bt_ctf_trace *trace, - struct bt_ctf_stream_class *stream_class) -{ - int ret; - int stream_class_found = 0; - size_t i; - struct bt_ctf_stream *stream = NULL; - - if (!trace || !stream_class) { - goto error; - } - - for (i = 0; i < trace->stream_classes->len; i++) { - if (trace->stream_classes->pdata[i] == stream_class) { - stream_class_found = 1; - } - } - - if (!stream_class_found) { - ret = bt_ctf_trace_add_stream_class(trace, stream_class); - if (ret) { - goto error; - } - } - - stream = bt_ctf_stream_create(stream_class, trace); - if (!stream) { - goto error; + if (trace->listeners) { + g_ptr_array_free(trace->listeners, TRUE); } - g_ptr_array_add(trace->streams, stream); - return stream; -error: - BT_PUT(stream); - return stream; + bt_put(trace->packet_header_type); + g_free(trace); } int bt_ctf_trace_set_environment_field(struct bt_ctf_trace *trace, @@ -373,7 +389,7 @@ int bt_ctf_trace_add_clock(struct bt_ctf_trace *trace, int ret = 0; struct search_query query = { .value = clock, .found = 0 }; - if (!trace || !clock) { + if (!trace || !bt_ctf_clock_is_valid(clock)) { ret = -1; goto end; } @@ -388,6 +404,15 @@ int bt_ctf_trace_add_clock(struct bt_ctf_trace *trace, bt_get(clock); g_ptr_array_add(trace->clocks, clock); + if (!trace->is_created_by_writer) { + /* + * Non-writer mode trace: disable clock value functions + * because clock values are per-stream in that + * situation. + */ + clock->has_value = 0; + } + if (trace->frozen) { bt_ctf_clock_freeze(clock); } @@ -440,12 +465,21 @@ int bt_ctf_trace_add_stream_class(struct bt_ctf_trace *trace, struct bt_ctf_field_type *event_header_type = NULL; struct bt_ctf_field_type *stream_event_ctx_type = NULL; int event_class_count; + struct bt_ctf_clock *clock_to_add_to_trace = NULL; + struct bt_ctf_trace *current_parent_trace = NULL; if (!trace || !stream_class) { ret = -1; goto end; } + current_parent_trace = bt_ctf_stream_class_get_trace(stream_class); + if (current_parent_trace) { + /* Stream class is already associated to a trace, abort. */ + ret = -1; + goto end; + } + event_class_count = bt_ctf_stream_class_get_event_class_count(stream_class); assert(event_class_count >= 0); @@ -459,6 +493,32 @@ int bt_ctf_trace_add_stream_class(struct bt_ctf_trace *trace, } } + /* + * If the stream class has a clock, register this clock to this + * trace if not already done. + */ + if (stream_class->clock) { + const char *clock_name = + bt_ctf_clock_get_name(stream_class->clock); + struct bt_ctf_clock *trace_clock; + + assert(clock_name); + trace_clock = bt_ctf_trace_get_clock_by_name(trace, clock_name); + bt_put(trace_clock); + if (trace_clock) { + if (trace_clock != stream_class->clock) { + /* + * Error: two different clocks in the + * trace would share the same name. + */ + ret = -1; + goto end; + } + } else { + clock_to_add_to_trace = bt_get(stream_class->clock); + } + } + /* * We're about to freeze both the trace and the stream class. * Also, each event class contained in this stream class are @@ -621,12 +681,22 @@ int bt_ctf_trace_add_stream_class(struct bt_ctf_trace *trace, trace->byte_order); bt_ctf_stream_class_set_byte_order(stream_class, trace->byte_order); + /* Add stream class's clock if it exists */ + if (clock_to_add_to_trace) { + int add_clock_ret = + bt_ctf_trace_add_clock(trace, clock_to_add_to_trace); + assert(add_clock_ret == 0); + } + /* * Freeze the trace and the stream class. */ bt_ctf_stream_class_freeze(stream_class); bt_ctf_trace_freeze(trace); + /* Notifiy listeners of the trace's schema modification. */ + bt_ctf_stream_class_visit(stream_class, + bt_ctf_trace_object_modification, trace); end: if (ret) { bt_object_set_parent(stream_class, NULL); @@ -641,6 +711,8 @@ end: g_free(ec_validation_outputs); bt_ctf_validation_output_put_types(&trace_sc_validation_output); + BT_PUT(clock_to_add_to_trace); + bt_put(current_parent_trace); assert(!packet_header_type); assert(!packet_context_type); assert(!event_header_type); @@ -1001,28 +1073,132 @@ int bt_ctf_trace_set_packet_header_type(struct bt_ctf_trace *trace, { int ret = 0; - if (!trace || !packet_header_type || trace->frozen) { + if (!trace || trace->frozen) { ret = -1; goto end; } - /* packet_header_type must be a structure */ - if (bt_ctf_field_type_get_type_id(packet_header_type) != - BT_CTF_TYPE_ID_STRUCT) { + /* packet_header_type must be a structure. */ + if (packet_header_type && + bt_ctf_field_type_get_type_id(packet_header_type) != + BT_CTF_TYPE_ID_STRUCT) { ret = -1; goto end; } - bt_get(packet_header_type); bt_put(trace->packet_header_type); - trace->packet_header_type = packet_header_type; + trace->packet_header_type = bt_get(packet_header_type); end: return ret; } +static +int get_stream_class_count(void *element) +{ + return bt_ctf_trace_get_stream_class_count( + (struct bt_ctf_trace *) element); +} + +static +void *get_stream_class(void *element, int i) +{ + return bt_ctf_trace_get_stream_class( + (struct bt_ctf_trace *) element, i); +} + +static +int visit_stream_class(void *object, bt_ctf_visitor visitor,void *data) +{ + return bt_ctf_stream_class_visit(object, visitor, data); +} + +int bt_ctf_trace_visit(struct bt_ctf_trace *trace, + bt_ctf_visitor visitor, void *data) +{ + int ret; + struct bt_ctf_object obj = + { .object = trace, .type = BT_CTF_OBJECT_TYPE_TRACE }; + + if (!trace || !visitor) { + ret = -1; + goto end; + } + + ret = visitor_helper(&obj, get_stream_class_count, + get_stream_class, visit_stream_class, visitor, data); +end: + return ret; +} + +static +int invoke_listener(struct bt_ctf_object *object, void *data) +{ + struct listener_wrapper *listener_wrapper = data; + + listener_wrapper->listener(object, listener_wrapper->data); + return 0; +} + +int bt_ctf_trace_add_listener(struct bt_ctf_trace *trace, + bt_ctf_listener_cb listener, void *listener_data) +{ + int ret = 0; + struct listener_wrapper *listener_wrapper = + g_new0(struct listener_wrapper, 1); + + if (!trace || !listener || !listener_wrapper) { + ret = -1; + goto error; + } + + listener_wrapper->listener = listener; + listener_wrapper->data = listener_data; + + /* Visit the current schema. */ + ret = bt_ctf_trace_visit(trace, invoke_listener, listener_wrapper); + if (ret) { + goto error; + } + + /* + * Add listener to the array of callbacks which will be invoked on + * schema changes. + */ + g_ptr_array_add(trace->listeners, listener_wrapper); + return ret; +error: + g_free(listener_wrapper); + return ret; +} + +BT_HIDDEN +int bt_ctf_trace_object_modification(struct bt_ctf_object *object, + void *trace_ptr) +{ + size_t i; + struct bt_ctf_trace *trace = trace_ptr; + + assert(trace); + assert(object); + + if (trace->listeners->len == 0) { + goto end; + } + + for (i = 0; i < trace->listeners->len; i++) { + struct listener_wrapper *listener = + g_ptr_array_index(trace->listeners, i); + + listener->listener(object, listener->data); + } +end: + return 0; +} + BT_HIDDEN struct bt_ctf_field_type *get_field_type(enum field_type_alias alias) { + int ret; unsigned int alignment, size; struct bt_ctf_field_type *field_type = NULL; @@ -1033,7 +1209,10 @@ struct bt_ctf_field_type *get_field_type(enum field_type_alias alias) alignment = field_type_aliases_alignments[alias]; size = field_type_aliases_sizes[alias]; field_type = bt_ctf_field_type_integer_create(size); - bt_ctf_field_type_set_alignment(field_type, alignment); + ret = bt_ctf_field_type_set_alignment(field_type, alignment); + if (ret) { + BT_PUT(field_type); + } end: return field_type; }