Print timestamps in text plug-in
[babeltrace.git] / plugins / ctf / common / notif-iter / notif-iter.c
index 37b5da023e81b939ec4b7350f7c839dac02e114f..260d15ee21d4dcd76cd2cfcc37089c16ea922ca4 100644 (file)
@@ -38,6 +38,8 @@
 #include <babeltrace/ctf-ir/stream.h>
 #include <babeltrace/ctf-ir/clock.h>
 #include <babeltrace/ctf-ir/event-class.h>
+#include <babeltrace/plugin/notification/packet.h>
+#include <babeltrace/plugin/notification/event.h>
 #include <babeltrace/ref.h>
 #include <glib.h>
 
@@ -75,9 +77,6 @@ struct stack_entry {
 struct stack {
        /* Entries (struct stack_entry *) (top is last element) */
        GPtrArray *entries;
-
-       /* Link to owner */
-       struct bt_ctf_notif_iter *notit;
 };
 
 /* State */
@@ -144,7 +143,7 @@ struct bt_ctf_notif_iter {
        /* Current state */
        enum state state;
 
-       /* User buffer stuff */
+       /* Current medium buffer data */
        struct {
                /* Last address provided by medium */
                const uint8_t *addr;
@@ -162,7 +161,7 @@ struct bt_ctf_notif_iter {
        /* Binary type reader */
        struct bt_ctf_btr *btr;
 
-       /* Medium stuff */
+       /* Current medium data */
        struct {
                struct bt_ctf_notif_iter_medium_ops medops;
                size_t max_request_sz;
@@ -170,12 +169,18 @@ struct bt_ctf_notif_iter {
        } medium;
 
        /* Current packet size (bits) (-1 if unknown) */
-       size_t cur_packet_size;
+       int64_t cur_packet_size;
 
        /* Current content size (bits) (-1 if unknown) */
-       size_t cur_content_size;
+       int64_t cur_content_size;
+
+       /* bt_ctf_clock to uint64_t. */
+       GHashTable *clock_states;
 };
 
+static
+int bt_ctf_notif_iter_switch_packet(struct bt_ctf_notif_iter *notit);
+
 static
 void stack_entry_free_func(gpointer data)
 {
@@ -200,13 +205,9 @@ struct stack *stack_new(struct bt_ctf_notif_iter *notit)
                goto error;
        }
 
-       stack->notit = notit;
-
        return stack;
-
 error:
        g_free(stack);
-
        return NULL;
 }
 
@@ -223,14 +224,11 @@ int stack_push(struct stack *stack, struct bt_ctf_field *base)
 {
        int ret = 0;
        struct stack_entry *entry;
-       struct bt_ctf_notif_iter *notit;
 
        assert(stack);
        assert(base);
-       notit = stack->notit;
        entry = g_new0(struct stack_entry, 1);
        if (!entry) {
-               PERR("Cannot create new stack entry\n");
                ret = -1;
                goto end;
        }
@@ -343,7 +341,8 @@ bool buf_has_enough_bits(struct bt_ctf_notif_iter *notit, size_t sz)
 }
 
 static
-enum bt_ctf_notif_iter_status request_medium_bytes(struct bt_ctf_notif_iter *notit)
+enum bt_ctf_notif_iter_status request_medium_bytes(
+               struct bt_ctf_notif_iter *notit)
 {
        uint8_t *buffer_addr;
        size_t buffer_sz;
@@ -445,15 +444,15 @@ enum bt_ctf_notif_iter_status read_dscope_continue_state(
        }
 
        consumed_bits = bt_ctf_btr_continue(notit->btr, notit->buf.addr,
-               notit->buf.sz, &btr_status);
+                       notit->buf.sz, &btr_status);
 
        switch (btr_status) {
        case BT_CTF_BTR_STATUS_OK:
-               /* Type was read completely */
+               /* Type was read completely. */
                notit->state = done_state;
                break;
        case BT_CTF_BTR_STATUS_EOF:
-               /* Stay in this continue state */
+               /* Stay in this continue state. */
                break;
        default:
                PERR("Binary type reader failed to continue\n");
@@ -461,9 +460,8 @@ enum bt_ctf_notif_iter_status read_dscope_continue_state(
                goto end;
        }
 
-       /* Consume bits now since we know we're not in an error state */
+       /* Consume bits now since we know we're not in an error state. */
        buf_consume_bits(notit, consumed_bits);
-
 end:
        return status;
 }
@@ -489,33 +487,30 @@ static
 enum bt_ctf_notif_iter_status read_packet_header_begin_state(
                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;
+       enum bt_ctf_notif_iter_status ret = BT_CTF_NOTIF_ITER_STATUS_OK;
 
-       /* Reset all dynamic scopes since we're reading a new packet */
-       put_all_dscopes(notit);
-       BT_PUT(notit->packet);
-       BT_PUT(notit->meta.stream_class);
-       BT_PUT(notit->meta.event_class);
+       if (bt_ctf_notif_iter_switch_packet(notit)) {
+               ret = BT_CTF_NOTIF_ITER_STATUS_ERROR;
+               goto end;
+       }
 
-       /* Packet header type is common to the whole trace */
+       /* Packet header type is common to the whole trace. */
        packet_header_type = bt_ctf_trace_get_packet_header_type(
-               notit->meta.trace);
+                       notit->meta.trace);
        if (!packet_header_type) {
                PERR("Failed to retrieve trace's packet header type\n");
-               status = BT_CTF_NOTIF_ITER_STATUS_ERROR;
+               ret = BT_CTF_NOTIF_ITER_STATUS_ERROR;
                goto end;
        }
 
-       status = read_dscope_begin_state(notit, packet_header_type,
-               STATE_AFTER_TRACE_PACKET_HEADER,
-               STATE_DSCOPE_TRACE_PACKET_HEADER_CONTINUE,
-               &notit->dscopes.trace_packet_header);
-
+       ret = read_dscope_begin_state(notit, packet_header_type,
+                       STATE_AFTER_TRACE_PACKET_HEADER,
+                       STATE_DSCOPE_TRACE_PACKET_HEADER_CONTINUE,
+                       &notit->dscopes.trace_packet_header);
 end:
        BT_PUT(packet_header_type);
-
-       return status;
+       return ret;
 }
 
 static
@@ -523,19 +518,21 @@ enum bt_ctf_notif_iter_status read_packet_header_continue_state(
                struct bt_ctf_notif_iter *notit)
 {
        return read_dscope_continue_state(notit,
-               STATE_AFTER_TRACE_PACKET_HEADER);
+                       STATE_AFTER_TRACE_PACKET_HEADER);
 }
 
 static inline
 bool is_struct_type(struct bt_ctf_field_type *field_type)
 {
-       return bt_ctf_field_type_get_type_id(field_type) == BT_CTF_TYPE_ID_STRUCT;
+       return bt_ctf_field_type_get_type_id(field_type) ==
+                       BT_CTF_TYPE_ID_STRUCT;
 }
 
 static inline
 bool is_variant_type(struct bt_ctf_field_type *field_type)
 {
-       return bt_ctf_field_type_get_type_id(field_type) == BT_CTF_TYPE_ID_VARIANT;
+       return bt_ctf_field_type_get_type_id(field_type) ==
+                       BT_CTF_TYPE_ID_VARIANT;
 }
 
 static inline
@@ -548,7 +545,7 @@ enum bt_ctf_notif_iter_status set_current_stream_class(struct bt_ctf_notif_iter
 
        /* Is there any "stream_id" field in the packet header? */
        packet_header_type = bt_ctf_trace_get_packet_header_type(
-               notit->meta.trace);
+                       notit->meta.trace);
        if (!packet_header_type) {
                PERR("Failed to retrieve trace's packet header type\n");
                status = BT_CTF_NOTIF_ITER_STATUS_ERROR;
@@ -559,8 +556,8 @@ enum bt_ctf_notif_iter_status set_current_stream_class(struct bt_ctf_notif_iter
 
        // TODO: optimalize!
        stream_id_field_type =
-               bt_ctf_field_type_structure_get_field_type_by_name(
-                       packet_header_type, "stream_id");
+                       bt_ctf_field_type_structure_get_field_type_by_name(
+                               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;
@@ -570,24 +567,22 @@ enum bt_ctf_notif_iter_status set_current_stream_class(struct bt_ctf_notif_iter
 
                // TODO: optimalize!
                stream_id_field = bt_ctf_field_structure_get_field(
-                       notit->dscopes.trace_packet_header, "stream_id");
+                               notit->dscopes.trace_packet_header, "stream_id");
                assert(stream_id_field);
                ret = bt_ctf_field_unsigned_integer_get_value(
-                       stream_id_field, &stream_id);
+                               stream_id_field, &stream_id);
                assert(!ret);
                BT_PUT(stream_id_field);
        } else {
                /* Only one stream: pick the first stream class */
                assert(bt_ctf_trace_get_stream_class_count(
-                       notit->meta.trace) == 1);
+                               notit->meta.trace) == 1);
                stream_id = 0;
        }
 
        BT_PUT(notit->meta.stream_class);
