X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=plugins%2Fctf%2Fcommon%2Fnotif-iter%2Fnotif-iter.c;h=692ed6a93bae231a4089f67a81001450d03c4cfb;hb=b7726e327a09e8ceadb4e131d7d757d500ba7d62;hp=9c6134f9422317e8a77d82240ce1ef854bf0f588;hpb=e7a4393bc8bd4ac95ce121b34d932620ebc386cd;p=babeltrace.git diff --git a/plugins/ctf/common/notif-iter/notif-iter.c b/plugins/ctf/common/notif-iter/notif-iter.c index 9c6134f9..692ed6a9 100644 --- a/plugins/ctf/common/notif-iter/notif-iter.c +++ b/plugins/ctf/common/notif-iter/notif-iter.c @@ -40,6 +40,7 @@ #include #include #include +#include #include #include @@ -173,6 +174,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 @@ -496,8 +500,7 @@ enum bt_ctf_notif_iter_status read_packet_header_begin_state( packet_header_type = bt_ctf_trace_get_packet_header_type( notit->meta.trace); if (!packet_header_type) { - PERR("Failed to retrieve trace's packet header type\n"); - ret = BT_CTF_NOTIF_ITER_STATUS_ERROR; + notit->state = STATE_AFTER_TRACE_PACKET_HEADER; goto end; } @@ -533,7 +536,8 @@ bool is_variant_type(struct bt_ctf_field_type *field_type) } static inline -enum bt_ctf_notif_iter_status set_current_stream_class(struct bt_ctf_notif_iter *notit) +enum bt_ctf_notif_iter_status set_current_stream_class( + struct bt_ctf_notif_iter *notit) { enum bt_ctf_notif_iter_status status = BT_CTF_NOTIF_ITER_STATUS_OK; struct bt_ctf_field_type *packet_header_type; @@ -578,9 +582,7 @@ enum bt_ctf_notif_iter_status set_current_stream_class(struct bt_ctf_notif_iter } BT_PUT(notit->meta.stream_class); - - // TODO: get by ID - notit->meta.stream_class = bt_ctf_trace_get_stream_class( + notit->meta.stream_class = bt_ctf_trace_get_stream_class_by_id( notit->meta.trace, stream_id); if (!notit->meta.stream_class) { PERR("Cannot find stream class with ID %" PRIu64 "\n", @@ -621,8 +623,7 @@ enum bt_ctf_notif_iter_status read_packet_context_begin_state( packet_context_type = bt_ctf_stream_class_get_packet_context_type( notit->meta.stream_class); if (!packet_context_type) { - PERR("Failed to retrieve stream class's packet context\n"); - status = BT_CTF_NOTIF_ITER_STATUS_ERROR; + notit->state = STATE_AFTER_STREAM_PACKET_CONTEXT; goto end; } @@ -733,8 +734,7 @@ enum bt_ctf_notif_iter_status read_event_header_begin_state( event_header_type = bt_ctf_stream_class_get_event_header_type( notit->meta.stream_class); if (!event_header_type) { - PERR("Failed to retrieve stream class's event header type\n"); - status = BT_CTF_NOTIF_ITER_STATUS_ERROR; + notit->state = STATE_AFTER_STREAM_EVENT_HEADER; goto end; } @@ -890,12 +890,6 @@ enum bt_ctf_notif_iter_status after_event_header_state( { enum bt_ctf_notif_iter_status status; - status = set_current_packet_content_sizes(notit); - if (status != BT_CTF_NOTIF_ITER_STATUS_OK) { - PERR("Failed to set current packet and content sizes\n"); - goto end; - } - status = set_current_event_class(notit); if (status != BT_CTF_NOTIF_ITER_STATUS_OK) { PERR("Failed to set current event class\n"); @@ -918,8 +912,7 @@ enum bt_ctf_notif_iter_status read_stream_event_context_begin_state( stream_event_context_type = bt_ctf_stream_class_get_event_context_type( notit->meta.stream_class); if (!stream_event_context_type) { - PERR("Failed to retrieve stream class's event context type\n"); - status = BT_CTF_NOTIF_ITER_STATUS_ERROR; + notit->state = STATE_DSCOPE_EVENT_CONTEXT_BEGIN; goto end; } @@ -952,11 +945,9 @@ enum bt_ctf_notif_iter_status read_event_context_begin_state( event_context_type = bt_ctf_event_class_get_context_type( notit->meta.event_class); if (!event_context_type) { - PERR("Failed to retrieve event class's context type\n"); - status = BT_CTF_NOTIF_ITER_STATUS_ERROR; + notit->state = STATE_DSCOPE_EVENT_PAYLOAD_BEGIN; goto end; } - status = read_dscope_begin_state(notit, event_context_type, STATE_DSCOPE_EVENT_PAYLOAD_BEGIN, STATE_DSCOPE_EVENT_CONTEXT_CONTINUE, @@ -986,8 +977,7 @@ enum bt_ctf_notif_iter_status read_event_payload_begin_state( event_payload_type = bt_ctf_event_class_get_payload_type( notit->meta.event_class); if (!event_payload_type) { - PERR("Failed to retrieve event class's payload type\n"); - status = BT_CTF_NOTIF_ITER_STATUS_ERROR; + notit->state = STATE_EMIT_NOTIF_EVENT; goto end; } @@ -1228,6 +1218,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) @@ -1243,18 +1330,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; } @@ -1267,11 +1358,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; } @@ -1290,18 +1382,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; } @@ -1314,11 +1410,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; } @@ -1378,6 +1475,18 @@ enum bt_ctf_btr_status btr_string_begin_cb( goto end; } + /* + * Initialize string field payload to an empty string since in the + * case of a length 0 string the btr_string_cb won't be called and + * we will end up with an unset string payload. + */ + ret = bt_ctf_field_string_set_value(field, ""); + if (ret) { + PERR("Failed to initialize string field\n"); + status = BT_CTF_BTR_STATUS_ERROR; + goto end; + } + end: BT_PUT(field); @@ -1639,10 +1748,42 @@ struct bt_ctf_field_type *btr_get_variant_type_cb( end: BT_PUT(tag_field); BT_PUT(selected_field); + BT_PUT(path); return selected_field_type; } +static +int set_event_clocks(struct bt_ctf_event *event, + struct bt_ctf_notif_iter *notit) +{ + int ret; + GHashTableIter iter; + struct bt_ctf_clock *clock; + uint64_t *clock_state; + + g_hash_table_iter_init(&iter, notit->clock_states); + + while (g_hash_table_iter_next(&iter, (gpointer) &clock, + (gpointer) &clock_state)) { + struct bt_ctf_clock_value *clock_value; + + clock_value = bt_ctf_clock_value_create(clock, *clock_state); + if (!clock_value) { + ret = -1; + goto end; + } + ret = bt_ctf_event_set_clock_value(event, clock, clock_value); + bt_put(clock_value); + if (ret) { + goto end; + } + } + ret = 0; +end: + return ret; +} + static struct bt_ctf_event *create_event(struct bt_ctf_notif_iter *notit) { @@ -1680,6 +1821,11 @@ struct bt_ctf_event *create_event(struct bt_ctf_notif_iter *notit) goto error; } + ret = set_event_clocks(event, notit); + if (ret) { + goto error; + } + /* Associate with current packet. */ assert(notit->packet); ret = bt_ctf_event_set_packet(event, notit->packet); @@ -1797,33 +1943,64 @@ end: BT_PUT(event); } +//FIXME: not used ? static void notify_eos(struct bt_ctf_notif_iter *notit, struct bt_notification **notification) { - struct bt_ctf_event *event; + struct bt_ctf_stream *stream = NULL; struct bt_notification *ret = NULL; - /* Create event */ - event = create_event(notit); - if (!event) { + /* Ask the user for the stream */ + stream = notit->medium.medops.get_stream(notit->meta.stream_class, + notit->medium.data); + if (!stream) { goto end; } - ret = bt_notification_stream_end_create(event); + ret = bt_notification_stream_end_create(stream); if (!ret) { goto end; } *notification = ret; end: - BT_PUT(event); + BT_PUT(stream); +} + +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 = { @@ -1849,9 +2026,18 @@ 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->meta.trace = trace; - bt_get(notit->meta.trace); + 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; notit->medium.data = data; @@ -1859,23 +2045,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) @@ -1894,6 +2080,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); }