Big cleanup of network live
authorJulien Desfossez <jdesfossez@efficios.com>
Thu, 30 Jan 2014 04:20:25 +0000 (23:20 -0500)
committerJulien Desfossez <jdesfossez@efficios.com>
Thu, 30 Jan 2014 04:20:25 +0000 (23:20 -0500)
Sync with the babeltrace tree to use the same code base for network live
streaming.

Use :
$ lttngtop -r net://localhost
to list the sessions on localhost and then
$ lttngtop -r net://localhost/42
to attach to session 42 on localhost for example.

Signed-off-by: Julien Desfossez <jdesfossez@efficios.com>
29 files changed:
lib/babeltrace/ctf-writer/clock-internal.h [new file with mode: 0644]
lib/babeltrace/ctf-writer/clock.h [new file with mode: 0644]
lib/babeltrace/ctf-writer/event-fields-internal.h [new file with mode: 0644]
lib/babeltrace/ctf-writer/event-fields.h [new file with mode: 0644]
lib/babeltrace/ctf-writer/event-internal.h [new file with mode: 0644]
lib/babeltrace/ctf-writer/event-types-internal.h [new file with mode: 0644]
lib/babeltrace/ctf-writer/event-types.h [new file with mode: 0644]
lib/babeltrace/ctf-writer/event.h [new file with mode: 0644]
lib/babeltrace/ctf-writer/functor-internal.h [new file with mode: 0644]
lib/babeltrace/ctf-writer/ref-internal.h [new file with mode: 0644]
lib/babeltrace/ctf-writer/stream-internal.h [new file with mode: 0644]
lib/babeltrace/ctf-writer/stream.h [new file with mode: 0644]
lib/babeltrace/ctf-writer/writer-internal.h [new file with mode: 0644]
lib/babeltrace/ctf-writer/writer.h [new file with mode: 0644]
lib/babeltrace/ctf/ctf-index.h [new file with mode: 0644]
lib/babeltrace/ctf/events-internal.h
lib/babeltrace/ctf/events.h
lib/babeltrace/ctf/types.h
lib/babeltrace/format.h
lib/babeltrace/iterator.h
lib/babeltrace/types.h
src/Makefile.am
src/lttng-live-functions.c [new file with mode: 0644]
src/lttng-live-functions.h [new file with mode: 0644]
src/lttng-viewer.h
src/lttngtop.c
src/lttngtop.h [new file with mode: 0644]
src/network-live.c
src/network-live.h

