summary |
shortlog |
log |
commit | commitdiff |
tree
raw |
patch |
inline | side by side (from parent 1:
5b48921)
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>
struct bt_context *ctx,
struct bt_iter_pos *inter_begin_pos,
struct bt_iter_pos *inter_end_pos);
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 */
%rename("_bt_context_create") bt_context_create(void);
/* context.h, context-internal.h */
%rename("_bt_context_create") bt_context_create(void);
-int _bt_python_has_intersection(struct bt_context *ctx)
+int _bt_python_trace_collection_has_intersection(struct bt_context *ctx)
- uint64_t begin = 0, end = ULLONG_MAX;
- ret = ctf_find_packets_intersection(ctx, &begin, &end);
+ ret = ctf_find_tc_stream_packet_intersection_union(ctx, &begin, &end);
return ret == 0 ? 1 : 0;
}
return ret == 0 ? 1 : 0;
}
struct bt_context *ctx,
struct bt_iter_pos *inter_begin_pos,
struct bt_iter_pos *inter_end_pos);
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);
@property
def has_intersection(self):
@property
def has_intersection(self):
- return nbt._bt_python_has_intersection(self._tc)
+ return nbt._bt_python_trace_collection_has_intersection(self._tc)
@property
def events(self):
@property
def events(self):
FILE *fp;
pos = g_new0(struct ctf_text_stream_pos, 1);
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;
pos->last_real_timestamp = -1ULL;
pos->last_cycles_timestamp = -1ULL;
*/
#include <babeltrace/format.h>
*/
#include <babeltrace/format.h>
+#include <babeltrace/format-internal.h>
#include <babeltrace/ctf/types.h>
#include <babeltrace/ctf/metadata.h>
#include <babeltrace/babeltrace-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)
*/
#define WRITE_PACKET_LEN (getpagesize() * 8 * CHAR_BIT)
-#ifndef min
-#define min(a, b) (((a) < (b)) ? (a) : (b))
-#endif
-
#define NSEC_PER_SEC 1000000000LL
#define INDEX_PATH "./index/%s.idx"
#define NSEC_PER_SEC 1000000000LL
#define INDEX_PATH "./index/%s.idx"
* empty streams and return a negative value on error.
*/
static
* 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 packet_index_time real = { INT64_MIN, INT64_MAX },
+ cycles = { INT64_MIN, INT64_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++) {
for (stream_id = 0; stream_id < tin->streams->len;
stream_id++) {
}
index = &g_array_index(stream_pos->packet_index,
struct packet_index, 0);
}
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);
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);
+ if (ret == 0) {
+ if (_real) {
+ *_real = real;
+ }
+ if (_cycles) {
+ *_cycles = cycles;
+ }
+ }
- * 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.
*/
*
* 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,
+ int64_t *_ts_begin, int64_t *_ts_end)
+ int ret = 0, i;
+ int64_t ts_begin = INT64_MAX, ts_end = INT64_MIN;
- 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;
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;
}
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) {
+
+ 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) {
+ 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;
packet_seek = ctf_packet_seek;
td = g_new0(struct ctf_trace, 1);
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:
switch (flags & O_ACCMODE) {
case O_RDONLY:
struct bt_iter_pos **inter_begin_pos,
struct bt_iter_pos **inter_end_pos)
{
struct bt_iter_pos **inter_begin_pos,
struct bt_iter_pos **inter_end_pos)
{
- uint64_t begin = 0, end = ULLONG_MAX;
- 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;
if (ret == 1) {
fprintf(stderr, "[error] No intersection found between trace files.\n");
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
/*
* 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
void bt_ctf_iter_destroy(struct bt_ctf_iter *iter)
{
struct bt_stream_callbacks *bt_stream_cb;
void bt_ctf_iter_destroy(struct bt_ctf_iter *iter)
{
struct bt_stream_callbacks *bt_stream_cb;
+#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
*/
/*
* BT_HIDDEN: set the hidden attribute for internal functions
*/
* bt_ctf_get_decl_field_name: return the name of a field decl or NULL on error
*/
const char *bt_ctf_get_decl_field_name(const struct bt_ctf_field_decl *field);
* bt_ctf_get_decl_field_name: return the name of a field decl or NULL on error
*/
const char *bt_ctf_get_decl_field_name(const struct bt_ctf_field_decl *field);
-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,
+ int64_t *ts_begin, int64_t *ts_end);
void ctf_update_current_packet_index(struct ctf_stream_definition *stream,
struct packet_index *prev_index,
struct packet_index *cur_index);
void ctf_update_current_packet_index(struct ctf_stream_definition *stream,
struct packet_index *prev_index,
struct packet_index *cur_index);
+int ctf_tc_set_stream_intersection_mode(struct bt_context *ctx);
+
#endif /*_BABELTRACE_CTF_EVENTS_INTERNAL_H */
#endif /*_BABELTRACE_CTF_EVENTS_INTERNAL_H */
#include <babeltrace/compat/limits.h>
#include <babeltrace/context-internal.h>
#include <babeltrace/babeltrace-internal.h>
#include <babeltrace/compat/limits.h>
#include <babeltrace/context-internal.h>
#include <babeltrace/babeltrace-internal.h>
+#include <babeltrace/ctf/types.h>
#ifdef __cplusplus
extern "C" {
#ifdef __cplusplus
extern "C" {
struct trace_collection *collection; /* Container of this trace */
GHashTable *clocks;
struct ctf_clock *single_clock; /* currently supports only one clock */
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
#ifdef __cplusplus
}
#endif
#include <stdlib.h>
#include <babeltrace/babeltrace.h>
#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>
#include <babeltrace/context.h>
#include <babeltrace/context-internal.h>
#include <babeltrace/iterator-internal.h>
fprintf(stderr, "[error] Reading event failed.\n");
return ret;
}
fprintf(stderr, "[error] Reading event failed.\n");
return ret;
}
{
int i, j, ret;
int found = 0;
{
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++) {
/* for each stream_class */
for (i = 0; i < tin->streams->len; i++) {
ctx->current_iterator = iter;
if (begin_pos && begin_pos->type != BT_SEEK_BEGIN) {
ret = bt_iter_set_pos(iter, begin_pos);
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;
+ }
{
struct ctf_file_stream *file_stream, *removed;
int ret;
{
struct ctf_file_stream *file_stream, *removed;
int ret;
+ bool event_outside_interval = false;
if (!iter)
return -EINVAL;
if (!iter)
return -EINVAL;
}
ret = stream_read_event(file_stream);
}
ret = stream_read_event(file_stream);
+ 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;
removed = bt_heap_remove(iter->stream_heap);
assert(removed == file_stream);
ret = 0;