plugins/ctf/lttng-live/Makefile
plugins/muxer/Makefile
plugins/text/Makefile
- plugins/trimmer/Makefile
plugins/writer/Makefile
+ plugins/utils/Makefile
+ plugins/utils/dummy/Makefile
+ plugins/utils/trimmer/Makefile
babeltrace.pc
babeltrace-ctf.pc
])
PLUGINS_PATH = $(abs_top_builddir)/plugins
AM_CFLAGS = $(PACKAGE_CFLAGS) -I$(top_srcdir)/include \
- -DCONFIG_IN_TREE_PLUGIN_PATH=\"$(PLUGINS_PATH)/ctf:$(PLUGINS_PATH)/text:$(PLUGINS_PATH)/muxer:$(PLUGINS_PATH)/trimmer:$(PLUGINS_PATH)/writer\"
+ -DCONFIG_IN_TREE_PLUGIN_PATH=\"$(PLUGINS_PATH)/ctf:$(PLUGINS_PATH)/text:$(PLUGINS_PATH)/muxer:$(PLUGINS_PATH)/writer:$(PLUGINS_PATH)/utils\"
AM_LDFLAGS = -lpopt
bin_PROGRAMS = babeltrace.bin babeltrace-log
-SUBDIRS = ctf text muxer trimmer writer
+SUBDIRS = ctf text muxer writer utils
noinst_HEADERS = plugins-common.h
+++ /dev/null
-AM_CFLAGS = $(PACKAGE_CFLAGS) -I$(top_srcdir)/include -I$(top_srcdir)/plugins
-
-SUBDIRS = .
-
-plugindir = "$(PLUGINSDIR)"
-plugin_LTLIBRARIES = libbabeltrace-plugin-trimmer.la
-
-libbabeltrace_plugin_trimmer_la_SOURCES = \
- trimmer.c \
- iterator.c \
- trimmer.h \
- iterator.h
-
-libbabeltrace_plugin_trimmer_la_LDFLAGS = \
- -version-info $(BABELTRACE_LIBRARY_VERSION)
-
-libbabeltrace_plugin_trimmer_la_LIBADD = \
- $(top_builddir)/lib/libbabeltrace.la \
- $(top_builddir)/formats/ctf/libbabeltrace-ctf.la
+++ /dev/null
-/*
- * iterator.c
- *
- * Babeltrace Trace Trimmer Iterator
- *
- * Copyright 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include "trimmer.h"
-#include "iterator.h"
-#include <babeltrace/component/notification/iterator.h>
-#include <babeltrace/component/notification/notification.h>
-#include <babeltrace/component/notification/event.h>
-#include <babeltrace/component/notification/stream.h>
-#include <babeltrace/component/notification/packet.h>
-#include <babeltrace/component/component-filter.h>
-#include <babeltrace/ctf-ir/event.h>
-#include <babeltrace/ctf-ir/stream.h>
-#include <babeltrace/ctf-ir/stream-class.h>
-#include <babeltrace/ctf-ir/clock-class.h>
-#include <babeltrace/ctf-ir/packet.h>
-#include <babeltrace/ctf-ir/trace.h>
-#include <babeltrace/ctf-ir/fields.h>
-#include <assert.h>
-#include <plugins-common.h>
-
-BT_HIDDEN
-void trimmer_iterator_destroy(struct bt_notification_iterator *it)
-{
- struct trimmer_iterator *it_data;
-
- it_data = bt_notification_iterator_get_private_data(it);
- assert(it_data);
-
- if (it_data->input_iterator_group) {
- g_ptr_array_free(it_data->input_iterator_group, TRUE);
- }
- bt_put(it_data->current_notification);
- g_free(it_data);
-}
-
-BT_HIDDEN
-enum bt_notification_iterator_status trimmer_iterator_init(
- struct bt_component *component,
- struct bt_notification_iterator *iterator,
- UNUSED_VAR void *init_method_data)
-{
- enum bt_notification_iterator_status ret =
- BT_NOTIFICATION_ITERATOR_STATUS_OK;
- enum bt_notification_iterator_status it_ret;
- struct trimmer_iterator *it_data = g_new0(struct trimmer_iterator, 1);
-
- if (!it_data) {
- ret = BT_NOTIFICATION_ITERATOR_STATUS_NOMEM;
- goto end;
- }
-
- /* FIXME init trimmer_iterator */
- it_ret = bt_notification_iterator_set_private_data(iterator, it_data);
- if (it_ret) {
- goto end;
- }
-end:
- return ret;
-}
-
-BT_HIDDEN
-struct bt_notification *trimmer_iterator_get(
- struct bt_notification_iterator *iterator)
-{
- struct trimmer_iterator *trim_it;
-
- trim_it = bt_notification_iterator_get_private_data(iterator);
- assert(trim_it);
-
- if (!trim_it->current_notification) {
- enum bt_notification_iterator_status it_ret;
-
- it_ret = trimmer_iterator_next(iterator);
- if (it_ret) {
- goto end;
- }
- }
-end:
- return bt_get(trim_it->current_notification);
-}
-
-static
-int update_lazy_bound(struct trimmer_bound *bound, const char *name,
- int64_t ts, bool *lazy_update)
-{
- struct tm tm;
- int64_t value;
- time_t timeval;
-
- *lazy_update = false;
-
- if (!bound->lazy) {
- return 0;
- }
- tm.tm_isdst = -1;
- timeval = ts / NSEC_PER_SEC;
-
- if (bound->lazy_values.gmt) {
- /* Get day, month, year. */
- if (!gmtime_r(&timeval, &tm)) {
- printf_error("Failure in gmtime_r()");
- goto error;
- }
- tm.tm_sec = bound->lazy_values.ss;
- tm.tm_min = bound->lazy_values.mm;
- tm.tm_hour = bound->lazy_values.hh;
- timeval = timegm(&tm);
- if (timeval < 0) {
- printf_error("Failure in timegm(), incorrectly formatted %s timestamp",
- name);
- goto error;
- }
- } else {
- /* Get day, month, year. */
- if (!localtime_r(&timeval, &tm)) {
- printf_error("Failure in localtime_r()");
- goto error;
- }
- tm.tm_sec = bound->lazy_values.ss;
- tm.tm_min = bound->lazy_values.mm;
- tm.tm_hour = bound->lazy_values.hh;
- timeval = mktime(&tm);
- if (timeval < 0) {
- printf_error("Failure in mktime(), incorrectly formatted %s timestamp",
- name);
- goto error;
- }
- }
- value = (int64_t) timeval;
- value *= NSEC_PER_SEC;
- value += bound->lazy_values.ns;
- bound->value = value;
- bound->set = true;
- bound->lazy = false;
- *lazy_update = true;
- return 0;
-
-error:
- return -1;
-}
-
-static
-enum bt_notification_iterator_status
-evaluate_event_notification(struct bt_notification *notification,
- struct trimmer_bound *begin, struct trimmer_bound *end,
- bool *_event_in_range)
-{
- int64_t ts;
- int clock_ret;
- struct bt_ctf_event *event = NULL;
- bool in_range = true;
- struct bt_ctf_clock_class *clock_class = 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;
- enum bt_notification_iterator_status ret =
- BT_NOTIFICATION_ITERATOR_STATUS_OK;
- bool lazy_update = false;
-
- event = bt_notification_event_get_event(notification);
- assert(event);
-
- stream = bt_ctf_event_get_stream(event);
- assert(stream);
-
- 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_class = bt_ctf_trace_get_clock_class(trace, 0);
- if (!clock_class) {
- goto end;
- }
-
- clock_value = bt_ctf_event_get_clock_value(event, clock_class);
- if (!clock_value) {
- printf_error("Failed to retrieve clock value");
- ret = BT_NOTIFICATION_ITERATOR_STATUS_ERROR;
- 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");
- ret = BT_NOTIFICATION_ITERATOR_STATUS_ERROR;
- goto end;
- }
- if (update_lazy_bound(begin, "begin", ts, &lazy_update)) {
- ret = BT_NOTIFICATION_ITERATOR_STATUS_ERROR;
- goto end;
- }
- if (update_lazy_bound(end, "end", ts, &lazy_update)) {
- ret = BT_NOTIFICATION_ITERATOR_STATUS_ERROR;
- goto end;
- }
- if (lazy_update && begin->set && end->set) {
- if (begin->value > end->value) {
- printf_error("Unexpected: time range begin value is above end value");
- ret = BT_NOTIFICATION_ITERATOR_STATUS_ERROR;
- goto end;
- }
- }
- if (begin->set && ts < begin->value) {
- in_range = false;
- }
- if (end->set && ts > end->value) {
- in_range = false;
- }
-end:
- bt_put(event);
- bt_put(clock_class);
- bt_put(trace);
- bt_put(stream);
- bt_put(stream_class);
- bt_put(clock_value);
- *_event_in_range = in_range;
- return ret;
-}
-
-static
-int ns_from_integer_field(struct bt_ctf_field *integer, int64_t *ns)
-{
- int ret = 0;
- int is_signed;
- uint64_t raw_clock_value;
- struct bt_ctf_field_type *integer_type = NULL;
- struct bt_ctf_clock_class *clock_class = NULL;
- struct bt_ctf_clock_value *clock_value = NULL;
-
- integer_type = bt_ctf_field_get_type(integer);
- assert(integer_type);
- clock_class = bt_ctf_field_type_integer_get_mapped_clock_class(
- integer_type);
- if (!clock_class) {
- ret = -1;
- goto end;
- }
-
- 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;
- }
-
- clock_value = bt_ctf_clock_value_create(clock_class, raw_clock_value);
- if (!clock_value) {
- goto end;
- }
-
- ret = bt_ctf_clock_value_get_value_ns_from_epoch(clock_value, ns);
-end:
- bt_put(integer_type);
- bt_put(clock_class);
- bt_put(clock_value);
- return ret;
-}
-
-static
-enum bt_notification_iterator_status evaluate_packet_notification(
- struct bt_notification *notification,
- struct trimmer_bound *begin, struct trimmer_bound *end,
- bool *_packet_in_range)
-{
- enum bt_notification_iterator_status ret =
- BT_NOTIFICATION_ITERATOR_STATUS_OK;
- 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:
- break;
- }
- 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;
- }
-
- if (ns_from_integer_field(timestamp_begin, &pkt_begin_ns)) {
- goto end;
- }
- if (ns_from_integer_field(timestamp_end, &pkt_end_ns)) {
- 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:
- *_packet_in_range = in_range;
- bt_put(packet);
- bt_put(packet_context);
- bt_put(timestamp_begin);
- bt_put(timestamp_end);
- return ret;
-}
-
-/* Return true if the notification should be forwarded. */
-static
-enum bt_notification_iterator_status evaluate_notification(
- struct bt_notification *notification,
- struct trimmer_bound *begin, struct trimmer_bound *end,
- bool *in_range)
-{
- enum bt_notification_type type;
- enum bt_notification_iterator_status ret =
- BT_NOTIFICATION_ITERATOR_STATUS_OK;
-
- *in_range = true;
- type = bt_notification_get_type(notification);
- switch (type) {
- case BT_NOTIFICATION_TYPE_EVENT:
- ret = evaluate_event_notification(notification, begin,
- end, in_range);
- break;
- case BT_NOTIFICATION_TYPE_PACKET_BEGIN:
- case BT_NOTIFICATION_TYPE_PACKET_END:
- ret = evaluate_packet_notification(notification, begin,
- end, in_range);
- break;
- default:
- /* Accept all other notifications. */
- break;
- }
- return ret;
-}
-
-BT_HIDDEN
-enum bt_notification_iterator_status trimmer_iterator_next(
- struct bt_notification_iterator *iterator)
-{
- struct trimmer_iterator *trim_it = NULL;
- struct bt_component *component = NULL;
- struct trimmer *trimmer = NULL;
- struct bt_notification_iterator *source_it = NULL;
- enum bt_notification_iterator_status ret =
- BT_NOTIFICATION_ITERATOR_STATUS_OK;
- enum bt_component_status component_ret;
- bool notification_in_range = false;
-
- trim_it = bt_notification_iterator_get_private_data(iterator);
- assert(trim_it);
-
- component = bt_notification_iterator_get_component(iterator);
- assert(component);
- trimmer = bt_component_get_private_data(component);
- assert(trimmer);
-
- /* FIXME, should handle input iterator groups. */
- component_ret = bt_component_filter_get_input_iterator(component, 0,
- &source_it);
- assert((component_ret == BT_COMPONENT_STATUS_OK) && source_it);
-
- while (!notification_in_range) {
- struct bt_notification *notification;
-
- ret = bt_notification_iterator_next(source_it);
- if (ret != BT_NOTIFICATION_ITERATOR_STATUS_OK) {
- goto end;
- }
-
- notification = bt_notification_iterator_get_notification(
- source_it);
- if (!notification) {
- ret = BT_NOTIFICATION_ITERATOR_STATUS_ERROR;
- goto end;
- }
-
- ret = evaluate_notification(notification,
- &trimmer->begin, &trimmer->end,
- ¬ification_in_range);
- if (notification_in_range) {
- BT_MOVE(trim_it->current_notification, notification);
- } else {
- bt_put(notification);
- }
-
- if (ret != BT_NOTIFICATION_ITERATOR_STATUS_OK) {
- break;
- }
- }
-end:
- bt_put(source_it);
- bt_put(component);
- return ret;
-}
-
-BT_HIDDEN
-enum bt_notification_iterator_status trimmer_iterator_seek_time(
- struct bt_notification_iterator *iterator, int64_t time)
-{
- enum bt_notification_iterator_status ret;
-
- ret = BT_NOTIFICATION_ITERATOR_STATUS_OK;
-end:
- return ret;
-}
+++ /dev/null
-#ifndef BABELTRACE_PLUGIN_TRIMMER_ITERATOR_H
-#define BABELTRACE_PLUGIN_TRIMMER_ITERATOR_H
-
-/*
- * BabelTrace - Trace Trimmer Iterator
- *
- * Copyright 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include "trimmer.h"
-#include <babeltrace/component/notification/notification.h>
-#include <babeltrace/component/notification/iterator.h>
-
-struct trimmer_iterator {
- /* Input iterators associated with this output iterator. */
- GPtrArray *input_iterator_group;
- struct bt_notification *current_notification;
-};
-
-BT_HIDDEN
-enum bt_notification_iterator_status trimmer_iterator_init(
- struct bt_component *component,
- struct bt_notification_iterator *iterator, void *init_method_data);
-
-BT_HIDDEN
-void trimmer_iterator_destroy(struct bt_notification_iterator *it);
-
-BT_HIDDEN
-struct bt_notification *trimmer_iterator_get(
- struct bt_notification_iterator *iterator);
-
-BT_HIDDEN
-enum bt_notification_iterator_status trimmer_iterator_next(
- struct bt_notification_iterator *iterator);
-
-BT_HIDDEN
-enum bt_notification_iterator_status trimmer_iterator_seek_time(
- struct bt_notification_iterator *iterator, int64_t time);
-
-#endif /* BABELTRACE_PLUGIN_TRIMMER_ITERATOR_H */
+++ /dev/null
-/*
- * trimmer.c
- *
- * Babeltrace Trace Trimmer
- *
- * Copyright 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <babeltrace/plugin/plugin-dev.h>
-#include <babeltrace/component/component.h>
-#include <babeltrace/component/component-filter.h>
-#include <babeltrace/component/notification/notification.h>
-#include <babeltrace/component/notification/iterator.h>
-#include <babeltrace/component/notification/event.h>
-#include <plugins-common.h>
-#include "trimmer.h"
-#include "iterator.h"
-#include <assert.h>
-
-static
-void destroy_trimmer_data(struct trimmer *trimmer)
-{
- g_free(trimmer);
-}
-
-static
-struct trimmer *create_trimmer_data(void)
-{
- struct trimmer *trimmer;
-
- trimmer = g_new0(struct trimmer, 1);
- if (!trimmer) {
- goto end;
- }
-end:
- return trimmer;
-}
-
-static
-void destroy_trimmer(struct bt_component *component)
-{
- void *data = bt_component_get_private_data(component);
-
- destroy_trimmer_data(data);
-}
-
-/*
- * Parses a timestamp, figuring out its format.
- *
- * Returns a negative value if anything goes wrong.
- *
- * Expected formats:
- *
- * YYYY-MM-DD hh:mm:ss.ns
- * hh:mm:ss.ns
- * -ss.ns
- * ss.ns
- * YYYY-MM-DD hh:mm:ss
- * hh:mm:ss
- * -ss
- * ss
- */
-static
-int timestamp_from_arg(const char *arg, struct trimmer *trimmer,
- struct trimmer_bound *result_bound, bool gmt)
-{
- int ret;
- int64_t value;
- unsigned int year, month, day, hh, mm, ss, ns;
-
- /* YYYY-MM-DD hh:mm:ss.ns */
- ret = sscanf(arg, "%u-%u-%u %u:%u:%u.%u",
- &year, &month, &day, &hh, &mm, &ss, &ns);
- if (ret == 7) {
- struct tm tm = {
- .tm_sec = ss,
- .tm_min = mm,
- .tm_hour = hh,
- .tm_mday = day,
- .tm_mon = month - 1,
- .tm_year = year - 1900,
- .tm_isdst = -1,
- };
- time_t result;
-
- if (gmt) {
- result = timegm(&tm);
- if (result < 0) {
- return -1;
- }
- } else {
- result = mktime(&tm);
- if (result < 0) {
- return -1;
- }
- }
- value = (int64_t) result;
- value *= NSEC_PER_SEC;
- value += ns;
- if (!trimmer->date) {
- trimmer->year = year;
- trimmer->month = month;
- trimmer->day = day;
- trimmer->date = true;
- }
- goto set;
- }
- /* hh:mm:ss.ns */
- ret = sscanf(arg, "%u:%u:%u.%u",
- &hh, &mm, &ss, &ns);
- if (ret == 4) {
- if (!trimmer->date) {
- /* We don't know which day until we get an event. */
- result_bound->lazy_values.hh = hh;
- result_bound->lazy_values.mm = mm;
- result_bound->lazy_values.ss = ss;
- result_bound->lazy_values.ns = ns;
- result_bound->lazy_values.gmt = gmt;
- goto lazy;
- } else {
- struct tm tm = {
- .tm_sec = ss,
- .tm_min = mm,
- .tm_hour = hh,
- .tm_mday = trimmer->day,
- .tm_mon = trimmer->month - 1,
- .tm_year = trimmer->year - 1900,
- .tm_isdst = -1,
- };
- time_t result;
-
- if (gmt) {
- result = timegm(&tm);
- if (result < 0) {
- return -1;
- }
- } else {
- result = mktime(&tm);
- if (result < 0) {
- return -1;
- }
- }
- value = (int64_t) result;
- value *= NSEC_PER_SEC;
- value += ns;
- goto set;
- }
- }
- /* -ss.ns */
- ret = sscanf(arg, "-%u.%u",
- &ss, &ns);
- if (ret == 2) {
- value = -ss * NSEC_PER_SEC;
- value -= ns;
- goto set;
- }
- /* ss.ns */
- ret = sscanf(arg, "%u.%u",
- &ss, &ns);
- if (ret == 2) {
- value = ss * NSEC_PER_SEC;
- value += ns;
- goto set;
- }
-
- /* YYYY-MM-DD hh:mm:ss */
- ret = sscanf(arg, "%u-%u-%u %u:%u:%u",
- &year, &month, &day, &hh, &mm, &ss);
- if (ret == 6) {
- struct tm tm = {
- .tm_sec = ss,
- .tm_min = mm,
- .tm_hour = hh,
- .tm_mday = day,
- .tm_mon = month - 1,
- .tm_year = year - 1900,
- .tm_isdst = -1,
- };
-
- if (gmt) {
- value = timegm(&tm);
- if (value < 0) {
- return -1;
- }
- } else {
- value = mktime(&tm);
- if (value < 0) {
- return -1;
- }
- }
- value *= NSEC_PER_SEC;
- if (!trimmer->date) {
- trimmer->year = year;
- trimmer->month = month;
- trimmer->day = day;
- trimmer->date = true;
- }
- goto set;
- }
- /* hh:mm:ss */
- ret = sscanf(arg, "%u:%u:%u",
- &hh, &mm, &ss);
- if (ret == 3) {
- if (!trimmer->date) {
- /* We don't know which day until we get an event. */
- result_bound->lazy_values.hh = hh;
- result_bound->lazy_values.mm = mm;
- result_bound->lazy_values.ss = ss;
- result_bound->lazy_values.ns = 0;
- result_bound->lazy_values.gmt = gmt;
- goto lazy;
- } else {
- struct tm tm = {
- .tm_sec = ss,
- .tm_min = mm,
- .tm_hour = hh,
- .tm_mday = trimmer->day,
- .tm_mon = trimmer->month - 1,
- .tm_year = trimmer->year - 1900,
- .tm_isdst = -1,
- };
- time_t result;
-
- if (gmt) {
- result = timegm(&tm);
- if (result < 0) {
- return -1;
- }
- } else {
- result = mktime(&tm);
- if (result < 0) {
- return -1;
- }
- }
- value = (int64_t) result;
- value *= NSEC_PER_SEC;
- goto set;
- }
- }
- /* -ss */
- ret = sscanf(arg, "-%u",
- &ss);
- if (ret == 1) {
- value = -ss * NSEC_PER_SEC;
- goto set;
- }
- /* ss */
- ret = sscanf(arg, "%u",
- &ss);
- if (ret == 1) {
- value = ss * NSEC_PER_SEC;
- goto set;
- }
-
- /* Not found. */
- return -1;
-
-set:
- result_bound->value = value;
- result_bound->set = true;
- return 0;
-
-lazy:
- result_bound->lazy = true;
- return 0;
-}
-
-static
-enum bt_component_status init_from_params(struct trimmer *trimmer, struct bt_value *params)
-{
- struct bt_value *value = NULL;
- bool gmt = false;
- enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
-
- assert(params);
-
- value = bt_value_map_get(params, "clock-gmt");
- if (value) {
- enum bt_value_status value_ret;
-
- value_ret = bt_value_bool_get(value, &gmt);
- if (value_ret) {
- ret = BT_COMPONENT_STATUS_INVALID;
- printf_error("Failed to retrieve clock-gmt value. Expecting a boolean");
- }
- }
- bt_put(value);
- if (ret != BT_COMPONENT_STATUS_OK) {
- goto end;
- }
-
- value = bt_value_map_get(params, "begin");
- if (value) {
- enum bt_value_status value_ret;
- const char *str;
-
- value_ret = bt_value_string_get(value, &str);
- if (value_ret || timestamp_from_arg(str,
- trimmer, &trimmer->begin, gmt)) {
- ret = BT_COMPONENT_STATUS_INVALID;
- printf_error("Failed to retrieve begin value. Expecting a timestamp string");
- }
- }
- bt_put(value);
- if (ret != BT_COMPONENT_STATUS_OK) {
- goto end;
- }
-
- value = bt_value_map_get(params, "end");
- if (value) {
- enum bt_value_status value_ret;
- const char *str;
-
- value_ret = bt_value_string_get(value, &str);
- if (value_ret || timestamp_from_arg(str,
- trimmer, &trimmer->end, gmt)) {
- ret = BT_COMPONENT_STATUS_INVALID;
- printf_error("Failed to retrieve end value. Expecting a timestamp string");
- }
- }
- bt_put(value);
-end:
- if (trimmer->begin.set && trimmer->end.set) {
- if (trimmer->begin.value > trimmer->end.value) {
- printf_error("Unexpected: time range begin value is above end value");
- ret = BT_COMPONENT_STATUS_INVALID;
- }
- }
- return ret;
-}
-
-enum bt_component_status trimmer_component_init(
- struct bt_component *component, struct bt_value *params,
- UNUSED_VAR void *init_method_data)
-{
- enum bt_component_status ret;
- struct trimmer *trimmer = create_trimmer_data();
-
- if (!trimmer) {
- ret = BT_COMPONENT_STATUS_NOMEM;
- goto end;
- }
-
- ret = bt_component_set_private_data(component, trimmer);
- if (ret != BT_COMPONENT_STATUS_OK) {
- goto error;
- }
-
- ret = init_from_params(trimmer, params);
-end:
- return ret;
-error:
- destroy_trimmer_data(trimmer);
- return ret;
-}
-
-/* Initialize plug-in entry points. */
-BT_PLUGIN(utils);
-BT_PLUGIN_DESCRIPTION("Babeltrace Trace Trimmer Plug-In.");
-BT_PLUGIN_AUTHOR("Jérémie Galarneau");
-BT_PLUGIN_LICENSE("MIT");
-BT_PLUGIN_FILTER_COMPONENT_CLASS(trimmer, trimmer_iterator_get,
- trimmer_iterator_next);
-BT_PLUGIN_FILTER_COMPONENT_CLASS_DESCRIPTION(trimmer,
- "Ensure that trace notifications outside of a given range are filtered-out.");
-BT_PLUGIN_FILTER_COMPONENT_CLASS_INIT_METHOD(trimmer, trimmer_component_init);
-BT_PLUGIN_FILTER_COMPONENT_CLASS_DESTROY_METHOD(trimmer, destroy_trimmer);
-BT_PLUGIN_FILTER_COMPONENT_CLASS_NOTIFICATION_ITERATOR_INIT_METHOD(trimmer,
- trimmer_iterator_init);
-BT_PLUGIN_FILTER_COMPONENT_CLASS_NOTIFICATION_ITERATOR_DESTROY_METHOD(trimmer,
- trimmer_iterator_destroy);
-BT_PLUGIN_FILTER_COMPONENT_CLASS_NOTIFICATION_ITERATOR_SEEK_TIME_METHOD(trimmer,
- trimmer_iterator_seek_time);
+++ /dev/null
-#ifndef BABELTRACE_PLUGIN_TRIMMER_H
-#define BABELTRACE_PLUGIN_TRIMMER_H
-
-/*
- * BabelTrace - Trace Trimmer Plug-in
- *
- * Copyright 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <stdbool.h>
-#include <babeltrace/babeltrace-internal.h>
-
-#define NSEC_PER_SEC 1000000000LL
-
-struct trimmer_bound {
- int64_t value;
- bool set;
- bool lazy;
- struct {
- int hh, mm, ss, ns;
- bool gmt;
- } lazy_values;
-};
-
-struct trimmer {
- struct trimmer_bound begin, end;
- bool date;
- int year, month, day;
-};
-
-#endif /* BABELTRACE_PLUGIN_TRIMMER_H */
--- /dev/null
+AM_CFLAGS = $(PACKAGE_CFLAGS) -I$(top_srcdir)/include -I$(top_srcdir)/plugins
+
+SUBDIRS = dummy trimmer .
+
+plugindir = "$(PLUGINSDIR)"
+plugin_LTLIBRARIES = libbabeltrace-plugin-utils.la
+
+libbabeltrace_plugin_utils_la_SOURCES = plugin.c
+libbabeltrace_plugin_utils_la_LDFLAGS = \
+ -version-info $(BABELTRACE_LIBRARY_VERSION)
+libbabeltrace_plugin_utils_la_LIBADD = \
+ $(top_builddir)/lib/libbabeltrace.la \
+ $(top_builddir)/formats/ctf/libbabeltrace-ctf.la \
+ dummy/libbabeltrace-plugin-dummy-cc.la \
+ trimmer/libbabeltrace-plugin-dummy-cc.la
--- /dev/null
+AM_CFLAGS = $(PACKAGE_CFLAGS) -I$(top_srcdir)/include -I$(top_srcdir)/plugins
+
+noinst_LTLIBRARIES = libbabeltrace-plugin-dummy-cc.la
+libbabeltrace_plugin_dummy_cc_la_SOURCES = dummy.c dummy.h
--- /dev/null
+/*
+ * Copyright 2017 Philippe Proulx <pproulx@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <babeltrace/plugin/plugin-dev.h>
+#include <babeltrace/component/component.h>
+#include <babeltrace/component/component-sink.h>
+#include <babeltrace/component/notification/iterator.h>
+#include <babeltrace/component/notification/notification.h>
+#include <assert.h>
+
+enum bt_component_status dummy_consume(struct bt_component *component)
+{
+ enum bt_component_status ret;
+ struct bt_notification *notif = NULL;
+ struct bt_notification_iterator *it = NULL;
+ unsigned int it_count;
+ size_t i;
+ bool got_one = false;
+
+ ret = bt_component_sink_get_input_count(component, &it_count);
+ assert(ret == 0);
+
+ for (i = 0; i < it_count; i++) {
+ enum bt_notification_iterator_status it_ret;
+
+ ret = bt_component_sink_get_input_iterator(component, i, &it);
+ assert(ret == 0);
+ it_ret = bt_notification_iterator_next(it);
+ switch (it_ret) {
+ case BT_NOTIFICATION_ITERATOR_STATUS_ERROR:
+ ret = BT_COMPONENT_STATUS_ERROR;
+ goto end;
+ case BT_NOTIFICATION_ITERATOR_STATUS_END:
+ ret = BT_COMPONENT_STATUS_END;
+ BT_PUT(it);
+ continue;
+ default:
+ break;
+ }
+
+ notif = bt_notification_iterator_get_notification(it);
+ if (!notif) {
+ ret = BT_COMPONENT_STATUS_ERROR;
+ goto end;
+ }
+
+ /*
+ * Dummy! I'm doing nothing with this notification,
+ * NOTHING.
+ */
+ got_one = true;
+ BT_PUT(it);
+ BT_PUT(notif);
+ }
+
+ if (!got_one) {
+ ret = BT_COMPONENT_STATUS_END;
+ }
+
+end:
+ bt_put(it);
+ bt_put(notif);
+ return ret;
+}
--- /dev/null
+#ifndef BABELTRACE_PLUGINS_UTILS_DUMMY_H
+#define BABELTRACE_PLUGINS_UTILS_DUMMY_H
+
+/*
+ * Copyright 2017 Philippe Proulx <pproulx@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+enum bt_component_status dummy_consume(struct bt_component *component);
+
+#endif /* BABELTRACE_PLUGINS_UTILS_DUMMY_H */
--- /dev/null
+/*
+ * Copyright 2017 Philippe Proulx <pproulx@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <babeltrace/plugin/plugin-dev.h>
+#include "dummy/dummy.h"
+#include "trimmer/trimmer.h"
+#include "trimmer/iterator.h"
+
+BT_PLUGIN(utils);
+BT_PLUGIN_DESCRIPTION("Utilities.");
+BT_PLUGIN_AUTHOR("Philippe Proulx");
+BT_PLUGIN_LICENSE("MIT");
+
+/* dummy sink */
+BT_PLUGIN_SINK_COMPONENT_CLASS(dummy, dummy_consume);
+BT_PLUGIN_SINK_COMPONENT_CLASS_DESCRIPTION(dummy,
+ "Dummy sink component class: does absolutely nothing!");
+
+/* trimmer filter */
+BT_PLUGIN_FILTER_COMPONENT_CLASS(trimmer, trimmer_iterator_get,
+ trimmer_iterator_next);
+BT_PLUGIN_FILTER_COMPONENT_CLASS_DESCRIPTION(trimmer,
+ "Ensure that trace notifications outside of a given range are filtered-out.");
+BT_PLUGIN_FILTER_COMPONENT_CLASS_INIT_METHOD(trimmer, trimmer_component_init);
+BT_PLUGIN_FILTER_COMPONENT_CLASS_DESTROY_METHOD(trimmer, destroy_trimmer);
+BT_PLUGIN_FILTER_COMPONENT_CLASS_NOTIFICATION_ITERATOR_INIT_METHOD(trimmer,
+ trimmer_iterator_init);
+BT_PLUGIN_FILTER_COMPONENT_CLASS_NOTIFICATION_ITERATOR_DESTROY_METHOD(trimmer,
+ trimmer_iterator_destroy);
+BT_PLUGIN_FILTER_COMPONENT_CLASS_NOTIFICATION_ITERATOR_SEEK_TIME_METHOD(trimmer,
+ trimmer_iterator_seek_time);
--- /dev/null
+AM_CFLAGS = $(PACKAGE_CFLAGS) -I$(top_srcdir)/include -I$(top_srcdir)/plugins
+
+noinst_LTLIBRARIES = libbabeltrace-plugin-dummy-cc.la
+libbabeltrace_plugin_dummy_cc_la_SOURCES = \
+ trimmer.c \
+ iterator.c \
+ trimmer.h \
+ iterator.h
--- /dev/null
+/*
+ * iterator.c
+ *
+ * Babeltrace Trace Trimmer Iterator
+ *
+ * Copyright 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "trimmer.h"
+#include "iterator.h"
+#include <babeltrace/component/notification/iterator.h>
+#include <babeltrace/component/notification/notification.h>
+#include <babeltrace/component/notification/event.h>
+#include <babeltrace/component/notification/stream.h>
+#include <babeltrace/component/notification/packet.h>
+#include <babeltrace/component/component-filter.h>
+#include <babeltrace/ctf-ir/event.h>
+#include <babeltrace/ctf-ir/stream.h>
+#include <babeltrace/ctf-ir/stream-class.h>
+#include <babeltrace/ctf-ir/clock-class.h>
+#include <babeltrace/ctf-ir/packet.h>
+#include <babeltrace/ctf-ir/trace.h>
+#include <babeltrace/ctf-ir/fields.h>
+#include <assert.h>
+#include <plugins-common.h>
+
+BT_HIDDEN
+void trimmer_iterator_destroy(struct bt_notification_iterator *it)
+{
+ struct trimmer_iterator *it_data;
+
+ it_data = bt_notification_iterator_get_private_data(it);
+ assert(it_data);
+
+ if (it_data->input_iterator_group) {
+ g_ptr_array_free(it_data->input_iterator_group, TRUE);
+ }
+ bt_put(it_data->current_notification);
+ g_free(it_data);
+}
+
+BT_HIDDEN
+enum bt_notification_iterator_status trimmer_iterator_init(
+ struct bt_component *component,
+ struct bt_notification_iterator *iterator,
+ UNUSED_VAR void *init_method_data)
+{
+ enum bt_notification_iterator_status ret =
+ BT_NOTIFICATION_ITERATOR_STATUS_OK;
+ enum bt_notification_iterator_status it_ret;
+ struct trimmer_iterator *it_data = g_new0(struct trimmer_iterator, 1);
+
+ if (!it_data) {
+ ret = BT_NOTIFICATION_ITERATOR_STATUS_NOMEM;
+ goto end;
+ }
+
+ /* FIXME init trimmer_iterator */
+ it_ret = bt_notification_iterator_set_private_data(iterator, it_data);
+ if (it_ret) {
+ goto end;
+ }
+end:
+ return ret;
+}
+
+BT_HIDDEN
+struct bt_notification *trimmer_iterator_get(
+ struct bt_notification_iterator *iterator)
+{
+ struct trimmer_iterator *trim_it;
+
+ trim_it = bt_notification_iterator_get_private_data(iterator);
+ assert(trim_it);
+
+ if (!trim_it->current_notification) {
+ enum bt_notification_iterator_status it_ret;
+
+ it_ret = trimmer_iterator_next(iterator);
+ if (it_ret) {
+ goto end;
+ }
+ }
+end:
+ return bt_get(trim_it->current_notification);
+}
+
+static
+int update_lazy_bound(struct trimmer_bound *bound, const char *name,
+ int64_t ts, bool *lazy_update)
+{
+ struct tm tm;
+ int64_t value;
+ time_t timeval;
+
+ *lazy_update = false;
+
+ if (!bound->lazy) {
+ return 0;
+ }
+ tm.tm_isdst = -1;
+ timeval = ts / NSEC_PER_SEC;
+
+ if (bound->lazy_values.gmt) {
+ /* Get day, month, year. */
+ if (!gmtime_r(&timeval, &tm)) {
+ printf_error("Failure in gmtime_r()");
+ goto error;
+ }
+ tm.tm_sec = bound->lazy_values.ss;
+ tm.tm_min = bound->lazy_values.mm;
+ tm.tm_hour = bound->lazy_values.hh;
+ timeval = timegm(&tm);
+ if (timeval < 0) {
+ printf_error("Failure in timegm(), incorrectly formatted %s timestamp",
+ name);
+ goto error;
+ }
+ } else {
+ /* Get day, month, year. */
+ if (!localtime_r(&timeval, &tm)) {
+ printf_error("Failure in localtime_r()");
+ goto error;
+ }
+ tm.tm_sec = bound->lazy_values.ss;
+ tm.tm_min = bound->lazy_values.mm;
+ tm.tm_hour = bound->lazy_values.hh;
+ timeval = mktime(&tm);
+ if (timeval < 0) {
+ printf_error("Failure in mktime(), incorrectly formatted %s timestamp",
+ name);
+ goto error;
+ }
+ }
+ value = (int64_t) timeval;
+ value *= NSEC_PER_SEC;
+ value += bound->lazy_values.ns;
+ bound->value = value;
+ bound->set = true;
+ bound->lazy = false;
+ *lazy_update = true;
+ return 0;
+
+error:
+ return -1;
+}
+
+static
+enum bt_notification_iterator_status
+evaluate_event_notification(struct bt_notification *notification,
+ struct trimmer_bound *begin, struct trimmer_bound *end,
+ bool *_event_in_range)
+{
+ int64_t ts;
+ int clock_ret;
+ struct bt_ctf_event *event = NULL;
+ bool in_range = true;
+ struct bt_ctf_clock_class *clock_class = 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;
+ enum bt_notification_iterator_status ret =
+ BT_NOTIFICATION_ITERATOR_STATUS_OK;
+ bool lazy_update = false;
+
+ event = bt_notification_event_get_event(notification);
+ assert(event);
+
+ stream = bt_ctf_event_get_stream(event);
+ assert(stream);
+
+ 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_class = bt_ctf_trace_get_clock_class(trace, 0);
+ if (!clock_class) {
+ goto end;
+ }
+
+ clock_value = bt_ctf_event_get_clock_value(event, clock_class);
+ if (!clock_value) {
+ printf_error("Failed to retrieve clock value");
+ ret = BT_NOTIFICATION_ITERATOR_STATUS_ERROR;
+ 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");
+ ret = BT_NOTIFICATION_ITERATOR_STATUS_ERROR;
+ goto end;
+ }
+ if (update_lazy_bound(begin, "begin", ts, &lazy_update)) {
+ ret = BT_NOTIFICATION_ITERATOR_STATUS_ERROR;
+ goto end;
+ }
+ if (update_lazy_bound(end, "end", ts, &lazy_update)) {
+ ret = BT_NOTIFICATION_ITERATOR_STATUS_ERROR;
+ goto end;
+ }
+ if (lazy_update && begin->set && end->set) {
+ if (begin->value > end->value) {
+ printf_error("Unexpected: time range begin value is above end value");
+ ret = BT_NOTIFICATION_ITERATOR_STATUS_ERROR;
+ goto end;
+ }
+ }
+ if (begin->set && ts < begin->value) {
+ in_range = false;
+ }
+ if (end->set && ts > end->value) {
+ in_range = false;
+ }
+end:
+ bt_put(event);
+ bt_put(clock_class);
+ bt_put(trace);
+ bt_put(stream);
+ bt_put(stream_class);
+ bt_put(clock_value);
+ *_event_in_range = in_range;
+ return ret;
+}
+
+static
+int ns_from_integer_field(struct bt_ctf_field *integer, int64_t *ns)
+{
+ int ret = 0;
+ int is_signed;
+ uint64_t raw_clock_value;
+ struct bt_ctf_field_type *integer_type = NULL;
+ struct bt_ctf_clock_class *clock_class = NULL;
+ struct bt_ctf_clock_value *clock_value = NULL;
+
+ integer_type = bt_ctf_field_get_type(integer);
+ assert(integer_type);
+ clock_class = bt_ctf_field_type_integer_get_mapped_clock_class(
+ integer_type);
+ if (!clock_class) {
+ ret = -1;
+ goto end;
+ }
+
+ 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;
+ }
+
+ clock_value = bt_ctf_clock_value_create(clock_class, raw_clock_value);
+ if (!clock_value) {
+ goto end;
+ }
+
+ ret = bt_ctf_clock_value_get_value_ns_from_epoch(clock_value, ns);
+end:
+ bt_put(integer_type);
+ bt_put(clock_class);
+ bt_put(clock_value);
+ return ret;
+}
+
+static
+enum bt_notification_iterator_status evaluate_packet_notification(
+ struct bt_notification *notification,
+ struct trimmer_bound *begin, struct trimmer_bound *end,
+ bool *_packet_in_range)
+{
+ enum bt_notification_iterator_status ret =
+ BT_NOTIFICATION_ITERATOR_STATUS_OK;
+ 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:
+ break;
+ }
+ 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;
+ }
+
+ if (ns_from_integer_field(timestamp_begin, &pkt_begin_ns)) {
+ goto end;
+ }
+ if (ns_from_integer_field(timestamp_end, &pkt_end_ns)) {
+ 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:
+ *_packet_in_range = in_range;
+ bt_put(packet);
+ bt_put(packet_context);
+ bt_put(timestamp_begin);
+ bt_put(timestamp_end);
+ return ret;
+}
+
+/* Return true if the notification should be forwarded. */
+static
+enum bt_notification_iterator_status evaluate_notification(
+ struct bt_notification *notification,
+ struct trimmer_bound *begin, struct trimmer_bound *end,
+ bool *in_range)
+{
+ enum bt_notification_type type;
+ enum bt_notification_iterator_status ret =
+ BT_NOTIFICATION_ITERATOR_STATUS_OK;
+
+ *in_range = true;
+ type = bt_notification_get_type(notification);
+ switch (type) {
+ case BT_NOTIFICATION_TYPE_EVENT:
+ ret = evaluate_event_notification(notification, begin,
+ end, in_range);
+ break;
+ case BT_NOTIFICATION_TYPE_PACKET_BEGIN:
+ case BT_NOTIFICATION_TYPE_PACKET_END:
+ ret = evaluate_packet_notification(notification, begin,
+ end, in_range);
+ break;
+ default:
+ /* Accept all other notifications. */
+ break;
+ }
+ return ret;
+}
+
+BT_HIDDEN
+enum bt_notification_iterator_status trimmer_iterator_next(
+ struct bt_notification_iterator *iterator)
+{
+ struct trimmer_iterator *trim_it = NULL;
+ struct bt_component *component = NULL;
+ struct trimmer *trimmer = NULL;
+ struct bt_notification_iterator *source_it = NULL;
+ enum bt_notification_iterator_status ret =
+ BT_NOTIFICATION_ITERATOR_STATUS_OK;
+ enum bt_component_status component_ret;
+ bool notification_in_range = false;
+
+ trim_it = bt_notification_iterator_get_private_data(iterator);
+ assert(trim_it);
+
+ component = bt_notification_iterator_get_component(iterator);
+ assert(component);
+ trimmer = bt_component_get_private_data(component);
+ assert(trimmer);
+
+ /* FIXME, should handle input iterator groups. */
+ component_ret = bt_component_filter_get_input_iterator(component, 0,
+ &source_it);
+ assert((component_ret == BT_COMPONENT_STATUS_OK) && source_it);
+
+ while (!notification_in_range) {
+ struct bt_notification *notification;
+
+ ret = bt_notification_iterator_next(source_it);
+ if (ret != BT_NOTIFICATION_ITERATOR_STATUS_OK) {
+ goto end;
+ }
+
+ notification = bt_notification_iterator_get_notification(
+ source_it);
+ if (!notification) {
+ ret = BT_NOTIFICATION_ITERATOR_STATUS_ERROR;
+ goto end;
+ }
+
+ ret = evaluate_notification(notification,
+ &trimmer->begin, &trimmer->end,
+ ¬ification_in_range);
+ if (notification_in_range) {
+ BT_MOVE(trim_it->current_notification, notification);
+ } else {
+ bt_put(notification);
+ }
+
+ if (ret != BT_NOTIFICATION_ITERATOR_STATUS_OK) {
+ break;
+ }
+ }
+end:
+ bt_put(source_it);
+ bt_put(component);
+ return ret;
+}
+
+BT_HIDDEN
+enum bt_notification_iterator_status trimmer_iterator_seek_time(
+ struct bt_notification_iterator *iterator, int64_t time)
+{
+ enum bt_notification_iterator_status ret;
+
+ ret = BT_NOTIFICATION_ITERATOR_STATUS_OK;
+end:
+ return ret;
+}
--- /dev/null
+#ifndef BABELTRACE_PLUGIN_TRIMMER_ITERATOR_H
+#define BABELTRACE_PLUGIN_TRIMMER_ITERATOR_H
+
+/*
+ * BabelTrace - Trace Trimmer Iterator
+ *
+ * Copyright 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "trimmer.h"
+#include <babeltrace/component/notification/notification.h>
+#include <babeltrace/component/notification/iterator.h>
+
+struct trimmer_iterator {
+ /* Input iterators associated with this output iterator. */
+ GPtrArray *input_iterator_group;
+ struct bt_notification *current_notification;
+};
+
+BT_HIDDEN
+enum bt_notification_iterator_status trimmer_iterator_init(
+ struct bt_component *component,
+ struct bt_notification_iterator *iterator, void *init_method_data);
+
+BT_HIDDEN
+void trimmer_iterator_destroy(struct bt_notification_iterator *it);
+
+BT_HIDDEN
+struct bt_notification *trimmer_iterator_get(
+ struct bt_notification_iterator *iterator);
+
+BT_HIDDEN
+enum bt_notification_iterator_status trimmer_iterator_next(
+ struct bt_notification_iterator *iterator);
+
+BT_HIDDEN
+enum bt_notification_iterator_status trimmer_iterator_seek_time(
+ struct bt_notification_iterator *iterator, int64_t time);
+
+#endif /* BABELTRACE_PLUGIN_TRIMMER_ITERATOR_H */
--- /dev/null
+/*
+ * trimmer.c
+ *
+ * Babeltrace Trace Trimmer
+ *
+ * Copyright 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <babeltrace/plugin/plugin-dev.h>
+#include <babeltrace/component/component.h>
+#include <babeltrace/component/component-filter.h>
+#include <babeltrace/component/notification/notification.h>
+#include <babeltrace/component/notification/iterator.h>
+#include <babeltrace/component/notification/event.h>
+#include <plugins-common.h>
+#include "trimmer.h"
+#include "iterator.h"
+#include <assert.h>
+
+static
+void destroy_trimmer_data(struct trimmer *trimmer)
+{
+ g_free(trimmer);
+}
+
+static
+struct trimmer *create_trimmer_data(void)
+{
+ struct trimmer *trimmer;
+
+ trimmer = g_new0(struct trimmer, 1);
+ if (!trimmer) {
+ goto end;
+ }
+end:
+ return trimmer;
+}
+
+void destroy_trimmer(struct bt_component *component)
+{
+ void *data = bt_component_get_private_data(component);
+
+ destroy_trimmer_data(data);
+}
+
+/*
+ * Parses a timestamp, figuring out its format.
+ *
+ * Returns a negative value if anything goes wrong.
+ *
+ * Expected formats:
+ *
+ * YYYY-MM-DD hh:mm:ss.ns
+ * hh:mm:ss.ns
+ * -ss.ns
+ * ss.ns
+ * YYYY-MM-DD hh:mm:ss
+ * hh:mm:ss
+ * -ss
+ * ss
+ */
+static
+int timestamp_from_arg(const char *arg, struct trimmer *trimmer,
+ struct trimmer_bound *result_bound, bool gmt)
+{
+ int ret;
+ int64_t value;
+ unsigned int year, month, day, hh, mm, ss, ns;
+
+ /* YYYY-MM-DD hh:mm:ss.ns */
+ ret = sscanf(arg, "%u-%u-%u %u:%u:%u.%u",
+ &year, &month, &day, &hh, &mm, &ss, &ns);
+ if (ret == 7) {
+ struct tm tm = {
+ .tm_sec = ss,
+ .tm_min = mm,
+ .tm_hour = hh,
+ .tm_mday = day,
+ .tm_mon = month - 1,
+ .tm_year = year - 1900,
+ .tm_isdst = -1,
+ };
+ time_t result;
+
+ if (gmt) {
+ result = timegm(&tm);
+ if (result < 0) {
+ return -1;
+ }
+ } else {
+ result = mktime(&tm);
+ if (result < 0) {
+ return -1;
+ }
+ }
+ value = (int64_t) result;
+ value *= NSEC_PER_SEC;
+ value += ns;
+ if (!trimmer->date) {
+ trimmer->year = year;
+ trimmer->month = month;
+ trimmer->day = day;
+ trimmer->date = true;
+ }
+ goto set;
+ }
+ /* hh:mm:ss.ns */
+ ret = sscanf(arg, "%u:%u:%u.%u",
+ &hh, &mm, &ss, &ns);
+ if (ret == 4) {
+ if (!trimmer->date) {
+ /* We don't know which day until we get an event. */
+ result_bound->lazy_values.hh = hh;
+ result_bound->lazy_values.mm = mm;
+ result_bound->lazy_values.ss = ss;
+ result_bound->lazy_values.ns = ns;
+ result_bound->lazy_values.gmt = gmt;
+ goto lazy;
+ } else {
+ struct tm tm = {
+ .tm_sec = ss,
+ .tm_min = mm,
+ .tm_hour = hh,
+ .tm_mday = trimmer->day,
+ .tm_mon = trimmer->month - 1,
+ .tm_year = trimmer->year - 1900,
+ .tm_isdst = -1,
+ };
+ time_t result;
+
+ if (gmt) {
+ result = timegm(&tm);
+ if (result < 0) {
+ return -1;
+ }
+ } else {
+ result = mktime(&tm);
+ if (result < 0) {
+ return -1;
+ }
+ }
+ value = (int64_t) result;
+ value *= NSEC_PER_SEC;
+ value += ns;
+ goto set;
+ }
+ }
+ /* -ss.ns */
+ ret = sscanf(arg, "-%u.%u",
+ &ss, &ns);
+ if (ret == 2) {
+ value = -ss * NSEC_PER_SEC;
+ value -= ns;
+ goto set;
+ }
+ /* ss.ns */
+ ret = sscanf(arg, "%u.%u",
+ &ss, &ns);
+ if (ret == 2) {
+ value = ss * NSEC_PER_SEC;
+ value += ns;
+ goto set;
+ }
+
+ /* YYYY-MM-DD hh:mm:ss */
+ ret = sscanf(arg, "%u-%u-%u %u:%u:%u",
+ &year, &month, &day, &hh, &mm, &ss);
+ if (ret == 6) {
+ struct tm tm = {
+ .tm_sec = ss,
+ .tm_min = mm,
+ .tm_hour = hh,
+ .tm_mday = day,
+ .tm_mon = month - 1,
+ .tm_year = year - 1900,
+ .tm_isdst = -1,
+ };
+
+ if (gmt) {
+ value = timegm(&tm);
+ if (value < 0) {
+ return -1;
+ }
+ } else {
+ value = mktime(&tm);
+ if (value < 0) {
+ return -1;
+ }
+ }
+ value *= NSEC_PER_SEC;
+ if (!trimmer->date) {
+ trimmer->year = year;
+ trimmer->month = month;
+ trimmer->day = day;
+ trimmer->date = true;
+ }
+ goto set;
+ }
+ /* hh:mm:ss */
+ ret = sscanf(arg, "%u:%u:%u",
+ &hh, &mm, &ss);
+ if (ret == 3) {
+ if (!trimmer->date) {
+ /* We don't know which day until we get an event. */
+ result_bound->lazy_values.hh = hh;
+ result_bound->lazy_values.mm = mm;
+ result_bound->lazy_values.ss = ss;
+ result_bound->lazy_values.ns = 0;
+ result_bound->lazy_values.gmt = gmt;
+ goto lazy;
+ } else {
+ struct tm tm = {
+ .tm_sec = ss,
+ .tm_min = mm,
+ .tm_hour = hh,
+ .tm_mday = trimmer->day,
+ .tm_mon = trimmer->month - 1,
+ .tm_year = trimmer->year - 1900,
+ .tm_isdst = -1,
+ };
+ time_t result;
+
+ if (gmt) {
+ result = timegm(&tm);
+ if (result < 0) {
+ return -1;
+ }
+ } else {
+ result = mktime(&tm);
+ if (result < 0) {
+ return -1;
+ }
+ }
+ value = (int64_t) result;
+ value *= NSEC_PER_SEC;
+ goto set;
+ }
+ }
+ /* -ss */
+ ret = sscanf(arg, "-%u",
+ &ss);
+ if (ret == 1) {
+ value = -ss * NSEC_PER_SEC;
+ goto set;
+ }
+ /* ss */
+ ret = sscanf(arg, "%u",
+ &ss);
+ if (ret == 1) {
+ value = ss * NSEC_PER_SEC;
+ goto set;
+ }
+
+ /* Not found. */
+ return -1;
+
+set:
+ result_bound->value = value;
+ result_bound->set = true;
+ return 0;
+
+lazy:
+ result_bound->lazy = true;
+ return 0;
+}
+
+static
+enum bt_component_status init_from_params(struct trimmer *trimmer, struct bt_value *params)
+{
+ struct bt_value *value = NULL;
+ bool gmt = false;
+ enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
+
+ assert(params);
+
+ value = bt_value_map_get(params, "clock-gmt");
+ if (value) {
+ enum bt_value_status value_ret;
+
+ value_ret = bt_value_bool_get(value, &gmt);
+ if (value_ret) {
+ ret = BT_COMPONENT_STATUS_INVALID;
+ printf_error("Failed to retrieve clock-gmt value. Expecting a boolean");
+ }
+ }
+ bt_put(value);
+ if (ret != BT_COMPONENT_STATUS_OK) {
+ goto end;
+ }
+
+ value = bt_value_map_get(params, "begin");
+ if (value) {
+ enum bt_value_status value_ret;
+ const char *str;
+
+ value_ret = bt_value_string_get(value, &str);
+ if (value_ret || timestamp_from_arg(str,
+ trimmer, &trimmer->begin, gmt)) {
+ ret = BT_COMPONENT_STATUS_INVALID;
+ printf_error("Failed to retrieve begin value. Expecting a timestamp string");
+ }
+ }
+ bt_put(value);
+ if (ret != BT_COMPONENT_STATUS_OK) {
+ goto end;
+ }
+
+ value = bt_value_map_get(params, "end");
+ if (value) {
+ enum bt_value_status value_ret;
+ const char *str;
+
+ value_ret = bt_value_string_get(value, &str);
+ if (value_ret || timestamp_from_arg(str,
+ trimmer, &trimmer->end, gmt)) {
+ ret = BT_COMPONENT_STATUS_INVALID;
+ printf_error("Failed to retrieve end value. Expecting a timestamp string");
+ }
+ }
+ bt_put(value);
+end:
+ if (trimmer->begin.set && trimmer->end.set) {
+ if (trimmer->begin.value > trimmer->end.value) {
+ printf_error("Unexpected: time range begin value is above end value");
+ ret = BT_COMPONENT_STATUS_INVALID;
+ }
+ }
+ return ret;
+}
+
+enum bt_component_status trimmer_component_init(
+ struct bt_component *component, struct bt_value *params,
+ UNUSED_VAR void *init_method_data)
+{
+ enum bt_component_status ret;
+ struct trimmer *trimmer = create_trimmer_data();
+
+ if (!trimmer) {
+ ret = BT_COMPONENT_STATUS_NOMEM;
+ goto end;
+ }
+
+ ret = bt_component_set_private_data(component, trimmer);
+ if (ret != BT_COMPONENT_STATUS_OK) {
+ goto error;
+ }
+
+ ret = init_from_params(trimmer, params);
+end:
+ return ret;
+error:
+ destroy_trimmer_data(trimmer);
+ return ret;
+}
--- /dev/null
+#ifndef BABELTRACE_PLUGINS_UTILS_TRIMMER_H
+#define BABELTRACE_PLUGINS_UTILS_TRIMMER_H
+
+/*
+ * BabelTrace - Trace Trimmer Plug-in
+ *
+ * Copyright 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <stdbool.h>
+#include <babeltrace/babeltrace-internal.h>
+#include <babeltrace/values.h>
+#include <babeltrace/component/component.h>
+
+#define NSEC_PER_SEC 1000000000LL
+
+struct trimmer_bound {
+ int64_t value;
+ bool set;
+ bool lazy;
+ struct {
+ int hh, mm, ss, ns;
+ bool gmt;
+ } lazy_values;
+};
+
+struct trimmer {
+ struct trimmer_bound begin, end;
+ bool date;
+ int year, month, day;
+};
+
+enum bt_component_status trimmer_component_init(
+ struct bt_component *component, struct bt_value *params,
+ void *init_method_data);
+
+void destroy_trimmer(struct bt_component *component);
+
+#endif /* BABELTRACE_PLUGINS_UTILS_TRIMMER_H */