Rename writer.writer -> ctf.fs (sink) and standardize plugin descriptions
authorPhilippe Proulx <eeppeliteloop@gmail.com>
Fri, 5 May 2017 17:54:23 +0000 (13:54 -0400)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Sun, 28 May 2017 16:57:42 +0000 (12:57 -0400)
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
40 files changed:
configure.ac
plugins/Makefile.am
plugins/ctf/Makefile.am
plugins/ctf/fs-sink/Makefile.am [new file with mode: 0644]
plugins/ctf/fs-sink/write.c [new file with mode: 0644]
plugins/ctf/fs-sink/writer.c [new file with mode: 0644]
plugins/ctf/fs-sink/writer.h [new file with mode: 0644]
plugins/ctf/fs-src/Makefile.am [new file with mode: 0644]
plugins/ctf/fs-src/data-stream.c [new file with mode: 0644]
plugins/ctf/fs-src/data-stream.h [new file with mode: 0644]
plugins/ctf/fs-src/file.c [new file with mode: 0644]
plugins/ctf/fs-src/file.h [new file with mode: 0644]
plugins/ctf/fs-src/fs.c [new file with mode: 0644]
plugins/ctf/fs-src/fs.h [new file with mode: 0644]
plugins/ctf/fs-src/lttng-index.h [new file with mode: 0644]
plugins/ctf/fs-src/metadata.c [new file with mode: 0644]
plugins/ctf/fs-src/metadata.h [new file with mode: 0644]
plugins/ctf/fs-src/print.h [new file with mode: 0644]
plugins/ctf/fs/Makefile.am [deleted file]
plugins/ctf/fs/data-stream.c [deleted file]
plugins/ctf/fs/data-stream.h [deleted file]
plugins/ctf/fs/file.c [deleted file]
plugins/ctf/fs/file.h [deleted file]
plugins/ctf/fs/fs.c [deleted file]
plugins/ctf/fs/fs.h [deleted file]
plugins/ctf/fs/lttng-index.h [deleted file]
plugins/ctf/fs/metadata.c [deleted file]
plugins/ctf/fs/metadata.h [deleted file]
plugins/ctf/fs/print.h [deleted file]
plugins/ctf/lttng-live/lttng-live-internal.h
plugins/ctf/plugin.c
plugins/text/dmesg/Makefile.am [new file with mode: 0644]
plugins/text/dmesg/dmesg.c [new file with mode: 0644]
plugins/text/dmesg/dmesg.h [new file with mode: 0644]
plugins/text/plugin.c
plugins/utils/plugin.c
plugins/writer/Makefile.am [deleted file]
plugins/writer/write.c [deleted file]
plugins/writer/writer.c [deleted file]
plugins/writer/writer.h [deleted file]