-
-       // TODO: get by ID
-       notit->meta.stream_class = bt_ctf_trace_get_stream_class(
-               notit->meta.trace, stream_id);
+       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",
                        stream_id);
@@ -625,7 +620,7 @@ enum bt_ctf_notif_iter_status read_packet_context_begin_state(
 
        assert(notit->meta.stream_class);
        packet_context_type = bt_ctf_stream_class_get_packet_context_type(
-               notit->meta.stream_class);
+                       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;
@@ -633,13 +628,12 @@ enum bt_ctf_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,
-               &notit->dscopes.stream_packet_context);
+                       STATE_AFTER_STREAM_PACKET_CONTEXT,
+                       STATE_DSCOPE_STREAM_PACKET_CONTEXT_CONTINUE,
+                       &notit->dscopes.stream_packet_context);
 
 end:
        BT_PUT(packet_context_type);
-
        return status;
 }
 
@@ -648,10 +642,10 @@ enum bt_ctf_notif_iter_status read_packet_context_continue_state(
                struct bt_ctf_notif_iter *notit)
 {
        return read_dscope_continue_state(notit,
-               STATE_AFTER_STREAM_PACKET_CONTEXT);
+                       STATE_AFTER_STREAM_PACKET_CONTEXT);
 }
 
-static inline
+static
 enum bt_ctf_notif_iter_status set_current_packet_content_sizes(
                struct bt_ctf_notif_iter *notit)
 {
@@ -662,16 +656,15 @@ enum bt_ctf_notif_iter_status set_current_packet_content_sizes(
 
        assert(notit->dscopes.stream_packet_context);
 
-       // TODO: optimalize!
        packet_size_field = bt_ctf_field_structure_get_field(
-               notit->dscopes.stream_packet_context, "packet_size");
+                       notit->dscopes.stream_packet_context, "packet_size");
        content_size_field = bt_ctf_field_structure_get_field(
-               notit->dscopes.stream_packet_context, "content_size");
+                       notit->dscopes.stream_packet_context, "content_size");
        if (packet_size_field) {
                int ret = bt_ctf_field_unsigned_integer_get_value(
-                       packet_size_field, &packet_size);
-               assert(!ret);
+                               packet_size_field, &packet_size);
 
