Change behaviour of stream-intersection with multiple traces
authorJérémie Galarneau <jeremie.galarneau@efficios.com>
Wed, 11 May 2016 17:45:10 +0000 (13:45 -0400)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Fri, 13 May 2016 19:52:01 +0000 (15:52 -0400)
The stream-intersection currently results in the reading of
the intersection of every stream, in every trace of a Trace
Collection.

Since reading a TraceCollection returns the union of its traces,
the behaviour of this option is changed so that it returns the
union of each trace's individual "active" section, that is the
section for which all streams are active.

Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
bindings/python/babeltrace.i.in
bindings/python/python-complements.c
bindings/python/python-complements.h
formats/ctf-text/ctf-text.c
formats/ctf/ctf.c
formats/ctf/iterator.c
include/babeltrace/babeltrace-internal.h
include/babeltrace/ctf/events-internal.h
include/babeltrace/format-internal.h
lib/iterator.c

index aaa102094d6740da590c93ba831b124516b592e4..4fee29d1d678db8632f4db3fb607536e7ba87267 100644 (file)
@@ -104,7 +104,7 @@ struct bt_ctf_iter *_bt_python_ctf_iter_create_intersect(
                struct bt_context *ctx,
                struct bt_iter_pos *inter_begin_pos,
                struct bt_iter_pos *inter_end_pos);
-int _bt_python_has_intersection(struct bt_context *ctx);
+int _bt_python_trace_collection_has_intersection(struct bt_context *ctx);
 
 /* =================================================================
                CONTEXT.H, CONTEXT-INTERNAL.H
@@ -219,7 +219,7 @@ class TraceCollection:
 
        @property
        def has_intersection(self):
-               return _bt_python_has_intersection(self._tc)
+               return _bt_python_trace_collection_has_intersection(self._tc)
 
        @property
        def events(self):
index 6b47ff9bf9aaaaac16213b00e9cb854c9752b89f..b9a11f1410d880cee18e777b3e8846269ce938b0 100644 (file)
@@ -261,12 +261,12 @@ struct bt_ctf_iter *_bt_python_ctf_iter_create_intersect(
                        &inter_end_pos);
 }
 
-int _bt_python_has_intersection(struct bt_context *ctx)
+int _bt_python_trace_collection_has_intersection(struct bt_context *ctx)
 {
        int ret;
-       uint64_t begin = 0, end = ULLONG_MAX;
+       int64_t begin, end;
 
-       ret = ctf_find_packets_intersection(ctx, &begin, &end);
+       ret = ctf_find_tc_stream_packet_intersection_union(ctx, &begin, &end);
 
        return ret == 0 ? 1 : 0;
 }
index 0e787d62d81eb81e1552463a67214b78f68e6191..3176ba64ede94c6c4399b21a968eba6c634e6873 100644 (file)
@@ -78,4 +78,4 @@ struct bt_ctf_iter *_bt_python_ctf_iter_create_intersect(
                struct bt_context *ctx,
                struct bt_iter_pos *inter_begin_pos,
                struct bt_iter_pos *inter_end_pos);
-int _bt_python_has_intersection(struct bt_context *ctx);
+int _bt_python_trace_collection_has_intersection(struct bt_context *ctx);
index afdc07c1d80576c367743e0e49a25e98c5fe17aa..ddf41a54b107e765bb1fb7c3a1cfba537d3e430f 100644 (file)
@@ -547,6 +547,10 @@ struct bt_trace_descriptor *ctf_text_open_trace(const char *path, int flags,
        FILE *fp;
 
        pos = g_new0(struct ctf_text_stream_pos, 1);
+       if (!pos) {
+               goto error;
+       }
+       init_trace_descriptor(&pos->trace_descriptor);
 
        pos->last_real_timestamp = -1ULL;
        pos->last_cycles_timestamp = -1ULL;
index e0f6cb89431646c19cbcca62f85696f67249699b..c960ef7291d49ee635d15165e51a2134b9069152 100644 (file)
@@ -27,6 +27,7 @@
  */
 
 #include <babeltrace/format.h>
