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
-SUBDIRS = libctfcopytrace ctf text utils writer
+SUBDIRS = libctfcopytrace ctf text utils
if ENABLE_DEBUG_INFO
SUBDIRS += lttng-utils
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
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
--- /dev/null
+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
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+#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 */
--- /dev/null
+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
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+#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 */
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+#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 */
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+#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 */
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * 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);
+ }
+}
--- /dev/null
+#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 */
--- /dev/null
+#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 */
+++ /dev/null
-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
+++ /dev/null
-/*
- * 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;
-}
+++ /dev/null
-#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 */
+++ /dev/null
-/*
- * 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;
-}
+++ /dev/null
-#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 */
+++ /dev/null
-/*
- * 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;
-}
+++ /dev/null
-#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 */
+++ /dev/null
-/*
- * 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 */
+++ /dev/null
-/*
- * 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);
- }
-}
+++ /dev/null
-#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 */
+++ /dev/null
-#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 */
#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);
*/
#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);
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.");
--- /dev/null
+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
--- /dev/null
+/*
+ * 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)
+{
+
+}
--- /dev/null
+#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 */
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).");
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,
/* 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,
+++ /dev/null
-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
+++ /dev/null
-/*
- * 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;
-}
+++ /dev/null
-/*
- * 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.");
+++ /dev/null
-#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 */