Example #1
0
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;
}
Example #2
0
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;
}