int bt_iter_next(struct bt_iter *iter) { struct ctf_file_stream *file_stream, *removed; int ret; bool event_outside_interval = false; if (!iter) return -EINVAL; file_stream = bt_heap_maximum(iter->stream_heap); if (!file_stream) { /* end of file for all streams */ ret = 0; goto end; } ret = stream_read_event(file_stream); if (file_stream->pos.parent.trace && file_stream->pos.parent.trace->interval_set) { event_outside_interval = file_stream->parent.real_timestamp > file_stream->pos.parent.trace->interval_real.timestamp_end; } if (ret == EOF || event_outside_interval) { removed = bt_heap_remove(iter->stream_heap); assert(removed == file_stream); ret = 0; goto end; } else if (ret == EAGAIN) { /* * Live streaming: the stream is inactive for now, we * just updated the timestamp_end to skip over this * stream up to a certain point in time. * * Since we can't guarantee that a stream will ever have * any activity, we can't rely on the fact that * bt_iter_next will be called for each stream and deal * with inactive streams. So instead, we return 0 here * to the caller and let the read API handle the * retry case. */ ret = 0; goto reinsert; } else if (ret) { goto end; } reinsert: /* Reinsert the file stream into the heap, and rebalance. */ removed = bt_heap_replace_max(iter->stream_heap, file_stream); assert(removed == file_stream); end: return ret; }
struct bt_iter_pos *bt_iter_get_pos(struct bt_iter *iter) { struct bt_iter_pos *pos; struct trace_collection *tc; struct ctf_file_stream *file_stream = NULL, *removed; struct ptr_heap iter_heap_copy; int ret; if (!iter) return NULL; tc = iter->ctx->tc; pos = g_new0(struct bt_iter_pos, 1); pos->type = BT_SEEK_RESTORE; pos->u.restore = g_new0(struct bt_saved_pos, 1); pos->u.restore->tc = tc; pos->u.restore->stream_saved_pos = g_array_new(FALSE, TRUE, sizeof(struct stream_saved_pos)); if (!pos->u.restore->stream_saved_pos) goto error; ret = bt_heap_copy(&iter_heap_copy, iter->stream_heap); if (ret < 0) goto error_heap; /* iterate over each stream in the heap */ file_stream = bt_heap_maximum(&iter_heap_copy); while (file_stream != NULL) { struct stream_saved_pos saved_pos; assert(file_stream->pos.last_offset != LAST_OFFSET_POISON); saved_pos.offset = file_stream->pos.last_offset; saved_pos.file_stream = file_stream; saved_pos.cur_index = file_stream->pos.cur_index; saved_pos.current_real_timestamp = file_stream->parent.real_timestamp; saved_pos.current_cycles_timestamp = file_stream->parent.cycles_timestamp; g_array_append_val( pos->u.restore->stream_saved_pos, saved_pos); printf_debug("stream : %" PRIu64 ", cur_index : %zd, " "offset : %zd, " "timestamp = %" PRIu64 "\n", file_stream->parent.stream_id, saved_pos.cur_index, saved_pos.offset, saved_pos.current_real_timestamp); /* remove the stream from the heap copy */ removed = bt_heap_remove(&iter_heap_copy); assert(removed == file_stream); file_stream = bt_heap_maximum(&iter_heap_copy); } bt_heap_free(&iter_heap_copy); return pos; error_heap: g_array_free(pos->u.restore->stream_saved_pos, TRUE); error: g_free(pos); return NULL; }