+               assert(!ret);
                if (packet_size == 0) {
                        PERR("Decoded packet size is 0\n");
                        status = BT_CTF_NOTIF_ITER_STATUS_ERROR;
@@ -682,9 +675,11 @@ enum bt_ctf_notif_iter_status set_current_packet_content_sizes(
                        goto end;
                }
        }
+
        if (content_size_field) {
                int ret = bt_ctf_field_unsigned_integer_get_value(
                        content_size_field, &content_size);
+
                assert(!ret);
        } else {
                content_size = packet_size;
@@ -692,11 +687,9 @@ enum bt_ctf_notif_iter_status set_current_packet_content_sizes(
 
        notit->cur_packet_size = packet_size;
        notit->cur_content_size = content_size;
-
 end:
        BT_PUT(packet_size_field);
        BT_PUT(content_size_field);
-
        return status;
 }
 
@@ -730,9 +723,9 @@ enum bt_ctf_notif_iter_status read_event_header_begin_state(
                } else if (packet_at(notit) > notit->cur_content_size) {
                        /* That's not supposed to happen */
                        PERR("Cursor passed packet's content size:\n");
-                       PERR("  Decoded content size: %zu\n",
+                       PERR("\tDecoded content size: %zu\n",
                                notit->cur_content_size);
-                       PERR("  Cursor position:      %zu\n", packet_at(notit));
+                       PERR("\tCursor position:      %zu\n", packet_at(notit));
                        status = BT_CTF_NOTIF_ITER_STATUS_ERROR;
                        goto end;
                }
@@ -751,7 +744,6 @@ enum bt_ctf_notif_iter_status read_event_header_begin_state(
                STATE_AFTER_STREAM_EVENT_HEADER,
                STATE_DSCOPE_STREAM_EVENT_HEADER_CONTINUE,
                &notit->dscopes.stream_event_header);
-
 end:
        BT_PUT(event_header_type);
 
@@ -899,12 +891,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");
@@ -1124,6 +1110,19 @@ 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)
 {
        assert(notit);
@@ -1141,6 +1140,43 @@ void bt_ctf_notif_iter_reset(struct bt_ctf_notif_iter *notit)
        notit->cur_packet_size = -1;
 }
 
+static
+int bt_ctf_notif_iter_switch_packet(struct bt_ctf_notif_iter *notit)
+{
+       int ret = 0;
+
+       assert(notit);
+       stack_clear(notit->stack);
+       BT_PUT(notit->meta.stream_class);
+       BT_PUT(notit->meta.event_class);
+       BT_PUT(notit->packet);
+       put_all_dscopes(notit);
+
+       /*
+        * Adjust current buffer so that addr points to the beginning of the new
+        * packet.
+        */
+       if (notit->buf.addr) {
+               size_t consumed_bytes = (size_t) (notit->buf.at / CHAR_BIT);
+
+               /* Packets are assumed to start on a byte frontier. */
+               if (notit->buf.at % CHAR_BIT) {
+                       ret = -1;
+                       goto end;
+               }
+
+               notit->buf.addr += consumed_bytes;
+               notit->buf.sz -= consumed_bytes;
+               notit->buf.at = 0;
+               notit->buf.packet_offset = 0;
+       }
+
+       notit->cur_content_size = -1;
+       notit->cur_packet_size = -1;
+end:
+       return ret;
+}
+
 static
 struct bt_ctf_field *get_next_field(struct bt_ctf_notif_iter *notit)
 {
@@ -1177,12 +1213,113 @@ 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);
 
        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)
