Fix: support 64-bit events discarded counter types
[babeltrace.git] / formats / ctf / ctf.c
index 7c3df128c9b147dd86846e8d2aaed8c6170f6ee6..07966632e82caa99139f20458faf7f3d99f87449 100644 (file)
 #include <babeltrace/ctf/metadata.h>
 #include <babeltrace/babeltrace-internal.h>
 #include <babeltrace/ctf/events-internal.h>
+#include <babeltrace/trace-handle-internal.h>
+#include <babeltrace/context-internal.h>
+#include <babeltrace/uuid.h>
+#include <babeltrace/endian.h>
 #include <inttypes.h>
 #include <stdio.h>
-#include <uuid/uuid.h>
 #include <sys/mman.h>
 #include <errno.h>
-#include <endian.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
@@ -41,6 +43,7 @@
 #include "metadata/ctf-parser.h"
 #include "metadata/ctf-ast.h"
 #include "events-private.h"
+#include "memstream.h"
 
 /*
  * We currently simply map a page to read the packet header and packet
@@ -48,7 +51,6 @@
  */
 #define MAX_PACKET_HEADER_LEN  (getpagesize() * CHAR_BIT)
 #define WRITE_PACKET_LEN       (getpagesize() * 8 * CHAR_BIT)
-#define UUID_LEN 16    /* uuid by value len */
 
 #ifndef min
 #define min(a, b)      (((a) < (b)) ? (a) : (b))
@@ -76,9 +78,21 @@ struct trace_descriptor *ctf_open_mmap_trace(
                void (*packet_seek)(struct stream_pos *pos, size_t index,
                        int whence),
                FILE *metadata_fp);
+static
+void ctf_set_context(struct trace_descriptor *descriptor,
+               struct bt_context *ctx);
+static
+void ctf_set_handle(struct trace_descriptor *descriptor,
+               struct bt_trace_handle *handle);
 
 static
 void ctf_close_trace(struct trace_descriptor *descriptor);
