Track clock states in notification iterator
authorJérémie Galarneau <jeremie.galarneau@efficios.com>
Thu, 17 Nov 2016 20:49:53 +0000 (15:49 -0500)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Sat, 27 May 2017 18:09:06 +0000 (14:09 -0400)
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
formats/ctf/ir/event.c
formats/ctf/ir/stream.c
include/babeltrace/ctf-ir/event-internal.h
include/babeltrace/ctf-ir/stream-internal.h
plugins/ctf/common/btr/btr.h
plugins/ctf/common/notif-iter/notif-iter.c

index 13bf8a44c965b930799630d5ffda06527ccf0209..505aa1049e24a473bf19c98ed70702f69aacfe51 100644 (file)
@@ -856,37 +856,3 @@ void bt_ctf_event_freeze(struct bt_ctf_event *event)
        bt_ctf_field_freeze(event->fields_payload);
        event->frozen = 1;
 }
-
-static
-void insert_stream_clock_value_into_event_clock_values(gpointer key,
-               gpointer value,
-               gpointer data)
-{
-       struct bt_ctf_event *event = data;
-       uint64_t *clock_value;
-
-       assert(event);
-
-       /* Copy clock value because it belongs to the hash table */
-       clock_value = g_new0(uint64_t, 1);
-       *clock_value = *((uint64_t *) value);
-
-       /* Insert copy into event clock values */
-       g_hash_table_insert(event->clock_values, key, clock_value);
-}
-
-BT_HIDDEN
-int bt_ctf_event_register_stream_clock_values(struct bt_ctf_event *event)
-{
-       int ret = 0;
-       struct bt_ctf_stream *stream;
-
-       stream = bt_ctf_event_get_stream(event);
-       assert(stream);
-       g_hash_table_remove_all(event->clock_values);
-       g_hash_table_foreach(stream->clock_values,
-               insert_stream_clock_value_into_event_clock_values, event);
-       BT_PUT(stream);
-
-       return ret;
-}
index 56abfcea5f89fe1f78f47241428fcc20d3688361..8c5a9877fb3dceae1aadf01aae9476a868d93a0a 100644 (file)
@@ -403,9 +403,6 @@ struct bt_ctf_stream *bt_ctf_stream_create(
                if (ret) {
                        goto error;
                }
-
-               stream->clock_values = g_hash_table_new_full(g_direct_hash,
-                       g_direct_equal, NULL, g_free);
        }
 
        /* Add this stream to the trace's streams */
@@ -937,10 +934,6 @@ void bt_ctf_stream_destroy(struct bt_object *obj)
                g_string_free(stream->name, TRUE);
        }
 
-       if (stream->clock_values) {
-               g_hash_table_destroy(stream->clock_values);
-       }
-
        bt_put(stream->packet_header);
        bt_put(stream->packet_context);
        g_free(stream);
@@ -1009,78 +1002,3 @@ const char *bt_ctf_stream_get_name(struct bt_ctf_stream *stream)
 end:
        return name;
 }
-
-BT_HIDDEN
-void bt_ctf_stream_update_clock_value(struct bt_ctf_stream *stream,
-               struct bt_ctf_field *value_field)
-{
-       struct bt_ctf_field_type *value_type = NULL;
-       struct bt_ctf_clock *clock = NULL;
-       uint64_t requested_new_value;
-       uint64_t requested_new_value_mask;
-       uint64_t *cur_value;
-       uint64_t cur_value_masked;
-       int requested_new_value_size;
-       int ret;
-
-       assert(stream);
-       assert(clock);
-       assert(value_field);
-       value_type = bt_ctf_field_get_type(value_field);
-       assert(value_type);
-       clock = bt_ctf_field_type_integer_get_mapped_clock(value_type);
-       assert(clock);
-       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);
-       cur_value = g_hash_table_lookup(stream->clock_values, clock);
-
-       if (!cur_value) {
-               /*
-                * Updating the value of a clock which is not registered
-                * yet, so register it with the new value as its initial
-                * value.
-                */
-               uint64_t *requested_new_value_ptr = g_new0(uint64_t, 1);
-
-               *requested_new_value_ptr = requested_new_value;
-               g_hash_table_insert(stream->clock_values, clock,
-                       requested_new_value_ptr);
-               goto end;
-       }
-
-       /*
-        * 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) {
-               *cur_value = requested_new_value;
-               goto end;
-       }
-
-       requested_new_value_mask = (1ULL << requested_new_value_size) - 1;
-       cur_value_masked = *cur_value & 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.
-                */
-               *cur_value += requested_new_value_mask + 1;
-       }
-
-       /* Clear the low bits of the current clock value */
-       *cur_value &= ~requested_new_value_mask;
-
-       /* Set the low bits of the current clock value */
-       *cur_value |= requested_new_value;
-
-end:
-       bt_put(clock);
-       bt_put(value_type);
-}
index cc10f224015034a9bb9484b91f3b82dba6814608..ed09e962bf9bca9a3536c0c8ae3392dce129a7a7 100644 (file)
@@ -50,9 +50,6 @@ struct bt_ctf_event {
        int frozen;
 };
 
-BT_HIDDEN
-int bt_ctf_event_register_stream_clock_values(struct bt_ctf_event *event);
-
 BT_HIDDEN
 int bt_ctf_event_validate(struct bt_ctf_event *event);
 
index dc392f4ad907fce01be034de6d089e7360aa1788..a39b1529108bfdbd511ab8162a0815f8c9c1548a 100644 (file)
@@ -47,14 +47,9 @@ struct bt_ctf_stream {
        GString *name;
        struct bt_ctf_field *packet_header;
        struct bt_ctf_field *packet_context;
-       GHashTable *clock_values; /* Maps clock addresses to (uint64_t *) */
 };
 
 BT_HIDDEN
 int bt_ctf_stream_set_fd(struct bt_ctf_stream *stream, int fd);
 
-BT_HIDDEN
-void bt_ctf_stream_update_clock_value(struct bt_ctf_stream *stream,
-               struct bt_ctf_field *value_field);
-
 #endif /* BABELTRACE_CTF_WRITER_STREAM_INTERNAL_H */
index 7548415527b4860cfedfead5d1c01ce2fe929d65..ee6695a19fbab0f839dad46a544234bb927269da 100644 (file)
@@ -52,6 +52,8 @@
  * Binary type reader API status codes.
  */
 enum bt_ctf_btr_status {
+       /** Out of memory. */
+       BT_CTF_BTR_STATUS_ENOMEM =      -5,
        /**
         * The binary stream reader reached the end of the user-provided
         * buffer, but data is still needed to finish decoding the
index 5e06362613c1e6f5500322ef4ecb5026291afc0d..d4bfdb1b14409503fb03869ce998d07d60b47878 100644 (file)
@@ -173,6 +173,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
@@ -1220,6 +1223,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)
@@ -1235,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;
        }
 
@@ -1259,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;
 }
 
@@ -1282,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;
        }
 
@@ -1306,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;
 }
 
@@ -1824,11 +1934,40 @@ end:
        BT_PUT(event);
 }
 
+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 = {
@@ -1854,7 +1993,17 @@ 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->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;
@@ -1863,23 +2012,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)
@@ -1898,6 +2047,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.031404 seconds and 4 git commands to generate.