index 8890f4abd5289b40f72ca64ff1527f1587f76a81..0ca41afb239777637e899a2d50841efb1d32ee93 100644 (file)
@@ -496,11 +496,11 @@ AC_CONFIG_FILES([
        plugins/ctf/common/btr/Makefile
        plugins/ctf/common/metadata/Makefile
        plugins/ctf/common/notif-iter/Makefile
-       plugins/ctf/fs/Makefile
+       plugins/ctf/fs-src/Makefile
+       plugins/ctf/fs-sink/Makefile
        plugins/ctf/lttng-live/Makefile
        plugins/text/Makefile
        plugins/text/pretty/Makefile
-       plugins/writer/Makefile
        plugins/utils/Makefile
        plugins/utils/dummy/Makefile
        plugins/utils/trimmer/Makefile
index c6249c4d0ce2d97b05ae6c7399b0d67fdf5256d8..be2de4e7a86409f198aa1f968e25491a095499c9 100644 (file)
@@ -1,4 +1,4 @@
-SUBDIRS = libctfcopytrace ctf text utils writer
+SUBDIRS = libctfcopytrace ctf text utils
 
 if ENABLE_DEBUG_INFO
 SUBDIRS += lttng-utils
index f53a6ab34060b9fb59c888cc576e6eaf184262f3..566577ae96705e92a88ac562bdfc4849b3701e5e 100644 (file)
@@ -1,6 +1,6 @@
 AM_CFLAGS = $(PACKAGE_CFLAGS) -I$(top_srcdir)/include
 
-SUBDIRS = common fs lttng-live
+SUBDIRS = common fs-src fs-sink lttng-live
 
 plugindir = "$(PLUGINSDIR)"
 plugin_LTLIBRARIES = libbabeltrace-plugin-ctf.la
@@ -13,5 +13,6 @@ libbabeltrace_plugin_ctf_la_LDFLAGS = \
 
 libbabeltrace_plugin_ctf_la_LIBADD = \
        $(top_builddir)/lib/libbabeltrace.la \
-       fs/libbabeltrace-plugin-ctf-fs.la \
-       lttng-live/libbabeltrace-plugin-ctf-lttng-live.la
+       fs-src/libbabeltrace-plugin-ctf-fs.la \
+       lttng-live/libbabeltrace-plugin-ctf-lttng-live.la \
+       fs-sink/libbabeltrace-plugin-ctf-writer.la
diff --git a/plugins/ctf/fs-sink/Makefile.am b/plugins/ctf/fs-sink/Makefile.am
new file mode 100644 (file)
index 0000000..62f7711
--- /dev/null
@@ -0,0 +1,8 @@
+AM_CFLAGS = $(PACKAGE_CFLAGS) -I$(top_srcdir)/include -I$(top_srcdir)/plugins \
+       -I$(top_srcdir)/plugins/libctfcopytrace
+
+noinst_LTLIBRARIES = libbabeltrace-plugin-ctf-writer.la
+
+libbabeltrace_plugin_ctf_writer_la_LIBADD = \
+       $(top_builddir)/plugins/libctfcopytrace/libctfcopytrace.la
+libbabeltrace_plugin_ctf_writer_la_SOURCES = writer.c writer.h write.c
diff --git a/plugins/ctf/fs-sink/write.c b/plugins/ctf/fs-sink/write.c
new file mode 100644 (file)
index 0000000..91b9289
--- /dev/null
@@ -0,0 +1,492 @@
+/*
+ * writer.c
+ *
+ * Babeltrace CTF Writer Output Plugin Event Handling
+ *
+ * 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/ctf-ir/event.h>
+#include <babeltrace/ctf-ir/packet.h>
+#include <babeltrace/ctf-ir/event-class.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/fields.h>
+#include <babeltrace/ctf-writer/stream-class.h>
+#include <babeltrace/ctf-writer/stream.h>
+
+#include <ctfcopytrace.h>
+
+#include "writer.h"
+
+static
+struct bt_ctf_stream_class *insert_new_stream_class(
+               struct writer_component *writer_component,
+               struct bt_ctf_writer *ctf_writer,
+               struct bt_ctf_stream_class *stream_class)
+{
+       struct bt_ctf_stream_class *writer_stream_class = NULL;
+       struct bt_ctf_trace *trace = NULL, *writer_trace = NULL;
+       enum bt_component_status ret;
+
+       trace = bt_ctf_stream_class_get_trace(stream_class);
+       if (!trace) {
+               fprintf(writer_component->err,
+                               "[error] %s in %s:%d\n", __func__, __FILE__,
+                               __LINE__);
+               goto error;
+       }
+
+       writer_trace = bt_ctf_writer_get_trace(ctf_writer);
+       if (!writer_trace) {
+               fprintf(writer_component->err,
+                               "[error] %s in %s:%d\n", __func__, __FILE__,
+                               __LINE__);
+               goto error;
+       }
+
+       ret = ctf_copy_clock_classes(writer_component->err, writer_trace,
+                       writer_stream_class, trace);
+       if (ret != BT_COMPONENT_STATUS_OK) {
+               fprintf(writer_component->err,
+                               "[error] %s in %s:%d\n", __func__, __FILE__,
+                               __LINE__);
+               goto error;
+       }
+
+       writer_stream_class = ctf_copy_stream_class(writer_component->err,
+                       stream_class, writer_trace, true);
+       if (!writer_stream_class) {
+               fprintf(writer_component->err, "[error] Failed to copy stream class\n");
+               fprintf(writer_component->err, "[error] %s in %s:%d\n",
+                               __func__, __FILE__, __LINE__);
+               goto error;
+       }
+
+       g_hash_table_insert(writer_component->stream_class_map,
+                       (gpointer) stream_class, writer_stream_class);
+
+       goto end;
+
+error:
+       BT_PUT(writer_stream_class);
+end:
+       bt_put(writer_trace);
+       bt_put(trace);
+       return writer_stream_class;
+}
+
+static
+struct bt_ctf_stream *insert_new_stream(
+               struct writer_component *writer_component,
+               struct bt_ctf_writer *ctf_writer,
+               struct bt_ctf_stream_class *stream_class,
+               struct bt_ctf_stream *stream)
+{
+       struct bt_ctf_stream *writer_stream = NULL;
+       struct bt_ctf_stream_class *writer_stream_class = NULL;
+
+       writer_stream_class = g_hash_table_lookup(
+                       writer_component->stream_class_map,
+                       (gpointer) stream_class);
+       if (!writer_stream_class) {
+               writer_stream_class = insert_new_stream_class(
+                               writer_component, ctf_writer, stream_class);
+               if (!writer_stream_class) {
+                       fprintf(writer_component->err, "[error] %s in %s:%d\n",
+                                       __func__, __FILE__, __LINE__);
+                       goto error;
+               }
+       }
+       bt_get(writer_stream_class);
+
+       writer_stream = bt_ctf_writer_create_stream(ctf_writer,
+                       writer_stream_class);
+       if (!writer_stream) {
+               fprintf(writer_component->err, "[error] %s in %s:%d\n",
+                               __func__, __FILE__, __LINE__);
+               goto error;
+       }
+
+       g_hash_table_insert(writer_component->stream_map, (gpointer) stream,
+                       writer_stream);
+
+       goto end;
+
+error:
+       BT_PUT(writer_stream);
+end:
+       bt_put(writer_stream_class);
+       return writer_stream;
+}
+
+static
+struct bt_ctf_stream *lookup_stream(struct writer_component *writer_component,
+               struct bt_ctf_stream *stream)
+{
+       return (struct bt_ctf_stream *) g_hash_table_lookup(
+                       writer_component->stream_map,
+                       (gpointer) stream);
+}
+
+static
+struct bt_ctf_event_class *get_event_class(struct writer_component *writer_component,
+               struct bt_ctf_stream_class *writer_stream_class,
+               struct bt_ctf_event_class *event_class)
+{
+       return bt_ctf_stream_class_get_event_class_by_id(writer_stream_class,
+                       bt_ctf_event_class_get_id(event_class));
+}
+
+struct bt_ctf_writer *insert_new_writer(
+               struct writer_component *writer_component,
+               struct bt_ctf_trace *trace)
+{
+       struct bt_ctf_writer *ctf_writer = NULL;
+       struct bt_ctf_trace *writer_trace = NULL;
+       char trace_name[PATH_MAX];
+       enum bt_component_status ret;
+
+       /* FIXME: replace with trace name when it will work. */
+       snprintf(trace_name, PATH_MAX, "%s/%s_%03d",
+                       writer_component->base_path->str,
+                       writer_component->trace_name_base->str,
+                       writer_component->trace_id++);
+       printf_verbose("CTF-Writer creating trace in %s\n", trace_name);
+
+       ctf_writer = bt_ctf_writer_create(trace_name);
+       if (!ctf_writer) {
+               fprintf(writer_component->err, "[error] %s in %s:%d\n",
+                               __func__, __FILE__, __LINE__);
+               goto error;
+       }
+
+       writer_trace = bt_ctf_writer_get_trace(ctf_writer);
+       if (!writer_trace) {
+               fprintf(writer_component->err,
+                               "[error] %s in %s:%d\n", __func__, __FILE__,
+                               __LINE__);
+               goto error;
+       }
+
+       ret = ctf_copy_trace(writer_component->err, trace, writer_trace);
+       if (ret != BT_COMPONENT_STATUS_OK) {
+               fprintf(writer_component->err, "[error] Failed to copy trace\n");
+               fprintf(writer_component->err, "[error] %s in %s:%d\n",
+                               __func__, __FILE__, __LINE__);
+               BT_PUT(ctf_writer);
+               goto end;
+       }
+       BT_PUT(writer_trace);
+
+       g_hash_table_insert(writer_component->trace_map, (gpointer) trace,
+                       ctf_writer);
+
+       goto end;
+
+error:
+       bt_put(writer_trace);
+       BT_PUT(ctf_writer);
+end:
+       return ctf_writer;
+}
+
+static
+struct bt_ctf_writer *get_writer(struct writer_component *writer_component,
+               struct bt_ctf_stream_class *stream_class)
+{
+       struct bt_ctf_trace *trace = NULL;
+       struct bt_ctf_writer *ctf_writer = NULL;
+
+       trace = bt_ctf_stream_class_get_trace(stream_class);
+       if (!trace) {
+               ctf_writer = NULL;
+               fprintf(writer_component->err, "[error] %s in %s:%d\n",
+                               __func__, __FILE__, __LINE__);
+               goto error;
+       }
+
+       ctf_writer = g_hash_table_lookup(writer_component->trace_map,
+                       (gpointer) trace);
+       if (!ctf_writer) {
+               ctf_writer = insert_new_writer(writer_component, trace);
+       }
+       bt_get(ctf_writer);
+       BT_PUT(trace);
+       goto end;
+
+error:
+       BT_PUT(ctf_writer);
+end:
+       return ctf_writer;
+}
+
+static
+struct bt_ctf_stream *get_writer_stream(
+               struct writer_component *writer_component,
+               struct bt_ctf_packet *packet, struct bt_ctf_stream *stream)
+{
+       struct bt_ctf_stream_class *stream_class = NULL;
+       struct bt_ctf_writer *ctf_writer = NULL;
+       struct bt_ctf_stream *writer_stream = NULL;
+
+       stream_class = bt_ctf_stream_get_class(stream);
+       if (!stream_class) {
+               fprintf(writer_component->err, "[error] %s in %s:%d\n",
+                               __func__, __FILE__, __LINE__);
+               goto error;
+       }
+
+       ctf_writer = get_writer(writer_component, stream_class);
+       if (!ctf_writer) {
+               fprintf(writer_component->err, "[error] %s in %s:%d\n",
+                               __func__, __FILE__, __LINE__);
+               goto error;
+       }
+
+       writer_stream = lookup_stream(writer_component, stream);
+       if (!writer_stream) {
+               writer_stream = insert_new_stream(writer_component, ctf_writer,
+                               stream_class, stream);
+       }
+       bt_get(writer_stream);
+
+       goto end;
+
+error:
+       BT_PUT(writer_stream);
+end:
+       bt_put(ctf_writer);
+       bt_put(stream_class);
+       return writer_stream;
+}
+
+BT_HIDDEN
+enum bt_component_status writer_new_packet(
+               struct writer_component *writer_component,
+               struct bt_ctf_packet *packet)
+{
+       struct bt_ctf_stream *stream = NULL, *writer_stream = NULL;
+       struct bt_ctf_field *writer_packet_context = NULL;
+       enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
+       int int_ret;
+
+       stream = bt_ctf_packet_get_stream(packet);
+       if (!stream) {
+               fprintf(writer_component->err, "[error] %s in %s:%d\n",
+                               __func__, __FILE__, __LINE__);
+               goto error;
+       }
+
+       writer_stream = get_writer_stream(writer_component, packet, stream);
+       if (!writer_stream) {
+               fprintf(writer_component->err, "[error] %s in %s:%d\n",
+                               __func__, __FILE__, __LINE__);
+               goto error;
+       }
+       BT_PUT(stream);
+
+       writer_packet_context = ctf_copy_packet_context(writer_component->err,
+                       packet, writer_stream);
+       if (!writer_packet_context) {
+               fprintf(writer_component->err, "[error] %s in %s:%d\n",
+                               __func__, __FILE__, __LINE__);
+               goto error;
+       }
+
+       int_ret = bt_ctf_stream_set_packet_context(writer_stream,
+                       writer_packet_context);
+       if (int_ret < 0) {
+               fprintf(writer_component->err, "[error] %s in %s:%d\n", __func__,
+                               __FILE__, __LINE__);
+               goto error;
+       }
+       BT_PUT(writer_stream);
+       BT_PUT(writer_packet_context);
+
+       goto end;
+
+error:
+       ret = BT_COMPONENT_STATUS_ERROR;
+end:
+       bt_put(writer_stream);
+       bt_put(writer_packet_context);
+       bt_put(stream);
+       return ret;
+}
+
+BT_HIDDEN
+enum bt_component_status writer_close_packet(
+               struct writer_component *writer_component,
+               struct bt_ctf_packet *packet)
+{
+       struct bt_ctf_stream *stream = NULL, *writer_stream = NULL;
+       enum bt_component_status ret;
+
+       stream = bt_ctf_packet_get_stream(packet);
+       if (!stream) {
+               fprintf(writer_component->err, "[error] %s in %s:%d\n",
+                               __func__, __FILE__, __LINE__);
+               goto error;
+       }
+
+       writer_stream = lookup_stream(writer_component, stream);
+       if (!writer_stream) {
+               fprintf(writer_component->err, "[error] %s in %s:%d\n",
+                               __func__, __FILE__, __LINE__);
+               goto error;
+       }
+       BT_PUT(stream);
+
+       bt_get(writer_stream);
+
+       ret = bt_ctf_stream_flush(writer_stream);
+       if (ret < 0) {
+               fprintf(writer_component->err,
+                               "[error] Failed to flush packet\n");
+               goto error;
+       }
+       BT_PUT(writer_stream);
+
+       ret = BT_COMPONENT_STATUS_OK;
+       goto end;
+
+error:
+       ret = BT_COMPONENT_STATUS_ERROR;
+end:
+       bt_put(writer_stream);
+       bt_put(stream);
+       return ret;
+}
+
+BT_HIDDEN
+enum bt_component_status writer_output_event(
+               struct writer_component *writer_component,
+               struct bt_ctf_event *event)
+{
+       enum bt_component_status ret;
+       struct bt_ctf_event_class *event_class = NULL, *writer_event_class = NULL;
+       struct bt_ctf_stream *stream = NULL, *writer_stream = NULL;
+       struct bt_ctf_stream_class *stream_class = NULL, *writer_stream_class = NULL;
+       struct bt_ctf_event *writer_event = NULL;
+       const char *event_name;
+       int int_ret;
+
+       event_class = bt_ctf_event_get_class(event);
+       if (!event_class) {
+               fprintf(writer_component->err, "[error] %s in %s:%d\n", __func__,
+                               __FILE__, __LINE__);
+               goto error;
+       }
+
+       event_name = bt_ctf_event_class_get_name(event_class);
+       if (!event_name) {
+               fprintf(writer_component->err, "[error] %s in %s:%d\n", __func__,
+                               __FILE__, __LINE__);
+               goto error;
+       }
+
+       stream = bt_ctf_event_get_stream(event);
+       if (!stream) {
+               fprintf(writer_component->err, "[error] %s in %s:%d\n", __func__,
+                               __FILE__, __LINE__);
+               goto error;
+       }
+
+       writer_stream = lookup_stream(writer_component, stream);
+       if (!writer_stream || !bt_get(writer_stream)) {
+               fprintf(writer_component->err, "[error] %s in %s:%d\n", __func__,
+                               __FILE__, __LINE__);
+               goto error;
+       }
+
+       stream_class = bt_ctf_event_class_get_stream_class(event_class);
+       if (!stream_class) {
+               fprintf(writer_component->err, "[error] %s in %s:%d\n", __func__,
+                               __FILE__, __LINE__);
+               goto error;
+       }
+
+       writer_stream_class = g_hash_table_lookup(
+                       writer_component->stream_class_map,
+                       (gpointer) stream_class);
+       if (!writer_stream_class || !bt_get(writer_stream_class)) {
+               fprintf(writer_component->err, "[error] %s in %s:%d\n", __func__,
+                               __FILE__, __LINE__);
+               goto error;
+       }
+
+       writer_event_class = get_event_class(writer_component,
+                       writer_stream_class, event_class);
+       if (!writer_event_class) {
+               writer_event_class = ctf_copy_event_class(writer_component->err,
+                               event_class);
+               if (!writer_event_class) {
+                       fprintf(writer_component->err, "[error] %s in %s:%d\n",
+                                       __func__, __FILE__, __LINE__);
+                       goto error;
+               }
+               int_ret = bt_ctf_stream_class_add_event_class(
+                               writer_stream_class, writer_event_class);
+               if (int_ret) {
+                       fprintf(writer_component->err, "[error] %s in %s:%d\n",
+                                       __func__, __FILE__, __LINE__);
+                       goto error;
+               }
+       }
+
+       writer_event = ctf_copy_event(writer_component->err, event,
+                       writer_event_class, true);
+       if (!writer_event) {
+               fprintf(writer_component->err, "[error] %s in %s:%d\n", __func__,
+                               __FILE__, __LINE__);
+               fprintf(writer_component->err, "[error] Failed to copy event %s\n",
+                               bt_ctf_event_class_get_name(writer_event_class));
+               goto error;
+       }
+
+       int_ret = bt_ctf_stream_append_event(writer_stream, writer_event);
+       if (int_ret < 0) {
+               fprintf(writer_component->err, "[error] %s in %s:%d\n", __func__,
+                               __FILE__, __LINE__);
+               fprintf(writer_component->err, "[error] Failed to append event %s\n",
+                               bt_ctf_event_class_get_name(writer_event_class));
+               goto error;
+       }
+
+       ret = BT_COMPONENT_STATUS_OK;
+       goto end;
+
+error:
+       ret = BT_COMPONENT_STATUS_ERROR;
+end:
+       bt_put(writer_event);
+       bt_put(writer_event_class);
+       bt_put(writer_stream_class);
+       bt_put(stream_class);
+       bt_put(writer_stream);
+       bt_put(stream);
+       bt_put(event_class);
+       return ret;
+}
diff --git a/plugins/ctf/fs-sink/writer.c b/plugins/ctf/fs-sink/writer.c
new file mode 100644 (file)
index 0000000..211a6a9
--- /dev/null
@@ -0,0 +1,317 @@
+/*
+ * writer.c
+ *
+ * Babeltrace CTF Writer Output Plugin
+ *
+ * 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/ctf-ir/packet.h>
+#include <babeltrace/plugin/plugin-dev.h>
+#include <babeltrace/graph/component.h>
+#include <babeltrace/graph/private-component.h>
+#include <babeltrace/graph/component-sink.h>
+#include <babeltrace/graph/private-component-sink.h>
+#include <babeltrace/graph/private-port.h>
+#include <babeltrace/graph/private-connection.h>
+#include <babeltrace/graph/notification.h>
+#include <babeltrace/graph/notification-iterator.h>
+#include <babeltrace/graph/notification-event.h>
+#include <babeltrace/graph/notification-packet.h>
+#include <plugins-common.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <glib.h>
+#include "writer.h"
+#include <assert.h>
+
+static
+void destroy_writer_component_data(struct writer_component *writer_component)
+{
+       bt_put(writer_component->input_iterator);
+       g_hash_table_destroy(writer_component->stream_map);
+       g_hash_table_destroy(writer_component->stream_class_map);
+       g_hash_table_destroy(writer_component->trace_map);
+       g_string_free(writer_component->base_path, true);
+       g_string_free(writer_component->trace_name_base, true);
+}
+
+BT_HIDDEN
+void writer_component_finalize(struct bt_private_component *component)
+{
+       struct writer_component *writer_component = (struct writer_component *)
+               bt_private_component_get_user_data(component);
+
+       destroy_writer_component_data(writer_component);
+       g_free(writer_component);
+}
+
+static
+void unref_stream_class(struct bt_ctf_stream_class *writer_stream_class)
+{
+       bt_put(writer_stream_class);
+}
+
+static
+void unref_stream(struct bt_ctf_stream_class *writer_stream)
+{
+       bt_put(writer_stream);
+}
+
+static
+void unref_trace(struct bt_ctf_writer *writer)
+{
+       bt_put(writer);
+}
+
+static
+struct writer_component *create_writer_component(void)
+{
+       struct writer_component *writer_component;
+
+       writer_component = g_new0(struct writer_component, 1);
+       if (!writer_component) {
+               goto end;
+       }
+
+       writer_component->err = stderr;
+       writer_component->trace_id = 0;
+       writer_component->trace_name_base = g_string_new("trace");
+       writer_component->processed_first_event = false;
+       if (!writer_component->trace_name_base) {
+               g_free(writer_component);
+               writer_component = NULL;
+               goto end;
+       }
+
+       /*
+        * Reader to writer corresponding structures.
+        */
+       writer_component->trace_map = g_hash_table_new_full(g_direct_hash,
+                       g_direct_equal, NULL, (GDestroyNotify) unref_trace);
+       writer_component->stream_class_map = g_hash_table_new_full(g_direct_hash,
+                       g_direct_equal, NULL, (GDestroyNotify) unref_stream_class);
+       writer_component->stream_map = g_hash_table_new_full(g_direct_hash,
+                       g_direct_equal, NULL, (GDestroyNotify) unref_stream);
+
+end:
+       return writer_component;
+}
+
+static
+enum bt_component_status handle_notification(
+               struct writer_component *writer_component,
+               struct bt_notification *notification)
+{
+       enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
+
+       if (!writer_component) {
+               ret = BT_COMPONENT_STATUS_ERROR;
+               goto end;
+       }
+
+       switch (bt_notification_get_type(notification)) {
+       case BT_NOTIFICATION_TYPE_PACKET_BEGIN:
+       {
+               struct bt_ctf_packet *packet =
+                       bt_notification_packet_begin_get_packet(notification);
+
+               if (!packet) {
+                       ret = BT_COMPONENT_STATUS_ERROR;
+                       goto end;
+               }
+
+               ret = writer_new_packet(writer_component, packet);
+               bt_put(packet);
+               break;
+       }
+       case BT_NOTIFICATION_TYPE_PACKET_END:
+       {
+               struct bt_ctf_packet *packet =
+                       bt_notification_packet_end_get_packet(notification);
+
+               if (!packet) {
+                       ret = BT_COMPONENT_STATUS_ERROR;
+                       goto end;
+               }
+               ret = writer_close_packet(writer_component, packet);
+               bt_put(packet);
+               break;
+       }
+       case BT_NOTIFICATION_TYPE_EVENT:
+       {
+               struct bt_ctf_event *event = bt_notification_event_get_event(
+                               notification);
+
+               if (!event) {
+                       ret = BT_COMPONENT_STATUS_ERROR;
+                       goto end;
+               }
+               ret = BT_COMPONENT_STATUS_OK;
+               ret = writer_output_event(writer_component, event);
+               bt_put(event);
+               if (ret != BT_COMPONENT_STATUS_OK) {
+                       goto end;
+               }
+               break;
+       }
+       case BT_NOTIFICATION_TYPE_STREAM_END:
+               break;
+       default:
+               puts("Unhandled notification type");
+       }
+end:
+       return ret;
+}
+
+BT_HIDDEN
+void writer_component_port_connected(
+               struct bt_private_component *component,
+               struct bt_private_port *self_port,
+               struct bt_port *other_port)
+{
+       struct bt_private_connection *connection;
+       struct writer_component *writer;
+
+       writer = bt_private_component_get_user_data(component);
+       assert(writer);
+       assert(!writer->input_iterator);
+       connection = bt_private_port_get_private_connection(self_port);
+       assert(connection);
+       writer->input_iterator =
+               bt_private_connection_create_notification_iterator(connection,
+                       NULL);
+
+       if (!writer->input_iterator) {
+               writer->error = true;
+       }
+
+       bt_put(connection);
+}
+
+BT_HIDDEN
+enum bt_component_status writer_run(struct bt_private_component *component)
+{
+       enum bt_component_status ret;
+       struct bt_notification *notification = NULL;
+       struct bt_notification_iterator *it;
+       struct writer_component *writer_component =
+               bt_private_component_get_user_data(component);
+
+       it = writer_component->input_iterator;
+       assert(it);
+
+       if (unlikely(writer_component->error)) {
+               ret = BT_COMPONENT_STATUS_ERROR;
+               goto end;
+       }
+
+       if (likely(writer_component->processed_first_event)) {
+               enum bt_notification_iterator_status it_ret;
+
+               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(writer_component->input_iterator);
+                               goto end;
+                       default:
+                               break;
+               }
+       }
+
+       notification = bt_notification_iterator_get_notification(it);
+       if (!notification) {
+               ret = BT_COMPONENT_STATUS_ERROR;
+               goto end;
+       }
+
+       ret = handle_notification(writer_component, notification);
+       writer_component->processed_first_event = true;
+end:
+       bt_put(notification);
+       return ret;
+}
+
+BT_HIDDEN
+enum bt_component_status writer_component_init(
+       struct bt_private_component *component, struct bt_value *params,
+       UNUSED_VAR void *init_method_data)
+{
+       enum bt_component_status ret;
+       enum bt_value_status value_ret;
+       struct writer_component *writer_component = create_writer_component();
+       struct bt_value *value = NULL;
+       const char *path;
+       void *priv_port;
+
+       if (!writer_component) {
+               ret = BT_COMPONENT_STATUS_NOMEM;
+               goto end;
+       }
+
+       priv_port = bt_private_component_sink_add_input_private_port(component,
+               "in", NULL);
+       if (!priv_port) {
+               ret = BT_COMPONENT_STATUS_NOMEM;
+               goto end;
+       }
+
+       bt_put(priv_port);
+
+       value = bt_value_map_get(params, "path");
+       if (!value || bt_value_is_null(value) || !bt_value_is_string(value)) {
+               fprintf(writer_component->err,
+                               "[error] output path parameter required\n");
+               ret = BT_COMPONENT_STATUS_INVALID;
+               goto error;
+       }
+
+       value_ret = bt_value_string_get(value, &path);
+       if (value_ret != BT_VALUE_STATUS_OK) {
+               ret = BT_COMPONENT_STATUS_INVALID;
+               goto error;
+       }
+       bt_put(value);
+
+       writer_component->base_path = g_string_new(path);
+       if (!writer_component) {
+               ret = BT_COMPONENT_STATUS_ERROR;
+               goto error;
+       }
+
+       ret = bt_private_component_set_user_data(component, writer_component);
+       if (ret != BT_COMPONENT_STATUS_OK) {
+               goto error;
+       }
+
+end:
+       return ret;
+error:
+       destroy_writer_component_data(writer_component);
+       g_free(writer_component);
+       return ret;
+}
diff --git a/plugins/ctf/fs-sink/writer.h b/plugins/ctf/fs-sink/writer.h
new file mode 100644 (file)
index 0000000..1765a96
--- /dev/null
@@ -0,0 +1,79 @@
+#ifndef BABELTRACE_PLUGIN_WRITER_H
+#define BABELTRACE_PLUGIN_WRITER_H
+
+/*
+ * BabelTrace - CTF Writer Output 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/graph/component.h>
+#include <babeltrace/ctf-writer/writer.h>
+
+struct writer_component {
+       GString *base_path;
+       GString *trace_name_base;
+       /* For the directory name suffix. */
+       int trace_id;
+       /* Map between struct bt_ctf_trace and struct bt_ctf_writer. */
+       GHashTable *trace_map;
+       /* Map between reader and writer stream. */
+       GHashTable *stream_map;
+       /* Map between reader and writer stream class. */
+       GHashTable *stream_class_map;
+       FILE *err;
+       struct bt_notification_iterator *input_iterator;
+       bool processed_first_event;
+       bool error;
+};
+
+BT_HIDDEN
+enum bt_component_status writer_output_event(struct writer_component *writer,
+               struct bt_ctf_event *event);
+BT_HIDDEN
+enum bt_component_status writer_new_packet(struct writer_component *writer,
+               struct bt_ctf_packet *packet);
+BT_HIDDEN
+enum bt_component_status writer_close_packet(struct writer_component *writer,
+               struct bt_ctf_packet *packet);
+
+BT_HIDDEN
+enum bt_component_status writer_component_init(
+       struct bt_private_component *component, struct bt_value *params,
+       void *init_method_data);
+
+BT_HIDDEN
+enum bt_component_status writer_run(struct bt_private_component *component);
+
+BT_HIDDEN
+void writer_component_port_connected(
+               struct bt_private_component *component,
+               struct bt_private_port *self_port,
+               struct bt_port *other_port);
+
+BT_HIDDEN
+void writer_component_finalize(struct bt_private_component *component);
+
+#endif /* BABELTRACE_PLUGIN_WRITER_H */
diff --git a/plugins/ctf/fs-src/Makefile.am b/plugins/ctf/fs-src/Makefile.am
new file mode 100644 (file)
index 0000000..3c5c8b6
--- /dev/null
@@ -0,0 +1,17 @@
+AM_CFLAGS = $(PACKAGE_CFLAGS) -I$(top_srcdir)/include -I$(top_srcdir)/plugins
+
+noinst_LTLIBRARIES = libbabeltrace-plugin-ctf-fs.la
+
+libbabeltrace_plugin_ctf_fs_la_LIBADD = \
+       $(builddir)/../common/libbabeltrace-plugin-ctf-common.la
+libbabeltrace_plugin_ctf_fs_la_SOURCES = \
+       fs.c \
+       data-stream.c \
+       metadata.c \
+       file.c \
+       data-stream.h \
+       file.h \
+       fs.h \
+       lttng-index.h \
+       metadata.h \
+       print.h
diff --git a/plugins/ctf/fs-src/data-stream.c b/plugins/ctf/fs-src/data-stream.c
new file mode 100644 (file)
index 0000000..38843d7
--- /dev/null
@@ -0,0 +1,480 @@
+/*
+ * Copyright 2016 - Philippe Proulx <pproulx@efficios.com>
+ * Copyright 2016 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ * Copyright 2010-2011 - EfficiOS Inc. and Linux Foundation
+ *
+ * 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 <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <glib.h>
+#include <inttypes.h>
+#include <sys/mman.h>
+#include <babeltrace/ctf-ir/stream.h>
+#include <babeltrace/graph/notification-iterator.h>
+#include <babeltrace/graph/notification-stream.h>
+#include <babeltrace/graph/notification-event.h>
+#include <babeltrace/graph/notification-packet.h>
+#include "file.h"
+#include "metadata.h"
+#include "../common/notif-iter/notif-iter.h"
+#include <assert.h>
+#include "data-stream.h"
+
+#define PRINT_ERR_STREAM       ctf_fs->error_fp
+#define PRINT_PREFIX           "ctf-fs-data-stream"
+#include "print.h"
+
+static inline
+size_t remaining_mmap_bytes(struct ctf_fs_stream *stream)
+{
+       return stream->mmap_valid_len - stream->request_offset;
+}
+
+static
+int stream_munmap(struct ctf_fs_stream *stream)
+{
+       int ret = 0;
+       struct ctf_fs_component *ctf_fs = stream->file->ctf_fs;
+
+       if (munmap(stream->mmap_addr, stream->mmap_len)) {
+               PERR("Cannot memory-unmap address %p (size %zu) of file \"%s\" (%p): %s\n",
+                       stream->mmap_addr, stream->mmap_len,
+                       stream->file->path->str, stream->file->fp,
+                       strerror(errno));
+               ret = -1;
+               goto end;
+       }
+end:
+       return ret;
+}
+
+static
+enum bt_ctf_notif_iter_medium_status mmap_next(struct ctf_fs_stream *stream)
+{
+       enum bt_ctf_notif_iter_medium_status ret =
+                       BT_CTF_NOTIF_ITER_MEDIUM_STATUS_OK;
+       struct ctf_fs_component *ctf_fs = stream->file->ctf_fs;
+
+       /* Unmap old region */
+       if (stream->mmap_addr) {
+               if (stream_munmap(stream)) {
+                       goto error;
+               }
+
+               stream->mmap_offset += stream->mmap_valid_len;
+               stream->request_offset = 0;
+       }
+
+       stream->mmap_valid_len = MIN(stream->file->size - stream->mmap_offset,
+                       stream->mmap_max_len);
+       if (stream->mmap_valid_len == 0) {
+               ret = BT_CTF_NOTIF_ITER_MEDIUM_STATUS_EOF;
+               goto end;
+       }
+       /* Round up to next page, assuming page size being a power of 2. */
+       stream->mmap_len = (stream->mmap_valid_len + ctf_fs->page_size - 1)
+                       & ~(ctf_fs->page_size - 1);
+       /* Map new region */
+       assert(stream->mmap_len);
+       stream->mmap_addr = mmap((void *) 0, stream->mmap_len,
+                       PROT_READ, MAP_PRIVATE, fileno(stream->file->fp),
+                       stream->mmap_offset);
+       if (stream->mmap_addr == MAP_FAILED) {
+               PERR("Cannot memory-map address (size %zu) of file \"%s\" (%p) at offset %zu: %s\n",
+                               stream->mmap_len, stream->file->path->str,
+                               stream->file->fp, stream->mmap_offset,
+                               strerror(errno));
+               goto error;
+       }
+
+       goto end;
+error:
+       stream_munmap(stream);
+       ret = BT_CTF_NOTIF_ITER_MEDIUM_STATUS_ERROR;
+end:
+       return ret;
+}
+
+static
+enum bt_ctf_notif_iter_medium_status medop_request_bytes(
+               size_t request_sz, uint8_t **buffer_addr,
+               size_t *buffer_sz, void *data)
+{
+       enum bt_ctf_notif_iter_medium_status status =
+               BT_CTF_NOTIF_ITER_MEDIUM_STATUS_OK;
+       struct ctf_fs_stream *stream = data;
+       struct ctf_fs_component *ctf_fs = stream->file->ctf_fs;
+
+       if (request_sz == 0) {
+               goto end;
+       }
+
+       /* Check if we have at least one memory-mapped byte left */
+       if (remaining_mmap_bytes(stream) == 0) {
+               /* Are we at the end of the file? */
+               if (stream->mmap_offset >= stream->file->size) {
+                       PDBG("Reached end of file \"%s\" (%p)\n",
+                               stream->file->path->str, stream->file->fp);
+                       status = BT_CTF_NOTIF_ITER_MEDIUM_STATUS_EOF;
+                       goto end;
+               }
+
+               status = mmap_next(stream);
+               switch (status) {
+               case BT_CTF_NOTIF_ITER_MEDIUM_STATUS_OK:
+                       break;
+               case BT_CTF_NOTIF_ITER_MEDIUM_STATUS_EOF:
+                       goto end;
+               default:
+                       PERR("Cannot memory-map next region of file \"%s\" (%p)\n",
+                                       stream->file->path->str,
+                                       stream->file->fp);
+                       goto error;
+               }
+       }
+
+       *buffer_sz = MIN(remaining_mmap_bytes(stream), request_sz);
+       *buffer_addr = ((uint8_t *) stream->mmap_addr) + stream->request_offset;
+       stream->request_offset += *buffer_sz;
+       goto end;
+
+error:
+       status = BT_CTF_NOTIF_ITER_MEDIUM_STATUS_ERROR;
+
+end:
+       return status;
+}
+
+static
+struct bt_ctf_stream *medop_get_stream(
+               struct bt_ctf_stream_class *stream_class, void *data)
+{
+       struct ctf_fs_stream *fs_stream = data;
+       struct ctf_fs_component *ctf_fs = fs_stream->file->ctf_fs;
+
+       if (!fs_stream->stream) {
+               int64_t id = bt_ctf_stream_class_get_id(stream_class);
+
+               PDBG("Creating stream out of stream class %" PRId64 "\n", id);
+               fs_stream->stream = bt_ctf_stream_create(stream_class,
+                               fs_stream->file->path->str);
+               if (!fs_stream->stream) {
+                       PERR("Cannot create stream (stream class %" PRId64 ")\n",
+                                       id);
+               }
+       }
+
+       return fs_stream->stream;
+}
+
+static struct bt_ctf_notif_iter_medium_ops medops = {
+       .request_bytes = medop_request_bytes,
+       .get_stream = medop_get_stream,
+};
+
+static
+int build_index_from_idx_file(struct ctf_fs_stream *stream)
+{
+       int ret = 0;
+       gchar *directory = NULL;
+       gchar *basename = NULL;
+       GString *index_basename = NULL;
+       gchar *index_file_path = NULL;
+       GMappedFile *mapped_file = NULL;
+       gsize filesize;
+       const struct ctf_packet_index_file_hdr *header;
+       const char *mmap_begin, *file_pos;
+       struct index_entry *index;
+       uint64_t total_packets_size = 0;
+       size_t file_index_entry_size;
+       size_t file_entry_count;
+       size_t i;
+
+       /* Look for index file in relative path index/name.idx. */
+       basename = g_path_get_basename(stream->file->path->str);
+       if (!basename) {
+               ret = -1;
+               goto end;
+       }
+
+       directory = g_path_get_dirname(stream->file->path->str);
+       if (!directory) {
+               ret = -1;
+               goto end;
+       }
+
+       index_basename = g_string_new(basename);
+       if (!index_basename) {
+               ret = -1;
+               goto end;
+       }
+
+       g_string_append(index_basename, ".idx");
+       index_file_path = g_build_filename(directory, "index",
+                       index_basename->str, NULL);
+       mapped_file = g_mapped_file_new(index_file_path, FALSE, NULL);
+       if (!mapped_file) {
+               ret = -1;
+               goto end;
+       }
+       filesize = g_mapped_file_get_length(mapped_file);
+       if (filesize < sizeof(*header)) {
+               printf_error("Invalid LTTng trace index: file size < header size");
+               ret = -1;
+               goto end;
+       }
+
+       mmap_begin = g_mapped_file_get_contents(mapped_file);
+       header = (struct ctf_packet_index_file_hdr *) mmap_begin;
+
+       file_pos = g_mapped_file_get_contents(mapped_file) + sizeof(*header);
+       if (be32toh(header->magic) != CTF_INDEX_MAGIC) {
+               printf_error("Invalid LTTng trace index: \"magic\" validation failed");
+               ret = -1;
+               goto end;
+       }
+
+       file_index_entry_size = be32toh(header->packet_index_len);
+       file_entry_count = (filesize - sizeof(*header)) / file_index_entry_size;
+       if ((filesize - sizeof(*header)) % (file_entry_count * file_index_entry_size)) {
+               printf_error("Invalid index file size; not a multiple of index entry size");
+               ret = -1;
+               goto end;
+       }
+
+       stream->index.entries = g_array_sized_new(FALSE, TRUE,
+                       sizeof(struct index_entry), file_entry_count);
+       if (!stream->index.entries) {
+               ret = -1;
+               goto end;
+       }
+       index = (struct index_entry *) stream->index.entries->data;
+       for (i = 0; i < file_entry_count; i++) {
+               struct ctf_packet_index *file_index =
+                               (struct ctf_packet_index *) file_pos;
+               uint64_t packet_size = be64toh(file_index->packet_size);
+
+               if (packet_size % CHAR_BIT) {
+                       ret = -1;
+                       printf_error("Invalid packet size encountered in index file");
+                       goto invalid_index;
+               }
+
+               /* Convert size in bits to bytes. */
+               packet_size /= CHAR_BIT;
+               index->packet_size = packet_size;
+
+               index->offset = be64toh(file_index->offset);
+               if (i != 0 && index->offset < (index - 1)->offset) {
+                       printf_error("Invalid, non-monotonic, packet offset encountered in index file");
+                       ret = -1;
+                       goto invalid_index;
+               }
+
+               index->timestamp_begin = be64toh(file_index->timestamp_begin);
+               index->timestamp_end = be64toh(file_index->timestamp_end);
+               if (index->timestamp_end < index->timestamp_begin) {
+                       printf_error("Invalid packet time bounds encountered in index file");
+                       ret = -1;
+                       goto invalid_index;
+               }
+
+               total_packets_size += packet_size;
+               file_pos += file_index_entry_size;
+               index++;
+       }
+
+       /* Validate that the index addresses the complete stream. */
+       if (stream->file->size != total_packets_size) {
+               printf_error("Invalid index; indexed size != stream file size");
+               ret = -1;
+               goto invalid_index;
+       }
+end:
+       g_free(directory);
+       g_free(basename);
+       g_free(index_file_path);
+       if (index_basename) {
+               g_string_free(index_basename, TRUE);
+       }
+       if (mapped_file) {
+               g_mapped_file_unref(mapped_file);
+       }
+       return ret;
+invalid_index:
+       g_array_free(stream->index.entries, TRUE);
+       goto end;
+}
+
+static
+int build_index_from_stream(struct ctf_fs_stream *stream)
+{
+       return 0;
+}
+
+static
+int init_stream_index(struct ctf_fs_stream *stream)
+{
+       int ret;
+
+       ret = build_index_from_idx_file(stream);
+       if (!ret) {
+               goto end;
+       }
+
+       ret = build_index_from_stream(stream);
+end:
+       return ret;
+}
+
+BT_HIDDEN
+struct ctf_fs_stream *ctf_fs_stream_create(
+               struct ctf_fs_component *ctf_fs, const char *path)
+{
+       int ret;
+       struct ctf_fs_stream *stream = g_new0(struct ctf_fs_stream, 1);
+
+       if (!stream) {
+               goto error;
+       }
+
+       stream->file = ctf_fs_file_create(ctf_fs);
+       if (!stream->file) {
+               goto error;
+       }
+
+       stream->cc_prio_map = bt_get(ctf_fs->cc_prio_map);
+       g_string_assign(stream->file->path, path);
+       ret = ctf_fs_file_open(ctf_fs, stream->file, "rb");
+       if (ret) {
+               goto error;
+       }
+
+       stream->notif_iter = bt_ctf_notif_iter_create(ctf_fs->metadata->trace,
+                       ctf_fs->page_size, medops, stream,
+                       ctf_fs->error_fp);
+       if (!stream->notif_iter) {
+               goto error;
+       }
+
+       stream->mmap_max_len = ctf_fs->page_size * 2048;
+       ret = init_stream_index(stream);
+       if (ret) {
+               goto error;
+       }
+       goto end;
+error:
+       /* Do not touch "borrowed" file. */
+       ctf_fs_stream_destroy(stream);
+       stream = NULL;
+end:
+       return stream;
+}
+
+BT_HIDDEN
+void ctf_fs_stream_destroy(struct ctf_fs_stream *stream)
+{
+       if (!stream) {
+               return;
+       }
+
+       bt_put(stream->cc_prio_map);
+
+       if (stream->file) {
+               ctf_fs_file_destroy(stream->file);
+       }
+
+       if (stream->stream) {
+               BT_PUT(stream->stream);
+       }
+
+       if (stream->notif_iter) {
+               bt_ctf_notif_iter_destroy(stream->notif_iter);
+       }
+
+       if (stream->index.entries) {
+               g_array_free(stream->index.entries, TRUE);
+       }
+
+       g_free(stream);
+}
+
+BT_HIDDEN
+struct bt_notification_iterator_next_return ctf_fs_stream_next(
+               struct ctf_fs_stream *stream)
+{
+       enum bt_ctf_notif_iter_status notif_iter_status;
+       struct bt_notification_iterator_next_return ret = {
+               .status = BT_NOTIFICATION_ITERATOR_STATUS_ERROR,
+               .notification = NULL,
+       };
+
+       if (stream->end_reached) {
+               notif_iter_status = BT_CTF_NOTIF_ITER_STATUS_EOF;
+               goto translate_status;
+       }
+
+       notif_iter_status = bt_ctf_notif_iter_get_next_notification(stream->notif_iter,
+                       stream->cc_prio_map, &ret.notification);
+       if (notif_iter_status != BT_CTF_NOTIF_ITER_STATUS_OK &&
+                       notif_iter_status != BT_CTF_NOTIF_ITER_STATUS_EOF) {
+               goto translate_status;
+       }
+
+       /* Should be handled in bt_ctf_notif_iter_get_next_notification. */
+       if (notif_iter_status == BT_CTF_NOTIF_ITER_STATUS_EOF) {
+               ret.notification = bt_notification_stream_end_create(
+                       stream->stream);
+               if (!ret.notification) {
+                       notif_iter_status = BT_CTF_NOTIF_ITER_STATUS_ERROR;
+                       goto translate_status;
+               }
+
+               notif_iter_status = BT_CTF_NOTIF_ITER_STATUS_OK;
+               stream->end_reached = true;
+       }
+
+translate_status:
+       switch (notif_iter_status) {
+       case BT_CTF_NOTIF_ITER_STATUS_EOF:
+               ret.status = BT_NOTIFICATION_ITERATOR_STATUS_END;
+               break;
+       case BT_CTF_NOTIF_ITER_STATUS_OK:
+               ret.status = BT_NOTIFICATION_ITERATOR_STATUS_OK;
+               break;
+       case BT_CTF_NOTIF_ITER_STATUS_AGAIN:
+               /*
+                * Should not make it this far as this is
+                * medium-specific; there is nothing for the user to do
+                * and it should have been handled upstream.
+                */
+               assert(false);
+       case BT_CTF_NOTIF_ITER_STATUS_INVAL:
+       case BT_CTF_NOTIF_ITER_STATUS_ERROR:
+       default:
+               ret.status = BT_NOTIFICATION_ITERATOR_STATUS_ERROR;
+               break;
+       }
+
+       return ret;
+}
diff --git a/plugins/ctf/fs-src/data-stream.h b/plugins/ctf/fs-src/data-stream.h
new file mode 100644 (file)
index 0000000..3d48442
--- /dev/null
@@ -0,0 +1,63 @@
+#ifndef CTF_FS_DATA_STREAM_H
+#define CTF_FS_DATA_STREAM_H
+
+/*
+ * Copyright 2016 - 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 <stdio.h>
+#include <glib.h>
+#include <babeltrace/babeltrace-internal.h>
+#include <babeltrace/ctf-ir/trace.h>
+
+#include "../common/notif-iter/notif-iter.h"
+#include "lttng-index.h"
+
+struct ctf_fs_component;
+struct ctf_fs_file;
+struct ctf_fs_stream;
+
+struct index_entry {
+       uint64_t offset; /* in bytes. */
+       uint64_t packet_size; /* in bytes. */
+       /* relative to the packet context field's mapped clock. */
+       uint64_t timestamp_begin, timestamp_end;
+};
+
+struct index {
+       GArray *entries; /* Array of struct index_entry. */
+};
+
+BT_HIDDEN
+struct ctf_fs_stream *ctf_fs_stream_create(
+               struct ctf_fs_component *ctf_fs, const char *path);
+
+BT_HIDDEN
+void ctf_fs_stream_destroy(struct ctf_fs_stream *stream);
+
+BT_HIDDEN
+int ctf_fs_data_stream_open_streams(struct ctf_fs_component *ctf_fs);
+
+BT_HIDDEN
+struct bt_notification_iterator_next_return ctf_fs_stream_next(
+               struct ctf_fs_stream *stream);
+
+#endif /* CTF_FS_DATA_STREAM_H */
diff --git a/plugins/ctf/fs-src/file.c b/plugins/ctf/fs-src/file.c
new file mode 100644 (file)
index 0000000..8b75649
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2016 - 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 <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <glib.h>
+
+#define PRINT_ERR_STREAM       ctf_fs->error_fp
+#define PRINT_PREFIX           "ctf-fs-file"
+#include "print.h"
+
+#include "file.h"
+
+BT_HIDDEN
+void ctf_fs_file_destroy(struct ctf_fs_file *file)
+{
+       struct ctf_fs_component *ctf_fs;;
+
+       if (!file) {
+               return;
+       }
+
+       ctf_fs = file->ctf_fs;
+
+       if (file->fp) {
+               PDBG("Closing file \"%s\" (%p)\n", file->path->str, file->fp);
+
+               if (fclose(file->fp)) {
+                       PERR("Cannot close file \"%s\": %s\n", file->path->str,
+                               strerror(errno));
+               }
+       }
+
+       if (file->path) {
+               g_string_free(file->path, TRUE);
+       }
+
+       g_free(file);
+}
+
+BT_HIDDEN
+struct ctf_fs_file *ctf_fs_file_create(struct ctf_fs_component *ctf_fs)
+{
+       struct ctf_fs_file *file = g_new0(struct ctf_fs_file, 1);
+
+       if (!file) {
+               goto error;
+       }
+
+       file->ctf_fs = ctf_fs;
+       file->path = g_string_new(NULL);
+       if (!file->path) {
+               goto error;
+       }
+
+       goto end;
+
+error:
+       ctf_fs_file_destroy(file);
+       file = NULL;
+
+end:
+       return file;
+}
+
+BT_HIDDEN
+int ctf_fs_file_open(struct ctf_fs_component *ctf_fs, struct ctf_fs_file *file,
+               const char *mode)
+{
+       int ret = 0;
+       struct stat stat;
+
+       PDBG("Opening file \"%s\" with mode \"%s\"\n", file->path->str, mode);
+       file->fp = fopen(file->path->str, mode);
+       if (!file->fp) {
+               PERR("Cannot open file \"%s\" with mode \"%s\": %s\n",
+                       file->path->str, mode, strerror(errno));
+               goto error;
+       }
+
+       PDBG("Opened file: %p\n", file->fp);
+
+       if (fstat(fileno(file->fp), &stat)) {
+               PERR("Cannot get file informations: %s\n", strerror(errno));
+               goto error;
+       }
+
+       file->size = stat.st_size;
+       PDBG("  File is %zu bytes\n", file->size);
+       goto end;
+
+error:
+       ret = -1;
+
+       if (file->fp) {
+               if (fclose(file->fp)) {
+                       PERR("Cannot close file \"%s\": %s\n", file->path->str,
+                               strerror(errno));
+               }
+       }
+
+end:
+       return ret;
+}
diff --git a/plugins/ctf/fs-src/file.h b/plugins/ctf/fs-src/file.h
new file mode 100644 (file)
index 0000000..59f3d0e
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef CTF_FS_FILE_H
+#define CTF_FS_FILE_H
+
+/*
+ * Copyright 2016 - 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 <stdio.h>
+#include <glib.h>
+#include <babeltrace/babeltrace-internal.h>
+#include "fs.h"
+
+BT_HIDDEN
+void ctf_fs_file_destroy(struct ctf_fs_file *file);
+
+BT_HIDDEN
+struct ctf_fs_file *ctf_fs_file_create(struct ctf_fs_component *ctf_fs);
+
+BT_HIDDEN
+int ctf_fs_file_open(struct ctf_fs_component *ctf_fs, struct ctf_fs_file *file,
+               const char *mode);
+
+#endif /* CTF_FS_FILE_H */
diff --git a/plugins/ctf/fs-src/fs.c b/plugins/ctf/fs-src/fs.c
new file mode 100644 (file)
index 0000000..2abd9b5
--- /dev/null
@@ -0,0 +1,620 @@
+/*
+ * fs.c
+ *
+ * Babeltrace CTF file system Reader Component
+ *
+ * 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/ctf-ir/packet.h>
+#include <babeltrace/ctf-ir/clock-class.h>
+#include <babeltrace/graph/private-port.h>
+#include <babeltrace/graph/private-component.h>
+#include <babeltrace/graph/private-component-source.h>
+#include <babeltrace/graph/private-notification-iterator.h>
+#include <babeltrace/graph/component.h>
+#include <babeltrace/graph/notification-iterator.h>
+#include <babeltrace/graph/clock-class-priority-map.h>
+#include <plugins-common.h>
+#include <glib.h>
+#include <assert.h>
+#include <unistd.h>
+#include "fs.h"
+#include "metadata.h"
+#include "data-stream.h"
+#include "file.h"
+#include "../common/metadata/decoder.h"
+
+#define PRINT_ERR_STREAM       ctf_fs->error_fp
+#define PRINT_PREFIX           "ctf-fs"
+#include "print.h"
+#define METADATA_TEXT_SIG      "/* CTF 1.8"
+
+BT_HIDDEN
+bool ctf_fs_debug;
+
+struct bt_notification_iterator_next_return ctf_fs_iterator_next(
+               struct bt_private_notification_iterator *iterator)
+{
+       struct ctf_fs_stream *fs_stream =
+               bt_private_notification_iterator_get_user_data(iterator);
+
+       return ctf_fs_stream_next(fs_stream);
+}
+
+void ctf_fs_iterator_finalize(struct bt_private_notification_iterator *it)
+{
+       void *ctf_fs_stream =
+               bt_private_notification_iterator_get_user_data(it);
+
+       ctf_fs_stream_destroy(ctf_fs_stream);
+}
+
+enum bt_notification_iterator_status ctf_fs_iterator_init(
+               struct bt_private_notification_iterator *it,
+               struct bt_private_port *port)
+{
+       struct ctf_fs_stream *stream = NULL;
+       struct ctf_fs_component *ctf_fs;
+       struct ctf_fs_port_data *port_data;
+       struct bt_private_component *priv_comp =
+               bt_private_notification_iterator_get_private_component(it);
+       enum bt_notification_iterator_status ret =
+               BT_NOTIFICATION_ITERATOR_STATUS_OK;
+
+       assert(priv_comp);
+
+       ctf_fs = bt_private_component_get_user_data(priv_comp);
+       if (!ctf_fs) {
+               ret = BT_NOTIFICATION_ITERATOR_STATUS_INVALID;
+               goto error;
+       }
+
+       port_data = bt_private_port_get_user_data(port);
+       if (!port_data) {
+               ret = BT_NOTIFICATION_ITERATOR_STATUS_INVALID;
+               goto error;
+       }
+
+       stream = ctf_fs_stream_create(ctf_fs, port_data->path->str);
+       if (!stream) {
+               goto error;
+       }
+
+       ret = bt_private_notification_iterator_set_user_data(it, stream);
+       if (ret) {
+               goto error;
+       }
+
+       stream = NULL;
+       goto end;
+
+error:
+       (void) bt_private_notification_iterator_set_user_data(it, NULL);
+
+       if (ret == BT_NOTIFICATION_ITERATOR_STATUS_OK) {
+               ret = BT_NOTIFICATION_ITERATOR_STATUS_ERROR;
+       }
+
+end:
+       ctf_fs_stream_destroy(stream);
+       bt_put(priv_comp);
+       return ret;
+}
+
+static
+void ctf_fs_destroy_data(struct ctf_fs_component *ctf_fs)
+{
+       if (!ctf_fs) {
+               return;
+       }
+
+       if (ctf_fs->trace_path) {
+               g_string_free(ctf_fs->trace_path, TRUE);
+       }
+
+       if (ctf_fs->port_data) {
+               g_ptr_array_free(ctf_fs->port_data, TRUE);
+       }
+
+       if (ctf_fs->metadata) {
+               ctf_fs_metadata_fini(ctf_fs->metadata);
+               g_free(ctf_fs->metadata);
+       }
+
+       bt_put(ctf_fs->cc_prio_map);
+       g_free(ctf_fs);
+}
+
+void ctf_fs_finalize(struct bt_private_component *component)
+{
+       void *data = bt_private_component_get_user_data(component);
+
+       ctf_fs_destroy_data(data);
+}
+
+static
+void port_data_destroy(void *data) {
+       struct ctf_fs_port_data *port_data = data;
+
+       if (!port_data) {
+               return;
+       }
+
+       if (port_data->path) {
+               g_string_free(port_data->path, TRUE);
+       }
+
+       g_free(port_data);
+}
+
+static
+int create_one_port(struct ctf_fs_component *ctf_fs,
+               const char *stream_basename, const char *stream_path)
+{
+       int ret = 0;
+       struct bt_private_port *port = NULL;
+       struct ctf_fs_port_data *port_data = NULL;
+       GString *port_name = NULL;
+
+       port_name = g_string_new(NULL);
+       if (!port_name) {
+               goto error;
+       }
+
+       /* Assign the name for the new output port */
+       g_string_assign(port_name, "");
+       g_string_printf(port_name, "trace0-stream-%s", stream_basename);
+       PDBG("Creating one port named `%s` associated with path `%s`\n",
+               port_name->str, stream_path);
+
+       /* Create output port for this file */
+       port_data = g_new0(struct ctf_fs_port_data, 1);
+       if (!port_data) {
+               goto error;
+       }
+
+       port_data->path = g_string_new(stream_path);
+       if (!port_data->path) {
+               goto error;
+       }
+
+       port = bt_private_component_source_add_output_private_port(
+               ctf_fs->priv_comp, port_name->str, port_data);
+       if (!port) {
+               goto error;
+       }
+
+       g_ptr_array_add(ctf_fs->port_data, port_data);
+       port_data = NULL;
+       goto end;
+
+error:
+       ret = -1;
+
+end:
+       if (port_name) {
+               g_string_free(port_name, TRUE);
+       }
+
+       bt_put(port);
+       port_data_destroy(port_data);
+       return ret;
+}
+
+static
+int create_ports(struct ctf_fs_component *ctf_fs)
+{
+       int ret = 0;
+       const char *basename;
+       GError *error = NULL;
+       GDir *dir = NULL;
+       struct ctf_fs_file *file = NULL;
+
+       /* Create one output port for each stream file */
+       dir = g_dir_open(ctf_fs->trace_path->str, 0, &error);
+       if (!dir) {
+               PERR("Cannot open directory `%s`: %s (code %d)\n",
+                       ctf_fs->trace_path->str, error->message,
+                       error->code);
+               goto error;
+       }
+
+       while ((basename = g_dir_read_name(dir))) {
+               if (!strcmp(basename, CTF_FS_METADATA_FILENAME)) {
+                       /* Ignore the metadata stream. */
+                       PDBG("Ignoring metadata file `%s`\n", basename);
+                       continue;
+               }
+
+               if (basename[0] == '.') {
+                       PDBG("Ignoring hidden file `%s`\n", basename);
+                       continue;
+               }
+
+               /* Create the file. */
+               file = ctf_fs_file_create(ctf_fs);
+               if (!file) {
+                       PERR("Cannot create stream file object for file `%s`\n",
+                               basename);
+                       goto error;
+               }
+
+               /* Create full path string. */
+               g_string_append_printf(file->path, "%s/%s",
+                               ctf_fs->trace_path->str, basename);
+               if (!g_file_test(file->path->str, G_FILE_TEST_IS_REGULAR)) {
+                       PDBG("Ignoring non-regular file `%s`\n", basename);
+                       ctf_fs_file_destroy(file);
+                       file = NULL;
+                       continue;
+               }
+
+               ret = ctf_fs_file_open(ctf_fs, file, "rb");
+               if (ret) {
+                       PERR("Cannot open stream file `%s`\n", basename);
+                       goto error;
+               }
+
+               if (file->size == 0) {
+                       /* Skip empty stream. */
+                       PDBG("Ignoring empty file `%s`\n", basename);
+                       ctf_fs_file_destroy(file);
+                       file = NULL;
+                       continue;
+               }
+
+               ret = create_one_port(ctf_fs, basename, file->path->str);
+               if (ret) {
+                       PERR("Cannot create output port for file `%s`\n",
+                               basename);
+                       goto error;
+               }
+
+               ctf_fs_file_destroy(file);
+               file = NULL;
+       }
+
+       goto end;
+
+error:
+       ret = -1;
+
+end:
+       if (dir) {
+               g_dir_close(dir);
+               dir = NULL;
+       }
+
+       if (error) {
+               g_error_free(error);
+       }
+
+       ctf_fs_file_destroy(file);
+       return ret;
+}
+
+static
+int create_cc_prio_map(struct ctf_fs_component *ctf_fs)
+{
+       int ret = 0;
+       size_t i;
+       int count;
+
+       assert(ctf_fs);
+       ctf_fs->cc_prio_map = bt_clock_class_priority_map_create();
+       if (!ctf_fs->cc_prio_map) {
+               ret = -1;
+               goto end;
+       }
+
+       count = bt_ctf_trace_get_clock_class_count(ctf_fs->metadata->trace);
+       assert(count >= 0);
+
+       for (i = 0; i < count; i++) {
+               struct bt_ctf_clock_class *clock_class =
+                       bt_ctf_trace_get_clock_class_by_index(
+                               ctf_fs->metadata->trace, i);
+
+               assert(clock_class);
+               ret = bt_clock_class_priority_map_add_clock_class(
+                       ctf_fs->cc_prio_map, clock_class, 0);
+               BT_PUT(clock_class);
+
+               if (ret) {
+                       goto end;
+               }
+       }
+
+end:
+       return ret;
+}
+
+static
+struct ctf_fs_component *ctf_fs_create(struct bt_private_component *priv_comp,
+               struct bt_value *params)
+{
+       struct ctf_fs_component *ctf_fs;
+       struct bt_value *value = NULL;
+       const char *path;
+       int ret;
+
+       ctf_fs = g_new0(struct ctf_fs_component, 1);
+       if (!ctf_fs) {
+               goto end;
+       }
+
+       /*
+        * We don't need to get a new reference here because as long as
+        * our private ctf_fs_component object exists, the containing
+        * private component should also exist.
+        */
+       ctf_fs->priv_comp = priv_comp;
+
+       /* FIXME: should probably look for a source URI */
+       value = bt_value_map_get(params, "path");
+       if (!value || bt_value_is_null(value) || !bt_value_is_string(value)) {
+               goto error;
+       }
+
+       ret = bt_value_string_get(value, &path);
+       if (ret) {
+               goto error;
+       }
+
+       ctf_fs->port_data = g_ptr_array_new_with_free_func(port_data_destroy);
+       if (!ctf_fs->port_data) {
+               goto error;
+       }
+
+       ctf_fs->trace_path = g_string_new(path);
+       if (!ctf_fs->trace_path) {
+               BT_PUT(value);
+               goto error;
+       }
+       bt_put(value);
+
+       value = bt_value_map_get(params, "offset-s");
+       if (value) {
+               int64_t offset;
+
+               if (!bt_value_is_integer(value)) {
+                       fprintf(stderr,
+                               "offset-s should be an integer\n");
+                       goto error;
+               }
+               ret = bt_value_integer_get(value, &offset);
+               if (ret != BT_VALUE_STATUS_OK) {
+                       fprintf(stderr,
+                               "Failed to get offset-s value\n");
+                       goto error;
+               }
+               ctf_fs->options.clock_offset = offset;
+               bt_put(value);
+       }
+
+       value = bt_value_map_get(params, "offset-ns");
+       if (value) {
+               int64_t offset;
+
+               if (!bt_value_is_integer(value)) {
+                       fprintf(stderr,
+                               "offset-ns should be an integer\n");
+                       goto error;
+               }
+               ret = bt_value_integer_get(value, &offset);
+               if (ret != BT_VALUE_STATUS_OK) {
+                       fprintf(stderr,
+                               "Failed to get offset-ns value\n");
+                       goto error;
+               }
+               ctf_fs->options.clock_offset_ns = offset;
+               bt_put(value);
+       }
+
+       ctf_fs->error_fp = stderr;
+       ctf_fs->page_size = (size_t) getpagesize();
+
+       // FIXME: check error.
+       ctf_fs->metadata = g_new0(struct ctf_fs_metadata, 1);
+       if (!ctf_fs->metadata) {
+               goto error;
+       }
+
+       ret = ctf_fs_metadata_set_trace(ctf_fs);
+       if (ret) {
+               goto error;
+       }
+
+       ret = create_cc_prio_map(ctf_fs);
+       if (ret) {
+               goto error;
+       }
+
+       ret = create_ports(ctf_fs);
+       if (ret) {
+               goto error;
+       }
+
+       goto end;
+
+error:
+       ctf_fs_destroy_data(ctf_fs);
+       ctf_fs = NULL;
+end:
+       return ctf_fs;
+}
+
+BT_HIDDEN
+enum bt_component_status ctf_fs_init(struct bt_private_component *priv_comp,
+               struct bt_value *params, UNUSED_VAR void *init_method_data)
+{
+       struct ctf_fs_component *ctf_fs;
+       enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
+
+       assert(priv_comp);
+       ctf_fs_debug = g_strcmp0(getenv("CTF_FS_DEBUG"), "1") == 0;
+       ctf_fs = ctf_fs_create(priv_comp, params);
+       if (!ctf_fs) {
+               ret = BT_COMPONENT_STATUS_NOMEM;
+               goto end;
+       }
+
+       ret = bt_private_component_set_user_data(priv_comp, ctf_fs);
+       if (ret != BT_COMPONENT_STATUS_OK) {
+               goto error;
+       }
+end:
+       return ret;
+error:
+       (void) bt_private_component_set_user_data(priv_comp, NULL);
+        ctf_fs_destroy_data(ctf_fs);
+       return ret;
+}
+
+BT_HIDDEN
+struct bt_value *ctf_fs_query(struct bt_component_class *comp_class,
+               const char *object, struct bt_value *params)
+{
+       struct bt_value *results = NULL;
+       struct bt_value *path_value = NULL;
+       char *metadata_text = NULL;
+       FILE *metadata_fp = NULL;
+       GString *g_metadata_text = NULL;
+
+       if (strcmp(object, "metadata-info") == 0) {
+               int ret;
+               int bo;
+               const char *path;
+               bool is_packetized;
+
+               results = bt_value_map_create();
+               if (!results) {
+                       goto error;
+               }
+
+               if (!bt_value_is_map(params)) {
+                       fprintf(stderr,
+                               "Query parameters is not a map value object\n");
+                       goto error;
+               }
+
+               path_value = bt_value_map_get(params, "path");
+               ret = bt_value_string_get(path_value, &path);
+               if (ret) {
+                       fprintf(stderr,
+                               "Cannot get `path` string parameter\n");
+                       goto error;
+               }
+
+               assert(path);
+               metadata_fp = ctf_fs_metadata_open_file(path);
+               if (!metadata_fp) {
+                       fprintf(stderr,
+                               "Cannot open trace at path `%s`\n", path);
+                       goto error;
+               }
+
+               is_packetized = ctf_metadata_decoder_is_packetized(metadata_fp,
+                       &bo);
+
+               if (is_packetized) {
+                       ret = ctf_metadata_decoder_packetized_file_stream_to_buf(
+                               metadata_fp, &metadata_text, bo);
+                       if (ret) {
+                               fprintf(stderr,
+                                       "Cannot decode packetized metadata file\n");
+                               goto error;
+                       }
+               } else {
+                       long filesize;
+
+                       fseek(metadata_fp, 0, SEEK_END);
+                       filesize = ftell(metadata_fp);
+                       rewind(metadata_fp);
+                       metadata_text = malloc(filesize + 1);
+                       if (!metadata_text) {
+                               fprintf(stderr,
+                                       "Cannot allocate buffer for metadata text\n");
+                               goto error;
+                       }
+
+                       if (fread(metadata_text, filesize, 1, metadata_fp) !=
+                                       1) {
+                               fprintf(stderr,
+                                       "Cannot read metadata file\n");
+                               goto error;
+                       }
+
+                       metadata_text[filesize] = '\0';
+               }
+
+               g_metadata_text = g_string_new(NULL);
+               if (!g_metadata_text) {
+                       goto error;
+               }
+
+               if (strncmp(metadata_text, METADATA_TEXT_SIG,
+                               sizeof(METADATA_TEXT_SIG) - 1) != 0) {
+                       g_string_assign(g_metadata_text, METADATA_TEXT_SIG);
+                       g_string_append(g_metadata_text, " */\n\n");
+               }
+
+               g_string_append(g_metadata_text, metadata_text);
+
+               ret = bt_value_map_insert_string(results, "text",
+                       g_metadata_text->str);
+               if (ret) {
+                       fprintf(stderr, "Cannot insert metadata text into results\n");
+                       goto error;
+               }
+
+               ret = bt_value_map_insert_bool(results, "is-packetized",
+                       is_packetized);
+               if (ret) {
+                       fprintf(stderr, "Cannot insert is packetized into results\n");
+                       goto error;
+               }
+       } else {
+               fprintf(stderr, "Unknown query object `%s`\n", object);
+               goto error;
+       }
+
+       goto end;
+
+error:
+       BT_PUT(results);
+
+end:
+       bt_put(path_value);
+       free(metadata_text);
+
+       if (g_metadata_text) {
+               g_string_free(g_metadata_text, TRUE);
+       }
+
+       if (metadata_fp) {
+               fclose(metadata_fp);
+       }
+       return results;
+}
diff --git a/plugins/ctf/fs-src/fs.h b/plugins/ctf/fs-src/fs.h
new file mode 100644 (file)
index 0000000..4619e79
--- /dev/null
@@ -0,0 +1,121 @@
+#ifndef BABELTRACE_PLUGIN_CTF_FS_H
+#define BABELTRACE_PLUGIN_CTF_FS_H
+
+/*
+ * BabelTrace - CTF on File System Component
+ *
+ * Copyright 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ * Copyright 2016 Philippe Proulx <pproulx@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/babeltrace-internal.h>
+#include <babeltrace/graph/component.h>
+#include <babeltrace/graph/clock-class-priority-map.h>
+#include "data-stream.h"
+
+BT_HIDDEN
+extern bool ctf_fs_debug;
+
+struct ctf_fs_file {
+       struct ctf_fs_component *ctf_fs;
+       GString *path;
+       FILE *fp;
+       off_t size;
+};
+
+struct ctf_fs_metadata {
+       struct bt_ctf_trace *trace;
+       uint8_t uuid[16];
+       bool is_uuid_set;
+       int bo;
+       char *text;
+};
+
+struct ctf_fs_stream {
+       struct ctf_fs_file *file;
+       struct bt_ctf_stream *stream;
+       struct bt_clock_class_priority_map *cc_prio_map;
+       struct bt_ctf_notif_iter *notif_iter;
+       /* A stream is assumed to be indexed. */
+       struct index index;
+       void *mmap_addr;
+       /* Max length of chunk to mmap() when updating the current mapping. */
+       size_t mmap_max_len;
+       /* Length of the current mapping. */
+       size_t mmap_len;
+       /* Length of the current mapping which *exists* in the backing file. */
+       size_t mmap_valid_len;
+       /* Offset in the file where the current mapping starts. */
+       off_t mmap_offset;
+       /*
+        * Offset, in the current mapping, of the address to return on the next
+        * request.
+        */
+       off_t request_offset;
+       bool end_reached;
+};
+
+struct ctf_fs_component_options {
+       uint64_t clock_offset;
+       uint64_t clock_offset_ns;
+};
+
+struct ctf_fs_port_data {
+       GString *path;
+};
+
+struct ctf_fs_component {
+       struct bt_private_component *priv_comp;
+       GString *trace_path;
+       FILE *error_fp;
+       size_t page_size;
+       struct ctf_fs_component_options options;
+       struct ctf_fs_metadata *metadata;
+       struct bt_clock_class_priority_map *cc_prio_map;
+
+       /* Array of struct ctf_fs_port_data *, owned by this */
+       GPtrArray *port_data;
+};
+
+BT_HIDDEN
+enum bt_component_status ctf_fs_init(struct bt_private_component *source,
+               struct bt_value *params, void *init_method_data);
+
+BT_HIDDEN
+void ctf_fs_finalize(struct bt_private_component *component);
+
+BT_HIDDEN
+enum bt_notification_iterator_status ctf_fs_iterator_init(
+               struct bt_private_notification_iterator *it,
+               struct bt_private_port *port);
+
+void ctf_fs_iterator_finalize(struct bt_private_notification_iterator *it);
+
+struct bt_notification_iterator_next_return ctf_fs_iterator_next(
+               struct bt_private_notification_iterator *iterator);
+
+BT_HIDDEN
+struct bt_value *ctf_fs_query(struct bt_component_class *comp_class,
+               const char *object, struct bt_value *params);
+
+#endif /* BABELTRACE_PLUGIN_CTF_FS_H */
diff --git a/plugins/ctf/fs-src/lttng-index.h b/plugins/ctf/fs-src/lttng-index.h
new file mode 100644 (file)
index 0000000..05629f8
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2013 - Julien Desfossez <jdesfossez@efficios.com>
+ *                      Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *                      David Goulet <dgoulet@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.
+ */
+
+#ifndef LTTNG_INDEX_H
+#define LTTNG_INDEX_H
+
+#include <babeltrace/compat/limits-internal.h>
+
+#define CTF_INDEX_MAGIC 0xC1F1DCC1
+#define CTF_INDEX_MAJOR 1
+#define CTF_INDEX_MINOR 1
+
+/*
+ * Header at the beginning of each index file.
+ * All integer fields are stored in big endian.
+ */
+struct ctf_packet_index_file_hdr {
+       uint32_t magic;
+       uint32_t index_major;
+       uint32_t index_minor;
+       /* size of struct ctf_packet_index, in bytes. */
+       uint32_t packet_index_len;
+} __attribute__((__packed__));
+
+/*
+ * Packet index generated for each trace packet store in a trace file.
+ * All integer fields are stored in big endian.
+ */
+struct ctf_packet_index {
+       uint64_t offset;                /* offset of the packet in the file, in bytes */
+       uint64_t packet_size;           /* packet size, in bits */
+       uint64_t content_size;          /* content size, in bits */
+       uint64_t timestamp_begin;
+       uint64_t timestamp_end;
+       uint64_t events_discarded;
+       uint64_t stream_id;
+       /* CTF_INDEX 1.0 limit */
+       uint64_t stream_instance_id;    /* ID of the channel instance */
+       uint64_t packet_seq_num;        /* packet sequence number */
+} __attribute__((__packed__));
+
+#endif /* LTTNG_INDEX_H */
diff --git a/plugins/ctf/fs-src/metadata.c b/plugins/ctf/fs-src/metadata.c
new file mode 100644 (file)
index 0000000..cd21196
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+ * Copyright 2016 - Philippe Proulx <pproulx@efficios.com>
+ * Copyright 2010-2011 - EfficiOS Inc. and Linux Foundation
+ *
+ * Some functions are based on older functions written by Mathieu Desnoyers.
+ *
+ * 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 <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <assert.h>
+#include <glib.h>
+#include <babeltrace/compat/uuid-internal.h>
+#include <babeltrace/compat/memstream-internal.h>
+
+#define PRINT_ERR_STREAM       ctf_fs->error_fp
+#define PRINT_PREFIX           "ctf-fs-metadata"
+#include "print.h"
+
+#include "fs.h"
+#include "file.h"
+#include "metadata.h"
+#include "../common/metadata/decoder.h"
+
+#define NSEC_PER_SEC 1000000000LL
+
+BT_HIDDEN
+FILE *ctf_fs_metadata_open_file(const char *trace_path)
+{
+       GString *metadata_path = g_string_new(trace_path);
+       FILE *fp = NULL;
+
+       if (!metadata_path) {
+               goto error;
+       }
+
+       g_string_append(metadata_path, "/" CTF_FS_METADATA_FILENAME);
+       fp = fopen(metadata_path->str, "rb");
+       if (!fp) {
+               goto error;
+       }
+
+       goto end;
+
+error:
+       if (fp) {
+               fclose(fp);
+               fp = NULL;
+       }
+
+end:
+       g_string_free(metadata_path, TRUE);
+       return fp;
+}
+
+static struct ctf_fs_file *get_file(struct ctf_fs_component *ctf_fs,
+               const char *trace_path)
+{
+       struct ctf_fs_file *file = ctf_fs_file_create(ctf_fs);
+
+       if (!file) {
+               goto error;
+       }
+
+       g_string_append(file->path, trace_path);
+       g_string_append(file->path, "/" CTF_FS_METADATA_FILENAME);
+
+       if (ctf_fs_file_open(ctf_fs, file, "rb")) {
+               goto error;
+       }
+
+       goto end;
+
+error:
+       if (file) {
+               ctf_fs_file_destroy(file);
+               file = NULL;
+       }
+
+end:
+       return file;
+}
+
+int ctf_fs_metadata_set_trace(struct ctf_fs_component *ctf_fs)
+{
+       int ret = 0;
+       struct ctf_fs_file *file = NULL;
+       struct ctf_metadata_decoder *metadata_decoder = NULL;
+
+       file = get_file(ctf_fs, ctf_fs->trace_path->str);
+       if (!file) {
+               PERR("Cannot create metadata file object\n");
+               goto end;
+       }
+
+       metadata_decoder = ctf_metadata_decoder_create(ctf_fs->error_fp,
+               ctf_fs->options.clock_offset * NSEC_PER_SEC +
+               ctf_fs->options.clock_offset_ns);
+       if (!metadata_decoder) {
+               PERR("Cannot create metadata decoder object\n");
+               goto end;
+       }
+
+       ret = ctf_metadata_decoder_decode(metadata_decoder, file->fp);
+       if (ret) {
+               PERR("Cannot decode metadata file\n");
+               goto end;
+       }
+
+       ctf_fs->metadata->trace = ctf_metadata_decoder_get_trace(
+               metadata_decoder);
+       assert(ctf_fs->metadata->trace);
+
+end:
+       ctf_fs_file_destroy(file);
+       ctf_metadata_decoder_destroy(metadata_decoder);
+       return ret;
+}
+
+int ctf_fs_metadata_init(struct ctf_fs_metadata *metadata)
+{
+       /* Nothing to initialize for the moment. */
+       return 0;
+}
+
+void ctf_fs_metadata_fini(struct ctf_fs_metadata *metadata)
+{
+       if (metadata->text) {
+               free(metadata->text);
+       }
+
+       if (metadata->trace) {
+               BT_PUT(metadata->trace);
+       }
+}
diff --git a/plugins/ctf/fs-src/metadata.h b/plugins/ctf/fs-src/metadata.h
new file mode 100644 (file)
index 0000000..85a7726
--- /dev/null
@@ -0,0 +1,53 @@
+#ifndef CTF_FS_METADATA_H
+#define CTF_FS_METADATA_H
+
+/*
+ * Copyright 2016 - 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 <stdio.h>
+#include <glib.h>
+#include <babeltrace/babeltrace-internal.h>
+#include <babeltrace/ctf-ir/trace.h>
+#include "fs.h"
+
+#define CTF_FS_METADATA_FILENAME       "metadata"
+
+BT_HIDDEN
+int ctf_fs_metadata_init(struct ctf_fs_metadata *metadata);
+
+BT_HIDDEN
+void ctf_fs_metadata_fini(struct ctf_fs_metadata *metadata);
+
+BT_HIDDEN
+int ctf_fs_metadata_set_trace(struct ctf_fs_component *ctf_fs);
+
+BT_HIDDEN
+FILE *ctf_fs_metadata_open_file(const char *trace_path);
+
+BT_HIDDEN
+bool ctf_metadata_is_packetized(FILE *fp, int *byte_order);
+
+BT_HIDDEN
+int ctf_metadata_packetized_file_to_buf(struct ctf_fs_component *ctf_fs,
+               FILE *fp, uint8_t **buf, int byte_order);
+
+#endif /* CTF_FS_METADATA_H */
diff --git a/plugins/ctf/fs-src/print.h b/plugins/ctf/fs-src/print.h
new file mode 100644 (file)
index 0000000..9daf7ea
--- /dev/null
@@ -0,0 +1,57 @@
+#ifndef CTF_FS_PRINT_H
+#define CTF_FS_PRINT_H
+
+/*
+ * Define PRINT_PREFIX and PRINT_ERR_STREAM, then include this file.
+ *
+ * Copyright (c) 2016 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 <stdio.h>
+
+#define PERR(fmt, ...)                                                 \
+       do {                                                            \
+               if (PRINT_ERR_STREAM) {                                 \
+                       fprintf(PRINT_ERR_STREAM,                       \
+                               "Error: " PRINT_PREFIX ": " fmt,        \
+                               ##__VA_ARGS__);                         \
+               }                                                       \
+       } while (0)
+
+#define PWARN(fmt, ...)                                                        \
+       do {                                                            \
+               if (PRINT_ERR_STREAM) {                                 \
+                       fprintf(PRINT_ERR_STREAM,                       \
+                               "Warning: " PRINT_PREFIX ": " fmt,      \
+                               ##__VA_ARGS__);                         \
+               }                                                       \
+       } while (0)
+
+#define PDBG(fmt, ...)                                                 \
+       do {                                                            \
+               if (ctf_fs_debug) {                                     \
+                       fprintf(stderr,                                 \
+                               "Debug: " PRINT_PREFIX ": " fmt,        \
+                               ##__VA_ARGS__);                         \
+               }                                                       \
+       } while (0)
+
+#endif /* CTF_FS_PRINT_H */
diff --git a/plugins/ctf/fs/Makefile.am b/plugins/ctf/fs/Makefile.am
deleted file mode 100644 (file)
index 3c5c8b6..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-AM_CFLAGS = $(PACKAGE_CFLAGS) -I$(top_srcdir)/include -I$(top_srcdir)/plugins
-
-noinst_LTLIBRARIES = libbabeltrace-plugin-ctf-fs.la
-
-libbabeltrace_plugin_ctf_fs_la_LIBADD = \
-       $(builddir)/../common/libbabeltrace-plugin-ctf-common.la
-libbabeltrace_plugin_ctf_fs_la_SOURCES = \
-       fs.c \
-       data-stream.c \
-       metadata.c \
-       file.c \
-       data-stream.h \
-       file.h \
-       fs.h \
-       lttng-index.h \
-       metadata.h \
-       print.h
diff --git a/plugins/ctf/fs/data-stream.c b/plugins/ctf/fs/data-stream.c
deleted file mode 100644 (file)
index 38843d7..0000000
+++ /dev/null
@@ -1,480 +0,0 @@
-/*
- * Copyright 2016 - Philippe Proulx <pproulx@efficios.com>
- * Copyright 2016 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
- * Copyright 2010-2011 - EfficiOS Inc. and Linux Foundation
- *
- * 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 <stdio.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <stdbool.h>
-#include <glib.h>
-#include <inttypes.h>
-#include <sys/mman.h>
-#include <babeltrace/ctf-ir/stream.h>
-#include <babeltrace/graph/notification-iterator.h>
-#include <babeltrace/graph/notification-stream.h>
-#include <babeltrace/graph/notification-event.h>
-#include <babeltrace/graph/notification-packet.h>
-#include "file.h"
-#include "metadata.h"
-#include "../common/notif-iter/notif-iter.h"
-#include <assert.h>
-#include "data-stream.h"
-
-#define PRINT_ERR_STREAM       ctf_fs->error_fp
-#define PRINT_PREFIX           "ctf-fs-data-stream"
-#include "print.h"
-
-static inline
-size_t remaining_mmap_bytes(struct ctf_fs_stream *stream)
-{
-       return stream->mmap_valid_len - stream->request_offset;
-}
-
-static
-int stream_munmap(struct ctf_fs_stream *stream)
-{
-       int ret = 0;
-       struct ctf_fs_component *ctf_fs = stream->file->ctf_fs;
-
-       if (munmap(stream->mmap_addr, stream->mmap_len)) {
-               PERR("Cannot memory-unmap address %p (size %zu) of file \"%s\" (%p): %s\n",
-                       stream->mmap_addr, stream->mmap_len,
-                       stream->file->path->str, stream->file->fp,
-                       strerror(errno));
-               ret = -1;
-               goto end;
-       }
-end:
-       return ret;
-}
-
-static
-enum bt_ctf_notif_iter_medium_status mmap_next(struct ctf_fs_stream *stream)
-{
-       enum bt_ctf_notif_iter_medium_status ret =
-                       BT_CTF_NOTIF_ITER_MEDIUM_STATUS_OK;
-       struct ctf_fs_component *ctf_fs = stream->file->ctf_fs;
-
-       /* Unmap old region */
-       if (stream->mmap_addr) {
-               if (stream_munmap(stream)) {
-                       goto error;
-               }
-
-               stream->mmap_offset += stream->mmap_valid_len;
-               stream->request_offset = 0;
-       }
-
-       stream->mmap_valid_len = MIN(stream->file->size - stream->mmap_offset,
-                       stream->mmap_max_len);
-       if (stream->mmap_valid_len == 0) {
-               ret = BT_CTF_NOTIF_ITER_MEDIUM_STATUS_EOF;
-               goto end;
-       }
-       /* Round up to next page, assuming page size being a power of 2. */
-       stream->mmap_len = (stream->mmap_valid_len + ctf_fs->page_size - 1)
-                       & ~(ctf_fs->page_size - 1);
-       /* Map new region */
-       assert(stream->mmap_len);
-       stream->mmap_addr = mmap((void *) 0, stream->mmap_len,
-                       PROT_READ, MAP_PRIVATE, fileno(stream->file->fp),
-                       stream->mmap_offset);
-       if (stream->mmap_addr == MAP_FAILED) {
-               PERR("Cannot memory-map address (size %zu) of file \"%s\" (%p) at offset %zu: %s\n",
-                               stream->mmap_len, stream->file->path->str,
-                               stream->file->fp, stream->mmap_offset,
-                               strerror(errno));
-               goto error;
-       }
-
-       goto end;
-error:
-       stream_munmap(stream);
-       ret = BT_CTF_NOTIF_ITER_MEDIUM_STATUS_ERROR;
-end:
-       return ret;
-}
-
-static
-enum bt_ctf_notif_iter_medium_status medop_request_bytes(
-               size_t request_sz, uint8_t **buffer_addr,
-               size_t *buffer_sz, void *data)
-{
-       enum bt_ctf_notif_iter_medium_status status =
-               BT_CTF_NOTIF_ITER_MEDIUM_STATUS_OK;
-       struct ctf_fs_stream *stream = data;
-       struct ctf_fs_component *ctf_fs = stream->file->ctf_fs;
-
-       if (request_sz == 0) {
-               goto end;
-       }
-
-       /* Check if we have at least one memory-mapped byte left */
-       if (remaining_mmap_bytes(stream) == 0) {
-               /* Are we at the end of the file? */
-               if (stream->mmap_offset >= stream->file->size) {
-                       PDBG("Reached end of file \"%s\" (%p)\n",
-                               stream->file->path->str, stream->file->fp);
-                       status = BT_CTF_NOTIF_ITER_MEDIUM_STATUS_EOF;
-                       goto end;
-               }
-
-               status = mmap_next(stream);
-               switch (status) {
-               case BT_CTF_NOTIF_ITER_MEDIUM_STATUS_OK:
-                       break;
-               case BT_CTF_NOTIF_ITER_MEDIUM_STATUS_EOF:
-                       goto end;
-               default:
-                       PERR("Cannot memory-map next region of file \"%s\" (%p)\n",
-                                       stream->file->path->str,
-                                       stream->file->fp);
-                       goto error;
-               }
-       }
-
-       *buffer_sz = MIN(remaining_mmap_bytes(stream), request_sz);
-       *buffer_addr = ((uint8_t *) stream->mmap_addr) + stream->request_offset;
-       stream->request_offset += *buffer_sz;
-       goto end;
-
-error:
-       status = BT_CTF_NOTIF_ITER_MEDIUM_STATUS_ERROR;
-
-end:
-       return status;
-}
-
-static
-struct bt_ctf_stream *medop_get_stream(
-               struct bt_ctf_stream_class *stream_class, void *data)
-{
-       struct ctf_fs_stream *fs_stream = data;
-       struct ctf_fs_component *ctf_fs = fs_stream->file->ctf_fs;
-
-       if (!fs_stream->stream) {
-               int64_t id = bt_ctf_stream_class_get_id(stream_class);
-
-               PDBG("Creating stream out of stream class %" PRId64 "\n", id);
-               fs_stream->stream = bt_ctf_stream_create(stream_class,
-                               fs_stream->file->path->str);
-               if (!fs_stream->stream) {
-                       PERR("Cannot create stream (stream class %" PRId64 ")\n",
-                                       id);
-               }
-       }
-
-       return fs_stream->stream;
-}
-
-static struct bt_ctf_notif_iter_medium_ops medops = {
-       .request_bytes = medop_request_bytes,
-       .get_stream = medop_get_stream,
-};
-
-static
-int build_index_from_idx_file(struct ctf_fs_stream *stream)
-{
-       int ret = 0;
-       gchar *directory = NULL;
-       gchar *basename = NULL;
-       GString *index_basename = NULL;
-       gchar *index_file_path = NULL;
-       GMappedFile *mapped_file = NULL;
-       gsize filesize;
-       const struct ctf_packet_index_file_hdr *header;
-       const char *mmap_begin, *file_pos;
-       struct index_entry *index;
-       uint64_t total_packets_size = 0;
-       size_t file_index_entry_size;
-       size_t file_entry_count;
-       size_t i;
-
-       /* Look for index file in relative path index/name.idx. */
-       basename = g_path_get_basename(stream->file->path->str);
-       if (!basename) {
-               ret = -1;
-               goto end;
-       }
-
-       directory = g_path_get_dirname(stream->file->path->str);
-       if (!directory) {
-               ret = -1;
-               goto end;
-       }
-
-       index_basename = g_string_new(basename);
-       if (!index_basename) {
-               ret = -1;
-               goto end;
-       }
-
-       g_string_append(index_basename, ".idx");
-       index_file_path = g_build_filename(directory, "index",
-                       index_basename->str, NULL);
-       mapped_file = g_mapped_file_new(index_file_path, FALSE, NULL);
-       if (!mapped_file) {
-               ret = -1;
-               goto end;
-       }
-       filesize = g_mapped_file_get_length(mapped_file);
-       if (filesize < sizeof(*header)) {
-               printf_error("Invalid LTTng trace index: file size < header size");
-               ret = -1;
-               goto end;
-       }
-
-       mmap_begin = g_mapped_file_get_contents(mapped_file);
-       header = (struct ctf_packet_index_file_hdr *) mmap_begin;
-
-       file_pos = g_mapped_file_get_contents(mapped_file) + sizeof(*header);
-       if (be32toh(header->magic) != CTF_INDEX_MAGIC) {
-               printf_error("Invalid LTTng trace index: \"magic\" validation failed");
-               ret = -1;
-               goto end;
-       }
-
-       file_index_entry_size = be32toh(header->packet_index_len);
-       file_entry_count = (filesize - sizeof(*header)) / file_index_entry_size;
-       if ((filesize - sizeof(*header)) % (file_entry_count * file_index_entry_size)) {
-               printf_error("Invalid index file size; not a multiple of index entry size");
-               ret = -1;
-               goto end;
-       }
-
-       stream->index.entries = g_array_sized_new(FALSE, TRUE,
-                       sizeof(struct index_entry), file_entry_count);
-       if (!stream->index.entries) {
-               ret = -1;
-               goto end;
-       }
-       index = (struct index_entry *) stream->index.entries->data;
-       for (i = 0; i < file_entry_count; i++) {
-               struct ctf_packet_index *file_index =
-                               (struct ctf_packet_index *) file_pos;
-               uint64_t packet_size = be64toh(file_index->packet_size);
-
-               if (packet_size % CHAR_BIT) {
-                       ret = -1;
-                       printf_error("Invalid packet size encountered in index file");
-                       goto invalid_index;
-               }
-
-               /* Convert size in bits to bytes. */
-               packet_size /= CHAR_BIT;
-               index->packet_size = packet_size;
-
-               index->offset = be64toh(file_index->offset);
-               if (i != 0 && index->offset < (index - 1)->offset) {
-                       printf_error("Invalid, non-monotonic, packet offset encountered in index file");
-                       ret = -1;
-                       goto invalid_index;
-               }
-
-               index->timestamp_begin = be64toh(file_index->timestamp_begin);
-               index->timestamp_end = be64toh(file_index->timestamp_end);
-               if (index->timestamp_end < index->timestamp_begin) {
-                       printf_error("Invalid packet time bounds encountered in index file");
-                       ret = -1;
-                       goto invalid_index;
-               }
-
-               total_packets_size += packet_size;
-               file_pos += file_index_entry_size;
-               index++;
-       }
-
-       /* Validate that the index addresses the complete stream. */
-       if (stream->file->size != total_packets_size) {
-               printf_error("Invalid index; indexed size != stream file size");
-               ret = -1;
-               goto invalid_index;
-       }
-end:
-       g_free(directory);
-       g_free(basename);
-       g_free(index_file_path);
-       if (index_basename) {
-               g_string_free(index_basename, TRUE);
-       }
-       if (mapped_file) {
-               g_mapped_file_unref(mapped_file);
-       }
-       return ret;
-invalid_index:
-       g_array_free(stream->index.entries, TRUE);
-       goto end;
-}
-
-static
-int build_index_from_stream(struct ctf_fs_stream *stream)
-{
-       return 0;
-}
-
-static
-int init_stream_index(struct ctf_fs_stream *stream)
-{
-       int ret;
-
-       ret = build_index_from_idx_file(stream);
-       if (!ret) {
-               goto end;
-       }
-
-       ret = build_index_from_stream(stream);
-end:
-       return ret;
-}
-
-BT_HIDDEN
-struct ctf_fs_stream *ctf_fs_stream_create(
-               struct ctf_fs_component *ctf_fs, const char *path)
-{
-       int ret;
-       struct ctf_fs_stream *stream = g_new0(struct ctf_fs_stream, 1);
-
-       if (!stream) {
-               goto error;
-       }
-
-       stream->file = ctf_fs_file_create(ctf_fs);
-       if (!stream->file) {
-               goto error;
-       }
-
-       stream->cc_prio_map = bt_get(ctf_fs->cc_prio_map);
-       g_string_assign(stream->file->path, path);
-       ret = ctf_fs_file_open(ctf_fs, stream->file, "rb");
-       if (ret) {
-               goto error;
-       }
-
-       stream->notif_iter = bt_ctf_notif_iter_create(ctf_fs->metadata->trace,
-                       ctf_fs->page_size, medops, stream,
-                       ctf_fs->error_fp);
-       if (!stream->notif_iter) {
-               goto error;
-       }
-
-       stream->mmap_max_len = ctf_fs->page_size * 2048;
-       ret = init_stream_index(stream);
-       if (ret) {
-               goto error;
-       }
-       goto end;
-error:
-       /* Do not touch "borrowed" file. */
-       ctf_fs_stream_destroy(stream);
-       stream = NULL;
-end:
-       return stream;
-}
-
-BT_HIDDEN
-void ctf_fs_stream_destroy(struct ctf_fs_stream *stream)
-{
-       if (!stream) {
-               return;
-       }
-
-       bt_put(stream->cc_prio_map);
-
-       if (stream->file) {
-               ctf_fs_file_destroy(stream->file);
-       }
-
-       if (stream->stream) {
-               BT_PUT(stream->stream);
-       }
-
-       if (stream->notif_iter) {
-               bt_ctf_notif_iter_destroy(stream->notif_iter);
-       }
-
-       if (stream->index.entries) {
-               g_array_free(stream->index.entries, TRUE);
-       }
-
-       g_free(stream);
-}
-
-BT_HIDDEN
-struct bt_notification_iterator_next_return ctf_fs_stream_next(
-               struct ctf_fs_stream *stream)
-{
-       enum bt_ctf_notif_iter_status notif_iter_status;
-       struct bt_notification_iterator_next_return ret = {
-               .status = BT_NOTIFICATION_ITERATOR_STATUS_ERROR,
-               .notification = NULL,
-       };
-
-       if (stream->end_reached) {
-               notif_iter_status = BT_CTF_NOTIF_ITER_STATUS_EOF;
-               goto translate_status;
-       }
-
-       notif_iter_status = bt_ctf_notif_iter_get_next_notification(stream->notif_iter,
-                       stream->cc_prio_map, &ret.notification);
-       if (notif_iter_status != BT_CTF_NOTIF_ITER_STATUS_OK &&
-                       notif_iter_status != BT_CTF_NOTIF_ITER_STATUS_EOF) {
-               goto translate_status;
-       }
-
-       /* Should be handled in bt_ctf_notif_iter_get_next_notification. */
-       if (notif_iter_status == BT_CTF_NOTIF_ITER_STATUS_EOF) {
-               ret.notification = bt_notification_stream_end_create(
-                       stream->stream);
-               if (!ret.notification) {
-                       notif_iter_status = BT_CTF_NOTIF_ITER_STATUS_ERROR;
-                       goto translate_status;
-               }
-
-               notif_iter_status = BT_CTF_NOTIF_ITER_STATUS_OK;
-               stream->end_reached = true;
-       }
-
-translate_status:
-       switch (notif_iter_status) {
-       case BT_CTF_NOTIF_ITER_STATUS_EOF:
-               ret.status = BT_NOTIFICATION_ITERATOR_STATUS_END;
-               break;
-       case BT_CTF_NOTIF_ITER_STATUS_OK:
-               ret.status = BT_NOTIFICATION_ITERATOR_STATUS_OK;
-               break;
-       case BT_CTF_NOTIF_ITER_STATUS_AGAIN:
-               /*
-                * Should not make it this far as this is
-                * medium-specific; there is nothing for the user to do
-                * and it should have been handled upstream.
-                */
-               assert(false);
-       case BT_CTF_NOTIF_ITER_STATUS_INVAL:
-       case BT_CTF_NOTIF_ITER_STATUS_ERROR:
-       default:
-               ret.status = BT_NOTIFICATION_ITERATOR_STATUS_ERROR;
-               break;
-       }
-
-       return ret;
-}
diff --git a/plugins/ctf/fs/data-stream.h b/plugins/ctf/fs/data-stream.h
deleted file mode 100644 (file)
index 3d48442..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-#ifndef CTF_FS_DATA_STREAM_H
-#define CTF_FS_DATA_STREAM_H
-
-/*
- * Copyright 2016 - 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 <stdio.h>
-#include <glib.h>
-#include <babeltrace/babeltrace-internal.h>
-#include <babeltrace/ctf-ir/trace.h>
-
-#include "../common/notif-iter/notif-iter.h"
-#include "lttng-index.h"
-
-struct ctf_fs_component;
-struct ctf_fs_file;
-struct ctf_fs_stream;
-
-struct index_entry {
-       uint64_t offset; /* in bytes. */
-       uint64_t packet_size; /* in bytes. */
-       /* relative to the packet context field's mapped clock. */
-       uint64_t timestamp_begin, timestamp_end;
-};
-
-struct index {
-       GArray *entries; /* Array of struct index_entry. */
-};
-
-BT_HIDDEN
-struct ctf_fs_stream *ctf_fs_stream_create(
-               struct ctf_fs_component *ctf_fs, const char *path);
-
-BT_HIDDEN
-void ctf_fs_stream_destroy(struct ctf_fs_stream *stream);
-
-BT_HIDDEN
-int ctf_fs_data_stream_open_streams(struct ctf_fs_component *ctf_fs);
-
-BT_HIDDEN
-struct bt_notification_iterator_next_return ctf_fs_stream_next(
-               struct ctf_fs_stream *stream);
-
-#endif /* CTF_FS_DATA_STREAM_H */
diff --git a/plugins/ctf/fs/file.c b/plugins/ctf/fs/file.c
deleted file mode 100644 (file)
index 8b75649..0000000
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright 2016 - 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 <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <glib.h>
-
-#define PRINT_ERR_STREAM       ctf_fs->error_fp
-#define PRINT_PREFIX           "ctf-fs-file"
-#include "print.h"
-
-#include "file.h"
-
-BT_HIDDEN
-void ctf_fs_file_destroy(struct ctf_fs_file *file)
-{
-       struct ctf_fs_component *ctf_fs;;
-
-       if (!file) {
-               return;
-       }
-
-       ctf_fs = file->ctf_fs;
-
-       if (file->fp) {
-               PDBG("Closing file \"%s\" (%p)\n", file->path->str, file->fp);
-
-               if (fclose(file->fp)) {
-                       PERR("Cannot close file \"%s\": %s\n", file->path->str,
-                               strerror(errno));
-               }
-       }
-
-       if (file->path) {
-               g_string_free(file->path, TRUE);
-       }
-
-       g_free(file);
-}
-
-BT_HIDDEN
-struct ctf_fs_file *ctf_fs_file_create(struct ctf_fs_component *ctf_fs)
-{
-       struct ctf_fs_file *file = g_new0(struct ctf_fs_file, 1);
-
-       if (!file) {
-               goto error;
-       }
-
-       file->ctf_fs = ctf_fs;
-       file->path = g_string_new(NULL);
-       if (!file->path) {
-               goto error;
-       }
-
-       goto end;
-
-error:
-       ctf_fs_file_destroy(file);
-       file = NULL;
-
-end:
-       return file;
-}
-
-BT_HIDDEN
-int ctf_fs_file_open(struct ctf_fs_component *ctf_fs, struct ctf_fs_file *file,
-               const char *mode)
-{
-       int ret = 0;
-       struct stat stat;
-
-       PDBG("Opening file \"%s\" with mode \"%s\"\n", file->path->str, mode);
-       file->fp = fopen(file->path->str, mode);
-       if (!file->fp) {
-               PERR("Cannot open file \"%s\" with mode \"%s\": %s\n",
-                       file->path->str, mode, strerror(errno));
-               goto error;
-       }
-
-       PDBG("Opened file: %p\n", file->fp);
-
-       if (fstat(fileno(file->fp), &stat)) {
-               PERR("Cannot get file informations: %s\n", strerror(errno));
-               goto error;
-       }
-
-       file->size = stat.st_size;
-       PDBG("  File is %zu bytes\n", file->size);
-       goto end;
-
-error:
-       ret = -1;
-
-       if (file->fp) {
-               if (fclose(file->fp)) {
-                       PERR("Cannot close file \"%s\": %s\n", file->path->str,
-                               strerror(errno));
-               }
-       }
-
-end:
-       return ret;
-}
diff --git a/plugins/ctf/fs/file.h b/plugins/ctf/fs/file.h
deleted file mode 100644 (file)
index 59f3d0e..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-#ifndef CTF_FS_FILE_H
-#define CTF_FS_FILE_H
-
-/*
- * Copyright 2016 - 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 <stdio.h>
-#include <glib.h>
-#include <babeltrace/babeltrace-internal.h>
-#include "fs.h"
-
-BT_HIDDEN
-void ctf_fs_file_destroy(struct ctf_fs_file *file);
-
-BT_HIDDEN
-struct ctf_fs_file *ctf_fs_file_create(struct ctf_fs_component *ctf_fs);
-
-BT_HIDDEN
-int ctf_fs_file_open(struct ctf_fs_component *ctf_fs, struct ctf_fs_file *file,
-               const char *mode);
-
-#endif /* CTF_FS_FILE_H */
diff --git a/plugins/ctf/fs/fs.c b/plugins/ctf/fs/fs.c
deleted file mode 100644 (file)
index 2abd9b5..0000000
+++ /dev/null
@@ -1,620 +0,0 @@
-/*
- * fs.c
- *
- * Babeltrace CTF file system Reader Component
- *
- * 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/ctf-ir/packet.h>
-#include <babeltrace/ctf-ir/clock-class.h>
-#include <babeltrace/graph/private-port.h>
-#include <babeltrace/graph/private-component.h>
-#include <babeltrace/graph/private-component-source.h>
-#include <babeltrace/graph/private-notification-iterator.h>
-#include <babeltrace/graph/component.h>
-#include <babeltrace/graph/notification-iterator.h>
-#include <babeltrace/graph/clock-class-priority-map.h>
-#include <plugins-common.h>
-#include <glib.h>
-#include <assert.h>
-#include <unistd.h>
-#include "fs.h"
-#include "metadata.h"
-#include "data-stream.h"
-#include "file.h"
-#include "../common/metadata/decoder.h"
-
-#define PRINT_ERR_STREAM       ctf_fs->error_fp
-#define PRINT_PREFIX           "ctf-fs"
-#include "print.h"
-#define METADATA_TEXT_SIG      "/* CTF 1.8"
-
-BT_HIDDEN
-bool ctf_fs_debug;
-
-struct bt_notification_iterator_next_return ctf_fs_iterator_next(
-               struct bt_private_notification_iterator *iterator)
-{
-       struct ctf_fs_stream *fs_stream =
-               bt_private_notification_iterator_get_user_data(iterator);
-
-       return ctf_fs_stream_next(fs_stream);
-}
-
-void ctf_fs_iterator_finalize(struct bt_private_notification_iterator *it)
-{
-       void *ctf_fs_stream =
-               bt_private_notification_iterator_get_user_data(it);
-
-       ctf_fs_stream_destroy(ctf_fs_stream);
-}
-
-enum bt_notification_iterator_status ctf_fs_iterator_init(
-               struct bt_private_notification_iterator *it,
-               struct bt_private_port *port)
-{
-       struct ctf_fs_stream *stream = NULL;
-       struct ctf_fs_component *ctf_fs;
-       struct ctf_fs_port_data *port_data;
-       struct bt_private_component *priv_comp =
-               bt_private_notification_iterator_get_private_component(it);
-       enum bt_notification_iterator_status ret =
-               BT_NOTIFICATION_ITERATOR_STATUS_OK;
-
-       assert(priv_comp);
-
-       ctf_fs = bt_private_component_get_user_data(priv_comp);
-       if (!ctf_fs) {
-               ret = BT_NOTIFICATION_ITERATOR_STATUS_INVALID;
-               goto error;
-       }
-
-       port_data = bt_private_port_get_user_data(port);
-       if (!port_data) {
-               ret = BT_NOTIFICATION_ITERATOR_STATUS_INVALID;
-               goto error;
-       }
-
-       stream = ctf_fs_stream_create(ctf_fs, port_data->path->str);
-       if (!stream) {
-               goto error;
-       }
-
-       ret = bt_private_notification_iterator_set_user_data(it, stream);
-       if (ret) {
-               goto error;
-       }
-
-       stream = NULL;
-       goto end;
-
-error:
-       (void) bt_private_notification_iterator_set_user_data(it, NULL);
-
-       if (ret == BT_NOTIFICATION_ITERATOR_STATUS_OK) {
-               ret = BT_NOTIFICATION_ITERATOR_STATUS_ERROR;
-       }
-
-end:
-       ctf_fs_stream_destroy(stream);
-       bt_put(priv_comp);
-       return ret;
-}
-
-static
-void ctf_fs_destroy_data(struct ctf_fs_component *ctf_fs)
-{
-       if (!ctf_fs) {
-               return;
-       }
-
-       if (ctf_fs->trace_path) {
-               g_string_free(ctf_fs->trace_path, TRUE);
-       }
-
-       if (ctf_fs->port_data) {
-               g_ptr_array_free(ctf_fs->port_data, TRUE);
-       }
-
-       if (ctf_fs->metadata) {
-               ctf_fs_metadata_fini(ctf_fs->metadata);
-               g_free(ctf_fs->metadata);
-       }
-
-       bt_put(ctf_fs->cc_prio_map);
-       g_free(ctf_fs);
-}
-
-void ctf_fs_finalize(struct bt_private_component *component)
-{
-       void *data = bt_private_component_get_user_data(component);
-
-       ctf_fs_destroy_data(data);
-}
-
-static
-void port_data_destroy(void *data) {
-       struct ctf_fs_port_data *port_data = data;
-
-       if (!port_data) {
-               return;
-       }
-
-       if (port_data->path) {
-               g_string_free(port_data->path, TRUE);
-       }
-
-       g_free(port_data);
-}
-
-static
-int create_one_port(struct ctf_fs_component *ctf_fs,
-               const char *stream_basename, const char *stream_path)
-{
-       int ret = 0;
-       struct bt_private_port *port = NULL;
-       struct ctf_fs_port_data *port_data = NULL;
-       GString *port_name = NULL;
-
-       port_name = g_string_new(NULL);
-       if (!port_name) {
-               goto error;
-       }
-
-       /* Assign the name for the new output port */
-       g_string_assign(port_name, "");
-       g_string_printf(port_name, "trace0-stream-%s", stream_basename);
-       PDBG("Creating one port named `%s` associated with path `%s`\n",
-               port_name->str, stream_path);
-
-       /* Create output port for this file */
-       port_data = g_new0(struct ctf_fs_port_data, 1);
-       if (!port_data) {
-               goto error;
-       }
-
-       port_data->path = g_string_new(stream_path);
-       if (!port_data->path) {
-               goto error;
-       }
-
-       port = bt_private_component_source_add_output_private_port(
-               ctf_fs->priv_comp, port_name->str, port_data);
-       if (!port) {
-               goto error;
-       }
-
-       g_ptr_array_add(ctf_fs->port_data, port_data);
-       port_data = NULL;
-       goto end;
-
-error:
-       ret = -1;
-
-end:
-       if (port_name) {
-               g_string_free(port_name, TRUE);
-       }
-
-       bt_put(port);
-       port_data_destroy(port_data);
-       return ret;
-}
-
-static
-int create_ports(struct ctf_fs_component *ctf_fs)
-{
-       int ret = 0;
-       const char *basename;
-       GError *error = NULL;
-       GDir *dir = NULL;
-       struct ctf_fs_file *file = NULL;
-
-       /* Create one output port for each stream file */
-       dir = g_dir_open(ctf_fs->trace_path->str, 0, &error);
-       if (!dir) {
-               PERR("Cannot open directory `%s`: %s (code %d)\n",
-                       ctf_fs->trace_path->str, error->message,
-                       error->code);
-               goto error;
-       }
-
-       while ((basename = g_dir_read_name(dir))) {
-               if (!strcmp(basename, CTF_FS_METADATA_FILENAME)) {
-                       /* Ignore the metadata stream. */
-                       PDBG("Ignoring metadata file `%s`\n", basename);
-                       continue;
-               }
-
-               if (basename[0] == '.') {
-                       PDBG("Ignoring hidden file `%s`\n", basename);
-                       continue;
-               }
-
-               /* Create the file. */
-               file = ctf_fs_file_create(ctf_fs);
-               if (!file) {
-                       PERR("Cannot create stream file object for file `%s`\n",
-                               basename);
-                       goto error;
-               }
-
-               /* Create full path string. */
-               g_string_append_printf(file->path, "%s/%s",
-                               ctf_fs->trace_path->str, basename);
-               if (!g_file_test(file->path->str, G_FILE_TEST_IS_REGULAR)) {
-                       PDBG("Ignoring non-regular file `%s`\n", basename);
-                       ctf_fs_file_destroy(file);
-                       file = NULL;
-                       continue;
-               }
-
-               ret = ctf_fs_file_open(ctf_fs, file, "rb");
-               if (ret) {
-                       PERR("Cannot open stream file `%s`\n", basename);
-                       goto error;
-               }
-
-               if (file->size == 0) {
-                       /* Skip empty stream. */
-                       PDBG("Ignoring empty file `%s`\n", basename);
-                       ctf_fs_file_destroy(file);
-                       file = NULL;
-                       continue;
-               }
-
-               ret = create_one_port(ctf_fs, basename, file->path->str);
-               if (ret) {
-                       PERR("Cannot create output port for file `%s`\n",
-                               basename);
-                       goto error;
-               }
-
-               ctf_fs_file_destroy(file);
-               file = NULL;
-       }
-
-       goto end;
-
-error:
-       ret = -1;
-
-end:
-       if (dir) {
-               g_dir_close(dir);
-               dir = NULL;
-       }
-
-       if (error) {
-               g_error_free(error);
-       }
-
-       ctf_fs_file_destroy(file);
-       return ret;
-}
-
-static
-int create_cc_prio_map(struct ctf_fs_component *ctf_fs)
-{
-       int ret = 0;
-       size_t i;
-       int count;
-
-       assert(ctf_fs);
-       ctf_fs->cc_prio_map = bt_clock_class_priority_map_create();
-       if (!ctf_fs->cc_prio_map) {
-               ret = -1;
-               goto end;
-       }
-
-       count = bt_ctf_trace_get_clock_class_count(ctf_fs->metadata->trace);
-       assert(count >= 0);
-
-       for (i = 0; i < count; i++) {
-               struct bt_ctf_clock_class *clock_class =
-                       bt_ctf_trace_get_clock_class_by_index(
-                               ctf_fs->metadata->trace, i);
-
-               assert(clock_class);
-               ret = bt_clock_class_priority_map_add_clock_class(
-                       ctf_fs->cc_prio_map, clock_class, 0);
-               BT_PUT(clock_class);
-
-               if (ret) {
-                       goto end;
-               }
-       }
-
-end:
-       return ret;
-}
-
-static
-struct ctf_fs_component *ctf_fs_create(struct bt_private_component *priv_comp,
-               struct bt_value *params)
-{
-       struct ctf_fs_component *ctf_fs;
-       struct bt_value *value = NULL;
-       const char *path;
-       int ret;
-
-       ctf_fs = g_new0(struct ctf_fs_component, 1);
-       if (!ctf_fs) {
-               goto end;
-       }
-
-       /*
-        * We don't need to get a new reference here because as long as
-        * our private ctf_fs_component object exists, the containing
-        * private component should also exist.
-        */
-       ctf_fs->priv_comp = priv_comp;
-
-       /* FIXME: should probably look for a source URI */
-       value = bt_value_map_get(params, "path");
-       if (!value || bt_value_is_null(value) || !bt_value_is_string(value)) {
-               goto error;
-       }
-
-       ret = bt_value_string_get(value, &path);
-       if (ret) {
-               goto error;
-       }
-
-       ctf_fs->port_data = g_ptr_array_new_with_free_func(port_data_destroy);
-       if (!ctf_fs->port_data) {
-               goto error;
-       }
-
-       ctf_fs->trace_path = g_string_new(path);
-       if (!ctf_fs->trace_path) {
-               BT_PUT(value);
-               goto error;
-       }
-       bt_put(value);
-
-       value = bt_value_map_get(params, "offset-s");
-       if (value) {
-               int64_t offset;
-
-               if (!bt_value_is_integer(value)) {
-                       fprintf(stderr,
-                               "offset-s should be an integer\n");
-                       goto error;
-               }
-               ret = bt_value_integer_get(value, &offset);
-               if (ret != BT_VALUE_STATUS_OK) {
-                       fprintf(stderr,
-                               "Failed to get offset-s value\n");
-                       goto error;
-               }
-               ctf_fs->options.clock_offset = offset;
-               bt_put(value);
-       }
-
-       value = bt_value_map_get(params, "offset-ns");
-       if (value) {
-               int64_t offset;
-
-               if (!bt_value_is_integer(value)) {
-                       fprintf(stderr,
-                               "offset-ns should be an integer\n");
-                       goto error;
-               }
-               ret = bt_value_integer_get(value, &offset);
-               if (ret != BT_VALUE_STATUS_OK) {
-                       fprintf(stderr,
-                               "Failed to get offset-ns value\n");
-                       goto error;
-               }
-               ctf_fs->options.clock_offset_ns = offset;
-               bt_put(value);
-       }
-
-       ctf_fs->error_fp = stderr;
-       ctf_fs->page_size = (size_t) getpagesize();
-
-       // FIXME: check error.
-       ctf_fs->metadata = g_new0(struct ctf_fs_metadata, 1);
-       if (!ctf_fs->metadata) {
-               goto error;
-       }
-
-       ret = ctf_fs_metadata_set_trace(ctf_fs);
-       if (ret) {
-               goto error;
-       }
-
-       ret = create_cc_prio_map(ctf_fs);
-       if (ret) {
-               goto error;
-       }
-
-       ret = create_ports(ctf_fs);
-       if (ret) {
-               goto error;
-       }
-
-       goto end;
-
-error:
-       ctf_fs_destroy_data(ctf_fs);
-       ctf_fs = NULL;
-end:
-       return ctf_fs;
-}
-
-BT_HIDDEN
-enum bt_component_status ctf_fs_init(struct bt_private_component *priv_comp,
-               struct bt_value *params, UNUSED_VAR void *init_method_data)
-{
-       struct ctf_fs_component *ctf_fs;
-       enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
-
-       assert(priv_comp);
-       ctf_fs_debug = g_strcmp0(getenv("CTF_FS_DEBUG"), "1") == 0;
-       ctf_fs = ctf_fs_create(priv_comp, params);
-       if (!ctf_fs) {
-               ret = BT_COMPONENT_STATUS_NOMEM;
-               goto end;
-       }
-
-       ret = bt_private_component_set_user_data(priv_comp, ctf_fs);
-       if (ret != BT_COMPONENT_STATUS_OK) {
-               goto error;
-       }
-end:
-       return ret;
-error:
-       (void) bt_private_component_set_user_data(priv_comp, NULL);
-        ctf_fs_destroy_data(ctf_fs);
-       return ret;
-}
-
-BT_HIDDEN
-struct bt_value *ctf_fs_query(struct bt_component_class *comp_class,
-               const char *object, struct bt_value *params)
-{
-       struct bt_value *results = NULL;
-       struct bt_value *path_value = NULL;
-       char *metadata_text = NULL;
-       FILE *metadata_fp = NULL;
-       GString *g_metadata_text = NULL;
-
-       if (strcmp(object, "metadata-info") == 0) {
-               int ret;
-               int bo;
-               const char *path;
-               bool is_packetized;
-
-               results = bt_value_map_create();
-               if (!results) {
-                       goto error;
-               }
-
-               if (!bt_value_is_map(params)) {
-                       fprintf(stderr,
-                               "Query parameters is not a map value object\n");
-                       goto error;
-               }
-
-               path_value = bt_value_map_get(params, "path");
-               ret = bt_value_string_get(path_value, &path);
-               if (ret) {
-                       fprintf(stderr,
-                               "Cannot get `path` string parameter\n");
-                       goto error;
-               }
-
-               assert(path);
-               metadata_fp = ctf_fs_metadata_open_file(path);
-               if (!metadata_fp) {
-                       fprintf(stderr,
-                               "Cannot open trace at path `%s`\n", path);
-                       goto error;
-               }
-
-               is_packetized = ctf_metadata_decoder_is_packetized(metadata_fp,
-                       &bo);
-
-               if (is_packetized) {
-                       ret = ctf_metadata_decoder_packetized_file_stream_to_buf(
-                               metadata_fp, &metadata_text, bo);
-                       if (ret) {
-                               fprintf(stderr,
-                                       "Cannot decode packetized metadata file\n");
-                               goto error;
-                       }
-               } else {
-                       long filesize;
-
-                       fseek(metadata_fp, 0, SEEK_END);
-                       filesize = ftell(metadata_fp);
-                       rewind(metadata_fp);
-                       metadata_text = malloc(filesize + 1);
-                       if (!metadata_text) {
-                               fprintf(stderr,
-                                       "Cannot allocate buffer for metadata text\n");
-                               goto error;
-                       }
-
-                       if (fread(metadata_text, filesize, 1, metadata_fp) !=
-                                       1) {
-                               fprintf(stderr,
-                                       "Cannot read metadata file\n");
-                               goto error;
-                       }
-
-                       metadata_text[filesize] = '\0';
-               }
-
-               g_metadata_text = g_string_new(NULL);
-               if (!g_metadata_text) {
-                       goto error;
-               }
-
-               if (strncmp(metadata_text, METADATA_TEXT_SIG,
-                               sizeof(METADATA_TEXT_SIG) - 1) != 0) {
-                       g_string_assign(g_metadata_text, METADATA_TEXT_SIG);
-                       g_string_append(g_metadata_text, " */\n\n");
-               }
-
-               g_string_append(g_metadata_text, metadata_text);
-
-               ret = bt_value_map_insert_string(results, "text",
-                       g_metadata_text->str);
-               if (ret) {
-                       fprintf(stderr, "Cannot insert metadata text into results\n");
-                       goto error;
-               }
-
-               ret = bt_value_map_insert_bool(results, "is-packetized",
-                       is_packetized);
-               if (ret) {
-                       fprintf(stderr, "Cannot insert is packetized into results\n");
-                       goto error;
-               }
-       } else {
-               fprintf(stderr, "Unknown query object `%s`\n", object);
-               goto error;
-       }
-
-       goto end;
-
-error:
-       BT_PUT(results);
-
-end:
-       bt_put(path_value);
-       free(metadata_text);
-
-       if (g_metadata_text) {
-               g_string_free(g_metadata_text, TRUE);
-       }
-
-       if (metadata_fp) {
-               fclose(metadata_fp);
-       }
-       return results;
-}
diff --git a/plugins/ctf/fs/fs.h b/plugins/ctf/fs/fs.h
deleted file mode 100644 (file)
index 836c106..0000000
+++ /dev/null
@@ -1,124 +0,0 @@
-#ifndef BABELTRACE_PLUGIN_CTF_FS_H
-#define BABELTRACE_PLUGIN_CTF_FS_H
-
-/*
- * BabelTrace - CTF on File System Component
- *
- * Copyright 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- * Copyright 2016 Philippe Proulx <pproulx@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/babeltrace-internal.h>
-#include <babeltrace/graph/component.h>
-#include <babeltrace/graph/clock-class-priority-map.h>
-#include "data-stream.h"
-
-#define CTF_FS_COMPONENT_DESCRIPTION \
-       "Component used to read a CTF trace located on a file system."
-
-BT_HIDDEN
-extern bool ctf_fs_debug;
-
-struct ctf_fs_file {
-       struct ctf_fs_component *ctf_fs;
-       GString *path;
-       FILE *fp;
-       off_t size;
-};
-
-struct ctf_fs_metadata {
-       struct bt_ctf_trace *trace;
-       uint8_t uuid[16];
-       bool is_uuid_set;
-       int bo;
-       char *text;
-};
-
-struct ctf_fs_stream {
-       struct ctf_fs_file *file;
-       struct bt_ctf_stream *stream;
-       struct bt_clock_class_priority_map *cc_prio_map;
-       struct bt_ctf_notif_iter *notif_iter;
-       /* A stream is assumed to be indexed. */
-       struct index index;
-       void *mmap_addr;
-       /* Max length of chunk to mmap() when updating the current mapping. */
-       size_t mmap_max_len;
-       /* Length of the current mapping. */
-       size_t mmap_len;
-       /* Length of the current mapping which *exists* in the backing file. */
-       size_t mmap_valid_len;
-       /* Offset in the file where the current mapping starts. */
-       off_t mmap_offset;
-       /*
-        * Offset, in the current mapping, of the address to return on the next
-        * request.
-        */
-       off_t request_offset;
-       bool end_reached;
-};
-
-struct ctf_fs_component_options {
-       uint64_t clock_offset;
-       uint64_t clock_offset_ns;
-};
-
-struct ctf_fs_port_data {
-       GString *path;
-};
-
-struct ctf_fs_component {
-       struct bt_private_component *priv_comp;
-       GString *trace_path;
-       FILE *error_fp;
-       size_t page_size;
-       struct ctf_fs_component_options options;
-       struct ctf_fs_metadata *metadata;
-       struct bt_clock_class_priority_map *cc_prio_map;
-
-       /* Array of struct ctf_fs_port_data *, owned by this */
-       GPtrArray *port_data;
-};
-
-BT_HIDDEN
-enum bt_component_status ctf_fs_init(struct bt_private_component *source,
-               struct bt_value *params, void *init_method_data);
-
-BT_HIDDEN
-void ctf_fs_finalize(struct bt_private_component *component);
-
-BT_HIDDEN
-enum bt_notification_iterator_status ctf_fs_iterator_init(
-               struct bt_private_notification_iterator *it,
-               struct bt_private_port *port);
-
-void ctf_fs_iterator_finalize(struct bt_private_notification_iterator *it);
-
-struct bt_notification_iterator_next_return ctf_fs_iterator_next(
-               struct bt_private_notification_iterator *iterator);
-
-BT_HIDDEN
-struct bt_value *ctf_fs_query(struct bt_component_class *comp_class,
-               const char *object, struct bt_value *params);
-
-#endif /* BABELTRACE_PLUGIN_CTF_FS_H */
diff --git a/plugins/ctf/fs/lttng-index.h b/plugins/ctf/fs/lttng-index.h
deleted file mode 100644 (file)
index 05629f8..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2013 - Julien Desfossez <jdesfossez@efficios.com>
- *                      Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *                      David Goulet <dgoulet@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.
- */
-
-#ifndef LTTNG_INDEX_H
-#define LTTNG_INDEX_H
-
-#include <babeltrace/compat/limits-internal.h>
-
-#define CTF_INDEX_MAGIC 0xC1F1DCC1
-#define CTF_INDEX_MAJOR 1
-#define CTF_INDEX_MINOR 1
-
-/*
- * Header at the beginning of each index file.
- * All integer fields are stored in big endian.
- */
-struct ctf_packet_index_file_hdr {
-       uint32_t magic;
-       uint32_t index_major;
-       uint32_t index_minor;
-       /* size of struct ctf_packet_index, in bytes. */
-       uint32_t packet_index_len;
-} __attribute__((__packed__));
-
-/*
- * Packet index generated for each trace packet store in a trace file.
- * All integer fields are stored in big endian.
- */
-struct ctf_packet_index {
-       uint64_t offset;                /* offset of the packet in the file, in bytes */
-       uint64_t packet_size;           /* packet size, in bits */
-       uint64_t content_size;          /* content size, in bits */
-       uint64_t timestamp_begin;
-       uint64_t timestamp_end;
-       uint64_t events_discarded;
-       uint64_t stream_id;
-       /* CTF_INDEX 1.0 limit */
-       uint64_t stream_instance_id;    /* ID of the channel instance */
-       uint64_t packet_seq_num;        /* packet sequence number */
-} __attribute__((__packed__));
-
-#endif /* LTTNG_INDEX_H */
diff --git a/plugins/ctf/fs/metadata.c b/plugins/ctf/fs/metadata.c
deleted file mode 100644 (file)
index cd21196..0000000
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * Copyright 2016 - Philippe Proulx <pproulx@efficios.com>
- * Copyright 2010-2011 - EfficiOS Inc. and Linux Foundation
- *
- * Some functions are based on older functions written by Mathieu Desnoyers.
- *
- * 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 <stdio.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <stdbool.h>
-#include <assert.h>
-#include <glib.h>
-#include <babeltrace/compat/uuid-internal.h>
-#include <babeltrace/compat/memstream-internal.h>
-
-#define PRINT_ERR_STREAM       ctf_fs->error_fp
-#define PRINT_PREFIX           "ctf-fs-metadata"
-#include "print.h"
-
-#include "fs.h"
-#include "file.h"
-#include "metadata.h"
-#include "../common/metadata/decoder.h"
-
-#define NSEC_PER_SEC 1000000000LL
-
-BT_HIDDEN
-FILE *ctf_fs_metadata_open_file(const char *trace_path)
-{
-       GString *metadata_path = g_string_new(trace_path);
-       FILE *fp = NULL;
-
-       if (!metadata_path) {
-               goto error;
-       }
-
-       g_string_append(metadata_path, "/" CTF_FS_METADATA_FILENAME);
-       fp = fopen(metadata_path->str, "rb");
-       if (!fp) {
-               goto error;
-       }
-
-       goto end;
-
-error:
-       if (fp) {
-               fclose(fp);
-               fp = NULL;
-       }
-
-end:
-       g_string_free(metadata_path, TRUE);
-       return fp;
-}
-
-static struct ctf_fs_file *get_file(struct ctf_fs_component *ctf_fs,
-               const char *trace_path)
-{
-       struct ctf_fs_file *file = ctf_fs_file_create(ctf_fs);
-
-       if (!file) {
-               goto error;
-       }
-
-       g_string_append(file->path, trace_path);
-       g_string_append(file->path, "/" CTF_FS_METADATA_FILENAME);
-
-       if (ctf_fs_file_open(ctf_fs, file, "rb")) {
-               goto error;
-       }
-
-       goto end;
-
-error:
-       if (file) {
-               ctf_fs_file_destroy(file);
-               file = NULL;
-       }
-
-end:
-       return file;
-}
-
-int ctf_fs_metadata_set_trace(struct ctf_fs_component *ctf_fs)
-{
-       int ret = 0;
-       struct ctf_fs_file *file = NULL;
-       struct ctf_metadata_decoder *metadata_decoder = NULL;
-
-       file = get_file(ctf_fs, ctf_fs->trace_path->str);
-       if (!file) {
-               PERR("Cannot create metadata file object\n");
-               goto end;
-       }
-
-       metadata_decoder = ctf_metadata_decoder_create(ctf_fs->error_fp,
-               ctf_fs->options.clock_offset * NSEC_PER_SEC +
-               ctf_fs->options.clock_offset_ns);
-       if (!metadata_decoder) {
-               PERR("Cannot create metadata decoder object\n");
-               goto end;
-       }
-
-       ret = ctf_metadata_decoder_decode(metadata_decoder, file->fp);
-       if (ret) {
-               PERR("Cannot decode metadata file\n");
-               goto end;
-       }
-
-       ctf_fs->metadata->trace = ctf_metadata_decoder_get_trace(
-               metadata_decoder);
-       assert(ctf_fs->metadata->trace);
-
-end:
-       ctf_fs_file_destroy(file);
-       ctf_metadata_decoder_destroy(metadata_decoder);
-       return ret;
-}
-
-int ctf_fs_metadata_init(struct ctf_fs_metadata *metadata)
-{
-       /* Nothing to initialize for the moment. */
-       return 0;
-}
-
-void ctf_fs_metadata_fini(struct ctf_fs_metadata *metadata)
-{
-       if (metadata->text) {
-               free(metadata->text);
-       }
-
-       if (metadata->trace) {
-               BT_PUT(metadata->trace);
-       }
-}
diff --git a/plugins/ctf/fs/metadata.h b/plugins/ctf/fs/metadata.h
deleted file mode 100644 (file)
index 85a7726..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-#ifndef CTF_FS_METADATA_H
-#define CTF_FS_METADATA_H
-
-/*
- * Copyright 2016 - 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 <stdio.h>
-#include <glib.h>
-#include <babeltrace/babeltrace-internal.h>
-#include <babeltrace/ctf-ir/trace.h>
-#include "fs.h"
-
-#define CTF_FS_METADATA_FILENAME       "metadata"
-
-BT_HIDDEN
-int ctf_fs_metadata_init(struct ctf_fs_metadata *metadata);
-
-BT_HIDDEN
-void ctf_fs_metadata_fini(struct ctf_fs_metadata *metadata);
-
-BT_HIDDEN
-int ctf_fs_metadata_set_trace(struct ctf_fs_component *ctf_fs);
-
-BT_HIDDEN
-FILE *ctf_fs_metadata_open_file(const char *trace_path);
-
-BT_HIDDEN
-bool ctf_metadata_is_packetized(FILE *fp, int *byte_order);
-
-BT_HIDDEN
-int ctf_metadata_packetized_file_to_buf(struct ctf_fs_component *ctf_fs,
-               FILE *fp, uint8_t **buf, int byte_order);
-
-#endif /* CTF_FS_METADATA_H */
diff --git a/plugins/ctf/fs/print.h b/plugins/ctf/fs/print.h
deleted file mode 100644 (file)
index 9daf7ea..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-#ifndef CTF_FS_PRINT_H
-#define CTF_FS_PRINT_H
-
-/*
- * Define PRINT_PREFIX and PRINT_ERR_STREAM, then include this file.
- *
- * Copyright (c) 2016 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 <stdio.h>
-
-#define PERR(fmt, ...)                                                 \
-       do {                                                            \
-               if (PRINT_ERR_STREAM) {                                 \
-                       fprintf(PRINT_ERR_STREAM,                       \
-                               "Error: " PRINT_PREFIX ": " fmt,        \
-                               ##__VA_ARGS__);                         \
-               }                                                       \
-       } while (0)
-
-#define PWARN(fmt, ...)                                                        \
-       do {                                                            \
-               if (PRINT_ERR_STREAM) {                                 \
-                       fprintf(PRINT_ERR_STREAM,                       \
-                               "Warning: " PRINT_PREFIX ": " fmt,      \
-                               ##__VA_ARGS__);                         \
-               }                                                       \
-       } while (0)
-
-#define PDBG(fmt, ...)                                                 \
-       do {                                                            \
-               if (ctf_fs_debug) {                                     \
-                       fprintf(stderr,                                 \
-                               "Debug: " PRINT_PREFIX ": " fmt,        \
-                               ##__VA_ARGS__);                         \
-               }                                                       \
-       } while (0)
-
-#endif /* CTF_FS_PRINT_H */
index e2f99b476fd57cd28405aa0b8159ce43d939bffa..51556274d68c89f1683b3a98891d08da889fe6fc 100644 (file)
@@ -30,8 +30,6 @@
 #include <babeltrace/babeltrace-internal.h>
 #include <babeltrace/graph/component.h>
 
