Fix: wrong return code check on try_set
[babeltrace.git] / lib / ctf-ir / stream.c
index ce3936da98a8776380a62da025ddad367ba8b825..3d21ecac7ea4b1fbf709a153c09e0f0d05b802de 100644 (file)
@@ -48,6 +48,7 @@
 #include <babeltrace/compiler-internal.h>
 #include <babeltrace/align-internal.h>
 #include <inttypes.h>
+#include <unistd.h>
 
 static
 void bt_ctf_stream_destroy(struct bt_object *obj);
@@ -851,7 +852,7 @@ struct bt_ctf_stream *bt_ctf_stream_create_with_id_no_check(
                        /* Initialize events_discarded */
                        ret = try_set_structure_field_integer(
                                stream->packet_context, "events_discarded", 0);
-                       if (ret != 1) {
+                       if (ret < 0) {
                                BT_LOGW("Cannot set `events_discarded` field in packet context: "
                                        "ret=%d, packet-context-field-addr=%p",
                                        ret, stream->packet_context);
@@ -997,20 +998,20 @@ end:
        return stream_class;
 }
 
-int64_t bt_ctf_stream_get_discarded_events_count(
+int bt_ctf_stream_get_discarded_events_count(
                struct bt_ctf_stream *stream, uint64_t *count)
 {
-       int64_t ret = 0;
+       int ret = 0;
 
        if (!stream) {
                BT_LOGW_STR("Invalid parameter: stream is NULL.");
-               ret = (int64_t) -1;
+               ret = -1;
                goto end;
        }
 
        if (!count) {
                BT_LOGW_STR("Invalid parameter: count is NULL.");
-               ret = (int64_t) -1;
+               ret = -1;
                goto end;
        }
 
@@ -1018,7 +1019,7 @@ int64_t bt_ctf_stream_get_discarded_events_count(
                BT_LOGW("Invalid parameter: stream is not a CTF writer stream: "
                        "stream-addr=%p, stream-name=\"%s\"",
                        stream, bt_ctf_stream_get_name(stream));
-               ret = (int64_t) -1;
+               ret = -1;
                goto end;
        }
 
@@ -1450,9 +1451,10 @@ void reset_structure_field(struct bt_ctf_field *structure, const char *name)
        struct bt_ctf_field *member;
 
        member = bt_ctf_field_structure_get_field(structure, name);
-       assert(member);
-       (void) bt_ctf_field_reset(member);
-       bt_put(member);
+       if (member) {
+               (void) bt_ctf_field_reset(member);
+               bt_put(member);
+       }
 }
 
 int bt_ctf_stream_flush(struct bt_ctf_stream *stream)
@@ -1462,6 +1464,7 @@ int bt_ctf_stream_flush(struct bt_ctf_stream *stream)
        struct bt_ctf_stream_pos packet_context_pos;
        struct bt_ctf_trace *trace;
        enum bt_ctf_byte_order native_byte_order;
+       bool has_packet_size = false;
 
        if (!stream) {
                BT_LOGW_STR("Invalid parameter: stream is NULL.");
@@ -1475,19 +1478,23 @@ int bt_ctf_stream_flush(struct bt_ctf_stream *stream)
                goto end;
        }
 
-       if (stream->flushed_packet_count == 1) {
+       if (stream->packet_context) {
                struct bt_ctf_field *packet_size_field;
 
+               packet_size_field = bt_ctf_field_structure_get_field(
+                               stream->packet_context, "packet_size");
+               has_packet_size = (packet_size_field != NULL);
+               bt_put(packet_size_field);
+       }
+
+       if (stream->flushed_packet_count == 1) {
                if (!stream->packet_context) {
                        BT_LOGW_STR("Cannot flush a stream which has no packet context field more than once.");
                        ret = -1;
                        goto end;
                }
 
-               packet_size_field = bt_ctf_field_structure_get_field(
-                       stream->packet_context, "packet_size");
-               bt_put(packet_size_field);
-               if (!packet_size_field) {
+               if (!has_packet_size) {
                        BT_LOGW_STR("Cannot flush a stream which has no packet context's `packet_size` field more than once.");
                        ret = -1;
                        goto end;
@@ -1593,8 +1600,24 @@ int bt_ctf_stream_flush(struct bt_ctf_stream *stream)
                }
        }
 
+       if (!has_packet_size && stream->pos.offset % 8 != 0) {
+               BT_LOGW("Stream's packet context field type has no `packet_size` field, "
+                       "but current content size is not a multiple of 8 bits: "
+                       "content-size=%" PRId64 ", "
+                       "packet-size=%" PRIu64,
+                       stream->pos.offset,
+                       stream->pos.packet_size);
+               ret = -1;
+               goto end;
+       }
+
        assert(stream->pos.packet_size % 8 == 0);
 
+       /*
+        * Remove extra padding bytes.
+        */
+       stream->pos.packet_size = (stream->pos.offset + 7) & ~7;
+
        if (stream->packet_context) {
                /*
                 * The whole packet is serialized at this point. Make sure that,
@@ -1647,13 +1670,26 @@ int bt_ctf_stream_flush(struct bt_ctf_stream *stream)
        g_ptr_array_set_size(stream->events, 0);
        stream->flushed_packet_count++;
        stream->size += stream->pos.packet_size / CHAR_BIT;
+
+       do {
+               ret = ftruncate(stream->pos.fd, stream->size);
+       } while (ret == -1 && errno == EINTR);
+       if (ret == -1) {
+               BT_LOGE_ERRNO("Cannot ftruncate() stream file to new size",
+                               "size = %" PRIu64 ", name = %s",
+                               stream->size,
+                               stream->name ? stream->name->str : "(null)");
+       }
+
 end:
        /* Reset automatically-set fields. */
-       reset_structure_field(stream->packet_context, "timestamp_begin");
-       reset_structure_field(stream->packet_context, "timestamp_end");
-       reset_structure_field(stream->packet_context, "packet_size");
-       reset_structure_field(stream->packet_context, "content_size");
-       reset_structure_field(stream->packet_context, "events_discarded");
+       if (stream->packet_context) {
+               reset_structure_field(stream->packet_context, "timestamp_begin");
+               reset_structure_field(stream->packet_context, "timestamp_end");
+               reset_structure_field(stream->packet_context, "packet_size");
+               reset_structure_field(stream->packet_context, "content_size");
+               reset_structure_field(stream->packet_context, "events_discarded");
+       }
 
        if (ret < 0) {
                /*
This page took 0.02498 seconds and 4 git commands to generate.