Fix compiler warnings
[babeltrace.git] / plugins / ctf / common / notif-iter / notif-iter.c
index 9c6134f9422317e8a77d82240ce1ef854bf0f588..692ed6a93bae231a4089f67a81001450d03c4cfb 100644 (file)
@@ -40,6 +40,7 @@
 #include <babeltrace/ctf-ir/event-class.h>
 #include <babeltrace/plugin/notification/packet.h>
 #include <babeltrace/plugin/notification/event.h>
+#include <babeltrace/plugin/notification/stream.h>
 #include <babeltrace/ref.h>
 #include <glib.h>
 
@@ -173,6 +174,9 @@ struct bt_ctf_notif_iter {
 
        /* Current content size (bits) (-1 if unknown) */
        int64_t cur_content_size;
+
+       /* bt_ctf_clock to uint64_t. */
+       GHashTable *clock_states;
 };
 
 static
@@ -496,8 +500,7 @@ enum bt_ctf_notif_iter_status read_packet_header_begin_state(
        packet_header_type = bt_ctf_trace_get_packet_header_type(
                        notit->meta.trace);
        if (!packet_header_type) {
-               PERR("Failed to retrieve trace's packet header type\n");
-               ret = BT_CTF_NOTIF_ITER_STATUS_ERROR;
+               notit->state = STATE_AFTER_TRACE_PACKET_HEADER;
                goto end;
        }
 
@@ -533,7 +536,8 @@ bool is_variant_type(struct bt_ctf_field_type *field_type)
 }
 
 static inline