diff --git a/lib/babeltrace/ctf-writer/clock-internal.h b/lib/babeltrace/ctf-writer/clock-internal.h
new file mode 100644 (file)
index 0000000..c60e5c0
--- /dev/null
@@ -0,0 +1,65 @@
+#ifndef BABELTRACE_CTF_WRITER_CLOCK_INTERNAL_H
+#define BABELTRACE_CTF_WRITER_CLOCK_INTERNAL_H
+
+/*
+ * BabelTrace - CTF Writer: Clock internal
+ *
+ * Copyright 2013 EfficiOS Inc.
+ *
+ * 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-writer/ref-internal.h>
+#include <babeltrace/ctf-writer/clock.h>
+#include <babeltrace/ctf-writer/writer-internal.h>
+#include <babeltrace/babeltrace-internal.h>
+#include <glib.h>
+#include <uuid/uuid.h>
+
+struct bt_ctf_clock {
+       struct bt_ctf_ref ref_count;
+       GString *name;
+       GString *description;
+       uint64_t frequency;
+       uint64_t precision;
+       uint64_t offset_s;      /* Offset in seconds */
+       uint64_t offset;        /* Offset in ticks */
+       uint64_t time;          /* Current clock value */
+       uuid_t uuid;
+       int absolute;
+       /*
+        * A clock's properties can't be modified once it is added to a stream
+        * class.
+        */
+       int frozen;
+};
+
+BT_HIDDEN
+void bt_ctf_clock_freeze(struct bt_ctf_clock *clock);
+
+BT_HIDDEN
+void bt_ctf_clock_serialize(struct bt_ctf_clock *clock,
+               struct metadata_context *context);
+
+BT_HIDDEN
+uint64_t bt_ctf_clock_get_time(struct bt_ctf_clock *clock);
+
+#endif /* BABELTRACE_CTF_WRITER_CLOCK_INTERNAL_H */
diff --git a/lib/babeltrace/ctf-writer/clock.h b/lib/babeltrace/ctf-writer/clock.h
new file mode 100644 (file)
index 0000000..7cfc073
--- /dev/null
@@ -0,0 +1,166 @@
+#ifndef BABELTRACE_CTF_WRITER_CLOCK_H
+#define BABELTRACE_CTF_WRITER_CLOCK_H
+
+/*
+ * BabelTrace - CTF Writer: Clock
+ *
+ * Copyright 2013 EfficiOS Inc.
+ *
+ * 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.
+ *
+ * The Common Trace Format (CTF) Specification is available at
+ * http://www.efficios.com/ctf
+ */
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct bt_ctf_clock;
+
+/*
+ * bt_ctf_clock_create: create a clock.
+ *
+ * Allocate a new clock setting its reference count to 1.
+ *
+ * @param name Name of the clock (will be copied).
+ *
+ * Returns an allocated clock on success, NULL on error.
+ */
+extern struct bt_ctf_clock *bt_ctf_clock_create(const char *name);
+
+/*
+ * bt_ctf_clock_set_description: set a clock's description.
+ *
+ * Set the clock's description. The description appears in the clock's TSDL
+ * meta-data.
+ *
+ * @param clock Clock instance.
+ * @param desc Description of the clock.
+ *
+ * Returns 0 on success, a negative value on error.
+ */
+extern int bt_ctf_clock_set_description(struct bt_ctf_clock *clock,
+               const char *desc);
+
+/*
+ * bt_ctf_clock_set_frequency: set a clock's frequency.
+ *
+ * Set the clock's frequency (Hz).
+ *
+ * @param clock Clock instance.
+ * @param freq Clock's frequency in Hz, defaults to 1 000 000 000 Hz (1ns).
+ *
+ * Returns 0 on success, a negative value on error.
+ */
+extern int bt_ctf_clock_set_frequency(struct bt_ctf_clock *clock,
+               uint64_t freq);
+
+/*
+ * bt_ctf_clock_set_precision: set a clock's precision.
+ *
+ * Set the clock's precision.
+ *
+ * @param clock Clock instance.
+ * @param precision Clock's precision in clock ticks, defaults to 1.
+ *
+ * Returns 0 on success, a negative value on error.
+ */
+extern int bt_ctf_clock_set_precision(struct bt_ctf_clock *clock,
+               uint64_t precision);
+
+/*
+ * bt_ctf_clock_set_offset_s: set a clock's offset in seconds.
+ *
+ * Set the clock's offset in seconds from POSIX.1 Epoch, 1970-01-01,
+ * defaults to 0.
+ *
+ * @param clock Clock instance.
+ * @param offset_s Clock's offset in seconds, defaults to 0.
+ *
+ * Returns 0 on success, a negative value on error.
+ */
+extern int bt_ctf_clock_set_offset_s(struct bt_ctf_clock *clock,
+               uint64_t offset_s);
+
+
+/*
+ * bt_ctf_clock_set_offset: set a clock's offset in ticks.
+ *
+ * Set the clock's offset in ticks from Epoch + offset_s.
+ *
+ * @param clock Clock instance.
+ * @param offset Clock's offset in ticks from Epoch + offset_s, defaults to 0.
+ *
+ * Returns 0 on success, a negative value on error.
+ */
+extern int bt_ctf_clock_set_offset(struct bt_ctf_clock *clock,
+               uint64_t offset);
+
+/*
+ * bt_ctf_clock_set_is_absolute: set a clock's absolute attribute.
+ *
+ * A clock is absolute if the clock is a global reference across the trace's
+ * other clocks.
+ *
+ * @param clock Clock instance.
+ * @param is_absolute Clock's absolute attribute, defaults to FALSE.
+ *
+ * Returns 0 on success, a negative value on error.
+ */
+extern int bt_ctf_clock_set_is_absolute(struct bt_ctf_clock *clock,
+               int is_absolute);
+
+/*
+ * bt_ctf_clock_set_time: set a clock's current time value.
+ *
+ * Set the current time in nanoseconds since the clock's origin (offset and
+ * offset_s attributes). The clock's value will be sampled as events are
+ * appended to a stream.
+ *
+ * Returns 0 on success, a negative value on error.
+ */
+extern int bt_ctf_clock_set_time(struct bt_ctf_clock *clock, uint64_t time);
+
+/*
+ * bt_ctf_clock_get and bt_ctf_clock_put: increment and decrement the
+ * refcount of the clock
+ *
+ * These functions ensure that the clock won't be destroyed when it
+ * is in use. The same number of get and put (plus one extra put to
+ * release the initial reference done at creation) has to be done to
+ * destroy a clock.
+ *
+ * When the clock refcount is decremented to 0 by a bt_ctf_clock_put,
+ * the clock is freed.
+ *
+ * @param clock Clock instance.
+ */
+extern void bt_ctf_clock_get(struct bt_ctf_clock *clock);
+extern void bt_ctf_clock_put(struct bt_ctf_clock *clock);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BABELTRACE_CTF_WRITER_CLOCK_H */
diff --git a/lib/babeltrace/ctf-writer/event-fields-internal.h b/lib/babeltrace/ctf-writer/event-fields-internal.h
new file mode 100644 (file)
index 0000000..9f2670d
--- /dev/null
@@ -0,0 +1,100 @@
+#ifndef BABELTRACE_CTF_WRITER_EVENT_FIELDS_INTERNAL_H
+#define BABELTRACE_CTF_WRITER_EVENT_FIELDS_INTERNAL_H
+
+/*
+ * BabelTrace - CTF Writer: Event Fields internal
+ *
+ * Copyright 2013 EfficiOS Inc.
+ *
+ * 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-writer/ref-internal.h>
+#include <babeltrace/ctf-writer/event-fields.h>
+#include <babeltrace/babeltrace-internal.h>
+#include <babeltrace/ctf/types.h>
+#include <glib.h>
+
+struct bt_ctf_field {
+       struct bt_ctf_ref ref_count;
+       struct bt_ctf_field_type *type;
+       int payload_set;
+};
+
+struct bt_ctf_field_integer {
+       struct bt_ctf_field parent;
+       struct definition_integer definition;
+};
+
+struct bt_ctf_field_enumeration {
+       struct bt_ctf_field parent;
+       struct bt_ctf_field *payload;
+};
+
+struct bt_ctf_field_floating_point {
+       struct bt_ctf_field parent;
+       struct definition_float definition;
+       struct definition_integer sign, mantissa, exp;
+};
+
+struct bt_ctf_field_structure {
+       struct bt_ctf_field parent;
+       GHashTable *field_name_to_index;
+       GPtrArray *fields; /* Array of pointers to struct bt_ctf_field */
+};
+
+struct bt_ctf_field_variant {
+       struct bt_ctf_field parent;
+       struct bt_ctf_field *tag;
+       struct bt_ctf_field *payload;
+};
+
+struct bt_ctf_field_array {
+       struct bt_ctf_field parent;
+       GPtrArray *elements; /* Array of pointers to struct bt_ctf_field */
+};
+
+struct bt_ctf_field_sequence {
+       struct bt_ctf_field parent;
+       struct bt_ctf_field *length;
+       GPtrArray *elements; /* Array of pointers to struct bt_ctf_field */
+};
+
+struct bt_ctf_field_string {
+       struct bt_ctf_field parent;
+       GString *payload;
+};
+
+/*
+ * Set a field's value with an already allocated field instance.
+ */
+BT_HIDDEN
+int bt_ctf_field_structure_set_field(struct bt_ctf_field *structure,
+               const char *name, struct bt_ctf_field *value);
+
+BT_HIDDEN
+int bt_ctf_field_validate(struct bt_ctf_field *field);
+
+BT_HIDDEN
+int bt_ctf_field_serialize(struct bt_ctf_field *field,
+               struct ctf_stream_pos *pos);
+
+#endif /* BABELTRACE_CTF_WRITER_EVENT_FIELDS_INTERNAL_H */
diff --git a/lib/babeltrace/ctf-writer/event-fields.h b/lib/babeltrace/ctf-writer/event-fields.h
new file mode 100644 (file)
index 0000000..8d3190b
--- /dev/null
@@ -0,0 +1,218 @@
+#ifndef BABELTRACE_CTF_WRITER_EVENT_FIELDS_H
+#define BABELTRACE_CTF_WRITER_EVENT_FIELDS_H
+
+/*
+ * BabelTrace - CTF Writer: Event Fields
+ *
+ * Copyright 2013 EfficiOS Inc.
+ *
+ * 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.
+ *
+ * The Common Trace Format (CTF) Specification is available at
+ * http://www.efficios.com/ctf
+ */
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct bt_ctf_event_class;
+struct bt_ctf_event;
+struct bt_ctf_field;
+struct bt_ctf_field_type;
+
+/*
+ * bt_ctf_field_create: create an instance of a field.
+ *
+ * Allocate a new field of the type described by the bt_ctf_field_type
+ * structure.The creation of a field sets its reference count to 1.
+ *
+ * @param type Field type to be instanciated.
+ *
+ * Returns an allocated field on success, NULL on error.
+ */
+extern struct bt_ctf_field *bt_ctf_field_create(
+               struct bt_ctf_field_type *type);
+
+/*
+ * bt_ctf_field_structure_get_field: get a structure's field.
+ *
+ * Get the structure's field corresponding to the provided field name.
+ * bt_ctf_field_put() must be called on the returned value.
+ *
+ * @param structure Structure field instance.
+ * @param name Name of the field in the provided structure.
+ *
+ * Returns a field instance on success, NULL on error.
+ */
+extern struct bt_ctf_field *bt_ctf_field_structure_get_field(
+               struct bt_ctf_field *structure, const char *name);
+
+/*
+ * bt_ctf_field_array_get_field: get an array's field at position "index".
+ *
+ * Return the array's field at position "index". bt_ctf_field_put() must be
+ * called on the returned value.
+ *
+ * @param array Array field instance.
+ * @param index Position of the array's desired element.
+ *
+ * Returns a field instance on success, NULL on error.
+ */
+extern struct bt_ctf_field *bt_ctf_field_array_get_field(
+               struct bt_ctf_field *array, uint64_t index);
+
+/*
+ * bt_ctf_field_sequence_set_length: set a sequence's length.
+ *
+ * Set the sequence's length field.
+ *
+ * @param sequence Sequence field instance.
+ * @param length_field Integer field instance indicating the sequence's length.
+ *
+ * Returns a field instance on success, NULL on error.
+ */
+extern int bt_ctf_field_sequence_set_length(struct bt_ctf_field *sequence,
+               struct bt_ctf_field *length_field);
+
+/*
+ * bt_ctf_field_sequence_get_field: get a sequence's field at position "index".
+ *
+ * Return the sequence's field at position "index". The sequence's length must
+ * have been set prior to calling this function using
+ * bt_ctf_field_sequence_set_length().
+ * bt_ctf_field_put() must be called on the returned value.
+ *
+ * @param array Sequence field instance.
+ * @param index Position of the sequence's desired element.
+ *
+ * Returns a field instance on success, NULL on error.
+ */
+extern struct bt_ctf_field *bt_ctf_field_sequence_get_field(
+               struct bt_ctf_field *sequence, uint64_t index);
+
+/*
+ * bt_ctf_field_variant_get_field: get a variant's selected field.
+ *
+ * Return the variant's selected field. The "tag" field is the selector enum
+ * field. bt_ctf_field_put() must be called on the returned value.
+ *
+ * @param variant Variant field instance.
+ * @param tag Selector enumeration field.
+ *
+ * Returns a field instance on success, NULL on error.
+ */
+extern struct bt_ctf_field *bt_ctf_field_variant_get_field(
+               struct bt_ctf_field *variant, struct bt_ctf_field *tag);
+
+/*
+ * bt_ctf_field_enumeration_get_container: get an enumeration field's container.
+ *
+ * Return the enumeration's underlying container field (an integer).
+ * bt_ctf_field_put() must be called on the returned value.
+ *
+ * @param enumeration Enumeration field instance.
+ *
+ * Returns a field instance on success, NULL on error.
+ */
+extern struct bt_ctf_field *bt_ctf_field_enumeration_get_container(
+               struct bt_ctf_field *enumeration);
+
+/*
+ * bt_ctf_field_signed_integer_set_value: set a signed integer field's value
+ *
+ * Set a signed integer field's value. The value is checked to make sure it
+ * can be stored in the underlying field.
+ *
+ * @param integer Signed integer field instance.
+ * @param value Signed integer field value.
+ *
+ * Returns 0 on success, a negative value on error.
+ */
+extern int bt_ctf_field_signed_integer_set_value(struct bt_ctf_field *integer,
+               int64_t value);
+
+/*
+ * bt_ctf_field_unsigned_integer_set_value: set unsigned integer field's value
+ *
+ * Set an unsigned integer field's value. The value is checked to make sure it
+ * can be stored in the underlying field.
+ *
+ * @param integer Unsigned integer field instance.
+ * @param value Unsigned integer field value.
+ *
+ * Returns 0 on success, a negative value on error.
+ */
+extern int bt_ctf_field_unsigned_integer_set_value(struct bt_ctf_field *integer,
+               uint64_t value);
+
+/*
+ * bt_ctf_field_floating_point_set_value: set a floating point field's value
+ *
+ * Set a floating point field's value. The underlying type may not support the
+ * double's full precision.
+ *
+ * @param floating_point Floating point field instance.
+ * @param value Floating point field value.
+ *
+ * Returns 0 on success, a negative value on error.
+ */
+extern int bt_ctf_field_floating_point_set_value(
+               struct bt_ctf_field *floating_point,
+               double value);
+
+/*
+ * bt_ctf_field_string_set_value: set a string field's value
+ *
+ * Set a string field's value.
+ *
+ * @param string String field instance.
+ * @param value String field value (will be copied).
+ *
+ * Returns 0 on success, a negative value on error.
+ */
+extern int bt_ctf_field_string_set_value(struct bt_ctf_field *string,
+               const char *value);
+
+/*
+ * bt_ctf_field_get and bt_ctf_field_put: increment and decrement the
+ * field's reference count.
+ *
+ * These functions ensure that the field won't be destroyed when it
+ * is in use. The same number of get and put (plus one extra put to
+ * release the initial reference done at creation) have to be done to
+ * destroy a field.
+ *
+ * When the field's reference count is decremented to 0 by a bt_ctf_field_put,
+ * the field is freed.
+ *
+ * @param field Field instance.
+ */
+extern void bt_ctf_field_get(struct bt_ctf_field *field);
+extern void bt_ctf_field_put(struct bt_ctf_field *field);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BABELTRACE_CTF_WRITER_EVENT_FIELDS_H */
diff --git a/lib/babeltrace/ctf-writer/event-internal.h b/lib/babeltrace/ctf-writer/event-internal.h
new file mode 100644 (file)
index 0000000..b84c3dd
--- /dev/null
@@ -0,0 +1,90 @@
+#ifndef BABELTRACE_CTF_WRITER_EVENT_INTERNAL_H
+#define BABELTRACE_CTF_WRITER_EVENT_INTERNAL_H
+
+/*
+ * BabelTrace - CTF Writer: Event internal
+ *
+ * Copyright 2013 EfficiOS Inc.
+ *
+ * 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-writer/ref-internal.h>
+#include <babeltrace/ctf-writer/event-types.h>
+#include <babeltrace/ctf-writer/event-fields.h>
+#include <babeltrace/babeltrace-internal.h>
+#include <babeltrace/ctf/types.h>
+#include <glib.h>
+
+struct bt_ctf_event_class {
+       struct bt_ctf_ref ref_count;
+       GQuark name;
+       int id_set;
+       uint32_t id;
+       int stream_id_set;
+       uint32_t stream_id;
+       /* Structure type containing the event's context */
+       struct bt_ctf_field_type *context;
+       /* Structure type containing the event's fields */
+       struct bt_ctf_field_type *fields;
+       int frozen;
+};
+
+struct bt_ctf_event {
+       struct bt_ctf_ref ref_count;
+       uint64_t timestamp;
+       struct bt_ctf_event_class *event_class;
+       struct bt_ctf_field *context_payload;
+       struct bt_ctf_field *fields_payload;
+};
+
+BT_HIDDEN
+void bt_ctf_event_class_freeze(struct bt_ctf_event_class *event_class);
+
+BT_HIDDEN
+int bt_ctf_event_class_set_id(struct bt_ctf_event_class *event_class,
+               uint32_t id);
+
+BT_HIDDEN
+uint32_t bt_ctf_event_class_get_id(struct bt_ctf_event_class *event_class);
+
+BT_HIDDEN
+int bt_ctf_event_class_set_stream_id(struct bt_ctf_event_class *event_class,
+               uint32_t id);
+
+BT_HIDDEN
+int bt_ctf_event_class_serialize(struct bt_ctf_event_class *event_class,
+               struct metadata_context *context);
+
+BT_HIDDEN
+int bt_ctf_event_validate(struct bt_ctf_event *event);
+
+BT_HIDDEN
+int bt_ctf_event_serialize(struct bt_ctf_event *event,
+               struct ctf_stream_pos *pos);
+
+BT_HIDDEN
+int bt_ctf_event_set_timestamp(struct bt_ctf_event *event, uint64_t timestamp);
+
+BT_HIDDEN
+uint64_t bt_ctf_event_get_timestamp(struct bt_ctf_event *event);
+
+#endif /* BABELTRACE_CTF_WRITER_EVENT_INTERNAL_H */
diff --git a/lib/babeltrace/ctf-writer/event-types-internal.h b/lib/babeltrace/ctf-writer/event-types-internal.h
new file mode 100644 (file)
index 0000000..a937c78
--- /dev/null
@@ -0,0 +1,153 @@
+#ifndef BABELTRACE_CTF_WRITER_EVENT_TYPES_INTERNAL_H
+#define BABELTRACE_CTF_WRITER_EVENT_TYPES_INTERNAL_H
+
+/*
+ * BabelTrace - CTF Writer: Event types internal
+ *
+ * Copyright 2013 EfficiOS Inc.
+ *
+ * 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-writer/event-types.h>
+#include <babeltrace/ctf-writer/ref-internal.h>
+#include <babeltrace/ctf-writer/event-fields.h>
+#include <babeltrace/ctf-writer/writer.h>
+#include <babeltrace/ctf-writer/writer-internal.h>
+#include <babeltrace/babeltrace-internal.h>
+#include <babeltrace/types.h>
+#include <babeltrace/ctf/events.h>
+#include <glib.h>
+
+typedef void(*type_freeze_func)(struct bt_ctf_field_type *);
+typedef int(*type_serialize_func)(struct bt_ctf_field_type *,
+               struct metadata_context *);
+
+struct bt_ctf_field_type {
+       struct bt_ctf_ref ref_count;
+       struct bt_declaration *declaration;
+       type_freeze_func freeze;
+       type_serialize_func serialize;
+       /*
+        * A type can't be modified once it is added to an event or after a
+        * a field has been instanciated from it.
+        */
+       int frozen;
+};
+
+struct bt_ctf_field_type_integer {
+       struct bt_ctf_field_type parent;
+       struct declaration_integer declaration;
+};
+
+struct enumeration_mapping {
+       int64_t range_start;
+       int64_t range_end;
+       GQuark string;
+};
+
+struct bt_ctf_field_type_enumeration {
+       struct bt_ctf_field_type parent;
+       struct bt_ctf_field_type *container;
+       GPtrArray *entries; /* Array of pointers to struct enum_mapping */
+       struct declaration_enum declaration;
+};
+
+struct bt_ctf_field_type_floating_point {
+       struct bt_ctf_field_type parent;
+       struct declaration_float declaration;
+       struct declaration_integer sign;
+       struct declaration_integer mantissa;
+       struct declaration_integer exp;
+};
+
+struct structure_field {
+       GQuark name;
+       struct bt_ctf_field_type *type;
+};
+
+struct bt_ctf_field_type_structure {
+       struct bt_ctf_field_type parent;
+       GHashTable *field_name_to_index;
+       GPtrArray *fields; /* Array of pointers to struct structure_field */
+       struct declaration_enum declaration;
+};
+
+struct bt_ctf_field_type_variant {
+       struct bt_ctf_field_type parent;
+       GString *tag_name;
+       struct bt_ctf_field_type_enumeration *tag;
+       GHashTable *field_name_to_index;
+       GPtrArray *fields; /* Array of pointers to struct structure_field */
+       struct declaration_variant declaration;
+};
+
+struct bt_ctf_field_type_array {
+       struct bt_ctf_field_type parent;
+       struct bt_ctf_field_type *element_type;
+       unsigned int length; /* Number of elements */
+       struct declaration_array declaration;
+};
+
+struct bt_ctf_field_type_sequence {
+       struct bt_ctf_field_type parent;
+       struct bt_ctf_field_type *element_type;
+       GString *length_field_name;
+       struct declaration_sequence declaration;
+};
+
+struct bt_ctf_field_type_string {
+       struct bt_ctf_field_type parent;
+       struct declaration_string declaration;
+};
+
+BT_HIDDEN
+void bt_ctf_field_type_freeze(struct bt_ctf_field_type *type);
+
+BT_HIDDEN
+enum ctf_type_id bt_ctf_field_type_get_type_id(
+               struct bt_ctf_field_type *type);
+
+BT_HIDDEN
+struct bt_ctf_field_type *bt_ctf_field_type_structure_get_type(
+               struct bt_ctf_field_type_structure *structure,
+               const char *name);
+
+BT_HIDDEN
+struct bt_ctf_field_type *bt_ctf_field_type_array_get_element_type(
+               struct bt_ctf_field_type_array *array);
+
+BT_HIDDEN
+struct bt_ctf_field_type *bt_ctf_field_type_sequence_get_element_type(
+               struct bt_ctf_field_type_sequence *sequence);
+
+BT_HIDDEN
+struct bt_ctf_field_type *bt_ctf_field_type_variant_get_field_type(
+               struct bt_ctf_field_type_variant *variant, int64_t tag_value);
+
+BT_HIDDEN
+int bt_ctf_field_type_serialize(struct bt_ctf_field_type *type,
+               struct metadata_context *context);
+
+BT_HIDDEN
+int bt_ctf_field_type_validate(struct bt_ctf_field_type *type);
+
+#endif /* BABELTRACE_CTF_WRITER_EVENT_TYPES_INTERNAL_H */
diff --git a/lib/babeltrace/ctf-writer/event-types.h b/lib/babeltrace/ctf-writer/event-types.h
new file mode 100644 (file)
index 0000000..cf43ed6
--- /dev/null
@@ -0,0 +1,353 @@
+#ifndef BABELTRACE_CTF_WRITER_EVENT_TYPES_H
+#define BABELTRACE_CTF_WRITER_EVENT_TYPES_H
+
+/*
+ * BabelTrace - CTF Writer: Event Types
+ *
+ * Copyright 2013 EfficiOS Inc.
+ *
+ * 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.
+ *
+ * The Common Trace Format (CTF) Specification is available at
+ * http://www.efficios.com/ctf
+ */
+
+#include <babeltrace/ctf-writer/writer.h>
+#include <babeltrace/ctf/events.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct bt_ctf_event_class;
+struct bt_ctf_event;
+struct bt_ctf_field_type;
+
+enum bt_ctf_integer_base {
+       BT_CTF_INTEGER_BASE_UNKNOWN = -1,
+       BT_CTF_INTEGER_BASE_BINARY = 2,
+       BT_CTF_INTEGER_BASE_OCTAL = 8,
+       BT_CTF_INTEGER_BASE_DECIMAL = 10,
+       BT_CTF_INTEGER_BASE_HEXADECIMAL = 16,
+};
+
+/*
+ * bt_ctf_field_type_integer_create: create an integer field type.
+ *
+ * Allocate a new integer field type of the given size. The creation of a field
+ * type sets its reference count to 1.
+ *
+ * @param size Integer field type size/length in bits.
+ *
+ * Returns an allocated field type on success, NULL on error.
+ */
+extern struct bt_ctf_field_type *bt_ctf_field_type_integer_create(
+               unsigned int size);
+
+/*
+ * bt_ctf_field_type_integer_set_signed: set an integer type's signedness.
+ *
+ * Set an integer type's signedness attribute.
+ *
+ * @param integer Integer type.
+ * @param is_signed Integer's signedness, defaults to FALSE.
+ *
+ * Returns 0 on success, a negative value on error.
+ */
+extern int bt_ctf_field_type_integer_set_signed(
+               struct bt_ctf_field_type *integer, int is_signed);
+
+/*
+ * bt_ctf_field_type_integer_set_base: set an integer type's base.
+ *
+ * Set an integer type's base used to pretty-print the resulting trace.
+ *
+ * @param integer Integer type.
+ * @param base Integer base, defaults to BT_CTF_INTEGER_BASE_DECIMAL.
+ *
+ * Returns 0 on success, a negative value on error.
+ */
+extern int bt_ctf_field_type_integer_set_base(
+               struct bt_ctf_field_type *integer,
+               enum bt_ctf_integer_base base);
+
+/*
+ * bt_ctf_field_type_integer_set_encoding: set an integer type's encoding.
+ *
+ * An integer encoding may be set to signal that the integer must be printed as
+ * a text character.
+ *
+ * @param integer Integer type.
+ * @param encoding Integer output encoding, defaults to CTF_STRING_ENCODING_NONE
+ *
+ * Returns 0 on success, a negative value on error.
+ */
+extern int bt_ctf_field_type_integer_set_encoding(
+               struct bt_ctf_field_type *integer,
+               enum ctf_string_encoding encoding);
+
+/*
+ * bt_ctf_field_type_enumeration_create: create an enumeration field type.
+ *
+ * Allocate a new enumeration field type with the given underlying type. The
+ * creation of a field type sets its reference count to 1.
+ * The resulting enumeration will share the integer_container_type's ownership
+ * by increasing its reference count.
+ *
+ * @param integer_container_type Underlying integer type of the enumeration
+ *     type.
+ *
+ * Returns an allocated field type on success, NULL on error.
+ */
+extern struct bt_ctf_field_type *bt_ctf_field_type_enumeration_create(
+               struct bt_ctf_field_type *integer_container_type);
+
+/*
+ * bt_ctf_field_type_enumeration_add_mapping: add an enumeration mapping.
+ *
+ * Add a mapping to the enumeration. The range's values are inclusive.
+ *
+ * @param enumeration Enumeration type.
+ * @param string Enumeration mapping name (will be copied).
+ * @param range_start Enumeration mapping range start.
+ * @param range_end Enumeration mapping range end.
+ *
+ * Returns 0 on success, a negative value on error.
+ */
+extern int bt_ctf_field_type_enumeration_add_mapping(
+               struct bt_ctf_field_type *enumeration, const char *string,
+               int64_t range_start, int64_t range_end);
+
+/*
+ * bt_ctf_field_type_floating_point_create: create a floating point field type.
+ *
+ * Allocate a new floating point field type. The creation of a field type sets
+ * its reference count to 1.
+ *
+ * Returns an allocated field type on success, NULL on error.
+ */
+extern struct bt_ctf_field_type *bt_ctf_field_type_floating_point_create(void);
+
+/*
+ * bt_ctf_field_type_floating_point_set_exponent_digits: set exponent digit
+ * count.
+ *
+ * Set the number of exponent digits to use to store the floating point field.
+ * The only values currently supported are FLT_EXP_DIG and DBL_EXP_DIG.
+ *
+ * @param floating_point Floating point type.
+ * @param exponent_digits Number of digits to allocate to the exponent (defaults
+ *     to FLT_EXP_DIG).
+ *
+ * Returns 0 on success, a negative value on error.
+ */
+extern int bt_ctf_field_type_floating_point_set_exponent_digits(
+               struct bt_ctf_field_type *floating_point,
+               unsigned int exponent_digits);
+
+/*
+ * bt_ctf_field_type_floating_point_set_mantissa_digits: set mantissa digit
+ * count.
+ *
+ * Set the number of mantissa digits to use to store the floating point field.
+ * The only values currently supported are FLT_MANT_DIG and DBL_MANT_DIG.
+ *
+ * @param floating_point Floating point type.
+ * @param mantissa_digits Number of digits to allocate to the mantissa (defaults
+ *     to FLT_MANT_DIG).
+ *
+ * Returns 0 on success, a negative value on error.
+ */
+extern int bt_ctf_field_type_floating_point_set_mantissa_digits(
+               struct bt_ctf_field_type *floating_point,
+               unsigned int mantissa_digits);
+
+/*
+ * bt_ctf_field_type_structure_create: create a structure field type.
+ *
+ * Allocate a new structure field type. The creation of a field type sets
+ * its reference count to 1.
+ *
+ * Returns an allocated field type on success, NULL on error.
+ */
+extern struct bt_ctf_field_type *bt_ctf_field_type_structure_create(void);
+
+/*
+ * bt_ctf_field_type_structure_add_field: add a field to a structure.
+ *
+ * Add a field of type "field_type" to the structure. The structure will share
+ * field_type's ownership by increasing its reference count.
+ *
+ * @param structure Structure type.
+ * @param field_type Type of the field to add to the structure type.
+ * @param field_name Name of the structure's new field (will be copied).
+ *
+ * Returns 0 on success, a negative value on error.
+ */
+extern int bt_ctf_field_type_structure_add_field(
+               struct bt_ctf_field_type *structure,
+               struct bt_ctf_field_type *field_type,
+               const char *field_name);
+
+/*
+ * bt_ctf_field_type_variant_create: create a variant field type.
+ *
+ * Allocate a new variant field type. The creation of a field type sets
+ * its reference count to 1. tag_name must be the name of an enumeration
+ * field declared in the same scope as this variant.
+ *
+ * @param enum_tag Type of the variant's tag/selector (must be an enumeration).
+ * @param tag_name Name of the variant's tag/selector field (will be copied).
+ *
+ * Returns an allocated field type on success, NULL on error.
+ */
+extern struct bt_ctf_field_type *bt_ctf_field_type_variant_create(
+               struct bt_ctf_field_type *enum_tag,
+               const char *tag_name);
+
+/*
+ * bt_ctf_field_type_variant_add_field: add a field to a variant.
+ *
+ * Add a field of type "field_type" to the variant.The variant will share
+ * field_type's ownership by increasing its reference count. The "field_name"
+ * will be copied. field_name must match a mapping in the tag/selector
+ * enumeration.
+ *
+ * @param variant Variant type.
+ * @param field_type Type of the variant type's new field.
+ * @param field_name Name of the variant type's new field (will be copied).
+ *
+ * Returns 0 on success, a negative value on error.
+ */
+extern int bt_ctf_field_type_variant_add_field(
+               struct bt_ctf_field_type *variant,
+               struct bt_ctf_field_type *field_type,
+               const char *field_name);
+
+/*
+ * bt_ctf_field_type_array_create: create an array field type.
+ *
+ * Allocate a new array field type. The creation of a field type sets
+ * its reference count to 1.
+ *
+ * @param element_type Array's element type.
+ * @oaram length Array type's length.
+ *
+ * Returns an allocated field type on success, NULL on error.
+ */
+extern struct bt_ctf_field_type *bt_ctf_field_type_array_create(
+               struct bt_ctf_field_type *element_type,
+               unsigned int length);
+
+/*
+ * bt_ctf_field_type_sequence_create: create a sequence field type.
+ *
+ * Allocate a new sequence field type. The creation of a field type sets
+ * its reference count to 1. "length_field_name" must match an integer field
+ * declared in the same scope.
+ *
+ * @param element_type Sequence's element type.
+ * @param length_field_name Name of the sequence's length field (will be
+ *     copied).
+ *
+ * Returns an allocated field type on success, NULL on error.
+ */
+extern struct bt_ctf_field_type *bt_ctf_field_type_sequence_create(
+               struct bt_ctf_field_type *element_type,
+               const char *length_field_name);
+
+/*
+ * bt_ctf_field_type_string_create: create a string field type.
+ *
+ * Allocate a new string field type. The creation of a field type sets
+ * its reference count to 1.
+ *
+ * Returns an allocated field type on success, NULL on error.
+ */
+extern struct bt_ctf_field_type *bt_ctf_field_type_string_create(void);
+
+/*
+ * bt_ctf_field_type_string_set_encoding: set a string type's encoding.
+ *
+ * Set the string type's encoding.
+ *
+ * @param string String type.
+ * @param encoding String field encoding, default CTF_STRING_ENCODING_ASCII.
+ *     Valid values are CTF_STRING_ENCODING_ASCII and CTF_STRING_ENCODING_UTF8.
+ *
+ * Returns 0 on success, a negative value on error.
+ */
+extern int bt_ctf_field_type_string_set_encoding(
+               struct bt_ctf_field_type *string,
+               enum ctf_string_encoding encoding);
+
+/*
+ * bt_ctf_field_type_set_alignment: set a field type's alignment.
+ *
+ * Set the field type's alignment.
+ *
+ * @param type Field type.
+ * @param alignment Type's alignment. Defaults to 1 (bit-aligned). However,
+ *     some types, such as structures and string, may impose other alignment
+ *     constraints.
+ *
+ * Returns 0 on success, a negative value on error.
+ */
+extern int bt_ctf_field_type_set_alignment(struct bt_ctf_field_type *type,
+               unsigned int alignment);
+
+/*
+ * bt_ctf_field_type_set_byte_order: set a field type's byte order.
+ *
+ * Set the field type's byte order.
+ *
+ * @param type Field type.
+ * @param byte_order Field type's byte order. Defaults to
+ * BT_CTF_BYTE_ORDER_NATIVE, the host machine's endianness.
+ *
+ * Returns 0 on success, a negative value on error.
+ */
+extern int bt_ctf_field_type_set_byte_order(struct bt_ctf_field_type *type,
+               enum bt_ctf_byte_order byte_order);
+
+/*
+ * bt_ctf_field_type_get and bt_ctf_field_type_put: increment and decrement
+ * the field type's reference count.
+ *
+ * These functions ensure that the field type won't be destroyed while it
+ * is in use. The same number of get and put (plus one extra put to
+ * release the initial reference done at creation) have to be done to
+ * destroy a field type.
+ *
+ * When the field type's reference count is decremented to 0 by a
+ * bt_ctf_field_type_put, the field type is freed.
+ *
+ * @param type Field type.
+ */
+extern void bt_ctf_field_type_get(struct bt_ctf_field_type *type);
+extern void bt_ctf_field_type_put(struct bt_ctf_field_type *type);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BABELTRACE_CTF_WRITER_EVENT_TYPES_H */
diff --git a/lib/babeltrace/ctf-writer/event.h b/lib/babeltrace/ctf-writer/event.h
new file mode 100644 (file)
index 0000000..d8ef9d9
--- /dev/null
@@ -0,0 +1,154 @@
+#ifndef BABELTRACE_CTF_WRITER_EVENT_H
+#define BABELTRACE_CTF_WRITER_EVENT_H
+
+/*
+ * BabelTrace - CTF Writer: Event
+ *
+ * Copyright 2013 EfficiOS Inc.
+ *
+ * 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.
+ *
+ * The Common Trace Format (CTF) Specification is available at
+ * http://www.efficios.com/ctf
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct bt_ctf_event_class;
+struct bt_ctf_event;
+struct bt_ctf_field;
+struct bt_ctf_field_type;
+
+/*
+ * bt_ctf_event_class_create: create an event class.
+ *
+ * Allocate a new event class of the given name. The creation of an event class
+ * sets its reference count to 1.
+ *
+ * @param name Event class name (will be copied).
+ *
+ * Returns an allocated event class on success, NULL on error.
+ */
+extern struct bt_ctf_event_class *bt_ctf_event_class_create(const char *name);
+
+/*
+ * bt_ctf_event_class_add_field: add a field to an event class.
+ *
+ * Add a field of type "type" to the event class. The event class will share
+ * type's ownership by increasing its reference count. The "name" will be
+ * copied.
+ *
+ * @param event_class Event class.
+ * @param type Field type to add to the event class.
+ * @param name Name of the new field.
+ *
+ * Returns 0 on success, a negative value on error.
+ */
+extern int bt_ctf_event_class_add_field(struct bt_ctf_event_class *event_class,
+               struct bt_ctf_field_type *type,
+               const char *name);
+
+/*
+ * bt_ctf_event_class__get and bt_ctf_event_class_put: increment and decrement
+ * the event class' reference count.
+ *
+ * These functions ensure that the event class won't be destroyed while it
+ * is in use. The same number of get and put (plus one extra put to
+ * release the initial reference done at creation) have to be done to
+ * destroy an event class.
+ *
+ * When the event class' reference count is decremented to 0 by a
+ * bt_ctf_event_class_put, the event class is freed.
+ *
+ * @param event_class Event class.
+ */
+extern void bt_ctf_event_class_get(struct bt_ctf_event_class *event_class);
+extern void bt_ctf_event_class_put(struct bt_ctf_event_class *event_class);
+
+/*
+ * bt_ctf_event_create: instanciate an event.
+ *
+ * Allocate a new event of the given event class. The creation of an event
+ * sets its reference count to 1. Each instance shares the ownership of the
+ * event class using its reference count.
+ *
+ * @param event_class Event class.
+ *
+ * Returns an allocated field type on success, NULL on error.
+ */
+extern struct bt_ctf_event *bt_ctf_event_create(
+               struct bt_ctf_event_class *event_class);
+
+/*
+ * bt_ctf_event_set_payload: set an event's field.
+ *
+ * Set a manually allocated field as an event's payload. The event will share
+ * the field's ownership by using its reference count.
+ * bt_ctf_field_put() must be called on the returned value.
+ *
+ * @param event Event instance.
+ * @param name Event field name.
+ * @param value Instance of a field whose type corresponds to the event's field.
+ *
+ * Returns 0 on success, a negative value on error.
+ */
+extern int bt_ctf_event_set_payload(struct bt_ctf_event *event,
+               const char *name,
+               struct bt_ctf_field *value);
+
+/*
+ * bt_ctf_event_get_payload: get an event's field.
+ *
+ * Returns the field matching "name". bt_ctf_field_put() must be called on the
+ * returned value.
+ *
+ * @param event Event instance.
+ * @param name Event field name.
+ *
+ * Returns a field instance on success, NULL on error.
+ */
+extern struct bt_ctf_field *bt_ctf_event_get_payload(struct bt_ctf_event *event,
+               const char *name);
+
+/*
+ * bt_ctf_event_get and bt_ctf_event_put: increment and decrement
+ * the event's reference count.
+ *
+ * These functions ensure that the event won't be destroyed while it
+ * is in use. The same number of get and put (plus one extra put to
+ * release the initial reference done at creation) have to be done to
+ * destroy an event.
+ *
+ * When the event's reference count is decremented to 0 by a
+ * bt_ctf_event_put, the event is freed.
+ *
+ * @param event Event instance.
+ */
+extern void bt_ctf_event_get(struct bt_ctf_event *event);
+extern void bt_ctf_event_put(struct bt_ctf_event *event);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BABELTRACE_CTF_WRITER_EVENT_H */
diff --git a/lib/babeltrace/ctf-writer/functor-internal.h b/lib/babeltrace/ctf-writer/functor-internal.h
new file mode 100644 (file)
index 0000000..66d3fcf
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef BABELTRACE_CTF_WRITER_FUNCTOR_INTERNAL_H
+#define BABELTRACE_CTF_WRITER_FUNCTOR_INTERNAL_H
+
+/*
+ * BabelTrace - CTF Writer: Functors for use with glib data structures
+ *
+ * Copyright 2013 EfficiOS Inc.
+ *
+ * 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 <glib.h>
+#include <babeltrace/babeltrace-internal.h>
+
+struct search_query {
+       gpointer value;
+       int found;
+};
+
+BT_HIDDEN
+void value_exists(gpointer element, gpointer search_query);
+
+#endif /* BABELTRACE_CTF_WRITER_FUNCTOR_INTERNAL_H */
diff --git a/lib/babeltrace/ctf-writer/ref-internal.h b/lib/babeltrace/ctf-writer/ref-internal.h
new file mode 100644 (file)
index 0000000..486e243
--- /dev/null
@@ -0,0 +1,61 @@
+#ifndef BABELTRACE_CTF_WRITER_REF_INTERNAL_H
+#define BABELTRACE_CTF_WRITER_REF_INTERNAL_H
+
+/*
+ * BabelTrace - CTF Writer: Reference count
+ *
+ * Copyright 2013 EfficiOS Inc.
+ *
+ * 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 <assert.h>
+
+struct bt_ctf_ref {
+       long refcount;
+};
+
+static inline
+void bt_ctf_ref_init(struct bt_ctf_ref *ref)
+{
+       assert(ref);
+       ref->refcount = 1;
+}
+
+static inline
+void bt_ctf_ref_get(struct bt_ctf_ref *ref)
+{
+       assert(ref);
+       ref->refcount++;
+}
+
+static inline
+void bt_ctf_ref_put(struct bt_ctf_ref *ref,
+               void (*release)(struct bt_ctf_ref *))
+{
+       assert(ref);
+       assert(release);
+       if ((--ref->refcount) == 0) {
+               release(ref);
+       }
+}
+
+#endif /* BABELTRACE_CTF_WRITER_REF_INTERNAL_H */
diff --git a/lib/babeltrace/ctf-writer/stream-internal.h b/lib/babeltrace/ctf-writer/stream-internal.h
new file mode 100644 (file)
index 0000000..57dd992
--- /dev/null
@@ -0,0 +1,101 @@
+#ifndef BABELTRACE_CTF_WRITER_STREAM_INTERNAL_H
+#define BABELTRACE_CTF_WRITER_STREAM_INTERNAL_H
+
+/*
+ * BabelTrace - CTF Writer: Stream internal
+ *
+ * Copyright 2013 EfficiOS Inc.
+ *
+ * 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-writer/ref-internal.h>
+#include <babeltrace/ctf-writer/clock.h>
+#include <babeltrace/ctf-writer/event-fields.h>
+#include <babeltrace/ctf-writer/event-types.h>
+#include <babeltrace/babeltrace-internal.h>
+#include <babeltrace/ctf/types.h>
+#include <glib.h>
+
+typedef void(*flush_func)(struct bt_ctf_stream *, void *);
+
+struct bt_ctf_stream_class {
+       struct bt_ctf_ref ref_count;
+       GString *name;
+       struct bt_ctf_clock *clock;
+       GPtrArray *event_classes; /* Array of pointers to bt_ctf_event_class */
+       int id_set;
+       uint32_t id;
+       uint32_t next_event_id;
+       uint32_t next_stream_id;
+       struct bt_ctf_field_type *event_header_type;
+       struct bt_ctf_field *event_header;
+       struct bt_ctf_field_type *packet_context_type;
+       struct bt_ctf_field *packet_context;
+       struct bt_ctf_field_type *event_context_type;
+       struct bt_ctf_field *event_context;
+       int frozen;
+};
+
+struct flush_callback {
+       flush_func func;
+       void *data;
+};
+
+struct bt_ctf_stream {
+       struct bt_ctf_ref ref_count;
+       uint32_t id;
+       struct bt_ctf_stream_class *stream_class;
+       struct flush_callback flush;
+       /* Array of pointers to bt_ctf_event for the current packet */
+       GPtrArray *events;
+       struct ctf_stream_pos pos;
+       unsigned int flushed_packet_count;
+       uint64_t events_discarded;
+};
+
+BT_HIDDEN
+void bt_ctf_stream_class_freeze(struct bt_ctf_stream_class *stream_class);
+
+BT_HIDDEN
+int bt_ctf_stream_class_set_id(struct bt_ctf_stream_class *stream_class,
+               uint32_t id);
+
+BT_HIDDEN
+int bt_ctf_stream_class_serialize(struct bt_ctf_stream_class *stream_class,
+               struct metadata_context *context);
+
+BT_HIDDEN
+int bt_ctf_stream_class_set_byte_order(struct bt_ctf_stream_class *stream_class,
+               enum bt_ctf_byte_order byte_order);
+
+BT_HIDDEN
+struct bt_ctf_stream *bt_ctf_stream_create(
+               struct bt_ctf_stream_class *stream_class);
+
+BT_HIDDEN
+int bt_ctf_stream_set_flush_callback(struct bt_ctf_stream *stream,
+               flush_func callback, void *data);
+
+BT_HIDDEN
+int bt_ctf_stream_set_fd(struct bt_ctf_stream *stream, int fd);
+
+#endif /* BABELTRACE_CTF_WRITER_STREAM_INTERNAL_H */
diff --git a/lib/babeltrace/ctf-writer/stream.h b/lib/babeltrace/ctf-writer/stream.h
new file mode 100644 (file)
index 0000000..9229f77
--- /dev/null
@@ -0,0 +1,169 @@
+#ifndef BABELTRACE_CTF_WRITER_STREAM_H
+#define BABELTRACE_CTF_WRITER_STREAM_H
+
+/*
+ * BabelTrace - CTF Writer: Stream
+ *
+ * Copyright 2013 EfficiOS Inc.
+ *
+ * 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.
+ *
+ * The Common Trace Format (CTF) Specification is available at
+ * http://www.efficios.com/ctf
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct bt_ctf_event;
+struct bt_ctf_event_class;
+struct bt_ctf_stream_class;
+struct bt_ctf_stream;
+struct bt_ctf_clock;
+
+/*
+ * bt_ctf_stream_class_create: create a stream class.
+ *
+ * Allocate a new stream class of the given name. The creation of an event class
+ * sets its reference count to 1.
+ *
+ * @param name Stream name.
+ *
+ * Returns an allocated stream class on success, NULL on error.
+ */
+extern struct bt_ctf_stream_class *bt_ctf_stream_class_create(const char *name);
+
+/*
+ * bt_ctf_stream_class_set_clock: assign a clock to a stream class.
+ *
+ * Assign a clock to a stream class. This clock will be sampled each time an
+ * event is appended to an instance of this stream class.
+ *
+ * @param stream_class Stream class.
+ * @param clock Clock to assign to the provided stream class.
+ *
+ * Returns 0 on success, a negative value on error.
+ */
+extern int bt_ctf_stream_class_set_clock(
+               struct bt_ctf_stream_class *stream_class,
+               struct bt_ctf_clock *clock);
+
+/*
+ * bt_ctf_stream_class_set_clock: assign a clock to a stream class.
+ *
+ * Add an event class to a stream class. New events can be added even after a
+ * stream has beem instanciated and events have been appended. However, a stream
+ * will not accept events of a class that has not been registered beforehand.
+ * The stream class will share the ownership of "event_class" by incrementing
+ * its reference count.
+ *
+ * @param stream_class Stream class.
+ * @param event_class Event class to add to the provided stream class.
+ *
+ * Returns 0 on success, a negative value on error.
+ */
+extern int bt_ctf_stream_class_add_event_class(
+               struct bt_ctf_stream_class *stream_class,
+               struct bt_ctf_event_class *event_class);
+
+/*
+ * bt_ctf_stream_class_get and bt_ctf_stream_class_put: increment and
+ * decrement the stream class' reference count.
+ *
+ * These functions ensure that the stream class won't be destroyed while it
+ * is in use. The same number of get and put (plus one extra put to
+ * release the initial reference done at creation) have to be done to
+ * destroy a stream class.
+ *
+ * When the stream class' reference count is decremented to 0 by a
+ * bt_ctf_stream_class_put, the stream class is freed.
+ *
+ * @param stream_class Stream class.
+ */
+extern void bt_ctf_stream_class_get(struct bt_ctf_stream_class *stream_class);
+extern void bt_ctf_stream_class_put(struct bt_ctf_stream_class *stream_class);
+
+/*
+ * bt_ctf_stream_append_discarded_events: increment discarded events count.
+ *
+ * Increase the current packet's discarded event count.
+ *
+ * @param stream Stream instance.
+ * @param event_count Number of discarded events to add to the stream's current
+ *     packet.
+ *
+ * Returns 0 on success, a negative value on error.
+ */
+extern void bt_ctf_stream_append_discarded_events(struct bt_ctf_stream *stream,
+               uint64_t event_count);
+
+/*
+ * bt_ctf_stream_append_event: append an event to the stream.
+ *
+ * Append "event" to the stream's current packet. The stream's associated clock
+ * will be sampled during this call. The event shall not be modified after
+ * being appended to a stream. The stream will share the event's ownership by
+ * incrementing its reference count. The current packet is not flushed to disk
+ * until the next call to bt_ctf_stream_flush.
+ *
+ * @param stream Stream instance.
+ * @param event Event instance to append to the stream's current packet.
+ *
+ * Returns 0 on success, a negative value on error.
+ */
+extern int bt_ctf_stream_append_event(struct bt_ctf_stream *stream,
+               struct bt_ctf_event *event);
+
+/*
+ * bt_ctf_stream_flush: flush a stream.
+ *
+ * The stream's current packet's events will be flushed to disk. Events
+ * subsequently appended to the stream will be added to a new packet.
+ *
+ * @param stream Stream instance.
+ *
+ * Returns 0 on success, a negative value on error.
+ */
+extern int bt_ctf_stream_flush(struct bt_ctf_stream *stream);
+
+/*
+ * bt_ctf_stream_get and bt_ctf_stream_put: increment and decrement the
+ * stream's reference count.
+ *
+ * These functions ensure that the stream won't be destroyed while it
+ * is in use. The same number of get and put (plus one extra put to
+ * release the initial reference done at creation) have to be done to
+ * destroy a stream.
+ *
+ * When the stream's reference count is decremented to 0 by a
+ * bt_ctf_stream_put, the stream is freed.
+ *
+ * @param stream Stream instance.
+ */
+extern void bt_ctf_stream_get(struct bt_ctf_stream *stream);
+extern void bt_ctf_stream_put(struct bt_ctf_stream *stream);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BABELTRACE_CTF_WRITER_STREAM_H */
diff --git a/lib/babeltrace/ctf-writer/writer-internal.h b/lib/babeltrace/ctf-writer/writer-internal.h
new file mode 100644 (file)
index 0000000..5c682dd
--- /dev/null
@@ -0,0 +1,87 @@
+#ifndef BABELTRACE_CTF_WRITER_WRITER_INTERNAL_H
+#define BABELTRACE_CTF_WRITER_WRITER_INTERNAL_H
+
+/*
+ * BabelTrace - CTF Writer: Writer internal
+ *
+ * Copyright 2013 EfficiOS Inc.
+ *
+ * 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-writer/ref-internal.h>
+#include <babeltrace/ctf-writer/writer.h>
+#include <babeltrace/ctf-writer/event-types.h>
+#include <babeltrace/ctf-writer/event-fields.h>
+#include <babeltrace/babeltrace-internal.h>
+#include <glib.h>
+#include <dirent.h>
+#include <sys/types.h>
+#include <uuid/uuid.h>
+
+enum field_type_alias {
+       FIELD_TYPE_ALIAS_UINT5_T = 0,
+       FIELD_TYPE_ALIAS_UINT8_T,
+       FIELD_TYPE_ALIAS_UINT16_T,
+       FIELD_TYPE_ALIAS_UINT27_T,
+       FIELD_TYPE_ALIAS_UINT32_T,
+       FIELD_TYPE_ALIAS_UINT64_T,
+       NR_FIELD_TYPE_ALIAS,
+};
+
+struct bt_ctf_writer {
+       struct bt_ctf_ref ref_count;
+       int frozen; /* Protects attributes that can't be changed mid-trace */
+       GString *path;
+       uuid_t uuid;
+       int byte_order;
+       int trace_dir_fd;
+       int metadata_fd;
+       GPtrArray *environment; /* Array of pointers to environment_variable */
+       GPtrArray *clocks; /* Array of pointers to bt_ctf_clock */
+       GPtrArray *stream_classes; /* Array of pointers to bt_ctf_stream_class */
+       GPtrArray *streams; /* Array of pointers to bt_ctf_stream */
+       struct bt_ctf_field_type *trace_packet_header_type;
+       struct bt_ctf_field *trace_packet_header;
+       uint32_t next_stream_id;
+};
+
+struct environment_variable {
+       GString *name, *value;
+};
+
+struct metadata_context {
+       GString *string;
+       GString *field_name;
+       unsigned int current_indentation_level;
+};
+
+/* Checks that the string does not contain a reserved keyword */
+BT_HIDDEN
+int validate_identifier(const char *string);
+
+BT_HIDDEN
+const char *get_byte_order_string(int byte_order);
+
+BT_HIDDEN
+struct bt_ctf_field_type *get_field_type(enum field_type_alias alias);
+
+#endif /* BABELTRACE_CTF_WRITER_WRITER_INTERNAL_H */
diff --git a/lib/babeltrace/ctf-writer/writer.h b/lib/babeltrace/ctf-writer/writer.h
new file mode 100644 (file)
index 0000000..68031ac
--- /dev/null
@@ -0,0 +1,164 @@
+#ifndef BABELTRACE_CTF_WRITER_WRITER_H
+#define BABELTRACE_CTF_WRITER_WRITER_H
+
+/*
+ * BabelTrace - CTF Writer: Writer
+ *
+ * Copyright 2013 EfficiOS Inc.
+ *
+ * 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.
+ *
+ * The Common Trace Format (CTF) Specification is available at
+ * http://www.efficios.com/ctf
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct bt_ctf_writer;
+struct bt_ctf_stream;
+struct bt_ctf_stream_class;
+struct bt_ctf_clock;
+
+enum bt_ctf_byte_order {
+       BT_CTF_BYTE_ORDER_NATIVE = 0,
+       BT_CTF_BYTE_ORDER_LITTLE_ENDIAN,
+       BT_CTF_BYTE_ORDER_BIG_ENDIAN,
+       BT_CTF_BYTE_ORDER_NETWORK,
+};
+
+/*
+ * bt_ctf_writer_create: create a writer instance.
+ *
+ * Allocate a new writer that will produce a trace in the given path.
+ * The creation of a writer sets its reference count to 1.
+ *
+ * @param path Path to the trace's containing folder (string is copied).
+ *
+ * Returns an allocated writer on success, NULL on error.
+ */
+extern struct bt_ctf_writer *bt_ctf_writer_create(const char *path);
+
+/*
+ * bt_ctf_writer_create_stream: create a stream instance.
+ *
+ * Allocate a new stream instance and register it to the writer. The creation of
+ * a stream sets its reference count to 1.
+ *
+ * @param writer Writer instance.
+ * @param stream_class Stream class to instantiate.
+ *
+ * Returns an allocated writer on success, NULL on error.
+ */
+extern struct bt_ctf_stream *bt_ctf_writer_create_stream(
+               struct bt_ctf_writer *writer,
+               struct bt_ctf_stream_class *stream_class);
+
+/*
+ * bt_ctf_writer_add_environment_field: add an environment field to the trace.
+ *
+ * Add an environment field to the trace. The name and value parameters are
+ * copied.
+ *
+ * @param writer Writer instance.
+ * @param name Name of the environment field (will be copied).
+ * @param value Value of the environment field (will be copied).
+ *
+ * Returns 0 on success, a negative value on error.
+ */
+extern int bt_ctf_writer_add_environment_field(struct bt_ctf_writer *writer,
+               const char *name,
+               const char *value);
+
+/*
+ * bt_ctf_writer_add_clock: add a clock to the trace.
+ *
+ * Add a clock to the trace. Clocks assigned to stream classes must be
+ * registered to the writer.
+ *
+ * @param writer Writer instance.
+ * @param clock Clock to add to the trace.
+ *
+ * Returns 0 on success, a negative value on error.
+ */
+extern int bt_ctf_writer_add_clock(struct bt_ctf_writer *writer,
+               struct bt_ctf_clock *clock);
+
+/*
+ * bt_ctf_writer_get_metadata_string: get meta-data string.
+ *
+ * Get the trace's TSDL meta-data. The caller assumes the ownership of the
+ * returned string.
+ *
+ * @param writer Writer instance.
+ *
+ * Returns the metadata string on success, NULL on error.
+ */
+extern char *bt_ctf_writer_get_metadata_string(struct bt_ctf_writer *writer);
+
+/*
+ * bt_ctf_writer_flush_metadata: flush the trace's metadata to disk.
+ *
+ * Flush the trace's metadata to the metadata file. Note that the metadata will
+ * be flushed automatically when the Writer instance is released (last call to
+ * bt_ctf_writer_put).
+ *
+ * @param writer Writer instance.
+ */
+extern void bt_ctf_writer_flush_metadata(struct bt_ctf_writer *writer);
+
+/*
+ * bt_ctf_writer_set_byte_order: set a field type's byte order.
+ *
+ * Set the trace's byte order. Defaults to BT_CTF_BYTE_ORDER_NATIVE,
+ * the host machine's endianness.
+ *
+ * @param writer Writer instance.
+ * @param byte_order Trace's byte order.
+ *
+ * Returns 0 on success, a negative value on error.
+ */
+extern int bt_ctf_writer_set_byte_order(struct bt_ctf_writer *writer,
+               enum bt_ctf_byte_order byte_order);
+
+/*
+ * bt_ctf_writer_get and bt_ctf_writer_put: increment and decrement the
+ * writer's reference count.
+ *
+ * These functions ensure that the writer won't be destroyed while it
+ * is in use. The same number of get and put (plus one extra put to
+ * release the initial reference done at creation) have to be done to
+ * destroy a writer.
+ *
+ * When the writer's reference count is decremented to 0 by a
+ * bt_ctf_writer_put, the writer is freed.
+ *
+ * @param writer Writer instance.
+ */
+extern void bt_ctf_writer_get(struct bt_ctf_writer *writer);
+extern void bt_ctf_writer_put(struct bt_ctf_writer *writer);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BABELTRACE_CTF_WRITER_WRITER_H */
diff --git a/lib/babeltrace/ctf/ctf-index.h b/lib/babeltrace/ctf/ctf-index.h
new file mode 100644 (file)
index 0000000..0efa888
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * 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 <limits.h>
+
+#define CTF_INDEX_MAGIC 0xC1F1DCC1
+#define CTF_INDEX_MAJOR 1
+#define CTF_INDEX_MINOR 0
+
+/*
+ * 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;
+       /* struct packet_index_len, 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;
+} __attribute__((__packed__));
+
+#endif /* LTTNG_INDEX_H */
index be111c1710144a86056cb6441ab8357a2a31ba65..acc756258f094133c5ea06e8e54dc7a88137d1f2 100644 (file)
@@ -38,6 +38,7 @@
 #include <glib.h>
 
 struct ctf_stream_definition;
