X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=plugins%2Fctf%2Fcommon%2Fnotif-iter%2Fnotif-iter.c;h=823a753ff29fcff4539ebeff616410fe1204f969;hb=ac0c6bddcdde51dcbb46fc73c61d4f2330774451;hp=260d15ee21d4dcd76cd2cfcc37089c16ea922ca4;hpb=1556a1afe8d70a3a89155ff25815e203333a93e9;p=babeltrace.git diff --git a/plugins/ctf/common/notif-iter/notif-iter.c b/plugins/ctf/common/notif-iter/notif-iter.c index 260d15ee..823a753f 100644 --- a/plugins/ctf/common/notif-iter/notif-iter.c +++ b/plugins/ctf/common/notif-iter/notif-iter.c @@ -36,10 +36,11 @@ #include #include #include -#include +#include #include #include #include +#include #include #include @@ -103,6 +104,39 @@ enum state { STATE_SKIP_PACKET_PADDING, }; +struct trace_field_path_cache { + /* + * Indexes of the stream_id and stream_instance_id field in the packet + * header structure, -1 if unset. + */ + int stream_id; + int stream_instance_id; +}; + +struct stream_class_field_path_cache { + /* + * Indexes of the v and id fields in the stream event header structure, + * -1 if unset. + */ + int v; + int id; + + /* + * index of the timestamp_end, packet_size and content_size fields in + * the stream packet context structure. Set to -1 if the fields were + * not found. + */ + int timestamp_end; + int packet_size; + int content_size; +}; + +struct field_cb_override { + enum bt_ctf_btr_status (* func)(void *value, + struct bt_ctf_field_type *type, void *data); + void *data; +}; + /* CTF notification iterator */ struct bt_ctf_notif_iter { /* Visit stack */ @@ -130,6 +164,11 @@ struct bt_ctf_notif_iter { /* Current packet (NULL if not created yet) */ struct bt_ctf_packet *packet; + /* + * Current timestamp_end field (to consider before switching packets). + */ + struct bt_ctf_field *cur_timestamp_end; + /* Database of current dynamic scopes (owned by this) */ struct { struct bt_ctf_field *trace_packet_header; @@ -140,6 +179,21 @@ struct bt_ctf_notif_iter { struct bt_ctf_field *event_payload; } dscopes; + /* + * Special field overrides. + * + * Overrides are used to implement the behaviours of special fields such + * as "timestamp_end" (which must be ignored until the end of the + * packet), "id" (event id) which can be present multiple times and must + * be updated multiple time. + * + * This should be used to implement the behaviour of integer fields + * mapped to clocks and other "tagged" fields (in CTF 2). + * + * bt_ctf_field_type to struct field_cb_override + */ + GHashTable *field_overrides; + /* Current state */ enum state state; @@ -174,13 +228,32 @@ struct bt_ctf_notif_iter { /* Current content size (bits) (-1 if unknown) */ int64_t cur_content_size; - /* bt_ctf_clock to uint64_t. */ + /* bt_ctf_clock_class to uint64_t. */ GHashTable *clock_states; + + /* + * Cache of the trace-constant field paths (event header type) + * associated to the current trace. + */ + struct trace_field_path_cache trace_field_path_cache; + + /* + * Field path cache associated with the current stream class. + * Ownership of this structure belongs to the field_path_caches HT. + */ + struct stream_class_field_path_cache *cur_sc_field_path_cache; + + /* bt_ctf_stream_class to struct stream_class_field_path_cache. */ + GHashTable *sc_field_path_caches; }; static int bt_ctf_notif_iter_switch_packet(struct bt_ctf_notif_iter *notit); +static +enum bt_ctf_btr_status btr_timestamp_end_cb(void *value, + struct bt_ctf_field_type *type, void *data); + static void stack_entry_free_func(gpointer data) { @@ -499,8 +572,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; } @@ -535,14 +607,157 @@ bool is_variant_type(struct bt_ctf_field_type *field_type) BT_CTF_TYPE_ID_VARIANT; } +static +struct stream_class_field_path_cache * +create_stream_class_field_path_cache_entry( + struct bt_ctf_notif_iter *notit, + struct bt_ctf_stream_class *stream_class) +{ + int v = -1; + int id = -1; + int timestamp_end = -1; + int packet_size = -1; + int content_size = -1; + struct stream_class_field_path_cache *cache_entry = g_new0( + struct stream_class_field_path_cache, 1); + struct bt_ctf_field_type *event_header = NULL, *packet_context = NULL; + + if (!cache_entry) { + goto end; + } + + event_header = bt_ctf_stream_class_get_event_header_type(stream_class); + if (event_header && bt_ctf_field_type_is_structure(event_header)) { + int i, count; + + count = bt_ctf_field_type_structure_get_field_count( + event_header); + if (count < 0) { + goto error; + } + for (i = 0; i < count; i++) { + int ret; + const char *name; + + ret = bt_ctf_field_type_structure_get_field( + event_header, &name, NULL, i); + if (ret) { + goto error; + } + + if (v != -1 && id != -1) { + break; + } + if (v == -1 && !strcmp(name, "v")) { + v = i; + } else if (id == -1 && !strcmp(name, "id")) { + id = i; + } + } + } + + packet_context = bt_ctf_stream_class_get_packet_context_type( + stream_class); + if (packet_context && bt_ctf_field_type_is_structure(packet_context)) { + int i, count; + + count = bt_ctf_field_type_structure_get_field_count( + packet_context); + if (count < 0) { + goto error; + } + for (i = 0; i < count; i++) { + int ret; + const char *name; + struct bt_ctf_field_type *field_type; + + if (timestamp_end != -1 && packet_size != -1 && + content_size != -1) { + break; + } + + ret = bt_ctf_field_type_structure_get_field( + packet_context, &name, &field_type, i); + if (ret) { + goto error; + } + + if (timestamp_end == -1 && + !strcmp(name, "timestamp_end")) { + struct field_cb_override *override = g_new0( + 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); + + timestamp_end = i; + } else if (packet_size == -1 && + !strcmp(name, "packet_size")) { + packet_size = i; + } else if (content_size == -1 && + !strcmp(name, "content_size")) { + content_size = i; + } + BT_PUT(field_type); + } + } + + cache_entry->v = v; + cache_entry->id = id; + 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; + goto end; +} + +static +struct stream_class_field_path_cache *get_stream_class_field_path_cache( + struct bt_ctf_notif_iter *notit, + struct bt_ctf_stream_class *stream_class) +{ + bool cache_entry_found; + struct stream_class_field_path_cache *cache_entry; + + cache_entry_found = g_hash_table_lookup_extended( + notit->sc_field_path_caches, + stream_class, NULL, (gpointer) &cache_entry); + if (unlikely(!cache_entry_found)) { + 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); + } + + return cache_entry; +} + 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; + struct bt_ctf_field_type *packet_header_type = NULL; struct bt_ctf_field_type *stream_id_field_type = NULL; uint64_t stream_id; + /* Clear the current stream class field path cache. */ + notit->cur_sc_field_path_cache = NULL; + /* Is there any "stream_id" field in the packet header? */ packet_header_type = bt_ctf_trace_get_packet_header_type( notit->meta.trace); @@ -560,8 +775,8 @@ enum bt_ctf_notif_iter_status set_current_stream_class(struct bt_ctf_notif_iter packet_header_type, "stream_id"); if (stream_id_field_type) { /* Find appropriate stream class using current stream ID */ - struct bt_ctf_field *stream_id_field = NULL; int ret; + struct bt_ctf_field *stream_id_field = NULL; assert(notit->dscopes.trace_packet_header); @@ -590,6 +805,17 @@ enum bt_ctf_notif_iter_status set_current_stream_class(struct bt_ctf_notif_iter goto end; } + /* + * Retrieve (or lazily create) the current stream class field path + * cache. + */ + notit->cur_sc_field_path_cache = get_stream_class_field_path_cache( + notit, notit->meta.stream_class); + if (!notit->cur_sc_field_path_cache) { + PERR("Failed to retrieve stream class field path cache\n"); + status = BT_CTF_NOTIF_ITER_STATUS_ERROR; + goto end; + } end: BT_PUT(packet_header_type); BT_PUT(stream_id_field_type); @@ -622,8 +848,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; } @@ -734,8 +959,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; } @@ -913,8 +1137,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; } @@ -947,11 +1170,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, @@ -981,8 +1202,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; } @@ -1110,17 +1330,8 @@ enum bt_ctf_notif_iter_status handle_state(struct bt_ctf_notif_iter *notit) return status; } - /** * Resets the internal state of a CTF notification iterator. - * - * This function can be used when it is desired to seek to the beginning - * of another packet. It is expected that the next call to - * bt_ctf_notif_iter_medium_ops::request_bytes() made by this - * notification iterator will return the \em first bytes of a \em - * packet. - * - * @param notif_iter CTF notification iterator */ static void bt_ctf_notif_iter_reset(struct bt_ctf_notif_iter *notit) @@ -1150,6 +1361,7 @@ int bt_ctf_notif_iter_switch_packet(struct bt_ctf_notif_iter *notit) BT_PUT(notit->meta.stream_class); BT_PUT(notit->meta.event_class); BT_PUT(notit->packet); + BT_PUT(notit->cur_timestamp_end); put_all_dscopes(notit); /* @@ -1173,6 +1385,7 @@ int bt_ctf_notif_iter_switch_packet(struct bt_ctf_notif_iter *notit) notit->cur_content_size = -1; notit->cur_packet_size = -1; + notit->cur_sc_field_path_cache = NULL; end: return ret; } @@ -1213,10 +1426,6 @@ struct bt_ctf_field *get_next_field(struct bt_ctf_notif_iter *notit) break; } - if (!next_field) { - next_field = NULL; - } - end: BT_PUT(base_type); @@ -1281,23 +1490,25 @@ 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; + gboolean clock_class_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( + struct bt_ctf_clock_class *clock_class = + bt_ctf_field_type_integer_get_mapped_clock_class( int_field_type); - if (likely(!clock)) { + if (likely(!clock_class)) { 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); + clock_class_found = g_hash_table_lookup_extended(notit->clock_states, + clock_class, NULL, (gpointer) &clock_state); + if (unlikely(!clock_class_found)) { + const char *clock_class_name = + bt_ctf_clock_class_get_name(clock_class); - PERR("Unknown clock %s mapped to integer encountered in stream\n", - clock_name ? : "NULL"); + PERR("Unknown clock class %s mapped to integer encountered in stream\n", + clock_class_name ? : "NULL"); ret = BT_CTF_BTR_STATUS_ERROR; goto end; } @@ -1308,21 +1519,22 @@ enum bt_ctf_btr_status update_clock(struct bt_ctf_notif_iter *notit, ret = BT_CTF_BTR_STATUS_ENOMEM; goto end; } - g_hash_table_insert(notit->clock_states, bt_get(clock), + g_hash_table_insert(notit->clock_states, bt_get(clock_class), clock_state); } /* Update the clock's state. */ update_clock_state(clock_state, int_field); end: - bt_put(clock); + bt_put(clock_class); 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) +enum bt_ctf_btr_status btr_unsigned_int_common(uint64_t value, + struct bt_ctf_field_type *type, void *data, + struct bt_ctf_field **_field) { enum bt_ctf_btr_status status = BT_CTF_BTR_STATUS_OK; struct bt_ctf_field *field = NULL; @@ -1330,10 +1542,10 @@ enum bt_ctf_btr_status btr_signed_int_cb(int64_t value, struct bt_ctf_notif_iter *notit = data; int ret; - /* create next field */ + /* Create next field */ field = get_next_field(notit); if (!field) { - PERR("Failed to get next field (signed int)\n"); + PERR("Failed to get next field (unsigned int)\n"); status = BT_CTF_BTR_STATUS_ERROR; goto end_no_put; } @@ -1360,21 +1572,64 @@ enum bt_ctf_btr_status btr_signed_int_cb(int64_t value, goto end; } - ret = bt_ctf_field_signed_integer_set_value(int_field, 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); + *_field = int_field; + end: BT_PUT(field); - BT_PUT(int_field); BT_PUT(type); end_no_put: return status; } +static +enum bt_ctf_btr_status btr_timestamp_end_cb(void *value, + struct bt_ctf_field_type *type, void *data) +{ + enum bt_ctf_btr_status status; + struct bt_ctf_field *field = NULL; + struct bt_ctf_notif_iter *notit = data; + + 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); + return status; +} + static enum bt_ctf_btr_status btr_unsigned_int_cb(uint64_t value, struct bt_ctf_field_type *type, void *data) +{ + struct bt_ctf_notif_iter *notit = data; + enum bt_ctf_btr_status status = BT_CTF_BTR_STATUS_OK; + struct bt_ctf_field *field = NULL; + struct field_cb_override *override; + + override = g_hash_table_lookup(notit->field_overrides, + type); + if (unlikely(override)) { + status = override->func(&value, type, override->data); + goto end; + } + + status = btr_unsigned_int_common(value, type, data, &field); + if (status != BT_CTF_BTR_STATUS_OK) { + goto end; + } + + status = update_clock(notit, type, field); + BT_PUT(field); +end: + return status; +} + +static +enum bt_ctf_btr_status btr_signed_int_cb(int64_t value, + struct bt_ctf_field_type *type, void *data) { enum bt_ctf_btr_status status = BT_CTF_BTR_STATUS_OK; struct bt_ctf_field *field = NULL; @@ -1382,10 +1637,10 @@ enum bt_ctf_btr_status btr_unsigned_int_cb(uint64_t value, struct bt_ctf_notif_iter *notit = data; int ret; - /* Create next field */ + /* create next field */ field = get_next_field(notit); if (!field) { - PERR("Failed to get next field (unsigned int)\n"); + PERR("Failed to get next field (signed int)\n"); status = BT_CTF_BTR_STATUS_ERROR; goto end_no_put; } @@ -1412,7 +1667,7 @@ enum bt_ctf_btr_status btr_unsigned_int_cb(uint64_t value, goto end; } - ret = bt_ctf_field_unsigned_integer_set_value(int_field, 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); @@ -1764,21 +2019,23 @@ int set_event_clocks(struct bt_ctf_event *event, { int ret; GHashTableIter iter; - struct bt_ctf_clock *clock; + struct bt_ctf_clock_class *clock_class; uint64_t *clock_state; g_hash_table_iter_init(&iter, notit->clock_states); - while (g_hash_table_iter_next(&iter, (gpointer) &clock, + while (g_hash_table_iter_next(&iter, (gpointer) &clock_class, (gpointer) &clock_state)) { struct bt_ctf_clock_value *clock_value; - clock_value = bt_ctf_clock_value_create(clock, *clock_state); + clock_value = bt_ctf_clock_value_create(clock_class, + *clock_state); if (!clock_value) { ret = -1; goto end; } - ret = bt_ctf_event_set_clock_value(event, clock, clock_value); + ret = bt_ctf_event_set_clock_value(event, clock_class, + clock_value); bt_put(clock_value); if (ret) { goto end; @@ -1901,7 +2158,7 @@ void notify_new_packet(struct bt_ctf_notif_iter *notit, return; } - ret = bt_notification_packet_start_create(notit->packet); + ret = bt_notification_packet_begin_create(notit->packet); if (!ret) { return; } @@ -1948,55 +2205,103 @@ 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; + int clock_class_count, i, ret = 0; - clock_count = bt_ctf_trace_get_clock_count(trace); - if (clock_count <= 0) { + clock_class_count = bt_ctf_trace_get_clock_class_count(trace); + if (clock_class_count <= 0) { ret = -1; goto end; } - for (i = 0; i < clock_count; i++) { - struct bt_ctf_clock *clock; + for (i = 0; i < clock_class_count; i++) { + struct bt_ctf_clock_class *clock_class; - clock = bt_ctf_trace_get_clock(trace, i); - if (!clock) { + clock_class = bt_ctf_trace_get_clock_class(trace, i); + if (!clock_class) { ret = -1; goto end; } - g_hash_table_insert(clock_states, bt_get(clock), NULL); - bt_put(clock); + g_hash_table_insert(clock_states, bt_get(clock_class), NULL); + bt_put(clock_class); } end: return ret; } +static +void init_trace_field_path_cache(struct bt_ctf_trace *trace, + struct trace_field_path_cache *trace_field_path_cache) +{ + int stream_id = -1; + int stream_instance_id = -1; + int i, count; + struct bt_ctf_field_type *packet_header = NULL; + + packet_header = bt_ctf_trace_get_packet_header_type(trace); + if (!packet_header) { + goto end; + } + + if (!bt_ctf_field_type_is_structure(packet_header)) { + goto end; + } + + count = bt_ctf_field_type_structure_get_field_count(packet_header); + if (count < 0) { + goto end; + } + + for (i = 0; (i < count && (stream_id == -1 || stream_instance_id == -1)); i++) { + int ret; + const char *field_name; + + ret = bt_ctf_field_type_structure_get_field(packet_header, + &field_name, NULL, i); + if (ret) { + goto end; + } + + if (stream_id == -1 && !strcmp(field_name, "stream_id")) { + stream_id = i; + } else if (stream_instance_id == -1 && + !strcmp(field_name, "stream_instance_id")) { + stream_instance_id = i; + } + } +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 struct bt_ctf_notif_iter *bt_ctf_notif_iter_create(struct bt_ctf_trace *trace, size_t max_request_sz, @@ -2059,6 +2364,20 @@ struct bt_ctf_notif_iter *bt_ctf_notif_iter_create(struct bt_ctf_trace *trace, bt_ctf_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); + if (!notit->sc_field_path_caches) { + PERR("Failed to create stream class field path caches\n"); + goto error; + } + + notit->field_overrides = g_hash_table_new_full(g_direct_hash, + g_direct_equal, bt_put, g_free); + if (!notit->field_overrides) { + goto error; + } + end: return notit; error: @@ -2073,6 +2392,7 @@ void bt_ctf_notif_iter_destroy(struct bt_ctf_notif_iter *notit) BT_PUT(notit->meta.stream_class); BT_PUT(notit->meta.event_class); BT_PUT(notit->packet); + BT_PUT(notit->cur_timestamp_end); put_all_dscopes(notit); if (notit->stack) { @@ -2086,6 +2406,14 @@ void bt_ctf_notif_iter_destroy(struct bt_ctf_notif_iter *notit) if (notit->clock_states) { g_hash_table_destroy(notit->clock_states); } + + if (notit->sc_field_path_caches) { + g_hash_table_destroy(notit->sc_field_path_caches); + } + + if (notit->field_overrides) { + g_hash_table_destroy(notit->field_overrides); + } g_free(notit); } @@ -2126,6 +2454,22 @@ enum bt_ctf_notif_iter_status bt_ctf_notif_iter_get_next_notification( } goto end; case STATE_EMIT_NOTIF_END_OF_PACKET: + /* Update clock with timestamp_end field. */ + if (notit->cur_timestamp_end) { + enum bt_ctf_btr_status btr_status; + struct bt_ctf_field_type *field_type = + bt_ctf_field_get_type( + notit->cur_timestamp_end); + + btr_status = update_clock(notit, field_type, + notit->cur_timestamp_end); + BT_PUT(field_type); + if (btr_status != BT_CTF_BTR_STATUS_OK) { + status = BT_CTF_NOTIF_ITER_STATUS_ERROR; + goto end; + } + } + PDBG("Emitting end of packet notification\n"); notify_end_of_packet(notit, notification); if (!*notification) {