From: Jérémie Galarneau Date: Thu, 17 Nov 2016 20:49:53 +0000 (-0500) Subject: Track clock states in notification iterator X-Git-Tag: v2.0.0-pre1~709 X-Git-Url: http://git.efficios.com/?p=babeltrace.git;a=commitdiff_plain;h=c44c3e709f9e95a847e9502c5297234aa1f01577 Track clock states in notification iterator Signed-off-by: Jérémie Galarneau --- diff --git a/formats/ctf/ir/event.c b/formats/ctf/ir/event.c index 13bf8a44..505aa104 100644 --- a/formats/ctf/ir/event.c +++ b/formats/ctf/ir/event.c @@ -856,37 +856,3 @@ void bt_ctf_event_freeze(struct bt_ctf_event *event) bt_ctf_field_freeze(event->fields_payload); event->frozen = 1; } - -static -void insert_stream_clock_value_into_event_clock_values(gpointer key, - gpointer value, - gpointer data) -{ - struct bt_ctf_event *event = data; - uint64_t *clock_value; - - assert(event); - - /* Copy clock value because it belongs to the hash table */ - clock_value = g_new0(uint64_t, 1); - *clock_value = *((uint64_t *) value); - - /* Insert copy into event clock values */ - g_hash_table_insert(event->clock_values, key, clock_value); -} - -BT_HIDDEN -int bt_ctf_event_register_stream_clock_values(struct bt_ctf_event *event) -{ - int ret = 0; - struct bt_ctf_stream *stream; - - stream = bt_ctf_event_get_stream(event); - assert(stream); - g_hash_table_remove_all(event->clock_values); - g_hash_table_foreach(stream->clock_values, - insert_stream_clock_value_into_event_clock_values, event); - BT_PUT(stream); - - return ret; -} diff --git a/formats/ctf/ir/stream.c b/formats/ctf/ir/stream.c index 56abfcea..8c5a9877 100644 --- a/formats/ctf/ir/stream.c +++ b/formats/ctf/ir/stream.c @@ -403,9 +403,6 @@ struct bt_ctf_stream *bt_ctf_stream_create( if (ret) { goto error; } - - stream->clock_values = g_hash_table_new_full(g_direct_hash, - g_direct_equal, NULL, g_free); } /* Add this stream to the trace's streams */ @@ -937,10 +934,6 @@ void bt_ctf_stream_destroy(struct bt_object *obj) g_string_free(stream->name, TRUE); } - if (stream->clock_values) { - g_hash_table_destroy(stream->clock_values); - } - bt_put(stream->packet_header); bt_put(stream->packet_context); g_free(stream); @@ -1009,78 +1002,3 @@ const char *bt_ctf_stream_get_name(struct bt_ctf_stream *stream) end: return name; } - -BT_HIDDEN -void bt_ctf_stream_update_clock_value(struct bt_ctf_stream *stream, - struct bt_ctf_field *value_field) -{ - struct bt_ctf_field_type *value_type = NULL; - struct bt_ctf_clock *clock = NULL; - uint64_t requested_new_value; - uint64_t requested_new_value_mask; - uint64_t *cur_value; - uint64_t cur_value_masked; - int requested_new_value_size; - int ret; - - assert(stream); - assert(clock); - assert(value_field); - value_type = bt_ctf_field_get_type(value_field); - assert(value_type); - clock = bt_ctf_field_type_integer_get_mapped_clock(value_type); - assert(clock); - requested_new_value_size = - bt_ctf_field_type_integer_get_size(value_type); - assert(requested_new_value_size > 0); - ret = bt_ctf_field_unsigned_integer_get_value(value_field, - &requested_new_value); - assert(!ret); - cur_value = g_hash_table_lookup(stream->clock_values, clock); - - if (!cur_value) { - /* - * Updating the value of a clock which is not registered - * yet, so register it with the new value as its initial - * value. - */ - uint64_t *requested_new_value_ptr = g_new0(uint64_t, 1); - - *requested_new_value_ptr = requested_new_value; - g_hash_table_insert(stream->clock_values, clock, - requested_new_value_ptr); - goto end; - } - - /* - * Special case for a 64-bit new value, which is the limit - * of a clock value as of this version: overwrite the - * current value directly. - */ - if (requested_new_value_size == 64) { - *cur_value = requested_new_value; - goto end; - } - - requested_new_value_mask = (1ULL << requested_new_value_size) - 1; - cur_value_masked = *cur_value & requested_new_value_mask; - - if (requested_new_value < cur_value_masked) { - /* - * It looks like a wrap happened on the number of bits - * of the requested new value. Assume that the clock - * value wrapped only one time. - */ - *cur_value += requested_new_value_mask + 1; - } - - /* Clear the low bits of the current clock value */ - *cur_value &= ~requested_new_value_mask; - - /* Set the low bits of the current clock value */ - *cur_value |= requested_new_value; - -end: - bt_put(clock); - bt_put(value_type); -} diff --git a/include/babeltrace/ctf-ir/event-internal.h b/include/babeltrace/ctf-ir/event-internal.h index cc10f224..ed09e962 100644 --- a/include/babeltrace/ctf-ir/event-internal.h +++ b/include/babeltrace/ctf-ir/event-internal.h @@ -50,9 +50,6 @@ struct bt_ctf_event { int frozen; }; -BT_HIDDEN -int bt_ctf_event_register_stream_clock_values(struct bt_ctf_event *event); - BT_HIDDEN int bt_ctf_event_validate(struct bt_ctf_event *event); diff --git a/include/babeltrace/ctf-ir/stream-internal.h b/include/babeltrace/ctf-ir/stream-internal.h index dc392f4a..a39b1529 100644 --- a/include/babeltrace/ctf-ir/stream-internal.h +++ b/include/babeltrace/ctf-ir/stream-internal.h @@ -47,14 +47,9 @@ struct bt_ctf_stream { GString *name; struct bt_ctf_field *packet_header; struct bt_ctf_field *packet_context; - GHashTable *clock_values; /* Maps clock addresses to (uint64_t *) */ }; BT_HIDDEN int bt_ctf_stream_set_fd(struct bt_ctf_stream *stream, int fd); -BT_HIDDEN -void bt_ctf_stream_update_clock_value(struct bt_ctf_stream *stream, - struct bt_ctf_field *value_field); - #endif /* BABELTRACE_CTF_WRITER_STREAM_INTERNAL_H */ diff --git a/plugins/ctf/common/btr/btr.h b/plugins/ctf/common/btr/btr.h index 75484155..ee6695a1 100644 --- a/plugins/ctf/common/btr/btr.h +++ b/plugins/ctf/common/btr/btr.h @@ -52,6 +52,8 @@ * Binary type reader API status codes. */ enum bt_ctf_btr_status { + /** Out of memory. */ + BT_CTF_BTR_STATUS_ENOMEM = -5, /** * The binary stream reader reached the end of the user-provided * buffer, but data is still needed to finish decoding the diff --git a/plugins/ctf/common/notif-iter/notif-iter.c b/plugins/ctf/common/notif-iter/notif-iter.c index 5e063626..d4bfdb1b 100644 --- a/plugins/ctf/common/notif-iter/notif-iter.c +++ b/plugins/ctf/common/notif-iter/notif-iter.c @@ -173,6 +173,9 @@ struct bt_ctf_notif_iter { /* Current content size (bits) (-1 if unknown) */ int64_t cur_content_size; + + /* bt_ctf_clock to uint64_t. */ + GHashTable *clock_states; }; static @@ -1220,6 +1223,103 @@ end: return next_field; } +static +void update_clock_state(uint64_t *state, + struct bt_ctf_field *value_field) +{ + struct bt_ctf_field_type *value_type = NULL; + uint64_t requested_new_value; + uint64_t requested_new_value_mask; + uint64_t cur_value_masked; + int requested_new_value_size; + int ret; + + value_type = bt_ctf_field_get_type(value_field); + assert(value_type); + + requested_new_value_size = + bt_ctf_field_type_integer_get_size(value_type); + assert(requested_new_value_size > 0); + + ret = bt_ctf_field_unsigned_integer_get_value(value_field, + &requested_new_value); + assert(!ret); + + /* + * Special case for a 64-bit new value, which is the limit + * of a clock value as of this version: overwrite the + * current value directly. + */ + if (requested_new_value_size == 64) { + *state = requested_new_value; + goto end; + } + + requested_new_value_mask = (1ULL << requested_new_value_size) - 1; + cur_value_masked = *state & requested_new_value_mask; + + if (requested_new_value < cur_value_masked) { + /* + * It looks like a wrap happened on the number of bits + * of the requested new value. Assume that the clock + * value wrapped only one time. + */ + *state += requested_new_value_mask + 1; + } + + /* Clear the low bits of the current clock value. */ + *state &= ~requested_new_value_mask; + + /* Set the low bits of the current clock value. */ + *state |= requested_new_value; +end: + bt_put(value_type); +} + +static +enum bt_ctf_btr_status update_clock(struct bt_ctf_notif_iter *notit, + struct bt_ctf_field_type *int_field_type, + struct bt_ctf_field *int_field) +{ + gboolean clock_found; + uint64_t *clock_state; + enum bt_ctf_btr_status ret = BT_CTF_BTR_STATUS_OK; + struct bt_ctf_clock *clock = bt_ctf_field_type_integer_get_mapped_clock( + int_field_type); + + if (likely(!clock)) { + goto end_no_clock; + } + + clock_found = g_hash_table_lookup_extended(notit->clock_states, + clock, NULL, (gpointer) &clock_state); + if (unlikely(!clock_found)) { + const char *clock_name = bt_ctf_clock_get_name(clock); + + PERR("Unknown clock %s mapped to integer encountered in stream\n", + clock_name ? : "NULL"); + ret = BT_CTF_BTR_STATUS_ERROR; + goto end; + } + + if (unlikely(!clock_state)) { + clock_state = g_new0(uint64_t, 1); + if (!clock_state) { + ret = BT_CTF_BTR_STATUS_ENOMEM; + goto end; + } + g_hash_table_insert(notit->clock_states, bt_get(clock), + clock_state); + } + + /* Update the clock's state. */ + update_clock_state(clock_state, int_field); +end: + bt_put(clock); +end_no_clock: + return ret; +} + static enum bt_ctf_btr_status btr_signed_int_cb(int64_t value, struct bt_ctf_field_type *type, void *data) @@ -1235,18 +1335,22 @@ enum bt_ctf_btr_status btr_signed_int_cb(int64_t value, if (!field) { PERR("Failed to get next field (signed int)\n"); status = BT_CTF_BTR_STATUS_ERROR; - goto end; + goto end_no_put; } switch(bt_ctf_field_type_get_type_id(type)) { case BT_CTF_TYPE_ID_INTEGER: /* Integer field is created field */ BT_MOVE(int_field, field); + bt_get(type); break; case BT_CTF_TYPE_ID_ENUM: int_field = bt_ctf_field_enumeration_get_container(field); + type = bt_ctf_field_get_type(int_field); break; default: + assert(0); + type = NULL; break; } @@ -1259,11 +1363,12 @@ enum bt_ctf_btr_status btr_signed_int_cb(int64_t value, ret = bt_ctf_field_signed_integer_set_value(int_field, value); assert(!ret); stack_top(notit->stack)->index++; - + status = update_clock(notit, type, int_field); end: BT_PUT(field); BT_PUT(int_field); - + BT_PUT(type); +end_no_put: return status; } @@ -1282,18 +1387,22 @@ enum bt_ctf_btr_status btr_unsigned_int_cb(uint64_t value, if (!field) { PERR("Failed to get next field (unsigned int)\n"); status = BT_CTF_BTR_STATUS_ERROR; - goto end; + goto end_no_put; } switch(bt_ctf_field_type_get_type_id(type)) { case BT_CTF_TYPE_ID_INTEGER: /* Integer field is created field */ BT_MOVE(int_field, field); + bt_get(type); break; case BT_CTF_TYPE_ID_ENUM: int_field = bt_ctf_field_enumeration_get_container(field); + type = bt_ctf_field_get_type(int_field); break; default: + assert(0); + type = NULL; break; } @@ -1306,11 +1415,12 @@ enum bt_ctf_btr_status btr_unsigned_int_cb(uint64_t value, ret = bt_ctf_field_unsigned_integer_set_value(int_field, value); assert(!ret); stack_top(notit->stack)->index++; - + status = update_clock(notit, type, int_field); end: BT_PUT(field); BT_PUT(int_field); - + BT_PUT(type); +end_no_put: return status; } @@ -1824,11 +1934,40 @@ end: BT_PUT(event); } +static +int init_clock_states(GHashTable *clock_states, struct bt_ctf_trace *trace) +{ + int clock_count, i, ret = 0; + + clock_count = bt_ctf_trace_get_clock_count(trace); + if (clock_count <= 0) { + ret = -1; + goto end; + } + + for (i = 0; i < clock_count; i++) { + struct bt_ctf_clock *clock; + + clock = bt_ctf_trace_get_clock(trace, i); + if (!clock) { + ret = -1; + goto end; + } + + g_hash_table_insert(clock_states, bt_get(clock), NULL); + bt_put(clock); + } +end: + return ret; +} + +BT_HIDDEN struct bt_ctf_notif_iter *bt_ctf_notif_iter_create(struct bt_ctf_trace *trace, size_t max_request_sz, struct bt_ctf_notif_iter_medium_ops medops, void *data, FILE *err_stream) { + int ret; struct bt_ctf_notif_iter *notit = NULL; struct bt_ctf_btr_cbs cbs = { .types = { @@ -1854,7 +1993,17 @@ struct bt_ctf_notif_iter *bt_ctf_notif_iter_create(struct bt_ctf_trace *trace, PERR("Failed to allocate memory for CTF notification iterator\n"); goto end; } - + notit->clock_states = g_hash_table_new_full(g_direct_hash, + g_direct_equal, bt_put, g_free); + if (!notit->clock_states) { + PERR("Failed to create hash table\n"); + goto error; + } + ret = init_clock_states(notit->clock_states, trace); + if (ret) { + PERR("Failed to initialize stream clock states\n"); + goto error; + } notit->meta.trace = bt_get(trace); notit->medium.medops = medops; notit->medium.max_request_sz = max_request_sz; @@ -1863,23 +2012,23 @@ struct bt_ctf_notif_iter *bt_ctf_notif_iter_create(struct bt_ctf_trace *trace, notit->stack = stack_new(notit); if (!notit->stack) { PERR("Failed to create stack\n"); - bt_ctf_notif_iter_destroy(notit); - notit = NULL; - goto end; + goto error; } notit->btr = bt_ctf_btr_create(cbs, notit, err_stream); if (!notit->btr) { PERR("Failed to create binary type reader\n"); - bt_ctf_notif_iter_destroy(notit); - notit = NULL; - goto end; + goto error; } bt_ctf_notif_iter_reset(notit); end: return notit; +error: + bt_ctf_notif_iter_destroy(notit); + notit = NULL; + goto end; } void bt_ctf_notif_iter_destroy(struct bt_ctf_notif_iter *notit) @@ -1898,6 +2047,9 @@ void bt_ctf_notif_iter_destroy(struct bt_ctf_notif_iter *notit) bt_ctf_btr_destroy(notit->btr); } + if (notit->clock_states) { + g_hash_table_destroy(notit->clock_states); + } g_free(notit); }