Iterators now expose an event providing function so that a user does not
need to know the input trace format to get "bt_ctf_event"s.

A context can now create a specialized iterator depending on its input
trace format.

Signed-off-by: Jérémie Galarneau <[email protected]>
---
 converter/babeltrace.c                 | 10 +++---
 formats/ctf/ctf.c                      |  3 ++
 formats/ctf/iterator.c                 | 34 +++++++++++++-------
 include/babeltrace/context-internal.h  |  1 +
 include/babeltrace/context.h           | 31 ++++++++++++++++++
 include/babeltrace/ctf/iterator.h      |  6 ++--
 include/babeltrace/format.h            | 14 +++++++++
 include/babeltrace/iterator-internal.h |  1 +
 include/babeltrace/iterator.h          | 11 +++++++
 lib/context.c                          | 57 ++++++++++++++++++++++++++++++++++
 lib/iterator.c                         | 14 +++++++++
 tests/lib/test-seeks.c                 | 42 ++++++++++++-------------
 12 files changed, 183 insertions(+), 41 deletions(-)

diff --git a/converter/babeltrace.c b/converter/babeltrace.c
index 8f09845..c86df93 100644
--- a/converter/babeltrace.c
+++ b/converter/babeltrace.c
@@ -617,19 +617,19 @@ static
 int convert_trace(struct bt_trace_descriptor *td_write,
                  struct bt_context *ctx)
 {
-       struct bt_ctf_iter *iter;
+       struct bt_iter *iter;
        struct bt_iter_pos begin_pos;
        struct bt_ctf_event *ctf_event;
        int ret;
        const GPtrArray *out_streams = 
bt_trace_descriptor_get_stream_pos(td_write);
 
        begin_pos.type = BT_SEEK_BEGIN;
-       iter = bt_ctf_iter_create(ctx, &begin_pos, NULL);
+       iter = bt_context_create_iterator(ctx, &begin_pos, NULL);
        if (!iter) {
                ret = -1;
                goto error_iter;
        }
-       while ((ctf_event = bt_ctf_iter_read_event(iter))) {
+       while ((ctf_event = bt_iter_get_event(iter))) {
                int sout_nr;
                for (sout_nr = 0; sout_nr < out_streams->len; ++sout_nr) {
                        struct bt_stream_pos *sout =
@@ -643,7 +643,7 @@ int convert_trace(struct bt_trace_descriptor *td_write,
                                goto end;
                        }
                }
-               ret = bt_iter_next(bt_ctf_get_iter(iter));
+               ret = bt_iter_next(iter);
                if (ret < 0) {
                        goto end;
                }
@@ -651,7 +651,7 @@ int convert_trace(struct bt_trace_descriptor *td_write,
        ret = 0;
 
 end:
-       bt_ctf_iter_destroy(iter);
+       bt_context_destroy_iterator(ctx, iter);
 error_iter:
        return ret;
 }
diff --git a/formats/ctf/ctf.c b/formats/ctf/ctf.c
index aee80b1..c029791 100644
--- a/formats/ctf/ctf.c
+++ b/formats/ctf/ctf.c
@@ -29,6 +29,7 @@
 #include <babeltrace/format.h>
 #include <babeltrace/ctf/types.h>
 #include <babeltrace/ctf/metadata.h>
+#include <babeltrace/ctf/iterator.h>
 #include <babeltrace/babeltrace-internal.h>
 #include <babeltrace/ctf/events-internal.h>
 #include <babeltrace/trace-handle-internal.h>
@@ -144,6 +145,8 @@ struct bt_format ctf_format = {
        .timestamp_begin = ctf_timestamp_begin,
        .timestamp_end = ctf_timestamp_end,
        .convert_index_timestamp = ctf_convert_index_timestamp,
+       .iterator_create = bt_ctf_iter_create,
+       .iterator_destroy = bt_ctf_iter_destroy
 };
 
 static
diff --git a/formats/ctf/iterator.c b/formats/ctf/iterator.c
index d2cd914..a294167 100644
--- a/formats/ctf/iterator.c
+++ b/formats/ctf/iterator.c
@@ -30,6 +30,7 @@
 #include <babeltrace/babeltrace.h>
 #include <babeltrace/format.h>
 #include <babeltrace/ctf/events.h>
+#include <babeltrace/ctf/iterator.h>
 #include <babeltrace/ctf-ir/metadata.h>
 #include <babeltrace/prio_heap.h>
 #include <babeltrace/iterator-internal.h>
@@ -39,7 +40,7 @@
 
 #include "events-private.h"
 
-struct bt_ctf_iter *bt_ctf_iter_create(struct bt_context *ctx,
+struct bt_iter *bt_ctf_iter_create(struct bt_context *ctx,
                const struct bt_iter_pos *begin_pos,
                const struct bt_iter_pos *end_pos)
 {
@@ -60,10 +61,11 @@ struct bt_ctf_iter *bt_ctf_iter_create(struct bt_context 
*ctx,
        iter->recalculate_dep_graph = 0;
        iter->main_callbacks.callback = NULL;
        iter->dep_gc = g_ptr_array_new();
-       return iter;
+       iter->parent.get_event = bt_ctf_iter_read_event;
+       return &iter->parent;
 }
 
-void bt_ctf_iter_destroy(struct bt_ctf_iter *iter)
+void bt_ctf_iter_destroy(struct bt_iter *iter)
 {
        struct bt_stream_callbacks *bt_stream_cb;
        struct bt_callback_chain *bt_chain;
@@ -71,13 +73,16 @@ void bt_ctf_iter_destroy(struct bt_ctf_iter *iter)
 
        assert(iter);
 
+       struct bt_ctf_iter *ctf_iter =
+               container_of(iter, struct bt_ctf_iter, parent);
+
        /* free all events callbacks */
-       if (iter->main_callbacks.callback)
-               g_array_free(iter->main_callbacks.callback, TRUE);
+       if (ctf_iter->main_callbacks.callback)
+               g_array_free(ctf_iter->main_callbacks.callback, TRUE);
 
        /* free per-event callbacks */
-       for (i = 0; i < iter->callbacks->len; i++) {
-               bt_stream_cb = &g_array_index(iter->callbacks,
+       for (i = 0; i < ctf_iter->callbacks->len; i++) {
+               bt_stream_cb = &g_array_index(ctf_iter->callbacks,
                                struct bt_stream_callbacks, i);
                if (!bt_stream_cb || !bt_stream_cb->per_id_callbacks)
                        continue;
@@ -90,10 +95,10 @@ void bt_ctf_iter_destroy(struct bt_ctf_iter *iter)
                }
                g_array_free(bt_stream_cb->per_id_callbacks, TRUE);
        }
-       g_array_free(iter->callbacks, TRUE);
-       g_ptr_array_free(iter->dep_gc, TRUE);
+       g_array_free(ctf_iter->callbacks, TRUE);
+       g_ptr_array_free(ctf_iter->dep_gc, TRUE);
 
-       bt_iter_fini(&iter->parent);
+       bt_iter_fini(iter);
        g_free(iter);
 }
 
@@ -158,9 +163,14 @@ stop:
        return NULL;
 }
 
-struct bt_ctf_event *bt_ctf_iter_read_event(struct bt_ctf_iter *iter)
+struct bt_ctf_event *bt_ctf_iter_read_event(struct bt_iter *iter)
 {
-       return bt_ctf_iter_read_event_flags(iter, NULL);
+       struct bt_ctf_iter *ctf_iter;
+       if (!iter) {
+               return NULL;
+       }
+       ctf_iter = container_of(iter, struct bt_ctf_iter, parent);
+       return bt_ctf_iter_read_event_flags(ctf_iter, NULL);
 }
 
 uint64_t bt_ctf_get_lost_events_count(struct bt_ctf_iter *iter)
diff --git a/include/babeltrace/context-internal.h 
b/include/babeltrace/context-internal.h
index 17d6202..7600d8d 100644
--- a/include/babeltrace/context-internal.h
+++ b/include/babeltrace/context-internal.h
@@ -51,6 +51,7 @@ struct bt_context {
        int refcount;
        int last_trace_handle_id;
        struct bt_iter *current_iterator;
+       struct bt_format *input_trace_format;
 };
 
 #endif /* _BABELTRACE_CONTEXT_INTERNAL_H */
diff --git a/include/babeltrace/context.h b/include/babeltrace/context.h
index b28df09..6455b65 100644
--- a/include/babeltrace/context.h
+++ b/include/babeltrace/context.h
@@ -32,6 +32,7 @@
  */
 
 #include <unistd.h>
+#include <stdio.h>
 #include <babeltrace/format.h>
 
 #ifdef __cplusplus
@@ -96,6 +97,36 @@ int bt_context_add_trace(struct bt_context *ctx, const char 
*path,
 int bt_context_remove_trace(struct bt_context *ctx, int trace_id);
 
 /*
+ * bt_context_create_iterator: Allocate an iterator on the current trace
+ * collection's events.
+ *
+ * begin_pos and end_pos are optional parameters to specify the position
+ * at which the trace collection should be seeked upon iterator
+ * creation, and the position at which iteration will start returning
+ * "EOF".
+ *
+ * By default, if begin_pos is NULL, a BT_SEEK_CUR is performed at
+ * creation. By default, if end_pos is NULL, a BT_SEEK_END (end of
+ * trace) is the EOF criterion.
+ *
+ * Return a pointer to the newly allocated iterator.
+ *
+ * Only one iterator can be created against a context. If more than one
+ * iterator is being created for the same context, the second creation
+ * will return NULL. The previous iterator must be destroyed before
+ * creation of the new iterator for this function to succeed.
+ */
+struct bt_iter *bt_context_create_iterator(struct bt_context *ctx,
+       const struct bt_iter_pos *position_begin,
+       const struct bt_iter_pos *position_end);
+
+/*
+ * bt_context_destroy_iterator: Free a trace collection iterator.
+ */
+void bt_context_destroy_iterator(struct bt_context *ctx,
+                struct bt_iter *iterator);
+
+/*
  * bt_context_get and bt_context_put : increments and decrement the
  * refcount of the context
  *
diff --git a/include/babeltrace/ctf/iterator.h 
b/include/babeltrace/ctf/iterator.h
index ec6aac7..159e4a4 100644
--- a/include/babeltrace/ctf/iterator.h
+++ b/include/babeltrace/ctf/iterator.h
@@ -59,7 +59,7 @@ struct bt_ctf_event;
  * will return NULL. The previous iterator must be destroyed before
  * creation of the new iterator for this function to succeed.
  */
-struct bt_ctf_iter *bt_ctf_iter_create(struct bt_context *ctx,
+struct bt_iter *bt_ctf_iter_create(struct bt_context *ctx,
                const struct bt_iter_pos *begin_pos,
                const struct bt_iter_pos *end_pos);
 
@@ -71,7 +71,7 @@ struct bt_iter *bt_ctf_get_iter(struct bt_ctf_iter *iter);
 /*
  * bt_ctf_iter_destroy - Free a CTF trace collection iterator.
  */
-void bt_ctf_iter_destroy(struct bt_ctf_iter *iter);
+void bt_ctf_iter_destroy(struct bt_iter *iter);
 
 /*
  * bt_ctf_iter_read_event: Read the iterator's current event data.
@@ -80,7 +80,7 @@ void bt_ctf_iter_destroy(struct bt_ctf_iter *iter);
  *
  * Return current event on success, NULL on end of trace.
  */
-struct bt_ctf_event *bt_ctf_iter_read_event(struct bt_ctf_iter *iter);
+struct bt_ctf_event *bt_ctf_iter_read_event(struct bt_iter *iter);
 
 /*
  * bt_ctf_iter_read_event_flags: Read the iterator's current event data.
diff --git a/include/babeltrace/format.h b/include/babeltrace/format.h
index 9f3d1c8..c170d83 100644
--- a/include/babeltrace/format.h
+++ b/include/babeltrace/format.h
@@ -45,6 +45,9 @@ typedef int bt_intern_str;
 struct bt_stream_pos;
 struct bt_context;
 struct bt_trace_handle;
+struct bt_trace_descriptor;
+struct bt_iter;
+struct bt_iter_pos;
 
 struct bt_mmap_stream {
        int fd;
@@ -77,6 +80,17 @@ struct bt_format {
        uint64_t (*timestamp_end)(struct bt_trace_descriptor *descriptor,
                        struct bt_trace_handle *handle, enum bt_clock_type 
type);
        int (*convert_index_timestamp)(struct bt_trace_descriptor *descriptor);
+
+       /*
+        * Only one iterator can be created against a context. If more than one
+        * iterator is being created for the same context, the second creation
+        * will return NULL. The previous iterator must be destroyed before
+        * creation of the new iterator for this function to succeed.
+        */
+       struct bt_iter *(*iterator_create)(struct bt_context *ctx,
+                       const struct bt_iter_pos *begin_pos,
+                       const struct bt_iter_pos *end_pos);
+       void (*iterator_destroy)(struct bt_iter *iterator);
 };
 
 extern struct bt_format *bt_lookup_format(bt_intern_str qname);
diff --git a/include/babeltrace/iterator-internal.h 
b/include/babeltrace/iterator-internal.h
index 2b0b2f2..2008d76 100644
--- a/include/babeltrace/iterator-internal.h
+++ b/include/babeltrace/iterator-internal.h
@@ -39,6 +39,7 @@ struct bt_iter {
        struct ptr_heap *stream_heap;
        struct bt_context *ctx;
        const struct bt_iter_pos *end_pos;
+       struct bt_ctf_event *(*get_event)(struct bt_iter *iter);
 };
 
 /*
diff --git a/include/babeltrace/iterator.h b/include/babeltrace/iterator.h
index 360a9c7..aa189a8 100644
--- a/include/babeltrace/iterator.h
+++ b/include/babeltrace/iterator.h
@@ -27,6 +27,7 @@
 
 #include <babeltrace/format.h>
 #include <babeltrace/context.h>
+#include <stdint.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -40,6 +41,7 @@ enum {
 /* Forward declarations */
 struct bt_iter;
 struct bt_saved_pos;
+struct bt_ctf_event;
 
 /*
  * bt_iter is an abstract class, each format has to implement its own
@@ -123,6 +125,15 @@ int bt_iter_set_pos(struct bt_iter *iter, const struct 
bt_iter_pos *pos);
 struct bt_iter_pos *bt_iter_create_time_pos(struct bt_iter *iter,
                uint64_t timestamp);
 
+/*
+ * bt_iter_get_event: Get the iterator's current event data
+ *
+ * @iter trace collection iterator (input). Should not be NULL.
+ *
+ * Return current event on success, NULL on end of trace.
+ */
+struct bt_ctf_event *bt_iter_get_event(struct bt_iter *iter);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/context.c b/lib/context.c
index dc77366..61215a3 100644
--- a/lib/context.c
+++ b/lib/context.c
@@ -87,6 +87,12 @@ int bt_context_add_trace(struct bt_context *ctx, const char 
*path,
                ret = -1;
                goto end;
        }
+       if (ctx->input_trace_format && ctx->input_trace_format != fmt) {
+               fprintf(stderr, "[error] [Context] Opening traces of different 
formats in the same context is not supported.\n");
+               ret = -1;
+               goto end;
+       }
+       ctx->input_trace_format = fmt;
        if (path) {
                td = fmt->open_trace(path, O_RDONLY, packet_seek, NULL);
                if (!td) {
@@ -211,3 +217,54 @@ void bt_context_put(struct bt_context *ctx)
        if (ctx->refcount == 0)
                bt_context_destroy(ctx);
 }
+
+struct bt_iter *bt_context_create_iterator(struct bt_context *ctx,
+                       const struct bt_iter_pos *position_begin,
+                       const struct bt_iter_pos *position_end)
+{
+       struct bt_iter *iter = NULL;
+       struct bt_format *fmt;
+       assert(ctx);
+
+       if (!ctx->input_trace_format) {
+               fprintf(stderr, "[error] No trace opened in context.\n");
+               goto end;
+       }
+       fmt = ctx->input_trace_format;
+       if (!fmt->iterator_create) {
+               fprintf(stderr, "[error] The %s format plug-in did not register 
an iterator creation function.\n", g_quark_to_string(fmt->name));
+               goto end;
+       }
+       iter = fmt->iterator_create(ctx, position_begin, position_end);
+
+       if (!ctx->current_iterator) {
+               fprintf(stderr, "[error] The %s format plug-in did not call 
bt_iter_init in its iterator creation function.\n",
+                       g_quark_to_string(fmt->name));
+       }
+
+end:
+       return iter;
+}
+
+void bt_context_destroy_iterator(struct bt_context *ctx,
+                       struct bt_iter *iter)
+{
+       struct bt_format *fmt;
+       assert(ctx);
+
+       if (!ctx->input_trace_format) {
+               fprintf(stderr, "[error] No trace opened in context.\n");
+               return;
+       }
+       fmt = ctx->input_trace_format;
+       if (!fmt->iterator_destroy) {
+               fprintf(stderr, "[error] The %s format plug-in did not register 
an iterator destruction function.\n",
+                       g_quark_to_string(fmt->name));
+               return;
+       }
+       fmt->iterator_destroy(iter);
+       if (ctx->current_iterator) {
+               fprintf(stderr, "[warn] The %s format plug-in did not call 
bt_iter_fini in its iterator destruction function.\n",
+                       g_quark_to_string(fmt->name));
+       }
+}
diff --git a/lib/iterator.c b/lib/iterator.c
index 4190e65..b838000 100644
--- a/lib/iterator.c
+++ b/lib/iterator.c
@@ -805,3 +805,17 @@ int bt_iter_next(struct bt_iter *iter)
 end:
        return ret;
 }
+
+struct bt_ctf_event *bt_iter_get_event(struct bt_iter *iter)
+{
+       struct bt_ctf_event *event;
+       if (!iter->get_event) {
+               event = NULL;
+               fprintf(stderr, "[error] No get_event callback registered by 
the output plug-in.\n");
+               goto end;
+       }
+       event = iter->get_event(iter);
+
+end:
+       return event;
+}
diff --git a/tests/lib/test-seeks.c b/tests/lib/test-seeks.c
index 47bb42e..69e4d4b 100644
--- a/tests/lib/test-seeks.c
+++ b/tests/lib/test-seeks.c
@@ -37,7 +37,7 @@
 void run_seek_begin(char *path, uint64_t expected_begin)
 {
        struct bt_context *ctx;
-       struct bt_ctf_iter *iter;
+       struct bt_iter *iter;
        struct bt_ctf_event *event;
        struct bt_iter_pos newpos;
        int ret;
@@ -51,12 +51,12 @@ void run_seek_begin(char *path, uint64_t expected_begin)
        }
 
        /* Create iterator with null begin and end */
-       iter = bt_ctf_iter_create(ctx, NULL, NULL);
+       iter = bt_context_create_iterator(ctx, NULL, NULL);
        if (!iter) {
                plan_skip_all("Cannot create valid iterator");
        }
 
-       event = bt_ctf_iter_read_event(iter);
+       event = bt_iter_get_event(iter);
 
        ok(event, "Event valid");
 
@@ -67,7 +67,7 @@ void run_seek_begin(char *path, uint64_t expected_begin)
 
        /* Validate that we get the same value after a seek begin */
        newpos.type = BT_SEEK_BEGIN;
-       ret = bt_iter_set_pos(bt_ctf_get_iter(iter), &newpos);
+       ret = bt_iter_set_pos(iter, &newpos);
 
        ok(ret == 0, "Seek begin retval %d", ret);
 
@@ -86,7 +86,7 @@ void run_seek_begin(char *path, uint64_t expected_begin)
 void run_seek_last(char *path, uint64_t expected_last)
 {
        struct bt_context *ctx;
-       struct bt_ctf_iter *iter;
+       struct bt_iter *iter;
        struct bt_ctf_event *event;
        struct bt_iter_pos newpos;
        int ret;
@@ -99,18 +99,18 @@ void run_seek_last(char *path, uint64_t expected_last)
        }
 
        /* Create iterator with null last and end */
-       iter = bt_ctf_iter_create(ctx, NULL, NULL);
+       iter = bt_context_create_iterator(ctx, NULL, NULL);
        if (!iter) {
                plan_skip_all("Cannot create valid iterator");
        }
 
-       event = bt_ctf_iter_read_event(iter);
+       event = bt_iter_get_event(iter);
 
        ok(event, "Event valid at beginning");
 
        /* Seek to last */
        newpos.type = BT_SEEK_LAST;
-       ret = bt_iter_set_pos(bt_ctf_get_iter(iter), &newpos);
+       ret = bt_iter_set_pos(iter, &newpos);
 
        ok(ret == 0, "Seek last retval %d", ret);
 
@@ -123,11 +123,11 @@ void run_seek_last(char *path, uint64_t expected_last)
        ok1(timestamp_last == expected_last);
 
        /* Try to read next event */
-       ret = bt_iter_next(bt_ctf_get_iter(iter));
+       ret = bt_iter_next(iter);
 
        ok(ret == 0, "iter next should return an error");
 
-       event = bt_ctf_iter_read_event(iter);
+       event = bt_iter_get_event(iter);
 
        ok(event == 0, "Event after last should be invalid");
 
@@ -139,7 +139,7 @@ void run_seek_cycles(char *path,
                uint64_t expected_last)
 {
        struct bt_context *ctx;
-       struct bt_ctf_iter *iter;
+       struct bt_iter *iter;
        struct bt_ctf_event *event;
        struct bt_iter_pos newpos;
        int ret;
@@ -152,22 +152,22 @@ void run_seek_cycles(char *path,
        }
 
        /* Create iterator with null last and end */
-       iter = bt_ctf_iter_create(ctx, NULL, NULL);
+       iter = bt_context_create_iterator(ctx, NULL, NULL);
        if (!iter) {
                plan_skip_all("Cannot create valid iterator");
        }
 
-       event = bt_ctf_iter_read_event(iter);
+       event = bt_iter_get_event(iter);
 
        ok(event, "Event valid at beginning");
 
        /* Seek to last */
        newpos.type = BT_SEEK_LAST;
-       ret = bt_iter_set_pos(bt_ctf_get_iter(iter), &newpos);
+       ret = bt_iter_set_pos(iter, &newpos);
 
        ok(ret == 0, "Seek last retval %d", ret);
 
-       event = bt_ctf_iter_read_event(iter);
+       event = bt_iter_get_event(iter);
 
        ok(event, "Event valid at last position");
 
@@ -176,21 +176,21 @@ void run_seek_cycles(char *path,
        ok1(timestamp == expected_last);
 
        /* Try to read next event */
-       ret = bt_iter_next(bt_ctf_get_iter(iter));
+       ret = bt_iter_next(iter);
 
        ok(ret == 0, "iter next should return an error");
 
-       event = bt_ctf_iter_read_event(iter);
+       event = bt_iter_get_event(iter);
 
        ok(event == 0, "Event after last should be invalid");
 
        /* Seek to BEGIN */
        newpos.type = BT_SEEK_BEGIN;
-       ret = bt_iter_set_pos(bt_ctf_get_iter(iter), &newpos);
+       ret = bt_iter_set_pos(iter, &newpos);
 
        ok(ret == 0, "Seek begin retval %d", ret);
 
-       event = bt_ctf_iter_read_event(iter);
+       event = bt_iter_get_event(iter);
 
        ok(event, "Event valid at first position");
 
@@ -200,11 +200,11 @@ void run_seek_cycles(char *path,
 
        /* Seek last again */
        newpos.type = BT_SEEK_LAST;
-       ret = bt_iter_set_pos(bt_ctf_get_iter(iter), &newpos);
+       ret = bt_iter_set_pos(iter, &newpos);
 
        ok(ret == 0, "Seek last retval %d", ret);
 
-       event = bt_ctf_iter_read_event(iter);
+       event = bt_iter_get_event(iter);
 
        ok(event, "Event valid at last position");
 
-- 
1.8.2.3


_______________________________________________
lttng-dev mailing list
[email protected]
http://lists.lttng.org/cgi-bin/mailman/listinfo/lttng-dev

Reply via email to