-#define LTTNG_LIVE_COMPONENT_DESCRIPTION "Component implementing an LTTng-live client."
-
 BT_HIDDEN
 enum bt_component_status lttng_live_init(struct bt_private_component *source,
                struct bt_value *params, void *init_method_data);
index 6d483b1de7f08c4680f0aad99038394be22d4f48..7b18bd109e8a56aa1ef943f92b67f7d080df6a94 100644 (file)
  */
 
 #include <babeltrace/plugin/plugin-dev.h>
-#include "fs/fs.h"
+#include "fs-src/fs.h"
+#include "fs-sink/writer.h"
 #include "lttng-live/lttng-live-internal.h"
 
 /* Initialize plug-in description. */
 BT_PLUGIN(ctf);
-BT_PLUGIN_DESCRIPTION("Built-in Babeltrace plug-in providing CTF read support.");
-BT_PLUGIN_AUTHOR("Jérémie Galarneau");
+BT_PLUGIN_DESCRIPTION("CTF source and sink support");
+BT_PLUGIN_AUTHOR("Julien Desfossez, Mathieu Desnoyers, Jérémie Galarneau, Philippe Proulx");
 BT_PLUGIN_LICENSE("MIT");
 
-/* Declare component classes implemented by this plug-in. */
+/* ctf.fs soource */
 BT_PLUGIN_SOURCE_COMPONENT_CLASS(fs, ctf_fs_iterator_next);