@@ -1198,18 +1335,22 @@ enum bt_ctf_btr_status btr_signed_int_cb(int64_t value,
        if (!field) {
                PERR("Failed to get next field (signed int)\n");
                status = BT_CTF_BTR_STATUS_ERROR;
-               goto end;
+               goto end_no_put;
        }
 
        switch(bt_ctf_field_type_get_type_id(type)) {
        case BT_CTF_TYPE_ID_INTEGER:
                /* Integer field is created field */
                BT_MOVE(int_field, field);
+               bt_get(type);
                break;
        case BT_CTF_TYPE_ID_ENUM:
                int_field = bt_ctf_field_enumeration_get_container(field);
+               type = bt_ctf_field_get_type(int_field);
                break;
        default:
+               assert(0);
+               type = NULL;
                break;
        }
 
@@ -1222,11 +1363,12 @@ enum bt_ctf_btr_status btr_signed_int_cb(int64_t value,
        ret = bt_ctf_field_signed_integer_set_value(int_field, value);
        assert(!ret);
        stack_top(notit->stack)->index++;
-
+       status = update_clock(notit, type, int_field);
 end:
        BT_PUT(field);
        BT_PUT(int_field);
-
+       BT_PUT(type);
+end_no_put:
        return status;
 }
 
@@ -1245,18 +1387,22 @@ enum bt_ctf_btr_status btr_unsigned_int_cb(uint64_t value,
        if (!field) {
                PERR("Failed to get next field (unsigned int)\n");
                status = BT_CTF_BTR_STATUS_ERROR;
-               goto end;
+               goto end_no_put;
        }
 
        switch(bt_ctf_field_type_get_type_id(type)) {
        case BT_CTF_TYPE_ID_INTEGER:
                /* Integer field is created field */
                BT_MOVE(int_field, field);
+               bt_get(type);
                break;
        case BT_CTF_TYPE_ID_ENUM:
                int_field = bt_ctf_field_enumeration_get_container(field);
+               type = bt_ctf_field_get_type(int_field);
                break;
        default:
+               assert(0);
+               type = NULL;
                break;
        }
 
@@ -1269,11 +1415,12 @@ enum bt_ctf_btr_status btr_unsigned_int_cb(uint64_t value,
        ret = bt_ctf_field_unsigned_integer_set_value(int_field, value);
        assert(!ret);
        stack_top(notit->stack)->index++;
-
+       status = update_clock(notit, type, int_field);
 end:
        BT_PUT(field);
        BT_PUT(int_field);
-
+       BT_PUT(type);
+end_no_put:
        return status;
 }
 
@@ -1333,6 +1480,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);
 
@@ -1519,7 +1678,7 @@ int64_t btr_get_sequence_length_cb(struct bt_ctf_field_type *type, void *data)
        int iret;
        struct bt_ctf_field_path *field_path;
        struct bt_ctf_notif_iter *notit = data;
-       struct bt_ctf_field *field = NULL;
+       struct bt_ctf_field *length_field = NULL;
        uint64_t length;
 
        field_path = bt_ctf_field_type_sequence_get_length_field_path(type);
@@ -1527,20 +1686,25 @@ int64_t btr_get_sequence_length_cb(struct bt_ctf_field_type *type, void *data)
                goto end;
        }
 
