#include <babeltrace/ctf/events-internal.h>
#include <babeltrace/trace-handle-internal.h>
#include <babeltrace/context-internal.h>
-#include <babeltrace/uuid.h>
+#include <babeltrace/compat/uuid.h>
#include <babeltrace/endian.h>
#include <inttypes.h>
#include <stdio.h>
#include "metadata/ctf-parser.h"
#include "metadata/ctf-ast.h"
#include "events-private.h"
-#include "memstream.h"
+#include <babeltrace/compat/memstream.h>
#define LOG2_CHAR_BIT 3
opt_clock_gmt;
uint64_t opt_clock_offset;
+uint64_t opt_clock_offset_ns;
extern int yydebug;
ts_nsec = timestamp;
+ /* Add command-line offset in ns*/
+ ts_nsec += opt_clock_offset_ns;
+
/* Add command-line offset */
ts_sec += opt_clock_offset;
}
fprintf(fp, "] in trace UUID ");
print_uuid(fp, stream->stream_class->trace->uuid);
- if (stream->stream_class->trace->path[0])
+ if (stream->stream_class->trace->parent.path[0])
fprintf(fp, ", at path: \"%s\"",
- stream->stream_class->trace->path);
+ stream->stream_class->trace->parent.path);
fprintf(fp, ", within stream id %" PRIu64, stream->stream_id);
if (stream->path[0])
return ret;
}
-int ctf_init_pos(struct ctf_stream_pos *pos, int fd, int open_flags)
+int ctf_init_pos(struct ctf_stream_pos *pos, struct bt_trace_descriptor *trace,
+ int fd, int open_flags)
{
pos->fd = fd;
if (fd >= 0) {
pos->flags = MAP_PRIVATE;
pos->parent.rw_table = read_dispatch_table;
pos->parent.event_cb = ctf_read_event;
+ pos->parent.trace = trace;
break;
case O_RDWR:
pos->prot = PROT_WRITE; /* Write has priority */
pos->flags = MAP_SHARED;
pos->parent.rw_table = write_dispatch_table;
pos->parent.event_cb = ctf_write_event;
+ pos->parent.trace = trace;
if (fd >= 0)
ctf_packet_seek(&pos->parent, 0, SEEK_SET); /* position for write */
break;
/*
* for SEEK_CUR: go to next packet.
- * for SEEK_POS: go to packet numer (index).
+ * for SEEK_SET: go to packet numer (index).
*/
void ctf_packet_seek(struct bt_stream_pos *stream_pos, size_t index, int whence)
{
off_t off;
struct packet_index *packet_index;
+ switch (whence) {
+ case SEEK_CUR:
+ case SEEK_SET: /* Fall-through */
+ break; /* OK */
+ default:
+ assert(0);
+ }
+
if (pos->prot == PROT_WRITE && pos->content_size_loc)
*pos->content_size_loc = pos->offset;
switch (whence) {
case SEEK_CUR:
/* The writer will add padding */
- pos->mmap_offset += WRITE_PACKET_LEN / CHAR_BIT;
+ pos->mmap_offset += pos->packet_size / CHAR_BIT;
break;
case SEEK_SET:
assert(index == 0); /* only seek supported for now */
if (pos->offset == EOF) {
return;
}
+ assert(pos->cur_index < pos->packet_cycles_index->len);
+ assert(pos->cur_index < pos->packet_real_index->len);
+
/* For printing discarded event count */
packet_index = &g_array_index(pos->packet_cycles_index,
struct packet_index, pos->cur_index);
break;
}
case SEEK_SET:
+ if (index >= pos->packet_cycles_index->len) {
+ pos->offset = EOF;
+ return;
+ }
packet_index = &g_array_index(pos->packet_cycles_index,
struct packet_index, index);
pos->last_events_discarded = packet_index->events_discarded;
* case, the collection is not there, so we
* cannot print the timestamps.
*/
- if ((&file_stream->parent)->stream_class->trace->collection) {
+ if ((&file_stream->parent)->stream_class->trace->parent.collection) {
/*
* When a stream reaches the end of the
* file, we need to show the number of
buflen = strlen(*buf);
if (!buflen) {
*fp = NULL;
- return -ENODATA;
+ return -ENOENT;
}
*fp = babeltrace_fmemopen(*buf, buflen, "rb");
if (!*fp) {
bt_definition_unref(&stream_event->event_fields->p);
if (stream_event->event_context)
bt_definition_unref(&stream_event->event_context->p);
+ fprintf(stderr, "[error] Unable to create event definition for event \"%s\".\n",
+ g_quark_to_string(event->name));
return NULL;
}
if (!event)
continue;
stream_event = create_event_definitions(td, stream, event);
- if (!stream_event)
+ if (!stream_event) {
+ ret = -EINVAL;
goto error_event;
+ }
g_ptr_array_index(stream->events_by_id, i) = stream_event;
}
return 0;
bt_definition_unref(&stream->stream_event_header->p);
if (stream->stream_packet_context)
bt_definition_unref(&stream->stream_packet_context->p);
+ fprintf(stderr, "[error] Unable to create stream (%" PRIu64 ") definitions: %s\n",
+ stream_class->stream_id, strerror(-ret));
return ret;
}
+static
+int stream_assign_class(struct ctf_trace *td,
+ struct ctf_file_stream *file_stream,
+ uint64_t stream_id)
+{
+ struct ctf_stream_declaration *stream;
+ int ret;
+
+ file_stream->parent.stream_id = stream_id;
+ if (stream_id >= td->streams->len) {
+ fprintf(stderr, "[error] Stream %" PRIu64 " is not declared in metadata.\n", stream_id);
+ return -EINVAL;
+ }
+ stream = g_ptr_array_index(td->streams, stream_id);
+ if (!stream) {
+ fprintf(stderr, "[error] Stream %" PRIu64 " is not declared in metadata.\n", stream_id);
+ return -EINVAL;
+ }
+ file_stream->parent.stream_class = stream;
+ ret = create_stream_definitions(td, &file_stream->parent);
+ if (ret)
+ return ret;
+ return 0;
+}
+
static
int create_stream_one_packet_index(struct ctf_stream_pos *pos,
struct ctf_trace *td,
size_t filesize)
{
struct packet_index packet_index;
- struct ctf_stream_declaration *stream;
- int len_index;
uint64_t stream_id = 0;
+ uint64_t packet_map_len = DEFAULT_HEADER_LEN, tmp_map_len;
int first_packet = 0;
- size_t packet_map_len = DEFAULT_HEADER_LEN, tmp_map_len;
+ int len_index;
int ret;
begin:
if (ret) {
if (ret == -EFAULT)
goto retry;
+ fprintf(stderr, "[error] Unable to read packet header: %s\n", strerror(-ret));
return ret;
}
len_index = bt_struct_declaration_lookup_field_index(file_stream->parent.trace_packet_header->declaration, g_quark_from_static_string("magic"));
return -EINVAL;
}
if (first_packet) {
- file_stream->parent.stream_id = stream_id;
- if (stream_id >= td->streams->len) {
- fprintf(stderr, "[error] Stream %" PRIu64 " is not declared in metadata.\n", stream_id);
- return -EINVAL;
- }
- stream = g_ptr_array_index(td->streams, stream_id);
- if (!stream) {
- fprintf(stderr, "[error] Stream %" PRIu64 " is not declared in metadata.\n", stream_id);
- return -EINVAL;
- }
- file_stream->parent.stream_class = stream;
- ret = create_stream_definitions(td, &file_stream->parent);
+ ret = stream_assign_class(td, file_stream, stream_id);
if (ret)
return ret;
}
if (ret) {
if (ret == -EFAULT)
goto retry;
+ fprintf(stderr, "[error] Unable to read packet context: %s\n", strerror(-ret));
return ret;
}
/* read content size from header */
field = bt_struct_definition_get_field_from_index(file_stream->parent.stream_packet_context, len_index);
packet_index.timestamp_begin = bt_get_unsigned_int(field);
- if (file_stream->parent.stream_class->trace->collection) {
+ if (file_stream->parent.stream_class->trace->parent.collection) {
packet_index.timestamp_begin =
ctf_get_real_timestamp(
&file_stream->parent,
field = bt_struct_definition_get_field_from_index(file_stream->parent.stream_packet_context, len_index);
packet_index.timestamp_end = bt_get_unsigned_int(field);
- if (file_stream->parent.stream_class->trace->collection) {
+ if (file_stream->parent.stream_class->trace->parent.collection) {
packet_index.timestamp_end =
ctf_get_real_timestamp(
&file_stream->parent,
tmp_map_len = packet_map_len << 1;
if (tmp_map_len >> 1 != packet_map_len) {
/* Overflow */
+ fprintf(stderr, "[error] Packet mapping length overflow\n");
return -EFAULT;
}
packet_map_len = tmp_map_len;
if (ret < 0)
return ret;
+ /* Deal with empty files */
+ if (!filestats.st_size) {
+ if (file_stream->parent.trace_packet_header
+ || file_stream->parent.stream_packet_context) {
+ /*
+ * We expect a trace packet header and/or stream packet
+ * context. Since a trace needs to have at least one
+ * packet, empty files are therefore not accepted.
+ */
+ fprintf(stderr, "[error] Encountered an empty file, but expecting a trace packet header.\n");
+ return -EINVAL;
+ } else {
+ /*
+ * Without trace packet header nor stream packet
+ * context, a one-packet trace can indeed be empty. This
+ * is only valid if there is only one stream class: 0.
+ */
+ ret = stream_assign_class(td, file_stream, 0);
+ if (ret)
+ return ret;
+ return 0;
+ }
+ }
+
for (pos->mmap_offset = 0; pos->mmap_offset < filestats.st_size; ) {
ret = create_stream_one_packet_index(pos, td, file_stream,
filestats.st_size);
return 0;
error:
+ fprintf(stderr, "[error] Unable to create trace definitions: %s\n", strerror(-ret));
return ret;
}
goto error_def;
}
- ret = ctf_init_pos(&file_stream->pos, fd, flags);
+ ret = ctf_init_pos(&file_stream->pos, &td->parent, fd, flags);
if (ret)
goto error_def;
ret = create_trace_definitions(td, &file_stream->parent);
/*
* For now, only a single clock per trace is supported.
*/
- file_stream->parent.current_clock = td->single_clock;
+ file_stream->parent.current_clock = td->parent.single_clock;
ret = create_stream_packet_index(td, file_stream);
- if (ret)
+ if (ret) {
+ fprintf(stderr, "[error] Stream index creation error.\n");
goto error_index;
+ }
/* Add stream file to stream class */
g_ptr_array_add(file_stream->parent.stream_class->streams,
&file_stream->parent);
ret = -errno;
goto error_dirfd;
}
- strncpy(td->path, path, sizeof(td->path));
- td->path[sizeof(td->path) - 1] = '\0';
+ strncpy(td->parent.path, path, sizeof(td->parent.path));
+ td->parent.path[sizeof(td->parent.path) - 1] = '\0';
/*
* Keep the metadata file separate.
/*
* For now, only a single clock per trace is supported.
*/
- file_stream->parent.current_clock = td->single_clock;
+ file_stream->parent.current_clock = td->parent.single_clock;
/* Add stream file to stream class */
g_ptr_array_add(file_stream->parent.stream_class->streams,
struct ctf_trace *td = container_of(descriptor, struct ctf_trace,
parent);
- td->ctx = ctx;
+ td->parent.ctx = ctx;
}
static
struct ctf_trace *td = container_of(descriptor, struct ctf_trace,
parent);
- td->handle = handle;
+ td->parent.handle = handle;
}
static