From: Jérémie Galarneau Date: Wed, 11 May 2016 17:45:10 +0000 (-0400) Subject: Change behaviour of stream-intersection with multiple traces X-Git-Tag: v1.4.0-rc1~5 X-Git-Url: http://git.efficios.com/?p=babeltrace.git;a=commitdiff_plain;h=837b0013ab8a3851ee975f33a10726289afa7369 Change behaviour of stream-intersection with multiple traces 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 --- diff --git a/bindings/python/babeltrace.i.in b/bindings/python/babeltrace.i.in index aaa10209..4fee29d1 100644 --- a/bindings/python/babeltrace.i.in +++ b/bindings/python/babeltrace.i.in @@ -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): diff --git a/bindings/python/python-complements.c b/bindings/python/python-complements.c index 6b47ff9b..b9a11f14 100644 --- a/bindings/python/python-complements.c +++ b/bindings/python/python-complements.c @@ -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; } diff --git a/bindings/python/python-complements.h b/bindings/python/python-complements.h index 0e787d62..3176ba64 100644 --- a/bindings/python/python-complements.h +++ b/bindings/python/python-complements.h @@ -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); diff --git a/formats/ctf-text/ctf-text.c b/formats/ctf-text/ctf-text.c index afdc07c1..ddf41a54 100644 --- a/formats/ctf-text/ctf-text.c +++ b/formats/ctf-text/ctf-text.c @@ -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; diff --git a/formats/ctf/ctf.c b/formats/ctf/ctf.c index e0f6cb89..c960ef72 100644 --- a/formats/ctf/ctf.c +++ b/formats/ctf/ctf.c @@ -27,6 +27,7 @@ */ #include +#include #include #include #include @@ -68,10 +69,6 @@ */ #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: diff --git a/formats/ctf/iterator.c b/formats/ctf/iterator.c index 6f8eb88a..7ef3e0b1 100644 --- a/formats/ctf/iterator.c +++ b/formats/ctf/iterator.c @@ -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; diff --git a/include/babeltrace/babeltrace-internal.h b/include/babeltrace/babeltrace-internal.h index f11672b1..a903c686 100644 --- a/include/babeltrace/babeltrace-internal.h +++ b/include/babeltrace/babeltrace-internal.h @@ -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 */ diff --git a/include/babeltrace/ctf/events-internal.h b/include/babeltrace/ctf/events-internal.h index f1e6df81..09786593 100644 --- a/include/babeltrace/ctf/events-internal.h +++ b/include/babeltrace/ctf/events-internal.h @@ -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 */ diff --git a/include/babeltrace/format-internal.h b/include/babeltrace/format-internal.h index 7f3eb5ef..78f2fd55 100644 --- a/include/babeltrace/format-internal.h +++ b/include/babeltrace/format-internal.h @@ -32,6 +32,7 @@ #include #include #include +#include #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 diff --git a/lib/iterator.c b/lib/iterator.c index 4ee0d5d2..70f25edd 100644 --- a/lib/iterator.c +++ b/lib/iterator.c @@ -28,6 +28,7 @@ #include #include +#include #include #include #include @@ -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;