+static
+uint64_t ctf_timestamp_begin(struct trace_descriptor *descriptor,
+               struct bt_trace_handle *handle);
+static
+uint64_t ctf_timestamp_end(struct trace_descriptor *descriptor,
+               struct bt_trace_handle *handle);
 
 static
 rw_dispatch read_dispatch_table[] = {
@@ -109,13 +123,104 @@ struct format ctf_format = {
        .open_trace = ctf_open_trace,
        .open_mmap_trace = ctf_open_mmap_trace,
        .close_trace = ctf_close_trace,
+       .set_context = ctf_set_context,
+       .set_handle = ctf_set_handle,
+       .timestamp_begin = ctf_timestamp_begin,
+       .timestamp_end = ctf_timestamp_end,
 };
 
+static
+uint64_t ctf_timestamp_begin(struct trace_descriptor *descriptor,
+               struct bt_trace_handle *handle)
+{
+       struct ctf_trace *tin;
+       uint64_t begin = ULLONG_MAX;
+       int i, j;
+
+       tin = container_of(descriptor, struct ctf_trace, parent);
+
+       if (!tin)
+               goto error;
+
+       /* for each stream_class */
+       for (i = 0; i < tin->streams->len; i++) {
+               struct ctf_stream_declaration *stream_class;
+
+               stream_class = g_ptr_array_index(tin->streams, i);
+               /* for each file_stream */
+               for (j = 0; j < stream_class->streams->len; j++) {
+                       struct ctf_stream_definition *stream;
+                       struct ctf_file_stream *cfs;
+                       struct ctf_stream_pos *stream_pos;
+                       struct packet_index *index;
+
+                       stream = g_ptr_array_index(stream_class->streams, j);
+                       cfs = container_of(stream, struct ctf_file_stream,
+                                       parent);
+                       stream_pos = &cfs->pos;
+
+                       index = &g_array_index(stream_pos->packet_index,
+                                       struct packet_index, 0);
+                       if (index->timestamp_begin < begin)
+                               begin = index->timestamp_begin;
+               }
+       }
+
+       return begin;
+
+error:
+       return -1ULL;
+}
+
+static
+uint64_t ctf_timestamp_end(struct trace_descriptor *descriptor,
+               struct bt_trace_handle *handle)
+{
+       struct ctf_trace *tin;
+       uint64_t end = 0;
+       int i, j;
+
+       tin = container_of(descriptor, struct ctf_trace, parent);
+
+       if (!tin)
+               goto error;
+
+       /* for each stream_class */
+       for (i = 0; i < tin->streams->len; i++) {
+               struct ctf_stream_declaration *stream_class;
+
+               stream_class = g_ptr_array_index(tin->streams, i);
+               /* for each file_stream */
+               for (j = 0; j < stream_class->streams->len; j++) {
+                       struct ctf_stream_definition *stream;
+                       struct ctf_file_stream *cfs;
+                       struct ctf_stream_pos *stream_pos;
+                       struct packet_index *index;
+
+                       stream = g_ptr_array_index(stream_class->streams, j);
+                       cfs = container_of(stream, struct ctf_file_stream,
+                                       parent);
+                       stream_pos = &cfs->pos;
+
+                       index = &g_array_index(stream_pos->packet_index,
+                                       struct packet_index,
+                                       stream_pos->packet_index->len - 1);
+                       if (index->timestamp_end > end)
+                               end = index->timestamp_end;
+               }
+       }
+
+       return end;
+
+error:
+       return -1ULL;
+}
+
 /*
  * Update stream current timestamp, keep at clock frequency.
  */
 static
-void ctf_update_timestamp(struct ctf_stream *stream,
+void ctf_update_timestamp(struct ctf_stream_definition *stream,
                          struct definition_integer *integer_definition)
 {
        struct declaration_integer *integer_declaration =
@@ -146,7 +251,7 @@ void ctf_update_timestamp(struct ctf_stream *stream,
  * applying offsets as needed (unix time).
  */
 void ctf_print_timestamp(FILE *fp,
-                       struct ctf_stream *stream,
+                       struct ctf_stream_definition *stream,
                        uint64_t timestamp)
 {
        uint64_t ts_sec = 0, ts_nsec;
@@ -211,12 +316,12 @@ end:
 }
 
 static
-int ctf_read_event(struct stream_pos *ppos, struct ctf_stream *stream)
+int ctf_read_event(struct stream_pos *ppos, struct ctf_stream_definition *stream)
 {
        struct ctf_stream_pos *pos =
                container_of(ppos, struct ctf_stream_pos, parent);
-       struct ctf_stream_class *stream_class = stream->stream_class;
-       struct ctf_stream_event *event;
+       struct ctf_stream_declaration *stream_class = stream->stream_class;
+       struct ctf_event_definition *event;
        uint64_t id = 0;
        int ret;
 
@@ -325,10 +430,10 @@ error:
 }
 
 static
-int ctf_write_event(struct stream_pos *pos, struct ctf_stream *stream)
+int ctf_write_event(struct stream_pos *pos, struct ctf_stream_definition *stream)
 {
-       struct ctf_stream_class *stream_class = stream->stream_class;
-       struct ctf_stream_event *event;
+       struct ctf_stream_declaration *stream_class = stream->stream_class;
+       struct ctf_event_definition *event;
        uint64_t id;
        int ret;
 
@@ -489,7 +594,7 @@ void ctf_packet_seek(struct stream_pos *stream_pos, size_t index, int whence)
                switch (whence) {
                case SEEK_CUR:
                {
-                       uint32_t events_discarded_diff;
+                       uint64_t events_discarded_diff;
 
                        if (pos->offset == EOF) {
                                return;
@@ -505,6 +610,13 @@ void ctf_packet_seek(struct stream_pos *stream_pos, size_t index, int whence)
                                                struct packet_index,
                                                pos->cur_index - 1);
                                events_discarded_diff -= packet_index->events_discarded;
+                               /*
+                                * Deal with 32-bit wrap-around if the
+                                * tracer provided a 32-bit field.
+                                */
+                               if (packet_index->events_discarded_len == 32) {
+                                       events_discarded_diff = (uint32_t) events_discarded_diff;
+                               }
                        }
                        file_stream->parent.events_discarded = events_discarded_diff;
                        file_stream->parent.prev_timestamp = file_stream->parent.timestamp;
@@ -538,14 +650,14 @@ void ctf_packet_seek(struct stream_pos *stream_pos, size_t index, int whence)
                                 */
                                if ((&file_stream->parent)->stream_class->trace->collection) {
                                        fflush(stdout);
-                                       fprintf(stderr, "[warning] Tracer discarded %d events at end of stream between [",
+                                       fprintf(stderr, "[warning] Tracer discarded %" PRIu64 " events at end of stream between [",
                                                        file_stream->parent.events_discarded);
                                        ctf_print_timestamp(stderr, &file_stream->parent,
                                                        file_stream->parent.prev_timestamp);
                                        fprintf(stderr, "] and [");
                                        ctf_print_timestamp(stderr, &file_stream->parent,
                                                        file_stream->parent.prev_timestamp_end);
-                                       fprintf(stderr, "]. You should consider increasing the buffer size.\n");
+                                       fprintf(stderr, "]. You should consider recording a new trace with larger buffers or with fewer events enabled.\n");
                                        fflush(stderr);
                                }
                                file_stream->parent.events_discarded = 0;
@@ -689,7 +801,7 @@ int ctf_open_trace_metadata_packet_read(struct ctf_trace *td, FILE *in,
                memcpy(td->uuid, header.uuid, sizeof(header.uuid));
                CTF_TRACE_SET_FIELD(td, uuid);
        } else {
-               if (uuid_compare(header.uuid, td->uuid))
+               if (babeltrace_uuid_compare(header.uuid, td->uuid))
                        return -EINVAL;
        }
 
@@ -748,7 +860,7 @@ int ctf_open_trace_metadata_stream_read(struct ctf_trace *td, FILE **fp,
         * because its size includes garbage at the end (after final
         * \0). This is the allocated size, not the actual string size.
         */
-       out = open_memstream(buf, &size);
+       out = babeltrace_open_memstream(buf, &size);
        if (out == NULL) {
                perror("Metadata open_memstream");
                return -errno;
@@ -763,10 +875,16 @@ int ctf_open_trace_metadata_stream_read(struct ctf_trace *td, FILE **fp,
                        break;
                }
        }
-       fclose(out);    /* flush the buffer */
+       /* close to flush the buffer */
+       ret = babeltrace_close_memstream(buf, &size, out);
+       if (ret < 0) {
+               perror("babeltrace_flush_memstream");
+               fclose(in);
+               return -errno;
+       }
        fclose(in);
        /* open for reading */
-       *fp = fmemopen(*buf, strlen(*buf), "rb");
+       *fp = babeltrace_fmemopen(*buf, strlen(*buf), "rb");
        if (!*fp) {
                perror("Metadata fmemopen");
                return -errno;
@@ -872,7 +990,8 @@ end:
        ctf_scanner_free(scanner);
 end_scanner_alloc:
 end_packet_read:
-       fclose(fp);
+       if (fp)
+               fclose(fp);
        free(buf);
 end_stream:
        close(metadata_stream->pos.fd);
@@ -882,11 +1001,11 @@ end_stream:
 }
 
 static
-struct ctf_stream_event *create_event_definitions(struct ctf_trace *td,
-                                                 struct ctf_stream *stream,
-                                                 struct ctf_event *event)
+struct ctf_event_definition *create_event_definitions(struct ctf_trace *td,
+                                                 struct ctf_stream_definition *stream,
+                                                 struct ctf_event_declaration *event)
 {
-       struct ctf_stream_event *stream_event = g_new0(struct ctf_stream_event, 1);
+       struct ctf_event_definition *stream_event = g_new0(struct ctf_event_definition, 1);
 
        if (event->context_decl) {
                struct definition *definition =
@@ -910,6 +1029,7 @@ struct ctf_stream_event *create_event_definitions(struct ctf_trace *td,
                                        struct definition_struct, p);
                stream->parent_def_scope = stream_event->event_fields->p.scope;
        }
+       stream_event->stream = stream;
        return stream_event;
 
 error:
@@ -921,9 +1041,9 @@ error:
 }
 
 static
-int create_stream_definitions(struct ctf_trace *td, struct ctf_stream *stream)
+int create_stream_definitions(struct ctf_trace *td, struct ctf_stream_definition *stream)
 {
-       struct ctf_stream_class *stream_class;
+       struct ctf_stream_declaration *stream_class;
        int ret;
        int i;
 
@@ -971,8 +1091,8 @@ int create_stream_definitions(struct ctf_trace *td, struct ctf_stream *stream)
        stream->events_by_id = g_ptr_array_new();
        g_ptr_array_set_size(stream->events_by_id, stream_class->events_by_id->len);
        for (i = 0; i < stream->events_by_id->len; i++) {
-               struct ctf_event *event = g_ptr_array_index(stream_class->events_by_id, i);
-               struct ctf_stream_event *stream_event;
+               struct ctf_event_declaration *event = g_ptr_array_index(stream_class->events_by_id, i);
+               struct ctf_event_definition *stream_event;
 
                if (!event)
                        continue;
@@ -985,7 +1105,7 @@ int create_stream_definitions(struct ctf_trace *td, struct ctf_stream *stream)
 
 error_event:
        for (i = 0; i < stream->events_by_id->len; i++) {
-               struct ctf_stream_event *stream_event = g_ptr_array_index(stream->events_by_id, i);
+               struct ctf_event_definition *stream_event = g_ptr_array_index(stream->events_by_id, i);
                if (stream_event)
                        g_free(stream_event);
        }
@@ -1005,7 +1125,7 @@ static
 int create_stream_packet_index(struct ctf_trace *td,
                               struct ctf_file_stream *file_stream)
 {
-       struct ctf_stream_class *stream;
+       struct ctf_stream_declaration *stream;
        int len_index;
        struct ctf_stream_pos *pos;
        struct stat filestats;
@@ -1077,20 +1197,20 @@ int create_stream_packet_index(struct ctf_trace *td,
                                struct definition_array *defarray;
                                struct definition *field;
                                uint64_t i;
-                               uint8_t uuidval[UUID_LEN];
+                               uint8_t uuidval[BABELTRACE_UUID_LEN];
 
                                field = struct_definition_get_field_from_index(file_stream->parent.trace_packet_header, len_index);
                                assert(field->declaration->id == CTF_TYPE_ARRAY);
                                defarray = container_of(field, struct definition_array, p);
-                               assert(array_len(defarray) == UUID_LEN);
+                               assert(array_len(defarray) == BABELTRACE_UUID_LEN);
 
-                               for (i = 0; i < UUID_LEN; i++) {
+                               for (i = 0; i < BABELTRACE_UUID_LEN; i++) {
                                        struct definition *elem;
 
                                        elem = array_index(defarray, i);
                                        uuidval[i] = get_unsigned_int(elem);
                                }
-                               ret = uuid_compare(td->uuid, uuidval);
+                               ret = babeltrace_uuid_compare(td->uuid, uuidval);
                                if (ret) {
                                        fprintf(stderr, "[error] Unique Universal Identifiers do not match.\n");
                                        return -EINVAL;
@@ -1183,6 +1303,7 @@ int create_stream_packet_index(struct ctf_trace *td,
 
                                field = struct_definition_get_field_from_index(file_stream->parent.stream_packet_context, len_index);
                                packet_index.events_discarded = get_unsigned_int(field);
+                               packet_index.events_discarded_len = get_int_len(field);
                        }
                } else {
                        /* Use file size for packet size */
@@ -1220,7 +1341,7 @@ int create_stream_packet_index(struct ctf_trace *td,
 }
 
 static
-int create_trace_definitions(struct ctf_trace *td, struct ctf_stream *stream)
+int create_trace_definitions(struct ctf_trace *td, struct ctf_stream_definition *stream)
 {
        int ret;
 
@@ -1313,14 +1434,14 @@ int ctf_open_trace_read(struct ctf_trace *td,
        /* Open trace directory */
        td->dir = opendir(path);
        if (!td->dir) {
-               fprintf(stderr, "[error] Unable to open trace directory.\n");
+               fprintf(stderr, "[error] Unable to open trace directory \"%s\".\n", path);
                ret = -ENOENT;
                goto error;
        }
 
        td->dirfd = open(path, 0);
        if (td->dirfd < 0) {
-               fprintf(stderr, "[error] Unable to open trace directory file descriptor.\n");
+               fprintf(stderr, "[error] Unable to open trace directory file descriptor for path \"%s\".\n", path);
                perror("Trace directory open");
                ret = -errno;
                goto error_dirfd;
@@ -1334,6 +1455,7 @@ int ctf_open_trace_read(struct ctf_trace *td,
 
        ret = ctf_open_trace_metadata_read(td, packet_seek, metadata_fp);
        if (ret) {
+               fprintf(stderr, "[warning] Unable to open trace metadata for path \"%s\".\n", path);
                goto error_metadata;
        }
 
@@ -1446,7 +1568,7 @@ static
 int prepare_mmap_stream_definition(struct ctf_trace *td,
                struct ctf_file_stream *file_stream)
 {
-       struct ctf_stream_class *stream;
+       struct ctf_stream_declaration *stream;
        uint64_t stream_id = 0;
        int ret;
 
@@ -1585,7 +1707,7 @@ void ctf_close_trace(struct trace_descriptor *tdp)
 
        if (td->streams) {
                for (i = 0; i < td->streams->len; i++) {
-                       struct ctf_stream_class *stream;
+                       struct ctf_stream_declaration *stream;
                        int j;
 
                        stream = g_ptr_array_index(td->streams, i);
@@ -1600,10 +1722,52 @@ void ctf_close_trace(struct trace_descriptor *tdp)
                }
                g_ptr_array_free(td->streams, TRUE);
        }
+
+       if (td->event_declarations) {
+               for (i = 0; i < td->event_declarations->len; i++) {
+                       struct bt_ctf_event_decl *event;
+
+                       event = g_ptr_array_index(td->event_declarations, i);
+                       if (event->context_decl)
+                               g_ptr_array_free(event->context_decl, TRUE);
+                       if (event->fields_decl)
+                               g_ptr_array_free(event->fields_decl, TRUE);
+                       if (event->packet_header_decl)
+                               g_ptr_array_free(event->packet_header_decl, TRUE);
+                       if (event->event_context_decl)
+                               g_ptr_array_free(event->event_context_decl, TRUE);
+                       if (event->event_header_decl)
+                               g_ptr_array_free(event->event_header_decl, TRUE);
+                       if (event->packet_context_decl)
+                               g_ptr_array_free(event->packet_context_decl, TRUE);
+                       g_free(event);
+               }
+               g_ptr_array_free(td->event_declarations, TRUE);
+       }
        closedir(td->dir);
        g_free(td);
 }
 
+static
+void ctf_set_context(struct trace_descriptor *descriptor,
+               struct bt_context *ctx)
+{
+       struct ctf_trace *td = container_of(descriptor, struct ctf_trace,
+                       parent);
+
+       td->ctx = ctx;
+}
+
+static
+void ctf_set_handle(struct trace_descriptor *descriptor,
+               struct bt_trace_handle *handle)
+{
+       struct ctf_trace *td = container_of(descriptor, struct ctf_trace,
+                       parent);
+
+       td->handle = handle;
+}
+
 void __attribute__((constructor)) ctf_init(void)
 {
        int ret;
This page took 0.029772 seconds and 4 git commands to generate.