+struct ctf_file_stream;
 
 /*
  * These structures are public mappings to internal ctf_event structures.
@@ -81,5 +82,7 @@ struct bt_ctf_iter {
 
 void ctf_print_discarded(FILE *fp, struct ctf_stream_definition *stream,
                        int end_stream);
+void compute_discarded_events(struct ctf_file_stream *file_stream,
+               struct ctf_stream_pos *pos);
 
 #endif /*_BABELTRACE_CTF_EVENTS_INTERNAL_H */
index c92470cf83de30effd11a2da27928f804f501980..c81d8852f83207881524129b1186d7a946c7f225 100644 (file)
@@ -211,6 +211,12 @@ enum ctf_string_encoding bt_ctf_get_encoding(const struct bt_declaration *decl);
  */
 int bt_ctf_get_array_len(const struct bt_declaration *decl);
 
+/*
+ * bt_ctf_get_struct_field_count: return the number of fields in a structure.
+ * Returns a negative value on error.
+ */
+uint64_t bt_ctf_get_struct_field_count(const struct bt_definition *field);
+
 /*
  * Field access functions
  *
@@ -231,6 +237,10 @@ const struct bt_definition *bt_ctf_get_enum_int(const struct bt_definition *fiel
 const char *bt_ctf_get_enum_str(const struct bt_definition *field);
 char *bt_ctf_get_char_array(const struct bt_definition *field);
 char *bt_ctf_get_string(const struct bt_definition *field);
+double bt_ctf_get_float(const struct bt_definition *field);
+const struct bt_definition *bt_ctf_get_variant(const struct bt_definition *field);
+const struct bt_definition *bt_ctf_get_struct_field_index(
+               const struct bt_definition *field, uint64_t i);
 
 /*
  * bt_ctf_field_get_error: returns the last error code encountered while
index c64b8d28616dcc1ab94622b51c0f7c26c79d42fe..338dad167ec976248c23a65c16b93973b9f44518 100644 (file)
@@ -61,7 +61,7 @@ struct packet_index {
 struct ctf_stream_pos {
        struct bt_stream_pos parent;
        int fd;                 /* backing file fd. -1 if unset. */
