#include <babeltrace/ctf-ir/clock.h>
#include <babeltrace/ctf-ir/packet.h>
#include <babeltrace/ctf-ir/trace.h>
+#include <babeltrace/ctf-ir/fields.h>
#include <assert.h>
static
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);
}
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
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);
&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);
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);