Пример #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;
}
Пример #2
0
struct bt_ctf_event *bt_ctf_iter_read_event_flags(struct bt_ctf_iter *iter,
		int *flags)
{
	struct ctf_file_stream *file_stream;
	struct bt_ctf_event *ret;
	struct ctf_stream_definition *stream;
	struct packet_index *packet_index;

	/*
	 * We do not want to fail for any other reason than end of
	 * trace, hence the assert.
	 */
	assert(iter);

	ret = &iter->current_ctf_event;
	file_stream = bt_heap_maximum(iter->parent.stream_heap);
	if (!file_stream) {
		/* end of file for all streams */
		goto stop;
	}
	stream = &file_stream->parent;
	ret->parent = g_ptr_array_index(stream->events_by_id,
			stream->event_id);

	if (flags)
		*flags = 0;
	if (!file_stream->pos.packet_cycles_index)
		packet_index = NULL;
	else
		packet_index = &g_array_index(file_stream->pos.packet_cycles_index,
				struct packet_index, file_stream->pos.cur_index);
	iter->events_lost = 0;
	if (packet_index && packet_index->events_discarded >
			file_stream->pos.last_events_discarded) {
		if (flags)
			*flags |= BT_ITER_FLAG_LOST_EVENTS;
		iter->events_lost += packet_index->events_discarded -
			file_stream->pos.last_events_discarded;
		file_stream->pos.last_events_discarded =
			packet_index->events_discarded;
	}

	if (ret->parent->stream->stream_id > iter->callbacks->len)
		goto end;

	process_callbacks(iter, ret->parent->stream);

end:
	return ret;
stop:
	return NULL;
}
Пример #3
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;
}
Пример #4
0
struct bt_ctf_event *bt_ctf_iter_read_event_flags(struct bt_ctf_iter *iter,
		int *flags)
{
	struct ctf_file_stream *file_stream;
	struct bt_ctf_event *ret;
	struct ctf_stream_definition *stream;
	struct packet_index *packet_index;

	/*
	 * We do not want to fail for any other reason than end of
	 * trace, hence the assert.
	 */
	assert(iter);

	if (flags)
		*flags = 0;

	ret = &iter->current_ctf_event;
	file_stream = bt_heap_maximum(iter->parent.stream_heap);
	if (!file_stream) {
		/* end of file for all streams */
		goto stop;
	}

	/*
	 * If the packet is empty (contains only headers or is of size 0), the
	 * caller has to know that we can't read the current event and we need
	 * to do a bt_iter_next.
	 */
	if (file_stream->pos.data_offset == file_stream->pos.content_size
			|| file_stream->pos.content_size == 0) {
		/* More events may come. */
		ret = NULL;
		if (flags)
			*flags |= BT_ITER_FLAG_RETRY;
		goto end;
	}

	stream = &file_stream->parent;
	if (iter->parent.end_pos &&
		iter->parent.end_pos->type == BT_SEEK_TIME &&
		stream->real_timestamp > iter->parent.end_pos->u.seek_time) {
		goto stop;
	}
	ret->parent = g_ptr_array_index(stream->events_by_id,
			stream->event_id);

	if (!file_stream->pos.packet_index)
		packet_index = NULL;
	else
		packet_index = &g_array_index(file_stream->pos.packet_index,
				struct packet_index, file_stream->pos.cur_index);
	iter->events_lost = 0;
	if (packet_index && packet_index->events_discarded >
			file_stream->pos.last_events_discarded) {
		if (flags)
			*flags |= BT_ITER_FLAG_LOST_EVENTS;
		iter->events_lost += packet_index->events_discarded -
			file_stream->pos.last_events_discarded;
		file_stream->pos.last_events_discarded =
			packet_index->events_discarded;
	}

	if (ret->parent->stream->stream_id > iter->callbacks->len)
		goto end;

	process_callbacks(iter, ret->parent->stream);

end:
	return ret;
stop:
	return NULL;
}