-enum bt_ctf_notif_iter_status set_current_stream_class(struct bt_ctf_notif_iter *notit)
+enum bt_ctf_notif_iter_status set_current_stream_class(
+               struct bt_ctf_notif_iter *notit)
 {
        enum bt_ctf_notif_iter_status status = BT_CTF_NOTIF_ITER_STATUS_OK;
        struct bt_ctf_field_type *packet_header_type;
@@ -578,9 +582,7 @@ enum bt_ctf_notif_iter_status set_current_stream_class(struct bt_ctf_notif_iter
        }
 
        BT_PUT(notit->meta.stream_class);
-
-       // TODO: get by ID
-       notit->meta.stream_class = bt_ctf_trace_get_stream_class(
+       notit->meta.stream_class = bt_ctf_trace_get_stream_class_by_id(
                        notit->meta.trace, stream_id);
        if (!notit->meta.stream_class) {
                PERR("Cannot find stream class with ID %" PRIu64 "\n",
@@ -621,8 +623,7 @@ enum bt_ctf_notif_iter_status read_packet_context_begin_state(
        packet_context_type = bt_ctf_stream_class_get_packet_context_type(
                        notit->meta.stream_class);
        if (!packet_context_type) {
-               PERR("Failed to retrieve stream class's packet context\n");
-               status = BT_CTF_NOTIF_ITER_STATUS_ERROR;
+               notit->state = STATE_AFTER_STREAM_PACKET_CONTEXT;
                goto end;
        }
 
@@ -733,8 +734,7 @@ enum bt_ctf_notif_iter_status read_event_header_begin_state(
        event_header_type = bt_ctf_stream_class_get_event_header_type(
                notit->meta.stream_class);
        if (!event_header_type) {
-               PERR("Failed to retrieve stream class's event header type\n");
-               status = BT_CTF_NOTIF_ITER_STATUS_ERROR;
+               notit->state = STATE_AFTER_STREAM_EVENT_HEADER;
                goto end;
        }
 
@@ -890,12 +890,6 @@ enum bt_ctf_notif_iter_status after_event_header_state(
 {
        enum bt_ctf_notif_iter_status status;
 
-       status = set_current_packet_content_sizes(notit);
-       if (status != BT_CTF_NOTIF_ITER_STATUS_OK) {
-               PERR("Failed to set current packet and content sizes\n");
-               goto end;
-       }
-
        status = set_current_event_class(notit);
        if (status != BT_CTF_NOTIF_ITER_STATUS_OK) {
                PERR("Failed to set current event class\n");
@@ -918,8 +912,7 @@ enum bt_ctf_notif_iter_status read_stream_event_context_begin_state(
        stream_event_context_type = bt_ctf_stream_class_get_event_context_type(
                notit->meta.stream_class);
        if (!stream_event_context_type) {
-               PERR("Failed to retrieve stream class's event context type\n");
-               status = BT_CTF_NOTIF_ITER_STATUS_ERROR;
+               notit->state = STATE_DSCOPE_EVENT_CONTEXT_BEGIN;
                goto end;
        }
 
@@ -952,11 +945,9 @@ enum bt_ctf_notif_iter_status read_event_context_begin_state(
        event_context_type = bt_ctf_event_class_get_context_type(
                notit->meta.event_class);
        if (!event_context_type) {
-               PERR("Failed to retrieve event class's context type\n");
-               status = BT_CTF_NOTIF_ITER_STATUS_ERROR;
+               notit->state = STATE_DSCOPE_EVENT_PAYLOAD_BEGIN;
                goto end;
        }
-
        status = read_dscope_begin_state(notit, event_context_type,
                STATE_DSCOPE_EVENT_PAYLOAD_BEGIN,
                STATE_DSCOPE_EVENT_CONTEXT_CONTINUE,
@@ -986,8 +977,7 @@ enum bt_ctf_notif_iter_status read_event_payload_begin_state(
        event_payload_type = bt_ctf_event_class_get_payload_type(
                notit->meta.event_class);
        if (!event_payload_type) {
-               PERR("Failed to retrieve event class's payload type\n");
-               status = BT_CTF_NOTIF_ITER_STATUS_ERROR;
+               notit->state = STATE_EMIT_NOTIF_EVENT;
                goto end;
        }
 
@@ -1228,6 +1218,103 @@ end:
        return next_field;
 }
 
+static
+void update_clock_state(uint64_t *state,
+               struct bt_ctf_field *value_field)
+{
+       struct bt_ctf_field_type *value_type = NULL;
+       uint64_t requested_new_value;
+       uint64_t requested_new_value_mask;
+       uint64_t cur_value_masked;
+       int requested_new_value_size;
+       int ret;
+
+       value_type = bt_ctf_field_get_type(value_field);
+       assert(value_type);
+
+       requested_new_value_size =
+                       bt_ctf_field_type_integer_get_size(value_type);
+       assert(requested_new_value_size > 0);
+
+       ret = bt_ctf_field_unsigned_integer_get_value(value_field,
+                       &requested_new_value);
+       assert(!ret);
+
+       /*
+        * Special case for a 64-bit new value, which is the limit
+        * of a clock value as of this version: overwrite the
+        * current value directly.
+        */
+       if (requested_new_value_size == 64) {
+               *state = requested_new_value;
+               goto end;
+       }
+
+       requested_new_value_mask = (1ULL << requested_new_value_size) - 1;
+       cur_value_masked = *state & requested_new_value_mask;
+
+       if (requested_new_value < cur_value_masked) {
+               /*
+                * It looks like a wrap happened on the number of bits
+                * of the requested new value. Assume that the clock
+                * value wrapped only one time.
+                */
+               *state += requested_new_value_mask + 1;
+       }
+
+       /* Clear the low bits of the current clock value. */
+       *state &= ~requested_new_value_mask;
+
+       /* Set the low bits of the current clock value. */
+       *state |= requested_new_value;
+end:
+       bt_put(value_type);
+}
+
+static
+enum bt_ctf_btr_status update_clock(struct bt_ctf_notif_iter *notit,
+               struct bt_ctf_field_type *int_field_type,
+               struct bt_ctf_field *int_field)
+{
+       gboolean clock_found;
+       uint64_t *clock_state;
+       enum bt_ctf_btr_status ret = BT_CTF_BTR_STATUS_OK;
+       struct bt_ctf_clock *clock = bt_ctf_field_type_integer_get_mapped_clock(
+                       int_field_type);
+
+       if (likely(!clock)) {
+               goto end_no_clock;
+       }
+
+       clock_found = g_hash_table_lookup_extended(notit->clock_states,
+                       clock, NULL, (gpointer) &clock_state);
+       if (unlikely(!clock_found)) {
+               const char *clock_name = bt_ctf_clock_get_name(clock);
+
+               PERR("Unknown clock %s mapped to integer encountered in stream\n",
+                               clock_name ? : "NULL");
+               ret = BT_CTF_BTR_STATUS_ERROR;
+               goto end;
+       }
+
+       if (unlikely(!clock_state)) {
+               clock_state = g_new0(uint64_t, 1);
+               if (!clock_state) {
+                       ret = BT_CTF_BTR_STATUS_ENOMEM;
+                       goto end;
+               }
+               g_hash_table_insert(notit->clock_states, bt_get(clock),
+                               clock_state);
+       }
+
+       /* Update the clock's state. */
+       update_clock_state(clock_state, int_field);
+end:
+       bt_put(clock);
+end_no_clock:
+       return ret;
+}
+
 static
 enum bt_ctf_btr_status btr_signed_int_cb(int64_t value,
                struct bt_ctf_field_type *type, void *data)
@@ -1243,18 +1330,22 @@ enum bt_ctf_btr_status btr_signed_int_cb(int64_t value,
        if (!field) {
                PERR("Failed to get next field (signed int)\n");
                status = BT_CTF_BTR_STATUS_ERROR;
-               goto end;
+               goto end_no_put;
        }
 
        switch(bt_ctf_field_type_get_type_id(type)) {
        case BT_CTF_TYPE_ID_INTEGER:
                /* Integer field is created field */
                BT_MOVE(int_field, field);
+               bt_get(type);
                break;
        case BT_CTF_TYPE_ID_ENUM:
                int_field = bt_ctf_field_enumeration_get_container(field);
+               type = bt_ctf_field_get_type(int_field);
                break;
        default:
+               assert(0);
+               type = NULL;
                break;
        }
 
@@ -1267,11 +1358,12 @@ enum bt_ctf_btr_status btr_signed_int_cb(int64_t value,
        ret = bt_ctf_field_signed_integer_set_value(int_field, value);
        assert(!ret);
        stack_top(notit->stack)->index++;
-
+       status = update_clock(notit, type, int_field);
 end:
        BT_PUT(field);
        BT_PUT(int_field);
-
+       BT_PUT(type);
+end_no_put:
        return status;
 }
 
@@ -1290,18 +1382,22 @@ enum bt_ctf_btr_status btr_unsigned_int_cb(uint64_t value,
        if (!field) {
                PERR("Failed to get next field (unsigned int)\n");
                status = BT_CTF_BTR_STATUS_ERROR;
-               goto end;
+               goto end_no_put;
        }
 
        switch(bt_ctf_field_type_get_type_id(type)) {
        case BT_CTF_TYPE_ID_INTEGER:
                /* Integer field is created field */
                BT_MOVE(int_field, field);
+               bt_get(type);
                break;
        case BT_CTF_TYPE_ID_ENUM:
                int_field = bt_ctf_field_enumeration_get_container(field);
+               type = bt_ctf_field_get_type(int_field);
                break;
        default:
+               assert(0);
+               type = NULL;
                break;
        }
 
@@ -1314,11 +1410,12 @@ enum bt_ctf_btr_status btr_unsigned_int_cb(uint64_t value,
        ret = bt_ctf_field_unsigned_integer_set_value(int_field, value);
        assert(!ret);
        stack_top(notit->stack)->index++;
-
+       status = update_clock(notit, type, int_field);
 end:
        BT_PUT(field);
        BT_PUT(int_field);
-
+       BT_PUT(type);
+end_no_put:
        return status;
 }
 
@@ -1378,6 +1475,18 @@ enum bt_ctf_btr_status btr_string_begin_cb(
                goto end;
        }
 
+       /*
+        * Initialize string field payload to an empty string since in the
+        * case of a length 0 string the btr_string_cb won't be called and
+        * we will end up with an unset string payload.
+        */
+       ret = bt_ctf_field_string_set_value(field, "");
+       if (ret) {
+               PERR("Failed to initialize string field\n");
+               status = BT_CTF_BTR_STATUS_ERROR;
+               goto end;
+       }
+
 end:
        BT_PUT(field);
 
@@ -1639,10 +1748,42 @@ struct bt_ctf_field_type *btr_get_variant_type_cb(
 end:
        BT_PUT(tag_field);
        BT_PUT(selected_field);
+       BT_PUT(path);
 
        return selected_field_type;
 }
 
+static
+int set_event_clocks(struct bt_ctf_event *event,
+               struct bt_ctf_notif_iter *notit)
+{
+       int ret;
+       GHashTableIter iter;
+       struct bt_ctf_clock *clock;
+       uint64_t *clock_state;
+
+       g_hash_table_iter_init(&iter, notit->clock_states);
+
+       while (g_hash_table_iter_next(&iter, (gpointer) &clock,
+                       (gpointer) &clock_state)) {
+               struct bt_ctf_clock_value *clock_value;
+
+               clock_value = bt_ctf_clock_value_create(clock, *clock_state);
+               if (!clock_value) {
+                       ret = -1;
+                       goto end;
+               }
+               ret = bt_ctf_event_set_clock_value(event, clock, clock_value);
+               bt_put(clock_value);
+               if (ret) {
+                       goto end;
+               }
+       }
+       ret = 0;
+end:
+       return ret;
+}
+
 static
 struct bt_ctf_event *create_event(struct bt_ctf_notif_iter *notit)
 {
@@ -1680,6 +1821,11 @@ struct bt_ctf_event *create_event(struct bt_ctf_notif_iter *notit)
                goto error;
        }
 
+       ret = set_event_clocks(event, notit);
+       if (ret) {
+               goto error;
+       }
+
        /* Associate with current packet. */
        assert(notit->packet);
        ret = bt_ctf_event_set_packet(event, notit->packet);
@@ -1797,33 +1943,64 @@ end:
        BT_PUT(event);
 }
 
+//FIXME: not used ?
 static
 void notify_eos(struct bt_ctf_notif_iter *notit,
                struct bt_notification **notification)
 {
-       struct bt_ctf_event *event;
+       struct bt_ctf_stream *stream = NULL;
        struct bt_notification *ret = NULL;
 
-       /* Create event */
-       event = create_event(notit);
-       if (!event) {
+       /* Ask the user for the stream */
+       stream = notit->medium.medops.get_stream(notit->meta.stream_class,
+                       notit->medium.data);
+       if (!stream) {
                goto end;
        }
 
-       ret = bt_notification_stream_end_create(event);
+       ret = bt_notification_stream_end_create(stream);
        if (!ret) {
                goto end;
        }
        *notification = ret;
 end:
-       BT_PUT(event);
+       BT_PUT(stream);
+}
+
+static
+int init_clock_states(GHashTable *clock_states, struct bt_ctf_trace *trace)
+{
+       int clock_count, i, ret = 0;
+
+       clock_count = bt_ctf_trace_get_clock_count(trace);
+       if (clock_count <= 0) {
+               ret = -1;
+               goto end;
+       }
+
+       for (i = 0; i < clock_count; i++) {
+               struct bt_ctf_clock *clock;
+
+               clock = bt_ctf_trace_get_clock(trace, i);
+               if (!clock) {
+                       ret = -1;
+                       goto end;
+               }
+
+               g_hash_table_insert(clock_states, bt_get(clock), NULL);
+               bt_put(clock);
+       }
+end:
+       return ret;
 }
 
+BT_HIDDEN
 struct bt_ctf_notif_iter *bt_ctf_notif_iter_create(struct bt_ctf_trace *trace,
                size_t max_request_sz,
                struct bt_ctf_notif_iter_medium_ops medops,
                void *data, FILE *err_stream)
 {
+       int ret;
        struct bt_ctf_notif_iter *notit = NULL;
        struct bt_ctf_btr_cbs cbs = {
                .types = {
@@ -1849,9 +2026,18 @@ struct bt_ctf_notif_iter *bt_ctf_notif_iter_create(struct bt_ctf_trace *trace,
                PERR("Failed to allocate memory for CTF notification iterator\n");
                goto end;
        }
-
-       notit->meta.trace = trace;
-       bt_get(notit->meta.trace);
+       notit->clock_states = g_hash_table_new_full(g_direct_hash,
+                       g_direct_equal, bt_put, g_free);
+       if (!notit->clock_states) {
+               PERR("Failed to create hash table\n");
+               goto error;
+       }
+       ret = init_clock_states(notit->clock_states, trace);
+       if (ret) {
+               PERR("Failed to initialize stream clock states\n");
+               goto error;
+       }
+       notit->meta.trace = bt_get(trace);
        notit->medium.medops = medops;
        notit->medium.max_request_sz = max_request_sz;
        notit->medium.data = data;
@@ -1859,23 +2045,23 @@ struct bt_ctf_notif_iter *bt_ctf_notif_iter_create(struct bt_ctf_trace *trace,
        notit->stack = stack_new(notit);
        if (!notit->stack) {
                PERR("Failed to create stack\n");
-               bt_ctf_notif_iter_destroy(notit);
-               notit = NULL;
-               goto end;
+               goto error;
        }
 
        notit->btr = bt_ctf_btr_create(cbs, notit, err_stream);
        if (!notit->btr) {
                PERR("Failed to create binary type reader\n");
-               bt_ctf_notif_iter_destroy(notit);
-               notit = NULL;
-               goto end;
+               goto error;
        }
 
        bt_ctf_notif_iter_reset(notit);
 
 end:
        return notit;
+error:
+       bt_ctf_notif_iter_destroy(notit);
+       notit = NULL;
+       goto end;
 }
 
 void bt_ctf_notif_iter_destroy(struct bt_ctf_notif_iter *notit)
@@ -1894,6 +2080,9 @@ void bt_ctf_notif_iter_destroy(struct bt_ctf_notif_iter *notit)
                bt_ctf_btr_destroy(notit->btr);
        }
 
+       if (notit->clock_states) {
+               g_hash_table_destroy(notit->clock_states);
+       }
        g_free(notit);
 }
 
This page took 0.028247 seconds and 4 git commands to generate.