X-Git-Url: http://git.efficios.com/?p=babeltrace.git;a=blobdiff_plain;f=formats%2Fctf%2Fctf.c;h=07966632e82caa99139f20458faf7f3d99f87449;hp=17f299c3dece67bb334c769a1516fa9898ba0c60;hb=4c4ba0211b25f7a4ef4f3fbd7cda9ee5a4bc6330;hpb=20d0dcf9609dcd28aebe87c167d6600ddbe668d1 diff --git a/formats/ctf/ctf.c b/formats/ctf/ctf.c index 17f299c3..07966632 100644 --- a/formats/ctf/ctf.c +++ b/formats/ctf/ctf.c @@ -22,12 +22,15 @@ #include #include #include +#include +#include +#include +#include +#include #include #include -#include #include #include -#include #include #include #include @@ -39,6 +42,8 @@ #include "metadata/ctf-scanner.h" #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 @@ -46,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)) @@ -74,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[] = { @@ -107,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 = @@ -144,25 +251,18 @@ 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; - struct ctf_trace *trace = stream->stream_class->trace; - struct trace_collection *tc = trace->collection; - uint64_t tc_offset = tc->single_clock_offset_avg; - if (stream->current_clock->freq == 1000000000ULL) { - ts_nsec = timestamp; + if (opt_clock_raw) { + ts_nsec = ctf_get_timestamp_raw(stream, timestamp); } else { - ts_nsec = (uint64_t) ((double) timestamp * 1000000000.0 - / (double) stream->current_clock->freq); + ts_nsec = ctf_get_timestamp(stream, timestamp); } - /* Add offsets */ - if (!opt_clock_raw) { - ts_nsec += tc_offset; - } + /* Add command-line offset */ ts_sec += opt_clock_offset; ts_sec += ts_nsec / NSEC_PER_SEC; @@ -216,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; @@ -330,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; @@ -494,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; @@ -510,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; @@ -534,16 +641,25 @@ void ctf_packet_seek(struct stream_pos *stream_pos, size_t index, int whence) * be printed in the output. */ if (file_stream->parent.events_discarded) { - fflush(stdout); - fprintf(stderr, "[warning] Tracer discarded %d 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"); - fflush(stderr); + /* + * We need to check if we are in trace + * read or called from packet indexing. + * In this last case, the collection is + * not there, so we cannot print the + * timestamps. + */ + if ((&file_stream->parent)->stream_class->trace->collection) { + fflush(stdout); + 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 recording a new trace with larger buffers or with fewer events enabled.\n"); + fflush(stderr); + } file_stream->parent.events_discarded = 0; } pos->offset = EOF; @@ -685,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; } @@ -744,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; @@ -759,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; @@ -868,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); @@ -878,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 = @@ -906,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: @@ -917,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; @@ -967,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; @@ -981,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); } @@ -1001,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; @@ -1073,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; @@ -1179,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 */ @@ -1216,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; @@ -1309,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; @@ -1330,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; } @@ -1442,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; @@ -1581,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); @@ -1596,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;