-       field = resolve_field(notit, field_path);
-       if (!field) {
+       length_field = resolve_field(notit, field_path);
+       if (!length_field) {
                goto end;
        }
 
-       iret = bt_ctf_field_unsigned_integer_get_value(field, &length);
+       iret = bt_ctf_field_unsigned_integer_get_value(length_field, &length);
        if (iret) {
                goto end;
        }
 
+       iret = bt_ctf_field_sequence_set_length(stack_top(notit->stack)->base,
+                       length_field);
+       if (iret) {
+               goto end;
+       }
        ret = (int64_t) length;
 
 end:
-       BT_PUT(field);
+       BT_PUT(length_field);
        BT_PUT(field_path);
 
        return ret;
@@ -1589,22 +1753,55 @@ 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 struct bt_ctf_event *create_event(struct bt_ctf_notif_iter *notit)
+static
+int set_event_clocks(struct bt_ctf_event *event,
+               struct bt_ctf_notif_iter *notit)
 {
-       struct bt_ctf_event *event;
        int ret;
+       GHashTableIter iter;
+       struct bt_ctf_clock *clock;
+       uint64_t *clock_state;
+
+       g_hash_table_iter_init(&iter, notit->clock_states);
 
-       /* Create event object */
+       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)
+{
+       int ret;
+       struct bt_ctf_event *event;
+
+       /* Create event object. */
        event = bt_ctf_event_create(notit->meta.event_class);
        if (!event) {
                goto error;
        }
 
-       /* Set header, stream event context, context, and payload fields */
+       /* Set header, stream event context, context, and payload fields. */
        ret = bt_ctf_event_set_header(event,
                notit->dscopes.stream_event_header);
        if (ret) {
@@ -1629,7 +1826,12 @@ static struct bt_ctf_event *create_event(struct bt_ctf_notif_iter *notit)
                goto error;
        }
 
-       /* Associate with current packet */
+       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);
        if (ret) {
@@ -1637,15 +1839,14 @@ static struct bt_ctf_event *create_event(struct bt_ctf_notif_iter *notit)
        }
 
        goto end;
-
 error:
        BT_PUT(event);
-
 end:
        return event;
 }
 
-static void create_packet(struct bt_ctf_notif_iter *notit)
+static
+void create_packet(struct bt_ctf_notif_iter *notit)
 {
        int ret;
        struct bt_ctf_stream *stream = NULL;
@@ -1653,7 +1854,7 @@ static void create_packet(struct bt_ctf_notif_iter *notit)
 
        /* Ask the user for the stream */
        stream = notit->medium.medops.get_stream(notit->meta.stream_class,
-               notit->medium.data);
+                       notit->medium.data);
        if (!stream) {
                goto error;
        }