-BT_PLUGIN_SOURCE_COMPONENT_CLASS_DESCRIPTION(fs, CTF_FS_COMPONENT_DESCRIPTION);
+BT_PLUGIN_SOURCE_COMPONENT_CLASS_DESCRIPTION(fs,
+       "Read CTF traces from the file system.");
 BT_PLUGIN_SOURCE_COMPONENT_CLASS_INIT_METHOD(fs, ctf_fs_init);
 BT_PLUGIN_SOURCE_COMPONENT_CLASS_QUERY_METHOD(fs, ctf_fs_query);
 BT_PLUGIN_SOURCE_COMPONENT_CLASS_FINALIZE_METHOD(fs, ctf_fs_finalize);
@@ -47,9 +49,18 @@ BT_PLUGIN_SOURCE_COMPONENT_CLASS_NOTIFICATION_ITERATOR_INIT_METHOD(fs,
 BT_PLUGIN_SOURCE_COMPONENT_CLASS_NOTIFICATION_ITERATOR_FINALIZE_METHOD(fs,
        ctf_fs_iterator_finalize);
 
+/* ctf.lttng-live source */
 BT_PLUGIN_SOURCE_COMPONENT_CLASS_WITH_ID(auto, lttng_live, "lttng-live",
        lttng_live_iterator_next);
 BT_PLUGIN_SOURCE_COMPONENT_CLASS_INIT_METHOD_WITH_ID(auto, lttng_live,
        lttng_live_init);
 BT_PLUGIN_SOURCE_COMPONENT_CLASS_DESCRIPTION_WITH_ID(auto, lttng_live,
-        LTTNG_LIVE_COMPONENT_DESCRIPTION);
+        "Connect to an LTTng relay daemon and receive CTF streams.");
+
+/* ctf.fs sink */
+BT_PLUGIN_SINK_COMPONENT_CLASS(fs, writer_run);
+BT_PLUGIN_SINK_COMPONENT_CLASS_INIT_METHOD(fs, writer_component_init);
+BT_PLUGIN_SINK_COMPONENT_CLASS_PORT_CONNECTED_METHOD(fs,
+               writer_component_port_connected);
+BT_PLUGIN_SINK_COMPONENT_CLASS_FINALIZE_METHOD(fs, writer_component_finalize);
+BT_PLUGIN_SINK_COMPONENT_CLASS_DESCRIPTION(fs, "Write CTF traces to the file system.");
diff --git a/plugins/text/dmesg/Makefile.am b/plugins/text/dmesg/Makefile.am
new file mode 100644 (file)
index 0000000..04df5eb
--- /dev/null
@@ -0,0 +1,7 @@
+AM_CFLAGS = $(PACKAGE_CFLAGS) -I$(top_srcdir)/include -I$(top_srcdir)/plugins
+
+noinst_LTLIBRARIES = libbabeltrace-plugin-text-dmesg-cc.la
+
+libbabeltrace_plugin_text_dmesg_cc_la_SOURCES = dmesg.c dmesg.h
+libbabeltrace_plugin_text_dmesg_cc_la_LIBADD = \
+       $(top_builddir)/common/libbabeltrace-common.la
diff --git a/plugins/text/dmesg/dmesg.c b/plugins/text/dmesg/dmesg.c
new file mode 100644 (file)
index 0000000..0f8a6e7
--- /dev/null
@@ -0,0 +1,190 @@
+/*
+ * Copyright 2010-2011 EfficiOS Inc. and Linux Foundation
+ * Copyright 2017 Philippe Proulx <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 <stdio.h>
+#include <assert.h>
+#include <babeltrace/babeltrace-internal.h>
+#include <babeltrace/graph/component.h>
+#include <babeltrace/graph/clock-class-priority-map.h>
+#include <glib.h>
+
+struct dmesg_component;
+
+struct dmesg_notif_iter {
+       struct dmesg_component *dmesg_comp;
+       FILE *fp;
+};
+
+struct dmesg_component {
+       struct {
+               GString *path;
+               bool read_from_stdin;
+       } params;
+
+       struct bt_ctf_packet *packet;
+       struct bt_ctf_event_class *event_class;
+       struct bt_ctf_stream *stream;
+       struct bt_clock_class_priority_map *cc_prio_map;
+};
+
+static
+int check_params(struct dmesg_component *dmesg_comp, struct bt_value *params)
+{
+       struct bt_value *read_from_stdin;
+       struct bt_value *path;
+       const char *path_str;
+       int ret = 0;
+
+       if (!params || !bt_value_is_map(params)) {
+               fprintf(stderr, "Expecting a map value as parameters.\n");
+               goto error;
+       }
+
+       read_from_stdin = bt_value_map_get(params, "read-from-stdin");
+       if (read_from_stdin) {
+               if (!bt_value_is_bool(read_from_stdin)) {
+                       fprintf(stderr, "Expecting a boolean value for `read-from-stdin` parameter.\n");
+                       goto error;
+               }
+
+               ret = bt_value_bool_get(read_from_stdin,
+                       &dmesg_comp->params.read_from_stdin);
+               assert(ret == 0);
+       }
+
+       path = bt_value_map_get(params, "path");
+       if (path) {
+               if (dmesg_comp->params.read_from_stdin) {
+                       fprintf(stderr, "Cannot specify both `read-from-stdin` and `path` parameters.\n");
+                       goto error;
+               }
+
+               if (!bt_value_is_string(path)) {
+                       fprintf(stderr, "Expecting a string value for `path` parameter.\n");
+                       goto error;
+               }
+
+               ret = bt_value_bool_get(path, &path_str);
+               assert(ret == 0);
+               g_string_assign(dmesg_comp->params.path, path_str);
+       } else {
+               if (!dmesg_comp->params.read_from_stdin) {
+                       fprintf(stderr, "Expecting `path` parameter or `read-from-stdin` parameter set to true.\n");
+                       goto error;
+               }
+       }
+
+       goto end;
+
+error:
+       ret = -1;
+
+end:
+       bt_put(read_from_stdin);
+       bt_put(path);
+       return ret;
+}
+
+static
+int create_stream()
+
+static
+void destroy_dmesg_component(struct dmesg_component *dmesg_comp)
+{
+       if (!dmesg_comp) {
+               return;
+       }
+
+       if (dmesg_comp->params.path) {
+               g_string_free(dmesg_comp->params.path, TRUE);
+       }
+
+       bt_put(dmesg_comp->packet);
+       bt_put(dmesg_comp->event_class);
+       bt_put(dmesg_comp->stream);
+       bt_put(dmesg_comp->cc_prio_map);
+       g_free(dmesg_comp);
+}
+
+BT_HIDDEN
+enum bt_component_status dmesg_init(struct bt_private_component *priv_comp,
+               struct bt_value *params, void *init_method_data)
+{
+       int ret = 0;
+       struct dmesg_component *dmesg_comp = g_new0(struct dmesg_component, 1);
+       enum bt_component_status status = BT_COMPONENT_STATUS_OK;
+
+       if (!dmesg_comp) {
+               goto error;
+       }
+
+       dmesg_comp->params.path = g_string_new(NULL);
+       if (!dmesg_comp->params.path) {
+               goto error;
+       }
+
+       ret = check_params(dmesg_comp, params);
+       if (ret) {
+               goto error;
+       }
+
+
+
+       goto end;
+
+error:
+       destroy_dmesg_component(dmesg_comp);
+       status = BT_COMPONENT_STATUS_ERROR;
+
+end:
+       return status;
+}
+
+BT_HIDDEN
+void dmesg_finalize(struct bt_private_component *priv_comp)
+{
+
+}
+
+BT_HIDDEN
+enum bt_notification_iterator_status dmesg_notif_iter_init(
+               struct bt_private_notification_iterator *priv_notif_iter,
+               struct bt_private_port *priv_port)
+{
+
+}
+
+BT_HIDDEN
+void dmesg_iterator_finalize(
+               struct bt_private_notification_iterator *priv_notif_iter)
+{
+
+}
+
+BT_HIDDEN
+struct bt_notification_iterator_next_return dmesg_notif_iter_next(
+               struct bt_private_notification_iterator *priv_notif_iter)
+{
+
+}
diff --git a/plugins/text/dmesg/dmesg.h b/plugins/text/dmesg/dmesg.h
new file mode 100644 (file)
index 0000000..1108cb1
--- /dev/null
@@ -0,0 +1,51 @@
+#ifndef BABELTRACE_PLUGIN_TEXT_DMESG_DMESG_H
+#define BABELTRACE_PLUGIN_TEXT_DMESG_DMESG_H
+
+/*
+ * Copyright 2017 Philippe Proulx <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/graph/component.h>
+#include <babeltrace/graph/clock-class-priority-map.h>
+
+BT_HIDDEN
+enum bt_component_status dmesg_init(struct bt_private_component *priv_comp,
+               struct bt_value *params, void *init_method_data);
+
+BT_HIDDEN
+void dmesg_finalize(struct bt_private_component *priv_comp);
+
+BT_HIDDEN
+enum bt_notification_iterator_status dmesg_notif_iter_init(
+               struct bt_private_notification_iterator *priv_notif_iter,
+               struct bt_private_port *priv_port);
+
+BT_HIDDEN
+void dmesg_iterator_finalize(
+               struct bt_private_notification_iterator *priv_notif_iter);
+
+BT_HIDDEN
+struct bt_notification_iterator_next_return dmesg_notif_iter_next(
+               struct bt_private_notification_iterator *priv_notif_iter);
+
+#endif /* BABELTRACE_PLUGIN_TEXT_DMESG_DMESG_H */
index 1449e7579c16c22f6b7fe55603fce861206c93da..ff982630c4c154ee91fcff49d9aa61efd7525f2d 100644 (file)
@@ -35,4 +35,4 @@ BT_PLUGIN_SINK_COMPONENT_CLASS_FINALIZE_METHOD(pretty, pretty_finalize);
 BT_PLUGIN_SINK_COMPONENT_CLASS_PORT_CONNECTED_METHOD(pretty,
        pretty_port_connected);
 BT_PLUGIN_SINK_COMPONENT_CLASS_DESCRIPTION(pretty,
-       "Pretty-printing text output (`text` format of Babeltrace 1)");
+       "Pretty-printing text output (`text` format of Babeltrace 1).");
index 3f596299e8833784690b0a055dd64b711b5feb34..c155d7715e1dbe1bf5ad54233f8a1b6d91115469 100644 (file)
@@ -38,12 +38,12 @@ BT_PLUGIN_SINK_COMPONENT_CLASS_FINALIZE_METHOD(dummy, dummy_finalize);
 BT_PLUGIN_SINK_COMPONENT_CLASS_PORT_CONNECTED_METHOD(dummy,
        dummy_port_connected);
 BT_PLUGIN_SINK_COMPONENT_CLASS_DESCRIPTION(dummy,
-       "Dummy sink component class: does absolutely nothing!");
+       "Consume notifications and discard them.");
 
 /* trimmer filter */
 BT_PLUGIN_FILTER_COMPONENT_CLASS(trimmer, trimmer_iterator_next);
 BT_PLUGIN_FILTER_COMPONENT_CLASS_DESCRIPTION(trimmer,
-       "Ensure that trace notifications outside of a given range are filtered-out.");
+       "Keep notifications that occur within a specific time range.");
 BT_PLUGIN_FILTER_COMPONENT_CLASS_INIT_METHOD(trimmer, trimmer_component_init);
 BT_PLUGIN_FILTER_COMPONENT_CLASS_FINALIZE_METHOD(trimmer, finalize_trimmer);
 BT_PLUGIN_FILTER_COMPONENT_CLASS_NOTIFICATION_ITERATOR_INIT_METHOD(trimmer,
@@ -56,7 +56,7 @@ BT_PLUGIN_FILTER_COMPONENT_CLASS_NOTIFICATION_ITERATOR_SEEK_TIME_METHOD(trimmer,
 /* muxer filter */
 BT_PLUGIN_FILTER_COMPONENT_CLASS(muxer, muxer_notif_iter_next);
 BT_PLUGIN_FILTER_COMPONENT_CLASS_DESCRIPTION(muxer,
-       "Notification multiplexer");
+       "Sort notifications from multiple input ports to a single output port by time.");
 BT_PLUGIN_FILTER_COMPONENT_CLASS_INIT_METHOD(muxer, muxer_init);
 BT_PLUGIN_FILTER_COMPONENT_CLASS_FINALIZE_METHOD(muxer, muxer_finalize);
 BT_PLUGIN_FILTER_COMPONENT_CLASS_PORT_DISCONNECTED_METHOD(muxer,
diff --git a/plugins/writer/Makefile.am b/plugins/writer/Makefile.am
deleted file mode 100644 (file)
index 5b219e3..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-AM_CFLAGS = $(PACKAGE_CFLAGS) -I$(top_srcdir)/include -I$(top_srcdir)/plugins \
-           -I$(top_srcdir)/plugins/libctfcopytrace
-
-SUBDIRS = .
-
-plugindir = "$(PLUGINSDIR)"
-plugin_LTLIBRARIES = libbabeltrace-plugin-ctf-writer.la
-
-# ctf-writer plugin
-libbabeltrace_plugin_ctf_writer_la_SOURCES = \
-       writer.c \
-       write.c \
-       writer.h
-
-libbabeltrace_plugin_ctf_writer_la_LDFLAGS = \
-       -version-info $(BABELTRACE_LIBRARY_VERSION)
-
-libbabeltrace_plugin_ctf_writer_la_LIBADD = \
-       $(top_builddir)/lib/libbabeltrace.la \
-       $(top_builddir)/plugins/libctfcopytrace/libctfcopytrace.la
-
-noinst_HEADERS = writer.h
diff --git a/plugins/writer/write.c b/plugins/writer/write.c
deleted file mode 100644 (file)
index 91b9289..0000000
+++ /dev/null
@@ -1,492 +0,0 @@
-/*
- * writer.c
- *
- * Babeltrace CTF Writer Output Plugin Event Handling
- *
- * 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/ctf-ir/event.h>
-#include <babeltrace/ctf-ir/packet.h>
-#include <babeltrace/ctf-ir/event-class.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/fields.h>
-#include <babeltrace/ctf-writer/stream-class.h>
-#include <babeltrace/ctf-writer/stream.h>
-
-#include <ctfcopytrace.h>
-
-#include "writer.h"
-
-static
-struct bt_ctf_stream_class *insert_new_stream_class(
-               struct writer_component *writer_component,
-               struct bt_ctf_writer *ctf_writer,
-               struct bt_ctf_stream_class *stream_class)
-{
-       struct bt_ctf_stream_class *writer_stream_class = NULL;
-       struct bt_ctf_trace *trace = NULL, *writer_trace = NULL;
-       enum bt_component_status ret;
-
-       trace = bt_ctf_stream_class_get_trace(stream_class);
-       if (!trace) {
-               fprintf(writer_component->err,
-                               "[error] %s in %s:%d\n", __func__, __FILE__,
-                               __LINE__);
-               goto error;
-       }
-
-       writer_trace = bt_ctf_writer_get_trace(ctf_writer);
-       if (!writer_trace) {
-               fprintf(writer_component->err,
-                               "[error] %s in %s:%d\n", __func__, __FILE__,
-                               __LINE__);
-               goto error;
-       }
-
-       ret = ctf_copy_clock_classes(writer_component->err, writer_trace,
-                       writer_stream_class, trace);
-       if (ret != BT_COMPONENT_STATUS_OK) {
-               fprintf(writer_component->err,
-                               "[error] %s in %s:%d\n", __func__, __FILE__,
-                               __LINE__);
-               goto error;
-       }
-
-       writer_stream_class = ctf_copy_stream_class(writer_component->err,
-                       stream_class, writer_trace, true);
-       if (!writer_stream_class) {
-               fprintf(writer_component->err, "[error] Failed to copy stream class\n");
-               fprintf(writer_component->err, "[error] %s in %s:%d\n",
-                               __func__, __FILE__, __LINE__);
-               goto error;
-       }
-
-       g_hash_table_insert(writer_component->stream_class_map,
-                       (gpointer) stream_class, writer_stream_class);
-
-       goto end;
-
-error:
-       BT_PUT(writer_stream_class);
-end:
-       bt_put(writer_trace);
-       bt_put(trace);
-       return writer_stream_class;
-}
-
-static
-struct bt_ctf_stream *insert_new_stream(
-               struct writer_component *writer_component,
-               struct bt_ctf_writer *ctf_writer,
-               struct bt_ctf_stream_class *stream_class,
-               struct bt_ctf_stream *stream)
-{
-       struct bt_ctf_stream *writer_stream = NULL;
-       struct bt_ctf_stream_class *writer_stream_class = NULL;
-
-       writer_stream_class = g_hash_table_lookup(
-                       writer_component->stream_class_map,
-                       (gpointer) stream_class);
-       if (!writer_stream_class) {
-               writer_stream_class = insert_new_stream_class(
-                               writer_component, ctf_writer, stream_class);
-               if (!writer_stream_class) {
-                       fprintf(writer_component->err, "[error] %s in %s:%d\n",
-                                       __func__, __FILE__, __LINE__);
-                       goto error;
-               }
-       }
-       bt_get(writer_stream_class);
-
-       writer_stream = bt_ctf_writer_create_stream(ctf_writer,
-                       writer_stream_class);
-       if (!writer_stream) {
-               fprintf(writer_component->err, "[error] %s in %s:%d\n",
-                               __func__, __FILE__, __LINE__);
-               goto error;
-       }
-
-       g_hash_table_insert(writer_component->stream_map, (gpointer) stream,
-                       writer_stream);
-
-       goto end;
-
-error:
-       BT_PUT(writer_stream);
-end:
-       bt_put(writer_stream_class);
-       return writer_stream;
-}
-
-static
-struct bt_ctf_stream *lookup_stream(struct writer_component *writer_component,
-               struct bt_ctf_stream *stream)
-{
-       return (struct bt_ctf_stream *) g_hash_table_lookup(
-                       writer_component->stream_map,
-                       (gpointer) stream);
-}
-
-static
-struct bt_ctf_event_class *get_event_class(struct writer_component *writer_component,
-               struct bt_ctf_stream_class *writer_stream_class,
-               struct bt_ctf_event_class *event_class)
-{
-       return bt_ctf_stream_class_get_event_class_by_id(writer_stream_class,
-                       bt_ctf_event_class_get_id(event_class));
-}
-
-struct bt_ctf_writer *insert_new_writer(
-               struct writer_component *writer_component,
-               struct bt_ctf_trace *trace)
-{
-       struct bt_ctf_writer *ctf_writer = NULL;
-       struct bt_ctf_trace *writer_trace = NULL;
-       char trace_name[PATH_MAX];
-       enum bt_component_status ret;
-
-       /* FIXME: replace with trace name when it will work. */
-       snprintf(trace_name, PATH_MAX, "%s/%s_%03d",
-                       writer_component->base_path->str,
-                       writer_component->trace_name_base->str,
-                       writer_component->trace_id++);
-       printf_verbose("CTF-Writer creating trace in %s\n", trace_name);
-
-       ctf_writer = bt_ctf_writer_create(trace_name);
-       if (!ctf_writer) {
-               fprintf(writer_component->err, "[error] %s in %s:%d\n",
-                               __func__, __FILE__, __LINE__);
-               goto error;
-       }
-
-       writer_trace = bt_ctf_writer_get_trace(ctf_writer);
-       if (!writer_trace) {
-               fprintf(writer_component->err,
-                               "[error] %s in %s:%d\n", __func__, __FILE__,
-                               __LINE__);
-               goto error;
-       }
-
-       ret = ctf_copy_trace(writer_component->err, trace, writer_trace);
-       if (ret != BT_COMPONENT_STATUS_OK) {
-               fprintf(writer_component->err, "[error] Failed to copy trace\n");
-               fprintf(writer_component->err, "[error] %s in %s:%d\n",
-                               __func__, __FILE__, __LINE__);
-               BT_PUT(ctf_writer);
-               goto end;
-       }
-       BT_PUT(writer_trace);
-
-       g_hash_table_insert(writer_component->trace_map, (gpointer) trace,
-                       ctf_writer);
-
-       goto end;
-
-error:
-       bt_put(writer_trace);
-       BT_PUT(ctf_writer);
-end:
-       return ctf_writer;
-}
-
-static
-struct bt_ctf_writer *get_writer(struct writer_component *writer_component,
-               struct bt_ctf_stream_class *stream_class)
-{
-       struct bt_ctf_trace *trace = NULL;
-       struct bt_ctf_writer *ctf_writer = NULL;
-
-       trace = bt_ctf_stream_class_get_trace(stream_class);
-       if (!trace) {
-               ctf_writer = NULL;
-               fprintf(writer_component->err, "[error] %s in %s:%d\n",
-                               __func__, __FILE__, __LINE__);
-               goto error;
-       }
-
-       ctf_writer = g_hash_table_lookup(writer_component->trace_map,
-                       (gpointer) trace);
-       if (!ctf_writer) {
-               ctf_writer = insert_new_writer(writer_component, trace);
-       }
-       bt_get(ctf_writer);
-       BT_PUT(trace);
-       goto end;
-
-error:
-       BT_PUT(ctf_writer);
-end:
-       return ctf_writer;
-}
-
-static
-struct bt_ctf_stream *get_writer_stream(
-               struct writer_component *writer_component,
-               struct bt_ctf_packet *packet, struct bt_ctf_stream *stream)
-{
-       struct bt_ctf_stream_class *stream_class = NULL;
-       struct bt_ctf_writer *ctf_writer = NULL;
-       struct bt_ctf_stream *writer_stream = NULL;
-
-       stream_class = bt_ctf_stream_get_class(stream);
-       if (!stream_class) {
-               fprintf(writer_component->err, "[error] %s in %s:%d\n",
-                               __func__, __FILE__, __LINE__);
-               goto error;
-       }
-
-       ctf_writer = get_writer(writer_component, stream_class);
-       if (!ctf_writer) {
-               fprintf(writer_component->err, "[error] %s in %s:%d\n",
-                               __func__, __FILE__, __LINE__);
-               goto error;
-       }
-
-       writer_stream = lookup_stream(writer_component, stream);
-       if (!writer_stream) {
-               writer_stream = insert_new_stream(writer_component, ctf_writer,
-                               stream_class, stream);
-       }
-       bt_get(writer_stream);
-
-       goto end;
-
-error:
-       BT_PUT(writer_stream);
-end:
-       bt_put(ctf_writer);
-       bt_put(stream_class);
-       return writer_stream;
-}
-
-BT_HIDDEN
-enum bt_component_status writer_new_packet(
-               struct writer_component *writer_component,
-               struct bt_ctf_packet *packet)
-{
-       struct bt_ctf_stream *stream = NULL, *writer_stream = NULL;
-       struct bt_ctf_field *writer_packet_context = NULL;
-       enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
-       int int_ret;
-
-       stream = bt_ctf_packet_get_stream(packet);
-       if (!stream) {
-               fprintf(writer_component->err, "[error] %s in %s:%d\n",
-                               __func__, __FILE__, __LINE__);
-               goto error;
-       }
-
-       writer_stream = get_writer_stream(writer_component, packet, stream);
-       if (!writer_stream) {
-               fprintf(writer_component->err, "[error] %s in %s:%d\n",
-                               __func__, __FILE__, __LINE__);
-               goto error;
-       }
-       BT_PUT(stream);
-
-       writer_packet_context = ctf_copy_packet_context(writer_component->err,
-                       packet, writer_stream);
-       if (!writer_packet_context) {
-               fprintf(writer_component->err, "[error] %s in %s:%d\n",
-                               __func__, __FILE__, __LINE__);
-               goto error;
-       }
-
-       int_ret = bt_ctf_stream_set_packet_context(writer_stream,
-                       writer_packet_context);
-       if (int_ret < 0) {
-               fprintf(writer_component->err, "[error] %s in %s:%d\n", __func__,
-                               __FILE__, __LINE__);
-               goto error;
-       }
-       BT_PUT(writer_stream);
-       BT_PUT(writer_packet_context);
-
-       goto end;
-
-error:
-       ret = BT_COMPONENT_STATUS_ERROR;
-end:
-       bt_put(writer_stream);
-       bt_put(writer_packet_context);
-       bt_put(stream);
-       return ret;
-}
-
-BT_HIDDEN
-enum bt_component_status writer_close_packet(
-               struct writer_component *writer_component,
-               struct bt_ctf_packet *packet)
-{
-       struct bt_ctf_stream *stream = NULL, *writer_stream = NULL;
-       enum bt_component_status ret;
-
-       stream = bt_ctf_packet_get_stream(packet);
-       if (!stream) {
-               fprintf(writer_component->err, "[error] %s in %s:%d\n",
-                               __func__, __FILE__, __LINE__);
-               goto error;
-       }
-
-       writer_stream = lookup_stream(writer_component, stream);
-       if (!writer_stream) {
-               fprintf(writer_component->err, "[error] %s in %s:%d\n",
-                               __func__, __FILE__, __LINE__);
-               goto error;
-       }
-       BT_PUT(stream);
-
-       bt_get(writer_stream);
-
-       ret = bt_ctf_stream_flush(writer_stream);
-       if (ret < 0) {
-               fprintf(writer_component->err,
-                               "[error] Failed to flush packet\n");
-               goto error;
-       }
-       BT_PUT(writer_stream);
-
-       ret = BT_COMPONENT_STATUS_OK;
-       goto end;
-
-error:
-       ret = BT_COMPONENT_STATUS_ERROR;
-end:
-       bt_put(writer_stream);
-       bt_put(stream);
-       return ret;
-}
-
-BT_HIDDEN
-enum bt_component_status writer_output_event(
-               struct writer_component *writer_component,
-               struct bt_ctf_event *event)
-{
-       enum bt_component_status ret;
-       struct bt_ctf_event_class *event_class = NULL, *writer_event_class = NULL;
-       struct bt_ctf_stream *stream = NULL, *writer_stream = NULL;
-       struct bt_ctf_stream_class *stream_class = NULL, *writer_stream_class = NULL;
-       struct bt_ctf_event *writer_event = NULL;
-       const char *event_name;
-       int int_ret;
-
-       event_class = bt_ctf_event_get_class(event);
-       if (!event_class) {
-               fprintf(writer_component->err, "[error] %s in %s:%d\n", __func__,
-                               __FILE__, __LINE__);
-               goto error;
-       }
-
-       event_name = bt_ctf_event_class_get_name(event_class);
-       if (!event_name) {
-               fprintf(writer_component->err, "[error] %s in %s:%d\n", __func__,
-                               __FILE__, __LINE__);
-               goto error;
-       }
-
-       stream = bt_ctf_event_get_stream(event);
-       if (!stream) {
-               fprintf(writer_component->err, "[error] %s in %s:%d\n", __func__,
-                               __FILE__, __LINE__);
-               goto error;
-       }
-
-       writer_stream = lookup_stream(writer_component, stream);
-       if (!writer_stream || !bt_get(writer_stream)) {
-               fprintf(writer_component->err, "[error] %s in %s:%d\n", __func__,
-                               __FILE__, __LINE__);
-               goto error;
-       }
-
-       stream_class = bt_ctf_event_class_get_stream_class(event_class);
-       if (!stream_class) {
-               fprintf(writer_component->err, "[error] %s in %s:%d\n", __func__,
-                               __FILE__, __LINE__);
-               goto error;
-       }
-
-       writer_stream_class = g_hash_table_lookup(
-                       writer_component->stream_class_map,
-                       (gpointer) stream_class);
-       if (!writer_stream_class || !bt_get(writer_stream_class)) {
-               fprintf(writer_component->err, "[error] %s in %s:%d\n", __func__,
-                               __FILE__, __LINE__);
-               goto error;
-       }
-
-       writer_event_class = get_event_class(writer_component,
-                       writer_stream_class, event_class);
-       if (!writer_event_class) {
-               writer_event_class = ctf_copy_event_class(writer_component->err,
-                               event_class);
-               if (!writer_event_class) {
-                       fprintf(writer_component->err, "[error] %s in %s:%d\n",
-                                       __func__, __FILE__, __LINE__);
-                       goto error;
-               }
-               int_ret = bt_ctf_stream_class_add_event_class(
-                               writer_stream_class, writer_event_class);
-               if (int_ret) {
-                       fprintf(writer_component->err, "[error] %s in %s:%d\n",
-                                       __func__, __FILE__, __LINE__);
-                       goto error;
-               }
-       }
-
-       writer_event = ctf_copy_event(writer_component->err, event,
-                       writer_event_class, true);
-       if (!writer_event) {
-               fprintf(writer_component->err, "[error] %s in %s:%d\n", __func__,
-                               __FILE__, __LINE__);
-               fprintf(writer_component->err, "[error] Failed to copy event %s\n",
-                               bt_ctf_event_class_get_name(writer_event_class));
-               goto error;
-       }
-
-       int_ret = bt_ctf_stream_append_event(writer_stream, writer_event);
-       if (int_ret < 0) {
-               fprintf(writer_component->err, "[error] %s in %s:%d\n", __func__,
-                               __FILE__, __LINE__);
-               fprintf(writer_component->err, "[error] Failed to append event %s\n",
-                               bt_ctf_event_class_get_name(writer_event_class));
-               goto error;
-       }
-
-       ret = BT_COMPONENT_STATUS_OK;
-       goto end;
-
-error:
-       ret = BT_COMPONENT_STATUS_ERROR;
-end:
-       bt_put(writer_event);
-       bt_put(writer_event_class);
-       bt_put(writer_stream_class);
-       bt_put(stream_class);
-       bt_put(writer_stream);
-       bt_put(stream);
-       bt_put(event_class);
-       return ret;
-}
diff --git a/plugins/writer/writer.c b/plugins/writer/writer.c
deleted file mode 100644 (file)
index 3bca09b..0000000
+++ /dev/null
@@ -1,329 +0,0 @@
-/*
- * writer.c
- *
- * Babeltrace CTF Writer Output Plugin
- *
- * 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/ctf-ir/packet.h>
-#include <babeltrace/plugin/plugin-dev.h>
-#include <babeltrace/graph/component.h>
-#include <babeltrace/graph/private-component.h>
-#include <babeltrace/graph/component-sink.h>
-#include <babeltrace/graph/private-component-sink.h>
-#include <babeltrace/graph/private-port.h>
-#include <babeltrace/graph/private-connection.h>
-#include <babeltrace/graph/notification.h>
-#include <babeltrace/graph/notification-iterator.h>
-#include <babeltrace/graph/notification-event.h>
-#include <babeltrace/graph/notification-packet.h>
-#include <plugins-common.h>
-#include <stdio.h>
-#include <stdbool.h>
-#include <glib.h>
-#include "writer.h"
-#include <assert.h>
-
-static
-void destroy_writer_component_data(struct writer_component *writer_component)
-{
-       bt_put(writer_component->input_iterator);
-       g_hash_table_destroy(writer_component->stream_map);
-       g_hash_table_destroy(writer_component->stream_class_map);
-       g_hash_table_destroy(writer_component->trace_map);
-       g_string_free(writer_component->base_path, true);
-       g_string_free(writer_component->trace_name_base, true);
-}
-
-static
-void finalize_writer_component(struct bt_private_component *component)
-{
-       struct writer_component *writer_component = (struct writer_component *)
-               bt_private_component_get_user_data(component);
-
-       destroy_writer_component_data(writer_component);
-       g_free(writer_component);
-}
-
-static
-void unref_stream_class(struct bt_ctf_stream_class *writer_stream_class)
-{
-       bt_put(writer_stream_class);
-}
-
-static
-void unref_stream(struct bt_ctf_stream_class *writer_stream)
-{
-       bt_put(writer_stream);
-}
-
-static
-void unref_trace(struct bt_ctf_writer *writer)
-{
-       bt_put(writer);
-}
-
-static
-struct writer_component *create_writer_component(void)
-{
-       struct writer_component *writer_component;
-
-       writer_component = g_new0(struct writer_component, 1);
-       if (!writer_component) {
-               goto end;
-       }
-
-       writer_component->err = stderr;
-       writer_component->trace_id = 0;
-       writer_component->trace_name_base = g_string_new("trace");
-       writer_component->processed_first_event = false;
-       if (!writer_component->trace_name_base) {
-               g_free(writer_component);
-               writer_component = NULL;
-               goto end;
-       }
-
-       /*
-        * Reader to writer corresponding structures.
-        */
-       writer_component->trace_map = g_hash_table_new_full(g_direct_hash,
-                       g_direct_equal, NULL, (GDestroyNotify) unref_trace);
-       writer_component->stream_class_map = g_hash_table_new_full(g_direct_hash,
-                       g_direct_equal, NULL, (GDestroyNotify) unref_stream_class);
-       writer_component->stream_map = g_hash_table_new_full(g_direct_hash,
-                       g_direct_equal, NULL, (GDestroyNotify) unref_stream);
-
-end:
-       return writer_component;
-}
-
-static
-enum bt_component_status handle_notification(
-               struct writer_component *writer_component,
-               struct bt_notification *notification)
-{
-       enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
-
-       if (!writer_component) {
-               ret = BT_COMPONENT_STATUS_ERROR;
-               goto end;
-       }
-
-       switch (bt_notification_get_type(notification)) {
-       case BT_NOTIFICATION_TYPE_PACKET_BEGIN:
-       {
-               struct bt_ctf_packet *packet =
-                       bt_notification_packet_begin_get_packet(notification);
-
-               if (!packet) {
-                       ret = BT_COMPONENT_STATUS_ERROR;
-                       goto end;
-               }
-
-               ret = writer_new_packet(writer_component, packet);
-               bt_put(packet);
-               break;
-       }
-       case BT_NOTIFICATION_TYPE_PACKET_END:
-       {
-               struct bt_ctf_packet *packet =
-                       bt_notification_packet_end_get_packet(notification);
-
-               if (!packet) {
-                       ret = BT_COMPONENT_STATUS_ERROR;
-                       goto end;
-               }
-               ret = writer_close_packet(writer_component, packet);
-               bt_put(packet);
-               break;
-       }
-       case BT_NOTIFICATION_TYPE_EVENT:
-       {
-               struct bt_ctf_event *event = bt_notification_event_get_event(
-                               notification);
-
-               if (!event) {
-                       ret = BT_COMPONENT_STATUS_ERROR;
-                       goto end;
-               }
-               ret = BT_COMPONENT_STATUS_OK;
-               ret = writer_output_event(writer_component, event);
-               bt_put(event);
-               if (ret != BT_COMPONENT_STATUS_OK) {
-                       goto end;
-               }
-               break;
-       }
-       case BT_NOTIFICATION_TYPE_STREAM_END:
-               break;
-       default:
-               puts("Unhandled notification type");
-       }
-end:
-       return ret;
-}
-
-static
-void writer_component_port_connected(
-               struct bt_private_component *component,
-               struct bt_private_port *self_port,
-               struct bt_port *other_port)
-{
-       struct bt_private_connection *connection;
-       struct writer_component *writer;
-
-       writer = bt_private_component_get_user_data(component);
-       assert(writer);
-       assert(!writer->input_iterator);
-       connection = bt_private_port_get_private_connection(self_port);
-       assert(connection);
-       writer->input_iterator =
-               bt_private_connection_create_notification_iterator(connection,
-                       NULL);
-
-       if (!writer->input_iterator) {
-               writer->error = true;
-       }
-
-       bt_put(connection);
-}
-
-static
-enum bt_component_status run(struct bt_private_component *component)
-{
-       enum bt_component_status ret;
-       struct bt_notification *notification = NULL;
-       struct bt_notification_iterator *it;
-       struct writer_component *writer_component =
-               bt_private_component_get_user_data(component);
-
-       it = writer_component->input_iterator;
-       assert(it);
-
-       if (unlikely(writer_component->error)) {
-               ret = BT_COMPONENT_STATUS_ERROR;
-               goto end;
-       }
-
-       if (likely(writer_component->processed_first_event)) {
-               enum bt_notification_iterator_status it_ret;
-
-               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(writer_component->input_iterator);
-                               goto end;
-                       default:
-                               break;
-               }
-       }
-
-       notification = bt_notification_iterator_get_notification(it);
-       if (!notification) {
-               ret = BT_COMPONENT_STATUS_ERROR;
-               goto end;
-       }
-
-       ret = handle_notification(writer_component, notification);
-       writer_component->processed_first_event = true;
-end:
-       bt_put(notification);
-       return ret;
-}
-
-static
-enum bt_component_status writer_component_init(
-       struct bt_private_component *component, struct bt_value *params,
-       UNUSED_VAR void *init_method_data)
-{
-       enum bt_component_status ret;
-       enum bt_value_status value_ret;
-       struct writer_component *writer_component = create_writer_component();
-       struct bt_value *value = NULL;
-       const char *path;
-       void *priv_port;
-
-       if (!writer_component) {
-               ret = BT_COMPONENT_STATUS_NOMEM;
-               goto end;
-       }
-
-       priv_port = bt_private_component_sink_add_input_private_port(component,
-               "in", NULL);
-       if (!priv_port) {
-               ret = BT_COMPONENT_STATUS_NOMEM;
-               goto end;
-       }
-
-       bt_put(priv_port);
-
-       value = bt_value_map_get(params, "path");
-       if (!value || bt_value_is_null(value) || !bt_value_is_string(value)) {
-               fprintf(writer_component->err,
-                               "[error] output path parameter required\n");
-               ret = BT_COMPONENT_STATUS_INVALID;
-               goto error;
-       }
-
-       value_ret = bt_value_string_get(value, &path);
-       if (value_ret != BT_VALUE_STATUS_OK) {
-               ret = BT_COMPONENT_STATUS_INVALID;
-               goto error;
-       }
-       bt_put(value);
-
-       writer_component->base_path = g_string_new(path);
-       if (!writer_component) {
-               ret = BT_COMPONENT_STATUS_ERROR;
-               goto error;
-       }
-
-       ret = bt_private_component_set_user_data(component, writer_component);
-       if (ret != BT_COMPONENT_STATUS_OK) {
-               goto error;
-       }
-
-end:
-       return ret;
-error:
-       destroy_writer_component_data(writer_component);
-       g_free(writer_component);
-       return ret;
-}
-
-/* Initialize plug-in entry points. */
-BT_PLUGIN(writer);
-BT_PLUGIN_DESCRIPTION("Babeltrace CTF-Writer output plug-in.");
-BT_PLUGIN_AUTHOR("Jérémie Galarneau");
-BT_PLUGIN_LICENSE("MIT");
-BT_PLUGIN_SINK_COMPONENT_CLASS(writer, run);
-BT_PLUGIN_SINK_COMPONENT_CLASS_INIT_METHOD(writer, writer_component_init);
-BT_PLUGIN_SINK_COMPONENT_CLASS_PORT_CONNECTED_METHOD(writer,
-               writer_component_port_connected);
-BT_PLUGIN_SINK_COMPONENT_CLASS_FINALIZE_METHOD(writer, finalize_writer_component);
-BT_PLUGIN_SINK_COMPONENT_CLASS_DESCRIPTION(writer, "Formats CTF-IR to CTF.");
diff --git a/plugins/writer/writer.h b/plugins/writer/writer.h
deleted file mode 100644 (file)
index 6f6b8a4..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-#ifndef BABELTRACE_PLUGIN_WRITER_H
-#define BABELTRACE_PLUGIN_WRITER_H
-
-/*
- * BabelTrace - CTF Writer Output 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/graph/component.h>
-#include <babeltrace/ctf-writer/writer.h>
-
-struct writer_component {
-       GString *base_path;
-       GString *trace_name_base;
-       /* For the directory name suffix. */
-       int trace_id;
-       /* Map between struct bt_ctf_trace and struct bt_ctf_writer. */
-       GHashTable *trace_map;
-       /* Map between reader and writer stream. */
-       GHashTable *stream_map;
-       /* Map between reader and writer stream class. */
-       GHashTable *stream_class_map;
-       FILE *err;
-       struct bt_notification_iterator *input_iterator;
-       bool processed_first_event;
-       bool error;
-};
-
-BT_HIDDEN
-enum bt_component_status writer_output_event(struct writer_component *writer,
-               struct bt_ctf_event *event);
-BT_HIDDEN
-enum bt_component_status writer_new_packet(struct writer_component *writer,
-               struct bt_ctf_packet *packet);
-BT_HIDDEN
-enum bt_component_status writer_close_packet(struct writer_component *writer,
-               struct bt_ctf_packet *packet);
-
-#endif /* BABELTRACE_PLUGIN_WRITER_H */
This page took 0.130047 seconds and 4 git commands to generate.