+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);
+ if (!stream_class)
+ continue;
+ /* 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);
+ if (!stream_class)
+ continue;
+ /* 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_definition *stream,
+ struct definition_integer *integer_definition)
+{
+ struct declaration_integer *integer_declaration =
+ integer_definition->declaration;
+ uint64_t oldval, newval, updateval;
+
+ if (unlikely(integer_declaration->len == 64)) {
+ stream->timestamp = integer_definition->value._unsigned;
+ return;
+ }
+ /* keep low bits */
+ oldval = stream->timestamp;
+ oldval &= (1ULL << integer_declaration->len) - 1;
+ newval = integer_definition->value._unsigned;
+ /* Test for overflow by comparing low bits */
+ if (newval < oldval)
+ newval += 1ULL << integer_declaration->len;
+ /* updateval contains old high bits, and new low bits (sum) */
+ updateval = stream->timestamp;
+ updateval &= ~((1ULL << integer_declaration->len) - 1);
+ updateval += newval;
+ stream->prev_timestamp = stream->timestamp;
+ stream->timestamp = updateval;
+}
+
+/*
+ * Print timestamp, rescaling clock frequency to nanoseconds and
+ * applying offsets as needed (unix time).
+ */
+void ctf_print_timestamp(FILE *fp,
+ struct ctf_stream_definition *stream,
+ uint64_t timestamp)
+{
+ uint64_t ts_sec = 0, ts_nsec;
+
+ if (opt_clock_raw) {
+ ts_nsec = ctf_get_timestamp_raw(stream, timestamp);
+ } else {
+ ts_nsec = ctf_get_timestamp(stream, timestamp);
+ }
+
+ /* Add command-line offset */
+ ts_sec += opt_clock_offset;
+
+ ts_sec += ts_nsec / NSEC_PER_SEC;
+ ts_nsec = ts_nsec % NSEC_PER_SEC;
+
+ if (!opt_clock_seconds) {
+ struct tm tm;
+ time_t time_s = (time_t) ts_sec;
+
+ if (!opt_clock_gmt) {
+ struct tm *res;
+
+ res = localtime_r(&time_s, &tm);
+ if (!res) {
+ fprintf(stderr, "[warning] Unable to get localtime.\n");
+ goto seconds;
+ }
+ } else {
+ struct tm *res;
+
+ res = gmtime_r(&time_s, &tm);
+ if (!res) {
+ fprintf(stderr, "[warning] Unable to get gmtime.\n");
+ goto seconds;
+ }
+ }
+ if (opt_clock_date) {
+ char timestr[26];
+ size_t res;
+
+ /* Print date and time */
+ res = strftime(timestr, sizeof(timestr),
+ "%F ", &tm);
+ if (!res) {
+ fprintf(stderr, "[warning] Unable to print ascii time.\n");
+ goto seconds;
+ }
+ fprintf(fp, "%s", timestr);
+ }
+ /* Print time in HH:MM:SS.ns */
+ fprintf(fp, "%02d:%02d:%02d.%09" PRIu64,
+ tm.tm_hour, tm.tm_min, tm.tm_sec, ts_nsec);
+ goto end;
+ }
+seconds:
+ fprintf(fp, "%3" PRIu64 ".%09" PRIu64,
+ ts_sec, ts_nsec);
+
+end:
+ return;
+}
+
+static
+int ctf_read_event(struct stream_pos *ppos, struct ctf_stream_definition *stream)