@@ -1667,7 +1868,7 @@ static void create_packet(struct bt_ctf_notif_iter *notit)
        /* Set packet's context and header fields */
        if (notit->dscopes.trace_packet_header) {
                ret = bt_ctf_packet_set_header(packet,
-                       notit->dscopes.trace_packet_header);
+                               notit->dscopes.trace_packet_header);
                if (ret) {
                        goto error;
                }
@@ -1675,142 +1876,134 @@ static void create_packet(struct bt_ctf_notif_iter *notit)
 
        if (notit->dscopes.stream_packet_context) {
                ret = bt_ctf_packet_set_context(packet,
-                       notit->dscopes.stream_packet_context);
+                               notit->dscopes.stream_packet_context);
                if (ret) {
                        goto error;
                }
        }
 
        goto end;
-
 error:
        BT_PUT(packet);
-
 end:
        BT_MOVE(notit->packet, packet);
 }
 
-static void notify_new_packet(struct bt_ctf_notif_iter *notit,
-               struct bt_ctf_notif_iter_notif **notification)
+static
+void notify_new_packet(struct bt_ctf_notif_iter *notit,
+               struct bt_notification **notification)
 {
-       struct bt_ctf_notif_iter_notif_new_packet *rnotif;
+       struct bt_notification *ret;
 
-       rnotif = g_new0(struct bt_ctf_notif_iter_notif_new_packet, 1);
-       if (!rnotif) {
-               goto error;
-       }
-
-       rnotif->base.type = BT_CTF_NOTIF_ITER_NOTIF_NEW_PACKET;
-
-       /* Create packet */
+       /* Initialize the iterator's current packet */
        create_packet(notit);
        if (!notit->packet) {
-               goto error;
+               return;
        }
 
-       rnotif->packet = bt_get(notit->packet);
-       *notification = (struct bt_ctf_notif_iter_notif *) rnotif;
-       return;
-
-error:
-       bt_ctf_notif_iter_notif_destroy(rnotif);
+       ret = bt_notification_packet_start_create(notit->packet);
+       if (!ret) {
+               return;
+       }
+       *notification = ret;
 }
 
-static void notify_end_of_packet(struct bt_ctf_notif_iter *notit,
-               struct bt_ctf_notif_iter_notif **notification)
+static
+void notify_end_of_packet(struct bt_ctf_notif_iter *notit,
+               struct bt_notification **notification)
 {
-       struct bt_ctf_notif_iter_notif_end_of_packet *rnotif;
-
-       rnotif = g_new0(struct bt_ctf_notif_iter_notif_end_of_packet, 1);
-       if (!rnotif) {
-               goto error;
-       }
+       struct bt_notification *ret;
 
-       rnotif->base.type = BT_CTF_NOTIF_ITER_NOTIF_END_OF_PACKET;
-
-       /* Create packet */
-       create_packet(notit);
        if (!notit->packet) {
-               goto error;
+               return;
        }
 
-       rnotif->packet = bt_get(notit->packet);
-       *notification = (struct bt_ctf_notif_iter_notif *) rnotif;
-       return;
-
-error:
-       bt_ctf_notif_iter_notif_destroy(rnotif);
+       ret = bt_notification_packet_end_create(notit->packet);
+       if (!ret) {
+               return;
+       }
+       BT_PUT(notit->packet);
+       *notification = ret;
 }
 