+#include <babeltrace/format-internal.h>
 #include <babeltrace/ctf/types.h>
 #include <babeltrace/ctf/metadata.h>
 #include <babeltrace/babeltrace-internal.h>
  */
 #define WRITE_PACKET_LEN       (getpagesize() * 8 * CHAR_BIT)
 
-#ifndef min
-#define min(a, b)      (((a) < (b)) ? (a) : (b))
-#endif
-
 #define NSEC_PER_SEC 1000000000ULL
 
 #define INDEX_PATH "./index/%s.idx"
@@ -880,13 +877,25 @@ void ctf_update_current_packet_index(struct ctf_stream_definition *stream,
  * empty streams and return a negative value on error.
  */
 static
-int ctf_intersect_trace(struct bt_trace_descriptor *td_read,
-               uint64_t *begin, uint64_t *end)
+int ctf_find_stream_intersection(struct bt_trace_descriptor *td_read,
+               struct packet_index_time *_real,
+               struct packet_index_time *_cycles)
 {
-       struct ctf_trace *tin;
        int stream_id, ret = 0;
+       struct packet_index_time real = { 0, UINT64_MAX },
+                       cycles = { 0, UINT64_MAX };
+       struct ctf_trace *tin = container_of(td_read, struct ctf_trace, parent);
 
-       tin = container_of(td_read, struct ctf_trace, parent);
+       /* At least one of the two return args must be provided. */
+       if (!_real && !_cycles) {
+               ret = -1;
+               goto end;
+       }
+
+       if (tin->streams->len == 0) {
+               ret = 1;
+               goto end;
+       }
 
        for (stream_id = 0; stream_id < tin->streams->len;
                        stream_id++) {
@@ -915,56 +924,111 @@ int ctf_intersect_trace(struct bt_trace_descriptor *td_read,
                        }
                        index = &g_array_index(stream_pos->packet_index,
                                        struct packet_index, 0);
-                       if (index->ts_real.timestamp_begin > *begin) {
-                               *begin = index->ts_real.timestamp_begin;
-                       }
+                       real.timestamp_begin = max(real.timestamp_begin,
+                                       index->ts_real.timestamp_begin);
+                       cycles.timestamp_begin = max(cycles.timestamp_begin,
+                                       index->ts_cycles.timestamp_begin);
+
                        index = &g_array_index(stream_pos->packet_index,
                                        struct packet_index,
                                        stream_pos->packet_index->len - 1);
-                       if (index->ts_real.timestamp_end < *end) {
-                               *end = index->ts_real.timestamp_end;
-                       }
+                       real.timestamp_end = min(real.timestamp_end,
+                                       index->ts_real.timestamp_end);
+                       cycles.timestamp_end = min(cycles.timestamp_end,
+                                       index->ts_cycles.timestamp_end);
                }
        }
-
 end:
+       if (ret == 0) {
+               if (_real) {
+                       *_real = real;
+               }
+               if (_cycles) {
+                       *_cycles = cycles;
+               }
+       }
        return ret;
 }
 
 /*
- * Find the timerange where all streams in the trace collection are active
- * simultaneously.
+ * Find the union of all active regions in the trace collection's traces.
+ * Returns "real" timestamps.
  *
  * Return 0 on success.
  * Return 1 if no intersections are found.
  * Return a negative value on error.
  */
