X-Git-Url: http://git.efficios.com/?p=babeltrace.git;a=blobdiff_plain;f=plugins%2Fctf%2Fcommon%2Fnotif-iter%2Fnotif-iter.c;h=7128e184ba3821272e1d689415b9c0c795a06843;hp=bf3f9a743f1b8030b400690ca08ce35cfc2609a6;hb=312c056ae3d374b253fa0cfe5ed576c0b0e5e569;hpb=5ae32b513f61155918c427f6ae80fd574c17af0e diff --git a/plugins/ctf/common/notif-iter/notif-iter.c b/plugins/ctf/common/notif-iter/notif-iter.c index bf3f9a74..7128e184 100644 --- a/plugins/ctf/common/notif-iter/notif-iter.c +++ b/plugins/ctf/common/notif-iter/notif-iter.c @@ -54,7 +54,7 @@ struct stack_entry { * * sequence * * variant * - * Field is owned by this. + * Field is borrowed. */ struct bt_field *base; @@ -135,27 +135,45 @@ struct bt_notif_iter { /* * Current dynamic scope field pointer. * - * This is set when a dynamic scope field is first created by - * btr_compound_begin_cb(). It points to one of the fields in - * dscopes below. + * This is set by read_dscope_begin_state() and contains the + * value of one of the pointers in `dscopes` below. */ - struct bt_field **cur_dscope_field; + struct bt_field *cur_dscope_field; /* Trace and classes (owned by this) */ struct { struct bt_trace *trace; struct bt_stream_class *stream_class; struct bt_event_class *event_class; + struct bt_clock_class_priority_map *cc_prio_map; } meta; + /* Current packet header field wrapper (NULL if not created yet) */ + struct bt_packet_header_field *packet_header_field; + + /* Current packet header field wrapper (NULL if not created yet) */ + struct bt_packet_context_field *packet_context_field; + + /* Current event header field (NULL if not created yet) */ + struct bt_event_header_field *event_header_field; + /* Current packet (NULL if not created yet) */ struct bt_packet *packet; /* Current stream (NULL if not set yet) */ struct bt_stream *stream; + /* Current event (NULL if not created yet) */ + struct bt_event *event; + + /* Current event notification (NULL if not created yet) */ + struct bt_notification *event_notif; + /* - * Current timestamp_end field (to consider before switching packets). + * Current `timestamp_end` field (to consider before switching + * packets). If it's set, it's a field which is within + * `dscopes.stream_packet_context` below, which is in `packet` + * above. */ struct bt_field *cur_timestamp_end; @@ -312,10 +330,7 @@ enum bt_btr_status btr_timestamp_end_cb(void *value, static void stack_entry_free_func(gpointer data) { - struct stack_entry *entry = data; - - bt_put(entry->base); - g_free(entry); + g_free(data); } static @@ -370,7 +385,7 @@ int stack_push(struct stack *stack, struct bt_field *base) goto end; } - entry->base = bt_get(base); + entry->base = base; g_ptr_array_add(stack->entries, entry); end: @@ -558,13 +573,12 @@ enum bt_notif_iter_status read_dscope_begin_state( struct bt_notif_iter *notit, struct bt_field_type *dscope_field_type, enum state done_state, enum state continue_state, - struct bt_field **dscope_field) + struct bt_field *dscope_field) { enum bt_notif_iter_status status = BT_NOTIF_ITER_STATUS_OK; enum bt_btr_status btr_status; size_t consumed_bits; - bt_put(*dscope_field); notit->cur_dscope_field = dscope_field; BT_LOGV("Starting BTR: notit-addr=%p, btr-addr=%p, ft-addr=%p", notit, notit->btr, dscope_field_type); @@ -654,26 +668,38 @@ end: } static -void put_event_dscopes(struct bt_notif_iter *notit) +void release_event_dscopes(struct bt_notif_iter *notit) { - BT_LOGV_STR("Putting event header field."); - BT_PUT(notit->dscopes.stream_event_header); - BT_LOGV_STR("Putting stream event context field."); - BT_PUT(notit->dscopes.stream_event_context); - BT_LOGV_STR("Putting event context field."); - BT_PUT(notit->dscopes.event_context); - BT_LOGV_STR("Putting event payload field."); - BT_PUT(notit->dscopes.event_payload); + notit->dscopes.stream_event_header = NULL; + + if (notit->event_header_field) { + bt_event_header_field_release(notit->event_header_field); + notit->event_header_field = NULL; + } + + notit->dscopes.stream_event_context = NULL; + notit->dscopes.event_context = NULL; + notit->dscopes.event_payload = NULL; } static -void put_all_dscopes(struct bt_notif_iter *notit) +void release_all_dscopes(struct bt_notif_iter *notit) { - BT_LOGV_STR("Putting packet header field."); - BT_PUT(notit->dscopes.trace_packet_header); - BT_LOGV_STR("Putting packet context field."); - BT_PUT(notit->dscopes.stream_packet_context); - put_event_dscopes(notit); + notit->dscopes.trace_packet_header = NULL; + + if (notit->packet_header_field) { + bt_packet_header_field_release(notit->packet_header_field); + notit->packet_header_field = NULL; + } + + notit->dscopes.stream_packet_context = NULL; + + if (notit->packet_context_field) { + bt_packet_context_field_release(notit->packet_context_field); + notit->packet_context_field = NULL; + } + + release_event_dscopes(notit); } static @@ -690,13 +716,35 @@ enum bt_notif_iter_status read_packet_header_begin_state( } /* Packet header type is common to the whole trace. */ - packet_header_type = bt_trace_get_packet_header_field_type( + packet_header_type = bt_trace_borrow_packet_header_field_type( notit->meta.trace); if (!packet_header_type) { notit->state = STATE_AFTER_TRACE_PACKET_HEADER; goto end; } + /* + * Create free packet header field from trace. This field is + * going to be moved to the packet once we create it. We cannot + * create the packet now because: + * + * 1. A packet is created from a stream. + * 2. A stream is created from a stream class. + * 3. We need the packet header field's content to know the ID + * of the stream class to select. + */ + BT_ASSERT(!notit->packet_header_field); + notit->packet_header_field = bt_trace_create_packet_header_field( + notit->meta.trace); + if (!notit->packet_header_field) { + BT_LOGE_STR("Cannot create packet header field wrapper from trace."); + ret = BT_NOTIF_ITER_STATUS_ERROR; + goto end; + } + + notit->dscopes.trace_packet_header = + bt_packet_header_field_borrow_field(notit->packet_header_field); + BT_ASSERT(notit->dscopes.trace_packet_header); BT_LOGV("Decoding packet header field:" "notit-addr=%p, trace-addr=%p, trace-name=\"%s\", ft-addr=%p", notit, notit->meta.trace, @@ -704,7 +752,7 @@ enum bt_notif_iter_status read_packet_header_begin_state( ret = read_dscope_begin_state(notit, packet_header_type, STATE_AFTER_TRACE_PACKET_HEADER, STATE_DSCOPE_TRACE_PACKET_HEADER_CONTINUE, - ¬it->dscopes.trace_packet_header); + notit->dscopes.trace_packet_header); if (ret < 0) { BT_LOGW("Cannot decode packet header field: " "notit-addr=%p, trace-addr=%p, " @@ -713,8 +761,8 @@ enum bt_notif_iter_status read_packet_header_begin_state( bt_trace_get_name(notit->meta.trace), packet_header_type); } + end: - BT_PUT(packet_header_type); return ret; } @@ -726,20 +774,6 @@ enum bt_notif_iter_status read_packet_header_continue_state( STATE_AFTER_TRACE_PACKET_HEADER); } -static inline -bool is_struct_type(struct bt_field_type *field_type) -{ - return bt_field_type_get_type_id(field_type) == - BT_FIELD_TYPE_ID_STRUCT; -} - -static inline -bool is_variant_type(struct bt_field_type *field_type) -{ - return bt_field_type_get_type_id(field_type) == - BT_FIELD_TYPE_ID_VARIANT; -} - static struct stream_class_field_path_cache * create_stream_class_field_path_cache_entry( @@ -760,7 +794,8 @@ create_stream_class_field_path_cache_entry( goto end; } - event_header = bt_stream_class_get_event_header_field_type(stream_class); + event_header = bt_stream_class_borrow_event_header_field_type( + stream_class); if (event_header && bt_field_type_is_structure(event_header)) { int i, count; @@ -772,7 +807,7 @@ create_stream_class_field_path_cache_entry( int ret; const char *name; - ret = bt_field_type_structure_get_field_by_index( + ret = bt_field_type_structure_borrow_field_by_index( event_header, &name, NULL, i); if (ret) { BT_LOGE("Cannot get event header structure field type's field: " @@ -799,7 +834,7 @@ create_stream_class_field_path_cache_entry( } } - packet_context = bt_stream_class_get_packet_context_field_type( + packet_context = bt_stream_class_borrow_packet_context_field_type( stream_class); if (packet_context && bt_field_type_is_structure(packet_context)) { int i, count; @@ -818,7 +853,7 @@ create_stream_class_field_path_cache_entry( break; } - ret = bt_field_type_structure_get_field_by_index( + ret = bt_field_type_structure_borrow_field_by_index( packet_context, &name, &field_type, i); if (ret) { BT_LOGE("Cannot get packet context structure field type's field: " @@ -839,14 +874,13 @@ create_stream_class_field_path_cache_entry( struct field_cb_override, 1); if (!override) { - BT_PUT(field_type); goto error; } override->func = btr_timestamp_end_cb; override->data = notit; g_hash_table_insert(notit->field_overrides, - bt_get(field_type), override); + field_type, override); timestamp_end = i; } else if (packet_size == -1 && !strcmp(name, "packet_size")) { @@ -855,7 +889,6 @@ create_stream_class_field_path_cache_entry( !strcmp(name, "content_size")) { content_size = i; } - BT_PUT(field_type); } } @@ -864,10 +897,10 @@ create_stream_class_field_path_cache_entry( cache_entry->timestamp_end = timestamp_end; cache_entry->packet_size = packet_size; cache_entry->content_size = content_size; + end: - BT_PUT(event_header); - BT_PUT(packet_context); return cache_entry; + error: g_free(cache_entry); cache_entry = NULL; @@ -889,7 +922,7 @@ struct stream_class_field_path_cache *get_stream_class_field_path_cache( cache_entry = create_stream_class_field_path_cache_entry(notit, stream_class); g_hash_table_insert(notit->sc_field_path_caches, - bt_get(stream_class), (gpointer) cache_entry); + stream_class, (gpointer) cache_entry); } return cache_entry; @@ -909,7 +942,7 @@ enum bt_notif_iter_status set_current_stream_class( notit->cur_sc_field_path_cache = NULL; /* Is there any "stream_id" field in the packet header? */ - packet_header_type = bt_trace_get_packet_header_field_type( + packet_header_type = bt_trace_borrow_packet_header_field_type( notit->meta.trace); if (!packet_header_type) { /* @@ -919,11 +952,11 @@ enum bt_notif_iter_status set_current_stream_class( goto single_stream_class; } - BT_ASSERT(is_struct_type(packet_header_type)); + BT_ASSERT(bt_field_type_is_structure(packet_header_type)); // TODO: optimalize! stream_id_field_type = - bt_field_type_structure_get_field_type_by_name( + bt_field_type_structure_borrow_field_type_by_name( packet_header_type, "stream_id"); if (stream_id_field_type) { /* Find appropriate stream class using current stream ID */ @@ -933,13 +966,12 @@ enum bt_notif_iter_status set_current_stream_class( BT_ASSERT(notit->dscopes.trace_packet_header); // TODO: optimalize! - stream_id_field = bt_field_structure_get_field_by_name( + stream_id_field = bt_field_structure_borrow_field_by_name( notit->dscopes.trace_packet_header, "stream_id"); BT_ASSERT(stream_id_field); ret = bt_field_integer_unsigned_get_value( stream_id_field, &stream_id); BT_ASSERT(!ret); - BT_PUT(stream_id_field); } else { single_stream_class: /* Only one stream: pick the first stream class */ @@ -954,7 +986,7 @@ single_stream_class: notit, stream_id, notit->meta.trace, bt_trace_get_name(notit->meta.trace)); - new_stream_class = bt_trace_get_stream_class_by_id( + new_stream_class = bt_trace_borrow_stream_class_by_id( notit->meta.trace, stream_id); if (!new_stream_class) { BT_LOGW("No stream class with ID of stream class ID to use in trace: " @@ -988,7 +1020,7 @@ single_stream_class: goto end; } } else { - BT_MOVE(notit->meta.stream_class, new_stream_class); + notit->meta.stream_class = new_stream_class; } BT_LOGV("Set current stream class: " @@ -1014,10 +1046,114 @@ single_stream_class: status = BT_NOTIF_ITER_STATUS_ERROR; goto end; } + +end: + return status; +} + +static inline +uint64_t get_cur_stream_instance_id(struct bt_notif_iter *notit) +{ + struct bt_field *stream_instance_id_field = NULL; + uint64_t stream_instance_id = -1ULL; + int ret; + + if (!notit->dscopes.trace_packet_header) { + goto end; + } + + stream_instance_id_field = bt_field_structure_borrow_field_by_name( + notit->dscopes.trace_packet_header, "stream_instance_id"); + if (!stream_instance_id_field) { + goto end; + } + + ret = bt_field_integer_unsigned_get_value(stream_instance_id_field, + &stream_instance_id); + if (ret) { + stream_instance_id = -1ULL; + goto end; + } + +end: + return stream_instance_id; +} + +static inline +enum bt_notif_iter_status set_current_stream(struct bt_notif_iter *notit) +{ + enum bt_notif_iter_status status = BT_NOTIF_ITER_STATUS_OK; + struct bt_stream *stream = NULL; + + BT_LOGV("Calling user function (get stream): notit-addr=%p, " + "stream-class-addr=%p, stream-class-name=\"%s\", " + "stream-class-id=%" PRId64, + notit, notit->meta.stream_class, + bt_stream_class_get_name(notit->meta.stream_class), + bt_stream_class_get_id(notit->meta.stream_class)); + stream = bt_get(notit->medium.medops.borrow_stream( + notit->meta.stream_class, get_cur_stream_instance_id(notit), + notit->medium.data)); + BT_LOGV("User function returned: stream-addr=%p", stream); + if (!stream) { + BT_LOGW_STR("User function failed to return a stream object for the given stream class."); + status = BT_NOTIF_ITER_STATUS_ERROR; + goto end; + } + + if (notit->stream && stream != notit->stream) { + BT_LOGW("User function returned a different stream than the previous one for the same sequence of packets."); + status = BT_NOTIF_ITER_STATUS_ERROR; + goto end; + } + + BT_MOVE(notit->stream, stream); + +end: + bt_put(stream); + return status; +} + +static inline +enum bt_notif_iter_status set_current_packet(struct bt_notif_iter *notit) +{ + enum bt_notif_iter_status status = BT_NOTIF_ITER_STATUS_OK; + struct bt_packet *packet = NULL; + + BT_LOGV("Creating packet for packet notification: " + "notit-addr=%p", notit); + BT_LOGV("Creating packet from stream: " + "notit-addr=%p, stream-addr=%p, " + "stream-class-addr=%p, " + "stream-class-name=\"%s\", " + "stream-class-id=%" PRId64, + notit, notit->stream, notit->meta.stream_class, + bt_stream_class_get_name(notit->meta.stream_class), + bt_stream_class_get_id(notit->meta.stream_class)); + + /* Create packet */ + BT_ASSERT(notit->stream); + packet = bt_packet_create(notit->stream); + if (!packet) { + BT_LOGE("Cannot create packet from stream: " + "notit-addr=%p, stream-addr=%p, " + "stream-class-addr=%p, " + "stream-class-name=\"%s\", " + "stream-class-id=%" PRId64, + notit, notit->stream, notit->meta.stream_class, + bt_stream_class_get_name(notit->meta.stream_class), + bt_stream_class_get_id(notit->meta.stream_class)); + goto error; + } + + goto end; + +error: + BT_PUT(packet); + status = BT_NOTIF_ITER_STATUS_ERROR; + end: - BT_PUT(packet_header_type); - BT_PUT(stream_id_field_type); - bt_put(new_stream_class); + BT_MOVE(notit->packet, packet); return status; } @@ -1028,10 +1164,13 @@ enum bt_notif_iter_status after_packet_header_state( enum bt_notif_iter_status status; status = set_current_stream_class(notit); - if (status == BT_NOTIF_ITER_STATUS_OK) { - notit->state = STATE_DSCOPE_STREAM_PACKET_CONTEXT_BEGIN; + if (status != BT_NOTIF_ITER_STATUS_OK) { + goto end; } + notit->state = STATE_DSCOPE_STREAM_PACKET_CONTEXT_BEGIN; + +end: return status; } @@ -1043,7 +1182,7 @@ enum bt_notif_iter_status read_packet_context_begin_state( struct bt_field_type *packet_context_type; BT_ASSERT(notit->meta.stream_class); - packet_context_type = bt_stream_class_get_packet_context_field_type( + packet_context_type = bt_stream_class_borrow_packet_context_field_type( notit->meta.stream_class); if (!packet_context_type) { BT_LOGV("No packet packet context field type in stream class: continuing: " @@ -1056,6 +1195,27 @@ enum bt_notif_iter_status read_packet_context_begin_state( goto end; } + /* + * Create free packet context field from stream class. This + * field is going to be moved to the packet once we create it. + * We cannot create the packet now because a packet is created + * from a stream, and this API must be able to return the packet + * header and context fields without creating a stream + * (bt_notif_iter_get_packet_header_context_fields()). + */ + BT_ASSERT(!notit->packet_context_field); + notit->packet_context_field = + bt_stream_class_create_packet_context_field( + notit->meta.stream_class); + if (!notit->packet_context_field) { + BT_LOGE_STR("Cannot create packet context field wrapper from stream class."); + status = BT_NOTIF_ITER_STATUS_ERROR; + goto end; + } + + notit->dscopes.stream_packet_context = + bt_packet_context_field_borrow_field(notit->packet_context_field); + BT_ASSERT(notit->dscopes.stream_packet_context); BT_LOGV("Decoding packet context field: " "notit-addr=%p, stream-class-addr=%p, " "stream-class-name=\"%s\", stream-class-id=%" PRId64 ", " @@ -1067,7 +1227,7 @@ enum bt_notif_iter_status read_packet_context_begin_state( status = read_dscope_begin_state(notit, packet_context_type, STATE_AFTER_STREAM_PACKET_CONTEXT, STATE_DSCOPE_STREAM_PACKET_CONTEXT_CONTINUE, - ¬it->dscopes.stream_packet_context); + notit->dscopes.stream_packet_context); if (status < 0) { BT_LOGW("Cannot decode packet context field: " "notit-addr=%p, stream-class-addr=%p, " @@ -1080,7 +1240,6 @@ enum bt_notif_iter_status read_packet_context_begin_state( } end: - BT_PUT(packet_context_type); return status; } @@ -1105,9 +1264,9 @@ enum bt_notif_iter_status set_current_packet_content_sizes( goto end; } - packet_size_field = bt_field_structure_get_field_by_name( + packet_size_field = bt_field_structure_borrow_field_by_name( notit->dscopes.stream_packet_context, "packet_size"); - content_size_field = bt_field_structure_get_field_by_name( + content_size_field = bt_field_structure_borrow_field_by_name( notit->dscopes.stream_packet_context, "content_size"); if (packet_size_field) { int ret = bt_field_integer_unsigned_get_value( @@ -1165,8 +1324,6 @@ enum bt_notif_iter_status set_current_packet_content_sizes( "notit-addr=%p, packet-size=%" PRIu64 ", content-size=%" PRIu64, notit, packet_size, content_size); end: - BT_PUT(packet_size_field); - BT_PUT(content_size_field); return status; } @@ -1217,14 +1374,27 @@ enum bt_notif_iter_status read_event_header_begin_state( } } - event_header_type = bt_stream_class_get_event_header_field_type( + release_event_dscopes(notit); + BT_ASSERT(notit->meta.stream_class); + event_header_type = bt_stream_class_borrow_event_header_field_type( notit->meta.stream_class); if (!event_header_type) { notit->state = STATE_AFTER_STREAM_EVENT_HEADER; goto end; } - put_event_dscopes(notit); + BT_ASSERT(!notit->event_header_field); + notit->event_header_field = bt_stream_class_create_event_header_field( + notit->meta.stream_class); + if (!notit->event_header_field) { + BT_LOGE_STR("Cannot create event header field wrapper from trace."); + status = BT_NOTIF_ITER_STATUS_ERROR; + goto end; + } + + notit->dscopes.stream_event_header = + bt_event_header_field_borrow_field(notit->event_header_field); + BT_ASSERT(notit->dscopes.stream_event_header); BT_LOGV("Decoding event header field: " "notit-addr=%p, stream-class-addr=%p, " "stream-class-name=\"%s\", stream-class-id=%" PRId64 ", " @@ -1236,7 +1406,7 @@ enum bt_notif_iter_status read_event_header_begin_state( status = read_dscope_begin_state(notit, event_header_type, STATE_AFTER_STREAM_EVENT_HEADER, STATE_DSCOPE_STREAM_EVENT_HEADER_CONTINUE, - ¬it->dscopes.stream_event_header); + notit->dscopes.stream_event_header); if (status < 0) { BT_LOGW("Cannot decode event header field: " "notit-addr=%p, stream-class-addr=%p, " @@ -1247,9 +1417,8 @@ enum bt_notif_iter_status read_event_header_begin_state( bt_stream_class_get_id(notit->meta.stream_class), event_header_type); } -end: - BT_PUT(event_header_type); +end: return status; } @@ -1277,7 +1446,7 @@ enum bt_notif_iter_status set_current_event_class(struct bt_notif_iter *notit) uint64_t event_id = -1ULL; int ret; - event_header_type = bt_stream_class_get_event_header_field_type( + event_header_type = bt_stream_class_borrow_event_header_field_type( notit->meta.stream_class); if (!event_header_type) { /* @@ -1288,10 +1457,10 @@ enum bt_notif_iter_status set_current_event_class(struct bt_notif_iter *notit) } /* Is there any "id"/"v" field in the event header? */ - BT_ASSERT(is_struct_type(event_header_type)); - id_field_type = bt_field_type_structure_get_field_type_by_name( + BT_ASSERT(bt_field_type_is_structure(event_header_type)); + id_field_type = bt_field_type_structure_borrow_field_type_by_name( event_header_type, "id"); - v_field_type = bt_field_type_structure_get_field_type_by_name( + v_field_type = bt_field_type_structure_borrow_field_type_by_name( event_header_type, "v"); BT_ASSERT(notit->dscopes.stream_event_header); if (v_field_type) { @@ -1308,19 +1477,19 @@ enum bt_notif_iter_status set_current_event_class(struct bt_notif_iter *notit) struct bt_field *v_struct_id_field = NULL; // TODO: optimalize! - v_field = bt_field_structure_get_field_by_name( + v_field = bt_field_structure_borrow_field_by_name( notit->dscopes.stream_event_header, "v"); BT_ASSERT(v_field); v_struct_field = - bt_field_variant_get_current_field(v_field); + bt_field_variant_borrow_current_field(v_field); if (!v_struct_field) { goto end_v_field_type; } // TODO: optimalize! - v_struct_id_field = - bt_field_structure_get_field_by_name(v_struct_field, "id"); + v_struct_id_field = bt_field_structure_borrow_field_by_name( + v_struct_field, "id"); if (!v_struct_id_field) { goto end_v_field_type; } @@ -1335,41 +1504,24 @@ enum bt_notif_iter_status set_current_event_class(struct bt_notif_iter *notit) event_id = -1ULL; } } - -end_v_field_type: - BT_PUT(v_field); - BT_PUT(v_struct_field); - BT_PUT(v_struct_id_field); } +end_v_field_type: if (id_field_type && event_id == -1ULL) { /* Check "id" field */ struct bt_field *id_field = NULL; int ret_get_value = 0; // TODO: optimalize! - id_field = bt_field_structure_get_field_by_name( + id_field = bt_field_structure_borrow_field_by_name( notit->dscopes.stream_event_header, "id"); if (!id_field) { goto check_event_id; } - if (bt_field_is_integer(id_field)) { - ret_get_value = bt_field_integer_unsigned_get_value( - id_field, &event_id); - } else if (bt_field_is_enumeration(id_field)) { - struct bt_field *container; - - container = bt_field_enumeration_get_container( - id_field); - BT_ASSERT(container); - ret_get_value = bt_field_integer_unsigned_get_value( - container, &event_id); - BT_PUT(container); - } - + ret_get_value = bt_field_integer_unsigned_get_value( + id_field, &event_id); BT_ASSERT(ret_get_value == 0); - BT_PUT(id_field); } check_event_id: @@ -1389,8 +1541,7 @@ single_event_class: bt_stream_class_get_name(notit->meta.stream_class), bt_stream_class_get_id(notit->meta.stream_class), event_id); - BT_PUT(notit->meta.event_class); - notit->meta.event_class = bt_stream_class_get_event_class_by_id( + notit->meta.event_class = bt_stream_class_borrow_event_class_by_id( notit->meta.stream_class, event_id); if (!notit->meta.event_class) { BT_LOGW("No event class with ID of event class ID to use in stream class: " @@ -1414,10 +1565,43 @@ single_event_class: bt_event_class_get_id(notit->meta.event_class)); end: - BT_PUT(event_header_type); - BT_PUT(id_field_type); - BT_PUT(v_field_type); + return status; +} + +static inline +enum bt_notif_iter_status set_current_event_notification( + struct bt_notif_iter *notit) +{ + enum bt_notif_iter_status status = BT_NOTIF_ITER_STATUS_OK; + struct bt_notification *notif = NULL; + + BT_ASSERT(notit->meta.event_class); + BT_ASSERT(notit->packet); + BT_LOGV("Creating event notification from event class and packet: " + "notit-addr=%p, ec-addr=%p, ec-name=\"%s\", packet-addr=%p", + notit, notit->meta.event_class, + bt_event_class_get_name(notit->meta.event_class), + notit->packet); + notif = bt_notification_event_create(notit->meta.event_class, + notit->packet, notit->meta.cc_prio_map); + if (!notif) { + BT_LOGE("Cannot create event notification: " + "notit-addr=%p, ec-addr=%p, ec-name=\"%s\", " + "packet-addr=%p", + notit, notit->meta.event_class, + bt_event_class_get_name(notit->meta.event_class), + notit->packet); + goto error; + } + + goto end; + +error: + BT_PUT(notif); + status = BT_NOTIF_ITER_STATUS_ERROR; +end: + BT_MOVE(notit->event_notif, notif); return status; } @@ -1432,6 +1616,37 @@ enum bt_notif_iter_status after_event_header_state( goto end; } + status = set_current_event_notification(notit); + if (status != BT_NOTIF_ITER_STATUS_OK) { + goto end; + } + + notit->event = bt_notification_event_borrow_event(notit->event_notif); + BT_ASSERT(notit->event); + + if (notit->event_header_field) { + int ret; + + BT_ASSERT(notit->event); + ret = bt_event_move_header(notit->event, + notit->event_header_field); + + if (ret) { + status = BT_NOTIF_ITER_STATUS_ERROR; + goto end; + } + + notit->event_header_field = NULL; + + /* + * At this point notit->dscopes.stream_event_header has + * the same value as the event header field within + * notit->event. + */ + BT_ASSERT(bt_event_borrow_header(notit->event) == + notit->dscopes.stream_event_header); + } + notit->state = STATE_DSCOPE_STREAM_EVENT_CONTEXT_BEGIN; end: @@ -1446,13 +1661,17 @@ enum bt_notif_iter_status read_stream_event_context_begin_state( struct bt_field_type *stream_event_context_type; stream_event_context_type = - bt_stream_class_get_event_context_field_type( + bt_stream_class_borrow_event_context_field_type( notit->meta.stream_class); if (!stream_event_context_type) { notit->state = STATE_DSCOPE_EVENT_CONTEXT_BEGIN; goto end; } + BT_ASSERT(!notit->dscopes.stream_event_context); + notit->dscopes.stream_event_context = + bt_event_borrow_stream_event_context(notit->event); + BT_ASSERT(notit->dscopes.stream_event_context); BT_LOGV("Decoding stream event context field: " "notit-addr=%p, stream-class-addr=%p, " "stream-class-name=\"%s\", stream-class-id=%" PRId64 ", " @@ -1464,7 +1683,7 @@ enum bt_notif_iter_status read_stream_event_context_begin_state( status = read_dscope_begin_state(notit, stream_event_context_type, STATE_DSCOPE_EVENT_CONTEXT_BEGIN, STATE_DSCOPE_STREAM_EVENT_CONTEXT_CONTINUE, - ¬it->dscopes.stream_event_context); + notit->dscopes.stream_event_context); if (status < 0) { BT_LOGW("Cannot decode stream event context field: " "notit-addr=%p, stream-class-addr=%p, " @@ -1477,8 +1696,6 @@ enum bt_notif_iter_status read_stream_event_context_begin_state( } end: - BT_PUT(stream_event_context_type); - return status; } @@ -1497,13 +1714,16 @@ enum bt_notif_iter_status read_event_context_begin_state( enum bt_notif_iter_status status = BT_NOTIF_ITER_STATUS_OK; struct bt_field_type *event_context_type; - event_context_type = bt_event_class_get_context_field_type( + event_context_type = bt_event_class_borrow_context_field_type( notit->meta.event_class); if (!event_context_type) { notit->state = STATE_DSCOPE_EVENT_PAYLOAD_BEGIN; goto end; } + BT_ASSERT(!notit->dscopes.event_context); + notit->dscopes.event_context = bt_event_borrow_context(notit->event); + BT_ASSERT(notit->dscopes.event_context); BT_LOGV("Decoding event context field: " "notit-addr=%p, event-class-addr=%p, " "event-class-name=\"%s\", event-class-id=%" PRId64 ", " @@ -1515,7 +1735,7 @@ enum bt_notif_iter_status read_event_context_begin_state( status = read_dscope_begin_state(notit, event_context_type, STATE_DSCOPE_EVENT_PAYLOAD_BEGIN, STATE_DSCOPE_EVENT_CONTEXT_CONTINUE, - ¬it->dscopes.event_context); + notit->dscopes.event_context); if (status < 0) { BT_LOGW("Cannot decode event context field: " "notit-addr=%p, event-class-addr=%p, " @@ -1528,8 +1748,6 @@ enum bt_notif_iter_status read_event_context_begin_state( } end: - BT_PUT(event_context_type); - return status; } @@ -1548,13 +1766,16 @@ enum bt_notif_iter_status read_event_payload_begin_state( enum bt_notif_iter_status status = BT_NOTIF_ITER_STATUS_OK; struct bt_field_type *event_payload_type; - event_payload_type = bt_event_class_get_payload_field_type( + event_payload_type = bt_event_class_borrow_payload_field_type( notit->meta.event_class); if (!event_payload_type) { notit->state = STATE_EMIT_NOTIF_EVENT; goto end; } + BT_ASSERT(!notit->dscopes.event_payload); + notit->dscopes.event_payload = bt_event_borrow_payload(notit->event); + BT_ASSERT(notit->dscopes.event_payload); BT_LOGV("Decoding event payload field: " "notit-addr=%p, event-class-addr=%p, " "event-class-name=\"%s\", event-class-id=%" PRId64 ", " @@ -1566,7 +1787,7 @@ enum bt_notif_iter_status read_event_payload_begin_state( status = read_dscope_begin_state(notit, event_payload_type, STATE_EMIT_NOTIF_EVENT, STATE_DSCOPE_EVENT_PAYLOAD_CONTINUE, - ¬it->dscopes.event_payload); + notit->dscopes.event_payload); if (status < 0) { BT_LOGW("Cannot decode event payload field: " "notit-addr=%p, event-class-addr=%p, " @@ -1579,8 +1800,6 @@ enum bt_notif_iter_status read_event_payload_begin_state( } end: - BT_PUT(event_payload_type); - return status; } @@ -1724,11 +1943,29 @@ void bt_notif_iter_reset(struct bt_notif_iter *notit) BT_ASSERT(notit); BT_LOGD("Resetting notification iterator: addr=%p", notit); stack_clear(notit->stack); - BT_PUT(notit->meta.stream_class); - BT_PUT(notit->meta.event_class); + notit->meta.stream_class = NULL; + notit->meta.event_class = NULL; BT_PUT(notit->packet); BT_PUT(notit->stream); - put_all_dscopes(notit); + BT_PUT(notit->event_notif); + release_all_dscopes(notit); + notit->cur_dscope_field = NULL; + + if (notit->packet_header_field) { + bt_packet_header_field_release(notit->packet_header_field); + notit->packet_header_field = NULL; + } + + if (notit->packet_context_field) { + bt_packet_context_field_release(notit->packet_context_field); + notit->packet_context_field = NULL; + } + + if (notit->event_header_field) { + bt_event_header_field_release(notit->event_header_field); + notit->event_header_field = NULL; + } + notit->buf.addr = NULL; notit->buf.sz = 0; notit->buf.at = 0; @@ -1739,6 +1976,7 @@ void bt_notif_iter_reset(struct bt_notif_iter *notit) notit->cur_packet_size = -1; notit->cur_packet_offset = -1; notit->stream_begin_emitted = false; + notit->cur_timestamp_end = NULL; } static @@ -1752,17 +1990,21 @@ int bt_notif_iter_switch_packet(struct bt_notif_iter *notit) * iterator refer to the same stream class (the first one). */ BT_ASSERT(notit); + if (notit->cur_packet_size != -1) { notit->cur_packet_offset += notit->cur_packet_size; } + BT_LOGV("Switching packet: notit-addr=%p, cur=%zu, " "packet-offset=%" PRId64, notit, notit->buf.at, notit->cur_packet_offset); stack_clear(notit->stack); - BT_PUT(notit->meta.event_class); + notit->meta.event_class = NULL; BT_PUT(notit->packet); - BT_PUT(notit->cur_timestamp_end); - put_all_dscopes(notit); + BT_PUT(notit->event_notif); + notit->cur_timestamp_end = NULL; + release_all_dscopes(notit); + notit->cur_dscope_field = NULL; /* * Adjust current buffer so that addr points to the beginning of the new @@ -1796,7 +2038,7 @@ end: } static -struct bt_field *get_next_field(struct bt_notif_iter *notit) +struct bt_field *borrow_next_field(struct bt_notif_iter *notit) { struct bt_field *next_field = NULL; struct bt_field *base_field; @@ -1807,27 +2049,24 @@ struct bt_field *get_next_field(struct bt_notif_iter *notit) index = stack_top(notit->stack)->index; base_field = stack_top(notit->stack)->base; BT_ASSERT(base_field); - base_type = bt_field_get_type(base_field); + base_type = bt_field_borrow_type(base_field); BT_ASSERT(base_type); switch (bt_field_type_get_type_id(base_type)) { case BT_FIELD_TYPE_ID_STRUCT: { - next_field = bt_field_structure_get_field_by_index( + next_field = bt_field_structure_borrow_field_by_index( base_field, index); - const char *name; - bt_field_type_structure_get_field_by_index(base_type, - &name, NULL, index); break; } case BT_FIELD_TYPE_ID_ARRAY: - next_field = bt_field_array_get_field(base_field, index); + next_field = bt_field_array_borrow_field(base_field, index); break; case BT_FIELD_TYPE_ID_SEQUENCE: - next_field = bt_field_sequence_get_field(base_field, index); + next_field = bt_field_sequence_borrow_field(base_field, index); break; case BT_FIELD_TYPE_ID_VARIANT: - next_field = bt_field_variant_get_current_field(base_field); + next_field = bt_field_variant_borrow_current_field(base_field); break; default: BT_LOGF("Unknown base field type ID: " @@ -1838,22 +2077,19 @@ struct bt_field *get_next_field(struct bt_notif_iter *notit) abort(); } - BT_PUT(base_type); return next_field; } static -void update_clock_state(uint64_t *state, - struct bt_field *value_field) +void update_clock_state(uint64_t *state, struct bt_field *value_field, + struct bt_field_type *value_type) { - struct bt_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_field_get_type(value_field); BT_ASSERT(value_type); BT_ASSERT(bt_field_type_is_integer(value_type)); requested_new_value_size = @@ -1890,10 +2126,10 @@ void update_clock_state(uint64_t *state, /* Set the low bits of the current clock value. */ *state |= requested_new_value; + end: BT_LOGV("Updated clock's value from integer field's value: " "value=%" PRIu64, *state); - bt_put(value_type); } static @@ -1906,9 +2142,16 @@ enum bt_btr_status update_clock(struct bt_notif_iter *notit, enum bt_btr_status ret = BT_BTR_STATUS_OK; struct bt_clock_class *clock_class = NULL; - int_field_type = bt_field_get_type(int_field); + int_field_type = bt_field_borrow_type(int_field); BT_ASSERT(int_field_type); - clock_class = bt_field_type_integer_get_mapped_clock_class( + + if (bt_field_type_is_enumeration(int_field_type)) { + int_field_type = + bt_field_type_enumeration_borrow_container_field_type( + int_field_type); + } + + clock_class = bt_field_type_integer_borrow_mapped_clock_class( int_field_type); if (likely(!clock_class)) { goto end; @@ -1924,7 +2167,7 @@ enum bt_btr_status update_clock(struct bt_notif_iter *notit, goto end; } - g_hash_table_insert(notit->clock_states, bt_get(clock_class), + g_hash_table_insert(notit->clock_states, clock_class, clock_state); } @@ -1934,21 +2177,19 @@ enum bt_btr_status update_clock(struct bt_notif_iter *notit, "clock-class-name=\"%s\", value=%" PRIu64, notit, clock_class, bt_clock_class_get_name(clock_class), *clock_state); - update_clock_state(clock_state, int_field); + update_clock_state(clock_state, int_field, int_field_type); + end: - bt_put(int_field_type); - bt_put(clock_class); return ret; } static enum bt_btr_status btr_unsigned_int_common(uint64_t value, struct bt_field_type *type, void *data, - struct bt_field **out_int_field) + struct bt_field **out_field) { enum bt_btr_status status = BT_BTR_STATUS_OK; struct bt_field *field = NULL; - struct bt_field *int_field = NULL; struct bt_notif_iter *notit = data; int ret; @@ -1959,45 +2200,20 @@ enum bt_btr_status btr_unsigned_int_common(uint64_t value, bt_common_field_type_id_string( bt_field_type_get_type_id(type)), value); - - /* Create next field */ - field = get_next_field(notit); + field = borrow_next_field(notit); if (!field) { - BT_LOGW("Cannot get next field: notit-addr=%p", notit); + BT_LOGW("Cannot borrow next field: notit-addr=%p", notit); status = BT_BTR_STATUS_ERROR; - goto end_no_put; - } - - switch(bt_field_type_get_type_id(type)) { - case BT_FIELD_TYPE_ID_INTEGER: - /* Integer field is created field */ - BT_MOVE(int_field, field); - bt_get(type); - break; - case BT_FIELD_TYPE_ID_ENUM: - int_field = bt_field_enumeration_get_container(field); - BT_ASSERT(int_field); - type = bt_field_get_type(int_field); - BT_ASSERT(type); - break; - default: - BT_LOGF("Unexpected field type ID: " - "notit-addr=%p, ft-addr=%p, ft-id=%s", - notit, type, - bt_common_field_type_id_string( - bt_field_type_get_type_id(type))); - abort(); + goto end; } - BT_ASSERT(int_field); - ret = bt_field_integer_unsigned_set_value(int_field, value); + BT_ASSERT(bt_field_is_integer(field) || bt_field_is_enumeration(field)); + ret = bt_field_integer_unsigned_set_value(field, value); BT_ASSERT(ret == 0); stack_top(notit->stack)->index++; - *out_int_field = int_field; - BT_PUT(field); - BT_PUT(type); + *out_field = field; -end_no_put: +end: return status; } @@ -2008,6 +2224,7 @@ enum bt_btr_status btr_timestamp_end_cb(void *value, enum bt_btr_status status; struct bt_field *field = NULL; struct bt_notif_iter *notit = data; + uint64_t uvalue = *((uint64_t *) value); BT_LOGV("`timestamp_end` unsigned integer function called from BTR: " "notit-addr=%p, btr-addr=%p, ft-addr=%p, " @@ -2015,11 +2232,11 @@ enum bt_btr_status btr_timestamp_end_cb(void *value, notit, notit->btr, type, bt_common_field_type_id_string( bt_field_type_get_type_id(type))); - status = btr_unsigned_int_common(*((uint64_t *) value), type, data, - &field); - /* Set as the current packet's timestamp_end field. */ - BT_MOVE(notit->cur_timestamp_end, field); + status = btr_unsigned_int_common(uvalue, type, data, &field); + + /* Set as the current packet's end timestamp field */ + notit->cur_timestamp_end = field; return status; } @@ -2053,7 +2270,7 @@ enum bt_btr_status btr_unsigned_int_cb(uint64_t value, } status = update_clock(notit, field); - BT_PUT(field); + end: return status; } @@ -2064,7 +2281,6 @@ enum bt_btr_status btr_signed_int_cb(int64_t value, { enum bt_btr_status status = BT_BTR_STATUS_OK; struct bt_field *field = NULL; - struct bt_field *int_field = NULL; struct bt_notif_iter *notit = data; int ret; @@ -2075,46 +2291,19 @@ enum bt_btr_status btr_signed_int_cb(int64_t value, bt_common_field_type_id_string( bt_field_type_get_type_id(type)), value); - - /* create next field */ - field = get_next_field(notit); + field = borrow_next_field(notit); if (!field) { - BT_LOGW("Cannot get next field: notit-addr=%p", notit); + BT_LOGW("Cannot borrow next field: notit-addr=%p", notit); status = BT_BTR_STATUS_ERROR; - goto end_no_put; - } - - switch(bt_field_type_get_type_id(type)) { - case BT_FIELD_TYPE_ID_INTEGER: - /* Integer field is created field */ - BT_MOVE(int_field, field); - bt_get(type); - break; - case BT_FIELD_TYPE_ID_ENUM: - int_field = bt_field_enumeration_get_container(field); - BT_ASSERT(int_field); - type = bt_field_get_type(int_field); - BT_ASSERT(type); - break; - default: - BT_LOGF("Unexpected field type ID: " - "notit-addr=%p, ft-addr=%p, ft-id=%s", - notit, type, - bt_common_field_type_id_string( - bt_field_type_get_type_id(type))); - abort(); + goto end; } - BT_ASSERT(int_field); - ret = bt_field_integer_signed_set_value(int_field, value); - BT_ASSERT(!ret); + BT_ASSERT(bt_field_is_integer(field) || bt_field_is_enumeration(field)); + ret = bt_field_integer_signed_set_value(field, value); + BT_ASSERT(ret == 0); stack_top(notit->stack)->index++; - status = update_clock(notit, int_field); - BT_PUT(field); - BT_PUT(int_field); - BT_PUT(type); -end_no_put: +end: return status; } @@ -2134,11 +2323,9 @@ enum bt_btr_status btr_floating_point_cb(double value, bt_common_field_type_id_string( bt_field_type_get_type_id(type)), value); - - /* Create next field */ - field = get_next_field(notit); + field = borrow_next_field(notit); if (!field) { - BT_LOGW("Cannot get next field: notit-addr=%p", notit); + BT_LOGW("Cannot borrow next field: notit-addr=%p", notit); status = BT_BTR_STATUS_ERROR; goto end; } @@ -2148,7 +2335,6 @@ enum bt_btr_status btr_floating_point_cb(double value, stack_top(notit->stack)->index++; end: - BT_PUT(field); return status; } @@ -2167,15 +2353,16 @@ enum bt_btr_status btr_string_begin_cb( notit, notit->btr, type, bt_common_field_type_id_string( bt_field_type_get_type_id(type))); - - /* Create next field */ - field = get_next_field(notit); + field = borrow_next_field(notit); if (!field) { BT_LOGW("Cannot get next field: notit-addr=%p", notit); status = BT_BTR_STATUS_ERROR; goto end; } + ret = bt_field_string_clear(field); + BT_ASSERT(ret == 0); + /* * Push on stack. Not a compound type per se, but we know that only * btr_string_cb() may be called between this call and a subsequent @@ -2189,23 +2376,7 @@ enum bt_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_field_string_set_value(field, ""); - if (ret) { - BT_LOGE("Cannot initialize string field's value to an empty string: " - "notit-addr=%p, field-addr=%p, ret=%d", - notit, field, ret); - status = BT_BTR_STATUS_ERROR; - goto end; - } - end: - BT_PUT(field); - return status; } @@ -2225,12 +2396,10 @@ enum bt_btr_status btr_string_cb(const char *value, bt_common_field_type_id_string( bt_field_type_get_type_id(type)), len); - - /* Get string field */ field = stack_top(notit->stack)->base; BT_ASSERT(field); - /* Append current string */ + /* Append current substring */ ret = bt_field_string_append_len(field, value, len); if (ret) { BT_LOGE("Cannot append substring to string field's value: " @@ -2280,33 +2449,14 @@ enum bt_btr_status btr_compound_begin_cb( bt_common_field_type_id_string( bt_field_type_get_type_id(type))); - /* Create field */ + /* Borrow field */ if (stack_empty(notit->stack)) { - /* Root: create dynamic scope field */ - *notit->cur_dscope_field = bt_field_create(type); - field = *notit->cur_dscope_field; - - /* - * Field will be put at the end of this function - * (stack_push() will take one reference, but this - * reference is lost upon the equivalent stack_pop() - * later), so also get it for our context to own it. - */ - bt_get(*notit->cur_dscope_field); - - if (!field) { - BT_LOGE("Cannot create compound field: " - "notit-addr=%p, ft-addr=%p, ft-id=%s", - notit, type, - bt_common_field_type_id_string( - bt_field_type_get_type_id(type))); - status = BT_BTR_STATUS_ERROR; - goto end; - } + /* Root: already set by read_dscope_begin_state() */ + field = notit->cur_dscope_field; } else { - field = get_next_field(notit); + field = borrow_next_field(notit); if (!field) { - BT_LOGW("Cannot get next field: notit-addr=%p", notit); + BT_LOGW("Cannot borrow next field: notit-addr=%p", notit); status = BT_BTR_STATUS_ERROR; goto end; } @@ -2327,8 +2477,6 @@ enum bt_btr_status btr_compound_begin_cb( } end: - BT_PUT(field); - return status; } @@ -2409,26 +2557,23 @@ struct bt_field *resolve_field(struct bt_notif_iter *notit, goto end; } - bt_get(field); - for (i = 0; i < bt_field_path_get_index_count(path); ++i) { struct bt_field *next_field = NULL; struct bt_field_type *field_type; int index = bt_field_path_get_index(path, i); - field_type = bt_field_get_type(field); + field_type = bt_field_borrow_type(field); BT_ASSERT(field_type); - if (is_struct_type(field_type)) { - next_field = bt_field_structure_get_field_by_index( + if (bt_field_type_is_structure(field_type)) { + next_field = bt_field_structure_borrow_field_by_index( field, index); - } else if (is_variant_type(field_type)) { + } else if (bt_field_type_is_variant(field_type)) { next_field = - bt_field_variant_get_current_field(field); + bt_field_variant_borrow_current_field(field); } - BT_PUT(field); - BT_PUT(field_type); + field = NULL; if (!next_field) { BT_LOGW("Cannot find next field: " @@ -2441,7 +2586,7 @@ struct bt_field *resolve_field(struct bt_notif_iter *notit, } /* Move next field -> field */ - BT_MOVE(field, next_field); + field = next_field; } end: @@ -2459,7 +2604,7 @@ int64_t btr_get_sequence_length_cb(struct bt_field_type *type, void *data) struct bt_field *length_field = NULL; uint64_t length; - field_path = bt_field_type_sequence_get_length_field_path(type); + field_path = bt_field_type_sequence_borrow_length_field_path(type); BT_ASSERT(field_path); length_field = resolve_field(notit, field_path); if (!length_field) { @@ -2478,21 +2623,18 @@ int64_t btr_get_sequence_length_cb(struct bt_field_type *type, void *data) } seq_field = stack_top(notit->stack)->base; - iret = bt_field_sequence_set_length(seq_field, length_field); + iret = bt_field_sequence_set_length(seq_field, length); if (iret) { BT_LOGE("Cannot set sequence field's length field: " "notit-addr=%p, seq-field-addr=%p, " - "length-field-addr=%p, ", - notit, seq_field, length_field); + "length=%" PRIu64, + notit, seq_field, length); goto end; } ret = (int64_t) length; end: - BT_PUT(length_field); - BT_PUT(field_path); - return ret; } @@ -2500,14 +2642,17 @@ static struct bt_field_type *btr_borrow_variant_field_type_cb( struct bt_field_type *type, void *data) { + int ret; struct bt_field_path *path; struct bt_notif_iter *notit = data; struct bt_field *var_field; struct bt_field *tag_field = NULL; + struct bt_field_type *tag_ft = NULL; + struct bt_field_type *tag_int_ft = NULL; struct bt_field *selected_field = NULL; struct bt_field_type *selected_field_type = NULL; - path = bt_field_type_variant_get_tag_field_path(type); + path = bt_field_type_variant_borrow_tag_field_path(type); BT_ASSERT(path); tag_field = resolve_field(notit, path); if (!tag_field) { @@ -2522,34 +2667,51 @@ struct bt_field_type *btr_borrow_variant_field_type_cb( * able to select a current field for this variant. This * callback function we're in is called _after_ * compound_begin(), so the current stack top's base field is - * the variant field in question. We get the selected field here - * thanks to this tag field (thus creating the selected field), - * which will also provide us with its type. Then, this field - * will remain the current selected one until the next callback - * function call which is used to fill the current selected - * field. + * the variant field in question. We set the variant field's tag + * here and then get the current (selected) field thanks to this + * tag field's value. This current field will also provide us + * with its type. Then, this current field will remain the + * current selected one until the next callback function call + * which is used to fill it. */ var_field = stack_top(notit->stack)->base; - selected_field = bt_field_variant_get_field(var_field, tag_field); + tag_ft = bt_field_borrow_type(tag_field); + tag_int_ft = bt_field_type_enumeration_borrow_container_field_type( + tag_ft); + + if (bt_field_type_integer_is_signed(tag_int_ft)) { + int64_t tag_value; + + ret = bt_field_integer_signed_get_value(tag_field, &tag_value); + BT_ASSERT(ret == 0); + ret = bt_field_variant_set_tag_signed(var_field, tag_value); + BT_ASSERT(ret == 0); + } else { + uint64_t tag_value; + + ret = bt_field_integer_unsigned_get_value(tag_field, + &tag_value); + BT_ASSERT(ret == 0); + ret = bt_field_variant_set_tag_unsigned(var_field, tag_value); + BT_ASSERT(ret == 0); + } + + selected_field = bt_field_variant_borrow_current_field(var_field); if (!selected_field) { - BT_LOGW("Cannot get variant field's selection using tag field: " - "notit-addr=%p, var-field-addr=%p, tag-field-addr=%p", - notit, var_field, tag_field); + BT_LOGW("Cannot borrow variant field's current field: " + "notit-addr=%p, var-field-addr=%p", + notit, var_field); goto end; } selected_field_type = bt_field_borrow_type(selected_field); end: - BT_PUT(tag_field); - BT_PUT(selected_field); - BT_PUT(path); return selected_field_type; } static -int set_event_clocks(struct bt_event *event, - struct bt_notif_iter *notit) +int set_event_clocks(struct bt_notif_iter *notit) { int ret; GHashTableIter iter; @@ -2559,13 +2721,13 @@ int set_event_clocks(struct bt_event *event, g_hash_table_iter_init(&iter, notit->clock_states); while (g_hash_table_iter_next(&iter, (gpointer) &clock_class, - (gpointer) &clock_state)) { + (gpointer) &clock_state)) { struct bt_clock_value *clock_value; - clock_value = bt_clock_value_create(clock_class, - *clock_state); + clock_value = bt_event_borrow_clock_value(notit->event, + clock_class); if (!clock_value) { - BT_LOGE("Cannot create clock value from clock class: " + BT_LOGE("Cannot borrow clock value from event with given clock class: " "notit-addr=%p, clock-class-addr=%p, " "clock-class-name=\"%s\"", notit, clock_class, @@ -2573,310 +2735,26 @@ int set_event_clocks(struct bt_event *event, ret = -1; goto end; } - ret = bt_event_set_clock_value(event, clock_value); - bt_put(clock_value); - if (ret) { - struct bt_event_class *event_class = - bt_event_get_class(event); - - BT_ASSERT(event_class); - BT_LOGE("Cannot set event's clock value: " - "notit-addr=%p, event-addr=%p, " - "event-class-name=\"%s\", " - "event-class-id=%" PRId64 ", " - "clock-class-addr=%p, " - "clock-class-name=\"%s\", " - "clock-value-addr=%p", - notit, event, - bt_event_class_get_name(event_class), - bt_event_class_get_id(event_class), - clock_class, - bt_clock_class_get_name(clock_class), - clock_value); - bt_put(event_class); - goto end; - } - } - - ret = 0; -end: - return ret; -} - -static -struct bt_event *create_event(struct bt_notif_iter *notit) -{ - int ret; - struct bt_event *event; - - BT_LOGV("Creating event for event notification: " - "notit-addr=%p, event-class-addr=%p, " - "event-class-name=\"%s\", " - "event-class-id=%" PRId64, - notit, notit->meta.event_class, - bt_event_class_get_name(notit->meta.event_class), - bt_event_class_get_id(notit->meta.event_class)); - - /* Create event object. */ - event = bt_event_create(notit->meta.event_class); - if (!event) { - BT_LOGE("Cannot create event: " - "notit-addr=%p, event-class-addr=%p, " - "event-class-name=\"%s\", " - "event-class-id=%" PRId64, - notit, notit->meta.event_class, - bt_event_class_get_name(notit->meta.event_class), - bt_event_class_get_id(notit->meta.event_class)); - goto error; - } - - /* Set header, stream event context, context, and payload fields. */ - ret = bt_event_set_header(event, - notit->dscopes.stream_event_header); - if (ret) { - BT_LOGE("Cannot set event's header field: " - "notit-addr=%p, event-addr=%p, event-class-addr=%p, " - "event-class-name=\"%s\", " - "event-class-id=%" PRId64 ", field-addr=%p", - notit, event, notit->meta.event_class, - bt_event_class_get_name(notit->meta.event_class), - bt_event_class_get_id(notit->meta.event_class), - notit->dscopes.stream_event_header); - goto error; - } - - ret = bt_event_set_stream_event_context(event, - notit->dscopes.stream_event_context); - if (ret) { - BT_LOGE("Cannot set event's context field: " - "notit-addr=%p, event-addr=%p, event-class-addr=%p, " - "event-class-name=\"%s\", " - "event-class-id=%" PRId64 ", field-addr=%p", - notit, event, notit->meta.event_class, - bt_event_class_get_name(notit->meta.event_class), - bt_event_class_get_id(notit->meta.event_class), - notit->dscopes.stream_event_context); - goto error; - } - - ret = bt_event_set_context(event, - notit->dscopes.event_context); - if (ret) { - BT_LOGE("Cannot set event's stream event context field: " - "notit-addr=%p, event-addr=%p, event-class-addr=%p, " - "event-class-name=\"%s\", " - "event-class-id=%" PRId64 ", field-addr=%p", - notit, event, notit->meta.event_class, - bt_event_class_get_name(notit->meta.event_class), - bt_event_class_get_id(notit->meta.event_class), - notit->dscopes.event_context); - goto error; - } - - ret = bt_event_set_payload(event, - notit->dscopes.event_payload); - if (ret) { - BT_LOGE("Cannot set event's payload field: " - "notit-addr=%p, event-addr=%p, event-class-addr=%p, " - "event-class-name=\"%s\", " - "event-class-id=%" PRId64 ", field-addr=%p", - notit, event, notit->meta.event_class, - bt_event_class_get_name(notit->meta.event_class), - bt_event_class_get_id(notit->meta.event_class), - notit->dscopes.event_payload); - goto error; - } - - ret = set_event_clocks(event, notit); - if (ret) { - BT_LOGE("Cannot set event's clock values: " - "notit-addr=%p, event-addr=%p, event-class-addr=%p, " - "event-class-name=\"%s\", " - "event-class-id=%" PRId64, - notit, event, notit->meta.event_class, - bt_event_class_get_name(notit->meta.event_class), - bt_event_class_get_id(notit->meta.event_class)); - goto error; - } - - /* Associate with current packet. */ - BT_ASSERT(notit->packet); - ret = bt_event_set_packet(event, notit->packet); - if (ret) { - BT_LOGE("Cannot set event's header field: " - "notit-addr=%p, event-addr=%p, event-class-addr=%p, " - "event-class-name=\"%s\", " - "event-class-id=%" PRId64 ", packet-addr=%p", - notit, event, notit->meta.event_class, - bt_event_class_get_name(notit->meta.event_class), - bt_event_class_get_id(notit->meta.event_class), - notit->packet); - goto error; - } - - goto end; - -error: - BT_PUT(event); - -end: - return event; -} - -static -uint64_t get_cur_stream_instance_id(struct bt_notif_iter *notit) -{ - struct bt_field *stream_instance_id_field = NULL; - uint64_t stream_instance_id = -1ULL; - int ret; - - if (!notit->dscopes.trace_packet_header) { - goto end; - } - - stream_instance_id_field = bt_field_structure_get_field_by_name( - notit->dscopes.trace_packet_header, "stream_instance_id"); - if (!stream_instance_id_field) { - goto end; - } - - ret = bt_field_integer_unsigned_get_value(stream_instance_id_field, - &stream_instance_id); - if (ret) { - stream_instance_id = -1ULL; - goto end; - } - -end: - bt_put(stream_instance_id_field); - return stream_instance_id; -} - -static -int set_stream(struct bt_notif_iter *notit) -{ - int ret = 0; - struct bt_stream *stream = NULL; - - BT_LOGV("Calling user function (get stream): notit-addr=%p, " - "stream-class-addr=%p, stream-class-name=\"%s\", " - "stream-class-id=%" PRId64, - notit, notit->meta.stream_class, - bt_stream_class_get_name(notit->meta.stream_class), - bt_stream_class_get_id(notit->meta.stream_class)); - stream = bt_get(notit->medium.medops.get_stream( - notit->meta.stream_class, get_cur_stream_instance_id(notit), - notit->medium.data)); - BT_LOGV("User function returned: stream-addr=%p", stream); - if (!stream) { - BT_LOGW_STR("User function failed to return a stream object for the given stream class."); - ret = -1; - goto end; - } - if (notit->stream && stream != notit->stream) { - BT_LOGW("User function returned a different stream than the previous one for the same sequence of packets."); - ret = -1; - goto end; + ret = bt_clock_value_set_value(clock_value, *clock_state); + BT_ASSERT(ret == 0); } - BT_MOVE(notit->stream, stream); - + ret = 0; end: - bt_put(stream); return ret; } -static -void create_packet(struct bt_notif_iter *notit) -{ - int ret; - struct bt_packet *packet = NULL; - - BT_LOGV("Creating packet for packet notification: " - "notit-addr=%p", notit); - BT_LOGV("Creating packet from stream: " - "notit-addr=%p, stream-addr=%p, " - "stream-class-addr=%p, " - "stream-class-name=\"%s\", " - "stream-class-id=%" PRId64, - notit, notit->stream, notit->meta.stream_class, - bt_stream_class_get_name(notit->meta.stream_class), - bt_stream_class_get_id(notit->meta.stream_class)); - - /* Create packet */ - BT_ASSERT(notit->stream); - packet = bt_packet_create(notit->stream); - if (!packet) { - BT_LOGE("Cannot create packet from stream: " - "notit-addr=%p, stream-addr=%p, " - "stream-class-addr=%p, " - "stream-class-name=\"%s\", " - "stream-class-id=%" PRId64, - notit, notit->stream, notit->meta.stream_class, - bt_stream_class_get_name(notit->meta.stream_class), - bt_stream_class_get_id(notit->meta.stream_class)); - goto error; - } - - /* Set packet's context and header fields */ - if (notit->dscopes.trace_packet_header) { - ret = bt_packet_set_header(packet, - notit->dscopes.trace_packet_header); - if (ret) { - BT_LOGE("Cannot set packet's header field: " - "notit-addr=%p, packet-addr=%p, " - "stream-addr=%p, " - "stream-class-addr=%p, " - "stream-class-name=\"%s\", " - "stream-class-id=%" PRId64 ", " - "field-addr=%p", - notit, packet, notit->stream, notit->meta.stream_class, - bt_stream_class_get_name(notit->meta.stream_class), - bt_stream_class_get_id(notit->meta.stream_class), - notit->dscopes.trace_packet_header); - goto error; - } - } - - if (notit->dscopes.stream_packet_context) { - ret = bt_packet_set_context(packet, - notit->dscopes.stream_packet_context); - if (ret) { - BT_LOGE("Cannot set packet's context field: " - "notit-addr=%p, packet-addr=%p, " - "stream-addr=%p, " - "stream-class-addr=%p, " - "stream-class-name=\"%s\", " - "stream-class-id=%" PRId64 ", " - "field-addr=%p", - notit, packet, notit->stream, notit->meta.stream_class, - bt_stream_class_get_name(notit->meta.stream_class), - bt_stream_class_get_id(notit->meta.stream_class), - notit->dscopes.trace_packet_header); - goto error; - } - } - - goto end; - -error: - BT_PUT(packet); - -end: - BT_MOVE(notit->packet, packet); -} - static void notify_new_stream(struct bt_notif_iter *notit, struct bt_notification **notification) { + enum bt_notif_iter_status status; struct bt_notification *ret = NULL; - int iret; - /* Ask the user for the stream */ - iret = set_stream(notit); - if (iret) { + status = set_current_stream(notit); + if (status != BT_NOTIF_ITER_STATUS_OK) { + BT_PUT(ret); goto end; } @@ -2919,82 +2797,85 @@ static void notify_new_packet(struct bt_notif_iter *notit, struct bt_notification **notification) { - struct bt_notification *ret; + int ret; + enum bt_notif_iter_status status; + struct bt_notification *notif = NULL; - /* Initialize the iterator's current packet */ - create_packet(notit); - if (!notit->packet) { - BT_LOGE("Cannot create packet for packet notification: " - "notit-addr=%p", notit); - return; + status = set_current_packet(notit); + if (status != BT_NOTIF_ITER_STATUS_OK) { + goto end; } - ret = bt_notification_packet_begin_create(notit->packet); - if (!ret) { + BT_ASSERT(notit->packet); + + if (notit->packet_header_field) { + ret = bt_packet_move_header(notit->packet, + notit->packet_header_field); + if (ret) { + goto end; + } + + notit->packet_header_field = NULL; + + /* + * At this point notit->dscopes.trace_packet_header has + * the same value as the packet header field within + * notit->packet. + */ + BT_ASSERT(bt_packet_borrow_header(notit->packet) == + notit->dscopes.trace_packet_header); + } + + if (notit->packet_context_field) { + ret = bt_packet_move_context(notit->packet, + notit->packet_context_field); + if (ret) { + goto end; + } + + notit->packet_context_field = NULL; + + /* + * At this point notit->dscopes.trace_packet_header has + * the same value as the packet header field within + * notit->packet. + */ + BT_ASSERT(bt_packet_borrow_context(notit->packet) == + notit->dscopes.stream_packet_context); + } + + notif = bt_notification_packet_begin_create(notit->packet); + if (!notif) { BT_LOGE("Cannot create packet beginning notification: " "notit-addr=%p, packet-addr=%p", notit, notit->packet); return; } - *notification = ret; + +end: + *notification = notif; } static void notify_end_of_packet(struct bt_notif_iter *notit, struct bt_notification **notification) { - struct bt_notification *ret; + struct bt_notification *notif; if (!notit->packet) { return; } - ret = bt_notification_packet_end_create(notit->packet); - if (!ret) { + notif = bt_notification_packet_end_create(notit->packet); + if (!notif) { BT_LOGE("Cannot create packet end notification: " "notit-addr=%p, packet-addr=%p", notit, notit->packet); return; } - BT_PUT(notit->packet); - *notification = ret; -} - -static -void notify_event(struct bt_notif_iter *notit, - struct bt_clock_class_priority_map *cc_prio_map, - struct bt_notification **notification) -{ - struct bt_event *event = NULL; - struct bt_notification *ret = NULL; - - /* Make sure that the event contains at least one bit of data */ - if (notit->buf.at == notit->buf.last_eh_at) { - BT_LOGE("Cannot create empty event with 0 bits of data: " - "notit-addr=%p, packet-cur=%zu", - notit, packet_at(notit)); - goto end; - } - /* Create event */ - event = create_event(notit); - if (!event) { - BT_LOGE("Cannot create event for event notification: " - "notit-addr=%p", notit); - goto end; - } - - ret = bt_notification_event_create(event, cc_prio_map); - if (!ret) { - BT_LOGE("Cannot create event notification: " - "notit-addr=%p, event-addr=%p, " - "cc-prio-map-addr=%p", - notit, event, cc_prio_map); - goto end; - } - *notification = ret; -end: - BT_PUT(event); + BT_PUT(notit->packet); + *notification = notif; } static @@ -3006,7 +2887,7 @@ void init_trace_field_path_cache(struct bt_trace *trace, int i, count; struct bt_field_type *packet_header = NULL; - packet_header = bt_trace_get_packet_header_field_type(trace); + packet_header = bt_trace_borrow_packet_header_field_type(trace); if (!packet_header) { goto end; } @@ -3022,8 +2903,8 @@ void init_trace_field_path_cache(struct bt_trace *trace, int ret; const char *field_name; - ret = bt_field_type_structure_get_field_by_index(packet_header, - &field_name, NULL, i); + ret = bt_field_type_structure_borrow_field_by_index( + packet_header, &field_name, NULL, i); if (ret) { BT_LOGE("Cannot get structure field's field: " "field-addr=%p, index=%d", @@ -3042,7 +2923,6 @@ void init_trace_field_path_cache(struct bt_trace *trace, end: trace_field_path_cache->stream_id = stream_id; trace_field_path_cache->stream_instance_id = stream_instance_id; - BT_PUT(packet_header); } BT_HIDDEN @@ -3070,7 +2950,7 @@ struct bt_notif_iter *bt_notif_iter_create(struct bt_trace *trace, BT_ASSERT(trace); BT_ASSERT(medops.request_bytes); - BT_ASSERT(medops.get_stream); + BT_ASSERT(medops.borrow_stream); BT_LOGD("Creating CTF plugin notification iterator: " "trace-addr=%p, trace-name=\"%s\", max-request-size=%zu, " "data=%p", @@ -3081,12 +2961,12 @@ struct bt_notif_iter *bt_notif_iter_create(struct bt_trace *trace, goto end; } notit->clock_states = g_hash_table_new_full(g_direct_hash, - g_direct_equal, bt_put, g_free); + g_direct_equal, NULL, g_free); if (!notit->clock_states) { BT_LOGE_STR("Failed to allocate a GHashTable."); goto error; } - notit->meta.trace = bt_get(trace); + notit->meta.trace = trace; notit->medium.medops = medops; notit->medium.max_request_sz = max_request_sz; notit->medium.data = data; @@ -3105,14 +2985,14 @@ struct bt_notif_iter *bt_notif_iter_create(struct bt_trace *trace, bt_notif_iter_reset(notit); init_trace_field_path_cache(trace, ¬it->trace_field_path_cache); notit->sc_field_path_caches = g_hash_table_new_full(g_direct_hash, - g_direct_equal, bt_put, g_free); + g_direct_equal, NULL, g_free); if (!notit->sc_field_path_caches) { BT_LOGE_STR("Failed to allocate a GHashTable."); goto error; } notit->field_overrides = g_hash_table_new_full(g_direct_hash, - g_direct_equal, bt_put, g_free); + g_direct_equal, NULL, g_free); if (!notit->field_overrides) { BT_LOGE_STR("Failed to allocate a GHashTable."); goto error; @@ -3136,13 +3016,10 @@ error: void bt_notif_iter_destroy(struct bt_notif_iter *notit) { - BT_PUT(notit->meta.trace); - BT_PUT(notit->meta.stream_class); - BT_PUT(notit->meta.event_class); BT_PUT(notit->packet); BT_PUT(notit->stream); - BT_PUT(notit->cur_timestamp_end); - put_all_dscopes(notit); + BT_PUT(notit->meta.cc_prio_map); + release_all_dscopes(notit); BT_LOGD("Destroying CTF plugin notification iterator: addr=%p", notit); @@ -3176,11 +3053,17 @@ enum bt_notif_iter_status bt_notif_iter_get_next_notification( struct bt_clock_class_priority_map *cc_prio_map, struct bt_notification **notification) { + int ret; enum bt_notif_iter_status status = BT_NOTIF_ITER_STATUS_OK; BT_ASSERT(notit); BT_ASSERT(notification); + if (cc_prio_map != notit->meta.cc_prio_map) { + bt_put(notit->meta.cc_prio_map); + notit->meta.cc_prio_map = bt_get(cc_prio_map); + } + if (notit->state == STATE_DONE) { status = BT_NOTIF_ITER_STATUS_EOF; goto end; @@ -3195,6 +3078,7 @@ enum bt_notif_iter_status bt_notif_iter_get_next_notification( BT_LOGV_STR("Medium returned BT_NOTIF_ITER_STATUS_AGAIN."); goto end; } + if (status != BT_NOTIF_ITER_STATUS_OK) { if (status == BT_NOTIF_ITER_STATUS_EOF) { enum state next_state = notit->state; @@ -3202,9 +3086,11 @@ enum bt_notif_iter_status bt_notif_iter_get_next_notification( BT_LOGV_STR("Medium returned BT_NOTIF_ITER_STATUS_EOF."); if (notit->packet) { - notify_end_of_packet(notit, notification); + notify_end_of_packet(notit, + notification); } else { - notify_end_of_stream(notit, notification); + notify_end_of_stream(notit, + notification); next_state = STATE_DONE; } @@ -3215,12 +3101,12 @@ enum bt_notif_iter_status bt_notif_iter_get_next_notification( status = BT_NOTIF_ITER_STATUS_OK; notit->state = next_state; - goto end; } else { BT_LOGW("Cannot handle state: " "notit-addr=%p, state=%s", notit, state_string(notit->state)); } + goto end; } @@ -3239,26 +3125,25 @@ enum bt_notif_iter_status bt_notif_iter_get_next_notification( if (!*notification) { status = BT_NOTIF_ITER_STATUS_ERROR; } + goto end; case STATE_EMIT_NOTIF_EVENT: - /* notify_event() logs errors */ - notify_event(notit, cc_prio_map, notification); - if (!*notification) { + BT_ASSERT(notit->event_notif); + ret = set_event_clocks(notit); + if (ret) { status = BT_NOTIF_ITER_STATUS_ERROR; + goto end; } + + BT_MOVE(*notification, notit->event_notif); goto end; case STATE_EMIT_NOTIF_END_OF_PACKET: /* Update clock with timestamp_end field. */ if (notit->cur_timestamp_end) { enum bt_btr_status btr_status; - struct bt_field_type *field_type = - bt_field_get_type( - notit->cur_timestamp_end); - BT_ASSERT(field_type); btr_status = update_clock(notit, notit->cur_timestamp_end); - BT_PUT(field_type); if (btr_status != BT_BTR_STATUS_OK) { BT_LOGW("Cannot update stream's clock value: " "notit-addr=%p", notit); @@ -3272,6 +3157,7 @@ enum bt_notif_iter_status bt_notif_iter_get_next_notification( if (!*notification) { status = BT_NOTIF_ITER_STATUS_ERROR; } + goto end; default: /* Non-emitting state: continue */ @@ -3284,7 +3170,7 @@ end: } BT_HIDDEN -enum bt_notif_iter_status bt_notif_iter_get_packet_header_context_fields( +enum bt_notif_iter_status bt_notif_iter_borrow_packet_header_context_fields( struct bt_notif_iter *notit, struct bt_field **packet_header_field, struct bt_field **packet_context_field) @@ -3345,19 +3231,20 @@ enum bt_notif_iter_status bt_notif_iter_get_packet_header_context_fields( } set_fields: + ret = set_current_packet_content_sizes(notit); + if (ret) { + status = BT_NOTIF_ITER_STATUS_ERROR; + goto end; + } + if (packet_header_field) { - *packet_header_field = bt_get(notit->dscopes.trace_packet_header); + *packet_header_field = notit->dscopes.trace_packet_header; } if (packet_context_field) { - *packet_context_field = bt_get(notit->dscopes.stream_packet_context); + *packet_context_field = notit->dscopes.stream_packet_context; } - ret = set_current_packet_content_sizes(notit); - if (ret) { - status = BT_NOTIF_ITER_STATUS_ERROR; - goto end; - } end: return status; }