-static void notify_event(struct bt_ctf_notif_iter *notit,
-               struct bt_ctf_notif_iter_notif **notification)
+static
+void notify_event(struct bt_ctf_notif_iter *notit,
+               struct bt_notification **notification)
 {
-       struct bt_ctf_notif_iter_notif_event *rnotif;
-       struct bt_ctf_event *event = NULL;
+       struct bt_ctf_event *event;
+       struct bt_notification *ret = NULL;
 
-       rnotif = g_new0(struct bt_ctf_notif_iter_notif_event, 1);
-       if (!rnotif) {
-               goto error;
+       /* Create event */
+       event = create_event(notit);
+       if (!event) {
+               goto end;
+       }
+
+       ret = bt_notification_event_create(event);
+       if (!ret) {
+               goto end;
        }
+       *notification = ret;
+end:
+       BT_PUT(event);
+}
 
-       rnotif->base.type = BT_CTF_NOTIF_ITER_NOTIF_EVENT;
+static
+void notify_eos(struct bt_ctf_notif_iter *notit,
+               struct bt_notification **notification)
+{
+       struct bt_ctf_event *event;
+       struct bt_notification *ret = NULL;
 
        /* Create event */
        event = create_event(notit);
        if (!event) {
-               goto error;
+               goto end;
        }
 
-       BT_MOVE(rnotif->event, event);
-       *notification = (struct bt_ctf_notif_iter_notif *) rnotif;
-       return;
-
-error:
+       ret = bt_notification_stream_end_create(event);
+       if (!ret) {
+               goto end;
+       }
+       *notification = ret;
+end:
        BT_PUT(event);
-       bt_ctf_notif_iter_notif_destroy(rnotif);
 }
 
-void bt_ctf_notif_iter_notif_destroy(void *vnotif)
+static
+int init_clock_states(GHashTable *clock_states, struct bt_ctf_trace *trace)
 {
-       struct bt_ctf_notif_iter_notif *notif = vnotif;
-
-       switch (notif->type) {
-       case BT_CTF_NOTIF_ITER_NOTIF_NEW_PACKET:
-       {
-               struct bt_ctf_notif_iter_notif_new_packet *rnotif =
-                       (struct bt_ctf_notif_iter_notif_new_packet *) notif;
+       int clock_count, i, ret = 0;
 
-               BT_PUT(rnotif->packet);
-               break;
+       clock_count = bt_ctf_trace_get_clock_count(trace);
+       if (clock_count <= 0) {
+               ret = -1;
+               goto end;
        }
-       case BT_CTF_NOTIF_ITER_NOTIF_END_OF_PACKET:
-       {
-               struct bt_ctf_notif_iter_notif_end_of_packet *rnotif =
-                       (struct bt_ctf_notif_iter_notif_end_of_packet *) notif;
 
-               BT_PUT(rnotif->packet);
-               break;
-       }
-       case BT_CTF_NOTIF_ITER_NOTIF_EVENT:
-       {
-               struct bt_ctf_notif_iter_notif_event *rnotif =
-                       (struct bt_ctf_notif_iter_notif_event *) notif;
+       for (i = 0; i < clock_count; i++) {
+               struct bt_ctf_clock *clock;
 
-               BT_PUT(rnotif->event);
-               break;
-       }
-       default:
-               assert(false);
-       }
+               clock = bt_ctf_trace_get_clock(trace, i);
+               if (!clock) {
+                       ret = -1;
+                       goto end;
+               }
 
-       g_free(notif);
+               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 = {
@@ -1836,9 +2029,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;
@@ -1846,23 +2048,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)
@@ -1881,12 +2083,15 @@ 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);
 }
 
 enum bt_ctf_notif_iter_status bt_ctf_notif_iter_get_next_notification(
                struct bt_ctf_notif_iter *notit,
-               struct bt_ctf_notif_iter_notif **notification)
+               struct bt_notification **notification)
 {
        enum bt_ctf_notif_iter_status status = BT_CTF_NOTIF_ITER_STATUS_OK;
 
@@ -1897,10 +2102,10 @@ enum bt_ctf_notif_iter_status bt_ctf_notif_iter_get_next_notification(
                status = handle_state(notit);
                if (status != BT_CTF_NOTIF_ITER_STATUS_OK) {
                        if (status == BT_CTF_NOTIF_ITER_STATUS_EOF) {
-                               PDBG("Medium operation reported end of file\n");
+                               PDBG("Medium operation reported end of stream\n");
                        } else {
                                PERR("Failed to handle state:\n");
-                               PERR("  State: %d\n", notit->state);
+                               PERR("\tState: %d\n", notit->state);
                        }
                        goto end;
                }
This page took 0.055775 seconds and 4 git commands to generate.