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[] = {
.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.
*/
switch (whence) {
case SEEK_CUR:
{
- uint32_t events_discarded_diff;
+ uint64_t events_discarded_diff;
if (pos->offset == EOF) {
return;
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;
*/
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;
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);
struct definition_struct, p);
stream->parent_def_scope = stream_event->event_fields->p.scope;
}
+ stream_event->stream = stream;
return stream_event;
error:
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 */
if (packet_index.packet_size > ((uint64_t)filestats.st_size - packet_index.offset) * CHAR_BIT) {
fprintf(stderr, "[error] Packet size (%" PRIu64 " bits) is larger than remaining file size (%" PRIu64 " bits).\n",
- packet_index.content_size, ((uint64_t)filestats.st_size - packet_index.offset) * CHAR_BIT);
+ packet_index.packet_size, ((uint64_t)filestats.st_size - packet_index.offset) * CHAR_BIT);
return -EINVAL;
}
/* 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;
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;
}
}
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);
}