-int ctf_find_packets_intersection(struct bt_context *ctx,
-               uint64_t *ts_begin, uint64_t *ts_end)
+int ctf_find_tc_stream_packet_intersection_union(struct bt_context *ctx,
+               uint64_t *_ts_begin, uint64_t *_ts_end)
 {
-       int ret, i;
+       int ret = 0, i;
+       uint64_t ts_begin = UINT64_MAX, ts_end = 0;
 
-       if (!ctx || !ctx->tc || !ctx->tc->array) {
+       if (!ctx || !ctx->tc || !ctx->tc->array || !_ts_begin || !_ts_end) {
                ret = -EINVAL;
                goto end;
        }
 
        for (i = 0; i < ctx->tc->array->len; i++) {
                struct bt_trace_descriptor *td_read;
+               struct packet_index_time intersection_real;
 
                td_read = g_ptr_array_index(ctx->tc->array, i);
                if (!td_read) {
                        continue;
                }
-               ret = ctf_intersect_trace(td_read, ts_begin, ts_end);
-               if (ret) {
+               ret = ctf_find_stream_intersection(td_read, &intersection_real,
+                               NULL);
+               if (ret == 1) {
+                       /* Empty trace or no stream intersection. */
+                       continue;
+               } else if (ret < 0) {
                        goto end;
                }
+
+               ts_begin = min(intersection_real.timestamp_begin, ts_begin);
+               ts_end = max(intersection_real.timestamp_end, ts_end);
        }
-       if (*ts_end < *ts_begin) {
+
+       if (ts_end < ts_begin) {
                ret = 1;
-       } else {
-               ret = 0;
+               goto end;
+       }
+       *_ts_begin = ts_begin;
+       *_ts_end = ts_end;
+end:
+       return ret;
+}
+
+int ctf_tc_set_stream_intersection_mode(struct bt_context *ctx)
+{
+       int ret = 0, i;
+
+       if (!ctx || !ctx->tc || !ctx->tc->array) {
+               ret = -EINVAL;
+               goto end;
+       }
+
+       for (i = 0; i < ctx->tc->array->len; i++) {
+               struct bt_trace_descriptor *td_read;
+               struct packet_index_time intersection_real;
+
+               td_read = g_ptr_array_index(ctx->tc->array, i);
+               if (!td_read) {
+                       continue;
+               }
+
+               ret = ctf_find_stream_intersection(td_read, &intersection_real,
+                               NULL);
+               if (ret == 1) {
+                       /* Empty trace or no stream intersection. */
+                       continue;
+               } else if (ret < 0) {
+                       goto end;
+               }
+
+               td_read->interval_real = intersection_real;
+               td_read->interval_set = true;
        }
 end:
        return ret;
@@ -2337,6 +2401,10 @@ struct bt_trace_descriptor *ctf_open_trace(const char *path, int flags,
                packet_seek = ctf_packet_seek;
 
        td = g_new0(struct ctf_trace, 1);
+       if (!td) {
+               goto error;
+       }
+       init_trace_descriptor(&td->parent);
 
        switch (flags & O_ACCMODE) {
        case O_RDONLY:
index 6f8eb88a9de7b769817de518a1abf56db9e7f115..7ef3e0b1537479941193a26708ef42f605e03563 100644 (file)
@@ -67,10 +67,18 @@ struct bt_ctf_iter *bt_ctf_iter_create_intersect(struct bt_context *ctx,
                struct bt_iter_pos **inter_begin_pos,
                struct bt_iter_pos **inter_end_pos)
 {
-       uint64_t begin = 0, end = ULLONG_MAX;
        int ret;
+       uint64_t begin, end;
 
-       ret = ctf_find_packets_intersection(ctx, &begin, &end);
+       /*
+        * The iterator's range is the union of each trace's intersection of
+        * streams. This means that we determine the "active" region of each
+        * trace (that is the region where all of its streams are active), and
+        * use the TraceCollection to merge all of these active regions.
+        *
+        * This results in a union of the traces' active regions.
+        */
+       ret = ctf_find_tc_stream_packet_intersection_union(ctx, &begin, &end);
        if (ret == 1) {
                fprintf(stderr, "[error] No intersection found between trace files.\n");
                goto error;
@@ -86,6 +94,11 @@ struct bt_ctf_iter *bt_ctf_iter_create_intersect(struct bt_context *ctx,
                goto error;
        }
 
+       ret = ctf_tc_set_stream_intersection_mode(ctx);
+       if (ret) {
+               goto error;
+       }
+
        /*
         * bt_ctf_iter does not take ownership of begin and end positions,
         * so we return them to the caller who must still assume their ownership
@@ -97,7 +110,6 @@ error:
        return NULL;
 }
 
-
 void bt_ctf_iter_destroy(struct bt_ctf_iter *iter)
 {
        struct bt_stream_callbacks *bt_stream_cb;
index f11672b1c0ae749aa5470d04627fcdf1e1ae154e..a903c686965a8bdc918946557c8cdedd6a21fa3c 100644 (file)
@@ -151,6 +151,14 @@ extern int babeltrace_verbose, babeltrace_debug;
 # endif
 #endif
 
+#ifndef min
+#define min(a, b)      (((a) < (b)) ? (a) : (b))
+#endif
+
+#ifndef max
+#define max(a, b)      (((a) > (b)) ? (a) : (b))
+#endif
+
 /*
  * BT_HIDDEN: set the hidden attribute for internal functions
  */
index f1e6df811e3e74c615e47906a18f53240d7b6400..097865937d84bc34af1353126ecab25b2f6d1584 100644 (file)
@@ -84,5 +84,8 @@ int ctf_find_packets_intersection(struct bt_context *ctx,
 void ctf_update_current_packet_index(struct ctf_stream_definition *stream,
                struct packet_index *prev_index,
                struct packet_index *cur_index);
+int ctf_find_tc_stream_packet_intersection_union(struct bt_context *ctx,
+               uint64_t *ts_begin, uint64_t *ts_end);
+int ctf_tc_set_stream_intersection_mode(struct bt_context *ctx);
 
 #endif /*_BABELTRACE_CTF_EVENTS_INTERNAL_H */
index 7f3eb5ef9e723ec9657ae5a8e2c8fb043769d5bc..78f2fd552c8fdf3d6a05ad510b2996321bc8e940 100644 (file)
@@ -32,6 +32,7 @@
 #include <limits.h>
 #include <babeltrace/context-internal.h>
 #include <babeltrace/babeltrace-internal.h>
+#include <babeltrace/ctf/types.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -45,8 +46,20 @@ struct bt_trace_descriptor {
        struct trace_collection *collection;    /* Container of this trace */
        GHashTable *clocks;
        struct ctf_clock *single_clock;         /* currently supports only one clock */
+       bool interval_set;
+       struct packet_index_time interval_real; /* Interval of events to consider */
 };
 
+static inline void init_trace_descriptor(struct bt_trace_descriptor *td) {
+       if (!td) {
+               return;
+       }
+
+       td->interval_real.timestamp_begin = INT64_MIN;
+       td->interval_real.timestamp_end = INT64_MAX;
+       td->interval_set = false;
+}
+
 #ifdef __cplusplus
 }
 #endif
index 4ee0d5d22d454394075e3e3e68c2051d1c9202ba..70f25edd9f0a0948a7820b894fec2bb7143426a3 100644 (file)
@@ -28,6 +28,7 @@
 
 #include <stdlib.h>
 #include <babeltrace/babeltrace.h>
+#include <babeltrace/babeltrace-internal.h>
 #include <babeltrace/context.h>
 #include <babeltrace/context-internal.h>
 #include <babeltrace/iterator-internal.h>
@@ -72,6 +73,7 @@ static int stream_read_event(struct ctf_file_stream *sin)
                fprintf(stderr, "[error] Reading event failed.\n");
                return ret;
        }
+
        return 0;
 }
 
@@ -170,6 +172,16 @@ static int seek_ctf_trace_by_timestamp(struct ctf_trace *tin,
 {
        int i, j, ret;
        int found = 0;
+       struct bt_trace_descriptor *td = &tin->parent;
+
+       if (td->interval_set) {
+               /*
+                * If this trace has an interval selected, don't allow seeks
+                * before the selected interval. We seek to the start of the
+                * interval, thereby presenting a shorter "virtual" trace.
+                */
+               timestamp = max(timestamp, td->interval_real.timestamp_begin);
+       }
 
        /* for each stream_class */
        for (i = 0; i < tin->streams->len; i++) {
@@ -748,6 +760,9 @@ int bt_iter_init(struct bt_iter *iter,
        ctx->current_iterator = iter;
        if (begin_pos && begin_pos->type != BT_SEEK_BEGIN) {
                ret = bt_iter_set_pos(iter, begin_pos);
+               if (ret) {
+                       goto error;
+               }
        }
 
        return ret;
@@ -802,6 +817,7 @@ 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;
@@ -814,7 +830,12 @@ int bt_iter_next(struct bt_iter *iter)
        }
 
        ret = stream_read_event(file_stream);
-       if (ret == EOF) {
+       if (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;
This page took 0.048535 seconds and 4 git commands to generate.