Add utils.dummy component class, move plugins/trimmer to plugins/utils
authorPhilippe Proulx <eeppeliteloop@gmail.com>
Sat, 11 Feb 2017 03:49:22 +0000 (22:49 -0500)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Sun, 28 May 2017 16:57:38 +0000 (12:57 -0400)
This patch adds a plugins/utils directory where the utils plugin sources
are. plugins/trimmer is moved to this new directory because the trimmer
component class is part of the utils plugin.

Also in the utils plugin is the dummy sink component class. This sink
does absolutely nothing with its notifications. It is the equivalent of
the BT 1.x dummy format. At consume time, it gets one notification per
input notification iterator and returns
BT_NOTIFICATION_ITERATOR_STATUS_END when all the iterators are at the
end.

The legacy `-o dummy` option is not handled specifically in this commit.
You can use the dummy sink as usual:

    babeltrace /path/to/trace -o utils.dummy

The dummy component class ignores its initialization parameters.

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
18 files changed:
configure.ac
converter/Makefile.am
plugins/Makefile.am
plugins/trimmer/Makefile.am [deleted file]
plugins/trimmer/iterator.c [deleted file]
plugins/trimmer/iterator.h [deleted file]
plugins/trimmer/trimmer.c [deleted file]
plugins/trimmer/trimmer.h [deleted file]
plugins/utils/Makefile.am [new file with mode: 0644]
plugins/utils/dummy/Makefile.am [new file with mode: 0644]
plugins/utils/dummy/dummy.c [new file with mode: 0644]
plugins/utils/dummy/dummy.h [new file with mode: 0644]
plugins/utils/plugin.c [new file with mode: 0644]
plugins/utils/trimmer/Makefile.am [new file with mode: 0644]
plugins/utils/trimmer/iterator.c [new file with mode: 0644]
plugins/utils/trimmer/iterator.h [new file with mode: 0644]
plugins/utils/trimmer/trimmer.c [new file with mode: 0644]
plugins/utils/trimmer/trimmer.h [new file with mode: 0644]

index de5553b94a141f86e6504082b5ab82874fdc552d..d48be53b6904ec3ac67fa57d569349da5346474a 100644 (file)
@@ -492,8 +492,10 @@ AC_CONFIG_FILES([
        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
 ])
index 6cbe2ff92ad42cfb40e3dcd40c9af52732ced563..5e88fb0ba70039962cf6dc0703b511b24cb00c8f 100644 (file)
@@ -1,6 +1,6 @@
 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
index 2d697dbbbf5ca8751b2af65c88ba0466fedfd62f..158e7d7d336496d40680b76f0b0e95855c49ceae 100644 (file)
@@ -1,3 +1,3 @@
-SUBDIRS = ctf text muxer trimmer writer
+SUBDIRS = ctf text muxer writer utils
 
 noinst_HEADERS = plugins-common.h
diff --git a/plugins/trimmer/Makefile.am b/plugins/trimmer/Makefile.am
deleted file mode 100644 (file)
index cf1fba4..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-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
diff --git a/plugins/trimmer/iterator.c b/plugins/trimmer/iterator.c
deleted file mode 100644 (file)
index 04557cb..0000000
+++ /dev/null
@@ -1,465 +0,0 @@
-/*
- * 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,
-                               &notification_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;
-}
diff --git a/plugins/trimmer/iterator.h b/plugins/trimmer/iterator.h
deleted file mode 100644 (file)
index 1a632cd..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-#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 */
diff --git a/plugins/trimmer/trimmer.c b/plugins/trimmer/trimmer.c
deleted file mode 100644 (file)
index 06814ef..0000000
+++ /dev/null
@@ -1,393 +0,0 @@
-/*
- * 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);
diff --git a/plugins/trimmer/trimmer.h b/plugins/trimmer/trimmer.h
deleted file mode 100644 (file)
index 4d82a24..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-#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 */
diff --git a/plugins/utils/Makefile.am b/plugins/utils/Makefile.am
new file mode 100644 (file)
index 0000000..9918807
--- /dev/null
@@ -0,0 +1,15 @@
+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
diff --git a/plugins/utils/dummy/Makefile.am b/plugins/utils/dummy/Makefile.am
new file mode 100644 (file)
index 0000000..8be2676
--- /dev/null
@@ -0,0 +1,4 @@
+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
diff --git a/plugins/utils/dummy/dummy.c b/plugins/utils/dummy/dummy.c
new file mode 100644 (file)
index 0000000..66b2996
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * 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;
+}
diff --git a/plugins/utils/dummy/dummy.h b/plugins/utils/dummy/dummy.h
new file mode 100644 (file)
index 0000000..2fcf34b
--- /dev/null
@@ -0,0 +1,28 @@
+#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 */
diff --git a/plugins/utils/plugin.c b/plugins/utils/plugin.c
new file mode 100644 (file)
index 0000000..de25342
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * 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);
diff --git a/plugins/utils/trimmer/Makefile.am b/plugins/utils/trimmer/Makefile.am
new file mode 100644 (file)
index 0000000..8ef55db
--- /dev/null
@@ -0,0 +1,8 @@
+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
diff --git a/plugins/utils/trimmer/iterator.c b/plugins/utils/trimmer/iterator.c
new file mode 100644 (file)
index 0000000..04557cb
--- /dev/null
@@ -0,0 +1,465 @@
+/*
+ * 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,
+                               &notification_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;
+}
diff --git a/plugins/utils/trimmer/iterator.h b/plugins/utils/trimmer/iterator.h
new file mode 100644 (file)
index 0000000..1a632cd
--- /dev/null
@@ -0,0 +1,60 @@
+#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 */
diff --git a/plugins/utils/trimmer/trimmer.c b/plugins/utils/trimmer/trimmer.c
new file mode 100644 (file)
index 0000000..af838d7
--- /dev/null
@@ -0,0 +1,374 @@
+/*
+ * 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;
+}
diff --git a/plugins/utils/trimmer/trimmer.h b/plugins/utils/trimmer/trimmer.h
new file mode 100644 (file)
index 0000000..655a60c
--- /dev/null
@@ -0,0 +1,59 @@
+#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 */
This page took 0.04871 seconds and 4 git commands to generate.