X-Git-Url: http://git.efficios.com/?p=babeltrace.git;a=blobdiff_plain;f=lib%2Fctf-ir%2Fstream-class.c;h=c414f79d96c808be2ba5433adfd043d39009fc72;hp=2bb8b2903887fdbfa0495c8702f9eb93fa3044e4;hb=312c056ae3d374b253fa0cfe5ed576c0b0e5e569;hpb=d1e4683534e67cc8643ad27536f64f6cc54bc5dc diff --git a/lib/ctf-ir/stream-class.c b/lib/ctf-ir/stream-class.c index 2bb8b290..c414f79d 100644 --- a/lib/ctf-ir/stream-class.c +++ b/lib/ctf-ir/stream-class.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -115,10 +116,36 @@ void bt_stream_class_destroy(struct bt_object *obj) BT_LOGD("Destroying stream class: addr=%p, name=\"%s\", id=%" PRId64, stream_class, bt_stream_class_get_name(stream_class), bt_stream_class_get_id(stream_class)); + + /* + * IMPORTANT: Finalize the common stream class BEFORE finalizing + * the pools because otherwise this scenario is possible: + * + * 1. Event header field object pool is finalized, thus + * destroying its internal array and state. + * + * 2. Stream class is finalized: each event class is destroyed. + * + * 3. Destroying an event class finalizes its event pool, + * destroying each contained event. + * + * 4. Destroying an event makes it recycle its event header + * field to its stream class's event header field pool. But + * said pool is already destroyed. + */ bt_stream_class_common_finalize(BT_TO_COMMON(stream_class)); + bt_object_pool_finalize(&stream_class->event_header_field_pool); + bt_object_pool_finalize(&stream_class->packet_context_field_pool); g_free(stream_class); } +static +void free_field_wrapper(struct bt_field_wrapper *field_wrapper, + struct bt_stream_class *stream_class) +{ + bt_field_wrapper_destroy((void *) field_wrapper); +} + struct bt_stream_class *bt_stream_class_create(const char *name) { struct bt_stream_class *stream_class = NULL; @@ -138,6 +165,26 @@ struct bt_stream_class *bt_stream_class_create(const char *name) goto error; } + ret = bt_object_pool_initialize(&stream_class->event_header_field_pool, + (bt_object_pool_new_object_func) bt_field_wrapper_new, + (bt_object_pool_destroy_object_func) free_field_wrapper, + stream_class); + if (ret) { + BT_LOGE("Failed to initialize event header field pool: ret=%d", + ret); + goto error; + } + + ret = bt_object_pool_initialize(&stream_class->packet_context_field_pool, + (bt_object_pool_new_object_func) bt_field_wrapper_new, + (bt_object_pool_destroy_object_func) free_field_wrapper, + stream_class); + if (ret) { + BT_LOGE("Failed to initialize packet context field pool: ret=%d", + ret); + goto error; + } + BT_LOGD("Created stream class object: addr=%p, name=\"%s\"", stream_class, name); return stream_class; @@ -147,6 +194,72 @@ error: return NULL; } +struct bt_event_header_field *bt_stream_class_create_event_header_field( + struct bt_stream_class *stream_class) +{ + struct bt_field_wrapper *field_wrapper; + + BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class"); + BT_ASSERT_PRE(stream_class->common.frozen, + "Stream class is not part of a trace: %!+S", stream_class); + BT_ASSERT_PRE(stream_class->common.event_header_field_type, + "Stream class has no event header field type: %!+S", + stream_class); + field_wrapper = bt_field_wrapper_create( + &stream_class->event_header_field_pool, + (void *) stream_class->common.event_header_field_type); + if (!field_wrapper) { + BT_LIB_LOGE("Cannot allocate one event header field from stream class: " + "%![sc-]+S", stream_class); + goto error; + } + + BT_ASSERT(field_wrapper->field); + goto end; + +error: + if (field_wrapper) { + bt_field_wrapper_destroy(field_wrapper); + field_wrapper = NULL; + } + +end: + return (void *) field_wrapper; +} + +struct bt_packet_context_field *bt_stream_class_create_packet_context_field( + struct bt_stream_class *stream_class) +{ + struct bt_field_wrapper *field_wrapper; + + BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class"); + BT_ASSERT_PRE(stream_class->common.frozen, + "Stream class is not part of a trace: %!+S", stream_class); + BT_ASSERT_PRE(stream_class->common.packet_context_field_type, + "Stream class has no packet context field type: %!+S", + stream_class); + field_wrapper = bt_field_wrapper_create( + &stream_class->packet_context_field_pool, + (void *) stream_class->common.packet_context_field_type); + if (!field_wrapper) { + BT_LIB_LOGE("Cannot allocate one packet context field from stream class: " + "%![sc-]+S", stream_class); + goto error; + } + + BT_ASSERT(field_wrapper->field); + goto end; + +error: + if (field_wrapper) { + bt_field_wrapper_destroy(field_wrapper); + field_wrapper = NULL; + } + +end: + return (void *) field_wrapper; +} + struct bt_trace *bt_stream_class_borrow_trace(struct bt_stream_class *stream_class) { return BT_FROM_COMMON(bt_stream_class_common_borrow_trace( @@ -465,6 +578,8 @@ int bt_stream_class_add_event_class( { struct bt_trace *trace; int ret = 0; + uint64_t i; + struct bt_clock_class *old_clock_class; if (!stream_class) { BT_LOGW("Invalid parameter: stream class is NULL: " @@ -473,6 +588,7 @@ int bt_stream_class_add_event_class( goto end; } + old_clock_class = stream_class->common.clock_class; trace = BT_FROM_COMMON(bt_stream_class_common_borrow_trace( BT_TO_COMMON(stream_class))); if (trace && trace->is_static) { @@ -498,6 +614,28 @@ int bt_stream_class_add_event_class( (void) bt_trace_object_modification(&obj, trace); } + if (!old_clock_class && stream_class->common.clock_class) { + /* + * Adding this event class updated the stream class's + * single clock class: make sure all the events which + * exist in event pools have an existing clock value for + * this clock class so that any created event object in + * the future (from a pool or not) has this clock value + * available. + */ + for (i = 0; i < stream_class->common.event_classes->len; i++) { + struct bt_event_class *event_class = + stream_class->common.event_classes->pdata[i]; + + BT_ASSERT(event_class); + ret = bt_event_class_update_event_pool_clock_values( + event_class); + if (ret) { + goto end; + } + } + } + end: return ret; }