-       int index_fd;           /* backing index file fd. -1 if unset. */
+       FILE *index_fp;         /* backing index file fp. NULL if unset. */
        GArray *packet_cycles_index;    /* contains struct packet_index in cycles */
        GArray *packet_real_index;      /* contains struct packet_index in ns */
        int prot;               /* mmap protection */
@@ -76,6 +76,7 @@ struct ctf_stream_pos {
        struct mmap_align *base_mma;/* mmap base address */
        int64_t offset;         /* offset from base, in bits. EOF for end of file. */
        int64_t last_offset;    /* offset before the last read_event */
+       int64_t data_offset;    /* offset of data in current packet */
        uint64_t cur_index;     /* current index in packet index */
        uint64_t last_events_discarded; /* last known amount of event discarded */
        void (*packet_seek)(struct bt_stream_pos *pos, size_t index,
@@ -83,6 +84,7 @@ struct ctf_stream_pos {
 
        int dummy;              /* dummy position, for length calculation */
        struct bt_stream_callbacks *cb; /* Callbacks registered for iterator. */
+       void *priv;
 };
 
 static inline
@@ -129,45 +131,41 @@ int ctf_fini_pos(struct ctf_stream_pos *pos);
 /*
  * move_pos - move position of a relative bit offset
  *
+ * Return 1 if OK, 0 if out-of-bound.
+ *
  * TODO: allow larger files by updating base too.
  */
 static inline
-void ctf_move_pos(struct ctf_stream_pos *pos, uint64_t bit_offset)
+int ctf_move_pos(struct ctf_stream_pos *pos, uint64_t bit_offset)
 {
+       uint64_t max_len;
+
        printf_debug("ctf_move_pos test EOF: %" PRId64 "\n", pos->offset);
        if (unlikely(pos->offset == EOF))
-               return;
-
-       if (pos->fd >= 0) {
-               /*
-                * PROT_READ ctf_packet_seek is called from within
-                * ctf_pos_get_event so end of packet does not change
-                * the packet context on for the last event of the
-                * packet.
-                */
-               if ((pos->prot == PROT_WRITE)
-                       && (unlikely(pos->offset + bit_offset >= pos->packet_size))) {
-                       printf_debug("ctf_packet_seek (before call): %" PRId64 "\n",
-                                    pos->offset);
-                       ctf_packet_seek(&pos->parent, 0, SEEK_CUR);
-                       printf_debug("ctf_packet_seek (after call): %" PRId64 "\n",
-                                    pos->offset);
-                       return;
-               }
-       }
+               return 0;
+       if (pos->prot == PROT_READ)
+               max_len = pos->content_size;
+       else
+               max_len = pos->packet_size;
+       if (unlikely(pos->offset + bit_offset > max_len))
+               return 0;
+
        pos->offset += bit_offset;
        printf_debug("ctf_move_pos after increment: %" PRId64 "\n", pos->offset);
+       return 1;
 }
 
 /*
  * align_pos - align position on a bit offset (> 0)
  *
+ * Return 1 if OK, 0 if out-of-bound.
+ *
  * TODO: allow larger files by updating base too.
  */
 static inline
-void ctf_align_pos(struct ctf_stream_pos *pos, uint64_t bit_offset)
+int ctf_align_pos(struct ctf_stream_pos *pos, uint64_t bit_offset)
 {
-       ctf_move_pos(pos, offset_align(pos->offset, bit_offset));
+       return ctf_move_pos(pos, offset_align(pos->offset, bit_offset));
 }
 
 static inline
@@ -202,21 +200,27 @@ int ctf_pos_packet(struct ctf_stream_pos *dummy)
 static inline
 void ctf_pos_pad_packet(struct ctf_stream_pos *pos)
 {
-       ctf_move_pos(pos, pos->packet_size - pos->offset);
+       ctf_packet_seek(&pos->parent, 0, SEEK_CUR);
 }
 
 static inline
 int ctf_pos_access_ok(struct ctf_stream_pos *pos, uint64_t bit_len)
 {
+       uint64_t max_len;
+
        if (unlikely(pos->offset == EOF))
                return 0;
-       if (unlikely(pos->offset + bit_len > pos->packet_size))
+       if (pos->prot == PROT_READ)
+               max_len = pos->content_size;
+       else
+               max_len = pos->packet_size;
+       if (unlikely(pos->offset + bit_len > max_len))
                return 0;
        return 1;
 }
 
 /*
- * Update the stream position for to the current event. This moves to
+ * Update the stream position to the current event. This moves to
  * the next packet if we are located at the end of the current packet.
  */
 static inline
index 07e854fee08645acb85b1e4cf0083992e385598e..dea8e0e5431e71d69e53df24fc97f1ed753bc18c 100644 (file)
@@ -49,6 +49,7 @@ struct bt_trace_descriptor;
 struct bt_mmap_stream {
        int fd;
        struct bt_list_head list;
+       void *priv;
 };
 
 struct bt_mmap_stream_list {
index 50232a905fc7df90268d62c4e58c28ed9d0cd025..5c3939c32b4261eaae4ed3676a20fbb205586c73 100644 (file)
@@ -35,6 +35,7 @@ extern "C" {
 /* Flags for the iterator read_event */
 enum {
        BT_ITER_FLAG_LOST_EVENTS        = (1 << 0),
+       BT_ITER_FLAG_RETRY              = (1 << 1),
 };
 
 /* Forward declarations */
index 8d660bea0e747fa21b0e20221a038dc4fbb5fab0..677818b9417b7309ec634e956dfab1f617fad394 100644 (file)
@@ -435,6 +435,10 @@ struct declaration_string *
 char *bt_get_string(const struct bt_definition *field);
 enum ctf_string_encoding bt_get_string_encoding(const struct bt_definition *field);
 
+double bt_get_float(const struct bt_definition *field);
+
+const struct bt_definition *bt_get_variant_field(struct bt_definition *definition);
+
 struct declaration_struct *
        bt_struct_declaration_new(struct declaration_scope *parent_scope,
                               uint64_t min_align);
@@ -453,10 +457,10 @@ struct declaration_field *
 bt_struct_declaration_get_field_from_index(struct declaration_struct *struct_declaration,
                                        int index);
 struct bt_definition *
-bt_struct_definition_get_field_from_index(struct definition_struct *struct_definition,
+bt_struct_definition_get_field_from_index(const struct definition_struct *struct_definition,
                                       int index);
 int bt_struct_rw(struct bt_stream_pos *pos, struct bt_definition *definition);
-uint64_t bt_struct_declaration_len(struct declaration_struct *struct_declaration);
+uint64_t bt_struct_declaration_len(const struct declaration_struct *struct_declaration);
 
 /*
  * The tag enumeration is validated to ensure that it contains only mappings
index 6d60e64f0d2a65a38a824e0df3083c17094b5f08..f199ca12c7f01024b778e55153bceba346908c99 100644 (file)
@@ -1,5 +1,10 @@
 AM_CFLAGS = $(PACKAGE_CFLAGS) -I$(top_srcdir)/lib -DBABELTRACE_HAVE_LIBUUID
 
+lib_LTLIBRARIES = libbabeltrace-lttng-live.la
+
+libbabeltrace_lttng_live_la_SOURCES = \
+                                     network-live.c lttng-live-functions.c
+
 bin_PROGRAMS = lttngtop
 
 noinst_HEADERS = \
@@ -9,7 +14,9 @@ noinst_HEADERS = \
        cursesdisplay.h \
        iostreamtop.h \
        mmap-live.h \
-       network-live.h
+       network-live.h \
+       lttng-live-functions.h \
+       lttngtop.h
 
 lttngtop_SOURCES = \
        lttngtop.c \
@@ -17,8 +24,11 @@ lttngtop_SOURCES = \
        cursesdisplay.c \
        cputop.c \
        iostreamtop.c \
-       mmap-live.c \
-       network-live.c
+       mmap-live.c
+
+lttngtop_LDFLAGS = -Wl,--no-as-needed
 
 #lttngtop_LDADD = -lbabeltrace -lbabeltrace-ctf -llttngtop-helper -llttng-ctl -lurcu -llttngtopmmappacketseek -llttng-ust-ctl -lcurses -lpanel
-lttngtop_LDADD = -lbabeltrace -lbabeltrace-ctf -llttng-ctl -lurcu -llttng-ust-ctl -lcurses -lpanel
+lttngtop_LDADD = -lbabeltrace -lbabeltrace-ctf -llttng-ctl -lurcu -llttng-ust-ctl -lcurses -lpanel \
+                $(top_builddir)/src/libbabeltrace-lttng-live.la
+
diff --git a/src/lttng-live-functions.c b/src/lttng-live-functions.c
new file mode 100644 (file)
index 0000000..67e7aba
--- /dev/null
@@ -0,0 +1,1013 @@
+/*
+ * Copyright (C) 2013 - Julien Desfossez <jdesfossez@efficios.com>
+ *                      Mathieu Desnoyers <mathieu.desnoyers@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 <sys/socket.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+
+#include <babeltrace/ctf/ctf-index.h>
+
+#include <babeltrace/babeltrace.h>
+#include <babeltrace/ctf/events.h>
+#include <babeltrace/ctf/callbacks.h>
+#include <babeltrace/ctf/iterator.h>
+
+/* for packet_index */
+#include <babeltrace/ctf/types.h>
+
+#include <babeltrace/ctf/metadata.h>
+#include <babeltrace/ctf-text/types.h>
+#include <babeltrace/ctf/events-internal.h>
+/*
+#include <formats/ctf/events-private.h>
+replaced with 
+*/
+#include "network-live.h"
+
+#include "lttng-live-functions.h"
+#include "lttng-viewer.h"
+#include "lttngtop.h"
+
+/*
+ * Memory allocation zeroed
+ */
+#define zmalloc(x) calloc(1, x)
+
+#ifndef max_t
+#define max_t(type, a, b)      \
+       ((type) (a) > (type) (b) ? (type) (a) : (type) (b))
+#endif
+
+int lttng_live_connect_viewer(struct lttng_live_ctx *ctx, char *hostname,
+               int port)
+{
+       struct hostent *host;
+       struct sockaddr_in server_addr;
+       int ret;
+
+       host = gethostbyname(hostname);
+       if (!host) {
+               ret = -1;
+               goto end;
+       }
+
+       if ((ctx->control_sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
+               perror("Socket");
+               ret = -1;
+               goto end;
+       }
+
+       server_addr.sin_family = AF_INET;
+       server_addr.sin_port = htons(port);
+       server_addr.sin_addr = *((struct in_addr *) host->h_addr);
+       bzero(&(server_addr.sin_zero), 8);
+
+       if (connect(ctx->control_sock, (struct sockaddr *) &server_addr,
+                               sizeof(struct sockaddr)) == -1) {
+               perror("Connect");
+               ret = -1;
+               goto end;
+       }
+
+       ret = 0;
+
+end:
+       return ret;
+}
+
+int lttng_live_establish_connection(struct lttng_live_ctx *ctx)
+{
+       struct lttng_viewer_cmd cmd;
+       struct lttng_viewer_connect connect;
+       int ret;
+       ssize_t ret_len;
+
+       cmd.cmd = htobe32(LTTNG_VIEWER_CONNECT);
+       cmd.data_size = sizeof(connect);
+       cmd.cmd_version = 0;
+
+       connect.viewer_session_id = -1ULL;      /* will be set on recv */
+       connect.major = htobe32(LTTNG_LIVE_MAJOR);
+       connect.minor = htobe32(LTTNG_LIVE_MINOR);
+       connect.type = htobe32(LTTNG_VIEWER_CLIENT_COMMAND);
+
+       do {
+               ret_len = send(ctx->control_sock, &cmd, sizeof(cmd), 0);
+       } while (ret_len < 0 && errno == EINTR);
+       if (ret_len < 0) {
+               fprintf(stderr, "[error] Error sending cmd\n");
+               ret = ret_len;
+               goto error;
+       }
+       assert(ret_len == sizeof(cmd));
+
+       do {
+               ret_len = send(ctx->control_sock, &connect, sizeof(connect), 0);
+       } while (ret_len < 0 && errno == EINTR);
+       if (ret_len < 0) {
+               fprintf(stderr, "[error] Error sending version\n");
+               ret = ret_len;
+               goto error;
+       }
+       assert(ret_len == sizeof(connect));
+
+       do {
+               ret_len = recv(ctx->control_sock, &connect, sizeof(connect), 0);
+       } while (ret_len < 0 && errno == EINTR);
+       if (ret_len < 0) {
+               fprintf(stderr, "[error] Error receiving version\n");
+               ret = ret_len;
+               goto error;
+       }
+       assert(ret_len == sizeof(connect));
+
+       printf_verbose("Received viewer session ID : %" PRIu64 "\n",
+                       be64toh(connect.viewer_session_id));
+       printf_verbose("Relayd version : %u.%u\n", be32toh(connect.major),
+                       be32toh(connect.minor));
+
+       ret = 0;
+
+error:
+       return ret;
+}
+
+int lttng_live_list_sessions(struct lttng_live_ctx *ctx, const char *path)
+{
+       struct lttng_viewer_cmd cmd;
+       struct lttng_viewer_list_sessions list;
+       struct lttng_viewer_session lsession;
+       int i, ret;
+       ssize_t ret_len;
+       int sessions_count;
+
+       cmd.cmd = htobe32(LTTNG_VIEWER_LIST_SESSIONS);
+       cmd.data_size = 0;
+       cmd.cmd_version = 0;
+
+       do {
+               ret_len = send(ctx->control_sock, &cmd, sizeof(cmd), 0);
+       } while (ret_len < 0 && errno == EINTR);
+       if (ret_len < 0) {
+               fprintf(stderr, "[error] Error sending cmd\n");
+               ret = ret_len;
+               goto error;
+       }
+       assert(ret_len == sizeof(cmd));
+
+       do {
+               ret_len = recv(ctx->control_sock, &list, sizeof(list), 0);
+       } while (ret_len < 0 && errno == EINTR);
+       if (ret_len < 0) {
+               fprintf(stderr, "[error] Error receiving session list\n");
+               ret = ret_len;
+               goto error;
+       }
+       assert(ret_len == sizeof(list));
+
+       sessions_count = be32toh(list.sessions_count);
+       fprintf(stdout, "%u active session(s)%c\n", sessions_count,
+                       sessions_count > 0 ? ':' : ' ');
+       for (i = 0; i < sessions_count; i++) {
+               do {
+                       ret_len = recv(ctx->control_sock, &lsession, sizeof(lsession), 0);
+               } while (ret_len < 0 && errno == EINTR);
+               if (ret_len < 0) {
+                       fprintf(stderr, "[error] Error receiving session\n");
+                       ret = ret_len;
+                       goto error;
+               }
+               assert(ret_len == sizeof(lsession));
+               lsession.hostname[LTTNG_VIEWER_HOST_NAME_MAX - 1] = '\0';
+               lsession.session_name[LTTNG_VIEWER_NAME_MAX - 1] = '\0';
+
+               fprintf(stdout, "%s/%" PRIu64 " : %s on host %s (timer = %u, "
+                               "%u stream(s), %u client(s) connected)\n",
+                               path, be64toh(lsession.id),
+                               lsession.session_name, lsession.hostname,
+                               be32toh(lsession.live_timer),
+                               be32toh(lsession.streams),
+                               be32toh(lsession.clients));
+       }
+
+       ret = 0;
+
+error:
+       return ret;
+}
+
+int lttng_live_ctf_trace_assign(struct lttng_live_viewer_stream *stream,
+               uint64_t ctf_trace_id)
+{
+       struct lttng_live_ctf_trace *trace;
+       int ret = 0;
+
+       trace = g_hash_table_lookup(stream->session->ctf_traces,
+                       (gpointer) ctf_trace_id);
+       if (!trace) {
+               trace = g_new0(struct lttng_live_ctf_trace, 1);
+               trace->ctf_trace_id = ctf_trace_id;
+               trace->streams = g_ptr_array_new();
+               g_hash_table_insert(stream->session->ctf_traces,
+                               (gpointer) ctf_trace_id,
+                               trace);
+       }
+       if (stream->metadata_flag)
+               trace->metadata_stream = stream;
+
+       stream->ctf_trace = trace;
+       g_ptr_array_add(trace->streams, stream);
+
+       return ret;
+}
+
+int lttng_live_attach_session(struct lttng_live_ctx *ctx, uint64_t id)
+{
+       struct lttng_viewer_cmd cmd;
+       struct lttng_viewer_attach_session_request rq;
+       struct lttng_viewer_attach_session_response rp;
+       struct lttng_viewer_stream stream;
+       int ret, i;
+       ssize_t ret_len;
+
+       cmd.cmd = htobe32(LTTNG_VIEWER_ATTACH_SESSION);
+       cmd.data_size = sizeof(rq);
+       cmd.cmd_version = 0;
+
+       memset(&rq, 0, sizeof(rq));
+       rq.session_id = htobe64(id);
+       // TODO: add cmd line parameter to select seek beginning
+       // rq.seek = htobe32(LTTNG_VIEWER_SEEK_BEGINNING);
+       rq.seek = htobe32(LTTNG_VIEWER_SEEK_LAST);
+
+       do {
+               ret_len = send(ctx->control_sock, &cmd, sizeof(cmd), 0);
+       } while (ret_len < 0 && errno == EINTR);
+       if (ret_len < 0) {
+               fprintf(stderr, "[error] Error sending cmd\n");
+               ret = ret_len;
+               goto error;
+       }
+       assert(ret_len == sizeof(cmd));
+
+       do {
+               ret_len = send(ctx->control_sock, &rq, sizeof(rq), 0);
+       } while (ret_len < 0 && errno == EINTR);
+       if (ret_len < 0) {
+               fprintf(stderr, "[error] Error sending attach request\n");
+               ret = ret_len;
+               goto error;
+       }
+       assert(ret_len == sizeof(rq));
+
+       do {
+               ret_len = recv(ctx->control_sock, &rp, sizeof(rp), 0);
+       } while (ret_len < 0 && errno == EINTR);
+       if (ret_len < 0) {
+               fprintf(stderr, "[error] Error receiving attach response\n");
+               ret = ret_len;
+               goto error;
+       }
+       assert(ret_len == sizeof(rp));
+
+       switch(be32toh(rp.status)) {
+       case LTTNG_VIEWER_ATTACH_OK:
+               break;
+       case LTTNG_VIEWER_ATTACH_UNK:
+               ret = -LTTNG_VIEWER_ATTACH_UNK;
+               goto end;
+       case LTTNG_VIEWER_ATTACH_ALREADY:
+               fprintf(stderr, "[error] Already a viewer attached\n");
+               ret = -1;
+               goto end;
+       case LTTNG_VIEWER_ATTACH_NOT_LIVE:
+               fprintf(stderr, "[error] Not a live session\n");
+               ret = -1;
+               goto end;
+       case LTTNG_VIEWER_ATTACH_SEEK_ERR:
+               fprintf(stderr, "[error] Wrong seek parameter\n");
+               ret = -1;
+               goto end;
+       default:
+               fprintf(stderr, "[error] Unknown attach return code %u\n",
+                               be32toh(rp.status));
+               ret = -1;
+               goto end;
+       }
+       if (be32toh(rp.status) != LTTNG_VIEWER_ATTACH_OK) {
+               ret = -1;
+               goto end;
+       }
+
+       ctx->session->stream_count = be32toh(rp.streams_count);
+       /*
+        * When the session is created but not started, we do an active wait
+        * until it starts. It allows the viewer to start processing the trace
+        * as soon as the session starts.
+        */
+       if (ctx->session->stream_count == 0) {
+               ret = 0;
+               goto end;
+       }
+       printf_verbose("Waiting for %" PRIu64 " streams:\n",
+               ctx->session->stream_count);
+       ctx->session->streams = g_new0(struct lttng_live_viewer_stream,
+                       ctx->session->stream_count);
+       for (i = 0; i < be32toh(rp.streams_count); i++) {
+               do {
+                       ret_len = recv(ctx->control_sock, &stream, sizeof(stream), 0);
+               } while (ret_len < 0 && errno == EINTR);
+               if (ret_len < 0) {
+                       fprintf(stderr, "[error] Error receiving stream\n");
+                       ret = ret_len;
+                       goto error;
+               }
+               assert(ret_len == sizeof(stream));
+               stream.path_name[LTTNG_VIEWER_PATH_MAX - 1] = '\0';
+               stream.channel_name[LTTNG_VIEWER_NAME_MAX - 1] = '\0';
+
+               printf_verbose("    stream %" PRIu64 " : %s/%s\n",
+                               be64toh(stream.id), stream.path_name,
+                               stream.channel_name);
+               ctx->session->streams[i].id = be64toh(stream.id);
+               ctx->session->streams[i].session = ctx->session;
+
+               ctx->session->streams[i].first_read = 1;
+               ctx->session->streams[i].mmap_size = 0;
+
+               if (be32toh(stream.metadata_flag)) {
+                       char *path;
+
+                       path = strdup(LTTNG_METADATA_PATH_TEMPLATE);
+                       if (!path) {
+                               perror("strdup");
+                               ret = -1;
+                               goto error;
+                       }
+                       if (!mkdtemp(path)) {
+                               perror("mkdtemp");
+                               free(path);
+                               ret = -1;
+                               goto error;
+                       }
+                       ctx->session->streams[i].metadata_flag = 1;
+                       snprintf(ctx->session->streams[i].path,
+                                       sizeof(ctx->session->streams[i].path),
+                                       "%s/%s", path,
+                                       stream.channel_name);
+                       ret = open(ctx->session->streams[i].path,
+                                       O_WRONLY | O_CREAT | O_TRUNC,
+                                       S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
+                       if (ret < 0) {
+                               perror("open");
+                               free(path);
+                               goto error;
+                       }
+                       ctx->session->streams[i].fd = ret;
+                       free(path);
+               }
+               ret = lttng_live_ctf_trace_assign(&ctx->session->streams[i],
+                               be64toh(stream.ctf_trace_id));
+               if (ret < 0) {
+                       goto error;
+               }
+
+       }
+       ret = 0;
+
+end:
+error:
+       return ret;
+}
+
+static
+int get_data_packet(struct lttng_live_ctx *ctx,
+               struct ctf_stream_pos *pos,
+               struct lttng_live_viewer_stream *stream, uint64_t offset,
+               uint64_t len)
+{
+       struct lttng_viewer_cmd cmd;
+       struct lttng_viewer_get_packet rq;
+       struct lttng_viewer_trace_packet rp;
+       ssize_t ret_len;
+       int ret;
+
+       cmd.cmd = htobe32(LTTNG_VIEWER_GET_PACKET);
+       cmd.data_size = sizeof(rq);
+       cmd.cmd_version = 0;
+
+       memset(&rq, 0, sizeof(rq));
+       rq.stream_id = htobe64(stream->id);
+       /* Already in big endian. */
+       rq.offset = offset;
+       rq.len = htobe32(len);
+
+       do {
+               ret_len = send(ctx->control_sock, &cmd, sizeof(cmd), 0);
+       } while (ret_len < 0 && errno == EINTR);
+       if (ret_len < 0) {
+               fprintf(stderr, "[error] Error sending cmd\n");
+               ret = ret_len;
+               goto error;
+       }
+       assert(ret_len == sizeof(cmd));
+
+       do {
+               ret_len = send(ctx->control_sock, &rq, sizeof(rq), 0);
+       } while (ret_len < 0 && errno == EINTR);
+       if (ret_len < 0) {
+               fprintf(stderr, "[error] Error sending get_data_packet request\n");
+               ret = ret_len;
+               goto error;
+       }
+       assert(ret_len == sizeof(rq));
+
+       do {
+               ret_len = recv(ctx->control_sock, &rp, sizeof(rp), 0);
+       } while (ret_len < 0 && errno == EINTR);
+       if (ret_len < 0) {
+               fprintf(stderr, "[error] Error receiving data response\n");
+               ret = ret_len;
+               goto error;
+       }
+       if (ret_len != sizeof(rp)) {
+               fprintf(stderr, "[error] get_data_packet: expected %" PRId64
+                               ", received %" PRId64 "\n", ret_len,
+                               sizeof(rp));
+               ret = -1;
+               goto error;
+       }
+
+       rp.flags = be32toh(rp.flags);
+
+       switch (be32toh(rp.status)) {
+       case LTTNG_VIEWER_GET_PACKET_OK:
+               len = be32toh(rp.len);
+               printf_verbose("get_data_packet: Ok, packet size : %" PRIu64
+                               "\n", len);
+               break;
+       case LTTNG_VIEWER_GET_PACKET_RETRY:
+               printf_verbose("get_data_packet: retry\n");
+               ret = -1;
+               goto end;
+       case LTTNG_VIEWER_GET_PACKET_ERR:
+               if (rp.flags & LTTNG_VIEWER_FLAG_NEW_METADATA) {
+                       printf_verbose("get_data_packet: new metadata needed\n");
+                       ret = 0;
+                       goto end;
+               }
+               fprintf(stderr, "[error] get_data_packet: error\n");
+               ret = -1;
+               goto end;
+       case LTTNG_VIEWER_GET_PACKET_EOF:
+               ret = -2;
+               goto error;
+       default:
+               printf_verbose("get_data_packet: unknown\n");
+               assert(0);
+               ret = -1;
+               goto end;
+       }
+
+       if (len <= 0) {
+               ret = -1;
+               goto end;
+       }
+
+       if (len > stream->mmap_size) {
+               uint64_t new_size;
+
+               new_size = max_t(uint64_t, len, stream->mmap_size << 1);
+               if (pos->base_mma) {
+                       /* unmap old base */
+                       ret = munmap_align(pos->base_mma);
+                       if (ret) {
+                               fprintf(stderr, "[error] Unable to unmap old base: %s.\n",
+                                       strerror(errno));
+                               ret = -1;
+                               goto error;
+                       }
+                       pos->base_mma = NULL;
+               }
+               pos->base_mma = mmap_align(new_size,
+                               PROT_READ | PROT_WRITE,
+                               MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+               if (pos->base_mma == MAP_FAILED) {
+                       fprintf(stderr, "[error] mmap error %s.\n",
+                               strerror(errno));
+                       pos->base_mma = NULL;
+                       ret = -1;
+                       goto error;
+               }
+
+               stream->mmap_size = new_size;
+               printf_verbose("Expanding stream mmap size to %" PRIu64 " bytes\n",
+                               stream->mmap_size);
+       }
+
+       do {
+               ret_len = recv(ctx->control_sock,
+                       mmap_align_addr(pos->base_mma), len,
+                       MSG_WAITALL);
+       } while (ret_len < 0 && errno == EINTR);
+       if (ret_len < 0) {
+               fprintf(stderr, "[error] Error receiving trace packet\n");
+               ret = ret_len;
+               goto error;
+       }
+       assert(ret_len == len);
+
+end:
+error:
+       return ret;
+}
+
+/*
+ * Return number of metadata bytes written or a negative value on error.
+ */
+static
+int get_new_metadata(struct lttng_live_ctx *ctx,
+               struct lttng_live_viewer_stream *viewer_stream,
+               uint64_t *metadata_len)
+{
+       uint64_t len = 0;
+       int ret;
+       struct lttng_viewer_cmd cmd;
+       struct lttng_viewer_get_metadata rq;
+       struct lttng_viewer_metadata_packet rp;
+       struct lttng_live_viewer_stream *metadata_stream;
+       char *data = NULL;
+       ssize_t ret_len;
+
+       cmd.cmd = htobe32(LTTNG_VIEWER_GET_METADATA);
+       cmd.data_size = sizeof(rq);
+       cmd.cmd_version = 0;
+
+       metadata_stream = viewer_stream->ctf_trace->metadata_stream;
+       rq.stream_id = htobe64(metadata_stream->id);
+
+       do {
+               ret_len = send(ctx->control_sock, &cmd, sizeof(cmd), 0);
+       } while (ret_len < 0 && errno == EINTR);
+       if (ret_len < 0) {
+               fprintf(stderr, "[error] Error sending cmd\n");
+               ret = ret_len;
+               goto error;
+       }
+       assert(ret_len == sizeof(cmd));
+
+       do {
+               ret_len = send(ctx->control_sock, &rq, sizeof(rq), 0);
+       } while (ret_len < 0 && errno == EINTR);
+       if (ret_len < 0) {
+               fprintf(stderr, "[error] Error sending get_metadata request\n");
+               ret = ret_len;
+               goto error;
+       }
+       assert(ret_len == sizeof(rq));
+
+       do {
+               ret_len = recv(ctx->control_sock, &rp, sizeof(rp), 0);
+       } while (ret_len < 0 && errno == EINTR);
+       if (ret_len < 0) {
+               fprintf(stderr, "[error] Error receiving metadata response\n");
+               ret = ret_len;
+               goto error;
+       }
+       assert(ret_len == sizeof(rp));
+
+       switch (be32toh(rp.status)) {
+               case LTTNG_VIEWER_METADATA_OK:
+                       printf_verbose("get_metadata : OK\n");
+                       break;
+               case LTTNG_VIEWER_NO_NEW_METADATA:
+                       printf_verbose("get_metadata : NO NEW\n");
+                       ret = -1;
+                       goto end;
+               case LTTNG_VIEWER_METADATA_ERR:
+                       printf_verbose("get_metadata : ERR\n");
+                       ret = -1;
+                       goto end;
+               default:
+                       printf_verbose("get_metadata : UNKNOWN\n");
+                       ret = -1;
+                       goto end;
+       }
+
+       len = be64toh(rp.len);
+       printf_verbose("Writing %" PRIu64" bytes to metadata\n", len);
+       if (len <= 0) {
+               ret = -1;
+               goto end;
+       }
+
+       data = zmalloc(len);
+       if (!data) {
+               perror("relay data zmalloc");
+               ret = -1;
+               goto error;
+       }
+       do {
+               ret_len = recv(ctx->control_sock, data, len, MSG_WAITALL);
+       } while (ret_len < 0 && errno == EINTR);
+       if (ret_len < 0) {
+               fprintf(stderr, "[error] Error receiving trace packet\n");
+               ret = ret_len;
+               free(data);
+               goto error;
+       }
+       assert(ret_len == len);
+
+       do {
+               ret_len = write(metadata_stream->fd, data, len);
+       } while (ret_len < 0 && errno == EINTR);
+       if (ret_len < 0) {
+               free(data);
+               ret = ret_len;
+               goto error;
+       }
+       assert(ret_len == len);
+
+       free(data);
+
+       *metadata_len = len;
+       ret = 0;
+end:
+error:
+       return ret;
+}
+
+/*
+ * Get one index for a stream.
+ *
+ * Returns 0 on success or a negative value on error.
+ */
+static
+int get_next_index(struct lttng_live_ctx *ctx,
+               struct lttng_live_viewer_stream *viewer_stream,
+               struct packet_index *index)
+{
+       struct lttng_viewer_cmd cmd;
+       struct lttng_viewer_get_next_index rq;
+       struct lttng_viewer_index rp;
+       int ret;
+       uint64_t metadata_len;
+       ssize_t ret_len;
+
+       cmd.cmd = htobe32(LTTNG_VIEWER_GET_NEXT_INDEX);
+       cmd.data_size = sizeof(rq);
+       cmd.cmd_version = 0;
+
+       memset(&rq, 0, sizeof(rq));
+       rq.stream_id = htobe64(viewer_stream->id);
+
+retry:
+       do {
+               ret_len = send(ctx->control_sock, &cmd, sizeof(cmd), 0);
+       } while (ret_len < 0 && errno == EINTR);
+       if (ret_len < 0) {
+               fprintf(stderr, "[error] Error sending cmd\n");
+               ret = ret_len;
+               goto error;
+       }
+       assert(ret_len == sizeof(cmd));
+
+       do {
+               ret_len = send(ctx->control_sock, &rq, sizeof(rq), 0);
+       } while (ret_len < 0 && errno == EINTR);
+       if (ret_len < 0) {
+               fprintf(stderr, "[error] Error sending get_next_index request\n");
+               ret = ret_len;
+               goto error;
+       }
+       assert(ret_len == sizeof(rq));
+
+       do {
+               ret_len = recv(ctx->control_sock, &rp, sizeof(rp), 0);
+       } while (ret_len < 0 && errno == EINTR);
+       if (ret_len < 0) {
+               fprintf(stderr, "[error] Error receiving index response\n");
+               ret = ret_len;
+               goto error;
+       }
+       assert(ret_len == sizeof(rp));
+
+       rp.flags = be32toh(rp.flags);
+
+       switch (be32toh(rp.status)) {
+       case LTTNG_VIEWER_INDEX_INACTIVE:
+               printf_verbose("get_next_index: inactive\n");
+               memset(index, 0, sizeof(struct packet_index));
+               index->timestamp_end = be64toh(rp.timestamp_end);
+               break;
+       case LTTNG_VIEWER_INDEX_OK:
+               printf_verbose("get_next_index: Ok, need metadata update : %u\n",
+                               rp.flags & LTTNG_VIEWER_FLAG_NEW_METADATA);
+               index->offset = be64toh(rp.offset);
+               index->packet_size = be64toh(rp.packet_size);
+               index->content_size = be64toh(rp.content_size);
+               index->timestamp_begin = be64toh(rp.timestamp_begin);
+               index->timestamp_end = be64toh(rp.timestamp_end);
+               index->events_discarded = be64toh(rp.events_discarded);
+
+               if (rp.flags & LTTNG_VIEWER_FLAG_NEW_METADATA) {
+                       printf_verbose("get_next_index: new metadata needed\n");
+                       ret = get_new_metadata(ctx, viewer_stream,
+                                       &metadata_len);
+                       if (ret < 0) {
+                               goto error;
+                       }
+               }
+               break;
+       case LTTNG_VIEWER_INDEX_RETRY:
+               printf_verbose("get_next_index: retry\n");
+               sleep(1);
+               goto retry;
+       case LTTNG_VIEWER_INDEX_HUP:
+               printf_verbose("get_next_index: stream hung up\n");
+               viewer_stream->id = -1ULL;
+               viewer_stream->fd = -1;
+               index->offset = EOF;
+               break;
+       case LTTNG_VIEWER_INDEX_ERR:
+               fprintf(stderr, "[error] get_next_index: error\n");
+               ret = -1;
+               goto error;
+       default:
+               fprintf(stderr, "[error] get_next_index: unkwown value\n");
+               ret = -1;
+               goto error;
+       }
+
+       ret = 0;
+
+error:
+       return ret;
+}
+
+void ctf_live_packet_seek(struct bt_stream_pos *stream_pos, size_t index,
+               int whence)
+{
+       struct ctf_stream_pos *pos;
+       struct ctf_file_stream *file_stream;
+       struct packet_index packet_index;
+       struct lttng_live_viewer_stream *viewer_stream;
+       struct lttng_live_session *session;
+       int ret;
+
+retry:
+       pos = ctf_pos(stream_pos);
+       file_stream = container_of(pos, struct ctf_file_stream, pos);
+       viewer_stream = (struct lttng_live_viewer_stream *) pos->priv;
+       session = viewer_stream->session;
+
+       printf_verbose("get_next_index for stream %" PRIu64 "\n", viewer_stream->id);
+       ret = get_next_index(session->ctx, viewer_stream, &packet_index);
+       if (ret < 0) {
+               pos->offset = EOF;
+               fprintf(stderr, "[error] get_next_index failed\n");
+               return;
+       }
+
+       pos->packet_size = packet_index.packet_size;
+       pos->content_size = packet_index.content_size;
+       pos->mmap_base_offset = 0;
+       if (packet_index.offset == EOF) {
+               pos->offset = EOF;
+       } else {
+               pos->offset = 0;
+       }
+
+       if (packet_index.content_size == 0) {
+               file_stream->parent.cycles_timestamp = packet_index.timestamp_end;
+               file_stream->parent.real_timestamp = ctf_get_real_timestamp(
+                               &file_stream->parent, packet_index.timestamp_end);
+       } else {
+               /* Append to the cycles_index. */
+               g_array_append_val(file_stream->pos.packet_cycles_index,
+                               packet_index);
+               /* Convert the timestamps and append to the real_index. */
+               packet_index.timestamp_begin = ctf_get_real_timestamp(
+                               &file_stream->parent, packet_index.timestamp_begin);
+               packet_index.timestamp_end = ctf_get_real_timestamp(
+                               &file_stream->parent, packet_index.timestamp_end);
+               g_array_append_val(file_stream->pos.packet_real_index,
+                               packet_index);
+
+               compute_discarded_events(file_stream, pos);
+
+               packet_index = g_array_index(pos->packet_cycles_index,
+                               struct packet_index, pos->cur_index);
+               file_stream->parent.cycles_timestamp = packet_index.timestamp_begin;
+
+               packet_index = g_array_index(pos->packet_real_index,
+                               struct packet_index, pos->cur_index);
+               file_stream->parent.real_timestamp = packet_index.timestamp_begin;
+               ++pos->cur_index;
+       }
+
+       if (pos->packet_size == 0 || pos->offset == EOF) {
+               goto end;
+       }
+
+       printf_verbose("get_data_packet for stream %" PRIu64 "\n",
+                       viewer_stream->id);
+       ret = get_data_packet(session->ctx, pos, viewer_stream,
+                       be64toh(packet_index.offset),
+                       packet_index.packet_size / CHAR_BIT);
+       if (ret == -2) {
+               goto retry;
+       } else if (ret < 0) {
+               pos->offset = EOF;
+               fprintf(stderr, "[error] get_data_packet failed\n");
+               return;
+       }
+
+       printf_verbose("Index received : packet_size : %" PRIu64
+                       ", offset %" PRIu64 ", content_size %" PRIu64
+                       ", timestamp_end : %" PRIu64 "\n",
+                       packet_index.packet_size, packet_index.offset,
+                       packet_index.content_size, packet_index.timestamp_end);
+
+       /* update trace_packet_header and stream_packet_context */
+       if (pos->prot != PROT_WRITE && file_stream->parent.trace_packet_header) {
+               /* Read packet header */
+               ret = generic_rw(&pos->parent, &file_stream->parent.trace_packet_header->p);
+               if (ret) {
+                       pos->offset = EOF;
+                       fprintf(stderr, "[error] trace packet header read failed\n");
+                       goto end;
+               }
+       }
+       if (pos->prot != PROT_WRITE && file_stream->parent.stream_packet_context) {
+               /* Read packet context */
+               ret = generic_rw(&pos->parent, &file_stream->parent.stream_packet_context->p);
+               if (ret) {
+                       pos->offset = EOF;
+                       fprintf(stderr, "[error] stream packet context read failed\n");
+                       goto end;
+               }
+       }
+       pos->data_offset = pos->offset;
+
+end:
+       return;
+}
+
+static int del_traces(gpointer key, gpointer value, gpointer user_data)
+{
+       struct bt_context *bt_ctx = user_data;
+       struct lttng_live_ctf_trace *trace = value;
+       int ret;
+
+       ret = bt_context_remove_trace(bt_ctx, trace->trace_id);
+       if (ret < 0)
+               fprintf(stderr, "[error] removing trace from context\n");
+
+       /* remove the key/value pair from the HT. */
+       return 1;
+}
+
+static void add_traces(gpointer key, gpointer value, gpointer user_data)
+{
+       int i, ret, total_metadata = 0;
+       uint64_t metadata_len;
+       struct bt_context *bt_ctx = user_data;
+       struct lttng_live_ctf_trace *trace = value;
+       struct lttng_live_viewer_stream *stream;
+       struct bt_mmap_stream *new_mmap_stream;
+       struct bt_mmap_stream_list mmap_list;
+       struct lttng_live_ctx *ctx = NULL;
+
+       BT_INIT_LIST_HEAD(&mmap_list.head);
+
+       for (i = 0; i < trace->streams->len; i++) {
+               stream = g_ptr_array_index(trace->streams, i);
+               ctx = stream->session->ctx;
+
+               if (!stream->metadata_flag) {
+                       new_mmap_stream = zmalloc(sizeof(struct bt_mmap_stream));
+                       new_mmap_stream->priv = (void *) stream;
+                       new_mmap_stream->fd = -1;
+                       bt_list_add(&new_mmap_stream->list, &mmap_list.head);
+               } else {
+                       /* Get all possible metadata before starting */
+                       do {
+                               ret = get_new_metadata(ctx, stream,
+                                               &metadata_len);
+                               if (ret == 0) {
+                                       total_metadata += metadata_len;
+                               }
+                       } while (ret == 0 || total_metadata == 0);
+                       trace->metadata_fp = fopen(stream->path, "r");
+               }
+       }
+
+       if (!trace->metadata_fp) {
+               fprintf(stderr, "[error] No metadata stream opened\n");
+               goto end_free;
+       }
+
+       ret = bt_context_add_trace(bt_ctx, NULL, "ctf",
+                       ctf_live_packet_seek, &mmap_list, trace->metadata_fp);
+       if (ret < 0) {
+               fprintf(stderr, "[error] Error adding trace\n");
+               goto end_free;
+       }
+       trace->trace_id = ret;
+
+       goto end;
+
+end_free:
+       bt_context_put(bt_ctx);
+end:
+       return;
+}
+
+void lttng_live_read(struct lttng_live_ctx *ctx, uint64_t session_id)
+{
+       int ret, active_session = 0;
+       struct bt_context *bt_ctx;
+
+       bt_ctx = bt_context_create();
+       if (!bt_ctx) {
+               fprintf(stderr, "[error] bt_context_create allocation\n");
+               goto end;
+       }
+
+       /*
+        * As long as the session is active, we try to reattach to it,
+        * even if all the streams get closed.
+        */
+//     do {
+               do {
+                       ret = lttng_live_attach_session(ctx, session_id);
+                       printf_verbose("Attaching session returns %d\n", ret);
+                       if (ret < 0) {
+                               if (ret == -LTTNG_VIEWER_ATTACH_UNK) {
+                                       if (active_session)
+                                               goto end_free;
+                                       fprintf(stderr, "[error] Unknown "
+                                                       "session ID\n");
+                               }
+                               goto end_free;
+                       } else {
+                               active_session = 1;
+                       }
+               } while (ctx->session->stream_count == 0);
+
+               g_hash_table_foreach(ctx->session->ctf_traces, add_traces, bt_ctx);
+
+               ret = check_requirements(bt_ctx);
+               if (ret < 0) {
+                       fprintf(stderr, "[error] some mandatory contexts "
+                                       "were missing, exiting.\n");
+                       goto end;
+               }
+
+               if (!opt_textdump) {
+                       pthread_create(&display_thread, NULL, ncurses_display,
+                                       (void *) NULL);
+                       pthread_create(&timer_thread, NULL, refresh_thread,
+                                       (void *) NULL);
+               }
+
+               iter_trace(bt_ctx);
+
+               g_hash_table_foreach_remove(ctx->session->ctf_traces, del_traces, bt_ctx);
+//     } while (active_session);
+
+end_free:
+       bt_context_put(bt_ctx);
+end:
+       return;
+}
diff --git a/src/lttng-live-functions.h b/src/lttng-live-functions.h
new file mode 100644 (file)
index 0000000..778540d
--- /dev/null
@@ -0,0 +1,74 @@
+#ifndef _LTTNG_LIVE_FUNCTIONS_H
+#define _LTTNG_LIVE_FUNCTIONS_H
+
+/*
+ * Copyright 2013 Julien Desfossez <julien.desfossez@efficios.com>
+ *                Mathieu Desnoyers <mathieu.desnoyers@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 <stdint.h>
+
+#define LTTNG_METADATA_PATH_TEMPLATE           "/tmp/lttng-live-XXXXXX"
+#define LTTNG_DEFAULT_NETWORK_VIEWER_PORT      5344
+
+#define LTTNG_LIVE_MAJOR                       2
+#define LTTNG_LIVE_MINOR                       4
+
+struct lttng_live_ctx {
+       int control_sock;
+       struct lttng_live_session *session;
+};
+
+struct lttng_live_viewer_stream {
+       uint64_t id;
+       uint64_t mmap_size;
+       int fd;
+       int metadata_flag;
+       int first_read;
+       struct lttng_live_session *session;
+       struct lttng_live_ctf_trace *ctf_trace;
+       char path[PATH_MAX];
+};
+
+struct lttng_live_session {
+       uint64_t live_timer_interval;
+       uint64_t stream_count;
+       struct lttng_live_ctx *ctx;
+       struct lttng_live_viewer_stream *streams;
+       GHashTable *ctf_traces;
+};
+
+struct lttng_live_ctf_trace {
+       uint64_t ctf_trace_id;
+       struct lttng_live_viewer_stream *metadata_stream;
+       GPtrArray *streams;
+       FILE *metadata_fp;
+       int trace_id;
+};
+
+int lttng_live_connect_viewer(struct lttng_live_ctx *ctx, char *hostname,
+               int port);
+int lttng_live_establish_connection(struct lttng_live_ctx *ctx);
+int lttng_live_list_sessions(struct lttng_live_ctx *ctx, const char *path);
+int lttng_live_attach_session(struct lttng_live_ctx *ctx, uint64_t id);
+void lttng_live_read(struct lttng_live_ctx *ctx, uint64_t session_id);
+
+#endif /* _LTTNG_LIVE_FUNCTIONS_H */
index 1977a43b460852627bec6b8a6c1444e2da29ad83..d424a976aecc1c06c31fff6ff30b8bb1981a4362 100644 (file)
 #define LTTNG_VIEWER_HOST_NAME_MAX     64
 
 /* Flags in reply to get_next_index and get_packet. */
-/* New metadata is required to read this packet. */
-#define LTTNG_VIEWER_FLAG_NEW_METADATA (1 << 0)
-/* New stream got added to the trace. */
-#define LTTNG_VIEWER_FLAG_NEW_STREAM   (1 << 1)
+enum {
+       /* New metadata is required to read this packet. */
+       LTTNG_VIEWER_FLAG_NEW_METADATA  = (1 << 0),
+       /* New stream got added to the trace. */
+       LTTNG_VIEWER_FLAG_NEW_STREAM    = (1 << 1),
+};
 
 enum lttng_viewer_command {
-       VIEWER_CONNECT          = 1,
-       VIEWER_LIST_SESSIONS    = 2,
-       VIEWER_ATTACH_SESSION   = 3,
-       VIEWER_GET_NEXT_INDEX   = 4,
-       VIEWER_GET_PACKET       = 5,
-       VIEWER_GET_METADATA     = 6,
+       LTTNG_VIEWER_CONNECT            = 1,
+       LTTNG_VIEWER_LIST_SESSIONS      = 2,
+       LTTNG_VIEWER_ATTACH_SESSION     = 3,
+       LTTNG_VIEWER_GET_NEXT_INDEX     = 4,
+       LTTNG_VIEWER_GET_PACKET         = 5,
+       LTTNG_VIEWER_GET_METADATA       = 6,
 };
 
 enum lttng_viewer_attach_return_code {
-       VIEWER_ATTACH_OK        = 1, /* If the attach command succeeded. */
-       VIEWER_ATTACH_ALREADY   = 2, /* If a viewer is already attached. */
-       VIEWER_ATTACH_UNK       = 3, /* If the session ID is unknown. */
-       VIEWER_ATTACH_NOT_LIVE  = 4, /* If the session is not live. */
-       VIEWER_ATTACH_SEEK_ERR  = 5, /* Seek error. */
+       LTTNG_VIEWER_ATTACH_OK          = 1, /* The attach command succeeded. */
+       LTTNG_VIEWER_ATTACH_ALREADY     = 2, /* A viewer is already attached. */
+       LTTNG_VIEWER_ATTACH_UNK         = 3, /* The session ID is unknown. */
+       LTTNG_VIEWER_ATTACH_NOT_LIVE    = 4, /* The session is not live. */
+       LTTNG_VIEWER_ATTACH_SEEK_ERR    = 5, /* Seek error. */
 };
 
 enum lttng_viewer_next_index_return_code {
-       VIEWER_INDEX_OK         = 1, /* Index is available. */
-       VIEWER_INDEX_RETRY      = 2, /* Index not yet available. */
-       VIEWER_INDEX_HUP        = 3, /* Index closed (trace destroyed). */
-       VIEWER_INDEX_ERR        = 4, /* Unknow error. */
-       VIEWER_INDEX_INACTIVE   = 5, /* Inactive stream beacon. */
-       VIEWER_INDEX_EOF        = 6, /* End of index file. */
+       LTTNG_VIEWER_INDEX_OK           = 1, /* Index is available. */
+       LTTNG_VIEWER_INDEX_RETRY        = 2, /* Index not yet available. */
+       LTTNG_VIEWER_INDEX_HUP          = 3, /* Index closed (trace destroyed). */
+       LTTNG_VIEWER_INDEX_ERR          = 4, /* Unknow error. */
+       LTTNG_VIEWER_INDEX_INACTIVE     = 5, /* Inactive stream beacon. */
+       LTTNG_VIEWER_INDEX_EOF          = 6, /* End of index file. */
 };
 
 enum lttng_viewer_get_packet_return_code {
-       VIEWER_GET_PACKET_OK            = 1,
-       VIEWER_GET_PACKET_RETRY         = 2,
-       VIEWER_GET_PACKET_ERR           = 3,
-       VIEWER_GET_PACKET_EOF           = 4,
+       LTTNG_VIEWER_GET_PACKET_OK      = 1,
+       LTTNG_VIEWER_GET_PACKET_RETRY   = 2,
+       LTTNG_VIEWER_GET_PACKET_ERR     = 3,
+       LTTNG_VIEWER_GET_PACKET_EOF     = 4,
 };
 
 enum lttng_viewer_get_metadata_return_code {
-       VIEWER_METADATA_OK      = 1,
-       VIEWER_NO_NEW_METADATA  = 2,
-       VIEWER_METADATA_ERR     = 3,
+       LTTNG_VIEWER_METADATA_OK        = 1,
+       LTTNG_VIEWER_NO_NEW_METADATA    = 2,
+       LTTNG_VIEWER_METADATA_ERR       = 3,
 };
 
 enum lttng_viewer_connection_type {
-       VIEWER_CLIENT_COMMAND           = 1,
-       VIEWER_CLIENT_NOTIFICATION      = 2,
+       LTTNG_VIEWER_CLIENT_COMMAND             = 1,
+       LTTNG_VIEWER_CLIENT_NOTIFICATION        = 2,
 };
 
 enum lttng_viewer_seek {
        /* Receive the trace packets from the beginning. */
-       VIEWER_SEEK_BEGINNING   = 1,
+       LTTNG_VIEWER_SEEK_BEGINNING     = 1,
        /* Receive the trace packets from now. */
-       VIEWER_SEEK_LAST        = 2,
+       LTTNG_VIEWER_SEEK_LAST          = 2,
 };
 
 struct lttng_viewer_session {
@@ -112,26 +114,26 @@ struct lttng_viewer_cmd {
 } __attribute__((__packed__));
 
 /*
- * CONNECT payload.
+ * LTTNG_VIEWER_CONNECT payload.
  */
 struct lttng_viewer_connect {
        /* session ID assigned by the relay for command connections */
        uint64_t viewer_session_id;
        uint32_t major;
        uint32_t minor;
-       uint32_t type; /* enum lttng_viewer_connection_type */
+       uint32_t type;          /* enum lttng_viewer_connection_type */
 } __attribute__((__packed__));
 
 /*
- * VIEWER_LIST_SESSIONS payload.
+ * LTTNG_VIEWER_LIST_SESSIONS payload.
  */
 struct lttng_viewer_list_sessions {
        uint32_t sessions_count;
-       char session_list[];            /* struct lttng_viewer_session */
+       char session_list[];    /* struct lttng_viewer_session */
 } __attribute__((__packed__));
 
 /*
- * VIEWER_ATTACH_SESSION payload.
+ * LTTNG_VIEWER_ATTACH_SESSION payload.
  */
 struct lttng_viewer_attach_session_request {
        uint64_t session_id;
@@ -148,7 +150,7 @@ struct lttng_viewer_attach_session_response {
 } __attribute__((__packed__));
 
 /*
- * VIEWER_GET_NEXT_INDEX payload.
+ * LTTNG_VIEWER_GET_NEXT_INDEX payload.
  */
 struct lttng_viewer_get_next_index {
        uint64_t stream_id;
@@ -162,13 +164,12 @@ struct lttng_viewer_index {
        uint64_t timestamp_end;
        uint64_t events_discarded;
        uint64_t stream_id;
-       /* enum lttng_viewer_next_index_return_code */
-       uint32_t status;
-       uint32_t flags; /* LTTNG_VIEWER_FLAG_* */
+       uint32_t status;        /* enum lttng_viewer_next_index_return_code */
+       uint32_t flags;         /* LTTNG_VIEWER_FLAG_* */
 } __attribute__ ((__packed__));
 
 /*
- * VIEWER_GET_PACKET payload.
+ * LTTNG_VIEWER_GET_PACKET payload.
  */
 struct lttng_viewer_get_packet {
        uint64_t stream_id;
@@ -177,15 +178,14 @@ struct lttng_viewer_get_packet {
 } __attribute__((__packed__));
 
 struct lttng_viewer_trace_packet {
-       /* enum lttng_viewer_get_packet_return_code */
-       uint32_t status;
+       uint32_t status;        /* enum lttng_viewer_get_packet_return_code */
        uint32_t len;
-       uint32_t flags; /* LTTNG_VIEWER_FLAG_* */
+       uint32_t flags;         /* LTTNG_VIEWER_FLAG_* */
        char data[];
 } __attribute__((__packed__));
 
 /*
- * VIEWER_GET_METADATA payload.
+ * LTTNG_VIEWER_GET_METADATA payload.
  */
 struct lttng_viewer_get_metadata {
        uint64_t stream_id;
@@ -193,8 +193,7 @@ struct lttng_viewer_get_metadata {
 
 struct lttng_viewer_metadata_packet {
        uint64_t len;
-       /* enum lttng_viewer_get_metadata_return_code */
-       uint32_t status;
+       uint32_t status;        /* enum lttng_viewer_get_metadata_return_code */
        char data[];
 } __attribute__((__packed__));
 
index ec8839c37220e41595c8d162637936a61b4b4799..374f3e90c8d578ec71d6502f53438fd2d194c5c6 100644 (file)
 #include "common.h"
 #include "network-live.h"
 
-#include "ctf-index.h"
+#define NET_URL_PREFIX "net://"
+#define NET4_URL_PREFIX        "net4://"
+#define NET6_URL_PREFIX        "net6://"
 
 #define DEFAULT_FILE_ARRAY_SIZE 1
 
 const char *opt_input_path;
-static int opt_textdump;
-static int opt_child;
-static int opt_begin;
+int opt_textdump;
+int opt_child;
+int opt_begin;
 
 int quit = 0;
 
@@ -831,6 +833,19 @@ int bt_context_add_traces_recursive(struct bt_context *ctx, const char *path,
        char * const paths[2] = { lpath, NULL };
        int ret = -1;
 
+       if ((strncmp(path, NET4_URL_PREFIX, sizeof(NET4_URL_PREFIX) - 1)) == 0 ||
+                       (strncmp(path, NET6_URL_PREFIX, sizeof(NET6_URL_PREFIX) - 1)) == 0 ||
+                       (strncmp(path, NET_URL_PREFIX, sizeof(NET_URL_PREFIX) - 1)) == 0) {
+               ret = bt_context_add_trace(ctx,
+                               path, format_str, packet_seek, NULL, NULL);
+               if (ret < 0) {
+                       fprintf(stderr, "[warning] [Context] cannot open trace \"%s\" "
+                                       "for reading.\n", path);
+                       /* Allow to skip erroneous traces. */
+                       ret = 1;        /* partial error */
+               }
+               return ret;
+       }
        /*
         * Need to copy path, because fts_open can change it.
         * It is the pointer array, not the strings, that are constant.
@@ -1047,6 +1062,7 @@ int main(int argc, char **argv)
 #endif /* LTTNGTOP_MMAP_LIVE */
        } else if (!opt_input_path && remote_live) {
                /* network live */
+#if 0
                ret = setup_network_live(opt_relay_hostname, opt_begin);
                if (ret < 0) {
                        goto end;
@@ -1056,6 +1072,15 @@ int main(int argc, char **argv)
                if (ret < 0) {
                        goto end;
                }
+#endif
+
+               bt_ctx = bt_context_create();
+               ret = bt_context_add_traces_recursive(bt_ctx, opt_relay_hostname,
+                               "lttng-live", NULL);
+               if (ret < 0) {
+                       fprintf(stderr, "[error] Opening the trace\n");
+                       goto end;
+               }
        } else {
                //init_lttngtop();
 
@@ -1065,19 +1090,24 @@ int main(int argc, char **argv)
                        fprintf(stderr, "[error] Opening the trace\n");
                        goto end;
                }
-       }
 
-       ret = check_requirements(bt_ctx);
-       if (ret < 0) {
-               fprintf(stderr, "[error] some mandatory contexts were missing, exiting.\n");
-               goto end;
-       }
-       if (!opt_textdump) {
-               pthread_create(&display_thread, NULL, ncurses_display, (void *) NULL);
-               pthread_create(&timer_thread, NULL, refresh_thread, (void *) NULL);
+               ret = check_requirements(bt_ctx);
+               if (ret < 0) {
+                       fprintf(stderr, "[error] some mandatory contexts "
+                                       "were missing, exiting.\n");
+                       goto end;
+               }
+
+               if (!opt_textdump) {
+                       pthread_create(&display_thread, NULL, ncurses_display,
+                                       (void *) NULL);
+                       pthread_create(&timer_thread, NULL, refresh_thread,
+                                       (void *) NULL);
+               }
+
+               iter_trace(bt_ctx);
        }
 
-       iter_trace(bt_ctx);
 
        pthread_join(display_thread, NULL);
        quit = 1;
diff --git a/src/lttngtop.h b/src/lttngtop.h
new file mode 100644 (file)
index 0000000..526bfdc
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2014 Julien Desfossez
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License Version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef LTTNGTOP_H
+#define LTTNGTOP_H
+
+int check_requirements(struct bt_context *ctx);
+extern int opt_textdump;
+extern int opt_child;
+extern int opt_begin;
+
+extern pthread_t display_thread;
+extern pthread_t timer_thread;
+void *ncurses_display(void *p);
+void *refresh_thread(void *p);
+void iter_trace(struct bt_context *bt_ctx);
+
+#endif /* LTTNGTOP_H */
index 46a5b4d2d0c317cd80de5be78c527b24c7871452..31c1354397e4515f563d63a19f747f1f4ea8aa6a 100644 (file)
@@ -35,8 +35,8 @@
 #include <sys/mman.h>
 
 #include "lttng-viewer.h"
-#include "ctf-index.h"
 #include "network-live.h"
+#include "lttng-live-functions.h"
 
 #include <babeltrace/babeltrace.h>
 #include <babeltrace/ctf/events.h>
 #include <babeltrace/ctf/metadata.h>
 #include <babeltrace/ctf-text/types.h>
 #include <babeltrace/ctf/events-internal.h>
+#include <lib/babeltrace/ctf/ctf-index.h>
 
 /*
- * Memory allocation zeroed
+ * hostname parameter needs to hold NAME_MAX chars.
  */
-#define zmalloc(x) calloc(1, x)
-/* FIXME : completely arbitrary */
-#define mmap_size 524288
-
-static int control_sock;
-struct live_session *session;
-
-struct viewer_stream {
-       uint64_t id;
-       uint64_t ctf_trace_id;
-       void *mmap_base;
-       int fd;
-       int metadata_flag;
-       int first_read;
-       char path[PATH_MAX];
-};
-
-struct live_session {
-       struct viewer_stream *streams;
-       uint64_t live_timer_interval;
-       uint64_t stream_count;
-};
-
-static
-int connect_viewer(char *hostname)
+static int parse_url(const char *path, char *hostname, int *port,
+               uint64_t *session_id)
 {
-       struct hostent *host;
-       struct sockaddr_in server_addr;
-       int ret;
+       char remain[2][NAME_MAX];
+       int ret = -1, proto, proto_offset = 0;
+       size_t path_len = strlen(path);
 
-       host = gethostbyname(hostname);
-       if (!host) {
-               ret = -1;
+       /*
+        * Since sscanf API does not allow easily checking string length
+        * against a size defined by a macro. Test it beforehand on the
+        * input. We know the output is always <= than the input length.
+        */
+       if (path_len > NAME_MAX) {
                goto end;
        }
-
-       if ((control_sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
-               perror("Socket");
-               ret = -1;
-               goto end;
+       ret = sscanf(path, "net%d://", &proto);
+       if (ret < 1) {
+               proto = 4;
+               /* net:// */
+               proto_offset = strlen("net://");
+       } else {
+               /* net4:// or net6:// */
+               proto_offset = strlen("netX://");
        }
-
-       server_addr.sin_family = AF_INET;
-       server_addr.sin_port = htons(5344);
-       server_addr.sin_addr = *((struct in_addr *) host->h_addr);
-       bzero(&(server_addr.sin_zero), 8);
-
-       if (connect(control_sock, (struct sockaddr *) &server_addr,
-                               sizeof(struct sockaddr)) == -1) {
-               perror("Connect");
-               ret = -1;
+       if (proto_offset > path_len) {
                goto end;
        }
+       /* TODO : parse for IPv6 as well */
+       /* Parse the hostname or IP */
+       ret = sscanf(&path[proto_offset], "%[a-zA-Z.0-9%-]%s",
+               hostname, remain[0]);
+       if (ret == 2) {
+               /* Optional port number */
+               switch (remain[0][0]) {
+               case ':':
+                       ret = sscanf(remain[0], ":%d%s", port, remain[1]);
+                       /* Optional session ID with port number */
+                       if (ret == 2) {
+                               ret = sscanf(remain[1], "/%" PRIu64,
+                                       session_id);
+                               /* Accept 0 or 1 (optional) */
+                               if (ret < 0) {
+                                       goto end;
+                               }
+                       }
+                       break;
+               case '/':
+                       /* Optional session ID */
+                       ret = sscanf(remain[0], "/%" PRIu64, session_id);
+                       /* Accept 0 or 1 (optional) */
+                       if (ret < 0) {
+                               goto end;
+                       }
+                       break;
+               default:
+                       fprintf(stderr, "[error] wrong delimitor : %c\n",
+                               remain[0][0]);
+                       ret = -1;
+                       goto end;
+               }
+       }
 
-       server_addr.sin_family = AF_INET;
-       server_addr.sin_port = htons(5345);
-       server_addr.sin_addr = *((struct in_addr *) host->h_addr);
-       bzero(&(server_addr.sin_zero), 8);
+       if (*port < 0)
+               *port = LTTNG_DEFAULT_NETWORK_VIEWER_PORT;
 
+       if (*session_id == -1ULL)
+               printf_verbose("Connecting to hostname : %s, port : %d, "
+                               "proto : IPv%d\n",
+                               hostname, *port, proto);
+       else
+               printf_verbose("Connecting to hostname : %s, port : %d, "
+                               "session id : %" PRIu64 ", proto : IPv%d\n",
+                               hostname, *port, *session_id, proto);
        ret = 0;
 
 end:
        return ret;
 }
 
-static
-int establish_connection(void)
+static int lttng_live_open_trace_read(const char *path)
 {
-       struct lttng_viewer_cmd cmd;
-       struct lttng_viewer_connect connect;
-       int ret;
+       char hostname[NAME_MAX];
+       int port = -1;
+       uint64_t session_id = -1ULL;
+       int ret = 0;
+       struct lttng_live_ctx ctx;
 
-       cmd.cmd = htobe32(VIEWER_CONNECT);
-       cmd.data_size = sizeof(connect);
-       cmd.cmd_version = 0;
+       ctx.session = g_new0(struct lttng_live_session, 1);
 
-       connect.major = htobe32(2);
-       connect.minor = htobe32(4);
-       connect.type = htobe32(VIEWER_CLIENT_COMMAND);
+       /* We need a pointer to the context from the packet_seek function. */
+       ctx.session->ctx = &ctx;
 
-       do {
-               ret = send(control_sock, &cmd, sizeof(cmd), 0);
-       } while (ret < 0 && errno == EINTR);
-       if (ret < 0) {
-               fprintf(stderr, "Error sending cmd\n");
-               goto error;
-       }
-       do {
-               ret = send(control_sock, &connect, sizeof(connect), 0);
-       } while (ret < 0 && errno == EINTR);
-       if (ret < 0) {
-               fprintf(stderr, "Error sending version\n");
-               goto error;
-       }
+       /* HT to store the CTF traces. */
+       ctx.session->ctf_traces = g_hash_table_new(g_direct_hash,
+                       g_direct_equal);
 
-       do {
-               ret = recv(control_sock, &connect, sizeof(connect), 0);
-       } while (ret < 0 && errno == EINTR);
+       ret = parse_url(path, hostname, &port, &session_id);
        if (ret < 0) {
-               fprintf(stderr, "Error receiving version\n");
-               goto error;
+               goto end_free;
        }
-       fprintf(stderr, "  - Received viewer session ID : %" PRIu64 "\n",
-                       be64toh(connect.viewer_session_id));
-       fprintf(stderr, "  - Received version : %u.%u\n", be32toh(connect.major),
-                       be32toh(connect.minor));
 
-       ret = 0;
-
-error:
-       return ret;
-}
-
-int list_sessions(void)
-{
-       struct lttng_viewer_cmd cmd;
-       struct lttng_viewer_list_sessions list;
-       struct lttng_viewer_session lsession;
-       int i, ret;
-       int first_session = 0;
-
-       cmd.cmd = htobe32(VIEWER_LIST_SESSIONS);
-       cmd.data_size = 0;
-       cmd.cmd_version = 0;
-
-       do {
-               ret = send(control_sock, &cmd, sizeof(cmd), 0);
-       } while (ret < 0 && errno == EINTR);
+       ret = lttng_live_connect_viewer(&ctx, hostname, port);
        if (ret < 0) {
-               fprintf(stderr, "Error sending cmd\n");
-               goto error;
+               fprintf(stderr, "[error] Connection failed\n");
+               goto end_free;
        }
+       printf_verbose("LTTng-live connected to relayd\n");
 
-       do {
-               ret = recv(control_sock, &list, sizeof(list), 0);
-       } while (ret < 0 && errno == EINTR);
+       ret = lttng_live_establish_connection(&ctx);
        if (ret < 0) {
-               fprintf(stderr, "Error receiving session list\n");
-               goto error;
+               goto end_free;
        }
 
-       fprintf(stderr, "  - %u active session(s)\n", be32toh(list.sessions_count));
-       for (i = 0; i < be32toh(list.sessions_count); i++) {
-               do {
-                       ret = recv(control_sock, &lsession, sizeof(lsession), 0);
-               } while (ret < 0 && errno == EINTR);
+       if (session_id == -1ULL) {
+               printf_verbose("Listing sessions\n");
+               ret = lttng_live_list_sessions(&ctx, path);
                if (ret < 0) {
-                       fprintf(stderr, "Error receiving session\n");
-                       goto error;
-               }
-               fprintf(stderr, "    - %" PRIu64 " : %s on host %s (timer = %u, "
-                               "%u client(s) connected)\n",
-                               be64toh(lsession.id), lsession.session_name,
-                               lsession.hostname, be32toh(lsession.live_timer),
-                               be32toh(lsession.clients));
-               if (first_session <= 0) {
-                       first_session = be64toh(lsession.id);
+                       fprintf(stderr, "[error] List error\n");
+                       goto end_free;
                }
-       }
-
-       /* I know, type mismatch */
-       ret = (int) first_session;
-
-error:
-       return ret;
-}
-
-static
-int attach_session(int id, int begin)
-{
-       struct lttng_viewer_cmd cmd;
-       struct lttng_viewer_attach_session_request rq;
-       struct lttng_viewer_attach_session_response rp;
-       struct lttng_viewer_stream stream;
-       int ret, i;
-
-       cmd.cmd = htobe32(VIEWER_ATTACH_SESSION);
-       cmd.data_size = sizeof(rq);
-       cmd.cmd_version = 0;
-
-       rq.session_id = htobe64(id);
-       if (begin) {
-               rq.seek = htobe32(VIEWER_SEEK_BEGINNING);
        } else {
-               rq.seek = htobe32(VIEWER_SEEK_LAST);
-       }
-
-       do {
-               ret = send(control_sock, &cmd, sizeof(cmd), 0);
-       } while (ret < 0 && errno == EINTR);
-       if (ret < 0) {
-               fprintf(stderr, "Error sending cmd\n");
-               goto error;
-       }
-       do {
-               ret = send(control_sock, &rq, sizeof(rq), 0);
-       } while (ret < 0 && errno == EINTR);
-       if (ret < 0) {
-               fprintf(stderr, "Error sending attach request\n");
-               goto error;
-       }
-
-       do {
-               ret = recv(control_sock, &rp, sizeof(rp), 0);
-       } while (ret < 0 && errno == EINTR);
-       if (ret < 0) {
-               fprintf(stderr, "Error receiving attach response\n");
-               goto error;
-       }
-       fprintf(stderr, "  - session attach response : %u\n", be32toh(rp.status));
-       if (be32toh(rp.status) != VIEWER_ATTACH_OK) {
-               ret = 1;
-               goto end;
+               lttng_live_read(&ctx, session_id);
        }
 
-       session->stream_count = be32toh(rp.streams_count);
-       fprintf(stderr, "  - Waiting for %" PRIu64 " streams\n", session->stream_count);
-       session->streams = zmalloc(session->stream_count *
-                       sizeof(struct viewer_stream));
-       if (!session->streams) {
-               ret = -1;
-               goto error;
-       }
-
-       for (i = 0; i < be32toh(rp.streams_count); i++) {
-               do {
-                       ret = recv(control_sock, &stream, sizeof(stream), 0);
-               } while (ret < 0 && errno == EINTR);
-               if (ret < 0) {
-                       fprintf(stderr, "Error receiving stream\n");
-                       goto error;
-               }
-               fprintf(stderr, "    - stream %" PRIu64 " : %s/%s\n",
-                               be64toh(stream.id), stream.path_name,
-                               stream.channel_name);
-               session->streams[i].id = be64toh(stream.id);
-
-               session->streams[i].ctf_trace_id = be64toh(stream.ctf_trace_id);
-               session->streams[i].first_read = 1;
-               session->streams[i].mmap_base = mmap(NULL, mmap_size, PROT_READ | PROT_WRITE,
-                               MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
-               if (session->streams[i].mmap_base == MAP_FAILED) {
-                       fprintf(stderr, "mmap error\n");
-                       ret = -1;
-                       goto error;
-               }
-
-               if (be32toh(stream.metadata_flag)) {
-                       session->streams[i].metadata_flag = 1;
-                       unlink("testlivetrace");
-                       mkdir("testlivetrace", S_IRWXU | S_IRWXG);
-                       snprintf(session->streams[i].path,
-                                       sizeof(session->streams[i].path),
-                                       "testlivetrace/%s",
-                                       stream.channel_name);
-                       ret = open(session->streams[i].path,
-                                       O_WRONLY | O_CREAT | O_TRUNC,
-                                       S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
-                       if (ret < 0) {
-                               goto error;
-                       }
-                       session->streams[i].fd = ret;
-               }
-       }
-       ret = 0;
-
-end:
-error:
+end_free:
+       g_hash_table_destroy(ctx.session->ctf_traces);
+       g_free(ctx.session);
+       g_free(ctx.session->streams);
        return ret;
 }
 
-#if 0
-/* useful debug */
-static
-void dump_packet_index(struct lttng_packet_index *index)
-{
-       printf("      - index : %lu, %lu, %lu, %lu, %lu, %lu, %lu\n",
-                       be64toh(index->offset),
-                       be64toh(index->packet_size),
-                       be64toh(index->content_size),
-                       be64toh(index->timestamp_begin),
-                       be64toh(index->timestamp_end),
-                       be64toh(index->events_discarded),
-                       be64toh(index->stream_id));
-}
-#endif
-
 static
-int get_data_packet(int id, uint64_t offset,
-               uint64_t len)
+struct bt_trace_descriptor *lttng_live_open_trace(const char *path, int flags,
+               void (*packet_seek)(struct bt_stream_pos *pos, size_t index,
+                       int whence), FILE *metadata_fp)
 {
-       struct lttng_viewer_cmd cmd;
-       struct lttng_viewer_get_packet rq;
-       struct lttng_viewer_trace_packet rp;
-       int ret;
-
-       cmd.cmd = htobe32(VIEWER_GET_PACKET);
-       cmd.data_size = sizeof(rq);
-       cmd.cmd_version = 0;
-
-       rq.stream_id = htobe64(session->streams[id].id);
-       /* Already in big endian. */
-       rq.offset = offset;
-       rq.len = htobe32(len);
-       fprintf(stderr, "      - get_packet ");
-
-       do {
-               ret = send(control_sock, &cmd, sizeof(cmd), 0);
-       } while (ret < 0 && errno == EINTR);
-       if (ret < 0) {
-               fprintf(stderr, "Error sending cmd\n");
-               goto error;
-       }
-       do {
-               ret = send(control_sock, &rq, sizeof(rq), 0);
-       } while (ret < 0 && errno == EINTR);
-       if (ret < 0) {
-               fprintf(stderr, "Error sending get_data_packet request\n");
-               goto error;
-       }
-       do {
-               ret = recv(control_sock, &rp, sizeof(rp), 0);
-       } while (ret < 0 && errno == EINTR);
-       if (ret < 0) {
-               fprintf(stderr, "Error receiving data response\n");
-               goto error;
-       }
-       rp.flags = be32toh(rp.flags);
+       struct ctf_text_stream_pos *pos;
 
-       switch (be32toh(rp.status)) {
-       case VIEWER_GET_PACKET_OK:
-               fprintf(stderr, "OK\n");
+       switch (flags & O_ACCMODE) {
+       case O_RDONLY:
+               /* OK */
                break;
-       case VIEWER_GET_PACKET_RETRY:
-               fprintf(stderr, "RETRY\n");
-               ret = -1;
-               goto end;
-       case VIEWER_GET_PACKET_ERR:
-               if (rp.flags & LTTNG_VIEWER_FLAG_NEW_METADATA) {
-                       fprintf(stderr, "NEW_METADATA\n");
-                       ret = 0;
-                       goto end;
-               }
-               fprintf(stderr, "ERR\n");
-               ret = -1;
-               goto end;
+       case O_RDWR:
+               fprintf(stderr, "[error] lttng live plugin cannot be used as output plugin.\n");
+               goto error;
        default:
-               fprintf(stderr, "UNKNOWN\n");
-               ret = -1;
-               goto end;
-       }
-
-       len = be32toh(rp.len);
-       fprintf(stderr, "        - writing %" PRIu64" bytes to tracefile\n", len);
-       if (len <= 0) {
-               goto end;
-       }
-
-       if (len > mmap_size) {
-               fprintf(stderr, "mmap_size not big enough\n");
-               ret = -1;
+               fprintf(stderr, "[error] Incorrect open flags.\n");
                goto error;
        }
 
-       do {
-               ret = recv(control_sock, session->streams[id].mmap_base, len, MSG_WAITALL);
-       } while (ret < 0 && errno == EINTR);
-       if (ret < 0) {
-               fprintf(stderr, "Error receiving trace packet\n");
-               goto error;
-       }
+       pos = g_new0(struct ctf_text_stream_pos, 1);
+       pos->parent.rw_table = NULL;
+       pos->parent.event_cb = NULL;
+       pos->parent.trace = &pos->trace_descriptor;
+       lttng_live_open_trace_read(path);
+       return &pos->trace_descriptor;
 
-end:
 error:
-       return ret;
+       return NULL;
 }
 
-/*
- * Return number of metadata bytes written or a negative value on error.
- */
 static
-int get_new_metadata(int id)
+int lttng_live_close_trace(struct bt_trace_descriptor *td)
 {
-       struct lttng_viewer_cmd cmd;
-       struct lttng_viewer_get_metadata rq;
-       struct lttng_viewer_metadata_packet rp;
-       int ret;
-       uint64_t i;
-       char *data = NULL;
-       uint64_t len = 0;
-       int metadata_stream_id = -1;
-
-       cmd.cmd = htobe32(VIEWER_GET_METADATA);
-       cmd.data_size = sizeof(rq);
-       cmd.cmd_version = 0;
-
-       /* find the metadata stream for this ctf_trace */
-       for (i = 0; i < session->stream_count; i++) {
-               if (session->streams[i].metadata_flag &&
-                               session->streams[i].ctf_trace_id ==
-                               session->streams[id].ctf_trace_id) {
-                       metadata_stream_id = i;
-                       break;
-               }
-       }
-       if (metadata_stream_id < 0) {
-               fprintf(stderr, "No metadata stream found\n");
-               ret = -1;
-               goto error;
-       }
-
-       rq.stream_id = htobe64(session->streams[metadata_stream_id].id);
-       fprintf(stderr, "      - get_metadata ");
-
-       do {
-               ret = send(control_sock, &cmd, sizeof(cmd), 0);
-       } while (ret < 0 && errno == EINTR);
-       if (ret < 0) {
-               fprintf(stderr, "Error sending cmd\n");
-               goto error;
-       }
-       do {
-               ret = send(control_sock, &rq, sizeof(rq), 0);
-       } while (ret < 0 && errno == EINTR);
-       if (ret < 0) {
-               fprintf(stderr, "Error sending get_metadata request\n");
-               goto error;
-       }
-       do {
-               ret = recv(control_sock, &rp, sizeof(rp), 0);
-       } while (ret < 0 && errno == EINTR);
-       if (ret < 0) {
-               fprintf(stderr, "Error receiving metadata response\n");
-               goto error;
-       }
-       switch (be32toh(rp.status)) {
-               case VIEWER_METADATA_OK:
-                       fprintf(stderr, "OK\n");
-                       break;
-               case VIEWER_NO_NEW_METADATA:
-                       fprintf(stderr, "NO NEW\n");
-                       ret = -1;
-                       goto end;
-               case VIEWER_METADATA_ERR:
-                       fprintf(stderr, "ERR\n");
-                       ret = -1;
-                       goto end;
-               default:
-                       fprintf(stderr, "UNKNOWN\n");
-                       ret = -1;
-                       goto end;
-       }
-
-       len = be64toh(rp.len);
-       fprintf(stderr, "        - writing %" PRIu64" bytes to metadata\n", len);
-       if (len <= 0) {
-               goto end;
-       }
-
-       data = zmalloc(len);
-       if (!data) {
-               perror("relay data zmalloc");
-               goto error;
-       }
-       do {
-               ret = recv(control_sock, data, len, MSG_WAITALL);
-       } while (ret < 0 && errno == EINTR);
-       if (ret < 0) {
-               fprintf(stderr, "Error receiving trace packet\n");
-               free(data);
-               goto error;
-       }
-       do {
-               ret = write(session->streams[metadata_stream_id].fd, data, len);
-       } while (ret < 0 && errno == EINTR);
-       if (ret < 0) {
-               free(data);
-               goto error;
-       }
-       free(data);
-
-       /* FIXME : bad */
-       ret = (int) len;
-end:
-error:
-       return ret;
+       struct ctf_text_stream_pos *pos =
+               container_of(td, struct ctf_text_stream_pos,
+                       trace_descriptor);
+       free(pos);
+       return 0;
 }
 
-/*
- * Get one index for a stream.
- */
-int get_next_index(int id, struct packet_index *index)
-{
-       struct lttng_viewer_cmd cmd;
-       struct lttng_viewer_get_next_index rq;
-       struct lttng_viewer_index rp;
-       int ret;
-
-       cmd.cmd = htobe32(VIEWER_GET_NEXT_INDEX);
-       cmd.data_size = sizeof(rq);
-       cmd.cmd_version = 0;
-
-       fprintf(stderr, "  - get next index for stream %" PRIu64 "\n",
-                       session->streams[id].id);
-       rq.stream_id = htobe64(session->streams[id].id);
-
-retry:
-       do {
-               ret = send(control_sock, &cmd, sizeof(cmd), 0);
-       } while (ret < 0 && errno == EINTR);
-       if (ret < 0) {
-               fprintf(stderr, "Error sending cmd\n");
-               goto error;
-       }
-       do {
-               ret = send(control_sock, &rq, sizeof(rq), 0);
-       } while (ret < 0 && errno == EINTR);
-       if (ret < 0) {
-               fprintf(stderr, "Error sending get_next_index request\n");
-               goto error;
-       }
-       do {
-               ret = recv(control_sock, &rp, sizeof(rp), 0);
-       } while (ret < 0 && errno == EINTR);
-       if (ret < 0) {
-               fprintf(stderr, "Error receiving index response\n");
-               goto error;
-       }
-       fprintf(stderr, "    - reply : %u ", be32toh(rp.status));
-
-       rp.flags = be32toh(rp.flags);
-
-       switch (be32toh(rp.status)) {
-       case VIEWER_INDEX_INACTIVE:
-               fprintf(stderr, "(INACTIVE)\n");
-               memset(index, 0, sizeof(struct packet_index));
-               index->timestamp_end = be64toh(rp.timestamp_end);
-               break;
-       case VIEWER_INDEX_OK:
-               fprintf(stderr, "(OK), need metadata update : %u\n",
-                               rp.flags & LTTNG_VIEWER_FLAG_NEW_METADATA);
-               index->offset = be64toh(rp.offset);
-               index->packet_size = be64toh(rp.packet_size);
-               index->content_size = be64toh(rp.content_size);
-               index->timestamp_begin = be64toh(rp.timestamp_begin);
-               index->timestamp_end = be64toh(rp.timestamp_end);
-               index->events_discarded = be64toh(rp.events_discarded);
-
-               if (rp.flags & LTTNG_VIEWER_FLAG_NEW_METADATA) {
-                       fprintf(stderr, "NEW METADATA NEEDED\n");
-                       ret = get_new_metadata(id);
-                       if (ret < 0) {
-                               goto error;
-                       }
-               }
-               break;
-       case VIEWER_INDEX_RETRY:
-               fprintf(stderr, "(RETRY)\n");
-               sleep(1);
-               goto retry;
-       case VIEWER_INDEX_HUP:
-               fprintf(stderr, "(HUP)\n");
-               session->streams[id].id = -1ULL;
-               session->streams[id].fd = -1;
-               break;
-       case VIEWER_INDEX_ERR:
-               fprintf(stderr, "(ERR)\n");
-               ret = -1;
-               goto error;
-       default:
-               fprintf(stderr, "SHOULD NOT HAPPEN\n");
-               ret = -1;
-               goto error;
-       }
-
-error:
-       return ret;
-}
+static
+struct bt_format lttng_live_format = {
+       .open_trace = lttng_live_open_trace,
+       .close_trace = lttng_live_close_trace,
+};
 
-void ctf_live_packet_seek(struct bt_stream_pos *stream_pos, size_t index,
-               int whence)
+static
+void __attribute__((constructor)) lttng_live_init(void)
 {
-       struct ctf_stream_pos *pos;
-       struct ctf_file_stream *file_stream;
-       struct packet_index packet_index;
        int ret;
 
-       pos = ctf_pos(stream_pos);
-       file_stream = container_of(pos, struct ctf_file_stream, pos);
-
-       fprintf(stderr, "BT GET_NEXT_INDEX %d\n", pos->fd);
-       ret = get_next_index(pos->fd, &packet_index);
-       if (ret < 0) {
-               fprintf(stderr, "get_next_index failed\n");
-               return;
-       }
-
-       pos->packet_size = packet_index.packet_size;
-       pos->content_size = packet_index.content_size;
-       pos->mmap_base_offset = 0;
-       pos->offset = 0;
-       if (packet_index.offset == EOF) {
-               pos->offset = EOF;
-       } else {
-               pos->offset = 0;
-       }
-
-       file_stream->parent.cycles_timestamp = packet_index.timestamp_end;
-       file_stream->parent.real_timestamp = ctf_get_real_timestamp(
-                       &file_stream->parent, packet_index.timestamp_end);
-
-       if (pos->packet_size == 0) {
-               goto end;
-       }
-
-       fprintf(stderr, "BT GET_DATA_PACKET\n");
-       ret = get_data_packet(pos->fd, be64toh(packet_index.offset),
-                       packet_index.packet_size / CHAR_BIT);
-       if (ret < 0) {
-               fprintf(stderr, "get_data_packet failed");
-               return;
-       }
-
-       fprintf(stderr, "BT MMAP %d\n", pos->fd);
-       fprintf(stderr, "packet_size : %lu, offset %lu, content_size %lu, timestamp_end : %lu, real : %lu\n",
-                       packet_index.packet_size,
-                       packet_index.offset,
-                       packet_index.content_size,
-                       packet_index.timestamp_end,
-                       ctf_get_real_timestamp(
-                               &file_stream->parent, packet_index.timestamp_end));
-       if (!pos->base_mma) {
-               pos->base_mma = zmalloc(sizeof(*pos->base_mma));
-               if (!pos->base_mma) {
-                       fprintf(stderr, "alloc pos->base_mma\n");
-                       return;
-               }
-       }
-
-       mmap_align_set_addr(pos->base_mma, session->streams[pos->fd].mmap_base);
-       if (pos->base_mma == MAP_FAILED) {
-               perror("Error mmaping");
-               return;
-       }
-
-       /* update trace_packet_header and stream_packet_context */
-       if (pos->prot != PROT_WRITE && file_stream->parent.trace_packet_header) {
-               /* Read packet header */
-               ret = generic_rw(&pos->parent, &file_stream->parent.trace_packet_header->p);
-               assert(!ret);
-       }
-       if (pos->prot != PROT_WRITE && file_stream->parent.stream_packet_context) {
-               /* Read packet context */
-               ret = generic_rw(&pos->parent, &file_stream->parent.stream_packet_context->p);
-               assert(!ret);
-       }
-
-end:
-       return;
+       lttng_live_format.name = g_quark_from_static_string("lttng-live");
+       ret = bt_register_format(&lttng_live_format);
+       assert(!ret);
 }
 
-int open_trace(struct bt_context **bt_ctx)
-{
-       struct bt_mmap_stream *new_mmap_stream;
-       struct bt_mmap_stream_list mmap_list;
-       FILE *metadata_fp = NULL;
-       int i;
-       int ret = 0;
-
-       *bt_ctx = bt_context_create();
-       BT_INIT_LIST_HEAD(&mmap_list.head);
-
-       for (i = 0; i < session->stream_count; i++) {
-               int total_metadata = 0;
-
-               if (!session->streams[i].metadata_flag) {
-                       new_mmap_stream = zmalloc(sizeof(struct bt_mmap_stream));
-                       /*
-                        * The FD is unused when we handle manually the
-                        * packet seek, so we store here the ID of the
-                        * stream in our stream list to be able to use it
-                        * later.
-                        */
-                       new_mmap_stream->fd = i;
-                       bt_list_add(&new_mmap_stream->list, &mmap_list.head);
-               } else {
-                       /* Get all possible metadata before starting */
-                       do {
-                               ret = get_new_metadata(i);
-                               if (ret > 0) {
-                                       total_metadata += ret;
-                               }
-                       } while (ret > 0 || total_metadata == 0);
-                       metadata_fp = fopen(session->streams[i].path, "r");
-               }
-       }
-
-       if (!metadata_fp) {
-               fprintf(stderr, "No metadata stream opened\n");
-               goto end;
-       }
-
-       ret = bt_context_add_trace(*bt_ctx, NULL, "ctf",
-                       ctf_live_packet_seek, &mmap_list, metadata_fp);
-       if (ret < 0) {
-               fprintf(stderr, "Error adding trace\n");
-               goto end;
-       }
-
-       /*
-       begin_pos.type = BT_SEEK_BEGIN;
-       iter = bt_ctf_iter_create(bt_ctx, &begin_pos, NULL);
-       while ((event = bt_ctf_iter_read_event(iter)) != NULL) {
-               if (!skip) {
-                       ret = sout->parent.event_cb(&sout->parent, event->parent->stream);
-                       if (ret) {
-                               fprintf(stderr, "[error] Writing event failed.\n");
-                               goto end;
-                       }
-               }
-
-               ret = bt_iter_next(bt_ctf_get_iter(iter));
-               if (ret < 0) {
-                       goto end;
-               } else if (ret == EAGAIN) {
-                       skip = 1;
-                       continue;
-               }
-               skip = 0;
-       }
-       */
-
-end:
-       return ret;
-}
-
-int setup_network_live(char *hostname, int begin)
+static
+void __attribute__((destructor)) lttng_live_exit(void)
 {
-       int ret;
-       int session_id;
-
-       session = zmalloc(sizeof(struct live_session));
-       if (!session) {
-               goto error;
-       }
-
-       ret = connect_viewer(hostname);
-       if (ret < 0) {
-               goto error;
-       }
-       fprintf(stderr, "* Connected\n");
-
-       fprintf(stderr, "* Establish connection and version check\n");
-       ret = establish_connection();
-       if (ret < 0) {
-               goto error;
-       }
-
-       fprintf(stderr, "* List sessions\n");
-       ret = list_sessions();
-       if (ret < 0) {
-               fprintf(stderr, "* List error\n");
-               goto error;
-       } else if (ret == 0) {
-               fprintf(stderr, "* No session to attach to, exiting\n");
-               ret = 0;
-               goto end;
-       }
-       session_id = ret;
-
-       do {
-               fprintf(stderr, "* Attach session %d\n", ret);
-               ret = attach_session(session_id, begin);
-               if (ret < 0) {
-                       goto error;
-               }
-       } while (session->stream_count == 0);
-
-end:
-       return 0;
-
-error:
-       free(session->streams);
-       fprintf(stderr, "* Exiting %d\n", ret);
-       return ret;
+       bt_unregister_format(&lttng_live_format);
 }
index b84fc0ba645b057a9ebdd2b8f57f9076c495c59b..5d8e5df2623aea7116ce596526dd074255a60caa 100644 (file)
@@ -21,7 +21,7 @@
 #include <lib/babeltrace/ctf/types.h>
 #include <lib/babeltrace/ctf-ir/metadata.h>
 #include <lib/babeltrace/clock-internal.h>
-#include "ctf-index.h"
+#include <lib/babeltrace/ctf/ctf-index.h>
 
 /* Copied from babeltrace/formats/ctf/events-private.h */
 static inline
@@ -43,12 +43,4 @@ uint64_t ctf_get_real_timestamp(struct ctf_stream_definition *stream,
        return ts_nsec;
 }
 
-int list_sessions(void);
-void dump_packet_index(struct ctf_packet_index *index);
-int get_next_index(int id, struct packet_index *index);
-void ctf_live_packet_seek(struct bt_stream_pos *stream_pos, size_t index,
-               int whence);
-int open_trace(struct bt_context **bt_ctx);
-int setup_network_live(char *hostname, int begin);
-
 #endif /* _LIVE_H */
This page took 0.109668 seconds and 4 git commands to generate.