[lttng-dev] [BABELTRACE PATCH v3] Add BT_SEEK_LAST type to bt_iter_pos

Julien Desfossez jdesfossez at efficios.com
Thu Aug 16 19:31:26 EDT 2012


From: Francis Deslauriers <francis.deslauriers at polymtl.ca>

Signed-off-by: Francis Deslauriers <francis.deslauriers at polymtl.ca>
Signed-off-by: Julien Desfossez <jdesfossez at efficios.com>
---
 include/babeltrace/iterator.h |    1 +
 lib/iterator.c                |  192 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 193 insertions(+)

diff --git a/include/babeltrace/iterator.h b/include/babeltrace/iterator.h
index aa6470e..c13055d 100644
--- a/include/babeltrace/iterator.h
+++ b/include/babeltrace/iterator.h
@@ -48,6 +48,7 @@ struct bt_iter_pos {
 		BT_SEEK_CUR,
 		BT_SEEK_BEGIN,
 		BT_SEEK_END,
+		BT_SEEK_LAST,
 	} type;
 	union {
 		uint64_t seek_time;
diff --git a/lib/iterator.c b/lib/iterator.c
index f5f413e..b7ab2b5 100644
--- a/lib/iterator.c
+++ b/lib/iterator.c
@@ -187,6 +187,179 @@ static int seek_ctf_trace_by_timestamp(struct ctf_trace *tin,
 	return found ? 0 : EOF;
 }
 
+static int seek_last_element_ctf_file_stream(struct trace_collection *tc,
+		struct ctf_file_stream **cfs, int max_packet,
+		int max_stream_id, int max_stream_class_id,
+		int max_trace_descriptor_id, uint64_t max_timestamp)
+{
+	int ret;
+	struct trace_descriptor *max_td_read;
+	struct ctf_trace *max_tin;
+	struct ctf_stream_declaration *max_stream_class;
+	struct ctf_stream_definition *max_stream;
+	struct ctf_stream_pos *max_stream_pos;
+
+	max_td_read = g_ptr_array_index(tc->array,
+					max_trace_descriptor_id);
+	max_tin = container_of(max_td_read,
+				struct ctf_trace, parent);
+	max_stream_class = g_ptr_array_index(max_tin->streams,
+						max_stream_class_id);
+	max_stream = g_ptr_array_index(max_stream_class->streams,
+					max_stream_id);
+	*cfs = container_of(max_stream,
+				struct ctf_file_stream, parent);
+	max_stream_pos = &(*cfs)->pos;
+	/* we seek to the last packet of the stream. */
+	max_stream_pos->packet_seek(&max_stream_pos->parent,
+			max_packet, SEEK_SET);
+	/*
+	 * iterate over every event until we reach on an event that
+	 * its timestamp correspond with the max saved previously.
+	 */
+	do {
+		ret = stream_read_event(*cfs);
+	} while ((*cfs)->parent.real_timestamp != max_timestamp && ret == 0);
+
+	/* Return > 0 if error, 0 if ok or EOF */
+	return ret;
+}
+
+static int find_last_event(struct ctf_file_stream *cfs,
+		uint64_t *timestamp_end, int *packet)
+{
+	int ret = 0, count = 0, event_read = 0, i;
+	uint64_t tmp = 0;
+	struct ctf_stream_pos *stream_pos;
+
+	stream_pos = &cfs->pos;
+	/*
+	 * we start by the last packet as the current one.
+	 * If the current one is empty we go back one packet if possible.
+	 * Check if we have iterated on all the packets.
+	 * If we are not short on packets, we check what
+	 * made us leave the reading event loop.
+	 */
+	for (i = stream_pos->packet_real_index->len - 1; i >= 0 && count == 0; i--) {
+		stream_pos->packet_seek(&stream_pos->parent, i, SEEK_SET);
+		count = 0;
+		/* read each event until we reach the end of the packet */
+		do {
+			tmp = cfs->parent.real_timestamp;
+			ret = stream_read_event(cfs);
+			if (ret == 0) {
+				count++;
+			}
+		} while (ret == 0);
+
+		/* Error */
+		if (ret > 0) {
+			goto end;
+		}
+		event_read += count;
+		if (!count) {
+			break;
+		}
+	}
+	*packet = i;
+	*timestamp_end = tmp;
+
+	/* Check if we read one or less element and return error if so */
+	if (event_read <= 1) {
+		ret = 1;
+		goto end;
+	}
+	ret = 0;
+
+end:
+	return ret;
+}
+
+static int find_max_timestamp_ctf_file_stream(
+		struct ctf_stream_declaration *stream_class, int *max_stream_id,
+		int *packet, uint64_t *max_timestamp, int *new_max)
+{
+	struct ctf_file_stream *cfs;
+	int max_packet = 0, ret = 0, error = 1, i;
+	uint64_t savedtime;
+
+	for (i = 0; i < stream_class->streams->len; i++) {
+		struct ctf_stream_definition *stream;
+
+		stream = g_ptr_array_index(stream_class->streams, i);
+		if (!stream)
+			continue;
+		cfs = container_of(stream, struct ctf_file_stream, parent);
+		ret = find_last_event(cfs, &savedtime, &max_packet);
+		/* Can return either EOF, 0, or error (> 0). */
+		if (ret == 0 && savedtime >= *max_timestamp) {
+			*new_max = 1;
+			*max_stream_id = i;
+			*packet = max_packet;
+			*max_timestamp = savedtime;
+		}
+		/*
+		 * if one of the return values is equal to 0 than
+		 * error equals 0
+		 */
+		error = error & ret;
+	}
+	return error;
+}
+
+static int seek_last_ctf_file_stream(struct trace_collection *tc,
+		struct ctf_file_stream **cfs)
+{
+	int i, j, ret, new_max_found, max_packet, max_stream_id,
+			max_stream_class_id, max_trace_descriptor_id;
+	int found = 0;
+	uint64_t max_timestamp = 0;
+
+	if (!tc)
+		return -EINVAL;
+
+	/* For each trace in the trace_collection */
+	for (i = 0; i < tc->array->len; i++) {
+		struct ctf_trace *tin;
+		struct trace_descriptor *td_read;
+		td_read = g_ptr_array_index(tc->array, i);
+		if (!td_read)
+			continue;
+		tin = container_of(td_read, struct ctf_trace, parent);
+		/* For each stream_class in the trace */
+		for (j = 0; j < tin->streams->len; j++) {
+			struct ctf_stream_declaration *stream_class;
+
+			stream_class = g_ptr_array_index(tin->streams, j);
+			if (!stream_class)
+				continue;
+			/* For each file_stream in the stream_class */
+			new_max_found = 0;
+			ret = find_max_timestamp_ctf_file_stream(stream_class,
+					&max_stream_id, &max_packet,
+					&max_timestamp, &new_max_found);
+			if (!ret && new_max_found) {
+				found = 1;
+				max_trace_descriptor_id = i;
+				max_stream_class_id = j;
+			}
+		}
+	}
+	/*
+	 * Now we know in which trace, stream_class and stream is the
+	 * last event of the trace_collection.
+	 * We can seek to this targeted event.
+	 */
+	if (!found) {
+		ret = -1;
+	} else {
+		ret = seek_last_element_ctf_file_stream(tc, cfs, max_packet,
+				max_stream_id, max_stream_class_id,
+				max_trace_descriptor_id, max_timestamp);
+	}
+	return ret;
+}
+
 int bt_iter_set_pos(struct bt_iter *iter, const struct bt_iter_pos *iter_pos)
 {
 	struct trace_collection *tc;
@@ -329,6 +502,25 @@ int bt_iter_set_pos(struct bt_iter *iter, const struct bt_iter_pos *iter_pos)
 			}
 		}
 		break;
+	case BT_SEEK_LAST:
+	{
+		struct ctf_file_stream *cfs;
+
+		tc = iter->ctx->tc;
+		ret = seek_last_ctf_file_stream(tc, &cfs);
+		if (ret < 0)
+			goto error;
+		/* remove all stream from the heap */
+		heap_free(iter->stream_heap);
+		/* Create a new empty heap */
+		ret = heap_init(iter->stream_heap, 0, stream_compare);
+		if (ret < 0)
+			goto error;
+		/* Insert the stream that contains the last event */
+		heap_insert(iter->stream_heap, cfs);
+
+		return 0;
+	}
 	default:
 		/* not implemented */
 		return -EINVAL;
-- 
1.7.10.4




More information about the lttng-dev mailing list