From: Jérémie Galarneau Date: Sun, 11 Dec 2016 14:32:59 +0000 (-0500) Subject: Trimmer: Filter-out packet that are not in the specified range X-Git-Tag: v2.0.0-pre1~610 X-Git-Url: http://git.efficios.com/?p=babeltrace.git;a=commitdiff_plain;h=72208f0393e3d4c9f23b754affbc196f59d0951c Trimmer: Filter-out packet that are not in the specified range Signed-off-by: Jérémie Galarneau --- diff --git a/plugins/trimmer/iterator.c b/plugins/trimmer/iterator.c index 44a58e43..0cdd69f2 100644 --- a/plugins/trimmer/iterator.c +++ b/plugins/trimmer/iterator.c @@ -40,6 +40,7 @@ #include #include #include +#include #include static @@ -54,9 +55,6 @@ void trimmer_iterator_destroy(struct bt_notification_iterator *it) g_ptr_array_free(it_data->input_iterator_group, TRUE); } bt_put(it_data->current_notification); - if (it_data->stream_to_packet_start_notification) { - g_hash_table_destroy(it_data->stream_to_packet_start_notification); - } g_free(it_data); } @@ -131,124 +129,203 @@ end: return bt_get(trim_it->current_notification); } -/* - * Remove me. This is a temporary work-around due to our inhability to use - * libbabeltrace-ctf from libbabeltrace-plugin. - */ static -struct bt_ctf_stream *internal_bt_notification_get_stream( - struct bt_notification *notification) +bool evaluate_event_notification(struct bt_notification *notification, + struct trimmer_bound *begin, struct trimmer_bound *end) { + int64_t ts; + int clock_ret; + struct bt_ctf_event *event = NULL; + bool in_range = true; + struct bt_ctf_clock *clock = NULL; + struct bt_ctf_trace *trace = NULL; struct bt_ctf_stream *stream = NULL; + struct bt_ctf_stream_class *stream_class = NULL; + struct bt_ctf_clock_value *clock_value = NULL; - assert(notification); - switch (bt_notification_get_type(notification)) { - case BT_NOTIFICATION_TYPE_EVENT: - { - struct bt_ctf_event *event; + event = bt_notification_event_get_event(notification); + assert(event); - event = bt_notification_event_get_event(notification); - stream = bt_ctf_event_get_stream(event); - bt_put(event); - break; - } - case BT_NOTIFICATION_TYPE_PACKET_START: - { - struct bt_ctf_packet *packet; + stream = bt_ctf_event_get_stream(event); + assert(stream); - packet = bt_notification_packet_start_get_packet(notification); - stream = bt_ctf_packet_get_stream(packet); - bt_put(packet); - break; + stream_class = bt_ctf_stream_get_class(stream); + assert(stream_class); + + trace = bt_ctf_stream_class_get_trace(stream_class); + assert(trace); + + /* FIXME multi-clock? */ + clock = bt_ctf_trace_get_clock(trace, 0); + if (!clock) { + goto end; } - case BT_NOTIFICATION_TYPE_PACKET_END: - { - struct bt_ctf_packet *packet; - packet = bt_notification_packet_end_get_packet(notification); - stream = bt_ctf_packet_get_stream(packet); - bt_put(packet); - break; + clock_value = bt_ctf_event_get_clock_value(event, clock); + if (!clock_value) { + printf_error("Failed to retrieve clock value\n"); + goto end; } - case BT_NOTIFICATION_TYPE_STREAM_END: - stream = bt_notification_stream_end_get_stream(notification); - break; - default: + + clock_ret = bt_ctf_clock_value_get_value_ns_from_epoch( + clock_value, &ts); + if (clock_ret) { + printf_error("Failed to retrieve clock value timestamp\n"); goto end; } + + if (begin->set && ts < begin->value) { + in_range = false; + } + if (end->set && ts > end->value) { + in_range = false; + } end: - return stream; + bt_put(event); + bt_put(clock); + bt_put(trace); + bt_put(stream); + bt_put(stream_class); + bt_put(clock_value); + return in_range; } -/* Return true if the notification should be forwarded. */ static -bool evaluate_notification(struct bt_notification *notification, - struct trimmer *trimmer, struct trimmer_iterator *it) +int ns_from_integer_field(struct bt_ctf_field *integer, int64_t *ns) { - bool ret = true; + int ret = 0; + int is_signed; + uint64_t raw_clock_value; + struct bt_ctf_field_type *integer_type = NULL; struct bt_ctf_clock *clock = NULL; - enum bt_notification_type type; - struct bt_ctf_trace *trace = NULL; - struct bt_ctf_stream *stream = NULL; - struct bt_ctf_stream_class *stream_class = NULL; struct bt_ctf_clock_value *clock_value = NULL; - stream = internal_bt_notification_get_stream(notification); - if (!stream) { + integer_type = bt_ctf_field_get_type(integer); + assert(integer_type); + clock = bt_ctf_field_type_integer_get_mapped_clock(integer_type); + if (!clock) { + ret = -1; goto end; } - stream_class = bt_ctf_stream_get_class(stream); - assert(stream_class); - trace = bt_ctf_stream_class_get_trace(stream_class); - assert(trace); - - type = bt_notification_get_type(notification); - switch (type) { - case BT_NOTIFICATION_TYPE_EVENT: - { - int64_t ts; - int clock_ret; - struct bt_ctf_event *event; - - clock = bt_ctf_trace_get_clock(trace, 0); - if (!clock) { + is_signed = bt_ctf_field_type_integer_get_signed(integer_type); + if (!is_signed) { + ret = bt_ctf_field_unsigned_integer_get_value(integer, + &raw_clock_value); + if (ret) { goto end; } + } else { + /* Signed clock values are unsupported. */ + goto end; + } - event = bt_notification_event_get_event(notification); - assert(event); - clock_value = bt_ctf_event_get_clock_value(event, clock); - if (!clock_value) { - printf_error("Failed to retrieve clock value\n"); - bt_put(event); - goto end; - } + clock_value = bt_ctf_clock_value_create(clock, raw_clock_value); + if (!clock_value) { + goto end; + } - clock_ret = bt_ctf_clock_value_get_value_ns_from_epoch( - clock_value, &ts); - if (clock_ret) { - printf_error("Failed to retrieve clock value timestamp\n"); - goto end; - } + ret = bt_ctf_clock_value_get_value_ns_from_epoch(clock_value, ns); +end: + bt_put(integer_type); + bt_put(clock); + bt_put(clock_value); + return ret; +} - if (trimmer->begin.set && ts < trimmer->begin.value) { - ret = false; - } - if (trimmer->end.set && ts > trimmer->end.value) { - ret = false; - } +static +bool evaluate_packet_notification(struct bt_notification *notification, + struct trimmer_bound *begin, struct trimmer_bound *end) +{ + int ret; + int64_t begin_ns, pkt_begin_ns, end_ns, pkt_end_ns; + bool in_range = true; + struct bt_ctf_packet *packet = NULL; + struct bt_ctf_field *packet_context = NULL, + *timestamp_begin = NULL, + *timestamp_end = NULL; + + switch (bt_notification_get_type(notification)) { + case BT_NOTIFICATION_TYPE_PACKET_BEGIN: + packet = bt_notification_packet_begin_get_packet(notification); break; + case BT_NOTIFICATION_TYPE_PACKET_END: + packet = bt_notification_packet_end_get_packet(notification); + break; + default: + abort(); } + assert(packet); + + packet_context = bt_ctf_packet_get_context(packet); + if (!packet_context) { + goto end; + } + + if (!bt_ctf_field_is_structure(packet_context)) { + goto end; + } + + timestamp_begin = bt_ctf_field_structure_get_field( + packet_context, "timestamp_begin"); + if (!timestamp_begin || !bt_ctf_field_is_integer(timestamp_begin)) { + goto end; + } + timestamp_end = bt_ctf_field_structure_get_field( + packet_context, "timestamp_end"); + if (!timestamp_end || !bt_ctf_field_is_integer(timestamp_end)) { + goto end; + } + + ret = ns_from_integer_field(timestamp_begin, &pkt_begin_ns); + if (ret) { + goto end; + } + ret = ns_from_integer_field(timestamp_end, &pkt_end_ns); + if (ret) { + goto end; + } + + begin_ns = begin->set ? begin->value : INT64_MIN; + end_ns = end->set ? end->value : INT64_MAX; + + /* + * Accept if there is any overlap between the selected region and the + * packet. + */ + in_range = (pkt_end_ns >= begin_ns) && (pkt_begin_ns <= end_ns); +end: + bt_put(packet); + bt_put(packet_context); + bt_put(timestamp_begin); + bt_put(timestamp_end); + return in_range; +} + +/* Return true if the notification should be forwarded. */ +static +bool evaluate_notification(struct bt_notification *notification, + struct trimmer_bound *begin, struct trimmer_bound *end) +{ + bool in_range = true; + enum bt_notification_type type; + + type = bt_notification_get_type(notification); + switch (type) { + case BT_NOTIFICATION_TYPE_EVENT: + in_range = evaluate_event_notification(notification, begin, + end); + break; + case BT_NOTIFICATION_TYPE_PACKET_BEGIN: + case BT_NOTIFICATION_TYPE_PACKET_END: + in_range = evaluate_packet_notification(notification, begin, + end); + break; default: + /* Accept all other notifications. */ break; } -end: - bt_put(clock); - bt_put(trace); - bt_put(stream); - bt_put(clock_value); - return ret; + return in_range; } BT_HIDDEN @@ -262,7 +339,7 @@ enum bt_notification_iterator_status trimmer_iterator_next( enum bt_notification_iterator_status ret = BT_NOTIFICATION_ITERATOR_STATUS_OK;; enum bt_component_status component_ret; - bool event_in_range = false; + bool notification_in_range = false; trim_it = bt_notification_iterator_get_private_data(iterator); assert(trim_it); @@ -277,7 +354,7 @@ enum bt_notification_iterator_status trimmer_iterator_next( &source_it); assert((component_ret == BT_COMPONENT_STATUS_OK) && source_it); - while (!event_in_range) { + while (!notification_in_range) { struct bt_notification *notification; ret = bt_notification_iterator_next(source_it); @@ -292,9 +369,9 @@ enum bt_notification_iterator_status trimmer_iterator_next( goto end; } - event_in_range = evaluate_notification(notification, trimmer, - trim_it); - if (event_in_range) { + notification_in_range = evaluate_notification(notification, + &trimmer->begin, &trimmer->end); + if (notification_in_range) { BT_MOVE(trim_it->current_notification, notification); } else { bt_put(notification); diff --git a/plugins/trimmer/iterator.h b/plugins/trimmer/iterator.h index a517b1f0..f40f4b2d 100644 --- a/plugins/trimmer/iterator.h +++ b/plugins/trimmer/iterator.h @@ -34,7 +34,6 @@ struct trimmer_iterator { /* Input iterators associated with this output iterator. */ GPtrArray *input_iterator_group; struct bt_notification *current_notification; - GHashTable *stream_to_packet_start_notification; }; BT_HIDDEN