plugins \
cli \
bindings \
- tests \
doc \
- extras
+ extras \
+ tests
dist_doc_DATA = ChangeLog LICENSE mit-license.txt gpl-2.0.txt \
std-ext-lib.txt README CONTRIBUTING.adoc
babeltrace/ctf-ir/clock.h \
babeltrace/ctf-ir/event-class.h \
babeltrace/ctf-ir/event.h \
+ babeltrace/ctf-ir/event-header-field.h \
babeltrace/ctf-ir/field-path.h \
babeltrace/ctf-ir/field-types.h \
babeltrace/ctf-ir/fields.h \
babeltrace/ctf-ir/packet.h \
+ babeltrace/ctf-ir/packet-context-field.h \
+ babeltrace/ctf-ir/packet-header-field.h \
babeltrace/ctf-ir/stream-class.h \
babeltrace/ctf-ir/stream.h \
babeltrace/ctf-ir/trace.h \
babeltrace/common-internal.h \
babeltrace/bitfield-internal.h \
babeltrace/object-internal.h \
+ babeltrace/object-pool-internal.h \
babeltrace/plugin/plugin-internal.h \
babeltrace/plugin/plugin-so-internal.h \
babeltrace/plugin/python-plugin-provider-internal.h \
babeltrace/ctf-ir/stream-class-internal.h \
babeltrace/ctf-ir/event-internal.h \
babeltrace/ctf-ir/field-path-internal.h \
+ babeltrace/ctf-ir/field-wrapper-internal.h \
babeltrace/ctf-ir/trace-internal.h \
babeltrace/ctf-ir/clock-class-internal.h \
babeltrace/ctf-ir/field-types-internal.h \
*/
#include <assert.h>
+#include <babeltrace/babeltrace-internal.h>
#ifdef BT_DEBUG_MODE
/*
* In-depth explanation: https://stackoverflow.com/questions/37411809/how-to-elegantly-fix-this-unused-variable-warning/37412551#37412551
*/
# define BT_ASSERT(_cond) ((void) sizeof((void) (_cond), 0))
-# define BT_ASSERT_FUNC __attribute__((unused))
+# define BT_ASSERT_FUNC BT_UNUSED
#endif /* BT_DEBUG_MODE */
#endif /* BABELTRACE_ASSERT_INTERNAL_H */
#ifndef BABELTRACE_ASSERT_PRE_INTERNAL_H
#define BABELTRACE_ASSERT_PRE_INTERNAL_H
+#include <babeltrace/babeltrace-internal.h>
+
/*
* Copyright (c) 2018 EfficiOS Inc. and Linux Foundation
* Copyright (c) 2018 Philippe Proulx <pproulx@efficios.com>
* also need to define it before including this header.
*
* This is a reminder that in order to use
- * <babeltrace/assert-internal.hpp>, you also need to use logging
+ * <babeltrace/assert-pre-internal.h>, you also need to use logging
* explicitly.
*/
#ifndef BABELTRACE_LIB_LOGGING_INTERNAL_H
# define BT_ASSERT_PRE_MSG BT_LIB_LOGF
#else
# define BT_ASSERT_PRE(_cond, _fmt, ...)
-# define BT_ASSERT_PRE_FUNC __attribute__((unused))
+# define BT_ASSERT_PRE_FUNC BT_UNUSED
# define BT_ASSERT_PRE_MSG(_fmt, ...)
#endif /* BT_DEV_MODE */
#define TOSTRING(x) __STRINGIFY(x)
+#define BT_UNUSED __attribute__((unused))
+
#endif
#include <babeltrace/ctf-ir/clock-value.h>
#include <babeltrace/ctf-ir/clock.h>
#include <babeltrace/ctf-ir/event-class.h>
+#include <babeltrace/ctf-ir/event-header-field.h>
#include <babeltrace/ctf-ir/event.h>
#include <babeltrace/ctf-ir/field-path.h>
#include <babeltrace/ctf-ir/field-types.h>
#include <babeltrace/ctf-ir/fields.h>
+#include <babeltrace/ctf-ir/packet-context-field.h>
+#include <babeltrace/ctf-ir/packet-header-field.h>
#include <babeltrace/ctf-ir/packet.h>
#include <babeltrace/ctf-ir/stream-class.h>
#include <babeltrace/ctf-ir/stream.h>
#include <babeltrace/ctf-ir/clock-class.h>
#include <babeltrace/object-internal.h>
#include <babeltrace/babeltrace-internal.h>
+#include <babeltrace/object-pool-internal.h>
#include <babeltrace/compat/uuid-internal.h>
#include <babeltrace/types.h>
#include <stdbool.h>
* class.
*/
int frozen;
+
+ /* Pool of `struct bt_clock_value *` */
+ struct bt_object_pool cv_pool;
};
BT_HIDDEN
struct bt_clock_class *clock_class);
extern int bt_clock_class_set_uuid(struct bt_clock_class *clock_class,
const unsigned char *uuid);
+extern int bt_clock_class_cycles_to_ns(struct bt_clock_class *clock_class,
+ uint64_t cycles, int64_t *ns);
#ifdef __cplusplus
}
* SOFTWARE.
*/
+#include <babeltrace/babeltrace-internal.h>
#include <babeltrace/object-internal.h>
#include <stdbool.h>
#include <stdint.h>
uint64_t value;
bool ns_from_epoch_overflows;
int64_t ns_from_epoch;
+ bool is_set;
+ bool frozen;
};
+static inline
+void bt_clock_value_set(struct bt_clock_value *clock_value)
+{
+ BT_ASSERT(clock_value);
+ clock_value->is_set = true;
+}
+
+static inline
+void bt_clock_value_reset(struct bt_clock_value *clock_value)
+{
+ BT_ASSERT(clock_value);
+ clock_value->is_set = false;
+}
+
+BT_UNUSED
+static inline
+void _bt_clock_value_set_is_frozen(struct bt_clock_value *clock_value,
+ bool is_frozen)
+{
+ BT_ASSERT(clock_value);
+ clock_value->frozen = is_frozen;
+}
+
+#ifdef BT_DEV_MODE
+# define bt_clock_value_set_is_frozen _bt_clock_value_set_is_frozen
+#else
+# define bt_clock_value_set_is_frozen(_x, _f)
+#endif /* BT_DEV_MODE */
+
+BT_HIDDEN
+struct bt_clock_value *bt_clock_value_create(
+ struct bt_clock_class *clock_class);
+
+BT_HIDDEN
+void bt_clock_value_recycle(struct bt_clock_value *clock_value);
+
+BT_HIDDEN
+void bt_clock_value_set_raw_value(struct bt_clock_value *clock_value,
+ uint64_t cycles);
+
#endif /* BABELTRACE_CTF_IR_CLOCK_VALUE_INTERNAL_H */
struct bt_clock_class;
struct bt_clock_value;
-extern struct bt_clock_value *bt_clock_value_create(
- struct bt_clock_class *clock_class, uint64_t value);
extern struct bt_clock_class *bt_clock_value_borrow_class(
struct bt_clock_value *clock_value);
return bt_get(bt_clock_value_borrow_class(clock_value));
}
+extern int bt_clock_value_set_value(
+ struct bt_clock_value *clock_value, uint64_t raw_value);
extern int bt_clock_value_get_value(
struct bt_clock_value *clock_value, uint64_t *raw_value);
extern int bt_clock_value_get_value_ns_from_epoch(
#include <babeltrace/ctf-ir/event-class.h>
#include <babeltrace/object-internal.h>
#include <babeltrace/assert-internal.h>
+#include <babeltrace/object-pool-internal.h>
#include <glib.h>
struct bt_event_class_common {
struct bt_event_class {
struct bt_event_class_common common;
+
+ /* Pool of `struct bt_event *` */
+ struct bt_object_pool event_pool;
};
BT_HIDDEN
struct bt_event_class_common *event_class,
struct bt_clock_class **expected_clock_class);
+BT_HIDDEN
+int bt_event_class_update_event_pool_clock_values(
+ struct bt_event_class *event_class);
+
static inline
const char *bt_event_class_common_get_name(
struct bt_event_class_common *event_class)
--- /dev/null
+#ifndef BABELTRACE_CTF_IR_EVENT_HEADER_FIELD_H
+#define BABELTRACE_CTF_IR_EVENT_HEADER_FIELD_H
+
+/*
+ * Copyright 2018 Philippe Proulx <pproulx@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * The Common Trace Format (CTF) Specification is available at
+ * http://www.efficios.com/ctf
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct bt_event_header_field;
+struct bt_field;
+
+extern
+struct bt_field *bt_event_header_field_borrow_field(
+ struct bt_event_header_field *field);
+
+extern
+void bt_event_header_field_release(struct bt_event_header_field *field);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BABELTRACE_CTF_IR_EVENT_HEADER_FIELD_H */
#include <babeltrace/ctf-ir/fields.h>
#include <babeltrace/ctf-ir/fields-internal.h>
#include <babeltrace/ctf-ir/event-class-internal.h>
+#include <babeltrace/ctf-ir/field-wrapper-internal.h>
#include <babeltrace/ctf-ir/validation-internal.h>
#include <babeltrace/object-internal.h>
#include <babeltrace/assert-internal.h>
struct bt_event_common {
struct bt_object base;
struct bt_event_class_common *class;
- struct bt_field_common *header_field;
+ struct bt_field_wrapper *header_field;
struct bt_field_common *stream_event_context_field;
struct bt_field_common *context_field;
struct bt_field_common *payload_field;
int (*map_clock_classes_func)(struct bt_stream_class_common *stream_class,
struct bt_field_type_common *packet_context_field_type,
struct bt_field_type_common *event_header_field_type),
- void *(*create_field_func)(void *));
+ void *(*create_field_func)(void *),
+ void (*release_field_func)(void *),
+ void *(*create_header_field_func)(void *, void *),
+ void (*release_header_field_func)(void *));
static inline
struct bt_field_common *bt_event_common_borrow_payload(
return payload;
}
-static inline
-int bt_event_common_set_payload(struct bt_event_common *event,
- struct bt_field_common *payload)
-{
- BT_ASSERT_PRE_NON_NULL(event, "Event");
- BT_ASSERT_PRE_EVENT_COMMON_HOT(event, "Event");
-
- if (payload) {
- BT_ASSERT_PRE(bt_field_type_common_compare(payload->type,
- event->class->payload_field_type) == 0,
- "Payload field's type is different from the "
- "expected field type: %![event-]+_e, %![ft-]+_F, "
- "%![expected-ft-]+_F",
- event, payload->type,
- event->class->payload_field_type);
- } else {
- BT_ASSERT_PRE(!event->class->payload_field_type,
- "Setting no event payload field, "
- "but event payload field type is not NULL: ",
- "%![event-]+_e, %![payload-ft-]+_F",
- event, event->class->payload_field_type);
- }
-
- bt_put(event->payload_field);
- event->payload_field = bt_get(payload);
- BT_LOGV("Set event's payload field: event-addr=%p, "
- "event-class-name=\"%s\", event-class-id=%" PRId64 ", "
- "payload-field-addr=%p",
- event, bt_event_class_common_get_name(event->class),
- bt_event_class_common_get_id(event->class), payload);
- return 0;
-}
-
static inline
struct bt_field_common *bt_event_common_borrow_header(
struct bt_event_common *event)
goto end;
}
- header = event->header_field;
+ header = event->header_field->field;
end:
return header;
}
-static inline
-int bt_event_common_set_header(struct bt_event_common *event,
- struct bt_field_common *header)
-{
- BT_ASSERT_PRE_NON_NULL(event, "Event");
- BT_ASSERT_PRE_EVENT_COMMON_HOT(event, "Event");
-
- /*
- * Ensure the provided header's type matches the one registered to the
- * stream class.
- */
- if (header) {
- BT_ASSERT_PRE(bt_field_type_common_compare(header->type,
- bt_event_class_common_borrow_stream_class(event->class)->event_header_field_type) == 0,
- "Header field's type is different from the "
- "expected field type: %![event-]+_e, %![ft-]+_F, "
- "%![expected-ft-]+_F",
- event, header->type,
- bt_event_class_common_borrow_stream_class(event->class)->event_header_field_type);
- } else {
- BT_ASSERT_PRE(!bt_event_class_common_borrow_stream_class(event->class)->event_header_field_type,
- "Setting no event header field, "
- "but event header field type is not NULL: ",
- "%![event-]+_e, %![header-ft-]+_F",
- event,
- bt_event_class_common_borrow_stream_class(event->class)->event_header_field_type);
- }
-
- bt_put(event->header_field);
- event->header_field = bt_get(header);
- BT_LOGV("Set event's header field: event-addr=%p, "
- "event-class-name=\"%s\", event-class-id=%" PRId64 ", "
- "header-field-addr=%p",
- event, bt_event_class_common_get_name(event->class),
- bt_event_class_common_get_id(event->class), header);
- return 0;
-}
-
static inline
struct bt_field_common *bt_event_common_borrow_context(
struct bt_event_common *event)
return context;
}
-static inline
-int bt_event_common_set_context(struct bt_event_common *event,
- struct bt_field_common *context)
-{
- BT_ASSERT_PRE_NON_NULL(event, "Event");
- BT_ASSERT_PRE_EVENT_COMMON_HOT(event, "Event");
-
- if (context) {
- BT_ASSERT_PRE(bt_field_type_common_compare(context->type,
- event->class->context_field_type) == 0,
- "Context field's type is different from the "
- "expected field type: %![event-]+_e, %![ft-]+_F, "
- "%![expected-ft-]+_F",
- event, context->type, event->class->context_field_type);
- } else {
- BT_ASSERT_PRE(!event->class->context_field_type,
- "Setting no event context field, "
- "but event context field type is not NULL: ",
- "%![event-]+_e, %![context-ft-]+_F",
- event, event->class->context_field_type);
- }
-
- bt_put(event->context_field);
- event->context_field = bt_get(context);
- BT_LOGV("Set event's context field: event-addr=%p, "
- "event-class-name=\"%s\", event-class-id=%" PRId64 ", "
- "context-field-addr=%p",
- event, bt_event_class_common_get_name(event->class),
- bt_event_class_common_get_id(event->class), context);
- return 0;
-}
-
static inline
struct bt_field_common *bt_event_common_borrow_stream_event_context(
struct bt_event_common *event)
}
static inline
-int bt_event_common_set_stream_event_context(struct bt_event_common *event,
- struct bt_field_common *stream_event_context)
-{
- BT_ASSERT_PRE_NON_NULL(event, "Event");
- BT_ASSERT_PRE_EVENT_COMMON_HOT(event, "Event");
-
- if (stream_event_context) {
- BT_ASSERT_PRE(bt_field_type_common_compare(stream_event_context->type,
- bt_event_class_common_borrow_stream_class(event->class)->event_context_field_type) == 0,
- "Stream event context field's type is different from the "
- "expected field type: %![event-]+_e, %![ft-]+_F, "
- "%![expected-ft-]+_F",
- event, stream_event_context->type,
- bt_event_class_common_borrow_stream_class(event->class)->event_context_field_type);
- } else {
- BT_ASSERT_PRE(!bt_event_class_common_borrow_stream_class(event->class)->event_context_field_type,
- "Setting no stream event context field, "
- "but stream event context field type is not NULL: ",
- "%![event-]+_e, %![context-ft-]+_F",
- event,
- bt_event_class_common_borrow_stream_class(event->class)->event_context_field_type);
- }
-
- bt_get(stream_event_context);
- BT_MOVE(event->stream_event_context_field, stream_event_context);
- BT_LOGV("Set event's stream event context field: event-addr=%p, "
- "event-class-name=\"%s\", event-class-id=%" PRId64 ", "
- "stream-event-context-field-addr=%p",
- event, bt_event_class_common_get_name(event->class),
- bt_event_class_common_get_id(event->class),
- stream_event_context);
- return 0;
-}
-
-static inline
-void bt_event_common_finalize(struct bt_object *obj)
+void bt_event_common_finalize(struct bt_object *obj,
+ void (*field_release_func)(void *),
+ void (*header_field_release_func)(void *, struct bt_event_common *))
{
struct bt_event_common *event = (void *) obj;
BT_LOGD("Destroying event: addr=%p, "
"event-class-name=\"%s\", event-class-id=%" PRId64,
- event, bt_event_class_common_get_name(event->class),
- bt_event_class_common_get_id(event->class));
+ event,
+ event->class ? bt_event_class_common_get_name(event->class) : NULL,
+ event->class ? bt_event_class_common_get_id(event->class) : INT64_C(-1));
+
+ if (event->header_field) {
+ BT_LOGD_STR("Releasing event's header field.");
+ header_field_release_func(event->header_field, event);
+ }
+
+ if (event->stream_event_context_field) {
+ BT_LOGD_STR("Releasing event's stream event context field.");
+ field_release_func(event->stream_event_context_field);
+ }
+
+ if (event->context_field) {
+ BT_LOGD_STR("Releasing event's context field.");
+ field_release_func(event->context_field);
+ }
+
+ if (event->payload_field) {
+ BT_LOGD_STR("Releasing event's payload field.");
+ field_release_func(event->payload_field);
+ }
+ /*
+ * Leave this after calling header_field_release_func() because
+ * this function receives the event object and could need its
+ * class to perform some cleanup.
+ */
if (!event->base.parent) {
/*
* Event was keeping a reference to its class since it shared no
*/
bt_put(event->class);
}
-
- bt_put(event->header_field);
- BT_LOGD_STR("Putting event's stream event context field.");
- bt_put(event->stream_event_context_field);
- BT_LOGD_STR("Putting event's context field.");
- bt_put(event->context_field);
- BT_LOGD_STR("Putting event's payload field.");
- bt_put(event->payload_field);
- BT_LOGD_STR("Putting event's packet.");
}
+BT_HIDDEN
+struct bt_event *bt_event_new(struct bt_event_class *event_class);
+
+BT_HIDDEN
+struct bt_event *bt_event_create(struct bt_event_class *event_class,
+ struct bt_packet *packet);
+
+BT_HIDDEN
+void bt_event_recycle(struct bt_event *event);
+
+BT_HIDDEN
+void bt_event_destroy(struct bt_event *event);
+
+BT_HIDDEN
+int bt_event_set_packet(struct bt_event *event, struct bt_packet *packet);
+
#endif /* BABELTRACE_CTF_IR_EVENT_INTERNAL_H */
@sa ctfirevent
*/
struct bt_event;
+struct bt_event_header_field;
struct bt_clock;
struct bt_clock_value;
struct bt_event_class;
@pre \p event_class has a parent stream class.
@postsuccessrefcountret1
*/
-extern struct bt_event *bt_event_create(struct bt_event_class *event_class);
-
extern struct bt_event_class *bt_event_borrow_class(struct bt_event *event);
/**
return bt_get(bt_event_borrow_packet(event));
}
-/**
-@brief Associates the CTF IR event \p event to the CTF IR packet
- \p packet.
-
-The \link ctfirstreamclass CTF IR stream class\endlink of the
-parent \link ctfirstream CTF IR stream\endlink of \p packet \em must
-be the same as the parent stream class of the
-\link ctfireventclass CTF IR event class\endlink returned
-by bt_event_get_class() for \p event.
-
-You \em must call this function to create an event-packet association
-before you call bt_notification_event_create() with \p event.
-
-On success, this function also sets the parent stream object of
-\p event to the parent stream of \p packet.
-
-@param[in] event Event to which to associate \p packet.
-@param[in] packet Packet to associate to \p event.
-@returns 0 on success, or a negative value on error.
-
-@prenotnull{event}
-@prenotnull{packet}
-@prehot{event}
-@pre The parent stream class of \p packet is the same as the parent
- stream class of \p event.
-@postsuccessrefcountretinc
-
-@sa bt_event_get_packet(): Returns the associated packet of a
- given event object.
-*/
-extern int bt_event_set_packet(struct bt_event *event,
- struct bt_packet *packet);
-
extern struct bt_stream *bt_event_borrow_stream(struct bt_event *event);
/**
extern struct bt_field *bt_event_borrow_header(struct bt_event *event);
-/**
-@brief Returns the stream event header field of the CTF IR event
- \p event.
-
-@param[in] event Event of which to get the stream event header
- field.
-@returns Stream event header field of \p event,
- or \c NULL if the stream event header
- field is not set or on error.
-
-@prenotnull{event}
-@postrefcountsame{event}
-@postsuccessrefcountretinc
-
-@sa bt_event_get_header(): Sets the stream event header
- field of a given event.
-*/
-static inline
-struct bt_field *bt_event_get_header(struct bt_event *event)
-{
- return bt_get(bt_event_borrow_header(event));
-}
-
-/**
-@brief Sets the stream event header field of the CTF IR event
- \p event to \p header, or unsets the current stream event header field
- from \p event.
-
-If \p header is not \c NULL, the field type of \p header, as returned by
-bt_field_get_type(), \em must be equivalent to the field type returned by
-bt_stream_class_get_event_header_type() for the parent stream class
-of \p event.
-
-@param[in] event Event of which to set the stream event header
- field.
-@param[in] header Stream event header field.
-@returns 0 on success, or a negative value on error.
-
-@prenotnull{event}
-@prehot{event}
-@pre <strong>\p header, if not \c NULL</strong>, has a field type equivalent to
- the field type returned by bt_stream_class_get_event_header_type()
- for the parent stream class of \p event.
-@postrefcountsame{event}
-@post <strong>On success, if \p header is not \c NULL</strong>,
- the reference count of \p header is incremented.
-
-@sa bt_event_get_header(): Returns the stream event header field
- of a given event.
-*/
-extern int bt_event_set_header(struct bt_event *event,
- struct bt_field *header);
+extern int bt_event_move_header(struct bt_event *event,
+ struct bt_event_header_field *header);
extern struct bt_field *bt_event_borrow_stream_event_context(
struct bt_event *event);
-/**
-@brief Returns the stream event context field of the CTF IR event
- \p event.
-
-@param[in] event Event of which to get the stream event context
- field.
-@returns Stream event context field of \p event,
- or \c NULL if the stream event context
- field is not set or on error.
-
-@prenotnull{event}
-@postrefcountsame{event}
-@postsuccessrefcountretinc
-
-@sa bt_event_set_stream_event_context(): Sets the stream event context
- field of a given event.
-*/
-static inline
-struct bt_field *bt_event_get_stream_event_context(struct bt_event *event)
-{
- return bt_get(bt_event_borrow_stream_event_context(event));
-}
-
-/**
-@brief Sets the stream event context field of the CTF IR event
- \p event to \p context, or unsets the current stream event context field
- from \p event.
-
-If \p context is not \c NULL, the field type of \p context, as returned by
-bt_field_get_type(), \em must be equivalent to the field type returned by
-bt_stream_class_get_event_context_type() for the parent stream class
-of \p event.
-
-@param[in] event Event of which to set the stream event context field.
-@param[in] context Stream event context field.
-@returns 0 on success, or a negative value on error.
-
-@prenotnull{event}
-@prehot{event}
-@pre <strong>\p context, if not \c NULL</strong>, has a field type equivalent to
- the field type returned by bt_stream_class_get_event_context_type()
- for the parent stream class of \p event.
-@postrefcountsame{event}
-@post <strong>On success, if \p context is not \c NULL</strong>, the reference
- count of \p context is incremented.
-
-@sa bt_event_get_stream_event_context(): Returns the stream event context
- field of a given event.
-*/
-extern int bt_event_set_stream_event_context(struct bt_event *event,
- struct bt_field *context);
-
extern struct bt_field *bt_event_borrow_context(struct bt_event *event);
-/**
-@brief Returns the event context field of the CTF IR event \p event.
-
-@param[in] event Event of which to get the context field.
-@returns Event context field of \p event, or \c NULL if the
- event context field is not set or on error.
-
-@prenotnull{event}
-@postrefcountsame{event}
-@postsuccessrefcountretinc
-
-@sa bt_event_set_context(): Sets the event context field of a given
- event.
-*/
-static inline
-struct bt_field *bt_event_get_context(struct bt_event *event)
-{
- return bt_get(bt_event_borrow_context(event));
-}
-
-/**
-@brief Sets the event context field of the CTF IR event \p event to \p context,
- or unsets the current event context field from \p event.
-
-If \p context is not \c NULL, the field type of \p context, as returned by
-bt_field_get_type(), \em must be equivalent to the field type returned by
-bt_event_class_get_context_type() for the parent class of \p event.
-
-@param[in] event Event of which to set the context field.
-@param[in] context Event context field.
-@returns 0 on success, or a negative value on error.
-
-@prenotnull{event}
-@prehot{event}
-@pre <strong>\p context, if not \c NULL</strong>, has a field type equivalent to
- the field type returned by bt_event_class_get_context_type() for the
- parent class of \p event.
-@postrefcountsame{event}
-@post <strong>On success, if \p context is not \c NULL</strong>, the reference
- count of \p context is incremented.
-
-@sa bt_event_get_context(): Returns the context field of a given event.
-*/
-extern int bt_event_set_context(struct bt_event *event,
- struct bt_field *context);
-
extern struct bt_field *bt_event_borrow_payload(struct bt_event *event);
-/**
-@brief Returns the payload field of the CTF IR event \p event.
-
-@param[in] event Event of which to get the payload field.
-@returns Payload field of \p event, or \c NULL if the payload
- field is not set or on error.
-
-@prenotnull{event}
-@postrefcountsame{event}
-@postsuccessrefcountretinc
-
-@sa bt_event_set_payload(): Sets the payload field of a given
- event.
-*/
-static inline
-struct bt_field *bt_event_get_payload(struct bt_event *event)
-{
- return bt_get(bt_event_borrow_payload(event));
-}
-
-/**
-@brief Sets the payload field of the CTF IR event \p event to \p payload,
- or unsets the current event payload field from \p event.
-
-If \p payload is not \c NULL, the field type of \p payload, as returned by
-bt_field_get_type(), \em must be equivalent to the field type returned by
-bt_event_class_get_payload_type() for the parent class of \p event.
-
-@param[in] event Event of which to set the payload field.
-@param[in] payload Event payload field.
-@returns 0 on success, or a negative value on error.
-
-@prenotnull{event}
-@prehot{event}
-@pre <strong>\p payload, if not \c NULL</strong>, has a field type equivalent to
- the field typereturned by bt_event_class_get_payload_type() for the
- parent class of \p event.
-@postrefcountsame{event}
-@post <strong>On success, if \p payload is not \c NULL</strong>, the reference
- count of \p payload is incremented.
-
-@sa bt_event_get_payload(): Returns the payload field of a given event.
-*/
-extern int bt_event_set_payload(struct bt_event *event,
- struct bt_field *payload);
-
/** @} */
/**
struct bt_event *event,
struct bt_clock_class *clock_class);
-/**
-@brief Returns the value, as of the CTF IR event \p event, of the
- clock described by the
- \link ctfirclockclass CTF IR clock class\endlink \p clock_class.
-
-@param[in] event Event of which to get the value of the clock
- described by \p clock_class.
-@param[in] clock_class Class of the clock of which to get the value.
-@returns Value of the clock described by \p clock_class
- as of \p event.
-
-@prenotnull{event}
-@prenotnull{clock_class}
-@postrefcountsame{event}
-@postrefcountsame{clock_class}
-@postsuccessrefcountretinc
-
-@sa bt_event_set_clock_value(): Sets the clock value of a given event.
-*/
-static inline
-struct bt_clock_value *bt_event_get_clock_value(
- struct bt_event *event,
- struct bt_clock_class *clock_class)
-{
- return bt_get(bt_event_borrow_clock_value(event, clock_class));
-}
-
-/**
-@brief Sets the value, as of the CTF IR event \p event, of the
- clock described by its \link ctfirclockclass CTF IR
- clock class\endlink.
-
-@param[in] event Event of which to set the value of the clock
- described by the clock class of \p clock_value.
-@param[in] clock_value Value of the clock described by its clock class
- as of \p event.
-@returns 0 on success, or a negative value on error.
-
-@prenotnull{event}
-@prenotnull{clock_value}
-@prehot{event}
-@postrefcountsame{event}
-
-@sa bt_event_get_clock_value(): Returns the clock value of
- a given event.
-*/
-extern int bt_event_set_clock_value(
- struct bt_event *event,
- struct bt_clock_value *clock_value);
-
/** @} */
/** @} */
#define BT_ASSERT_PRE_FT_HOT(_ft, _name) \
BT_ASSERT_PRE_HOT((_ft), (_name), ": +%!+_F", (_ft))
+#define BT_FIELD_TYPE_COMMON_STRUCTURE_FIELD_AT_INDEX(_ft, _index) \
+ (&g_array_index(((struct bt_field_type_common_structure *) (_ft))->fields, \
+ struct bt_field_type_common_structure_field, (_index)))
+
+#define BT_FIELD_TYPE_COMMON_VARIANT_CHOICE_AT_INDEX(_ft, _index) \
+ (&g_array_index(((struct bt_field_type_common_variant *) (_ft))->choices, \
+ struct bt_field_type_common_variant_choice, (_index)))
+
struct bt_field_common;
struct bt_field_type_common;
struct bt_field_type;
struct bt_field_type_common_integer {
struct bt_field_type_common common;
+
+ /* Owned by this */
struct bt_clock_class *mapped_clock_class;
+
enum bt_byte_order user_byte_order;
bt_bool is_signed;
unsigned int size;
uint64_t _unsigned;
int64_t _signed;
} range_start;
-
union {
uint64_t _unsigned;
int64_t _signed;
struct bt_field_type_common_enumeration {
struct bt_field_type_common common;
+
+ /* Owned by this */
struct bt_field_type_common_integer *container_ft;
- GPtrArray *entries; /* Array of ptrs to struct enumeration_mapping */
- /* Only set during validation. */
+
+ /* Array of `struct enumeration_mapping *`, owned by this */
+ GPtrArray *entries;
+
+ /* Only set during validation */
bt_bool has_overlapping_ranges;
};
struct bt_field_type_enumeration_mapping_iterator {
struct bt_object base;
+
+ /* Owned by this */
struct bt_field_type_common_enumeration *enumeration_ft;
+
enum bt_field_type_enumeration_mapping_iterator_type type;
int index;
union {
unsigned int mant_dig;
};
-struct structure_field_common {
- struct bt_field_type_common common;
+struct bt_field_type_common_structure_field {
GQuark name;
+
+ /* Owned by this */
struct bt_field_type_common *type;
};
struct bt_field_type_common_structure {
struct bt_field_type_common common;
GHashTable *field_name_to_index;
- GPtrArray *fields; /* Array of pointers to struct structure_field_common */
+
+ /*
+ * Array of `struct bt_field_type_common_structure_field`,
+ * owned by this
+ */
+ GArray *fields;
+};
+
+struct bt_field_type_common_variant_choice_range {
+ union {
+ int64_t i;
+ uint64_t u;
+ } lower;
+ union {
+ int64_t i;
+ uint64_t u;
+ } upper;
+};
+
+struct bt_field_type_common_variant_choice {
+ GQuark name;
+
+ /* Owned by this */
+ struct bt_field_type_common *type;
+
+ /* Array of `struct bt_field_type_common_variant_choice_range` */
+ GArray *ranges;
};
struct bt_field_type_common_variant {
struct bt_field_type_common common;
GString *tag_name;
+ bool choices_up_to_date;
+
+ /* Owned by this */
struct bt_field_type_common_enumeration *tag_ft;
+
+ /* Owned by this */
struct bt_field_path *tag_field_path;
- GHashTable *field_name_to_index;
- GPtrArray *fields; /* Array of pointers to struct structure_field_common */
+
+ GHashTable *choice_name_to_index;
+
+ /*
+ * Array of `struct bt_field_type_common_variant_choice`,
+ * owned by this */
+ GArray *choices;
};
struct bt_field_type_common_array {
struct bt_field_type_common common;
+
+ /* Owned by this */
struct bt_field_type_common *element_ft;
- unsigned int length; /* Number of elements */
+
+ unsigned int length;
};
struct bt_field_type_common_sequence {
struct bt_field_type_common common;
+
+ /* Owned by this */
struct bt_field_type_common *element_ft;
+
GString *length_field_name;
+
+ /* Owned by this */
struct bt_field_path *length_field_path;
};
const char *field_name);
BT_HIDDEN
-struct bt_field_type_common *
-bt_field_type_common_variant_borrow_field_type_by_name(
- struct bt_field_type_common *ft,
- const char *field_name);
+int bt_field_type_common_variant_update_choices(
+ struct bt_field_type_common *ft);
BT_HIDDEN
struct bt_field_type_common *
-bt_field_type_common_variant_borrow_field_type_from_tag(
+bt_field_type_common_variant_borrow_field_type_by_name(
struct bt_field_type_common *ft,
- struct bt_field_common *tag_field,
- bt_field_common_create_func field_create_func);
+ const char *field_name);
BT_HIDDEN
int64_t bt_field_type_common_variant_get_field_count(
struct bt_field_type_common *ft,
struct bt_clock_class **expected_clock_class);
+BT_HIDDEN
+int64_t bt_field_type_common_variant_find_choice_index(
+ struct bt_field_type_common *ft, uint64_t uval,
+ bool is_signed);
+
#endif /* BABELTRACE_CTF_IR_FIELD_TYPES_INTERNAL_H */
--- /dev/null
+#ifndef BABELTRACE_CTF_IR_FIELD_WRAPPER_INTERNAL_H
+#define BABELTRACE_CTF_IR_FIELD_WRAPPER_INTERNAL_H
+
+/*
+ * Copyright 2018 Philippe Proulx <pproulx@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <babeltrace/ctf-ir/fields-internal.h>
+#include <babeltrace/object-pool-internal.h>
+#include <babeltrace/object-internal.h>
+
+struct bt_field_wrapper {
+ struct bt_object base;
+
+ /* Owned by this */
+ struct bt_field_common *field;
+};
+
+BT_HIDDEN
+struct bt_field_wrapper *bt_field_wrapper_new(void *data);
+
+BT_HIDDEN
+void bt_field_wrapper_destroy(struct bt_field_wrapper *field);
+
+BT_HIDDEN
+struct bt_field_wrapper *bt_field_wrapper_create(
+ struct bt_object_pool *pool, struct bt_field_type *ft);
+
+#endif /* BABELTRACE_CTF_IR_FIELD_WRAPPER_INTERNAL_H */
#include <glib.h>
#define BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(_field, _type_id, _name) \
- BT_ASSERT_PRE((_field)->type->id == (_type_id), \
+ BT_ASSERT_PRE((_field)->type->id == ((int) (_type_id)), \
_name " has the wrong type ID: expected-type-id=%s, " \
- "%![field-]+_f", bt_common_field_type_id_string(_type_id), \
- (_field))
+ "%![field-]+_f", \
+ bt_common_field_type_id_string((int) (_type_id)), (_field))
#define BT_ASSERT_PRE_FIELD_COMMON_IS_SET(_field, _name) \
BT_ASSERT_PRE(bt_field_common_is_set_recursive(_field), \
struct bt_field;
struct bt_field_common;
-typedef void (*bt_field_common_method_freeze)(struct bt_field_common *);
+typedef void (*bt_field_common_method_set_is_frozen)(struct bt_field_common *,
+ bool);
typedef int (*bt_field_common_method_validate)(struct bt_field_common *);
typedef struct bt_field_common *(*bt_field_common_method_copy)(
struct bt_field_common *);
typedef void (*bt_field_common_method_reset)(struct bt_field_common *);
struct bt_field_common_methods {
- bt_field_common_method_freeze freeze;
+ bt_field_common_method_set_is_frozen set_is_frozen;
bt_field_common_method_validate validate;
bt_field_common_method_copy copy;
bt_field_common_method_is_set is_set;
} payload;
};
-struct bt_field_common_enumeration {
- struct bt_field_common common;
- struct bt_field_common *payload;
-};
-
struct bt_field_common_floating_point {
struct bt_field_common common;
double payload;
struct bt_field_common_structure {
struct bt_field_common common;
- GPtrArray *fields; /* Array of pointers to struct bt_field_common */
+
+ /* Array of `struct bt_field_common *`, owned by this */
+ GPtrArray *fields;
};
struct bt_field_common_variant {
struct bt_field_common common;
- struct bt_field_common *tag;
- struct bt_field_common *payload;
+
+ union {
+ uint64_t u;
+ int64_t i;
+ } tag_value;
+
+ /* Weak: belongs to `choices` below */
+ struct bt_field_common *current_field;
+
+ /* Array of `struct bt_field_common *`, owned by this */
+ GPtrArray *fields;
};
struct bt_field_common_array {
struct bt_field_common common;
- GPtrArray *elements; /* Array of pointers to struct bt_field_common */
+
+ /* Array of `struct bt_field_common *`, owned by this */
+ GPtrArray *elements;
};
struct bt_field_common_sequence {
struct bt_field_common common;
- struct bt_field_common *length;
- GPtrArray *elements; /* Array of pointers to struct bt_field_common */
+
+ /*
+ * This is the true sequence field's length: its value can be
+ * less than `elements->len` below because we never shrink the
+ * array of elements to avoid reallocation.
+ */
+ uint64_t length;
+
+ /* Array of `struct bt_field_common *`, owned by this */
+ GPtrArray *elements;
};
struct bt_field_common_string {
GString *payload;
};
-BT_HIDDEN
-int64_t bt_field_sequence_get_int_length(struct bt_field *field);
+struct bt_field_enumeration {
+ struct bt_field_common_integer common;
+};
BT_HIDDEN
struct bt_field_common *bt_field_common_copy(struct bt_field_common *field);
struct bt_field_type_common *type,
bt_object_release_func release_func,
struct bt_field_common_methods *methods,
- bt_field_common_create_func field_create_func);
+ bt_field_common_create_func field_create_func,
+ GDestroyNotify field_release_func);
BT_HIDDEN
int bt_field_common_array_initialize(struct bt_field_common *field,
struct bt_field_type_common *type,
bt_object_release_func release_func,
- struct bt_field_common_methods *methods);
+ struct bt_field_common_methods *methods,
+ bt_field_common_create_func field_create_func,
+ GDestroyNotify field_destroy_func);
BT_HIDDEN
-int bt_field_common_generic_validate(struct bt_field_common *field);
+int bt_field_common_sequence_initialize(struct bt_field_common *field,
+ struct bt_field_type_common *type,
+ bt_object_release_func release_func,
+ struct bt_field_common_methods *methods,
+ GDestroyNotify field_destroy_func);
BT_HIDDEN
-int bt_field_common_enumeration_validate_recursive(
- struct bt_field_common *field);
+int bt_field_common_variant_initialize(struct bt_field_common *field,
+ struct bt_field_type_common *type,
+ bt_object_release_func release_func,
+ struct bt_field_common_methods *methods,
+ bt_field_common_create_func field_create_func,
+ GDestroyNotify field_release_func);
+
+BT_HIDDEN
+int bt_field_common_generic_validate(struct bt_field_common *field);
BT_HIDDEN
int bt_field_common_structure_validate_recursive(struct bt_field_common *field);
BT_HIDDEN
void bt_field_common_generic_reset(struct bt_field_common *field);
-BT_HIDDEN
-void bt_field_common_enumeration_reset_recursive(struct bt_field_common *field);
-
BT_HIDDEN
void bt_field_common_structure_reset_recursive(struct bt_field_common *field);
void bt_field_common_string_reset(struct bt_field_common *field);
BT_HIDDEN
-void bt_field_common_generic_freeze(struct bt_field_common *field);
-
-BT_HIDDEN
-void bt_field_common_enumeration_freeze_recursive(struct bt_field_common *field);
+void bt_field_common_generic_set_is_frozen(struct bt_field_common *field,
+ bool is_frozen);
BT_HIDDEN
-void bt_field_common_structure_freeze_recursive(struct bt_field_common *field);
+void bt_field_common_structure_set_is_frozen_recursive(
+ struct bt_field_common *field, bool is_frozen);
BT_HIDDEN
-void bt_field_common_variant_freeze_recursive(struct bt_field_common *field);
+void bt_field_common_variant_set_is_frozen_recursive(
+ struct bt_field_common *field, bool is_frozen);
BT_HIDDEN
-void bt_field_common_array_freeze_recursive(struct bt_field_common *field);
+void bt_field_common_array_set_is_frozen_recursive(
+ struct bt_field_common *field, bool is_frozen);
BT_HIDDEN
-void bt_field_common_sequence_freeze_recursive(struct bt_field_common *field);
+void bt_field_common_sequence_set_is_frozen_recursive(
+ struct bt_field_common *field, bool is_frozen);
BT_HIDDEN
-void _bt_field_common_freeze_recursive(struct bt_field_common *field);
+void _bt_field_common_set_is_frozen_recursive(struct bt_field_common *field,
+ bool is_frozen);
BT_HIDDEN
bt_bool bt_field_common_generic_is_set(struct bt_field_common *field);
-BT_HIDDEN
-bt_bool bt_field_common_enumeration_is_set_recursive(
- struct bt_field_common *field);
-
BT_HIDDEN
bt_bool bt_field_common_structure_is_set_recursive(
struct bt_field_common *field);
BT_HIDDEN
bt_bool bt_field_common_sequence_is_set_recursive(struct bt_field_common *field);
-BT_HIDDEN
-void bt_field_common_integer_destroy(struct bt_object *obj);
-
-BT_HIDDEN
-void bt_field_common_enumeration_destroy_recursive(struct bt_object *obj);
-
-BT_HIDDEN
-void bt_field_common_floating_point_destroy(struct bt_object *obj);
-
-BT_HIDDEN
-void bt_field_common_structure_destroy_recursive(struct bt_object *obj);
-
-BT_HIDDEN
-void bt_field_common_variant_destroy_recursive(struct bt_object *obj);
-
-BT_HIDDEN
-void bt_field_common_array_destroy_recursive(struct bt_object *obj);
-
-BT_HIDDEN
-void bt_field_common_sequence_destroy_recursive(struct bt_object *obj);
-
-BT_HIDDEN
-void bt_field_common_string_destroy(struct bt_object *obj);
-
#ifdef BT_DEV_MODE
-# define bt_field_common_validate_recursive _bt_field_common_validate_recursive
-# define bt_field_common_freeze_recursive _bt_field_common_freeze_recursive
-# define bt_field_common_is_set_recursive _bt_field_common_is_set_recursive
-# define bt_field_common_reset_recursive _bt_field_common_reset_recursive
-# define bt_field_common_set _bt_field_common_set
-# define bt_field_validate_recursive _bt_field_validate_recursive
-# define bt_field_freeze_recursive _bt_field_freeze_recursive
-# define bt_field_is_set_recursive _bt_field_is_set_recursive
-# define bt_field_reset_recursive _bt_field_reset_recursive
-# define bt_field_set _bt_field_set
+# define bt_field_common_validate_recursive _bt_field_common_validate_recursive
+# define bt_field_common_set_is_frozen_recursive _bt_field_common_set_is_frozen_recursive
+# define bt_field_common_is_set_recursive _bt_field_common_is_set_recursive
+# define bt_field_common_reset_recursive _bt_field_common_reset_recursive
+# define bt_field_common_set _bt_field_common_set
+# define bt_field_validate_recursive _bt_field_validate_recursive
+# define bt_field_set_is_frozen_recursive _bt_field_set_is_frozen_recursive
+# define bt_field_is_set_recursive _bt_field_is_set_recursive
+# define bt_field_reset_recursive _bt_field_reset_recursive
+# define bt_field_set _bt_field_set
#else
# define bt_field_common_validate_recursive(_field) (-1)
-# define bt_field_common_freeze_recursive(_field)
+# define bt_field_common_set_is_frozen_recursive(_field, _is_frozen)
# define bt_field_common_is_set_recursive(_field) (BT_FALSE)
# define bt_field_common_reset_recursive(_field) (BT_TRUE)
# define bt_field_common_set(_field, _val)
# define bt_field_validate_recursive(_field) (-1)
-# define bt_field_freeze_recursive(_field)
+# define bt_field_set_is_frozen_recursive(_field, _is_frozen)
# define bt_field_is_set_recursive(_field) (BT_FALSE)
# define bt_field_reset_recursive(_field) (BT_TRUE)
# define bt_field_set(_field, _val)
static inline bool field_type_common_has_known_id(
struct bt_field_type_common *ft)
{
- return ft->id > BT_FIELD_TYPE_ID_UNKNOWN ||
- ft->id < BT_FIELD_TYPE_ID_NR;
+ return (int) ft->id > BT_FIELD_TYPE_ID_UNKNOWN ||
+ (int) ft->id < BT_FIELD_TYPE_ID_NR;
}
static inline
}
static inline
-int64_t bt_field_common_sequence_get_int_length(struct bt_field_common *field)
-{
- struct bt_field_common_sequence *sequence = BT_FROM_COMMON(field);
- int64_t ret;
-
- BT_ASSERT(field);
- BT_ASSERT(field->type->id == BT_FIELD_TYPE_ID_SEQUENCE);
- if (!sequence->length) {
- ret = -1;
- goto end;
- }
-
- ret = (int64_t) sequence->elements->len;
-
-end:
- return ret;
-}
-
-static inline
-struct bt_field_common *bt_field_common_sequence_borrow_length(
- struct bt_field_common *field)
+int64_t bt_field_common_sequence_get_length(struct bt_field_common *field)
{
struct bt_field_common_sequence *sequence = BT_FROM_COMMON(field);
BT_ASSERT_PRE_NON_NULL(field, "Sequence field");
BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_SEQUENCE,
"Field");
- return sequence->length;
+ return (int64_t) sequence->length;
}
static inline
int bt_field_common_sequence_set_length(struct bt_field_common *field,
- struct bt_field_common *length_field)
+ uint64_t length, bt_field_common_create_func field_create_func)
{
int ret = 0;
- struct bt_field_common_integer *length = BT_FROM_COMMON(length_field);
struct bt_field_common_sequence *sequence = BT_FROM_COMMON(field);
- uint64_t sequence_length;
BT_ASSERT_PRE_NON_NULL(field, "Sequence field");
- BT_ASSERT_PRE_NON_NULL(length_field, "Length field");
BT_ASSERT_PRE_FIELD_COMMON_HOT(field, "Sequence field");
- BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(length_field,
- BT_FIELD_TYPE_ID_INTEGER, "Length field");
- BT_ASSERT_PRE(
- !bt_field_type_common_integer_is_signed(length->common.type),
- "Length field's type is signed: %!+_f", length_field);
- BT_ASSERT_PRE_FIELD_COMMON_IS_SET(length_field, "Length field");
- sequence_length = length->payload.unsignd;
- if (sequence->elements) {
- g_ptr_array_free(sequence->elements, TRUE);
- bt_put(sequence->length);
- }
- sequence->elements = g_ptr_array_sized_new((size_t) sequence_length);
- if (!sequence->elements) {
- BT_LOGE_STR("Failed to allocate a GPtrArray.");
- ret = -1;
- goto end;
+ if (length > sequence->elements->len) {
+ /* Make more room */
+ struct bt_field_type_common_sequence *sequence_ft;
+ uint64_t cur_len = sequence->elements->len;
+ uint64_t i;
+
+ g_ptr_array_set_size(sequence->elements, length);
+ sequence_ft = BT_FROM_COMMON(sequence->common.type);
+
+ for (i = cur_len; i < sequence->elements->len; i++) {
+ struct bt_field_common *elem_field =
+ field_create_func(sequence_ft->element_ft);
+
+ if (!elem_field) {
+ ret = -1;
+ goto end;
+ }
+
+ BT_ASSERT(!sequence->elements->pdata[i]);
+ sequence->elements->pdata[i] = elem_field;
+ }
}
- g_ptr_array_set_free_func(sequence->elements,
- (GDestroyNotify) bt_put);
- g_ptr_array_set_size(sequence->elements, (size_t) sequence_length);
- bt_get(length_field);
- sequence->length = length_field;
- bt_field_common_freeze_recursive(length_field);
+ sequence->length = length;
end:
return ret;
return structure->fields->pdata[index];
}
-BT_ASSERT_PRE_FUNC
-static inline bool field_to_set_has_expected_type(
- struct bt_field_common *struct_field,
- const char *name, struct bt_field_common *value)
-{
- bool ret = true;
- struct bt_field_type_common *expected_field_type = NULL;
-
- expected_field_type =
- bt_field_type_common_structure_borrow_field_type_by_name(
- struct_field->type, name);
-
- if (bt_field_type_common_compare(expected_field_type, value->type)) {
- BT_ASSERT_PRE_MSG("Value field's type is different from the expected field type: "
- "%![value-ft-]+_F, %![expected-ft-]+_F", value->type,
- expected_field_type);
- ret = false;
- goto end;
- }
-
-end:
- return ret;
-}
-
-static inline
-int bt_field_common_structure_set_field_by_name(struct bt_field_common *field,
- const char *name, struct bt_field_common *value)
-{
- int ret = 0;
- GQuark field_quark;
- struct bt_field_common_structure *structure = BT_FROM_COMMON(field);
- size_t index;
- GHashTable *field_name_to_index;
- struct bt_field_type_common_structure *structure_ft;
-
- BT_ASSERT_PRE_NON_NULL(field, "Structure field");
- BT_ASSERT_PRE_NON_NULL(name, "Field name");
- BT_ASSERT_PRE_NON_NULL(value, "Value field");
- BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_STRUCT,
- "Parent field");
- BT_ASSERT_PRE(field_to_set_has_expected_type(field, name, value),
- "Value field's type is different from the expected field type.");
- field_quark = g_quark_from_string(name);
- structure_ft = BT_FROM_COMMON(field->type);
- field_name_to_index = structure_ft->field_name_to_index;
- if (!g_hash_table_lookup_extended(field_name_to_index,
- GUINT_TO_POINTER(field_quark), NULL,
- (gpointer *) &index)) {
- BT_LOGV("Invalid parameter: no such field in structure field's type: "
- "struct-field-addr=%p, struct-ft-addr=%p, "
- "field-ft-addr=%p, name=\"%s\"",
- field, field->type, value->type, name);
- ret = -1;
- goto end;
- }
- bt_get(value);
- BT_MOVE(structure->fields->pdata[index], value);
-
-end:
- return ret;
-}
-
static inline
struct bt_field_common *bt_field_common_array_borrow_field(
- struct bt_field_common *field, uint64_t index,
- bt_field_common_create_func field_create_func)
+ struct bt_field_common *field, uint64_t index)
{
- struct bt_field_common *new_field = NULL;
- struct bt_field_type_common *field_type = NULL;
struct bt_field_common_array *array = BT_FROM_COMMON(field);
BT_ASSERT_PRE_NON_NULL(field, "Array field");
- BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_ARRAY, "Field");
+ BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_ARRAY,
+ "Field");
BT_ASSERT_PRE(index < array->elements->len,
"Index is out of bound: %![array-field-]+_f, "
"index=%" PRIu64 ", count=%u", field,
index, array->elements->len);
-
- field_type = bt_field_type_common_array_borrow_element_field_type(
- field->type);
- if (array->elements->pdata[(size_t) index]) {
- new_field = array->elements->pdata[(size_t) index];
- goto end;
- }
-
- /* We don't want to modify this field if it's frozen */
- BT_ASSERT_PRE_FIELD_COMMON_HOT(field, "Array field");
- new_field = field_create_func(field_type);
- array->elements->pdata[(size_t) index] = new_field;
-
-end:
- return new_field;
+ return array->elements->pdata[(size_t) index];
}
static inline
struct bt_field_common *bt_field_common_sequence_borrow_field(
- struct bt_field_common *field, uint64_t index,
- bt_field_common_create_func field_create_func)
+ struct bt_field_common *field, uint64_t index)
{
- struct bt_field_common *new_field = NULL;
- struct bt_field_type_common *field_type = NULL;
struct bt_field_common_sequence *sequence = BT_FROM_COMMON(field);
BT_ASSERT_PRE_NON_NULL(field, "Sequence field");
BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_SEQUENCE,
"Field");
- BT_ASSERT_PRE_NON_NULL(sequence->elements, "Sequence field's element array");
- BT_ASSERT_PRE(index < sequence->elements->len,
+ BT_ASSERT_PRE(index < sequence->length,
"Index is out of bound: %![seq-field-]+_f, "
"index=%" PRIu64 ", count=%u", field, index,
sequence->elements->len);
- field_type = bt_field_type_common_sequence_borrow_element_field_type(
- field->type);
- if (sequence->elements->pdata[(size_t) index]) {
- new_field = sequence->elements->pdata[(size_t) index];
- goto end;
- }
-
- /* We don't want to modify this field if it's frozen */
- BT_ASSERT_PRE_FIELD_COMMON_HOT(field, "Sequence field");
- new_field = field_create_func(field_type);
- sequence->elements->pdata[(size_t) index] = new_field;
-
-end:
- return new_field;
+ return sequence->elements->pdata[(size_t) index];
}
static inline
-struct bt_field_common *bt_field_common_enumeration_borrow_container(
- struct bt_field_common *field,
- bt_field_common_create_func field_create_func)
+int bt_field_variant_common_set_tag(struct bt_field_common *variant_field,
+ uint64_t tag_uval, bool is_signed)
{
- struct bt_field_common_enumeration *enumeration = BT_FROM_COMMON(field);
-
- BT_ASSERT_PRE_NON_NULL(field, "Enumeration field");
- BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field,
- BT_FIELD_TYPE_ID_ENUM, "Field");
-
- if (!enumeration->payload) {
- struct bt_field_type_common_enumeration *enumeration_type;
-
- /* We don't want to modify this field if it's frozen */
- BT_ASSERT_PRE_FIELD_COMMON_HOT(field, "Enumeration field");
-
- enumeration_type = BT_FROM_COMMON(field->type);
- enumeration->payload =
- field_create_func(
- BT_TO_COMMON(enumeration_type->container_ft));
- }
-
- return enumeration->payload;
-}
-
-static inline
-struct bt_field_common *bt_field_common_variant_borrow_field(
- struct bt_field_common *field,
- struct bt_field_common *tag_field,
- bt_field_common_create_func field_create_func)
-{
- struct bt_field_common *new_field = NULL;
- struct bt_field_common_variant *variant = BT_FROM_COMMON(field);
- struct bt_field_type_common_variant *variant_type;
- struct bt_field_type_common *field_type;
- struct bt_field_common *tag_enum = NULL;
- struct bt_field_common_integer *tag_enum_integer =
- BT_FROM_COMMON(field);
- int64_t tag_enum_value;
-
- BT_ASSERT_PRE_NON_NULL(field, "Variant field");
- BT_ASSERT_PRE_NON_NULL(tag_field, "Tag field");
- BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_VARIANT,
- "Variant field");
- BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(tag_field, BT_FIELD_TYPE_ID_ENUM,
- "Tag field");
- variant_type = BT_FROM_COMMON(field->type);
- tag_enum = bt_field_common_enumeration_borrow_container(tag_field,
- field_create_func);
- BT_ASSERT_PRE_NON_NULL(tag_enum, "Tag field's container");
- tag_enum_integer = BT_FROM_COMMON(tag_enum);
- BT_ASSERT_PRE(bt_field_common_validate_recursive(tag_field) == 0,
- "Tag field is invalid: %!+_f", tag_field);
- tag_enum_value = tag_enum_integer->payload.signd;
+ int ret = 0;
+ int64_t choice_index;
+ struct bt_field_common_variant *variant = BT_FROM_COMMON(variant_field);
- /*
- * If the variant currently has a tag and a payload, and if the
- * requested tag value is the same as the current one, return
- * the current payload instead of creating a fresh one.
- */
- if (variant->tag && variant->payload) {
- struct bt_field_common *cur_tag_container = NULL;
- struct bt_field_common_integer *cur_tag_enum_integer;
- int64_t cur_tag_value;
-
- cur_tag_container =
- bt_field_common_enumeration_borrow_container(
- variant->tag, field_create_func);
- BT_ASSERT(cur_tag_container);
- cur_tag_enum_integer = BT_FROM_COMMON(cur_tag_container);
- cur_tag_value = cur_tag_enum_integer->payload.signd;
-
- if (cur_tag_value == tag_enum_value) {
- new_field = variant->payload;
- goto end;
- }
- }
+ BT_ASSERT_PRE_NON_NULL(variant_field, "Variant field");
+ BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(variant_field,
+ BT_FIELD_TYPE_ID_VARIANT, "Field");
- /* We don't want to modify this field if it's frozen */
- BT_ASSERT_PRE_FIELD_COMMON_HOT(field, "Variant field");
- field_type = bt_field_type_common_variant_borrow_field_type_signed(
- variant_type, tag_enum_value);
-
- /* It's the caller's job to make sure the tag's value is valid */
- BT_ASSERT_PRE(field_type,
- "Variant field's type does not contain a field type for "
- "this tag value: tag-value-signed=%" PRId64 ", "
- "%![var-ft-]+_F, %![tag-field-]+_f", tag_enum_value,
- variant_type, tag_field);
-
- new_field = field_create_func(field_type);
- if (!new_field) {
- BT_LOGW("Cannot create field: "
- "variant-field-addr=%p, variant-ft-addr=%p, "
- "field-ft-addr=%p", field, field->type, field_type);
+ /* Find matching index in variant field's type */
+ choice_index = bt_field_type_common_variant_find_choice_index(
+ variant_field->type, tag_uval, is_signed);
+ if (choice_index < 0) {
+ ret = -1;
goto end;
}
- bt_put(variant->tag);
- bt_put(variant->payload);
- variant->tag = bt_get(tag_field);
- variant->payload = new_field;
+ /* Select corresponding field */
+ BT_ASSERT(choice_index < variant->fields->len);
+ variant->current_field = variant->fields->pdata[choice_index];
+ variant->tag_value.u = tag_uval;
end:
- return new_field;
+ return ret;
}
static inline
BT_ASSERT_PRE_NON_NULL(variant_field, "Variant field");
BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(variant_field,
BT_FIELD_TYPE_ID_VARIANT, "Field");
- return variant->payload;
+ BT_ASSERT_PRE(variant->current_field,
+ "Variant field has no current field: %!+_f", variant_field);
+ return variant->current_field;
}
static inline
-struct bt_field_common *bt_field_common_variant_borrow_tag(
- struct bt_field_common *variant_field)
+int bt_field_common_variant_get_tag_signed(struct bt_field_common *variant_field,
+ int64_t *tag)
{
struct bt_field_common_variant *variant = BT_FROM_COMMON(variant_field);
BT_ASSERT_PRE_NON_NULL(variant_field, "Variant field");
BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(variant_field,
BT_FIELD_TYPE_ID_VARIANT, "Field");
- return variant->tag;
-}
-
-static inline
-int bt_field_common_integer_signed_get_value(struct bt_field_common *field,
- int64_t *value)
-{
- struct bt_field_common_integer *integer = BT_FROM_COMMON(field);
-
- BT_ASSERT_PRE_NON_NULL(field, "Integer field");
- BT_ASSERT_PRE_NON_NULL(value, "Value");
- BT_ASSERT_PRE_FIELD_COMMON_IS_SET(field, "Integer field");
- BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field,
- BT_FIELD_TYPE_ID_INTEGER, "Field");
- BT_ASSERT_PRE(bt_field_type_common_integer_is_signed(field->type),
- "Field's type is unsigned: %!+_f", field);
- *value = integer->payload.signd;
- return 0;
-}
-
-BT_ASSERT_PRE_FUNC
-static inline bool value_is_in_range_signed(unsigned int size, int64_t value)
-{
- bool ret = true;
- int64_t min_value, max_value;
-
- min_value = -(1ULL << (size - 1));
- max_value = (1ULL << (size - 1)) - 1;
- if (value < min_value || value > max_value) {
- BT_LOGF("Value is out of bounds: value=%" PRId64 ", "
- "min-value=%" PRId64 ", max-value=%" PRId64,
- value, min_value, max_value);
- ret = false;
- }
-
- return ret;
-}
-
-static inline
-int bt_field_common_integer_signed_set_value(struct bt_field_common *field,
- int64_t value)
-{
- int ret = 0;
- struct bt_field_common_integer *integer = BT_FROM_COMMON(field);
- struct bt_field_type_common_integer *integer_type;
-
- BT_ASSERT_PRE_NON_NULL(field, "Integer field");
- BT_ASSERT_PRE_FIELD_COMMON_HOT(field, "Integer field");
- BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field,
- BT_FIELD_TYPE_ID_INTEGER, "Field");
- integer_type = BT_FROM_COMMON(field->type);
- BT_ASSERT_PRE(bt_field_type_common_integer_is_signed(field->type),
- "Field's type is unsigned: %!+_f", field);
- BT_ASSERT_PRE(value_is_in_range_signed(integer_type->size, value),
- "Value is out of bounds: value=%" PRId64 ", %![field-]+_f",
- value, field);
- integer->payload.signd = value;
- bt_field_common_set(field, true);
- return ret;
-}
-
-static inline
-int bt_field_common_integer_unsigned_get_value(struct bt_field_common *field,
- uint64_t *value)
-{
- struct bt_field_common_integer *integer = BT_FROM_COMMON(field);
-
- BT_ASSERT_PRE_NON_NULL(field, "Integer field");
- BT_ASSERT_PRE_NON_NULL(value, "Value");
- BT_ASSERT_PRE_FIELD_COMMON_IS_SET(field, "Integer field");
- BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field,
- BT_FIELD_TYPE_ID_INTEGER, "Field");
- BT_ASSERT_PRE(!bt_field_type_common_integer_is_signed(field->type),
- "Field's type is signed: %!+_f", field);
- *value = integer->payload.unsignd;
+ BT_ASSERT_PRE(variant->current_field,
+ "Variant field has no current field: %!+_f", variant_field);
+ *tag = variant->tag_value.i;
return 0;
}
-BT_ASSERT_PRE_FUNC
-static inline bool value_is_in_range_unsigned(unsigned int size, uint64_t value)
-{
- bool ret = true;
- int64_t max_value;
-
- max_value = (size == 64) ? UINT64_MAX : ((uint64_t) 1 << size) - 1;
- if (value > max_value) {
- BT_LOGF("Value is out of bounds: value=%" PRIu64 ", "
- "max-value=%" PRIu64,
- value, max_value);
- ret = false;
- }
-
- return ret;
-}
-
static inline
-int bt_field_common_integer_unsigned_set_value(struct bt_field_common *field,
- uint64_t value)
+int bt_field_common_variant_get_tag_unsigned(struct bt_field_common *variant_field,
+ uint64_t *tag)
{
- struct bt_field_common_integer *integer = BT_FROM_COMMON(field);
- struct bt_field_type_common_integer *integer_type;
+ struct bt_field_common_variant *variant = BT_FROM_COMMON(variant_field);
- BT_ASSERT_PRE_NON_NULL(field, "Integer field");
- BT_ASSERT_PRE_FIELD_COMMON_HOT(field, "Integer field");
- BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field,
- BT_FIELD_TYPE_ID_INTEGER, "Field");
- integer_type = BT_FROM_COMMON(field->type);
- BT_ASSERT_PRE(!bt_field_type_common_integer_is_signed(field->type),
- "Field's type is signed: %!+_f", field);
- BT_ASSERT_PRE(value_is_in_range_unsigned(integer_type->size, value),
- "Value is out of bounds: value=%" PRIu64 ", %![field-]+_f",
- value, field);
- integer->payload.unsignd = value;
- bt_field_common_set(field, true);
+ BT_ASSERT_PRE_NON_NULL(variant_field, "Variant field");
+ BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(variant_field,
+ BT_FIELD_TYPE_ID_VARIANT, "Field");
+ BT_ASSERT_PRE(variant->current_field,
+ "Variant field has no current field: %!+_f", variant_field);
+ *tag = variant->tag_value.u;
return 0;
}
static inline
struct bt_field_type_enumeration_mapping_iterator *
bt_field_common_enumeration_get_mappings(struct bt_field_common *field,
- bt_field_common_create_func field_create_func)
+ bt_field_common_create_func field_create_func,
+ uint64_t uval)
{
- int ret;
- struct bt_field_common *container = NULL;
+ struct bt_field_type_common_enumeration *enum_type = NULL;
struct bt_field_type_common_integer *integer_type = NULL;
struct bt_field_type_enumeration_mapping_iterator *iter = NULL;
- BT_ASSERT_PRE_NON_NULL(field, "Enumeration field");
- BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field,
- BT_FIELD_TYPE_ID_ENUM, "Field");
- container = bt_field_common_enumeration_borrow_container(field,
- field_create_func);
- BT_ASSERT_PRE(container,
- "Enumeration field has no container field: %!+_f", field);
- BT_ASSERT(container->type);
- integer_type = BT_FROM_COMMON(container->type);
- BT_ASSERT_PRE_FIELD_COMMON_IS_SET(container,
- "Enumeration field's payload field");
+ BT_ASSERT(field);
+ BT_ASSERT(field->type->id == BT_FIELD_TYPE_ID_ENUM);
+ BT_ASSERT(field->payload_set);
+ enum_type = BT_FROM_COMMON(field->type);
+ integer_type = enum_type->container_ft;
if (!integer_type->is_signed) {
- uint64_t value;
-
- ret = bt_field_common_integer_unsigned_get_value(container,
- &value);
- BT_ASSERT(ret == 0);
iter = bt_field_type_common_enumeration_unsigned_find_mappings_by_value(
- field->type, value);
+ field->type, uval);
} else {
- int64_t value;
-
- ret = bt_field_common_integer_signed_get_value(container, &value);
- BT_ASSERT(ret == 0);
iter = bt_field_type_common_enumeration_signed_find_mappings_by_value(
- field->type, value);
+ field->type, (int64_t) uval);
}
return iter;
return 0;
}
+static inline
+int bt_field_common_string_clear(struct bt_field_common *field)
+{
+ struct bt_field_common_string *string_field = BT_FROM_COMMON(field);
+
+ BT_ASSERT_PRE_NON_NULL(field, "String field");
+ BT_ASSERT_PRE_FIELD_COMMON_HOT(field, "String field");
+ BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field,
+ BT_FIELD_TYPE_ID_STRING, "Field");
+
+ if (string_field->payload) {
+ g_string_set_size(string_field->payload, 0);
+ } else {
+ string_field->payload = g_string_new(NULL);
+ }
+
+ bt_field_common_set(field, true);
+ return 0;
+}
+
static inline
int _bt_field_validate_recursive(struct bt_field *field)
{
}
static inline
-void _bt_field_freeze_recursive(struct bt_field *field)
+void _bt_field_set_is_frozen_recursive(struct bt_field *field, bool is_frozen)
{
- return _bt_field_common_freeze_recursive((void *) field);
+ return _bt_field_common_set_is_frozen_recursive((void *) field,
+ is_frozen);
}
static inline
_bt_field_common_set((void *) field, value);
}
+static inline
+void bt_field_common_finalize(struct bt_field_common *field)
+{
+ BT_ASSERT(field);
+ BT_LOGD_STR("Putting field's type.");
+ bt_put(field->type);
+}
+
+static inline
+void bt_field_common_integer_finalize(struct bt_field_common *field)
+{
+ BT_ASSERT(field);
+ BT_LOGD("Finalizing common integer field object: addr=%p", field);
+ bt_field_common_finalize(field);
+}
+
+static inline
+void bt_field_common_floating_point_finalize(struct bt_field_common *field)
+{
+ BT_ASSERT(field);
+ BT_LOGD("Finalizing common floating point number field object: addr=%p", field);
+ bt_field_common_finalize(field);
+}
+
+static inline
+void bt_field_common_structure_finalize_recursive(struct bt_field_common *field)
+{
+ struct bt_field_common_structure *structure = BT_FROM_COMMON(field);
+
+ BT_ASSERT(field);
+ BT_LOGD("Finalizing common structure field object: addr=%p", field);
+ bt_field_common_finalize(field);
+
+ if (structure->fields) {
+ g_ptr_array_free(structure->fields, TRUE);
+ }
+}
+
+static inline
+void bt_field_common_variant_finalize_recursive(struct bt_field_common *field)
+{
+ struct bt_field_common_variant *variant = BT_FROM_COMMON(field);
+
+ BT_ASSERT(field);
+ BT_LOGD("Finalizing common variant field object: addr=%p", field);
+ bt_field_common_finalize(field);
+
+ if (variant->fields) {
+ g_ptr_array_free(variant->fields, TRUE);
+ }
+}
+
+static inline
+void bt_field_common_array_finalize_recursive(struct bt_field_common *field)
+{
+ struct bt_field_common_array *array = BT_FROM_COMMON(field);
+
+ BT_ASSERT(field);
+ BT_LOGD("Finalizing common array field object: addr=%p", field);
+ bt_field_common_finalize(field);
+
+ if (array->elements) {
+ g_ptr_array_free(array->elements, TRUE);
+ }
+}
+
+static inline
+void bt_field_common_sequence_finalize_recursive(struct bt_field_common *field)
+{
+ struct bt_field_common_sequence *sequence = BT_FROM_COMMON(field);
+
+ BT_ASSERT(field);
+ BT_LOGD("Finalizing common sequence field object: addr=%p", field);
+ bt_field_common_finalize(field);
+
+ if (sequence->elements) {
+ g_ptr_array_free(sequence->elements, TRUE);
+ }
+}
+
+static inline
+void bt_field_common_string_finalize(struct bt_field_common *field)
+{
+ struct bt_field_common_string *string = BT_FROM_COMMON(field);
+
+ BT_ASSERT(field);
+ BT_LOGD("Finalizing common string field object: addr=%p", field);
+ bt_field_common_finalize(field);
+
+ if (string->payload) {
+ g_string_free(string->payload, TRUE);
+ }
+}
+
+BT_ASSERT_PRE_FUNC
+static inline bool value_is_in_range_signed(unsigned int size, int64_t value)
+{
+ bool ret = true;
+ int64_t min_value, max_value;
+
+ min_value = -(1ULL << (size - 1));
+ max_value = (1ULL << (size - 1)) - 1;
+ if (value < min_value || value > max_value) {
+ BT_LOGF("Value is out of bounds: value=%" PRId64 ", "
+ "min-value=%" PRId64 ", max-value=%" PRId64,
+ value, min_value, max_value);
+ ret = false;
+ }
+
+ return ret;
+}
+
+BT_ASSERT_PRE_FUNC
+static inline bool value_is_in_range_unsigned(unsigned int size, uint64_t value)
+{
+ bool ret = true;
+ int64_t max_value;
+
+ max_value = (size == 64) ? UINT64_MAX : ((uint64_t) 1 << size) - 1;
+ if (value > max_value) {
+ BT_LOGF("Value is out of bounds: value=%" PRIu64 ", "
+ "max-value=%" PRIu64,
+ value, max_value);
+ ret = false;
+ }
+
+ return ret;
+}
+
+BT_HIDDEN
+struct bt_field *bt_field_create_recursive(struct bt_field_type *type);
+
+BT_HIDDEN
+void bt_field_destroy_recursive(struct bt_field *field);
+
#endif /* BABELTRACE_CTF_IR_FIELDS_INTERNAL_H */
@{
*/
-/**
-@brief Creates an uninitialized @field described by the @ft
- \p field_type.
-
-On success, \p field_type becomes the parent of the created field
-object.
-
-On success, this function creates an \em uninitialized field: it has
-no value. You need to set the value of the created field with one of the
-its specific setters.
-
-@param[in] field_type Field type which describes the field to create.
-@returns Created field object, or \c NULL on error.
-
-@prenotnull{field_type}
-@postsuccessrefcountret1
-@postsuccessfrozen{field_type}
-*/
-extern struct bt_field *bt_field_create(struct bt_field_type *field_type);
-
extern struct bt_field_type *bt_field_borrow_type(struct bt_field *field);
/**
@{
*/
-/**
-@brief Creates a \em deep copy of the @field \p field.
-
-You can copy a frozen field: the resulting copy is <em>not frozen</em>.
-
-@param[in] field Field to copy.
-@returns Deep copy of \p field on success,
- or \c NULL on error.
-
-@prenotnull{field}
-@postrefcountsame{field}
-@postsuccessrefcountret1
-@post <strong>On success</strong>, the returned field is not frozen.
-*/
-extern struct bt_field *bt_field_copy(struct bt_field *field);
-
/** @} */
/** @} */
/** @} */
-/**
-@defgroup ctfirenumfield CTF IR enumeration field
-@ingroup ctfirfields
-@brief CTF IR enumeration field.
-
-@code
-#include <babeltrace/ctf-ir/fields.h>
-@endcode
-
-A CTF IR <strong><em>enumeration field</em></strong> is a @field which
-holds a @intfield, and which is described by a @enumft.
-
-To set the current integral value of an enumeration field, you need to
-get its wrapped @intfield with bt_field_enumeration_get_container(),
-and then set the integral value with either
-bt_field_integer_signed_set_value() or
-bt_field_integer_unsigned_set_value().
-
-Once you set the integral value of an enumeration field by following the
-previous paragraph, you can get the mappings containing this value in
-their range with bt_field_enumeration_get_mappings(). This function
-returns a @enumftiter.
-
-@sa ctfirenumfieldtype
-@sa ctfirfields
-
-@addtogroup ctfirenumfield
-@{
-*/
-
-extern struct bt_field *bt_field_enumeration_borrow_container(
- struct bt_field *enum_field);
-
-/**
-@brief Returns the @intfield, potentially creating it, wrapped by the
- @enumfield \p enum_field.
-
-This function creates the @intfield to return if it does not currently
-exist.
-
-@param[in] enum_field Enumeration field of which to get the wrapped
- integer field.
-@returns Integer field wrapped by \p enum_field, or
- \c NULL on error.
-
-@prenotnull{enum_field}
-@preisenumfield{enum_field}
-@postrefcountsame{enum_field}
-@postsuccessrefcountretinc
-*/
-static inline
-struct bt_field *bt_field_enumeration_get_container(
- struct bt_field *enum_field)
-{
- return bt_get(bt_field_enumeration_borrow_container(enum_field));
-}
-
/**
@brief Returns a @enumftiter on all the mappings of the field type of
\p enum_field which contain the current integral value of the
struct bt_field *string_field, const char *value,
unsigned int length);
+extern int bt_field_string_clear(struct bt_field *string_field);
+
/** @} */
/**
extern struct bt_field *bt_field_structure_borrow_field_by_name(
struct bt_field *struct_field, const char *name);
-/**
-@brief Returns the @field named \p name, potentially creating it,
- in the @structfield \p struct_field.
-
-This function creates the @field to return if it does not currently
-exist.
-
-@param[in] struct_field Structure field of which to get the field
- named \p name.
-@param[in] name Name of the field to get from \p struct_field.
-@returns Field named \p name in \p struct_field, or
- \c NULL on error.
-
-@prenotnull{struct_field}
-@prenotnull{name}
-@preisstructfield{struct_field}
-@postrefcountsame{struct_field}
-@postsuccessrefcountretinc
-
-@sa bt_field_structure_get_field_by_index(): Returns the field of a
- given structure field by index.
-@sa bt_field_structure_set_field_by_name(): Sets the field of a
- given structure field by name.
-*/
-static inline
-struct bt_field *bt_field_structure_get_field_by_name(
- struct bt_field *struct_field, const char *name)
-{
- return bt_get(bt_field_structure_borrow_field_by_name(struct_field,
- name));
-}
-
extern struct bt_field *bt_field_structure_borrow_field_by_index(
struct bt_field *struct_field, uint64_t index);
-/**
-@brief Returns the @field at index \p index in the @structfield
- \p struct_field.
-
-@param[in] struct_field Structure field of which to get the field
- at index \p index.
-@param[in] index Index of the field to get in \p struct_field.
-@returns Field at index \p index in \p struct_field, or
- \c NULL on error.
-
-@prenotnull{struct_field}
-@preisstructfield{struct_field}
-@pre \p index is lesser than the number of fields contained in the
- parent field type of \p struct_field (see
- bt_field_type_structure_get_field_count()).
-@postrefcountsame{struct_field}
-@postsuccessrefcountretinc
-
-@sa bt_field_structure_get_field_by_name(): Returns the field of a
- given structure field by name.
-@sa bt_field_structure_set_field_by_name(): Sets the field of a
- given structure field by name.
-*/
-static inline
-struct bt_field *bt_field_structure_get_field_by_index(
- struct bt_field *struct_field, uint64_t index)
-{
- return bt_get(bt_field_structure_borrow_field_by_index(struct_field,
- index));
-}
-
-/**
-@brief Sets the field of the @structfield \p struct_field named \p name
- to the @field \p field.
-
-If \p struct_field already contains a field named \p name, then it may
-either be replaced by \p field and its reference count is decremented,
-or \p field's value is assigned to it.
-
-The field type of \p field, as returned by bt_field_get_type(),
-\em must be equivalent to the field type returned by
-bt_field_type_structure_get_field_type_by_name() with the field
-type of \p struct_field and the same name, \p name.
-
-bt_trace_get_packet_header_type() for the parent trace class of
-\p packet.
-
-@param[in] struct_field Structure field of which to set the field
- named \p name.
-@param[in] name Name of the field to set in \p struct_field.
-@param[in] field Field named \p name to set in \p struct_field.
-@returns 0 on success, or -1 on error.
-
-@prenotnull{struct_field}
-@prenotnull{name}
-@prenotnull{field}
-@prehot{struct_field}
-@preisstructfield{struct_field}
-@pre \p field has a field type equivalent to the field type returned by
- bt_field_type_structure_get_field_type_by_name() for the
- field type of \p struct_field with the name \p name.
-@postrefcountsame{struct_field}
-@post <strong>On success, the field in \p struct_field named \p name</strong>
- may either be replaced by \p field or have the same value as \p field.
-@postsuccessrefcountinc{field}
-
-@sa bt_field_structure_get_field_by_index(): Returns the field of a
- given structure field by index.
-@sa bt_field_structure_get_field_by_name(): Returns the field of a
- given structure field by name.
-*/
-extern int bt_field_structure_set_field_by_name(
- struct bt_field *struct_field,
- const char *name, struct bt_field *field);
-
/** @} */
/**
extern struct bt_field *bt_field_array_borrow_field(
struct bt_field *array_field, uint64_t index);
-/**
-@brief Returns the @field at index \p index, potentially creating it,
- in the @arrayfield \p array_field.
-
-This function creates the @field to return if it does not currently
-exist.
-
-@param[in] array_field Array field of which to get the field
- at index \p index.
-@param[in] index Index of the field to get in \p array_field.
-@returns Field at index \p index in \p array_field, or
- \c NULL on error.
-
-@prenotnull{array_field}
-@preisarrayfield{array_field}
-@pre \p index is lesser than bt_field_type_array_get_length() called
- on the field type of \p array_field.
-@postrefcountsame{array_field}
-@postsuccessrefcountretinc
-*/
-static inline
-struct bt_field *bt_field_array_get_field(
- struct bt_field *array_field, uint64_t index)
-{
- return bt_get(bt_field_array_borrow_field(array_field, index));
-}
-
/** @} */
/**
extern struct bt_field *bt_field_sequence_borrow_field(
struct bt_field *sequence_field, uint64_t index);
-/**
-@brief Returns the @field at index \p index, potentially creating it,
- in the @seqfield \p sequence_field.
-
-This function creates the @field to return if it does not currently
-exist.
-
-@param[in] sequence_field Sequence field of which to get the field
- at index \p index.
-@param[in] index Index of the field to get in
- \p sequence_field.
-@returns Field at index \p index in
- \p sequence_field, or \c NULL on error.
-
-@prenotnull{sequence_field}
-@preisseqfield{sequence_field}
-@pre \p sequence_field has a length field previously set with
- bt_field_sequence_set_length().
-@pre \p index is lesser than the current integral value of the current
- length field of \p sequence_field (see
- bt_field_sequence_get_length()).
-@postrefcountsame{sequence_field}
-@postsuccessrefcountretinc
-*/
-static inline
-struct bt_field *bt_field_sequence_get_field(
- struct bt_field *sequence_field, uint64_t index)
-{
- return bt_get(bt_field_sequence_borrow_field(sequence_field, index));
-}
-
-extern struct bt_field *bt_field_sequence_borrow_length(
- struct bt_field *sequence_field);
-
-/**
-@brief Returns the length @intfield of the @seqfield \p sequence_field.
-
-The current integral value of the returned length field indicates the
-number of fields contained in \p sequence_field.
-
-@param[in] sequence_field Sequence field of which to get the
- length field.
-@returns Length field of \p sequence_field, or
- \c NULL on error.
-
-@prenotnull{sequence_field}
-@preisseqfield{sequence_field}
-@pre \p sequence_field has a length field previously set with
- bt_field_sequence_set_length().
-@postrefcountsame{sequence_field}
-@postsuccessrefcountretinc
-@post <strong>On success</strong>, the returned field is a @intfield.
-
-@sa bt_field_sequence_set_length(): Sets the length field of a given
- sequence field.
-*/
-static inline
-struct bt_field *bt_field_sequence_get_length(
- struct bt_field *sequence_field)
-{
- return bt_get(bt_field_sequence_borrow_length(sequence_field));
-}
+extern int64_t bt_field_sequence_get_length(struct bt_field *sequence_field);
/**
@brief Sets the length @intfield of the @seqfield \p sequence_field
given sequence field.
*/
extern int bt_field_sequence_set_length(struct bt_field *sequence_field,
- struct bt_field *length_field);
+ uint64_t length);
/** @} */
@{
*/
-extern struct bt_field *bt_field_variant_borrow_field(
- struct bt_field *variant_field,
- struct bt_field *tag_field);
+extern int bt_field_variant_set_tag_signed(struct bt_field *variant_field,
+ int64_t tag);
-/**
-@brief Returns the @field, potentially creating it, selected by the
- tag @intfield \p tag_field in the @varfield \p variant_field.
-
-This function creates the @field to return if it does not currently
-exist.
-
-Once you call this function, you can call
-bt_field_variant_get_current_field() to get the same field again,
-and you can call bt_field_variant_get_tag() to get \p tag_field.
-
-@param[in] variant_field Variant field of which to get the field
- selected by \p tag_field.
-@param[in] tag_field Tag field.
-@returns Field selected by \p tag_field in
- \p variant_field, or \c NULL on error.
-
-@prenotnull{variant_field}
-@prenotnull{tag_field}
-@preisvarfield{variant_field}
-@preisenumfield{tag_field}
-@postrefcountsame{variant_field}
-@postsuccessrefcountinc{tag_field}
-@postsuccessrefcountretinc
-*/
-static inline
-struct bt_field *bt_field_variant_get_field(
- struct bt_field *variant_field,
- struct bt_field *tag_field)
-{
- return bt_get(bt_field_variant_borrow_field(variant_field, tag_field));
-}
+extern int bt_field_variant_set_tag_unsigned(struct bt_field *variant_field,
+ uint64_t tag);
-extern struct bt_field *bt_field_variant_borrow_current_field(
- struct bt_field *variant_field);
+extern int bt_field_variant_get_tag_signed(struct bt_field *variant_field,
+ int64_t *tag);
-/**
-@brief Returns the currently selected @field of the @varfield
- \p variant_field.
-
-@param[in] variant_field Variant field of which to get the
- currently selected field.
-@returns Currently selected field of
- \p variant_field, or \c NULL if there's
- no selected field or on error.
-
-@prenotnull{variant_field}
-@preisvarfield{variant_field}
-@pre \p variant_field contains has a current selected field previously
- set with bt_field_variant_get_field().
-@postrefcountsame{variant_field}
-@postsuccessrefcountretinc
-*/
-static inline
-struct bt_field *bt_field_variant_get_current_field(
- struct bt_field *variant_field)
-{
- return bt_get(bt_field_variant_borrow_current_field(variant_field));
-}
+extern int bt_field_variant_get_tag_unsigned(struct bt_field *variant_field,
+ uint64_t *tag);
-extern struct bt_field *bt_field_variant_borrow_tag(
+extern struct bt_field *bt_field_variant_borrow_current_field(
struct bt_field *variant_field);
-/**
-@brief Returns the tag @enumfield of the @varfield \p variant_field.
-
-@param[in] variant_field Variant field of which to get the
- tag field.
-@returns Tag field of \p variant_field, or
- \c NULL on error.
-
-@prenotnull{variant_field}
-@preisvarfield{variant_field}
-@pre \p variant_field contains has a current selected field previously
- set with bt_field_variant_get_field().
-@postrefcountsame{variant_field}
-@postsuccessrefcountretinc
-@post <strong>On success</strong>, the returned field is a @enumfield.
-*/
-static inline
-struct bt_field *bt_field_variant_get_tag(
- struct bt_field *variant_field)
-{
- return bt_get(bt_field_variant_borrow_tag(variant_field));
-}
-
/** @} */
#ifdef __cplusplus
--- /dev/null
+#ifndef BABELTRACE_CTF_IR_PACKET_CONTEXT_FIELD_H
+#define BABELTRACE_CTF_IR_PACKET_CONTEXT_FIELD_H
+
+/*
+ * Copyright 2018 Philippe Proulx <pproulx@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * The Common Trace Format (CTF) Specification is available at
+ * http://www.efficios.com/ctf
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct bt_packet_context_field;
+struct bt_field;
+
+extern
+struct bt_field *bt_packet_context_field_borrow_field(
+ struct bt_packet_context_field *field);
+
+extern
+void bt_packet_context_field_release(struct bt_packet_context_field *field);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BABELTRACE_CTF_IR_PACKET_CONTEXT_FIELD_H */
--- /dev/null
+#ifndef BABELTRACE_CTF_IR_PACKET_HEADER_FIELD_H
+#define BABELTRACE_CTF_IR_PACKET_HEADER_FIELD_H
+
+/*
+ * Copyright 2018 Philippe Proulx <pproulx@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * The Common Trace Format (CTF) Specification is available at
+ * http://www.efficios.com/ctf
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct bt_packet_header_field;
+struct bt_field;
+
+extern
+struct bt_field *bt_packet_header_field_borrow_field(
+ struct bt_packet_header_field *field);
+
+extern
+void bt_packet_header_field_release(struct bt_packet_header_field *field);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BABELTRACE_CTF_IR_PACKET_HEADER_FIELD_H */
#include <babeltrace/assert-internal.h>
#include <babeltrace/ctf-ir/fields.h>
#include <babeltrace/ctf-ir/stream.h>
+#include <babeltrace/ctf-ir/field-wrapper-internal.h>
#include <babeltrace/object-internal.h>
#include <babeltrace/babeltrace-internal.h>
struct bt_packet {
struct bt_object base;
- struct bt_field *header;
- struct bt_field *context;
+ struct bt_field_wrapper *header;
+ struct bt_field_wrapper *context;
struct bt_stream *stream;
int frozen;
};
#ifdef BT_DEV_MODE
# define bt_packet_freeze _bt_packet_freeze
#else
-# define bt_packet_freeze
+# define bt_packet_freeze(_packet)
#endif /* BT_DEV_MODE */
+BT_HIDDEN
+struct bt_packet *bt_packet_new(struct bt_stream *stream);
+
+BT_HIDDEN
+void bt_packet_recycle(struct bt_packet *packet);
+
+BT_HIDDEN
+void bt_packet_destroy(struct bt_packet *packet);
+
#endif /* BABELTRACE_CTF_IR_PACKET_INTERNAL_H */
@sa ctfirpacket
*/
struct bt_packet;
+struct bt_packet_header_field;
+struct bt_packet_context_field;
struct bt_stream;
/**
@prenotnull{stream}
@postsuccessrefcountret1
*/
-extern struct bt_packet *bt_packet_create(
- struct bt_stream *stream);
+extern struct bt_packet *bt_packet_create(struct bt_stream *stream);
-extern struct bt_stream *bt_packet_borrow_stream(
- struct bt_packet *packet);
+extern struct bt_stream *bt_packet_borrow_stream(struct bt_packet *packet);
/**
@brief Returns the parent CTF IR stream of the CTF IR packet \p packet.
extern
struct bt_field *bt_packet_borrow_header(struct bt_packet *packet);
-/**
-@brief Returns the trace packet header field of the CTF IR packet
- \p packet.
-
-@param[in] packet Packet of which to get the trace packet header
- field.
-@returns Trace packet header field of \p packet,
- or \c NULL if the trace packet header
- field is not set or on error.
-
-@prenotnull{packet}
-@postrefcountsame{packet}
-@postsuccessrefcountretinc
-
-@sa bt_packet_set_header(): Sets the trace packet header
- field of a given packet.
-*/
-static inline
-struct bt_field *bt_packet_get_header(struct bt_packet *packet)
-{
- return bt_get(bt_packet_borrow_header(packet));
-}
-
-/**
-@brief Sets the trace packet header field of the CTF IR packet \p packet to
- \p header, or unsets the current trace packet header field from
- \p packet.
-
-If \p header is not \c NULL, the field type of \p header, as returned by
-bt_field_get_type(), \em must be equivalent to the field type returned by
-bt_trace_get_packet_header_type() for the parent trace class of
-\p packet.
-
-@param[in] packet Packet of which to set the trace packet header field.
-@param[in] header Trace packet header field.
-@returns 0 on success, or a negative value on error.
-
-@prenotnull{packet}
-@prehot{packet}
-@pre <strong>\p header, if not \c NULL</strong>, has a field type equivalent to
- the field type returned by bt_trace_get_packet_header_type() for the
- parent trace class of \p packet.
-@postrefcountsame{event}
-@post <strong>On success, if \p header is not \c NULL</strong>, the reference
- count of \p header is incremented.
-
-@sa bt_packet_get_header(): Returns the trace packet header field of a given
- packet.
-*/
-extern int bt_packet_set_header(struct bt_packet *packet,
- struct bt_field *header);
-
-extern struct bt_field *bt_packet_borrow_context(
- struct bt_packet *packet);
-
-/**
-@brief Returns the stream packet context field of the CTF IR packet
- \p packet.
-
-@param[in] packet Packet of which to get the stream packet context
- field.
-@returns Stream packet context field of \p packet,
- or \c NULL if the stream packet context
- field is not set or on error.
-
-@prenotnull{packet}
-@postrefcountsame{packet}
-@postsuccessrefcountretinc
-
-@sa bt_packet_set_context(): Sets the stream packet context
- field of a given packet.
-*/
-static inline
-struct bt_field *bt_packet_get_context(struct bt_packet *packet)
-{
- return bt_get(bt_packet_borrow_context(packet));
-}
-
-/**
-@brief Sets the stream packet context field of the CTF IR packet \p packet to
- \p context, or unsets the current packet context field from \p packet.
-
-If \p context is not \c NULL, the field type of \p context, as returned by
-bt_field_get_type(), \em must be equivalent to the field type returned by
-bt_stream_class_get_packet_context_type() for the parent stream class of
-\p packet.
-
-@param[in] packet Packet of which to set the stream packet context field.
-@param[in] context Stream packet context field.
-@returns 0 on success, or a negative value on error.
+extern
+int bt_packet_move_header(struct bt_packet *packet,
+ struct bt_packet_header_field *header);
-@prenotnull{packet}
-@prehot{packet}
-@pre <strong>\p context, if not \c NULL</strong>, has a field type equivalent to
- the field type returned by bt_stream_class_get_packet_context_type()
- for the parent stream class of \p packet.
-@postrefcountsame{packet}
-@post <strong>On success, if \p context is not \c NULL</strong>, the reference
- count of \p context is incremented.
+extern
+struct bt_field *bt_packet_borrow_context(struct bt_packet *packet);
-@sa bt_packet_get_context(): Returns the stream packet context field of a
- given packet.
-*/
-extern int bt_packet_set_context(
- struct bt_packet *packet, struct bt_field *context);
+extern
+int bt_packet_move_context(struct bt_packet *packet,
+ struct bt_packet_context_field *context);
/** @} */
#include <babeltrace/ctf-ir/utils-internal.h>
#include <babeltrace/ctf-ir/visitor.h>
#include <babeltrace/object-internal.h>
+#include <babeltrace/object-pool-internal.h>
#include <babeltrace/babeltrace-internal.h>
#include <glib.h>
#include <inttypes.h>
struct bt_stream_class {
struct bt_stream_class_common common;
+
+ /* Pool of `struct bt_field_wrapper *` */
+ struct bt_object_pool event_header_field_pool;
+
+ /* Pool of `struct bt_field_wrapper *` */
+ struct bt_object_pool packet_context_field_pool;
};
struct bt_event_class_common;
struct bt_stream_class;
struct bt_event_class;
struct bt_clock;
+struct bt_event_header_field;
+struct bt_packet_context_field;
/**
@name Creation and parent access functions
stream_class));
}
+extern
+struct bt_packet_context_field *bt_stream_class_create_packet_context_field(
+ struct bt_stream_class *stream_class);
+
/**
@brief Sets the packet context field type of the CTF IR stream class
\p stream_class to \p packet_context_type, or unsets the current packet
struct bt_stream_class *stream_class,
struct bt_field_type *event_header_type);
+extern struct bt_event_header_field *bt_stream_class_create_event_header_field(
+ struct bt_stream_class *stream_class);
+
extern struct bt_field_type *
bt_stream_class_borrow_event_context_field_type(
struct bt_stream_class *stream_class);
#include <babeltrace/ctf-ir/stream.h>
#include <babeltrace/ctf-ir/utils-internal.h>
#include <babeltrace/object-internal.h>
+#include <babeltrace/object-pool-internal.h>
#include <babeltrace/babeltrace-internal.h>
#include <glib.h>
struct bt_stream {
struct bt_stream_common common;
+
+ /* Pool of `struct bt_packet *` */
+ struct bt_object_pool packet_pool;
};
BT_HIDDEN
#include <babeltrace/ctf-ir/attributes-internal.h>
#include <babeltrace/ctf-ir/clock-class-internal.h>
#include <babeltrace/object-internal.h>
+#include <babeltrace/object-pool-internal.h>
#include <babeltrace/babeltrace-internal.h>
#include <babeltrace/values.h>
#include <babeltrace/types.h>
GArray *is_static_listeners;
bt_bool is_static;
bt_bool in_remove_listener;
+
+ /* Pool of `struct bt_field_wrapper *` */
+ struct bt_object_pool packet_header_field_pool;
};
BT_HIDDEN
extern "C" {
#endif
-struct bt_field_type;
-struct bt_value;
-
/**
@defgroup ctfirtraceclass CTF IR trace class
@ingroup ctfir
struct bt_stream;
struct bt_stream_class;
struct bt_clock_class;
+struct bt_field_type;
+struct bt_value;
+struct bt_packet_header_field;
/**
@brief User function type to use with
return bt_get(bt_trace_borrow_packet_header_field_type(trace_class));
}
+extern struct bt_packet_header_field *bt_trace_create_packet_header_field(
+ struct bt_trace *trace);
+
/**
@brief Sets the packet header field type of the CTF IR trace class
\p trace_class to \p packet_header_type, or unsets the current packet
#include <stdint.h>
#include <stddef.h>
-/* For bt_bool */
#include <babeltrace/babeltrace.h>
#include <babeltrace/ctf-ir/fields-internal.h>
#include <babeltrace/ctf-writer/fields.h>
#include <babeltrace/ctf-writer/serialize-internal.h>
+struct bt_ctf_field_enumeration {
+ struct bt_field_common common;
+ struct bt_field_common_integer *container;
+};
+
+struct bt_ctf_field_variant {
+ struct bt_field_common_variant common;
+ struct bt_ctf_field_enumeration *tag;
+};
+
BT_HIDDEN
int bt_ctf_field_serialize_recursive(struct bt_ctf_field *field,
struct bt_ctf_stream_pos *pos,
enum bt_ctf_byte_order native_byte_order);
+BT_HIDDEN
+int bt_ctf_field_structure_set_field_by_name(struct bt_ctf_field *field,
+ const char *name, struct bt_ctf_field *value);
+
+BT_HIDDEN
+struct bt_ctf_field *bt_ctf_field_enumeration_borrow_container(
+ struct bt_ctf_field *field);
+
static inline
bt_bool bt_ctf_field_is_set_recursive(struct bt_ctf_field *field)
{
extern struct bt_ctf_field *bt_ctf_field_enumeration_get_container(
struct bt_ctf_field *enum_field);
-extern struct bt_ctf_field_type_enumeration_mapping_iterator *
-bt_ctf_field_enumeration_get_mappings(struct bt_ctf_field *enum_field);
-
extern const char *bt_ctf_field_string_get_value(
struct bt_ctf_field *string_field);
extern struct bt_ctf_field *bt_ctf_field_structure_get_field_by_index(
struct bt_ctf_field *struct_field, uint64_t index);
-extern int bt_ctf_field_structure_set_field_by_name(
- struct bt_ctf_field *struct_field,
- const char *name, struct bt_ctf_field *field);
-
extern struct bt_ctf_field *bt_ctf_field_array_get_field(
struct bt_ctf_field *array_field, uint64_t index);
extern struct bt_ctf_field *bt_ctf_field_sequence_get_field(
struct bt_ctf_field *sequence_field, uint64_t index);
-extern struct bt_ctf_field *bt_ctf_field_sequence_get_length(
- struct bt_ctf_field *sequence_field);
-
extern int bt_ctf_field_sequence_set_length(struct bt_ctf_field *sequence_field,
struct bt_ctf_field *length_field);
extern struct bt_ctf_field *bt_ctf_field_variant_get_current_field(
struct bt_ctf_field *variant_field);
-extern struct bt_ctf_field *bt_ctf_field_variant_get_tag(
- struct bt_ctf_field *variant_field);
-
#ifdef __cplusplus
}
#endif
struct bt_notification;
struct bt_event;
+struct bt_event_class;
struct bt_clock_class_priority_map;
-/**
- * Create an event notification.
- *
- * @param event The event
- * @returns An event notification instance
- *
- * @see #bt_notification_type
- */
extern struct bt_notification *bt_notification_event_create(
- struct bt_event *event,
+ struct bt_event_class *event_class,
+ struct bt_packet *packet,
struct bt_clock_class_priority_map *clock_class_priority_map);
extern struct bt_event *bt_notification_event_borrow_event(
struct bt_notification *notification);
-/**
- * Get an event notification's event.
- *
- * @param notification Event notification instance
- * @returns An event instance
- *
- * @see #bt_event
- */
-static inline
-struct bt_event *bt_notification_event_get_event(
- struct bt_notification *notification)
-{
- return bt_get(bt_notification_event_borrow_event(notification));
-}
-
extern struct bt_clock_class_priority_map *
bt_notification_event_borrow_clock_class_priority_map(
struct bt_notification *notification);
struct bt_notification *notification,
struct bt_clock_class *clock_class);
-static inline
-struct bt_clock_value *bt_notification_inactivity_get_clock_value(
- struct bt_notification *notification,
- struct bt_clock_class *clock_class)
-{
- return bt_get(bt_notification_inactivity_borrow_clock_value(
- notification, clock_class));
-}
-
-extern int bt_notification_inactivity_set_clock_value(
- struct bt_notification *notification,
- struct bt_clock_value *clock_value);
-
#ifdef __cplusplus
}
#endif
* `u`:
* Plugin. The parameter type is `struct bt_plugin *`.
*
+ * `o`:
+ * Object pool. The parameter type is `struct bt_object_pool *`.
+ *
* CTF writer category:
* `F`:
* CTF writer field type. The parameter type is `struct bt_field_type *`.
* SOFTWARE.
*/
+#include <babeltrace/babeltrace-internal.h>
#include <babeltrace/ref-internal.h>
#include <babeltrace/ref.h>
#include <babeltrace/assert-internal.h>
+#include <stdbool.h>
/**
* All objects publicly exposed by Babeltrace APIs must contain this structure
bt_object_release_func parent_is_owner_listener;
/* @see doc/ref-counting.md */
struct bt_object *parent;
+
+ /*
+ * True if this object is shared, that is, it uses reference
+ * counting. Only used in developer mode.
+ */
+ bool is_shared;
};
static inline
child->parent = bt_get(parent);
}
+#ifdef BT_DEV_MODE
+static inline
+void _bt_object_set_is_shared(struct bt_object *obj, bool is_shared)
+{
+ obj->is_shared = is_shared;
+}
+
+# define bt_object_set_is_shared _bt_object_set_is_shared
+#else
+# define bt_object_set_is_shared(_obj, _is_shared)
+#endif
+
static inline
void bt_object_init(void *ptr, bt_object_release_func release)
{
obj->release = release;
obj->parent = NULL;
+ bt_object_set_is_shared(obj, true);
bt_ref_init(&obj->ref_count, generic_release);
}
--- /dev/null
+#ifndef BABELTRACE_OBJECT_POOL_INTERNAL_H
+#define BABELTRACE_OBJECT_POOL_INTERNAL_H
+
+/*
+ * Copyright (c) 2018 EfficiOS Inc. and Linux Foundation
+ * Copyright (c) 2018 Philippe Proulx <pproulx@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/*
+ * This is a generic object pool to avoid memory allocation/deallocation
+ * for objects of which the lifespan is typically short, but which are
+ * created a lot.
+ *
+ * The object pool, thanks to two user functions, knows how to allocate
+ * a brand new object in memory when the pool is empty and how to
+ * destroy an object when we destroy the pool.
+ *
+ * The object pool's user is responsible for:
+ *
+ * * Setting whatever references the object needs to keep and reset some
+ * properties _after_ calling bt_object_pool_create_object(). This is
+ * typically done in the bt_*_create() function which calls
+ * bt_object_pool_create_object() (which could call the user-provided
+ * allocation function if the pool is empty) and then sets the
+ * appropriate properties on the possibly recycled object.
+ *
+ * * Releasing whatever references the object keeps _before_ calling
+ * bt_object_pool_recycle_object(). This is typically done in a custom
+ * bt_*_recycle() function which does the necessary before calling
+ * bt_object_pool_recycle_object() with an object ready to be reused
+ * at any time.
+ */
+
+#include <glib.h>
+#include <babeltrace/object-internal.h>
+
+typedef void *(*bt_object_pool_new_object_func)(void *data);
+typedef void *(*bt_object_pool_destroy_object_func)(void *obj, void *data);
+
+struct bt_object_pool {
+ /*
+ * Container of recycled objects, owned by this. The array's size
+ * is the pool's capacity.
+ */
+ GPtrArray *objects;
+
+ /*
+ * Pool's size, that is, number of elements in the array above,
+ * starting at index 0, which exist as recycled objects.
+ */
+ size_t size;
+
+ /* User functions */
+ struct {
+ /* Allocate a new object in memory */
+ bt_object_pool_new_object_func new_object;
+
+ /* Free direct and indirect memory occupied by object */
+ bt_object_pool_destroy_object_func destroy_object;
+ } funcs;
+
+ /* User data passed to user functions */
+ void *data;
+};
+
+/*
+ * Initializes an object pool which is already allocated.
+ */
+int bt_object_pool_initialize(struct bt_object_pool *pool,
+ bt_object_pool_new_object_func new_object_func,
+ bt_object_pool_destroy_object_func destroy_object_func,
+ void *data);
+
+/*
+ * Finalizes an object pool without deallocating it.
+ */
+void bt_object_pool_finalize(struct bt_object_pool *pool);
+
+/*
+ * Creates an object from an object pool. If the pool is empty, this
+ * function calls the "new" user function to allocate a new object
+ * before returning it. Otherwise this function returns a recycled
+ * object, removing it from the pool.
+ *
+ * The returned object is owned by the caller.
+ */
+static inline
+void *bt_object_pool_create_object(struct bt_object_pool *pool)
+{
+ struct bt_object *obj;
+
+ BT_ASSERT(pool);
+
+#ifdef BT_LOGV
+ BT_LOGV("Creating object from pool: pool-addr=%p, pool-size=%zu, pool-cap=%u",
+ pool, pool->size, pool->objects->len);
+#endif
+
+ if (pool->size > 0) {
+ /* Pick one from the pool */
+ pool->size--;
+ obj = pool->objects->pdata[pool->size];
+ pool->objects->pdata[pool->size] = NULL;
+
+ if (obj->is_shared) {
+ /* Object is shared: reset reference count to 1 */
+ obj->ref_count.count = 1;
+ }
+ goto end;
+ }
+
+ /* Pool is empty: create a brand new object */
+#ifdef BT_LOGV
+ BT_LOGV("Pool is empty: allocating new object: pool-addr=%p",
+ pool);
+#endif
+
+ obj = pool->funcs.new_object(pool->data);
+
+end:
+#ifdef BT_LOGV
+ BT_LOGV("Created one object from pool: pool-addr=%p, obj-addr=%p",
+ pool, obj);
+#endif
+
+ return obj;
+}
+
+/*
+ * Recycles an object, that is, puts it back into the pool.
+ *
+ * The pool becomes the sole owner of the object to recycle.
+ */
+static inline
+void bt_object_pool_recycle_object(struct bt_object_pool *pool, void *obj)
+{
+ BT_ASSERT(pool);
+ BT_ASSERT(obj);
+
+#ifdef BT_LOGV
+ BT_LOGV("Recycling object: pool-addr=%p, pool-size=%zu, pool-cap=%u, obj-addr=%p",
+ pool, pool->size, pool->objects->len, obj);
+#endif
+
+ if (pool->size == pool->objects->len) {
+ /* Backing array is full: make place for recycled object */
+#ifdef BT_LOGV
+ BT_LOGV("Object pool is full: increasing object pool capacity: "
+ "pool-addr=%p, old-pool-cap=%u, new-pool-cap=%u",
+ pool, pool->objects->len, pool->objects->len + 1);
+#endif
+ g_ptr_array_set_size(pool->objects, pool->size + 1);
+ }
+
+ pool->objects->pdata[pool->size] = obj;
+ pool->size++;
+
+#ifdef BT_LOGV
+ BT_LOGV("Recycled object: pool-addr=%p, pool-size=%zu, pool-cap=%u, obj-addr=%p",
+ pool, pool->size, pool->objects->len, obj);
+#endif
+}
+
+#endif /* BABELTRACE_OBJECT_POOL_INTERNAL_H */
lib_LTLIBRARIES = libbabeltrace.la libbabeltrace-ctf.la
-libbabeltrace_la_SOURCES = babeltrace.c values.c ref.c lib-logging.c logging.c
+libbabeltrace_la_SOURCES = \
+ babeltrace.c \
+ values.c \
+ ref.c \
+ lib-logging.c \
+ logging.c \
+ object-pool.c
libbabeltrace_la_LDFLAGS = $(LT_NO_UNDEFINED) \
-version-info $(BABELTRACE_LIBRARY_VERSION)
clock-class.c \
event.c \
event-class.c \
+ event-header-field.c \
+ field-wrapper.c \
fields.c \
field-types.c \
field-path.c \
packet.c \
+ packet-context-field.c \
+ packet-header-field.c \
stream.c \
stream-class.c \
trace.c \
#define BT_LOG_TAG "CLOCK-CLASS"
#include <babeltrace/lib-logging-internal.h>
+#include <babeltrace/assert-pre-internal.h>
#include <babeltrace/compat/uuid-internal.h>
#include <babeltrace/ctf-ir/clock-class-internal.h>
#include <babeltrace/ctf-ir/clock-value-internal.h>
static
void bt_clock_class_destroy(struct bt_object *obj);
+static
+struct bt_clock_value *bt_clock_value_new(struct bt_clock_class *clock_class);
+
+static
+void bt_clock_value_destroy(struct bt_clock_value *clock_value);
+
BT_HIDDEN
bt_bool bt_clock_class_is_valid(struct bt_clock_class *clock_class)
{
return is_valid;
}
+static
+void bt_clock_class_free_clock_value(struct bt_clock_value *clock_value,
+ struct bt_clock_class *clock_class)
+{
+ bt_clock_value_destroy(clock_value);
+}
+
struct bt_clock_class *bt_clock_class_create(const char *name,
uint64_t freq)
{
}
}
+ ret = bt_object_pool_initialize(&clock_class->cv_pool,
+ (bt_object_pool_new_object_func) bt_clock_value_new,
+ (bt_object_pool_destroy_object_func)
+ bt_clock_class_free_clock_value,
+ clock_class);
+ if (ret) {
+ BT_LOGE("Failed to initialize clock value pool: ret=%d",
+ ret);
+ goto error;
+ }
+
BT_LOGD("Created clock class object: addr=%p, name=\"%s\"",
clock_class, name);
return clock_class;
return ret;
}
-static uint64_t ns_from_value(uint64_t frequency, uint64_t value)
+static inline
+uint64_t ns_from_value(uint64_t frequency, uint64_t value)
{
uint64_t ns;
- if (frequency == 1000000000) {
+ if (frequency == UINT64_C(1000000000)) {
ns = value;
} else {
double dblres = ((1e9 * (double) value) / (double) frequency);
clock_class = container_of(obj, struct bt_clock_class, base);
BT_LOGD("Destroying clock class: addr=%p, name=\"%s\"",
obj, bt_clock_class_get_name(clock_class));
+
if (clock_class->name) {
g_string_free(clock_class->name, TRUE);
}
+
if (clock_class->description) {
g_string_free(clock_class->description, TRUE);
}
+ bt_object_pool_finalize(&clock_class->cv_pool);
g_free(clock_class);
}
static
-void bt_clock_value_destroy(struct bt_object *obj)
+void bt_clock_value_destroy(struct bt_clock_value *clock_value)
{
- struct bt_clock_value *value;
-
- if (!obj) {
- return;
- }
-
- value = container_of(obj, struct bt_clock_value, base);
BT_LOGD("Destroying clock value: addr=%p, clock-class-addr=%p, "
- "clock-class-name=\"%s\"", obj, value->clock_class,
- bt_clock_class_get_name(value->clock_class));
- bt_put(value->clock_class);
- g_free(value);
+ "clock-class-name=\"%s\"", clock_value,
+ clock_value->clock_class,
+ bt_clock_class_get_name(clock_value->clock_class));
+ bt_put(clock_value->clock_class);
+ g_free(clock_value);
}
-static
-void set_ns_from_epoch(struct bt_clock_value *clock_value)
+static inline
+int ns_from_epoch(struct bt_clock_class *clock_class, uint64_t value,
+ int64_t *ns_from_epoch, bool *overflows)
{
- struct bt_clock_class *clock_class = clock_value->clock_class;
+ int ret = 0;
int64_t diff;
int64_t s_ns;
uint64_t u_ns;
uint64_t cycles;
+ *overflows = false;
+
/* Initialize nanosecond timestamp to clock's offset in seconds */
- if (clock_class->offset_s <= (INT64_MIN / 1000000000) ||
- clock_class->offset_s >= (INT64_MAX / 1000000000)) {
+ if (clock_class->offset_s <= (INT64_MIN / INT64_C(1000000000)) ||
+ clock_class->offset_s >= (INT64_MAX / INT64_C(1000000000))) {
/*
* Overflow: offset in seconds converted to nanoseconds
* is outside the int64_t range.
*/
- clock_value->ns_from_epoch_overflows = true;
+ *overflows = true;
goto end;
}
- clock_value->ns_from_epoch = clock_class->offset_s * (int64_t) 1000000000;
+ *ns_from_epoch = clock_class->offset_s * INT64_C(1000000000);
/* Add offset in cycles */
if (clock_class->offset < 0) {
- cycles = (uint64_t) (-clock_class->offset);
+ cycles = (uint64_t) -clock_class->offset;
} else {
cycles = (uint64_t) clock_class->offset;
}
u_ns = ns_from_value(clock_class->frequency, cycles);
- if (u_ns == -1ULL || u_ns >= INT64_MAX) {
+ if (u_ns == UINT64_C(-1) || u_ns >= INT64_MAX) {
/*
* Overflow: offset in cycles converted to nanoseconds
* is outside the int64_t range.
*/
- clock_value->ns_from_epoch_overflows = true;
+ *overflows = true;
goto end;
}
BT_ASSERT(s_ns >= 0);
if (clock_class->offset < 0) {
- if (clock_value->ns_from_epoch >= 0) {
+ if (*ns_from_epoch >= 0) {
/*
* Offset in cycles is negative so it must also
* be negative once converted to nanoseconds.
goto offset_ok;
}
- diff = clock_value->ns_from_epoch - INT64_MIN;
+ diff = *ns_from_epoch - INT64_MIN;
if (s_ns >= diff) {
/*
* plus the offset in cycles converted to
* nanoseconds is outside the int64_t range.
*/
- clock_value->ns_from_epoch_overflows = true;
+ *overflows = true;
goto end;
}
*/
s_ns = -s_ns;
} else {
- if (clock_value->ns_from_epoch <= 0) {
+ if (*ns_from_epoch <= 0) {
goto offset_ok;
}
- diff = INT64_MAX - clock_value->ns_from_epoch;
+ diff = INT64_MAX - *ns_from_epoch;
if (s_ns >= diff) {
/*
* plus the offset in cycles converted to
* nanoseconds is outside the int64_t range.
*/
- clock_value->ns_from_epoch_overflows = true;
+ *overflows = true;
goto end;
}
}
offset_ok:
- clock_value->ns_from_epoch += s_ns;
+ *ns_from_epoch += s_ns;
/* Add clock value (cycles) */
- u_ns = ns_from_value(clock_class->frequency, clock_value->value);
+ u_ns = ns_from_value(clock_class->frequency, value);
if (u_ns == -1ULL || u_ns >= INT64_MAX) {
/*
* Overflow: value converted to nanoseconds is outside
* the int64_t range.
*/
- clock_value->ns_from_epoch_overflows = true;
+ *overflows = true;
goto end;
}
BT_ASSERT(s_ns >= 0);
/* Clock value (cycles) is always positive */
- if (clock_value->ns_from_epoch <= 0) {
+ if (*ns_from_epoch <= 0) {
goto value_ok;
}
- diff = INT64_MAX - clock_value->ns_from_epoch;
+ diff = INT64_MAX - *ns_from_epoch;
if (s_ns >= diff) {
/*
* clock value converted to nanoseconds is outside the
* int64_t range.
*/
- clock_value->ns_from_epoch_overflows = true;
+ *overflows = true;
goto end;
}
value_ok:
- clock_value->ns_from_epoch += s_ns;
+ *ns_from_epoch += s_ns;
end:
- if (clock_value->ns_from_epoch_overflows) {
- clock_value->ns_from_epoch = 0;
+ if (*overflows) {
+ *ns_from_epoch = 0;
+ ret = -1;
}
+
+ return ret;
}
-struct bt_clock_value *bt_clock_value_create(
- struct bt_clock_class *clock_class, uint64_t value)
+static
+void set_ns_from_epoch(struct bt_clock_value *clock_value)
+{
+ (void) ns_from_epoch(clock_value->clock_class,
+ clock_value->value, &clock_value->ns_from_epoch,
+ &clock_value->ns_from_epoch_overflows);
+}
+
+static
+struct bt_clock_value *bt_clock_value_new(struct bt_clock_class *clock_class)
{
struct bt_clock_value *ret = NULL;
BT_LOGD("Creating clock value object: clock-class-addr=%p, "
- "clock-class-name=\"%s\", value=%" PRIu64, clock_class,
- bt_clock_class_get_name(clock_class), value);
+ "clock-class-name=\"%s\"", clock_class,
+ bt_clock_class_get_name(clock_class));
if (!clock_class) {
BT_LOGW_STR("Invalid parameter: clock class is NULL.");
goto end;
}
- bt_object_init(ret, bt_clock_value_destroy);
+ bt_object_init(ret, NULL);
+ bt_object_set_is_shared((void *) ret, false);
ret->clock_class = bt_get(clock_class);
- ret->value = value;
- set_ns_from_epoch(ret);
bt_clock_class_freeze(clock_class);
BT_LOGD("Created clock value object: clock-value-addr=%p, "
"clock-class-addr=%p, clock-class-name=\"%s\", "
return ret;
}
-int bt_clock_value_get_value(
- struct bt_clock_value *clock_value, uint64_t *raw_value)
+BT_HIDDEN
+struct bt_clock_value *bt_clock_value_create(struct bt_clock_class *clock_class)
+{
+ struct bt_clock_value *clock_value = NULL;
+
+ BT_ASSERT(clock_class);
+ clock_value = bt_object_pool_create_object(&clock_class->cv_pool);
+ if (!clock_value) {
+ BT_LIB_LOGE("Cannot allocate one clock value from clock class's clock value pool: "
+ "%![cc-]+K", clock_class);
+ goto error;
+ }
+
+ if (!clock_value->clock_class) {
+ clock_value->clock_class = bt_get(clock_class);
+ }
+
+ goto end;
+
+error:
+ if (clock_value) {
+ bt_clock_value_recycle(clock_value);
+ clock_value = NULL;
+ }
+
+end:
+ return clock_value;
+}
+
+BT_HIDDEN
+void bt_clock_value_recycle(struct bt_clock_value *clock_value)
+{
+ struct bt_clock_class *clock_class;
+
+ BT_ASSERT(clock_value);
+ BT_LIB_LOGD("Recycling clock value: %!+k", clock_value);
+
+ /*
+ * Those are the important ordered steps:
+ *
+ * 1. Reset the clock value object, but do NOT put its clock
+ * class's reference. This clock class contains the pool to
+ * which we're about to recycle this clock value object, so
+ * we must guarantee its existence thanks to this existing
+ * reference.
+ *
+ * 2. Move the clock class reference to our `clock_class`
+ * variable so that we can set the clock value's clock class
+ * member to NULL before recycling it. We CANNOT do this
+ * after we put the clock class reference because this
+ * bt_put() could destroy the clock class, also destroying
+ * its clock value pool, thus also destroying our clock value
+ * object (this would result in an invalid write access).
+ *
+ * 3. Recycle the clock value object.
+ *
+ * 4. Put our clock class reference.
+ */
+ bt_clock_value_reset(clock_value);
+ bt_clock_value_set_is_frozen(clock_value, false);
+ clock_class = clock_value->clock_class;
+ BT_ASSERT(clock_class);
+ clock_value->clock_class = NULL;
+ bt_object_pool_recycle_object(&clock_class->cv_pool, clock_value);
+ bt_put(clock_class);
+}
+
+BT_HIDDEN
+void bt_clock_value_set_raw_value(struct bt_clock_value *clock_value,
+ uint64_t cycles)
+{
+ BT_ASSERT(clock_value);
+
+ clock_value->value = cycles;
+ set_ns_from_epoch(clock_value);
+ bt_clock_value_set(clock_value);
+}
+
+int bt_clock_value_set_value(struct bt_clock_value *clock_value,
+ uint64_t raw_value)
+{
+ BT_ASSERT_PRE_NON_NULL(clock_value, "Clock value");
+ BT_ASSERT_PRE_HOT(clock_value, "Clock value", ": %!+k", clock_value);
+ bt_clock_value_set_raw_value(clock_value, raw_value);
+ return 0;
+}
+
+int bt_clock_value_get_value(struct bt_clock_value *clock_value,
+ uint64_t *raw_value)
{
int ret = 0;
end:
return ret;
}
+
+int bt_clock_class_cycles_to_ns(struct bt_clock_class *clock_class,
+ uint64_t cycles, int64_t *ns)
+{
+ int ret;
+ bool overflows;
+
+ BT_ASSERT_PRE_NON_NULL(clock_class, "Clock class");
+ BT_ASSERT_PRE_NON_NULL(ns, "Nanoseconds");
+
+ ret = ns_from_epoch(clock_class, cycles, ns, &overflows);
+ if (ret) {
+ if (overflows) {
+ BT_LIB_LOGW("Cannot convert cycles to nanoseconds "
+ "from Epoch for given clock class: "
+ "value overflow: %![cc-]+K, cycles=%" PRIu64,
+ clock_class, cycles);
+ } else {
+ BT_LIB_LOGW("Cannot convert cycles to nanoseconds "
+ "from Epoch for given clock class: "
+ "%![cc-]+K, cycles=%" PRIu64,
+ clock_class, cycles);
+ }
+
+ goto end;
+ }
+
+end:
+ return ret;
+}
#include <babeltrace/lib-logging-internal.h>
#include <babeltrace/assert-pre-internal.h>
+#include <babeltrace/ctf-ir/clock-value-internal.h>
#include <babeltrace/ctf-ir/fields-internal.h>
#include <babeltrace/ctf-ir/field-types-internal.h>
#include <babeltrace/ctf-ir/event-class.h>
#include <babeltrace/ctf-ir/event-class-internal.h>
+#include <babeltrace/ctf-ir/event-internal.h>
#include <babeltrace/ctf-ir/stream-class.h>
#include <babeltrace/ctf-ir/stream-class-internal.h>
#include <babeltrace/ctf-ir/trace-internal.h>
static
void bt_event_class_destroy(struct bt_object *obj)
{
+ struct bt_event_class *event_class = (void *) obj;
+
BT_LOGD("Destroying event class: addr=%p", obj);
bt_event_class_common_finalize(obj);
+ bt_object_pool_finalize(&event_class->event_pool);
g_free(obj);
}
+static
+void free_event(struct bt_event *event,
+ struct bt_event_class *event_class)
+{
+ bt_event_destroy(event);
+}
+
struct bt_event_class *bt_event_class_create(const char *name)
{
int ret;
goto error;
}
+ ret = bt_object_pool_initialize(&event_class->event_pool,
+ (bt_object_pool_new_object_func) bt_event_new,
+ (bt_object_pool_destroy_object_func) free_event,
+ event_class);
+ if (ret) {
+ BT_LOGE("Failed to initialize event pool: ret=%d",
+ ret);
+ goto error;
+ }
+
BT_LOGD("Created event class object: addr=%p, name=\"%s\"",
event_class, bt_event_class_get_name(event_class));
goto end;
end:
return ret;
}
+
+BT_HIDDEN
+int bt_event_class_update_event_pool_clock_values(
+ struct bt_event_class *event_class)
+{
+ int ret = 0;
+ uint64_t i;
+ struct bt_stream_class *stream_class =
+ bt_event_class_borrow_stream_class(event_class);
+
+ BT_ASSERT(stream_class->common.clock_class);
+
+ for (i = 0; i < event_class->event_pool.size; i++) {
+ struct bt_clock_value *cv;
+ struct bt_event *event =
+ event_class->event_pool.objects->pdata[i];
+
+ BT_ASSERT(event);
+
+ cv = g_hash_table_lookup(event->clock_values,
+ stream_class->common.clock_class);
+ if (cv) {
+ continue;
+ }
+
+ cv = bt_clock_value_create(stream_class->common.clock_class);
+ if (!cv) {
+ BT_LIB_LOGE("Cannot create clock value from clock class: "
+ "%![cc-]+K", stream_class->common.clock_class);
+ ret = -1;
+ goto end;
+ }
+
+ g_hash_table_insert(event->clock_values,
+ stream_class->common.clock_class, cv);
+ }
+
+end:
+ return ret;
+}
--- /dev/null
+/*
+ * Copyright 2018 Philippe Proulx <pproulx@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#define BT_LOG_TAG "EVENT-HEADER-FIELD"
+#include <babeltrace/lib-logging-internal.h>
+
+#include <babeltrace/assert-pre-internal.h>
+#include <babeltrace/ctf-ir/event-header-field.h>
+#include <babeltrace/ctf-ir/fields-internal.h>
+#include <babeltrace/ctf-ir/field-wrapper-internal.h>
+#include <glib.h>
+
+struct bt_field *bt_event_header_field_borrow_field(
+ struct bt_event_header_field *header_field)
+{
+ struct bt_field_wrapper *field_wrapper = (void *) header_field;
+
+ BT_ASSERT_PRE_NON_NULL(field_wrapper, "Event header field");
+ BT_ASSERT_PRE_NON_NULL(field_wrapper->field,
+ "Event header field's field object");
+ return (void *) field_wrapper->field;
+}
+
+void bt_event_header_field_release(struct bt_event_header_field *header_field)
+{
+ struct bt_field_wrapper *field_wrapper = (void *) header_field;
+
+ BT_ASSERT_PRE_NON_NULL(field_wrapper, "Event header field");
+
+ /*
+ * Do not recycle because the pool could be destroyed at this
+ * point. This function is only called when there's an error
+ * anyway because the goal of an event header field wrapper is
+ * to eventually move it to an event with bt_event_move_header()
+ * after creating it.
+ */
+ bt_field_wrapper_destroy(field_wrapper);
+}
#include <babeltrace/assert-internal.h>
#include <inttypes.h>
-static
-void bt_event_destroy(struct bt_object *obj);
-
static
int bt_event_common_validate_types_for_create(
struct bt_event_class_common *event_class,
static
int bt_event_common_create_fields(
+ struct bt_stream_class_common *stream_class,
struct bt_validation_output *validation_output,
void *(*create_field_func)(void *),
- struct bt_field_common **header_field,
+ void (*release_field_func)(void *),
+ void *(*create_header_field_func)(void *, void *),
+ void (*release_header_field_func)(void *),
+ struct bt_field_wrapper **header_field,
struct bt_field_common **stream_event_context_field,
struct bt_field_common **context_field,
struct bt_field_common **payload_field)
BT_LOGD("Creating initial event header field: ft-addr=%p",
validation_output->event_header_type);
*header_field =
- create_field_func(validation_output->event_header_type);
+ create_header_field_func(stream_class,
+ validation_output->event_header_type);
if (!*header_field) {
BT_LOGE_STR("Cannot create initial event header field object.");
goto error;
goto end;
error:
- BT_PUT(*header_field);
- BT_PUT(*stream_event_context_field);
- BT_PUT(*context_field);
- BT_PUT(*payload_field);
+ if (*header_field) {
+ release_header_field_func(*header_field);
+ }
+
+ if (*stream_event_context_field) {
+ release_field_func(*stream_event_context_field);
+ }
+
+ if (*context_field) {
+ release_field_func(*context_field);
+ }
+
+ if (*payload_field) {
+ release_field_func(*payload_field);
+ }
+
ret = -1;
end:
BT_ASSERT(event);
if (event->header_field) {
- ret = bt_field_common_validate_recursive(event->header_field);
+ ret = bt_field_common_validate_recursive(
+ event->header_field->field);
if (ret) {
BT_ASSERT_PRE_MSG("Invalid event's header field: "
"%![event-]+_e, %![field-]+_f",
- event, event->header_field);
+ event, event->header_field->field);
goto end;
}
}
"event-class-name=\"%s\", event-class-id=%" PRId64,
event, bt_event_class_common_get_name(event->class),
bt_event_class_common_get_id(event->class));
- BT_LOGD_STR("Freezing event's header field.");
- bt_field_common_freeze_recursive(event->header_field);
- BT_LOGD_STR("Freezing event's stream event context field.");
- bt_field_common_freeze_recursive(event->stream_event_context_field);
- BT_LOGD_STR("Freezing event's context field.");
- bt_field_common_freeze_recursive(event->context_field);
- BT_LOGD_STR("Freezing event's payload field.");
- bt_field_common_freeze_recursive(event->payload_field);
+
+ if (event->header_field) {
+ BT_LOGD_STR("Freezing event's header field.");
+ bt_field_common_set_is_frozen_recursive(
+ event->header_field->field, true);
+ }
+
+ if (event->stream_event_context_field) {
+ BT_LOGD_STR("Freezing event's stream event context field.");
+ bt_field_common_set_is_frozen_recursive(
+ event->stream_event_context_field, true);
+ }
+
+ if (event->context_field) {
+ BT_LOGD_STR("Freezing event's context field.");
+ bt_field_common_set_is_frozen_recursive(event->context_field, true);
+ }
+
+ if (event->payload_field) {
+ BT_LOGD_STR("Freezing event's payload field.");
+ bt_field_common_set_is_frozen_recursive(event->payload_field, true);
+ }
+
event->frozen = 1;
}
int (*map_clock_classes_func)(struct bt_stream_class_common *stream_class,
struct bt_field_type_common *packet_context_field_type,
struct bt_field_type_common *event_header_field_type),
- void *(*create_field_func)(void *))
+ void *(*create_field_func)(void *),
+ void (*release_field_func)(void *),
+ void *(*create_header_field_func)(void *, void *),
+ void (*release_header_field_func)(void *))
{
int ret;
struct bt_trace_common *trace = NULL;
struct bt_stream_class_common *stream_class = NULL;
- struct bt_field_common *event_header = NULL;
+ struct bt_field_wrapper *event_header = NULL;
struct bt_field_common *stream_event_context = NULL;
struct bt_field_common *event_context = NULL;
struct bt_field_common *event_payload = NULL;
*/
event->class = bt_get(event_class);
- ret = bt_event_common_create_fields(&validation_output,
- create_field_func, &event_header,
- &stream_event_context, &event_context, &event_payload);
+ ret = bt_event_common_create_fields(stream_class,
+ &validation_output,
+ create_field_func, release_field_func,
+ create_header_field_func, release_header_field_func,
+ &event_header, &stream_event_context, &event_context,
+ &event_payload);
if (ret) {
/* bt_event_common_create_fields() logs errors */
goto error;
bt_validation_replace_types(trace, stream_class, event_class,
&validation_output,
BT_VALIDATION_FLAG_STREAM | BT_VALIDATION_FLAG_EVENT);
- BT_MOVE(event->header_field, event_header);
- BT_MOVE(event->stream_event_context_field, stream_event_context);
- BT_MOVE(event->context_field, event_context);
- BT_MOVE(event->payload_field, event_payload);
+ event->header_field = event_header;
+ event_header = NULL;
+ event->stream_event_context_field = stream_event_context;
+ stream_event_context = NULL;
+ event->context_field = event_context;
+ event_context = NULL;
+ event->payload_field = event_payload;
+ event_payload = NULL;
/*
* Put what was not moved in bt_validation_replace_types().
error:
bt_validation_output_put_types(&validation_output);
bt_put(expected_clock_class);
- bt_put(event_header);
- bt_put(stream_event_context);
- bt_put(event_context);
- bt_put(event_payload);
+
+ if (event_header) {
+ release_header_field_func(event_header);
+ }
+
+ if (stream_event_context) {
+ release_field_func(stream_event_context);
+ }
+
+ if (event_context) {
+ release_field_func(event_context);
+ }
+
+ if (event_payload) {
+ release_field_func(event_payload);
+ }
+
ret = -1;
end:
return ret;
}
-struct bt_event *bt_event_create(struct bt_event_class *event_class)
+static
+void bt_event_header_field_recycle(struct bt_field_wrapper *field_wrapper,
+ struct bt_stream_class *stream_class)
+{
+ BT_ASSERT(field_wrapper);
+ BT_LIB_LOGD("Recycling event header field: "
+ "addr=%p, %![sc-]+S, %![field-]+f", field_wrapper,
+ stream_class, field_wrapper->field);
+ bt_object_pool_recycle_object(
+ &stream_class->event_header_field_pool,
+ field_wrapper);
+}
+
+static
+struct bt_field_wrapper *create_event_header_field(
+ struct bt_stream_class *stream_class,
+ struct bt_field_type_common *ft)
+{
+ struct bt_field_wrapper *field_wrapper = NULL;
+
+ field_wrapper = bt_field_wrapper_create(
+ &stream_class->event_header_field_pool, (void *) ft);
+ if (!field_wrapper) {
+ goto error;
+ }
+
+ goto end;
+
+error:
+ if (field_wrapper) {
+ bt_event_header_field_recycle(field_wrapper, stream_class);
+ field_wrapper = NULL;
+ }
+
+end:
+ return field_wrapper;
+}
+
+BT_HIDDEN
+struct bt_event *bt_event_new(struct bt_event_class *event_class)
{
int ret;
struct bt_event *event = NULL;
+ struct bt_stream_class *stream_class;
event = g_new0(struct bt_event, 1);
if (!event) {
}
ret = bt_event_common_initialize(BT_TO_COMMON(event),
- BT_TO_COMMON(event_class), NULL, bt_event_destroy,
+ BT_TO_COMMON(event_class), NULL, NULL,
(bt_validation_flag_copy_field_type_func) bt_field_type_copy,
- true, NULL, (void *) bt_field_create);
+ true, NULL,
+ (void *) bt_field_create_recursive,
+ (void *) bt_field_destroy_recursive,
+ (void *) create_event_header_field,
+ (void *) bt_event_header_field_recycle);
if (ret) {
/* bt_event_common_initialize() logs errors */
goto error;
}
+ bt_object_set_is_shared((void *) event, false);
event->clock_values = g_hash_table_new_full(g_direct_hash,
- g_direct_equal, NULL, bt_put);
- assert(event->clock_values);
+ g_direct_equal, NULL,
+ (GDestroyNotify) bt_clock_value_recycle);
+ BT_ASSERT(event->clock_values);
+ stream_class = bt_event_class_borrow_stream_class(event_class);
+ BT_ASSERT(stream_class);
+
+ if (stream_class->common.clock_class) {
+ struct bt_clock_value *clock_value;
+
+ clock_value = bt_clock_value_create(
+ stream_class->common.clock_class);
+ if (!clock_value) {
+ BT_LIB_LOGE("Cannot create clock value from clock class: "
+ "%![cc-]+K", stream_class->common.clock_class);
+ goto error;
+ }
+
+ g_hash_table_insert(event->clock_values,
+ stream_class->common.clock_class, clock_value);
+ }
+
goto end;
error:
- BT_PUT(event);
+ if (event) {
+ bt_event_destroy(event);
+ event = NULL;
+ }
+
+end:
+ return event;
+}
+
+BT_ASSERT_PRE_FUNC
+static inline
+void _bt_event_reset_dev_mode(struct bt_event *event)
+{
+ GHashTableIter iter;
+ gpointer key, value;
+
+ BT_ASSERT(event);
+
+ if (event->common.header_field) {
+ bt_field_common_set_is_frozen_recursive(
+ event->common.header_field->field, false);
+ bt_field_common_reset_recursive(
+ event->common.header_field->field);
+ }
+
+ if (event->common.stream_event_context_field) {
+ bt_field_common_set_is_frozen_recursive(
+ event->common.stream_event_context_field, false);
+ bt_field_common_reset_recursive(
+ event->common.stream_event_context_field);
+ }
+
+ if (event->common.context_field) {
+ bt_field_common_set_is_frozen_recursive(
+ event->common.context_field, false);
+ bt_field_common_reset_recursive(event->common.context_field);
+ }
+
+ if (event->common.payload_field) {
+ bt_field_common_set_is_frozen_recursive(
+ event->common.payload_field, false);
+ bt_field_common_reset_recursive(event->common.payload_field);
+ }
+
+ g_hash_table_iter_init(&iter, event->clock_values);
+ while (g_hash_table_iter_next(&iter, &key, &value)) {
+ struct bt_clock_value *clock_value = value;
+
+ BT_ASSERT(clock_value);
+ bt_clock_value_reset(clock_value);
+ bt_clock_value_set_is_frozen(clock_value, false);
+ }
+}
+
+#ifdef BT_DEV_MODE
+# define bt_event_reset_dev_mode _bt_event_reset_dev_mode
+#else
+# define bt_event_reset_dev_mode(_x)
+#endif
+
+static inline
+void bt_event_reset(struct bt_event *event)
+{
+ BT_ASSERT(event);
+ event->common.frozen = false;
+ bt_event_reset_dev_mode(event);
+ BT_PUT(event->packet);
+}
+
+BT_HIDDEN
+struct bt_event *bt_event_create(struct bt_event_class *event_class,
+ struct bt_packet *packet)
+{
+ int ret;
+ struct bt_event *event = NULL;
+
+ BT_ASSERT(event_class);
+ event = bt_object_pool_create_object(&event_class->event_pool);
+ if (!event) {
+ BT_LIB_LOGE("Cannot allocate one event from event class's event pool: "
+ "%![event-class-]+E", event_class);
+ goto error;
+ }
+
+ if (!event->common.class) {
+ event->common.class = bt_get(event_class);
+ }
+
+ BT_ASSERT(packet);
+ ret = bt_event_set_packet(event, packet);
+ if (ret) {
+ BT_LIB_LOGE("Cannot set event's packet: "
+ "%![event-]+e, %![packet-]+a", event, packet);
+ goto error;
+ }
+
+ goto end;
+
+error:
+ if (event) {
+ bt_event_recycle(event);
+ event = NULL;
+ }
end:
return event;
bt_event_common_borrow_payload(BT_TO_COMMON(event)));
}
-int bt_event_set_payload(struct bt_event *event, struct bt_field *field)
-{
- return bt_event_common_set_payload(BT_TO_COMMON(event),
- (void *) field);
-}
-
struct bt_field *bt_event_borrow_header(struct bt_event *event)
{
return BT_FROM_COMMON(
bt_event_common_borrow_header(BT_TO_COMMON(event)));
}
-int bt_event_set_header(struct bt_event *event, struct bt_field *field)
-{
- return bt_event_common_set_header(BT_TO_COMMON(event), (void *) field);
-}
-
struct bt_field *bt_event_borrow_context(struct bt_event *event)
{
return BT_FROM_COMMON(
bt_event_common_borrow_context(BT_TO_COMMON(event)));
}
-int bt_event_set_context(struct bt_event *event, struct bt_field *field)
-{
- return bt_event_common_set_context(BT_TO_COMMON(event), (void *) field);
-}
-
struct bt_field *bt_event_borrow_stream_event_context(
struct bt_event *event)
{
BT_TO_COMMON(event)));
}
-int bt_event_set_stream_event_context(struct bt_event *event,
- struct bt_field *field)
+static
+void release_event_header_field(struct bt_field_wrapper *field_wrapper,
+ struct bt_event_common *event_common)
{
- return bt_event_common_set_stream_event_context(
- BT_TO_COMMON(event), (void *) field);
+ struct bt_event *event = BT_FROM_COMMON(event_common);
+ struct bt_event_class *event_class = bt_event_borrow_class(event);
+
+ if (!event_class) {
+ bt_field_wrapper_destroy(field_wrapper);
+ } else {
+ struct bt_stream_class *stream_class =
+ bt_event_class_borrow_stream_class(event_class);
+
+ BT_ASSERT(stream_class);
+ bt_event_header_field_recycle(field_wrapper, stream_class);
+ }
}
-void bt_event_destroy(struct bt_object *obj)
+BT_HIDDEN
+void bt_event_destroy(struct bt_event *event)
{
- struct bt_event *event = (void *) obj;
-
- bt_event_common_finalize(obj);
+ BT_ASSERT(event);
+ bt_event_common_finalize((void *) event,
+ (void *) bt_field_destroy_recursive,
+ (void *) release_event_header_field);
g_hash_table_destroy(event->clock_values);
BT_LOGD_STR("Putting event's packet.");
bt_put(event->packet);
return clock_value;
}
-int bt_event_set_clock_value(struct bt_event *event,
- struct bt_clock_value *value)
-{
- struct bt_trace *trace;
- struct bt_stream_class *stream_class;
- struct bt_event_class *event_class;
- struct bt_clock_class *clock_class = NULL;
-
- BT_ASSERT_PRE_NON_NULL(event, "Event");
- BT_ASSERT_PRE_NON_NULL(value, "Clock value");
- BT_ASSERT_PRE_EVENT_COMMON_HOT(BT_TO_COMMON(event), "Event");
- clock_class = bt_clock_value_borrow_class(value);
- event_class = BT_FROM_COMMON(event->common.class);
- BT_ASSERT(event_class);
- stream_class = bt_event_class_borrow_stream_class(event_class);
- BT_ASSERT(stream_class);
- trace = bt_stream_class_borrow_trace(stream_class);
- BT_ASSERT(trace);
- BT_ASSERT_PRE(bt_trace_common_has_clock_class(BT_TO_COMMON(trace),
- clock_class),
- "Clock class is not part of event's trace: "
- "%![event-]+e, %![clock-class-]+K",
- event, clock_class);
- g_hash_table_insert(event->clock_values, clock_class, bt_get(value));
- BT_LOGV("Set event's clock value: "
- "event-addr=%p, event-class-name=\"%s\", "
- "event-class-id=%" PRId64 ", clock-class-addr=%p, "
- "clock-class-name=\"%s\", clock-value-addr=%p, "
- "clock-value-cycles=%" PRIu64,
- event, bt_event_class_common_get_name(event->common.class),
- bt_event_class_common_get_id(event->common.class),
- clock_class, bt_clock_class_get_name(clock_class),
- value, value->value);
- return 0;
-}
-
struct bt_packet *bt_event_borrow_packet(struct bt_event *event)
{
struct bt_packet *packet = NULL;
return packet;
}
-int bt_event_set_packet(struct bt_event *event,
- struct bt_packet *packet)
+BT_HIDDEN
+int bt_event_set_packet(struct bt_event *event, struct bt_packet *packet)
{
BT_ASSERT_PRE_NON_NULL(event, "Event");
BT_ASSERT_PRE_NON_NULL(packet, "Packet");
BT_LOGD_STR("Freezing event's packet.");
bt_packet_freeze(event->packet);
}
+
+BT_HIDDEN
+void bt_event_recycle(struct bt_event *event)
+{
+ struct bt_event_class *event_class;
+
+ BT_ASSERT(event);
+ BT_LIB_LOGD("Recycling event: %!+e", event);
+
+ /*
+ * Those are the important ordered steps:
+ *
+ * 1. Reset the event object (put any permanent reference it
+ * has, unfreeze it and its fields in developer mode, etc.),
+ * but do NOT put its class's reference. This event class
+ * contains the pool to which we're about to recycle this
+ * event object, so we must guarantee its existence thanks
+ * to this existing reference.
+ *
+ * 2. Move the event class reference to our `event_class`
+ * variable so that we can set the event's class member
+ * to NULL before recycling it. We CANNOT do this after
+ * we put the event class reference because this bt_put()
+ * could destroy the event class, also destroying its
+ * event pool, thus also destroying our event object (this
+ * would result in an invalid write access).
+ *
+ * 3. Recycle the event object.
+ *
+ * 4. Put our event class reference.
+ */
+ bt_event_reset(event);
+ event_class = BT_FROM_COMMON(event->common.class);
+ BT_ASSERT(event_class);
+ event->common.class = NULL;
+ bt_object_pool_recycle_object(&event_class->event_pool, event);
+ bt_put(event_class);
+}
+
+int bt_event_move_header(struct bt_event *event,
+ struct bt_event_header_field *header_field)
+{
+ struct bt_stream_class *stream_class;
+ struct bt_field_wrapper *field_wrapper = (void *) header_field;
+
+ BT_ASSERT_PRE_NON_NULL(event, "Event");
+ BT_ASSERT_PRE_NON_NULL(field_wrapper, "Header field");
+ BT_ASSERT_PRE_HOT(BT_TO_COMMON(event), "Event", ": +%!+e", event);
+ stream_class = bt_event_class_borrow_stream_class(
+ bt_event_borrow_class(event));
+ BT_ASSERT_PRE(stream_class->common.event_header_field_type,
+ "Stream class has no event header field type: %!+S",
+ stream_class);
+
+ /* Recycle current header field: always exists */
+ BT_ASSERT(event->common.header_field);
+ bt_event_header_field_recycle(event->common.header_field,
+ stream_class);
+
+ /* Move new field */
+ event->common.header_field = (void *) field_wrapper;
+ return 0;
+}
g_free(mapping);
}
-static
-void destroy_structure_field_common(struct structure_field_common *field)
-{
- if (!field) {
- return;
- }
-
- BT_LOGD("Destroying structure/variant field type's field object: "
- "addr=%p, field-ft-addr=%p, field-name=\"%s\"",
- field, field->type, g_quark_to_string(field->name));
- BT_LOGD_STR("Putting field type.");
- bt_put(field->type);
- g_free(field);
-}
-
BT_HIDDEN
void bt_field_type_common_initialize(struct bt_field_type_common *ft,
bool init_bo, bt_object_release_func release_func,
BT_LOGD_STR("Initializing common structure field type object.");
ft->id = BT_FIELD_TYPE_ID_STRUCT;
- struct_ft->fields = g_ptr_array_new_with_free_func(
- (GDestroyNotify) destroy_structure_field_common);
+ struct_ft->fields = g_array_new(FALSE, TRUE,
+ sizeof(struct bt_field_type_common_structure_field));
struct_ft->field_name_to_index = g_hash_table_new(NULL, NULL);
bt_field_type_common_initialize(ft, true, release_func, methods);
BT_LOGD("Initialized common structure field type object: addr=%p", ft);
tag_ft, tag_name);
ft->id = BT_FIELD_TYPE_ID_VARIANT;
var_ft->tag_name = g_string_new(tag_name);
- var_ft->field_name_to_index = g_hash_table_new(NULL, NULL);
- var_ft->fields = g_ptr_array_new_with_free_func(
- (GDestroyNotify) destroy_structure_field_common);
+ var_ft->choice_name_to_index = g_hash_table_new(NULL, NULL);
+ var_ft->choices = g_array_new(FALSE, TRUE,
+ sizeof(struct bt_field_type_common_variant_choice));
if (tag_ft) {
var_ft->tag_ft = bt_get(tag_ft);
g_free(ft);
}
+static
+void bt_field_type_common_structure_field_finalize(
+ struct bt_field_type_common_structure_field *field)
+{
+ if (!field) {
+ return;
+ }
+
+ BT_LOGD("Finalizing structure field type's field: "
+ "addr=%p, field-ft-addr=%p, field-name=\"%s\"",
+ field, field->type, g_quark_to_string(field->name));
+ BT_LOGD_STR("Putting field type.");
+ bt_put(field->type);
+}
BT_HIDDEN
void bt_field_type_common_structure_destroy_recursive(struct bt_object *obj)
{
struct bt_field_type_common_structure *ft = (void *) obj;
+ uint64_t i;
if (!ft) {
return;
}
BT_LOGD("Destroying structure field type object: addr=%p", ft);
- g_ptr_array_free(ft->fields, TRUE);
- g_hash_table_destroy(ft->field_name_to_index);
+
+ if (ft->fields) {
+ for (i = 0; i < ft->fields->len; i++) {
+ bt_field_type_common_structure_field_finalize(
+ BT_FIELD_TYPE_COMMON_STRUCTURE_FIELD_AT_INDEX(
+ ft, i));
+ }
+
+ g_array_free(ft->fields, TRUE);
+ }
+
+ if (ft->field_name_to_index) {
+ g_hash_table_destroy(ft->field_name_to_index);
+ }
+
g_free(ft);
}
g_free(ft);
}
+static
+void bt_field_type_common_variant_choice_finalize(
+ struct bt_field_type_common_variant_choice *choice)
+{
+ if (!choice) {
+ return;
+ }
+
+ BT_LOGD("Finalizing variant field type's choice: "
+ "addr=%p, field-ft-addr=%p, field-name=\"%s\"",
+ choice, choice->type, g_quark_to_string(choice->name));
+ BT_LOGD_STR("Putting field type.");
+ bt_put(choice->type);
+
+ if (choice->ranges) {
+ g_array_free(choice->ranges, TRUE);
+ }
+}
+
BT_HIDDEN
void bt_field_type_common_variant_destroy_recursive(struct bt_object *obj)
{
struct bt_field_type_common_variant *ft = (void *) obj;
+ uint64_t i;
if (!ft) {
return;
}
BT_LOGD("Destroying variant field type object: addr=%p", ft);
- g_ptr_array_free(ft->fields, TRUE);
- g_hash_table_destroy(ft->field_name_to_index);
- g_string_free(ft->tag_name, TRUE);
+
+ if (ft->choices) {
+ for (i = 0; i < ft->choices->len; i++) {
+ bt_field_type_common_variant_choice_finalize(
+ BT_FIELD_TYPE_COMMON_VARIANT_CHOICE_AT_INDEX(
+ ft, i));
+ }
+
+ g_array_free(ft->choices, TRUE);
+ }
+
+ if (ft->choice_name_to_index) {
+ g_hash_table_destroy(ft->choice_name_to_index);
+ }
+
+ if (ft->tag_name) {
+ g_string_free(ft->tag_name, TRUE);
+ }
+
BT_LOGD_STR("Putting tag field type.");
bt_put(ft->tag_ft);
BT_LOGD_STR("Putting tag field path.");
}
static
-int add_structure_field(GPtrArray *fields,
+int add_structure_variant_member(GArray *members,
GHashTable *field_name_to_index,
- struct bt_field_type_common *field_type, const char *field_name)
+ struct bt_field_type_common *field_type, const char *field_name,
+ bool is_variant)
{
int ret = 0;
GQuark name_quark = g_quark_from_string(field_name);
- struct structure_field_common *field;
+ struct bt_field_type_common **member_ft;
+ GQuark *member_name;
/* Make sure structure does not contain a field of the same name */
if (g_hash_table_lookup_extended(field_name_to_index,
goto end;
}
- field = g_new0(struct structure_field_common, 1);
- if (!field) {
- BT_LOGE_STR("Failed to allocate one structure/variant field type field.");
- ret = -1;
- goto end;
+ g_array_set_size(members, members->len + 1);
+
+ if (is_variant) {
+ struct bt_field_type_common_variant_choice *choice =
+ &g_array_index(members,
+ struct bt_field_type_common_variant_choice,
+ members->len - 1);
+
+ member_ft = &choice->type;
+ member_name = &choice->name;
+ BT_ASSERT(!choice->ranges);
+ choice->ranges = g_array_new(FALSE, TRUE,
+ sizeof(struct bt_field_type_common_variant_choice_range));
+ BT_ASSERT(choice->ranges);
+ } else {
+ struct bt_field_type_common_structure_field *field =
+ &g_array_index(members,
+ struct bt_field_type_common_structure_field,
+ members->len - 1);
+
+ member_ft = &field->type;
+ member_name = &field->name;
}
- bt_get(field_type);
- field->name = name_quark;
- field->type = field_type;
+ *member_name = name_quark;
+ *member_ft = bt_get(field_type);
g_hash_table_insert(field_name_to_index,
- GUINT_TO_POINTER(name_quark), GUINT_TO_POINTER(fields->len));
- g_ptr_array_add(fields, field);
- BT_LOGV("Added structure/variant field type field: field-ft-addr=%p, "
- "field-name=\"%s\"", field_type, field_name);
+ GUINT_TO_POINTER(name_quark),
+ GUINT_TO_POINTER(members->len - 1));
+ BT_LOGV("Added structure/variant field type member: member-ft-addr=%p, "
+ "member-name=\"%s\"", field_type, field_name);
+
end:
return ret;
}
name_quark = g_quark_from_string(field_name);
for (i = 0; i < struct_ft->fields->len; i++) {
- struct structure_field_common *field = g_ptr_array_index(
- struct_ft->fields, i);
+ struct bt_field_type_common_structure_field *field =
+ BT_FIELD_TYPE_COMMON_STRUCTURE_FIELD_AT_INDEX(ft, i);
if (field->name == name_quark) {
bt_put(field->type);
goto end;
}
- if (add_structure_field(struct_ft->fields,
- struct_ft->field_name_to_index, field_type, field_name)) {
+ if (add_structure_variant_member(struct_ft->fields,
+ struct_ft->field_name_to_index, field_type, field_name,
+ false)) {
BT_LOGW("Cannot add field to structure field type: "
"struct-ft-addr=%p, field-ft-addr=%p, field-name=\"%s\"",
ft, field_type, field_name);
struct bt_field_type_common **field_type, uint64_t index)
{
struct bt_field_type_common_structure *struct_ft = BT_FROM_COMMON(ft);
- struct structure_field_common *field;
+ struct bt_field_type_common_structure_field *field;
BT_ASSERT_PRE_NON_NULL(ft, "Field type");
BT_ASSERT_PRE_FT_COMMON_HAS_ID(ft, BT_FIELD_TYPE_ID_STRUCT,
"Index is out of bounds: index=%" PRIu64 ", "
"count=%u, %![ft-]+_F",
index, struct_ft->fields->len, ft);
- field = g_ptr_array_index(struct_ft->fields, index);
+ field = BT_FIELD_TYPE_COMMON_STRUCTURE_FIELD_AT_INDEX(struct_ft, index);
if (field_type) {
*field_type = field->type;
{
size_t index;
GQuark name_quark;
- struct structure_field_common *field;
+ struct bt_field_type_common_structure_field *field;
struct bt_field_type_common_structure *struct_ft = BT_FROM_COMMON(ft);
struct bt_field_type_common *field_type = NULL;
goto end;
}
- field = struct_ft->fields->pdata[index];
+ field = BT_FIELD_TYPE_COMMON_STRUCTURE_FIELD_AT_INDEX(ft, index);
field_type = field->type;
end:
}
}
- if (add_structure_field(var_ft->fields, var_ft->field_name_to_index,
- field_type, field_name)) {
+ if (add_structure_variant_member(var_ft->choices,
+ var_ft->choice_name_to_index, field_type,
+ field_name, true)) {
BT_LOGW("Cannot add field to variant field type: "
"variant-ft-addr=%p, field-ft-addr=%p, field-name=\"%s\"",
ft, field_type, field_name);
{
size_t index;
GQuark name_quark;
- struct structure_field_common *field;
+ struct bt_field_type_common_variant_choice *choice;
struct bt_field_type_common_variant *var_ft = BT_FROM_COMMON(ft);
struct bt_field_type_common *field_type = NULL;
goto end;
}
- if (!g_hash_table_lookup_extended(var_ft->field_name_to_index,
+ if (!g_hash_table_lookup_extended(var_ft->choice_name_to_index,
GUINT_TO_POINTER(name_quark), NULL, (gpointer *) &index)) {
BT_LOGV("No such variant field type field name: "
"ft-addr=%p, field-name=\"%s\"",
goto end;
}
- field = g_ptr_array_index(var_ft->fields, index);
- field_type = field->type;
+ choice = BT_FIELD_TYPE_COMMON_VARIANT_CHOICE_AT_INDEX(ft, index);
+ field_type = choice->type;
end:
return field_type;
(void *) ft, field_name);
}
-BT_HIDDEN
-struct bt_field_type_common *
-bt_field_type_common_variant_borrow_field_type_from_tag(
- struct bt_field_type_common *ft,
- struct bt_field_common *tag_field,
- bt_field_common_create_func field_create_func)
-{
- int ret;
- const char *enum_value;
- struct bt_field_type_common *field_type = NULL;
- struct bt_field_type_enumeration_mapping_iterator *iter = NULL;
-
- BT_ASSERT_PRE_NON_NULL(ft, "Variant field type");
- BT_ASSERT_PRE_NON_NULL(tag_field, "Tag field");
- BT_ASSERT_PRE_FT_COMMON_HAS_ID(ft, BT_FIELD_TYPE_ID_VARIANT,
- "Field type");
- iter = bt_field_common_enumeration_get_mappings(tag_field,
- field_create_func);
- ret = bt_field_type_enumeration_mapping_iterator_next(iter);
- if (!iter || ret) {
- BT_LOGW("Cannot get enumeration field type mapping iterator from enumeration field: "
- "enum-field-addr=%p", tag_field);
- goto end;
- }
-
- ret = bt_field_type_enumeration_mapping_iterator_signed_get(iter,
- &enum_value, NULL, NULL);
- if (ret) {
- BT_LOGW("Cannot get enumeration field type mapping iterator's current mapping: "
- "iter-addr=%p", iter);
- goto end;
- }
-
- field_type = bt_field_type_common_variant_borrow_field_type_by_name(
- ft, enum_value);
-
-end:
- bt_put(iter);
- return field_type;
-}
-
-struct bt_field_type *bt_field_type_variant_borrow_field_type_from_tag(
- struct bt_field_type *ft,
- struct bt_field *tag_field)
-{
- return (void *) bt_field_type_common_variant_borrow_field_type_from_tag(
- (void *) ft, (void *) tag_field,
- (bt_field_common_create_func) bt_field_create);
-}
-
BT_HIDDEN
int64_t bt_field_type_common_variant_get_field_count(
struct bt_field_type_common *ft)
BT_ASSERT_PRE_NON_NULL(ft, "Variant field type");
BT_ASSERT_PRE_FT_COMMON_HAS_ID(ft, BT_FIELD_TYPE_ID_VARIANT,
"Field type");
- return (int64_t) var_ft->fields->len;
+ return (int64_t) var_ft->choices->len;
}
int64_t bt_field_type_variant_get_field_count(struct bt_field_type *ft)
struct bt_field_type_common **field_type, uint64_t index)
{
struct bt_field_type_common_variant *var_ft = BT_FROM_COMMON(ft);
- struct structure_field_common *field;
+ struct bt_field_type_common_variant_choice *choice;
BT_ASSERT_PRE_NON_NULL(ft, "Field type");
BT_ASSERT_PRE_FT_COMMON_HAS_ID(ft, BT_FIELD_TYPE_ID_VARIANT,
"Field type");
- BT_ASSERT_PRE(index < var_ft->fields->len,
+ BT_ASSERT_PRE(index < var_ft->choices->len,
"Index is out of bounds: index=%" PRIu64 ", "
"count=%u, %![ft-]+_F",
- index, var_ft->fields->len, ft);
- field = g_ptr_array_index(var_ft->fields, index);
+ index, var_ft->choices->len, ft);
+ choice = BT_FIELD_TYPE_COMMON_VARIANT_CHOICE_AT_INDEX(ft, index);
if (field_type) {
- *field_type = field->type;
+ *field_type = choice->type;
}
if (field_name) {
- *field_name = g_quark_to_string(field->name);
+ *field_name = g_quark_to_string(choice->name);
BT_ASSERT(*field_name);
}
field_name, (void *) field_type, index);
}
+BT_HIDDEN
+int64_t bt_field_type_common_variant_find_choice_index(
+ struct bt_field_type_common *ft, uint64_t uval,
+ bool is_signed)
+{
+ int64_t ret;
+ uint64_t i;
+ struct bt_field_type_common_variant *var_ft = BT_FROM_COMMON(ft);
+
+ BT_ASSERT(ft);
+ BT_ASSERT(ft->id == BT_FIELD_TYPE_ID_VARIANT);
+
+ if (bt_field_type_common_variant_update_choices(ft)) {
+ ret = INT64_C(-1);
+ goto end;
+ }
+
+ for (i = 0; i < var_ft->choices->len; i++) {
+ uint64_t range_i;
+ struct bt_field_type_common_variant_choice *choice =
+ BT_FIELD_TYPE_COMMON_VARIANT_CHOICE_AT_INDEX(
+ var_ft, i);
+
+ for (range_i = 0; range_i < choice->ranges->len; range_i++) {
+ struct bt_field_type_common_variant_choice_range *range =
+ &g_array_index(
+ choice->ranges,
+ struct bt_field_type_common_variant_choice_range,
+ range_i);
+
+ if (is_signed) {
+ int64_t tag_ival = (int64_t) uval;
+
+ if (tag_ival >= range->lower.i &&
+ tag_ival <= range->upper.i) {
+ goto found;
+ }
+ } else {
+ if (uval >= range->lower.u &&
+ uval <= range->upper.u) {
+ goto found;
+ }
+ }
+ }
+ }
+
+ /* Range not found */
+ ret = INT64_C(-1);
+ goto end;
+
+found:
+ ret = (int64_t) i;
+
+end:
+ return ret;
+}
+
struct bt_field_type *bt_field_type_array_create(
struct bt_field_type *element_ft, unsigned int length)
{
struct bt_field_type_common *field_type = NULL;
GQuark field_name_quark;
gpointer index;
- struct structure_field_common *field_entry;
+ struct bt_field_type_common_variant_choice *choice;
struct range_overlap_query query = {
.range_start._signed = tag_value,
.range_end._signed = tag_value,
}
field_name_quark = query.mapping_name;
- if (!g_hash_table_lookup_extended(var_ft->field_name_to_index,
+ if (!g_hash_table_lookup_extended(var_ft->choice_name_to_index,
GUINT_TO_POINTER(field_name_quark), NULL, &index)) {
goto end;
}
- field_entry = g_ptr_array_index(var_ft->fields, (size_t) index);
- field_type = field_entry->type;
+ choice = BT_FIELD_TYPE_COMMON_VARIANT_CHOICE_AT_INDEX(var_ft,
+ (size_t) index);
+ field_type = choice->type;
end:
return field_type;
struct bt_field_type_common *field_type = NULL;
GQuark field_name_quark;
gpointer index;
- struct structure_field_common *field_entry;
+ struct bt_field_type_common_variant_choice *choice;
struct range_overlap_query query = {
.range_start._unsigned = tag_value,
.range_end._unsigned = tag_value,
}
field_name_quark = query.mapping_name;
- if (!g_hash_table_lookup_extended(var_ft->field_name_to_index,
+ if (!g_hash_table_lookup_extended(var_ft->choice_name_to_index,
GUINT_TO_POINTER(field_name_quark), NULL, &index)) {
goto end;
}
- field_entry = g_ptr_array_index(var_ft->fields, (size_t) index);
- field_type = field_entry->type;
+ choice = BT_FIELD_TYPE_COMMON_VARIANT_CHOICE_AT_INDEX(var_ft,
+ (size_t) index);
+ field_type = choice->type;
+
end:
return field_type;
}
goto end;
}
- if (!g_hash_table_lookup_extended(var_ft->field_name_to_index,
+ if (!g_hash_table_lookup_extended(var_ft->choice_name_to_index,
GUINT_TO_POINTER(name_quark),
NULL, (gpointer *) &index)) {
BT_LOGV("No such variant field type field name: "
bt_field_type_common_freeze(BT_TO_COMMON(enum_ft->container_ft));
}
-static
-void freeze_structure_field(struct structure_field_common *field)
-{
- BT_LOGD("Freezing structure/variant field type field: field-addr=%p, "
- "field-ft-addr=%p, field-name=\"%s\"", field,
- field->type, g_quark_to_string(field->name));
- bt_field_type_common_freeze(field->type);
-}
-
BT_HIDDEN
void bt_field_type_common_structure_freeze_recursive(
struct bt_field_type_common *ft)
{
struct bt_field_type_common_structure *struct_ft = BT_FROM_COMMON(ft);
+ uint64_t i;
/* Cache the alignment */
BT_LOGD("Freezing structure field type object: addr=%p", ft);
ft->alignment = bt_field_type_common_get_alignment(ft);
bt_field_type_common_generic_freeze(ft);
- g_ptr_array_foreach(struct_ft->fields,
- (GFunc) freeze_structure_field, NULL);
+
+ for (i = 0; i < struct_ft->fields->len; i++) {
+ struct bt_field_type_common_structure_field *field =
+ BT_FIELD_TYPE_COMMON_STRUCTURE_FIELD_AT_INDEX(ft, i);
+
+ BT_LOGD("Freezing structure field type field: "
+ "ft-addr=%p, name=\"%s\"",
+ field->type, g_quark_to_string(field->name));
+ bt_field_type_common_freeze(field->type);
+ }
+}
+
+BT_HIDDEN
+int bt_field_type_common_variant_update_choices(struct bt_field_type_common *ft)
+{
+ struct bt_field_type_common_variant *var_ft = BT_FROM_COMMON(ft);
+ uint64_t i;
+ int ret = 0;
+ bool is_signed;
+
+ if (ft->frozen && var_ft->choices_up_to_date) {
+ goto end;
+ }
+
+ BT_ASSERT(var_ft->tag_ft);
+ is_signed = !!var_ft->tag_ft->container_ft->is_signed;
+
+ for (i = 0; i < var_ft->choices->len; i++) {
+ struct bt_field_type_common_variant_choice *choice =
+ BT_FIELD_TYPE_COMMON_VARIANT_CHOICE_AT_INDEX(ft, i);
+ const char *choice_name = g_quark_to_string(choice->name);
+ struct bt_field_type_enumeration_mapping_iterator *iter =
+ bt_field_type_common_enumeration_find_mappings_by_name(
+ BT_TO_COMMON(var_ft->tag_ft), choice_name);
+
+ if (!iter) {
+ ret = -1;
+ goto end;
+ }
+
+ BT_ASSERT(choice->ranges);
+ g_array_set_size(choice->ranges, 0);
+
+ while (bt_field_type_enumeration_mapping_iterator_next(iter) == 0) {
+ struct bt_field_type_common_variant_choice_range range;
+
+ if (is_signed) {
+ ret = bt_field_type_enumeration_mapping_iterator_signed_get(
+ iter, NULL,
+ &range.lower.i, &range.upper.i);
+ } else {
+ ret = bt_field_type_enumeration_mapping_iterator_unsigned_get(
+ iter, NULL,
+ &range.lower.u, &range.upper.u);
+ }
+
+ BT_ASSERT(ret == 0);
+ g_array_append_val(choice->ranges, range);
+ }
+
+ bt_put(iter);
+ }
+
+ var_ft->choices_up_to_date = true;
+
+end:
+ return ret;
}
BT_HIDDEN
struct bt_field_type_common *ft)
{
struct bt_field_type_common_variant *var_ft = BT_FROM_COMMON(ft);
+ uint64_t i;
BT_LOGD("Freezing variant field type object: addr=%p", ft);
bt_field_type_common_generic_freeze(ft);
- g_ptr_array_foreach(var_ft->fields,
- (GFunc) freeze_structure_field, NULL);
+
+ for (i = 0; i < var_ft->choices->len; i++) {
+ struct bt_field_type_common_variant_choice *choice =
+ BT_FIELD_TYPE_COMMON_VARIANT_CHOICE_AT_INDEX(ft, i);
+
+ BT_LOGD("Freezing variant field type member: "
+ "ft-addr=%p, name=\"%s\"",
+ choice->type, g_quark_to_string(choice->name));
+ bt_field_type_common_freeze(choice->type);
+ }
}
BT_HIDDEN
struct bt_field_type_common_structure *struct_ft = BT_FROM_COMMON(ft);
for (i = 0; i < struct_ft->fields->len; i++) {
- struct structure_field_common *field = g_ptr_array_index(
- struct_ft->fields, i);
+ struct bt_field_type_common_structure_field *field =
+ BT_FIELD_TYPE_COMMON_STRUCTURE_FIELD_AT_INDEX(
+ struct_ft, i);
struct bt_field_type_common *field_type = field->type;
bt_field_type_common_set_byte_order(field_type, byte_order);
int i;
struct bt_field_type_common_variant *var_ft = BT_FROM_COMMON(ft);
- for (i = 0; i < var_ft->fields->len; i++) {
- struct structure_field_common *field = g_ptr_array_index(
- var_ft->fields, i);
- struct bt_field_type_common *field_type = field->type;
+ for (i = 0; i < var_ft->choices->len; i++) {
+ struct bt_field_type_common_variant_choice *choice =
+ BT_FIELD_TYPE_COMMON_VARIANT_CHOICE_AT_INDEX(
+ var_ft, i);
+ struct bt_field_type_common *field_type = choice->type;
bt_field_type_common_set_byte_order(field_type, byte_order);
}
}
static
-int compare_structure_fields(struct structure_field_common *field_a,
- struct structure_field_common *field_b)
+int compare_structure_variant_members(
+ struct bt_field_type_common *member_a_ft,
+ struct bt_field_type_common *member_b_ft,
+ GQuark member_a_name, GQuark member_b_name)
{
int ret = 1;
/* Label */
- if (field_a->name != field_b->name) {
+ if (member_a_name != member_b_name) {
BT_LOGV("Structure/variant field type fields differ: different names: "
"field-a-name=%s, field-b-name=%s",
- g_quark_to_string(field_a->name),
- g_quark_to_string(field_b->name));
+ g_quark_to_string(member_a_name),
+ g_quark_to_string(member_b_name));
goto end;
}
/* Type */
- ret = bt_field_type_common_compare(field_a->type, field_b->type);
+ ret = bt_field_type_common_compare(member_a_ft, member_b_ft);
if (ret == 1) {
BT_LOGV("Structure/variant field type fields differ: different field types: "
"field-name=\"%s\", field-a-ft-addr=%p, field-b-ft-addr=%p",
- g_quark_to_string(field_a->name),
- field_a->type, field_b->type);
+ g_quark_to_string(member_a_name),
+ member_a_ft, member_b_ft);
}
end:
}
for (i = 0; i < struct_ft_a->fields->len; ++i) {
- struct structure_field_common *field_a =
- g_ptr_array_index(struct_ft_a->fields, i);
- struct structure_field_common *field_b =
- g_ptr_array_index(struct_ft_b->fields, i);
-
- ret = compare_structure_fields(field_a, field_b);
+ struct bt_field_type_common_structure_field *field_a =
+ BT_FIELD_TYPE_COMMON_STRUCTURE_FIELD_AT_INDEX(
+ struct_ft_a, i);
+ struct bt_field_type_common_structure_field *field_b =
+ BT_FIELD_TYPE_COMMON_STRUCTURE_FIELD_AT_INDEX(
+ struct_ft_b, i);
+
+ ret = compare_structure_variant_members(field_a->type,
+ field_b->type, field_a->name, field_b->name);
if (ret) {
- /* compare_structure_fields() logs what differs */
+ /* compare_structure_variant_members() logs what differs */
BT_LOGV_STR("Structure field types differ: different fields.");
goto end;
}
ret = 1;
/* Fields */
- if (var_ft_a->fields->len != var_ft_b->fields->len) {
- BT_LOGV("Structure field types differ: different field counts: "
+ if (var_ft_a->choices->len != var_ft_b->choices->len) {
+ BT_LOGV("Variant field types differ: different field counts: "
"ft-a-field-count=%u, ft-b-field-count=%u",
- var_ft_a->fields->len, var_ft_b->fields->len);
+ var_ft_a->choices->len, var_ft_b->choices->len);
goto end;
}
- for (i = 0; i < var_ft_a->fields->len; ++i) {
- struct structure_field_common *field_a =
- g_ptr_array_index(var_ft_a->fields, i);
- struct structure_field_common *field_b =
- g_ptr_array_index(var_ft_b->fields, i);
+ for (i = 0; i < var_ft_a->choices->len; ++i) {
+ struct bt_field_type_common_variant_choice *choice_a =
+ BT_FIELD_TYPE_COMMON_VARIANT_CHOICE_AT_INDEX(
+ var_ft_a, i);
+ struct bt_field_type_common_variant_choice *choice_b =
+ BT_FIELD_TYPE_COMMON_VARIANT_CHOICE_AT_INDEX(
+ var_ft_b, i);
- ret = compare_structure_fields(field_a, field_b);
+ ret = compare_structure_variant_members(choice_a->type,
+ choice_b->type, choice_a->name, choice_b->name);
if (ret) {
- /* compare_structure_fields() logs what differs */
+ /* compare_structure_variant_members() logs what differs */
BT_LOGV_STR("Variant field types differ: different fields.");
goto end;
}
struct bt_field_type_common_integer *int_ft = (void *) ft;
struct bt_field_type_common_integer *copy_ft;
- BT_LOGD("Copying CTF writer integer field type's: addr=%p", ft);
+ BT_LOGD("Copying integer field type's: addr=%p", ft);
copy_ft = (void *) bt_field_type_integer_create(int_ft->size);
if (!copy_ft) {
- BT_LOGE_STR("Cannot create CTF writer integer field type.");
+ BT_LOGE_STR("Cannot create integer field type.");
goto end;
}
copy_ft->size = int_ft->size;
copy_ft->base = int_ft->base;
copy_ft->encoding = int_ft->encoding;
- BT_LOGD("Copied CTF writer integer field type: original-ft-addr=%p, copy-ft-addr=%p",
+ BT_LOGD("Copied integer field type: original-ft-addr=%p, copy-ft-addr=%p",
ft, copy_ft);
end:
struct bt_field_type_common_enumeration *copy_ft = NULL;
struct bt_field_type_common_enumeration *container_copy_ft;
- BT_LOGD("Copying CTF writer enumeration field type's: addr=%p", ft);
+ BT_LOGD("Copying enumeration field type's: addr=%p", ft);
/* Copy the source enumeration's container */
- BT_LOGD_STR("Copying CTF writer enumeration field type's container field type.");
+ BT_LOGD_STR("Copying enumeration field type's container field type.");
container_copy_ft = BT_FROM_COMMON(bt_field_type_common_copy(
BT_TO_COMMON(enum_ft->container_ft)));
if (!container_copy_ft) {
- BT_LOGE_STR("Cannot copy CTF writer enumeration field type's container field type.");
+ BT_LOGE_STR("Cannot copy enumeration field type's container field type.");
goto end;
}
copy_ft = (void *) bt_field_type_enumeration_create(
(void *) container_copy_ft);
if (!copy_ft) {
- BT_LOGE_STR("Cannot create CTF writer enumeration field type.");
+ BT_LOGE_STR("Cannot create enumeration field type.");
goto end;
}
g_ptr_array_add(copy_ft->entries, copy_mapping);
}
- BT_LOGD("Copied CTF writer enumeration field type: original-ft-addr=%p, copy-ft-addr=%p",
+ BT_LOGD("Copied enumeration field type: original-ft-addr=%p, copy-ft-addr=%p",
ft, copy_ft);
end:
struct bt_field_type_common_floating_point *flt_ft = BT_FROM_COMMON(ft);
struct bt_field_type_common_floating_point *copy_ft;
- BT_LOGD("Copying CTF writer floating point number field type's: addr=%p", ft);
+ BT_LOGD("Copying floating point number field type's: addr=%p", ft);
copy_ft = (void *) bt_field_type_floating_point_create();
if (!copy_ft) {
- BT_LOGE_STR("Cannot create CTF writer floating point number field type.");
+ BT_LOGE_STR("Cannot create floating point number field type.");
goto end;
}
copy_ft->user_byte_order = flt_ft->user_byte_order;
copy_ft->exp_dig = flt_ft->exp_dig;
copy_ft->mant_dig = flt_ft->mant_dig;
- BT_LOGD("Copied CTF writer floating point number field type: original-ft-addr=%p, copy-ft-addr=%p",
+ BT_LOGD("Copied floating point number field type: original-ft-addr=%p, copy-ft-addr=%p",
ft, copy_ft);
end:
struct bt_field_type_common_structure *struct_ft = (void *) ft;
struct bt_field_type_common_structure *copy_ft;
- BT_LOGD("Copying CTF writer structure field type's: addr=%p", ft);
+ BT_LOGD("Copying structure field type's: addr=%p", ft);
copy_ft = (void *) bt_field_type_structure_create();
if (!copy_ft) {
- BT_LOGE_STR("Cannot create CTF writer structure field type.");
+ BT_LOGE_STR("Cannot create structure field type.");
goto end;
}
key, value);
}
+ g_array_set_size(copy_ft->fields, struct_ft->fields->len);
+
for (i = 0; i < struct_ft->fields->len; i++) {
- struct structure_field_common *entry, *copy_entry;
+ struct bt_field_type_common_structure_field *entry, *copy_entry;
struct bt_field_type_common *field_ft_copy;
- entry = g_ptr_array_index(struct_ft->fields, i);
- BT_LOGD("Copying CTF writer structure field type's field: "
+ entry = BT_FIELD_TYPE_COMMON_STRUCTURE_FIELD_AT_INDEX(
+ struct_ft, i);
+ copy_entry = BT_FIELD_TYPE_COMMON_STRUCTURE_FIELD_AT_INDEX(
+ copy_ft, i);
+ BT_LOGD("Copying structure field type's field: "
"index=%" PRId64 ", "
"field-ft-addr=%p, field-name=\"%s\"",
i, entry, g_quark_to_string(entry->name));
- copy_entry = g_new0(struct structure_field_common, 1);
- if (!copy_entry) {
- BT_LOGE_STR("Failed to allocate one structure field type field.");
- goto error;
- }
field_ft_copy = (void *) bt_field_type_copy(
(void *) entry->type);
if (!field_ft_copy) {
- BT_LOGE("Cannot copy CTF writer structure field type's field: "
+ BT_LOGE("Cannot copy structure field type's field: "
"index=%" PRId64 ", "
"field-ft-addr=%p, field-name=\"%s\"",
i, entry, g_quark_to_string(entry->name));
- g_free(copy_entry);
goto error;
}
copy_entry->name = entry->name;
copy_entry->type = field_ft_copy;
- g_ptr_array_add(copy_ft->fields, copy_entry);
}
- BT_LOGD("Copied CTF writer structure field type: original-ft-addr=%p, copy-ft-addr=%p",
+ BT_LOGD("Copied structure field type: original-ft-addr=%p, copy-ft-addr=%p",
ft, copy_ft);
end:
struct bt_field_type_common_variant *var_ft = (void *) ft;
struct bt_field_type_common_variant *copy_ft = NULL;
- BT_LOGD("Copying CTF writer variant field type's: addr=%p", ft);
+ BT_LOGD("Copying variant field type's: addr=%p", ft);
if (var_ft->tag_ft) {
- BT_LOGD_STR("Copying CTF writer variant field type's tag field type.");
+ BT_LOGD_STR("Copying variant field type's tag field type.");
tag_ft_copy = bt_field_type_common_copy(
BT_TO_COMMON(var_ft->tag_ft));
if (!tag_ft_copy) {
- BT_LOGE_STR("Cannot copy CTF writer variant field type's tag field type.");
+ BT_LOGE_STR("Cannot copy variant field type's tag field type.");
goto end;
}
}
(void *) tag_ft_copy,
var_ft->tag_name->len ? var_ft->tag_name->str : NULL);
if (!copy_ft) {
- BT_LOGE_STR("Cannot create CTF writer variant field type.");
+ BT_LOGE_STR("Cannot create variant field type.");
goto end;
}
/* Copy field_name_to_index */
- g_hash_table_iter_init(&iter, var_ft->field_name_to_index);
+ g_hash_table_iter_init(&iter, var_ft->choice_name_to_index);
while (g_hash_table_iter_next(&iter, &key, &value)) {
- g_hash_table_insert(copy_ft->field_name_to_index,
+ g_hash_table_insert(copy_ft->choice_name_to_index,
key, value);
}
- for (i = 0; i < var_ft->fields->len; i++) {
- struct structure_field_common *entry, *copy_entry;
+ g_array_set_size(copy_ft->choices, var_ft->choices->len);
+
+ for (i = 0; i < var_ft->choices->len; i++) {
+ struct bt_field_type_common_variant_choice *entry, *copy_entry;
struct bt_field_type_common *field_ft_copy;
+ uint64_t range_i;
- entry = g_ptr_array_index(var_ft->fields, i);
- BT_LOGD("Copying CTF writer variant field type's field: "
+ entry = BT_FIELD_TYPE_COMMON_VARIANT_CHOICE_AT_INDEX(var_ft, i);
+ copy_entry = BT_FIELD_TYPE_COMMON_VARIANT_CHOICE_AT_INDEX(
+ copy_ft, i);
+ BT_LOGD("Copying variant field type's field: "
"index=%" PRId64 ", "
"field-ft-addr=%p, field-name=\"%s\"",
i, entry, g_quark_to_string(entry->name));
- copy_entry = g_new0(struct structure_field_common, 1);
- if (!copy_entry) {
- BT_LOGE_STR("Failed to allocate one variant field type field.");
- goto error;
- }
field_ft_copy = (void *) bt_field_type_copy(
(void *) entry->type);
if (!field_ft_copy) {
- BT_LOGE("Cannot copy CTF writer variant field type's field: "
+ BT_LOGE("Cannot copy variant field type's field: "
"index=%" PRId64 ", "
"field-ft-addr=%p, field-name=\"%s\"",
i, entry, g_quark_to_string(entry->name));
copy_entry->name = entry->name;
copy_entry->type = field_ft_copy;
- g_ptr_array_add(copy_ft->fields, copy_entry);
+
+ /* Copy ranges */
+ copy_entry->ranges = g_array_new(FALSE, TRUE,
+ sizeof(struct bt_field_type_common_variant_choice_range));
+ BT_ASSERT(copy_entry->ranges);
+ g_array_set_size(copy_entry->ranges, entry->ranges->len);
+
+ for (range_i = 0; range_i < entry->ranges->len; range_i++) {
+ copy_entry->ranges[range_i] = entry->ranges[range_i];
+ }
}
if (var_ft->tag_field_path) {
- BT_LOGD_STR("Copying CTF writer variant field type's tag field path.");
+ BT_LOGD_STR("Copying variant field type's tag field path.");
copy_ft->tag_field_path = bt_field_path_copy(
var_ft->tag_field_path);
if (!copy_ft->tag_field_path) {
- BT_LOGE_STR("Cannot copy CTF writer variant field type's tag field path.");
+ BT_LOGE_STR("Cannot copy variant field type's tag field path.");
goto error;
}
}
+ copy_ft->choices_up_to_date = var_ft->choices_up_to_date;
BT_LOGD("Copied variant field type: original-ft-addr=%p, copy-ft-addr=%p",
ft, copy_ft);
struct bt_field_type_common_array *array_ft = (void *) ft;
struct bt_field_type_common_array *copy_ft = NULL;
- BT_LOGD("Copying CTF writer array field type's: addr=%p", ft);
- BT_LOGD_STR("Copying CTF writer array field type's element field type.");
+ BT_LOGD("Copying array field type's: addr=%p", ft);
+ BT_LOGD_STR("Copying array field type's element field type.");
container_ft_copy = bt_field_type_common_copy(array_ft->element_ft);
if (!container_ft_copy) {
- BT_LOGE_STR("Cannot copy CTF writer array field type's element field type.");
+ BT_LOGE_STR("Cannot copy array field type's element field type.");
goto end;
}
copy_ft = (void *) bt_field_type_array_create(
(void *) container_ft_copy, array_ft->length);
if (!copy_ft) {
- BT_LOGE_STR("Cannot create CTF writer array field type.");
+ BT_LOGE_STR("Cannot create array field type.");
goto end;
}
- BT_LOGD("Copied CTF writer array field type: original-ft-addr=%p, copy-ft-addr=%p",
+ BT_LOGD("Copied array field type: original-ft-addr=%p, copy-ft-addr=%p",
ft, copy_ft);
end:
struct bt_field_type_common_sequence *seq_ft = (void *) ft;
struct bt_field_type_common_sequence *copy_ft = NULL;
- BT_LOGD("Copying CTF writer sequence field type's: addr=%p", ft);
- BT_LOGD_STR("Copying CTF writer sequence field type's element field type.");
+ BT_LOGD("Copying sequence field type's: addr=%p", ft);
+ BT_LOGD_STR("Copying sequence field type's element field type.");
container_ft_copy = bt_field_type_common_copy(seq_ft->element_ft);
if (!container_ft_copy) {
- BT_LOGE_STR("Cannot copy CTF writer sequence field type's element field type.");
+ BT_LOGE_STR("Cannot copy sequence field type's element field type.");
goto end;
}
seq_ft->length_field_name->len ?
seq_ft->length_field_name->str : NULL);
if (!copy_ft) {
- BT_LOGE_STR("Cannot create CTF writer sequence field type.");
+ BT_LOGE_STR("Cannot create sequence field type.");
goto end;
}
if (seq_ft->length_field_path) {
- BT_LOGD_STR("Copying CTF writer sequence field type's length field path.");
+ BT_LOGD_STR("Copying sequence field type's length field path.");
copy_ft->length_field_path = bt_field_path_copy(
seq_ft->length_field_path);
if (!copy_ft->length_field_path) {
- BT_LOGE_STR("Cannot copy CTF writer sequence field type's length field path.");
+ BT_LOGE_STR("Cannot copy sequence field type's length field path.");
goto error;
}
}
- BT_LOGD("Copied CTF writer sequence field type: original-ft-addr=%p, copy-ft-addr=%p",
+ BT_LOGD("Copied sequence field type: original-ft-addr=%p, copy-ft-addr=%p",
ft, copy_ft);
end:
struct bt_field_type_common_string *string_ft = (void *) ft;
struct bt_field_type_common_string *copy_ft = NULL;
- BT_LOGD("Copying CTF writer string field type's: addr=%p", ft);
+ BT_LOGD("Copying string field type's: addr=%p", ft);
copy_ft = (void *) bt_field_type_string_create();
if (!copy_ft) {
- BT_LOGE_STR("Cannot create CTF writer string field type.");
+ BT_LOGE_STR("Cannot create string field type.");
goto end;
}
copy_ft->encoding = string_ft->encoding;
- BT_LOGD("Copied CTF writer string field type: original-ft-addr=%p, copy-ft-addr=%p",
+ BT_LOGD("Copied string field type: original-ft-addr=%p, copy-ft-addr=%p",
ft, copy_ft);
end:
--- /dev/null
+/*
+ * Copyright 2018 Philippe Proulx <pproulx@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#define BT_LOG_TAG "FIELD-WRAPPER"
+#include <babeltrace/lib-logging-internal.h>
+
+#include <babeltrace/ctf-ir/field-wrapper-internal.h>
+#include <babeltrace/ctf-ir/fields-internal.h>
+#include <babeltrace/object-pool-internal.h>
+#include <babeltrace/object-internal.h>
+#include <glib.h>
+
+BT_HIDDEN
+struct bt_field_wrapper *bt_field_wrapper_new(void *data)
+{
+ struct bt_field_wrapper *field_wrapper =
+ g_new0(struct bt_field_wrapper, 1);
+
+ BT_LOGD_STR("Creating empty field wrapper object.");
+
+ if (!field_wrapper) {
+ BT_LOGE("Failed to allocate one field wrapper.");
+ goto end;
+ }
+
+ bt_object_init(field_wrapper, NULL);
+ bt_object_set_is_shared((void *) field_wrapper, false);
+ BT_LOGD("Created empty field wrapper object: addr=%p",
+ field_wrapper);
+
+end:
+ return field_wrapper;
+}
+
+BT_HIDDEN
+void bt_field_wrapper_destroy(struct bt_field_wrapper *field_wrapper)
+{
+ BT_LOGD("Destroying field wrapper: addr=%p", field_wrapper);
+
+ if (field_wrapper->field) {
+ BT_LOGD_STR("Destroying field.");
+ bt_field_destroy_recursive((void *) field_wrapper->field);
+ }
+
+ BT_LOGD_STR("Putting stream class.");
+ g_free(field_wrapper);
+}
+
+BT_HIDDEN
+struct bt_field_wrapper *bt_field_wrapper_create(
+ struct bt_object_pool *pool, struct bt_field_type *ft)
+{
+ struct bt_field_wrapper *field_wrapper = NULL;
+
+ BT_ASSERT(pool);
+ BT_ASSERT(ft);
+ field_wrapper = bt_object_pool_create_object(pool);
+ if (!field_wrapper) {
+ BT_LIB_LOGE("Cannot allocate one field wrapper from field wrapper pool: "
+ "%![pool-]+o", pool);
+ goto error;
+ }
+
+ if (!field_wrapper->field) {
+ field_wrapper->field = (void *) bt_field_create_recursive(ft);
+ if (!field_wrapper->field) {
+ BT_LIB_LOGE("Cannot create field wrapper from field type: "
+ "%![ft-]+F", ft);
+ goto error;
+ }
+
+ BT_LIB_LOGD("Created initial field wrapper object: "
+ "wrapper-addr=%p, %![field-]+f", field_wrapper,
+ field_wrapper->field);
+ }
+
+ goto end;
+
+error:
+ if (field_wrapper) {
+ bt_field_wrapper_destroy(field_wrapper);
+ field_wrapper = NULL;
+ }
+
+end:
+ return field_wrapper;
+}
#include <babeltrace/assert-internal.h>
#include <inttypes.h>
-static
-struct bt_field_common *bt_field_integer_copy(struct bt_field_common *src);
-
-static
-struct bt_field_common *bt_field_enumeration_copy_recursive(
- struct bt_field_common *src);
-
-static
-struct bt_field_common *bt_field_floating_point_copy(
- struct bt_field_common *src);
-
-static
-struct bt_field_common *bt_field_structure_copy_recursive(
- struct bt_field_common *src);
-
-static
-struct bt_field_common *bt_field_variant_copy_recursive(
- struct bt_field_common *src);
-
-static
-struct bt_field_common *bt_field_array_copy_recursive(
- struct bt_field_common *src);
-
-static
-struct bt_field_common *bt_field_sequence_copy_recursive(
- struct bt_field_common *src);
-
-static
-struct bt_field_common *bt_field_string_copy(struct bt_field_common *src);
+#define BT_ASSERT_PRE_FIELD_IS_INT_OR_ENUM(_field, _name) \
+ BT_ASSERT_PRE((_field)->type->id == BT_FIELD_TYPE_ID_INTEGER || \
+ (_field)->type->id == BT_FIELD_TYPE_ID_ENUM, \
+ _name " is not an integer or an enumeration field: " \
+ "%!+f", (_field))
static struct bt_field_common_methods bt_field_integer_methods = {
- .freeze = bt_field_common_generic_freeze,
+ .set_is_frozen = bt_field_common_generic_set_is_frozen,
.validate = bt_field_common_generic_validate,
- .copy = bt_field_integer_copy,
+ .copy = NULL,
.is_set = bt_field_common_generic_is_set,
.reset = bt_field_common_generic_reset,
};
static struct bt_field_common_methods bt_field_floating_point_methods = {
- .freeze = bt_field_common_generic_freeze,
+ .set_is_frozen = bt_field_common_generic_set_is_frozen,
.validate = bt_field_common_generic_validate,
- .copy = bt_field_floating_point_copy,
+ .copy = NULL,
.is_set = bt_field_common_generic_is_set,
.reset = bt_field_common_generic_reset,
};
static struct bt_field_common_methods bt_field_enumeration_methods = {
- .freeze = bt_field_common_enumeration_freeze_recursive,
- .validate = bt_field_common_enumeration_validate_recursive,
- .copy = bt_field_enumeration_copy_recursive,
- .is_set = bt_field_common_enumeration_is_set_recursive,
- .reset = bt_field_common_enumeration_reset_recursive,
+ .set_is_frozen = bt_field_common_generic_set_is_frozen,
+ .validate = bt_field_common_generic_validate,
+ .copy = NULL,
+ .is_set = bt_field_common_generic_is_set,
+ .reset = bt_field_common_generic_reset,
};
static struct bt_field_common_methods bt_field_string_methods = {
- .freeze = bt_field_common_generic_freeze,
+ .set_is_frozen = bt_field_common_generic_set_is_frozen,
.validate = bt_field_common_generic_validate,
- .copy = bt_field_string_copy,
+ .copy = NULL,
.is_set = bt_field_common_generic_is_set,
.reset = bt_field_common_string_reset,
};
static struct bt_field_common_methods bt_field_structure_methods = {
- .freeze = bt_field_common_structure_freeze_recursive,
+ .set_is_frozen = bt_field_common_structure_set_is_frozen_recursive,
.validate = bt_field_common_structure_validate_recursive,
- .copy = bt_field_structure_copy_recursive,
+ .copy = NULL,
.is_set = bt_field_common_structure_is_set_recursive,
.reset = bt_field_common_structure_reset_recursive,
};
static struct bt_field_common_methods bt_field_sequence_methods = {
- .freeze = bt_field_common_sequence_freeze_recursive,
+ .set_is_frozen = bt_field_common_sequence_set_is_frozen_recursive,
.validate = bt_field_common_sequence_validate_recursive,
- .copy = bt_field_sequence_copy_recursive,
+ .copy = NULL,
.is_set = bt_field_common_sequence_is_set_recursive,
.reset = bt_field_common_sequence_reset_recursive,
};
static struct bt_field_common_methods bt_field_array_methods = {
- .freeze = bt_field_common_array_freeze_recursive,
+ .set_is_frozen = bt_field_common_array_set_is_frozen_recursive,
.validate = bt_field_common_array_validate_recursive,
- .copy = bt_field_array_copy_recursive,
+ .copy = NULL,
.is_set = bt_field_common_array_is_set_recursive,
.reset = bt_field_common_array_reset_recursive,
};
static struct bt_field_common_methods bt_field_variant_methods = {
- .freeze = bt_field_common_variant_freeze_recursive,
+ .set_is_frozen = bt_field_common_variant_set_is_frozen_recursive,
.validate = bt_field_common_variant_validate_recursive,
- .copy = bt_field_variant_copy_recursive,
+ .copy = NULL,
.is_set = bt_field_common_variant_is_set_recursive,
.reset = bt_field_common_variant_reset_recursive,
};
[BT_FIELD_TYPE_ID_STRING] = bt_field_string_create,
};
-struct bt_field *bt_field_create(struct bt_field_type *type)
+static
+void bt_field_integer_destroy(struct bt_field *field);
+
+static
+void bt_field_enumeration_destroy(struct bt_field *field);
+
+static
+void bt_field_floating_point_destroy(struct bt_field *field);
+
+static
+void bt_field_structure_destroy_recursive(struct bt_field *field);
+
+static
+void bt_field_variant_destroy_recursive(struct bt_field *field);
+
+static
+void bt_field_array_destroy_recursive(struct bt_field *field);
+
+static
+void bt_field_sequence_destroy_recursive(struct bt_field *field);
+
+static
+void bt_field_string_destroy(struct bt_field *field);
+
+static
+void (* const field_destroy_funcs[])(struct bt_field *) = {
+ [BT_FIELD_TYPE_ID_INTEGER] = bt_field_integer_destroy,
+ [BT_FIELD_TYPE_ID_ENUM] = bt_field_enumeration_destroy,
+ [BT_FIELD_TYPE_ID_FLOAT] = bt_field_floating_point_destroy,
+ [BT_FIELD_TYPE_ID_STRUCT] = bt_field_structure_destroy_recursive,
+ [BT_FIELD_TYPE_ID_VARIANT] = bt_field_variant_destroy_recursive,
+ [BT_FIELD_TYPE_ID_ARRAY] = bt_field_array_destroy_recursive,
+ [BT_FIELD_TYPE_ID_SEQUENCE] = bt_field_sequence_destroy_recursive,
+ [BT_FIELD_TYPE_ID_STRING] = bt_field_string_destroy,
+};
+
+BT_HIDDEN
+struct bt_field *bt_field_create_recursive(struct bt_field_type *type)
{
struct bt_field *field = NULL;
enum bt_field_type_id type_id;
goto end;
}
+ bt_object_set_is_shared((void *) field, false);
bt_field_type_freeze(type);
end:
return bt_field_get_type_id(field) == BT_FIELD_TYPE_ID_VARIANT;
}
-BT_HIDDEN
-int64_t bt_field_sequence_get_int_length(struct bt_field *field)
+int64_t bt_field_sequence_get_length(struct bt_field *field)
{
- return bt_field_common_sequence_get_int_length((void *) field);
+ return bt_field_common_sequence_get_length((void *) field);
}
-struct bt_field *bt_field_sequence_borrow_length(struct bt_field *field)
-{
- return (void *) bt_field_common_sequence_borrow_length((void *) field);
-}
-
-int bt_field_sequence_set_length(struct bt_field *field,
- struct bt_field *length_field)
+int bt_field_sequence_set_length(struct bt_field *field, uint64_t length)
{
return bt_field_common_sequence_set_length((void *) field,
- (void *) length_field);
+ length, (bt_field_common_create_func) bt_field_create_recursive);
}
struct bt_field *bt_field_structure_borrow_field_by_index(
(void *) field, name);
}
-int bt_field_structure_set_field_by_name(struct bt_field_common *field,
- const char *name, struct bt_field_common *value)
-{
- return bt_field_common_structure_set_field_by_name((void *) field,
- name, (void *) value);
-}
-
struct bt_field *bt_field_array_borrow_field(
struct bt_field *field, uint64_t index)
{
return (void *) bt_field_common_array_borrow_field((void *) field,
- index, (bt_field_common_create_func) bt_field_create);
+ index);
}
struct bt_field *bt_field_sequence_borrow_field(
struct bt_field *field, uint64_t index)
{
return (void *) bt_field_common_sequence_borrow_field((void *) field,
- index, (bt_field_common_create_func) bt_field_create);
-}
-
-struct bt_field *bt_field_variant_borrow_field(struct bt_field *field,
- struct bt_field *tag_field)
-{
- return (void *) bt_field_common_variant_borrow_field((void *) field,
- (void *) tag_field,
- (bt_field_common_create_func) bt_field_create);
+ index);
}
struct bt_field *bt_field_variant_borrow_current_field(
(void *) variant_field);
}
-struct bt_field_common *bt_field_variant_borrow_tag(
- struct bt_field_common *variant_field)
+int bt_field_variant_set_tag_signed(struct bt_field *variant_field,
+ int64_t tag)
{
- return (void *) bt_field_common_variant_borrow_tag(
- (void *) variant_field);
+ return bt_field_variant_common_set_tag((void *) variant_field,
+ (uint64_t) tag, true);
+}
+
+int bt_field_variant_set_tag_unsigned(struct bt_field *variant_field,
+ uint64_t tag)
+{
+ return bt_field_variant_common_set_tag((void *) variant_field,
+ (uint64_t) tag, false);
}
-struct bt_field *bt_field_enumeration_borrow_container(struct bt_field *field)
+int bt_field_variant_get_tag_signed(struct bt_field *variant_field,
+ int64_t *tag)
{
- return (void *) bt_field_common_enumeration_borrow_container(
- (void *) field, (bt_field_common_create_func) bt_field_create);
+ return bt_field_common_variant_get_tag_signed((void *) variant_field, tag);
+}
+
+int bt_field_variant_get_tag_unsigned(struct bt_field *variant_field,
+ uint64_t *tag)
+{
+ return bt_field_common_variant_get_tag_unsigned((void *) variant_field, tag);
}
struct bt_field_type_enumeration_mapping_iterator *
bt_field_enumeration_get_mappings(struct bt_field *field)
{
+ struct bt_field_enumeration *enum_field = (void *) field;
+
+ BT_ASSERT_PRE_NON_NULL(field, "Enumeration field");
+ BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID((struct bt_field_common *) field,
+ BT_FIELD_TYPE_ID_ENUM, "Field");
+ BT_ASSERT_PRE_FIELD_COMMON_IS_SET((struct bt_field_common *) field,
+ "Enumeration field");
return bt_field_common_enumeration_get_mappings((void *) field,
- (bt_field_common_create_func) bt_field_create);
+ (bt_field_common_create_func) bt_field_create_recursive,
+ enum_field->common.payload.unsignd);
+}
+
+BT_ASSERT_PRE_FUNC
+static inline
+struct bt_field_type_common_integer *get_int_enum_int_ft(
+ struct bt_field *field)
+{
+ struct bt_field_common_integer *int_field = (void *) field;
+ struct bt_field_type_common_integer *int_ft = NULL;
+
+ if (int_field->common.type->id == BT_FIELD_TYPE_ID_INTEGER) {
+ int_ft = BT_FROM_COMMON(int_field->common.type);
+ } else if (int_field->common.type->id == BT_FIELD_TYPE_ID_ENUM) {
+ struct bt_field_type_common_enumeration *enum_ft =
+ BT_FROM_COMMON(int_field->common.type);
+ int_ft = enum_ft->container_ft;
+ }
+
+ BT_ASSERT(int_ft);
+ return int_ft;
}
int bt_field_integer_signed_get_value(struct bt_field *field, int64_t *value)
{
- return bt_field_common_integer_signed_get_value((void *) field, value);
+ struct bt_field_common_integer *integer = (void *) field;
+
+ BT_ASSERT_PRE_NON_NULL(field, "Integer/enumeration field");
+ BT_ASSERT_PRE_NON_NULL(value, "Value");
+ BT_ASSERT_PRE_FIELD_COMMON_IS_SET(BT_TO_COMMON(integer),
+ "Integer/enumeration field");
+ BT_ASSERT_PRE_FIELD_IS_INT_OR_ENUM(BT_TO_COMMON(integer), "Field");
+ BT_ASSERT_PRE(bt_field_type_common_integer_is_signed(
+ BT_TO_COMMON(get_int_enum_int_ft(field))),
+ "Field's type is unsigned: %!+f", field);
+ *value = integer->payload.signd;
+ return 0;
}
-int bt_field_integer_signed_set_value(struct bt_field *field,
- int64_t value)
+int bt_field_integer_signed_set_value(struct bt_field *field, int64_t value)
{
- return bt_field_common_integer_signed_set_value((void *) field, value);
+ int ret = 0;
+ struct bt_field_common_integer *integer = (void *) field;
+
+ BT_ASSERT_PRE_NON_NULL(field, "Integer field");
+ BT_ASSERT_PRE_FIELD_COMMON_HOT(BT_TO_COMMON(integer), "Integer field");
+ BT_ASSERT_PRE_FIELD_IS_INT_OR_ENUM(BT_TO_COMMON(integer), "Field");
+ BT_ASSERT_PRE(bt_field_type_common_integer_is_signed(
+ BT_FROM_COMMON(get_int_enum_int_ft(field))),
+ "Field's type is unsigned: %!+f", field);
+ BT_ASSERT_PRE(value_is_in_range_signed(
+ get_int_enum_int_ft(field)->size, value),
+ "Value is out of bounds: value=%" PRId64 ", %![field-]+f",
+ value, field);
+ integer->payload.signd = value;
+ bt_field_set(field, true);
+ return ret;
}
-int bt_field_integer_unsigned_get_value(struct bt_field *field,
- uint64_t *value)
+int bt_field_integer_unsigned_get_value(struct bt_field *field, uint64_t *value)
{
- return bt_field_common_integer_unsigned_get_value((void *) field,
- value);
+ struct bt_field_common_integer *integer = (void *) field;
+
+ BT_ASSERT_PRE_NON_NULL(field, "Integer field");
+ BT_ASSERT_PRE_NON_NULL(value, "Value");
+ BT_ASSERT_PRE_FIELD_COMMON_IS_SET(BT_TO_COMMON(integer), "Integer field");
+ BT_ASSERT_PRE_FIELD_IS_INT_OR_ENUM(BT_TO_COMMON(integer), "Field");
+ BT_ASSERT_PRE(!bt_field_type_common_integer_is_signed(
+ BT_FROM_COMMON(get_int_enum_int_ft(field))),
+ "Field's type is signed: %!+f", field);
+ *value = integer->payload.unsignd;
+ return 0;
}
-int bt_field_integer_unsigned_set_value(struct bt_field *field, uint64_t value)
+int bt_field_integer_unsigned_set_value(struct bt_field *field,
+ uint64_t value)
{
- return bt_field_common_integer_unsigned_set_value((void *) field, value);
+ struct bt_field_common_integer *integer = (void *) field;
+
+ BT_ASSERT_PRE_NON_NULL(field, "Integer field");
+ BT_ASSERT_PRE_FIELD_COMMON_HOT(BT_TO_COMMON(integer), "Integer field");
+ BT_ASSERT_PRE_FIELD_IS_INT_OR_ENUM(BT_TO_COMMON(integer), "Field");
+ BT_ASSERT_PRE(!bt_field_type_common_integer_is_signed(
+ BT_FROM_COMMON(get_int_enum_int_ft(field))),
+ "Field's type is signed: %!+f", field);
+ BT_ASSERT_PRE(value_is_in_range_unsigned(
+ get_int_enum_int_ft(field)->size, value),
+ "Value is out of bounds: value=%" PRIu64 ", %![field-]+f",
+ value, field);
+ integer->payload.unsignd = value;
+ bt_field_set(field, true);
+ return 0;
}
int bt_field_floating_point_get_value(struct bt_field *field,
return bt_field_common_string_append_len((void *) field, value, length);
}
+int bt_field_string_clear(struct bt_field *string_field)
+{
+ return bt_field_common_string_clear((void *) string_field);
+}
+
BT_HIDDEN
struct bt_field_common *bt_field_common_copy(struct bt_field_common *field)
{
return copy;
}
-struct bt_field *bt_field_copy(struct bt_field *field)
-{
- return (void *) bt_field_common_copy((void *) field);
-}
-
-static void bt_field_common_finalize(struct bt_field_common *field)
+static
+void bt_field_integer_destroy(struct bt_field *field)
{
- BT_ASSERT(field);
- BT_LOGD_STR("Putting field's type.");
- bt_put(field->type);
+ BT_LOGD("Destroying integer field object: addr=%p", field);
+ bt_field_common_integer_finalize((void *) field);
+ g_free(field);
}
-BT_HIDDEN
-void bt_field_common_integer_destroy(struct bt_object *obj)
+static
+void bt_field_floating_point_destroy(struct bt_field *field)
{
- struct bt_field_common_integer *integer = (void *) obj;
-
- BT_ASSERT(obj);
- bt_field_common_finalize(BT_TO_COMMON(integer));
- BT_LOGD("Destroying integer field object: addr=%p", obj);
- g_free(obj);
+ BT_LOGD("Destroying floating point field object: addr=%p", field);
+ bt_field_common_floating_point_finalize((void *) field);
+ g_free(field);
}
-BT_HIDDEN
-void bt_field_common_enumeration_destroy_recursive(struct bt_object *obj)
+static
+void bt_field_enumeration_destroy(struct bt_field *field)
{
- struct bt_field_common_enumeration *enumeration = (void *) obj;
-
- BT_ASSERT(enumeration);
- bt_field_common_finalize(BT_TO_COMMON(enumeration));
- BT_LOGD("Destroying enumeration field object: addr=%p", obj);
- BT_LOGD_STR("Putting payload field.");
- bt_put(enumeration->payload);
- g_free(enumeration);
+ BT_LOGD("Destroying enumeration field object: addr=%p", field);
+ bt_field_common_finalize((void *) field);
+ g_free(field);
}
-BT_HIDDEN
-void bt_field_common_floating_point_destroy(struct bt_object *obj)
+static
+void bt_field_structure_destroy_recursive(struct bt_field *field)
{
- struct bt_field_common_floating_point *floating_point = (void *) obj;
-
- BT_ASSERT(obj);
- bt_field_common_finalize(BT_TO_COMMON(floating_point));
- BT_LOGD("Destroying floating point number field object: addr=%p", obj);
- g_free(obj);
+ BT_LOGD("Destroying structure field object: addr=%p", field);
+ bt_field_common_structure_finalize_recursive((void *) field);
+ g_free(field);
}
-BT_HIDDEN
-void bt_field_common_structure_destroy_recursive(struct bt_object *obj)
+static
+void bt_field_variant_destroy_recursive(struct bt_field *field)
{
- struct bt_field_common_structure *structure = (void *) obj;
-
- BT_ASSERT(obj);
- bt_field_common_finalize(BT_TO_COMMON(structure));
- BT_LOGD("Destroying structure field object: addr=%p", obj);
- g_ptr_array_free(structure->fields, TRUE);
- g_free(structure);
+ BT_LOGD("Destroying variant field object: addr=%p", field);
+ bt_field_common_variant_finalize_recursive((void *) field);
+ g_free(field);
}
-BT_HIDDEN
-void bt_field_common_variant_destroy_recursive(struct bt_object *obj)
+static
+void bt_field_array_destroy_recursive(struct bt_field *field)
{
- struct bt_field_common_variant *variant = (void *) obj;
-
- BT_ASSERT(obj);
- bt_field_common_finalize(BT_TO_COMMON(variant));
- BT_LOGD("Destroying variant field object: addr=%p", obj);
- BT_LOGD_STR("Putting tag field.");
- bt_put(variant->tag);
- BT_LOGD_STR("Putting payload field.");
- bt_put(variant->payload);
- g_free(variant);
+ BT_LOGD("Destroying array field object: addr=%p", field);
+ bt_field_common_array_finalize_recursive((void *) field);
+ g_free(field);
}
-BT_HIDDEN
-void bt_field_common_array_destroy_recursive(struct bt_object *obj)
+static
+void bt_field_sequence_destroy_recursive(struct bt_field *field)
{
- struct bt_field_common_array *array = (void *) obj;
-
- BT_ASSERT(obj);
- bt_field_common_finalize(BT_TO_COMMON(array));
- BT_LOGD("Destroying array field object: addr=%p", obj);
- g_ptr_array_free(array->elements, TRUE);
- g_free(array);
+ BT_LOGD("Destroying sequence field object: addr=%p", field);
+ bt_field_common_sequence_finalize_recursive((void *) field);
+ g_free(field);
}
-BT_HIDDEN
-void bt_field_common_sequence_destroy_recursive(struct bt_object *obj)
+static
+void bt_field_string_destroy(struct bt_field *field)
{
- struct bt_field_common_sequence *sequence = (void *) obj;
-
- BT_ASSERT(obj);
- bt_field_common_finalize(BT_TO_COMMON(sequence));
- BT_LOGD("Destroying sequence field object: addr=%p", obj);
-
- if (sequence->elements) {
- g_ptr_array_free(sequence->elements, TRUE);
- }
-
- BT_LOGD_STR("Putting length field.");
- bt_put(sequence->length);
- g_free(sequence);
+ BT_LOGD("Destroying string field object: addr=%p", field);
+ bt_field_common_string_finalize((void *) field);
+ g_free(field);
}
BT_HIDDEN
-void bt_field_common_string_destroy(struct bt_object *obj)
+void bt_field_destroy_recursive(struct bt_field *field)
{
- struct bt_field_common_string *string = (void *) obj;
-
- BT_ASSERT(obj);
- bt_field_common_finalize(BT_TO_COMMON(string));
- BT_LOGD("Destroying string field object: addr=%p", obj);
+ struct bt_field_common *field_common = (void *) field;
- if (string->payload) {
- g_string_free(string->payload, TRUE);
+ if (!field) {
+ return;
}
- g_free(string);
+ BT_ASSERT(field_type_common_has_known_id((void *) field_common->type));
+ field_destroy_funcs[field_common->type->id](field);
}
static
if (integer) {
bt_field_common_initialize(BT_TO_COMMON(integer), (void *) type,
- bt_field_common_integer_destroy,
- &bt_field_integer_methods);
+ NULL, &bt_field_integer_methods);
BT_LOGD("Created integer field object: addr=%p, ft-addr=%p",
integer, type);
} else {
static
struct bt_field *bt_field_enumeration_create(struct bt_field_type *type)
{
- struct bt_field_common_enumeration *enumeration = g_new0(
- struct bt_field_common_enumeration, 1);
+ struct bt_field_enumeration *enumeration = g_new0(
+ struct bt_field_enumeration, 1);
BT_LOGD("Creating enumeration field object: ft-addr=%p", type);
if (enumeration) {
- bt_field_common_initialize(BT_TO_COMMON(enumeration),
- (void *) type,
- bt_field_common_enumeration_destroy_recursive,
- &bt_field_enumeration_methods);
+ bt_field_common_initialize(
+ BT_TO_COMMON(BT_TO_COMMON(enumeration)),
+ (void *) type, NULL, &bt_field_enumeration_methods);
BT_LOGD("Created enumeration field object: addr=%p, ft-addr=%p",
enumeration, type);
} else {
if (floating_point) {
bt_field_common_initialize(BT_TO_COMMON(floating_point),
- (void *) type,
- bt_field_common_floating_point_destroy,
- &bt_field_floating_point_methods);
+ (void *) type, NULL, &bt_field_floating_point_methods);
BT_LOGD("Created floating point number field object: addr=%p, ft-addr=%p",
floating_point, type);
} else {
struct bt_field_type_common *type,
bt_object_release_func release_func,
struct bt_field_common_methods *methods,
- bt_field_common_create_func field_create_func)
+ bt_field_common_create_func field_create_func,
+ GDestroyNotify field_release_func)
{
int ret = 0;
struct bt_field_type_common_structure *structure_type =
BT_LOGD("Initializing common structure field object: ft-addr=%p", type);
bt_field_common_initialize(field, type, release_func, methods);
- structure->fields = g_ptr_array_new_with_free_func(
- (GDestroyNotify) bt_put);
+ structure->fields = g_ptr_array_new_with_free_func(field_release_func);
g_ptr_array_set_size(structure->fields, structure_type->fields->len);
- /* Create all fields contained by the structure field. */
+ /* Create all fields contained in the structure field. */
for (i = 0; i < structure_type->fields->len; i++) {
struct bt_field_common *field;
- struct structure_field_common *struct_field =
- g_ptr_array_index(structure_type->fields, i);
-
+ struct bt_field_type_common_structure_field *struct_field =
+ BT_FIELD_TYPE_COMMON_STRUCTURE_FIELD_AT_INDEX(
+ structure_type, i);
field = field_create_func(struct_field->type);
if (!field) {
BT_LOGE("Failed to create structure field's member: name=\"%s\", index=%zu",
}
iret = bt_field_common_structure_initialize(BT_TO_COMMON(structure),
- (void *) type, bt_field_common_structure_destroy_recursive,
- &bt_field_structure_methods,
- (bt_field_common_create_func) bt_field_create);
+ (void *) type, NULL, &bt_field_structure_methods,
+ (bt_field_common_create_func) bt_field_create_recursive,
+ (GDestroyNotify) bt_field_destroy_recursive);
if (iret) {
BT_PUT(structure);
goto end;
return (void *) structure;
}
+BT_HIDDEN
+int bt_field_common_variant_initialize(struct bt_field_common *field,
+ struct bt_field_type_common *type,
+ bt_object_release_func release_func,
+ struct bt_field_common_methods *methods,
+ bt_field_common_create_func field_create_func,
+ GDestroyNotify field_release_func)
+{
+ int ret = 0;
+ struct bt_field_type_common_variant *variant_type =
+ BT_FROM_COMMON(type);
+ struct bt_field_common_variant *variant = BT_FROM_COMMON(field);
+ size_t i;
+
+ BT_LOGD("Initializing common variant field object: ft-addr=%p", type);
+ bt_field_common_initialize(field, type, release_func, methods);
+ ret = bt_field_type_common_variant_update_choices(type);
+ if (ret) {
+ BT_LOGE("Cannot update common variant field type choices: "
+ "ret=%d", ret);
+ goto end;
+ }
+
+ variant->fields = g_ptr_array_new_with_free_func(field_release_func);
+ g_ptr_array_set_size(variant->fields, variant_type->choices->len);
+
+ /* Create all fields contained in the variant field. */
+ for (i = 0; i < variant_type->choices->len; i++) {
+ struct bt_field_common *field;
+ struct bt_field_type_common_variant_choice *var_choice =
+ BT_FIELD_TYPE_COMMON_VARIANT_CHOICE_AT_INDEX(
+ variant_type, i);
+
+ field = field_create_func(var_choice->type);
+ if (!field) {
+ BT_LOGE("Failed to create variant field's member: name=\"%s\", index=%zu",
+ g_quark_to_string(var_choice->name), i);
+ ret = -1;
+ goto end;
+ }
+
+ g_ptr_array_index(variant->fields, i) = field;
+ }
+
+ BT_LOGD("Initialized common variant field object: addr=%p, ft-addr=%p",
+ field, type);
+
+end:
+ return ret;
+}
+
static
struct bt_field *bt_field_variant_create(struct bt_field_type *type)
{
struct bt_field_common_variant *variant = g_new0(
struct bt_field_common_variant, 1);
+ int iret;
BT_LOGD("Creating variant field object: ft-addr=%p", type);
- if (variant) {
- bt_field_common_initialize(BT_TO_COMMON(variant),
- (void *) type,
- bt_field_common_variant_destroy_recursive,
- &bt_field_variant_methods);
- BT_LOGD("Created variant field object: addr=%p, ft-addr=%p",
- variant, type);
- } else {
+ if (!variant) {
BT_LOGE_STR("Failed to allocate one variant field.");
+ goto end;
+ }
+
+ iret = bt_field_common_variant_initialize(BT_TO_COMMON(variant),
+ (void *) type, NULL, &bt_field_variant_methods,
+ (bt_field_common_create_func) bt_field_create_recursive,
+ (GDestroyNotify) bt_field_destroy_recursive);
+ if (iret) {
+ BT_PUT(variant);
+ goto end;
}
+ BT_LOGD("Created variant field object: addr=%p, ft-addr=%p",
+ variant, type);
+
+end:
return (void *) variant;
}
int bt_field_common_array_initialize(struct bt_field_common *field,
struct bt_field_type_common *type,
bt_object_release_func release_func,
- struct bt_field_common_methods *methods)
+ struct bt_field_common_methods *methods,
+ bt_field_common_create_func field_create_func,
+ GDestroyNotify field_destroy_func)
{
struct bt_field_type_common_array *array_type = BT_FROM_COMMON(type);
struct bt_field_common_array *array = BT_FROM_COMMON(field);
unsigned int array_length;
int ret = 0;
+ uint64_t i;
BT_LOGD("Initializing common array field object: ft-addr=%p", type);
BT_ASSERT(type);
goto end;
}
- g_ptr_array_set_free_func(array->elements, (GDestroyNotify) bt_put);
+ g_ptr_array_set_free_func(array->elements, field_destroy_func);
g_ptr_array_set_size(array->elements, array_length);
+
+ for (i = 0; i < array_length; i++) {
+ array->elements->pdata[i] = field_create_func(
+ array_type->element_ft);
+ if (!array->elements->pdata[i]) {
+ ret = -1;
+ goto end;
+ }
+ }
+
BT_LOGD("Initialized common array field object: addr=%p, ft-addr=%p",
field, type);
}
ret = bt_field_common_array_initialize(BT_TO_COMMON(array),
- (void *) type,
- bt_field_common_array_destroy_recursive,
- &bt_field_array_methods);
+ (void *) type, NULL, &bt_field_array_methods,
+ (bt_field_common_create_func) bt_field_create_recursive,
+ (GDestroyNotify) bt_field_destroy_recursive);
if (ret) {
BT_PUT(array);
goto end;
return (void *) array;
}
+BT_HIDDEN
+int bt_field_common_sequence_initialize(struct bt_field_common *field,
+ struct bt_field_type_common *type,
+ bt_object_release_func release_func,
+ struct bt_field_common_methods *methods,
+ GDestroyNotify field_destroy_func)
+{
+ struct bt_field_common_sequence *sequence = BT_FROM_COMMON(field);
+ int ret = 0;
+
+ BT_LOGD("Initializing common sequence field object: ft-addr=%p", type);
+ BT_ASSERT(type);
+ bt_field_common_initialize(field, type, release_func, methods);
+ sequence->elements = g_ptr_array_new();
+ if (!sequence->elements) {
+ ret = -1;
+ goto end;
+ }
+
+ g_ptr_array_set_free_func(sequence->elements, field_destroy_func);
+ BT_LOGD("Initialized common sequence field object: addr=%p, ft-addr=%p",
+ field, type);
+
+end:
+ return ret;
+}
+
static
struct bt_field *bt_field_sequence_create(struct bt_field_type *type)
{
- struct bt_field_common_sequence *sequence = g_new0(
- struct bt_field_common_sequence, 1);
+ struct bt_field_common_sequence *sequence =
+ g_new0(struct bt_field_common_sequence, 1);
+ int ret;
BT_LOGD("Creating sequence field object: ft-addr=%p", type);
+ BT_ASSERT(type);
- if (sequence) {
- bt_field_common_initialize(BT_TO_COMMON(sequence),
- (void *) type,
- bt_field_common_sequence_destroy_recursive,
- &bt_field_sequence_methods);
- BT_LOGD("Created sequence field object: addr=%p, ft-addr=%p",
- sequence, type);
- } else {
+ if (!sequence) {
BT_LOGE_STR("Failed to allocate one sequence field.");
+ goto end;
}
+ ret = bt_field_common_sequence_initialize(BT_TO_COMMON(sequence),
+ (void *) type, NULL, &bt_field_sequence_methods,
+ (GDestroyNotify) bt_field_destroy_recursive);
+ if (ret) {
+ BT_PUT(sequence);
+ goto end;
+ }
+
+ BT_LOGD("Created sequence field object: addr=%p, ft-addr=%p",
+ sequence, type);
+
+end:
return (void *) sequence;
}
if (string) {
bt_field_common_initialize(BT_TO_COMMON(string),
- (void *) type,
- bt_field_common_string_destroy,
- &bt_field_string_methods);
+ (void *) type, NULL, &bt_field_string_methods);
BT_LOGD("Created string field object: addr=%p, ft-addr=%p",
string, type);
} else {
return (field && field->payload_set) ? 0 : -1;
}
-BT_HIDDEN
-int bt_field_common_enumeration_validate_recursive(
- struct bt_field_common *field)
-{
- int ret;
- struct bt_field_common_enumeration *enumeration = BT_FROM_COMMON(field);
-
- BT_ASSERT(field);
-
- if (!enumeration->payload) {
- BT_ASSERT_PRE_MSG("Invalid enumeration field: payload is not set: "
- "%!+_f", field);
- ret = -1;
- goto end;
- }
-
- ret = bt_field_common_validate_recursive(enumeration->payload);
-
-end:
- return ret;
-}
-
BT_HIDDEN
int bt_field_common_structure_validate_recursive(struct bt_field_common *field)
{
struct bt_field_common_variant *variant = BT_FROM_COMMON(field);
BT_ASSERT(field);
- ret = bt_field_common_validate_recursive(variant->payload);
- if (ret) {
- BT_ASSERT_PRE_MSG("Invalid variant field's payload field: "
- "%![variant-field-]+_f, %![payload-field-]+_f",
- field, variant->payload);
+
+ if (!variant->current_field) {
+ ret = -1;
+ goto end;
}
+ ret = bt_field_common_validate_recursive(variant->current_field);
+
+end:
return ret;
}
field->payload_set = false;
}
-BT_HIDDEN
-void bt_field_common_enumeration_reset_recursive(struct bt_field_common *field)
-{
- struct bt_field_common_enumeration *enumeration = BT_FROM_COMMON(field);
-
- BT_ASSERT(field);
-
- if (!enumeration->payload) {
- return;
- }
-
- bt_field_common_reset_recursive(enumeration->payload);
-}
-
BT_HIDDEN
void bt_field_common_structure_reset_recursive(struct bt_field_common *field)
{
struct bt_field_common_variant *variant = BT_FROM_COMMON(field);
BT_ASSERT(field);
- BT_PUT(variant->tag);
- BT_PUT(variant->payload);
+ variant->current_field = NULL;
}
BT_HIDDEN
void bt_field_common_sequence_reset_recursive(struct bt_field_common *field)
{
struct bt_field_common_sequence *sequence = BT_FROM_COMMON(field);
+ uint64_t i;
BT_ASSERT(field);
- if (sequence->elements) {
- g_ptr_array_free(sequence->elements, TRUE);
- sequence->elements = NULL;
+ for (i = 0; i < sequence->elements->len; i++) {
+ if (sequence->elements->pdata[i]) {
+ bt_field_common_reset_recursive(
+ sequence->elements->pdata[i]);
+ }
}
- BT_PUT(sequence->length);
+ sequence->length = 0;
}
BT_HIDDEN
}
}
-static
-struct bt_field_common *bt_field_integer_copy(struct bt_field_common *src)
-{
- struct bt_field_common_integer *integer_src = (void *) src;
- struct bt_field_common_integer *integer_dst;
-
- BT_LOGD("Copying integer field: src-field-addr=%p", src);
- integer_dst = (void *) bt_field_create((void *) src->type);
- if (!integer_dst) {
- goto end;
- }
-
- integer_dst->payload = integer_src->payload;
- BT_LOGD_STR("Copied integer field.");
-
-end:
- return BT_TO_COMMON(integer_dst);
-}
-
-static
-struct bt_field_common *bt_field_enumeration_copy_recursive(
- struct bt_field_common *src)
-{
- struct bt_field_common_enumeration *enum_src = BT_FROM_COMMON(src);
- struct bt_field_common_enumeration *enum_dst;
-
- BT_LOGD("Copying enumeration field: src-field-addr=%p", src);
- enum_dst = (void *) bt_field_create((void *) src->type);
- if (!enum_dst) {
- goto error;
- }
-
- if (enum_src->payload) {
- BT_LOGD_STR("Copying enumeration field's payload field.");
- enum_dst->payload = (void *)
- bt_field_copy((void *) enum_src->payload);
- if (!enum_dst->payload) {
- BT_LOGE_STR("Cannot copy enumeration field's payload field.");
- goto error;
- }
- }
-
- BT_LOGD_STR("Copied enumeration field.");
- goto end;
-
-error:
- BT_PUT(enum_dst);
-
-end:
- return BT_TO_COMMON(enum_dst);
-}
-
-static
-struct bt_field_common *bt_field_floating_point_copy(
- struct bt_field_common *src)
-{
- struct bt_field_common_floating_point *float_src = BT_FROM_COMMON(src);
- struct bt_field_common_floating_point *float_dst;
-
- BT_LOGD("Copying floating point number field: src-field-addr=%p", src);
- float_dst = (void *) bt_field_create((void *) src->type);
- if (!float_dst) {
- goto end;
- }
-
- float_dst->payload = float_src->payload;
- BT_LOGD_STR("Copied floating point number field.");
-
-end:
- return BT_TO_COMMON(float_dst);
-}
-
-static
-struct bt_field_common *bt_field_structure_copy_recursive(
- struct bt_field_common *src)
-{
- int64_t i;
- struct bt_field_common_structure *struct_src = BT_FROM_COMMON(src);
- struct bt_field_common_structure *struct_dst;
-
- BT_LOGD("Copying structure field: src-field-addr=%p", src);
- struct_dst = (void *) bt_field_create((void *) src->type);
- if (!struct_dst) {
- goto error;
- }
-
- g_ptr_array_set_size(struct_dst->fields, struct_src->fields->len);
-
- for (i = 0; i < struct_src->fields->len; i++) {
- struct bt_field_common *field =
- g_ptr_array_index(struct_src->fields, i);
- struct bt_field_common *field_copy = NULL;
-
- if (field) {
- BT_LOGD("Copying structure field's field: src-field-addr=%p"
- "index=%" PRId64, field, i);
- field_copy = (void *) bt_field_copy((void *) field);
- if (!field_copy) {
- BT_LOGE("Cannot copy structure field's field: "
- "src-field-addr=%p, index=%" PRId64,
- field, i);
- goto error;
- }
- }
-
- BT_MOVE(g_ptr_array_index(struct_dst->fields, i), field_copy);
- }
-
- BT_LOGD_STR("Copied structure field.");
- goto end;
-
-error:
- BT_PUT(struct_dst);
-
-end:
- return BT_TO_COMMON(struct_dst);
-}
-
-static
-struct bt_field_common *bt_field_variant_copy_recursive(
- struct bt_field_common *src)
-{
- struct bt_field_common_variant *variant_src = BT_FROM_COMMON(src);
- struct bt_field_common_variant *variant_dst;
-
- BT_LOGD("Copying variant field: src-field-addr=%p", src);
- variant_dst = (void *) bt_field_create((void *) src->type);
- if (!variant_dst) {
- goto end;
- }
-
- if (variant_src->tag) {
- BT_LOGD_STR("Copying variant field's tag field.");
- variant_dst->tag = (void *) bt_field_copy(
- (void *) variant_src->tag);
- if (!variant_dst->tag) {
- BT_LOGE_STR("Cannot copy variant field's tag field.");
- goto error;
- }
- }
- if (variant_src->payload) {
- BT_LOGD_STR("Copying variant field's payload field.");
- variant_dst->payload = (void *) bt_field_copy(
- (void *) variant_src->payload);
- if (!variant_dst->payload) {
- BT_LOGE_STR("Cannot copy variant field's payload field.");
- goto error;
- }
- }
-
- BT_LOGD_STR("Copied variant field.");
- goto end;
-
-error:
- BT_PUT(variant_dst);
-
-end:
- return BT_TO_COMMON(variant_dst);
-}
-
-static
-struct bt_field_common *bt_field_array_copy_recursive(
- struct bt_field_common *src)
-{
- int64_t i;
- struct bt_field_common_array *array_src = BT_FROM_COMMON(src);
- struct bt_field_common_array *array_dst;
-
- BT_LOGD("Copying array field: src-field-addr=%p", src);
- array_dst = (void *) bt_field_create((void *) src->type);
- if (!array_dst) {
- goto error;
- }
-
- g_ptr_array_set_size(array_dst->elements, array_src->elements->len);
- for (i = 0; i < array_src->elements->len; i++) {
- struct bt_field_common *field =
- g_ptr_array_index(array_src->elements, i);
- struct bt_field_common *field_copy = NULL;
-
- if (field) {
- BT_LOGD("Copying array field's element field: field-addr=%p, "
- "index=%" PRId64, field, i);
- field_copy = (void *) bt_field_copy((void *) field);
- if (!field_copy) {
- BT_LOGE("Cannot copy array field's element field: "
- "src-field-addr=%p, index=%" PRId64,
- field, i);
- goto error;
- }
- }
-
- g_ptr_array_index(array_dst->elements, i) = field_copy;
- }
-
- BT_LOGD_STR("Copied array field.");
- goto end;
-
-error:
- BT_PUT(array_dst);
-
-end:
- return BT_TO_COMMON(array_dst);
-}
-
-static
-struct bt_field_common *bt_field_sequence_copy_recursive(
- struct bt_field_common *src)
-{
- int ret = 0;
- int64_t i;
- struct bt_field_common_sequence *sequence_src = BT_FROM_COMMON(src);
- struct bt_field_common_sequence *sequence_dst;
- struct bt_field_common *src_length;
- struct bt_field_common *dst_length;
-
- BT_LOGD("Copying sequence field: src-field-addr=%p", src);
- sequence_dst = (void *) bt_field_create((void *) src->type);
- if (!sequence_dst) {
- goto error;
- }
-
- src_length = bt_field_common_sequence_borrow_length(src);
- if (!src_length) {
- /* no length set yet: keep destination sequence empty */
- goto end;
- }
-
- /* copy source length */
- BT_LOGD_STR("Copying sequence field's length field.");
- dst_length = (void *) bt_field_copy((void *) src_length);
- if (!dst_length) {
- BT_LOGE_STR("Cannot copy sequence field's length field.");
- goto error;
- }
-
- /* this will initialize the destination sequence's internal array */
- ret = bt_field_common_sequence_set_length(
- BT_TO_COMMON(sequence_dst), dst_length);
- bt_put(dst_length);
- if (ret) {
- BT_LOGE("Cannot set sequence field copy's length field: "
- "dst-length-field-addr=%p", dst_length);
- goto error;
- }
-
- BT_ASSERT(sequence_dst->elements->len == sequence_src->elements->len);
-
- for (i = 0; i < sequence_src->elements->len; i++) {
- struct bt_field_common *field =
- g_ptr_array_index(sequence_src->elements, i);
- struct bt_field_common *field_copy = NULL;
-
- if (field) {
- BT_LOGD("Copying sequence field's element field: field-addr=%p, "
- "index=%" PRId64, field, i);
- field_copy = (void *) bt_field_copy((void *) field);
- if (!field_copy) {
- BT_LOGE("Cannot copy sequence field's element field: "
- "src-field-addr=%p, index=%" PRId64,
- field, i);
- goto error;
- }
- }
-
- g_ptr_array_index(sequence_dst->elements, i) = field_copy;
- }
-
- BT_LOGD_STR("Copied sequence field.");
- goto end;
-
-error:
- BT_PUT(sequence_dst);
-
-end:
- return BT_TO_COMMON(sequence_dst);
-}
-
-static
-struct bt_field_common *bt_field_string_copy(struct bt_field_common *src)
-{
- struct bt_field_common_string *string_src = BT_FROM_COMMON(src);
- struct bt_field_common_string *string_dst;
-
- BT_LOGD("Copying string field: src-field-addr=%p", src);
- string_dst = (void *) bt_field_create((void *) src->type);
- if (!string_dst) {
- goto error;
- }
-
- if (string_src->payload) {
- string_dst->payload = g_string_new(string_src->payload->str);
- if (!string_dst->payload) {
- BT_LOGE_STR("Failed to allocate a GString.");
- goto error;
- }
- }
-
- BT_LOGD_STR("Copied string field.");
- goto end;
-
-error:
- BT_PUT(string_dst);
-
-end:
- return BT_TO_COMMON(string_dst);
-}
-
BT_HIDDEN
-void bt_field_common_generic_freeze(struct bt_field_common *field)
+void bt_field_common_generic_set_is_frozen(struct bt_field_common *field,
+ bool is_frozen)
{
- field->frozen = true;
+ field->frozen = is_frozen;
}
BT_HIDDEN
-void bt_field_common_enumeration_freeze_recursive(struct bt_field_common *field)
+void bt_field_common_structure_set_is_frozen_recursive(
+ struct bt_field_common *field, bool is_frozen)
{
- struct bt_field_common_enumeration *enum_field = BT_FROM_COMMON(field);
-
- BT_LOGD("Freezing enumeration field object: addr=%p", field);
- BT_LOGD("Freezing enumeration field object's contained payload field: payload-field-addr=%p", enum_field->payload);
- bt_field_common_freeze_recursive(enum_field->payload);
- bt_field_common_generic_freeze(field);
-}
-
-BT_HIDDEN
-void bt_field_common_structure_freeze_recursive(struct bt_field_common *field)
-{
- int64_t i;
+ uint64_t i;
struct bt_field_common_structure *structure_field =
BT_FROM_COMMON(field);
BT_LOGD("Freezing structure field object: addr=%p", field);
for (i = 0; i < structure_field->fields->len; i++) {
- struct bt_field_common *field =
+ struct bt_field_common *struct_field =
g_ptr_array_index(structure_field->fields, i);
BT_LOGD("Freezing structure field's field: field-addr=%p, index=%" PRId64,
- field, i);
- bt_field_common_freeze_recursive(field);
+ struct_field, i);
+ bt_field_common_set_is_frozen_recursive(struct_field,
+ is_frozen);
}
- bt_field_common_generic_freeze(field);
+ bt_field_common_generic_set_is_frozen(field, is_frozen);
}
BT_HIDDEN
-void bt_field_common_variant_freeze_recursive(struct bt_field_common *field)
+void bt_field_common_variant_set_is_frozen_recursive(
+ struct bt_field_common *field, bool is_frozen)
{
+ uint64_t i;
struct bt_field_common_variant *variant_field = BT_FROM_COMMON(field);
BT_LOGD("Freezing variant field object: addr=%p", field);
- BT_LOGD("Freezing variant field object's tag field: tag-field-addr=%p", variant_field->tag);
- bt_field_common_freeze_recursive(variant_field->tag);
- BT_LOGD("Freezing variant field object's payload field: payload-field-addr=%p", variant_field->payload);
- bt_field_common_freeze_recursive(variant_field->payload);
- bt_field_common_generic_freeze(field);
+
+ for (i = 0; i < variant_field->fields->len; i++) {
+ struct bt_field_common *var_field =
+ g_ptr_array_index(variant_field->fields, i);
+
+ BT_LOGD("Freezing variant field's field: field-addr=%p, index=%" PRId64,
+ var_field, i);
+ bt_field_common_set_is_frozen_recursive(var_field, is_frozen);
+ }
+
+ bt_field_common_generic_set_is_frozen(field, is_frozen);
}
BT_HIDDEN
-void bt_field_common_array_freeze_recursive(struct bt_field_common *field)
+void bt_field_common_array_set_is_frozen_recursive(
+ struct bt_field_common *field, bool is_frozen)
{
int64_t i;
struct bt_field_common_array *array_field = BT_FROM_COMMON(field);
BT_LOGD("Freezing array field object's element field: "
"element-field-addr=%p, index=%" PRId64,
elem_field, i);
- bt_field_common_freeze_recursive(elem_field);
+ bt_field_common_set_is_frozen_recursive(elem_field, is_frozen);
}
- bt_field_common_generic_freeze(field);
+ bt_field_common_generic_set_is_frozen(field, is_frozen);
}
BT_HIDDEN
-void bt_field_common_sequence_freeze_recursive(struct bt_field_common *field)
+void bt_field_common_sequence_set_is_frozen_recursive(
+ struct bt_field_common *field, bool is_frozen)
{
int64_t i;
struct bt_field_common_sequence *sequence_field =
BT_FROM_COMMON(field);
BT_LOGD("Freezing sequence field object: addr=%p", field);
- BT_LOGD("Freezing sequence field object's length field: length-field-addr=%p",
- sequence_field->length);
- bt_field_common_freeze_recursive(sequence_field->length);
- for (i = 0; i < sequence_field->elements->len; i++) {
+ for (i = 0; i < sequence_field->length; i++) {
struct bt_field_common *elem_field =
g_ptr_array_index(sequence_field->elements, i);
BT_LOGD("Freezing sequence field object's element field: "
"element-field-addr=%p, index=%" PRId64,
elem_field, i);
- bt_field_common_freeze_recursive(elem_field);
+ bt_field_common_set_is_frozen_recursive(elem_field, is_frozen);
}
- bt_field_common_generic_freeze(field);
+ bt_field_common_generic_set_is_frozen(field, is_frozen);
}
BT_HIDDEN
-void _bt_field_common_freeze_recursive(struct bt_field_common *field)
+void _bt_field_common_set_is_frozen_recursive(struct bt_field_common *field,
+ bool is_frozen)
{
if (!field) {
goto end;
goto end;
}
- BT_LOGD("Freezing field object: addr=%p", field);
+ BT_LOGD("Setting field object's frozen state: addr=%p, is-frozen=%d",
+ field, is_frozen);
BT_ASSERT(field_type_common_has_known_id(field->type));
- BT_ASSERT(field->methods->freeze);
- field->methods->freeze(field);
+ BT_ASSERT(field->methods->set_is_frozen);
+ field->methods->set_is_frozen(field, is_frozen);
end:
return;
return field && field->payload_set;
}
-BT_HIDDEN
-bt_bool bt_field_common_enumeration_is_set_recursive(
- struct bt_field_common *field)
-{
- bt_bool is_set = BT_FALSE;
- struct bt_field_common_enumeration *enumeration = BT_FROM_COMMON(field);
-
- BT_ASSERT(field);
-
- if (!enumeration->payload) {
- goto end;
- }
-
- is_set = bt_field_common_is_set_recursive(enumeration->payload);
-
-end:
- return is_set;
-}
-
BT_HIDDEN
bt_bool bt_field_common_structure_is_set_recursive(
struct bt_field_common *field)
bt_bool bt_field_common_variant_is_set_recursive(struct bt_field_common *field)
{
struct bt_field_common_variant *variant = BT_FROM_COMMON(field);
+ bt_bool is_set = BT_FALSE;
BT_ASSERT(field);
- return bt_field_common_is_set_recursive(variant->payload);
+
+ if (variant->current_field) {
+ is_set = bt_field_common_is_set_recursive(
+ variant->current_field);
+ }
+
+ return is_set;
}
BT_HIDDEN
--- /dev/null
+/*
+ * Copyright 2018 Philippe Proulx <pproulx@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#define BT_LOG_TAG "PACKET-CONTEXT-FIELD"
+#include <babeltrace/lib-logging-internal.h>
+
+#include <babeltrace/assert-pre-internal.h>
+#include <babeltrace/ctf-ir/packet-context-field.h>
+#include <babeltrace/ctf-ir/fields-internal.h>
+#include <babeltrace/ctf-ir/field-wrapper-internal.h>
+#include <glib.h>
+
+struct bt_field *bt_packet_context_field_borrow_field(
+ struct bt_packet_context_field *context_field)
+{
+ struct bt_field_wrapper *field_wrapper = (void *) context_field;
+
+ BT_ASSERT_PRE_NON_NULL(field_wrapper, "Packet context field");
+ BT_ASSERT_PRE_NON_NULL(field_wrapper->field,
+ "Packet context field's field object");
+ return (void *) field_wrapper->field;
+}
+
+void bt_packet_context_field_release(struct bt_packet_context_field *context_field)
+{
+ struct bt_field_wrapper *field_wrapper = (void *) context_field;
+
+ BT_ASSERT_PRE_NON_NULL(field_wrapper, "Packet context field");
+
+ /*
+ * Do not recycle because the pool could be destroyed at this
+ * point. This function is only called when there's an error
+ * anyway because the goal of a packet context field wrapper is
+ * to eventually move it to a packet with bt_packet_move_context()
+ * after creating it.
+ */
+ bt_field_wrapper_destroy(field_wrapper);
+}
--- /dev/null
+/*
+ * Copyright 2018 Philippe Proulx <pproulx@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#define BT_LOG_TAG "PACKET-HEADER-FIELD"
+#include <babeltrace/lib-logging-internal.h>
+
+#include <babeltrace/assert-pre-internal.h>
+#include <babeltrace/ctf-ir/packet-header-field.h>
+#include <babeltrace/ctf-ir/field-wrapper-internal.h>
+#include <babeltrace/ctf-ir/fields-internal.h>
+#include <glib.h>
+
+struct bt_field *bt_packet_header_field_borrow_field(
+ struct bt_packet_header_field *header_field)
+{
+ struct bt_field_wrapper *field_wrapper = (void *) header_field;
+
+ BT_ASSERT_PRE_NON_NULL(field_wrapper, "Event header field");
+ BT_ASSERT_PRE_NON_NULL(field_wrapper->field,
+ "Event header field's field object");
+ return (void *) field_wrapper->field;
+}
+
+void bt_packet_header_field_release(struct bt_packet_header_field *header_field)
+{
+ struct bt_field_wrapper *field_wrapper = (void *) header_field;
+
+ BT_ASSERT_PRE_NON_NULL(field_wrapper, "Event header field");
+
+ /*
+ * Do not recycle because the pool could be destroyed at this
+ * point. This function is only called when there's an error
+ * anyway because the goal of a packet header field wrapper is
+ * to eventually move it to a packet with
+ * bt_packet_move_header() after creating it.
+ */
+ bt_field_wrapper_destroy(field_wrapper);
+}
#include <babeltrace/ctf-ir/fields-internal.h>
#include <babeltrace/ctf-ir/packet.h>
#include <babeltrace/ctf-ir/packet-internal.h>
+#include <babeltrace/ctf-ir/field-wrapper-internal.h>
#include <babeltrace/ctf-ir/trace.h>
#include <babeltrace/ctf-ir/stream-class-internal.h>
#include <babeltrace/ctf-ir/stream-class.h>
return packet->stream;
}
-struct bt_field *bt_packet_borrow_header(
- struct bt_packet *packet)
+struct bt_field *bt_packet_borrow_header(struct bt_packet *packet)
{
BT_ASSERT_PRE_NON_NULL(packet, "Packet");
- return packet->header;
+ return packet->header ? (void *) packet->header->field : NULL;
}
-BT_ASSERT_PRE_FUNC
-static inline bool validate_field_to_set(struct bt_field *field,
- struct bt_field_type_common *expected_ft)
+struct bt_field *bt_packet_borrow_context(struct bt_packet *packet)
{
- bool ret = true;
-
- if (!field) {
- if (expected_ft) {
- BT_ASSERT_PRE_MSG("Setting no field, but expected "
- "field type is not NULL: "
- "%![field-]+f, %![expected-ft-]+F",
- field, expected_ft);
- ret = false;
- goto end;
- }
+ BT_ASSERT_PRE_NON_NULL(packet, "Packet");
+ return packet->context ? (void *) packet->context->field : NULL;
+}
- goto end;
+BT_HIDDEN
+void _bt_packet_freeze(struct bt_packet *packet)
+{
+ if (!packet || packet->frozen) {
+ return;
}
- if (bt_field_type_compare(bt_field_borrow_type(field),
- BT_FROM_COMMON(expected_ft)) != 0) {
- BT_ASSERT_PRE_MSG("Field type is different from expected "
- " field type: %![field-ft-]+F, %![expected-ft-]+F",
- bt_field_borrow_type(field), expected_ft);
- ret = false;
- goto end;
+ BT_LOGD("Freezing packet: addr=%p", packet);
+
+ if (packet->header) {
+ BT_LOGD_STR("Freezing packet's header field.");
+ bt_field_set_is_frozen_recursive((void *) packet->header->field, true);
}
-end:
- return ret;
+ if (packet->context) {
+ BT_LOGD_STR("Freezing packet's context field.");
+ bt_field_set_is_frozen_recursive((void *) packet->context->field, true);
+ }
+
+ packet->frozen = 1;
}
-int bt_packet_set_header(struct bt_packet *packet,
- struct bt_field *header)
+static inline
+void bt_packet_reset(struct bt_packet *packet)
{
- BT_ASSERT_PRE_NON_NULL(packet, "Packet");
- BT_ASSERT_PRE_HOT(packet, "Packet", ": +%!+a", packet);
- BT_ASSERT_PRE(validate_field_to_set(header,
- bt_stream_class_borrow_trace(
- BT_FROM_COMMON(packet->stream->common.stream_class))->common.packet_header_field_type),
- "Invalid packet header field: "
- "%![packet-]+a, %![field-]+f", packet, header);
- bt_put(packet->header);
- packet->header = bt_get(header);
- BT_LOGV("Set packet's header field: packet-addr=%p, packet-header-addr=%p",
- packet, header);
- return 0;
+ BT_ASSERT(packet);
+ packet->frozen = false;
+
+ if (packet->header) {
+ bt_field_set_is_frozen_recursive(
+ (void *) packet->header->field, false);
+ bt_field_reset_recursive((void *) packet->header->field);
+ }
+
+ if (packet->context) {
+ bt_field_set_is_frozen_recursive(
+ (void *) packet->context->field, false);
+ bt_field_reset_recursive((void *) packet->context->field);
+ }
}
-struct bt_field *bt_packet_borrow_context(struct bt_packet *packet)
+static
+void bt_packet_header_field_recycle(struct bt_field_wrapper *header_field,
+ struct bt_trace *trace)
{
- BT_ASSERT_PRE_NON_NULL(packet, "Packet");
- return packet->context;
+ BT_ASSERT(header_field);
+ BT_LIB_LOGD("Recycling packet header field: "
+ "addr=%p, %![trace-]+t, %![field-]+f", header_field,
+ trace, header_field->field);
+ bt_object_pool_recycle_object(&trace->packet_header_field_pool,
+ header_field);
}
-int bt_packet_set_context(struct bt_packet *packet,
- struct bt_field *context)
+static
+void bt_packet_context_field_recycle(struct bt_field_wrapper *context_field,
+ struct bt_stream_class *stream_class)
{
- BT_ASSERT_PRE_NON_NULL(packet, "Packet");
- BT_ASSERT_PRE_HOT(packet, "Packet", ": +%!+a", packet);
- BT_ASSERT_PRE(validate_field_to_set(context,
- BT_FROM_COMMON(packet->stream->common.stream_class->packet_context_field_type)),
- "Invalid packet context field: "
- "%![packet-]+a, %![field-]+f", packet, context);
- bt_put(packet->context);
- packet->context = bt_get(context);
- BT_LOGV("Set packet's context field: packet-addr=%p, packet-context-addr=%p",
- packet, context);
- return 0;
+ BT_ASSERT(context_field);
+ BT_LIB_LOGD("Recycling packet context field: "
+ "addr=%p, %![sc-]+S, %![field-]+f", context_field,
+ stream_class, context_field->field);
+ bt_object_pool_recycle_object(&stream_class->packet_context_field_pool,
+ context_field);
}
BT_HIDDEN
-void _bt_packet_freeze(struct bt_packet *packet)
+void bt_packet_recycle(struct bt_packet *packet)
{
- if (!packet || packet->frozen) {
- return;
- }
+ struct bt_stream *stream;
- BT_LOGD("Freezing packet: addr=%p", packet);
- BT_LOGD_STR("Freezing packet's header field.");
- bt_field_freeze_recursive(packet->header);
- BT_LOGD_STR("Freezing packet's context field.");
- bt_field_freeze_recursive(packet->context);
- packet->frozen = 1;
+ BT_ASSERT(packet);
+ BT_LIB_LOGD("Recycling packet: %!+a", packet);
+
+ /*
+ * Those are the important ordered steps:
+ *
+ * 1. Reset the packet object (put any permanent reference it
+ * has, unfreeze it and its fields in developer mode, etc.),
+ * but do NOT put its stream's reference. This stream
+ * contains the pool to which we're about to recycle this
+ * packet object, so we must guarantee its existence thanks
+ * to this existing reference.
+ *
+ * 2. Move the stream reference to our `stream`
+ * variable so that we can set the packet's stream member
+ * to NULL before recycling it. We CANNOT do this after
+ * we put the stream reference because this bt_put()
+ * could destroy the stream, also destroying its
+ * packet pool, thus also destroying our packet object (this
+ * would result in an invalid write access).
+ *
+ * 3. Recycle the packet object.
+ *
+ * 4. Put our stream reference.
+ */
+ bt_packet_reset(packet);
+ stream = packet->stream;
+ BT_ASSERT(stream);
+ packet->stream = NULL;
+ bt_object_pool_recycle_object(&stream->packet_pool, packet);
+ bt_put(stream);
}
-static
-void bt_packet_destroy(struct bt_object *obj)
+BT_HIDDEN
+void bt_packet_destroy(struct bt_packet *packet)
{
- struct bt_packet *packet = (void *) obj;
-
BT_LOGD("Destroying packet: addr=%p", packet);
- BT_LOGD_STR("Putting packet's header field.");
- bt_put(packet->header);
- BT_LOGD_STR("Putting packet's context field.");
- bt_put(packet->context);
+ BT_LOGD_STR("Destroying packet's header field.");
+
+ if (packet->header) {
+ if (packet->stream) {
+ BT_LOGD_STR("Recycling packet's header field.");
+ bt_packet_header_field_recycle(packet->header,
+ bt_stream_class_borrow_trace(
+ bt_stream_borrow_class(packet->stream)));
+ } else {
+ bt_field_wrapper_destroy(packet->header);
+ }
+ }
+
+ if (packet->context) {
+ if (packet->stream) {
+ BT_LOGD_STR("Recycling packet's context field.");
+ bt_packet_context_field_recycle(packet->context,
+ bt_stream_borrow_class(packet->stream));
+ } else {
+ bt_field_wrapper_destroy(packet->context);
+ }
+ }
+
BT_LOGD_STR("Putting packet's stream.");
bt_put(packet->stream);
g_free(packet);
}
-struct bt_packet *bt_packet_create(
- struct bt_stream *stream)
+BT_HIDDEN
+struct bt_packet *bt_packet_new(struct bt_stream *stream)
{
struct bt_packet *packet = NULL;
struct bt_stream_class *stream_class = NULL;
struct bt_trace *trace = NULL;
- BT_ASSERT_PRE_NON_NULL(stream, "Stream");
+ BT_ASSERT(stream);
BT_LOGD("Creating packet object: stream-addr=%p, "
"stream-name=\"%s\", stream-class-addr=%p, "
"stream-class-name=\"%s\", stream-class-id=%" PRId64,
goto end;
}
- bt_object_init(packet, bt_packet_destroy);
+ bt_object_init(packet, (bt_object_release_func) bt_packet_recycle);
packet->stream = bt_get(stream);
if (trace->common.packet_header_field_type) {
BT_LOGD("Creating initial packet header field: ft-addr=%p",
trace->common.packet_header_field_type);
- packet->header = bt_field_create(
- BT_FROM_COMMON(trace->common.packet_header_field_type));
+ packet->header = bt_field_wrapper_create(
+ &trace->packet_header_field_pool,
+ (void *) trace->common.packet_header_field_type);
if (!packet->header) {
- BT_LOGE_STR("Cannot create initial packet header field object.");
+ BT_LOGE("Cannot create packet header field wrapper.");
BT_PUT(packet);
goto end;
}
if (stream->common.stream_class->packet_context_field_type) {
BT_LOGD("Creating initial packet context field: ft-addr=%p",
stream->common.stream_class->packet_context_field_type);
- packet->context = bt_field_create(
- BT_FROM_COMMON(stream->common.stream_class->packet_context_field_type));
+ packet->context = bt_field_wrapper_create(
+ &stream_class->packet_context_field_pool,
+ (void *) stream->common.stream_class->packet_context_field_type);
if (!packet->context) {
- BT_LOGE_STR("Cannot create initial packet header field object.");
+ BT_LOGE("Cannot create packet context field wrapper.");
BT_PUT(packet);
goto end;
}
end:
return packet;
}
+
+struct bt_packet *bt_packet_create(struct bt_stream *stream)
+{
+ struct bt_packet *packet = NULL;
+
+ BT_ASSERT_PRE_NON_NULL(stream, "Stream");
+ packet = bt_object_pool_create_object(&stream->packet_pool);
+ if (!packet) {
+ BT_LIB_LOGE("Cannot allocate one packet from stream's packet pool: "
+ "%![stream-]+s", stream);
+ goto error;
+ }
+
+ if (!packet->stream) {
+ packet->stream = bt_get(stream);
+ }
+
+ goto end;
+
+error:
+ if (packet) {
+ bt_packet_recycle(packet);
+ packet = NULL;
+ }
+
+end:
+ return packet;
+}
+
+int bt_packet_move_header(struct bt_packet *packet,
+ struct bt_packet_header_field *header_field)
+{
+ struct bt_trace *trace;
+ struct bt_field_wrapper *field_wrapper = (void *) header_field;
+
+ BT_ASSERT_PRE_NON_NULL(packet, "Event");
+ BT_ASSERT_PRE_NON_NULL(field_wrapper, "Header field");
+ BT_ASSERT_PRE_HOT(packet, "Packet", ": +%!+a", packet);
+ trace = bt_stream_class_borrow_trace(
+ bt_stream_borrow_class(packet->stream));
+ BT_ASSERT_PRE(trace->common.packet_header_field_type,
+ "Trace has no packet header field type: %!+t",
+ trace);
+
+ /* TODO: compare field types (precondition) */
+
+ /* Recycle current header field: always exists */
+ BT_ASSERT(packet->header);
+ bt_packet_header_field_recycle(packet->header, trace);
+
+ /* Move new field */
+ packet->header = field_wrapper;
+ return 0;
+}
+
+int bt_packet_move_context(struct bt_packet *packet,
+ struct bt_packet_context_field *context_field)
+{
+ struct bt_stream_class *stream_class;
+ struct bt_field_wrapper *field_wrapper = (void *) context_field;
+
+ BT_ASSERT_PRE_NON_NULL(packet, "Event");
+ BT_ASSERT_PRE_NON_NULL(field_wrapper, "Context field");
+ BT_ASSERT_PRE_HOT(packet, "Packet", ": +%!+a", packet);
+ stream_class = bt_stream_borrow_class(packet->stream);
+ BT_ASSERT_PRE(stream_class->common.packet_context_field_type,
+ "Stream class has no packet context field type: %!+S",
+ stream_class);
+
+ /* TODO: compare field types (precondition) */
+
+ /* Recycle current context field: always exists */
+ BT_ASSERT(packet->context);
+ bt_packet_context_field_recycle(packet->context, stream_class);
+
+ /* Move new field */
+ packet->context = field_wrapper;
+ return 0;
+}
#include <babeltrace/ctf-ir/visitor-internal.h>
#include <babeltrace/ctf-ir/utils.h>
#include <babeltrace/ctf-ir/utils-internal.h>
+#include <babeltrace/ctf-ir/field-wrapper-internal.h>
#include <babeltrace/ref.h>
#include <babeltrace/compiler-internal.h>
#include <babeltrace/align-internal.h>
BT_LOGD("Destroying stream class: addr=%p, name=\"%s\", id=%" PRId64,
stream_class, bt_stream_class_get_name(stream_class),
bt_stream_class_get_id(stream_class));
+
+ /*
+ * IMPORTANT: Finalize the common stream class BEFORE finalizing
+ * the pools because otherwise this scenario is possible:
+ *
+ * 1. Event header field object pool is finalized, thus
+ * destroying its internal array and state.
+ *
+ * 2. Stream class is finalized: each event class is destroyed.
+ *
+ * 3. Destroying an event class finalizes its event pool,
+ * destroying each contained event.
+ *
+ * 4. Destroying an event makes it recycle its event header
+ * field to its stream class's event header field pool. But
+ * said pool is already destroyed.
+ */
bt_stream_class_common_finalize(BT_TO_COMMON(stream_class));
+ bt_object_pool_finalize(&stream_class->event_header_field_pool);
+ bt_object_pool_finalize(&stream_class->packet_context_field_pool);
g_free(stream_class);
}
+static
+void free_field_wrapper(struct bt_field_wrapper *field_wrapper,
+ struct bt_stream_class *stream_class)
+{
+ bt_field_wrapper_destroy((void *) field_wrapper);
+}
+
struct bt_stream_class *bt_stream_class_create(const char *name)
{
struct bt_stream_class *stream_class = NULL;
goto error;
}
+ ret = bt_object_pool_initialize(&stream_class->event_header_field_pool,
+ (bt_object_pool_new_object_func) bt_field_wrapper_new,
+ (bt_object_pool_destroy_object_func) free_field_wrapper,
+ stream_class);
+ if (ret) {
+ BT_LOGE("Failed to initialize event header field pool: ret=%d",
+ ret);
+ goto error;
+ }
+
+ ret = bt_object_pool_initialize(&stream_class->packet_context_field_pool,
+ (bt_object_pool_new_object_func) bt_field_wrapper_new,
+ (bt_object_pool_destroy_object_func) free_field_wrapper,
+ stream_class);
+ if (ret) {
+ BT_LOGE("Failed to initialize packet context field pool: ret=%d",
+ ret);
+ goto error;
+ }
+
BT_LOGD("Created stream class object: addr=%p, name=\"%s\"",
stream_class, name);
return stream_class;
return NULL;
}
+struct bt_event_header_field *bt_stream_class_create_event_header_field(
+ struct bt_stream_class *stream_class)
+{
+ struct bt_field_wrapper *field_wrapper;
+
+ BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
+ BT_ASSERT_PRE(stream_class->common.frozen,
+ "Stream class is not part of a trace: %!+S", stream_class);
+ BT_ASSERT_PRE(stream_class->common.event_header_field_type,
+ "Stream class has no event header field type: %!+S",
+ stream_class);
+ field_wrapper = bt_field_wrapper_create(
+ &stream_class->event_header_field_pool,
+ (void *) stream_class->common.event_header_field_type);
+ if (!field_wrapper) {
+ BT_LIB_LOGE("Cannot allocate one event header field from stream class: "
+ "%![sc-]+S", stream_class);
+ goto error;
+ }
+
+ BT_ASSERT(field_wrapper->field);
+ goto end;
+
+error:
+ if (field_wrapper) {
+ bt_field_wrapper_destroy(field_wrapper);
+ field_wrapper = NULL;
+ }
+
+end:
+ return (void *) field_wrapper;
+}
+
+struct bt_packet_context_field *bt_stream_class_create_packet_context_field(
+ struct bt_stream_class *stream_class)
+{
+ struct bt_field_wrapper *field_wrapper;
+
+ BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
+ BT_ASSERT_PRE(stream_class->common.frozen,
+ "Stream class is not part of a trace: %!+S", stream_class);
+ BT_ASSERT_PRE(stream_class->common.packet_context_field_type,
+ "Stream class has no packet context field type: %!+S",
+ stream_class);
+ field_wrapper = bt_field_wrapper_create(
+ &stream_class->packet_context_field_pool,
+ (void *) stream_class->common.packet_context_field_type);
+ if (!field_wrapper) {
+ BT_LIB_LOGE("Cannot allocate one packet context field from stream class: "
+ "%![sc-]+S", stream_class);
+ goto error;
+ }
+
+ BT_ASSERT(field_wrapper->field);
+ goto end;
+
+error:
+ if (field_wrapper) {
+ bt_field_wrapper_destroy(field_wrapper);
+ field_wrapper = NULL;
+ }
+
+end:
+ return (void *) field_wrapper;
+}
+
struct bt_trace *bt_stream_class_borrow_trace(struct bt_stream_class *stream_class)
{
return BT_FROM_COMMON(bt_stream_class_common_borrow_trace(
{
struct bt_trace *trace;
int ret = 0;
+ uint64_t i;
+ struct bt_clock_class *old_clock_class;
if (!stream_class) {
BT_LOGW("Invalid parameter: stream class is NULL: "
goto end;
}
+ old_clock_class = stream_class->common.clock_class;
trace = BT_FROM_COMMON(bt_stream_class_common_borrow_trace(
BT_TO_COMMON(stream_class)));
if (trace && trace->is_static) {
(void) bt_trace_object_modification(&obj, trace);
}
+ if (!old_clock_class && stream_class->common.clock_class) {
+ /*
+ * Adding this event class updated the stream class's
+ * single clock class: make sure all the events which
+ * exist in event pools have an existing clock value for
+ * this clock class so that any created event object in
+ * the future (from a pool or not) has this clock value
+ * available.
+ */
+ for (i = 0; i < stream_class->common.event_classes->len; i++) {
+ struct bt_event_class *event_class =
+ stream_class->common.event_classes->pdata[i];
+
+ BT_ASSERT(event_class);
+ ret = bt_event_class_update_event_pool_clock_values(
+ event_class);
+ if (ret) {
+ goto end;
+ }
+ }
+ }
+
end:
return ret;
}
#include <babeltrace/ctf-ir/stream-class-internal.h>
#include <babeltrace/ctf-ir/trace.h>
#include <babeltrace/ctf-ir/trace-internal.h>
+#include <babeltrace/ctf-ir/packet-internal.h>
#include <babeltrace/ref.h>
#include <babeltrace/compiler-internal.h>
#include <babeltrace/align-internal.h>
BT_LOGD("Destroying stream object: addr=%p, name=\"%s\"",
stream, bt_stream_get_name(stream));
+ bt_object_pool_finalize(&stream->packet_pool);
bt_stream_common_finalize((void *) obj);
g_free(stream);
}
return ret;
}
+static
+void bt_stream_free_packet(struct bt_packet *packet, struct bt_stream *stream)
+{
+ bt_packet_destroy(packet);
+}
+
static
struct bt_stream *bt_stream_create_with_id_no_check(
struct bt_stream_class *stream_class,
goto error;
}
+ ret = bt_object_pool_initialize(&stream->packet_pool,
+ (bt_object_pool_new_object_func) bt_packet_new,
+ (bt_object_pool_destroy_object_func) bt_stream_free_packet,
+ stream);
+ if (ret) {
+ BT_LOGE("Failed to initialize packet pool: ret=%d", ret);
+ goto error;
+ }
+
g_ptr_array_add(trace->common.streams, stream);
BT_LOGD("Created stream object: addr=%p", stream);
goto end;
#include <babeltrace/ctf-ir/event-class-internal.h>
#include <babeltrace/ctf-writer/functor-internal.h>
#include <babeltrace/ctf-writer/clock-internal.h>
+#include <babeltrace/ctf-ir/field-wrapper-internal.h>
#include <babeltrace/ctf-ir/field-types-internal.h>
#include <babeltrace/ctf-ir/attributes-internal.h>
#include <babeltrace/ctf-ir/validation-internal.h>
g_ptr_array_free(trace->listeners, TRUE);
}
+ bt_object_pool_finalize(&trace->packet_header_field_pool);
bt_trace_common_finalize(BT_TO_COMMON(trace));
g_free(trace);
}
bt_put(trace->packet_header_field_type);
}
+static
+void free_packet_header_field(struct bt_field_wrapper *field_wrapper,
+ struct bt_trace *trace)
+{
+ bt_field_wrapper_destroy(field_wrapper);
+}
+
struct bt_trace *bt_trace_create(void)
{
struct bt_trace *trace = NULL;
goto error;
}
+ ret = bt_object_pool_initialize(&trace->packet_header_field_pool,
+ (bt_object_pool_new_object_func) bt_field_wrapper_new,
+ (bt_object_pool_destroy_object_func) free_packet_header_field,
+ trace);
+ if (ret) {
+ BT_LOGE("Failed to initialize packet header field pool: ret=%d",
+ ret);
+ goto error;
+ }
+
BT_LOGD("Created trace object: addr=%p", trace);
return trace;
end:
return ret;
}
+
+struct bt_packet_header_field *bt_trace_create_packet_header_field(
+ struct bt_trace *trace)
+{
+ struct bt_field_wrapper *field_wrapper;
+
+ BT_ASSERT_PRE_NON_NULL(trace, "Trace");
+ BT_ASSERT_PRE(trace->common.packet_header_field_type,
+ "Trace has no packet header field type: %!+t",
+ trace);
+ field_wrapper = bt_field_wrapper_create(
+ &trace->packet_header_field_pool,
+ (void *) trace->common.packet_header_field_type);
+ if (!field_wrapper) {
+ BT_LIB_LOGE("Cannot allocate one packet header field from trace: "
+ "%![trace-]+t", trace);
+ goto error;
+ }
+
+ BT_ASSERT(field_wrapper->field);
+ bt_trace_common_freeze(BT_TO_COMMON(trace));
+ goto end;
+
+error:
+ if (field_wrapper) {
+ bt_field_wrapper_destroy(field_wrapper);
+ field_wrapper = NULL;
+ }
+
+end:
+ return (void *) field_wrapper;
+}
return ret;
}
+static
+void destroy_event_header_field(struct bt_field_wrapper *field_wrapper)
+{
+ BT_ASSERT(field_wrapper);
+ bt_put(field_wrapper->field);
+ bt_field_wrapper_destroy(field_wrapper);
+}
+
+static
+struct bt_field_wrapper *create_event_header_field(
+ struct bt_stream_class *stream_class,
+ struct bt_field_type_common *ft)
+{
+ struct bt_field_wrapper *field_wrapper = NULL;
+ struct bt_ctf_field *field = bt_ctf_field_create((void *) ft);
+
+ if (!field) {
+ goto error;
+ }
+
+ field_wrapper = bt_field_wrapper_new(NULL);
+ if (!field_wrapper) {
+ goto error;
+ }
+
+ field_wrapper->field = (void *) field;
+ field = NULL;
+ goto end;
+
+error:
+ bt_put(field);
+
+ if (field_wrapper) {
+ destroy_event_header_field(field_wrapper);
+ field_wrapper = NULL;
+ }
+
+end:
+ return field_wrapper;
+}
+
struct bt_ctf_event *bt_ctf_event_create(struct bt_ctf_event_class *event_class)
{
int ret;
(bt_validation_flag_copy_field_type_func)
bt_ctf_field_type_copy,
false, map_clock_classes_func,
- (void *) bt_ctf_field_create);
+ (void *) bt_ctf_field_create,
+ (void *) bt_put,
+ (void *) create_event_header_field,
+ (void *) destroy_event_header_field);
if (ret) {
/* bt_event_common_initialize() logs errors */
goto error;
BT_ASSERT_PRE_NON_NULL(field, "Payload field");
BT_ASSERT_PRE_EVENT_COMMON_HOT(BT_TO_COMMON(event), "Event");
return bt_ctf_field_structure_set_field_by_name(
- BT_FROM_COMMON(event->common.payload_field), name, field);
+ (void *) event->common.payload_field, name, field);
}
struct bt_ctf_field *bt_ctf_event_get_payload(struct bt_ctf_event *event,
return bt_get(bt_event_common_borrow_payload(BT_TO_COMMON(event)));
}
-int bt_ctf_event_set_payload_field(struct bt_ctf_event *event,
- struct bt_ctf_field *field)
-{
- return bt_event_common_set_payload(BT_TO_COMMON(event), (void *) field);
-}
-
struct bt_ctf_field *bt_ctf_event_get_header(struct bt_ctf_event *event)
{
return bt_get(bt_event_common_borrow_header(BT_TO_COMMON(event)));
}
-int bt_ctf_event_set_header(struct bt_ctf_event *event,
- struct bt_ctf_field *field)
-{
- return bt_event_common_set_header(BT_TO_COMMON(event), (void *) field);
-}
-
struct bt_ctf_field *bt_ctf_event_get_context(struct bt_ctf_event *event)
{
return bt_get(bt_event_common_borrow_context(BT_TO_COMMON(event)));
}
-int bt_ctf_event_set_context(struct bt_ctf_event *event,
- struct bt_ctf_field *field)
-{
- return bt_event_common_set_context(BT_TO_COMMON(event), (void *) field);
-}
-
struct bt_ctf_field *bt_ctf_event_get_stream_event_context(
struct bt_ctf_event *event)
{
BT_TO_COMMON(event)));
}
-int bt_ctf_event_set_stream_event_context(struct bt_ctf_event *event,
- struct bt_ctf_field *field)
+static
+void release_event_header_field(struct bt_field_wrapper *field_wrapper,
+ struct bt_event_common *event_common)
{
- return bt_event_common_set_stream_event_context(
- BT_TO_COMMON(event), (void *) field);
+ BT_ASSERT(field_wrapper);
+ BT_PUT(field_wrapper->field);
+ bt_field_wrapper_destroy(field_wrapper);
}
static
void bt_ctf_event_destroy(struct bt_object *obj)
{
- bt_event_common_finalize(obj);
+ bt_event_common_finalize(obj, (void *) bt_put,
+ (void *) release_event_header_field);
g_free(obj);
}
{
_bt_event_common_freeze(BT_TO_COMMON(event));
}
+
+int bt_ctf_event_set_header(struct bt_ctf_event *event,
+ struct bt_ctf_field *header)
+{
+ BT_ASSERT_PRE_NON_NULL(event, "Event");
+ BT_ASSERT_PRE_EVENT_COMMON_HOT(BT_TO_COMMON(event), "Event");
+
+ /*
+ * Ensure the provided header's type matches the one registered to the
+ * stream class.
+ */
+ if (header) {
+ BT_ASSERT_PRE(bt_field_type_common_compare(
+ ((struct bt_field_common *) header)->type,
+ bt_event_class_common_borrow_stream_class(event->common.class)->event_header_field_type) == 0,
+ "Header field's type is different from the "
+ "expected field type: %![event-]+we, %![ft-]+wF, "
+ "%![expected-ft-]+wF",
+ event, ((struct bt_field_common *) header)->type,
+ bt_event_class_common_borrow_stream_class(event->common.class)->event_header_field_type);
+ } else {
+ BT_ASSERT_PRE(!bt_event_class_common_borrow_stream_class(event->common.class)->event_header_field_type,
+ "Setting no event header field, "
+ "but event header field type is not NULL: ",
+ "%![event-]+we, %![header-ft-]+wF",
+ event,
+ bt_event_class_common_borrow_stream_class(event->common.class)->event_header_field_type);
+ }
+
+ bt_put(event->common.header_field->field);
+ event->common.header_field->field = bt_get(header);
+ BT_LOGV("Set event's header field: event-addr=%p, "
+ "event-class-name=\"%s\", event-class-id=%" PRId64 ", "
+ "header-field-addr=%p",
+ event, bt_event_class_common_get_name(event->common.class),
+ bt_event_class_common_get_id(event->common.class), header);
+ return 0;
+}
+
+int bt_ctf_event_common_set_payload(struct bt_ctf_event *event,
+ struct bt_ctf_field *payload)
+{
+ BT_ASSERT_PRE_NON_NULL(event, "Event");
+ BT_ASSERT_PRE_EVENT_COMMON_HOT(BT_TO_COMMON(event), "Event");
+
+ if (payload) {
+ BT_ASSERT_PRE(bt_field_type_common_compare(
+ ((struct bt_field_common *) payload)->type,
+ event->common.class->payload_field_type) == 0,
+ "Payload field's type is different from the "
+ "expected field type: %![event-]+we, %![ft-]+wF, "
+ "%![expected-ft-]+wF",
+ event,
+ ((struct bt_field_common *) payload)->type,
+ event->common.class->payload_field_type);
+ } else {
+ BT_ASSERT_PRE(!event->common.class->payload_field_type,
+ "Setting no event payload field, "
+ "but event payload field type is not NULL: ",
+ "%![event-]+we, %![payload-ft-]+wF",
+ event, event->common.class->payload_field_type);
+ }
+
+ bt_put(event->common.payload_field);
+ event->common.payload_field = bt_get(payload);
+ BT_LOGV("Set event's payload field: event-addr=%p, "
+ "event-class-name=\"%s\", event-class-id=%" PRId64 ", "
+ "payload-field-addr=%p",
+ event, bt_event_class_common_get_name(event->common.class),
+ bt_event_class_common_get_id(event->common.class), payload);
+ return 0;
+}
+
+int bt_ctf_event_set_context(struct bt_ctf_event *event,
+ struct bt_ctf_field *context)
+{
+ BT_ASSERT_PRE_NON_NULL(event, "Event");
+ BT_ASSERT_PRE_EVENT_COMMON_HOT(BT_TO_COMMON(event), "Event");
+
+ if (context) {
+ BT_ASSERT_PRE(bt_field_type_common_compare(
+ ((struct bt_field_common *) context)->type,
+ event->common.class->context_field_type) == 0,
+ "Context field's type is different from the "
+ "expected field type: %![event-]+we, %![ft-]+wF, "
+ "%![expected-ft-]+wF",
+ event, ((struct bt_field_common *) context)->type,
+ event->common.class->context_field_type);
+ } else {
+ BT_ASSERT_PRE(!event->common.class->context_field_type,
+ "Setting no event context field, "
+ "but event context field type is not NULL: ",
+ "%![event-]+we, %![context-ft-]+wF",
+ event, event->common.class->context_field_type);
+ }
+
+ bt_put(event->common.context_field);
+ event->common.context_field = bt_get(context);
+ BT_LOGV("Set event's context field: event-addr=%p, "
+ "event-class-name=\"%s\", event-class-id=%" PRId64 ", "
+ "context-field-addr=%p",
+ event, bt_event_class_common_get_name(event->common.class),
+ bt_event_class_common_get_id(event->common.class), context);
+ return 0;
+}
+
+int bt_ctf_event_set_stream_event_context(struct bt_ctf_event *event,
+ struct bt_ctf_field *stream_event_context)
+{
+ BT_ASSERT_PRE_NON_NULL(event, "Event");
+ BT_ASSERT_PRE_EVENT_COMMON_HOT(BT_TO_COMMON(event), "Event");
+
+ if (stream_event_context) {
+ BT_ASSERT_PRE(bt_field_type_common_compare(
+ ((struct bt_field_common *) stream_event_context)->type,
+ bt_event_class_common_borrow_stream_class(event->common.class)->event_context_field_type) == 0,
+ "Stream event context field's type is different from the "
+ "expected field type: %![event-]+we, %![ft-]+wF, "
+ "%![expected-ft-]+wF",
+ event,
+ ((struct bt_field_common *) stream_event_context)->type,
+ bt_event_class_common_borrow_stream_class(event->common.class)->event_context_field_type);
+ } else {
+ BT_ASSERT_PRE(!bt_event_class_common_borrow_stream_class(event->common.class)->event_context_field_type,
+ "Setting no stream event context field, "
+ "but stream event context field type is not NULL: ",
+ "%![event-]+we, %![context-ft-]+wF",
+ event,
+ bt_event_class_common_borrow_stream_class(event->common.class)->event_context_field_type);
+ }
+
+ bt_put(event->common.stream_event_context_field);
+ event->common.stream_event_context_field = bt_get(stream_event_context);
+ BT_LOGV("Set event's stream event context field: event-addr=%p, "
+ "event-class-name=\"%s\", event-class-id=%" PRId64 ", "
+ "stream-event-context-field-addr=%p",
+ event, bt_event_class_common_get_name(event->common.class),
+ bt_event_class_common_get_id(event->common.class),
+ stream_event_context);
+ return 0;
+}
#include <babeltrace/ctf-writer/field-types.h>
#include <babeltrace/ctf-writer/field-types-internal.h>
#include <babeltrace/ctf-writer/fields.h>
+#include <babeltrace/ctf-writer/fields-internal.h>
#include <babeltrace/ctf-writer/clock-internal.h>
#include <babeltrace/object-internal.h>
#include <babeltrace/ref.h>
g_string_append(context->string, "struct {\n");
for (i = 0; i < structure->fields->len; i++) {
- struct structure_field_common *field = structure->fields->pdata[i];
+ struct bt_field_type_common_structure_field *field =
+ BT_FIELD_TYPE_COMMON_STRUCTURE_FIELD_AT_INDEX(
+ structure, i);
BT_LOGD("Serializing CTF writer structure field type's field metadata: "
"index=%zu, "
}
context->current_indentation_level++;
- for (i = 0; i < variant->fields->len; i++) {
- struct structure_field_common *field =
- variant->fields->pdata[i];
+ for (i = 0; i < variant->choices->len; i++) {
+ struct bt_field_type_common_variant_choice *field =
+ BT_FIELD_TYPE_COMMON_VARIANT_CHOICE_AT_INDEX(
+ variant, i);
BT_LOGD("Serializing CTF writer variant field type's field metadata: "
"index=%zu, "
struct bt_ctf_field_type *ft,
struct bt_ctf_field *tag_field)
{
- return bt_get(bt_field_type_common_variant_borrow_field_type_from_tag(
- (void *) ft, (void *) tag_field,
- (bt_field_common_create_func) bt_field_create));
+ int ret;
+ int64_t choice_index;
+ struct bt_ctf_field *container;
+ struct bt_field_type_common_variant *var_ft = (void *) ft;
+ struct bt_ctf_field_type *ret_ft = NULL;
+
+ BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+ BT_ASSERT_PRE_FT_COMMON_HAS_ID(ft, BT_FIELD_TYPE_ID_VARIANT,
+ "Field type");
+ BT_ASSERT_PRE_NON_NULL(tag_field, "Tag field");
+ BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(
+ (struct bt_field_common *) tag_field,
+ BT_CTF_FIELD_TYPE_ID_ENUM, "Tag field");
+ BT_ASSERT_PRE_FIELD_COMMON_IS_SET((struct bt_field_common *) tag_field,
+ "Tag field");
+
+ container = bt_ctf_field_enumeration_borrow_container(tag_field);
+ BT_ASSERT(container);
+
+ if (var_ft->tag_ft->container_ft->is_signed) {
+ int64_t val;
+
+ ret = bt_ctf_field_integer_signed_get_value(container,
+ &val);
+ BT_ASSERT(ret == 0);
+ choice_index = bt_field_type_common_variant_find_choice_index(
+ (void *) ft, (uint64_t) val, true);
+ } else {
+ uint64_t val;
+
+ ret = bt_ctf_field_integer_unsigned_get_value(container,
+ &val);
+ BT_ASSERT(ret == 0);
+ choice_index = bt_field_type_common_variant_find_choice_index(
+ (void *) ft, val, false);
+ }
+
+ if (choice_index < 0) {
+ BT_LIB_LOGW("Cannot find variant field type's field: "
+ "%![var-ft-]+wF, %![tag-field-]+wf", ft, tag_field);
+ goto end;
+ }
+
+ ret = bt_ctf_field_type_variant_get_field_by_index(ft, NULL,
+ &ret_ft, choice_index);
+ BT_ASSERT(ret == 0);
+
+end:
+ return ret_ft;
}
int64_t bt_ctf_field_type_variant_get_field_count(struct bt_ctf_field_type *ft)
key, value);
}
+ g_array_set_size(copy_ft->fields, struct_ft->fields->len);
+
for (i = 0; i < struct_ft->fields->len; i++) {
- struct structure_field_common *entry, *copy_entry;
+ struct bt_field_type_common_structure_field *entry, *copy_entry;
struct bt_field_type_common *field_ft_copy;
- entry = g_ptr_array_index(struct_ft->fields, i);
+ entry = BT_FIELD_TYPE_COMMON_STRUCTURE_FIELD_AT_INDEX(
+ struct_ft, i);
+ copy_entry = BT_FIELD_TYPE_COMMON_STRUCTURE_FIELD_AT_INDEX(
+ copy_ft, i);
BT_LOGD("Copying CTF writer structure field type's field: "
"index=%" PRId64 ", "
"field-ft-addr=%p, field-name=\"%s\"",
i, entry, g_quark_to_string(entry->name));
- copy_entry = g_new0(struct structure_field_common, 1);
- if (!copy_entry) {
- BT_LOGE_STR("Failed to allocate one structure field type field.");
- goto error;
- }
field_ft_copy = (void *) bt_ctf_field_type_copy(
(void *) entry->type);
"index=%" PRId64 ", "
"field-ft-addr=%p, field-name=\"%s\"",
i, entry, g_quark_to_string(entry->name));
- g_free(copy_entry);
goto error;
}
copy_entry->name = entry->name;
copy_entry->type = field_ft_copy;
- g_ptr_array_add(copy_ft->fields, copy_entry);
}
BT_LOGD("Copied CTF writer structure field type: original-ft-addr=%p, copy-ft-addr=%p",
}
/* Copy field_name_to_index */
- g_hash_table_iter_init(&iter, var_ft->field_name_to_index);
+ g_hash_table_iter_init(&iter, var_ft->choice_name_to_index);
while (g_hash_table_iter_next(&iter, &key, &value)) {
- g_hash_table_insert(copy_ft->field_name_to_index,
+ g_hash_table_insert(copy_ft->choice_name_to_index,
key, value);
}
- for (i = 0; i < var_ft->fields->len; i++) {
- struct structure_field_common *entry, *copy_entry;
+ g_array_set_size(copy_ft->choices, var_ft->choices->len);
+
+ for (i = 0; i < var_ft->choices->len; i++) {
+ struct bt_field_type_common_variant_choice *entry, *copy_entry;
struct bt_field_type_common *field_ft_copy;
+ uint64_t range_i;
- entry = g_ptr_array_index(var_ft->fields, i);
+ entry = BT_FIELD_TYPE_COMMON_VARIANT_CHOICE_AT_INDEX(var_ft, i);
+ copy_entry = BT_FIELD_TYPE_COMMON_VARIANT_CHOICE_AT_INDEX(
+ copy_ft, i);
BT_LOGD("Copying CTF writer variant field type's field: "
"index=%" PRId64 ", "
"field-ft-addr=%p, field-name=\"%s\"",
i, entry, g_quark_to_string(entry->name));
- copy_entry = g_new0(struct structure_field_common, 1);
- if (!copy_entry) {
- BT_LOGE_STR("Failed to allocate one variant field type field.");
- goto error;
- }
field_ft_copy = (void *) bt_ctf_field_type_copy(
(void *) entry->type);
copy_entry->name = entry->name;
copy_entry->type = field_ft_copy;
- g_ptr_array_add(copy_ft->fields, copy_entry);
+
+ /* Copy ranges */
+ copy_entry->ranges = g_array_new(FALSE, TRUE,
+ sizeof(struct bt_field_type_common_variant_choice_range));
+ BT_ASSERT(copy_entry->ranges);
+ g_array_set_size(copy_entry->ranges, entry->ranges->len);
+
+ for (range_i = 0; range_i < entry->ranges->len; range_i++) {
+ copy_entry->ranges[range_i] = entry->ranges[range_i];
+ }
}
if (var_ft->tag_field_path) {
}
}
- BT_LOGD("Copied variant field type: original-ft-addr=%p, copy-ft-addr=%p",
+ copy_ft->choices_up_to_date = var_ft->choices_up_to_date;
+ BT_LOGD("Copied CTF writer variant field type: original-ft-addr=%p, copy-ft-addr=%p",
ft, copy_ft);
end:
#include <stdlib.h>
static struct bt_field_common_methods bt_ctf_field_integer_methods = {
- .freeze = bt_field_common_generic_freeze,
+ .set_is_frozen = bt_field_common_generic_set_is_frozen,
.validate = bt_field_common_generic_validate,
.copy = NULL,
.is_set = bt_field_common_generic_is_set,
};
static struct bt_field_common_methods bt_ctf_field_floating_point_methods = {
- .freeze = bt_field_common_generic_freeze,
+ .set_is_frozen = bt_field_common_generic_set_is_frozen,
.validate = bt_field_common_generic_validate,
.copy = NULL,
.is_set = bt_field_common_generic_is_set,
.reset = bt_field_common_generic_reset,
};
+static
+void bt_ctf_field_enumeration_set_is_frozen_recursive(
+ struct bt_field_common *field, bool is_frozen);
+
+static
+int bt_ctf_field_enumeration_validate_recursive(struct bt_field_common *field);
+
+static
+bt_bool bt_ctf_field_enumeration_is_set_recursive(
+ struct bt_field_common *field);
+
+static
+void bt_ctf_field_enumeration_reset_recursive(struct bt_field_common *field);
+
static struct bt_field_common_methods bt_ctf_field_enumeration_methods = {
- .freeze = bt_field_common_enumeration_freeze_recursive,
- .validate = bt_field_common_enumeration_validate_recursive,
+ .set_is_frozen = bt_ctf_field_enumeration_set_is_frozen_recursive,
+ .validate = bt_ctf_field_enumeration_validate_recursive,
.copy = NULL,
- .is_set = bt_field_common_enumeration_is_set_recursive,
- .reset = bt_field_common_enumeration_reset_recursive,
+ .is_set = bt_ctf_field_enumeration_is_set_recursive,
+ .reset = bt_ctf_field_enumeration_reset_recursive,
};
static struct bt_field_common_methods bt_ctf_field_string_methods = {
- .freeze = bt_field_common_generic_freeze,
+ .set_is_frozen = bt_field_common_generic_set_is_frozen,
.validate = bt_field_common_generic_validate,
.copy = NULL,
.is_set = bt_field_common_generic_is_set,
};
static struct bt_field_common_methods bt_ctf_field_structure_methods = {
- .freeze = bt_field_common_structure_freeze_recursive,
+ .set_is_frozen = bt_field_common_structure_set_is_frozen_recursive,
.validate = bt_field_common_structure_validate_recursive,
.copy = NULL,
.is_set = bt_field_common_structure_is_set_recursive,
};
static struct bt_field_common_methods bt_ctf_field_sequence_methods = {
- .freeze = bt_field_common_sequence_freeze_recursive,
+ .set_is_frozen = bt_field_common_sequence_set_is_frozen_recursive,
.validate = bt_field_common_sequence_validate_recursive,
.copy = NULL,
.is_set = bt_field_common_sequence_is_set_recursive,
};
static struct bt_field_common_methods bt_ctf_field_array_methods = {
- .freeze = bt_field_common_array_freeze_recursive,
+ .set_is_frozen = bt_field_common_array_set_is_frozen_recursive,
.validate = bt_field_common_array_validate_recursive,
.copy = NULL,
.is_set = bt_field_common_array_is_set_recursive,
.reset = bt_field_common_array_reset_recursive,
};
+static
+void bt_ctf_field_variant_set_is_frozen_recursive(struct bt_field_common *field,
+ bool is_frozen);
+
+static
+int bt_ctf_field_variant_validate_recursive(struct bt_field_common *field);
+
+static
+bt_bool bt_ctf_field_variant_is_set_recursive(struct bt_field_common *field);
+
+static
+void bt_ctf_field_variant_reset_recursive(struct bt_field_common *field);
+
static struct bt_field_common_methods bt_ctf_field_variant_methods = {
- .freeze = bt_field_common_variant_freeze_recursive,
- .validate = bt_field_common_variant_validate_recursive,
+ .set_is_frozen = bt_ctf_field_variant_set_is_frozen_recursive,
+ .validate = bt_ctf_field_variant_validate_recursive,
.copy = NULL,
- .is_set = bt_field_common_variant_is_set_recursive,
- .reset = bt_field_common_variant_reset_recursive,
+ .is_set = bt_ctf_field_variant_is_set_recursive,
+ .reset = bt_ctf_field_variant_reset_recursive,
};
static
struct bt_field_common *, struct bt_ctf_stream_pos *,
enum bt_ctf_byte_order);
+static
+void bt_ctf_field_integer_destroy(struct bt_ctf_field *field)
+{
+ BT_LOGD("Destroying CTF writer integer field object: addr=%p", field);
+ bt_field_common_integer_finalize((void *) field);
+ g_free(field);
+}
+
+static
+void bt_ctf_field_floating_point_destroy(struct bt_ctf_field *field)
+{
+ BT_LOGD("Destroying CTF writer floating point field object: addr=%p",
+ field);
+ bt_field_common_floating_point_finalize((void *) field);
+ g_free(field);
+}
+
+static
+void bt_ctf_field_enumeration_destroy_recursive(struct bt_ctf_field *field)
+{
+ struct bt_ctf_field_enumeration *enumeration = BT_FROM_COMMON(field);
+
+ BT_LOGD("Destroying CTF writer enumeration field object: addr=%p",
+ field);
+ BT_LOGD_STR("Putting container field.");
+ bt_put(enumeration->container);
+ bt_field_common_finalize((void *) field);
+ g_free(field);
+}
+
+static
+void bt_ctf_field_structure_destroy_recursive(struct bt_ctf_field *field)
+{
+ BT_LOGD("Destroying CTF writer structure field object: addr=%p", field);
+ bt_field_common_structure_finalize_recursive((void *) field);
+ g_free(field);
+}
+
+static
+void bt_ctf_field_variant_destroy_recursive(struct bt_ctf_field *field)
+{
+ struct bt_ctf_field_variant *variant = BT_FROM_COMMON(field);
+
+ BT_LOGD("Destroying CTF writer variant field object: addr=%p", field);
+ BT_LOGD_STR("Putting tag field.");
+ bt_put(variant->tag);
+ bt_field_common_variant_finalize_recursive((void *) field);
+ g_free(field);
+}
+
+static
+void bt_ctf_field_array_destroy_recursive(struct bt_ctf_field *field)
+{
+ BT_LOGD("Destroying CTF writer array field object: addr=%p", field);
+ bt_field_common_array_finalize_recursive((void *) field);
+ g_free(field);
+}
+
+static
+void bt_ctf_field_sequence_destroy_recursive(struct bt_ctf_field *field)
+{
+ BT_LOGD("Destroying CTF writer sequence field object: addr=%p", field);
+ bt_field_common_sequence_finalize_recursive((void *) field);
+ g_free(field);
+}
+
+static
+void bt_ctf_field_string_destroy(struct bt_ctf_field *field)
+{
+ BT_LOGD("Destroying CTF writer string field object: addr=%p", field);
+ bt_field_common_string_finalize((void *) field);
+ g_free(field);
+}
+
BT_HIDDEN
int bt_ctf_field_serialize_recursive(struct bt_ctf_field *field,
struct bt_ctf_stream_pos *pos,
struct bt_ctf_stream_pos *pos,
enum bt_ctf_byte_order native_byte_order)
{
- struct bt_field_common_enumeration *enumeration = BT_FROM_COMMON(field);
+ struct bt_ctf_field_enumeration *enumeration = (void *) field;
BT_LOGV("Serializing enumeration field: addr=%p, pos-offset=%" PRId64 ", "
"native-bo=%s", field, pos->offset,
bt_common_byte_order_string((int) native_byte_order));
BT_LOGV_STR("Serializing enumeration field's payload field.");
- return bt_ctf_field_serialize_recursive((void *) enumeration->payload,
- pos, native_byte_order);
+ return bt_ctf_field_serialize_recursive(
+ (void *) enumeration->container, pos, native_byte_order);
}
static
bt_common_byte_order_string((int) native_byte_order));
BT_LOGV_STR("Serializing variant field's payload field.");
return bt_ctf_field_serialize_recursive(
- (void *) variant->payload, pos, native_byte_order);
+ (void *) variant->current_field, pos, native_byte_order);
}
static
return (int) field_common->type->id;
}
-struct bt_ctf_field *bt_ctf_field_sequence_get_length(
- struct bt_ctf_field *field)
-{
- return bt_get(bt_field_common_sequence_borrow_length((void *) field));
-}
-
int bt_ctf_field_sequence_set_length(struct bt_ctf_field *field,
struct bt_ctf_field *length_field)
{
+ int ret;
+ struct bt_field_common *common_length_field = (void *) length_field;
+ uint64_t length;
+
+ BT_ASSERT_PRE_NON_NULL(length_field, "Length field");
+ BT_ASSERT_PRE_FIELD_COMMON_IS_SET((void *) length_field, "Length field");
+ BT_ASSERT_PRE(common_length_field->type->id == BT_CTF_FIELD_TYPE_ID_INTEGER ||
+ common_length_field->type->id == BT_CTF_FIELD_TYPE_ID_ENUM,
+ "Length field must be an integer or enumeration field: %!+wf",
+ length_field);
+
+ if (common_length_field->type->id == BT_CTF_FIELD_TYPE_ID_ENUM) {
+ struct bt_ctf_field_enumeration *enumeration = (void *)
+ length_field;
+
+ length_field = (void *) enumeration->container;
+ }
+
+ ret = bt_ctf_field_integer_unsigned_get_value(length_field, &length);
+ BT_ASSERT(ret == 0);
return bt_field_common_sequence_set_length((void *) field,
- (void *) length_field);
+ length, (bt_field_common_create_func) bt_ctf_field_create);
}
struct bt_ctf_field *bt_ctf_field_structure_get_field_by_index(
(void *) field, name));
}
-int bt_ctf_field_structure_set_field_by_name(struct bt_ctf_field *field,
- const char *name, struct bt_ctf_field *value)
-{
- return bt_field_common_structure_set_field_by_name((void *) field,
- name, (void *) value);
-}
-
struct bt_ctf_field *bt_ctf_field_array_get_field(
struct bt_ctf_field *field, uint64_t index)
{
- return bt_get(bt_field_common_array_borrow_field((void *) field, index,
- (bt_field_common_create_func) bt_ctf_field_create));
+ return bt_get(
+ bt_field_common_array_borrow_field((void *) field, index));
}
struct bt_ctf_field *bt_ctf_field_sequence_get_field(
struct bt_ctf_field *field, uint64_t index)
{
- return bt_get(bt_field_common_sequence_borrow_field((void *) field,
- index, (bt_field_common_create_func) bt_ctf_field_create));
+ return bt_get(
+ bt_field_common_sequence_borrow_field((void *) field, index));
}
struct bt_ctf_field *bt_ctf_field_variant_get_field(struct bt_ctf_field *field,
struct bt_ctf_field *tag_field)
{
- return bt_get(bt_field_common_variant_borrow_field((void *) field,
- (void *) tag_field,
- (bt_field_common_create_func) bt_ctf_field_create));
+ struct bt_ctf_field_variant *variant_field = (void *) field;
+ struct bt_ctf_field_enumeration *enum_field = (void *) tag_field;
+ struct bt_field_type_common_variant *variant_ft;
+ struct bt_field_type_common_enumeration *tag_ft;
+ struct bt_ctf_field *current_field = NULL;
+ bt_bool is_signed;
+ uint64_t tag_uval;
+ int ret;
+
+ BT_ASSERT_PRE_NON_NULL(field, "Variant field");
+ BT_ASSERT_PRE_NON_NULL(tag_field, "Tag field");
+ BT_ASSERT_PRE_FIELD_COMMON_IS_SET((void *) tag_field, "Tag field");
+ BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(
+ (struct bt_field_common *) tag_field,
+ BT_FIELD_TYPE_ID_ENUM, "Tag field");
+ BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(
+ (struct bt_field_common *) field,
+ BT_FIELD_TYPE_ID_VARIANT, "Field");
+ BT_ASSERT_PRE(
+ bt_field_common_validate_recursive((void *) tag_field) == 0,
+ "Tag field is invalid: %!+wf", tag_field);
+ variant_ft = BT_FROM_COMMON(variant_field->common.common.type);
+ BT_ASSERT_PRE(bt_field_type_common_compare(
+ BT_TO_COMMON(variant_ft->tag_ft), enum_field->common.type) == 0,
+ "Unexpected tag field's type: %![expected-ft-]+wF, "
+ "%![tag-ft-]+wF", variant_ft->tag_ft,
+ enum_field->common.type);
+ tag_ft = BT_FROM_COMMON(enum_field->common.type);
+ is_signed = tag_ft->container_ft->is_signed;
+
+ if (is_signed) {
+ int64_t tag_ival;
+
+ ret = bt_ctf_field_integer_signed_get_value(
+ (void *) enum_field->container, &tag_ival);
+ tag_uval = (uint64_t) tag_ival;
+ } else {
+ ret = bt_ctf_field_integer_unsigned_get_value(
+ (void *) enum_field->container, &tag_uval);
+ }
+
+ BT_ASSERT(ret == 0);
+ ret = bt_field_variant_common_set_tag((void *) field, tag_uval,
+ is_signed);
+ if (ret) {
+ goto end;
+ }
+
+ bt_put(variant_field->tag);
+ variant_field->tag = bt_get(tag_field);
+ current_field = bt_ctf_field_variant_get_current_field(field);
+ BT_ASSERT(current_field);
+
+end:
+ return current_field;
}
struct bt_ctf_field *bt_ctf_field_variant_get_current_field(
(void *) variant_field));
}
-struct bt_ctf_field *bt_ctf_field_variant_get_tag(
- struct bt_ctf_field *variant_field)
+BT_HIDDEN
+struct bt_ctf_field *bt_ctf_field_enumeration_borrow_container(
+ struct bt_ctf_field *field)
{
- return bt_get(bt_field_common_variant_borrow_tag(
- (void *) variant_field));
+ struct bt_ctf_field_enumeration *enumeration = (void *) field;
+
+ BT_ASSERT_PRE_NON_NULL(field, "Enumeration field");
+ BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID((struct bt_field_common *) field,
+ BT_CTF_FIELD_TYPE_ID_ENUM, "Field");
+ BT_ASSERT(enumeration->container);
+ return (void *) enumeration->container;
}
-struct bt_ctf_field *bt_ctf_field_enumeration_get_container(struct bt_ctf_field *field)
+struct bt_ctf_field *bt_ctf_field_enumeration_get_container(
+ struct bt_ctf_field *field)
{
- return bt_get(bt_field_common_enumeration_borrow_container(
- (void *) field,
- (bt_field_common_create_func) bt_ctf_field_create));
+ return bt_get(bt_ctf_field_enumeration_borrow_container(field));
}
-int bt_ctf_field_integer_signed_get_value(struct bt_ctf_field *field, int64_t *value)
+int bt_ctf_field_integer_signed_get_value(struct bt_ctf_field *field,
+ int64_t *value)
{
- return bt_field_common_integer_signed_get_value((void *) field, value);
+ struct bt_field_common_integer *integer = (void *) field;
+
+ BT_ASSERT_PRE_NON_NULL(field, "Integer field");
+ BT_ASSERT_PRE_NON_NULL(value, "Value");
+ BT_ASSERT_PRE_FIELD_COMMON_IS_SET(BT_TO_COMMON(integer), "Integer field");
+ BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(BT_TO_COMMON(integer),
+ BT_FIELD_TYPE_ID_INTEGER, "Field");
+ BT_ASSERT_PRE(bt_field_type_common_integer_is_signed(
+ integer->common.type),
+ "Field's type is unsigned: %!+_f", field);
+ *value = integer->payload.signd;
+ return 0;
}
int bt_ctf_field_integer_signed_set_value(struct bt_ctf_field *field,
int64_t value)
{
- return bt_field_common_integer_signed_set_value((void *) field, value);
+ int ret = 0;
+ struct bt_field_common_integer *integer = (void *) field;
+ struct bt_field_type_common_integer *integer_type;
+
+ BT_ASSERT_PRE_NON_NULL(field, "Integer field");
+ BT_ASSERT_PRE_FIELD_COMMON_HOT(BT_TO_COMMON(integer), "Integer field");
+ BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(BT_TO_COMMON(integer),
+ BT_FIELD_TYPE_ID_INTEGER, "Field");
+ integer_type = BT_FROM_COMMON(integer->common.type);
+ BT_ASSERT_PRE(
+ bt_field_type_common_integer_is_signed(integer->common.type),
+ "Field's type is unsigned: %!+wf", field);
+ BT_ASSERT_PRE(value_is_in_range_signed(integer_type->size, value),
+ "Value is out of bounds: value=%" PRId64 ", %![field-]+wf",
+ value, field);
+ integer->payload.signd = value;
+ bt_field_common_set(BT_TO_COMMON(integer), true);
+ return ret;
}
int bt_ctf_field_integer_unsigned_get_value(struct bt_ctf_field *field,
uint64_t *value)
{
- return bt_field_common_integer_unsigned_get_value((void *) field,
- value);
+ struct bt_field_common_integer *integer = (void *) field;
+
+ BT_ASSERT_PRE_NON_NULL(field, "Integer field");
+ BT_ASSERT_PRE_NON_NULL(value, "Value");
+ BT_ASSERT_PRE_FIELD_COMMON_IS_SET(BT_TO_COMMON(integer), "Integer field");
+ BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(BT_TO_COMMON(integer),
+ BT_FIELD_TYPE_ID_INTEGER, "Field");
+ BT_ASSERT_PRE(
+ !bt_field_type_common_integer_is_signed(integer->common.type),
+ "Field's type is signed: %!+wf", field);
+ *value = integer->payload.unsignd;
+ return 0;
}
-int bt_ctf_field_integer_unsigned_set_value(struct bt_ctf_field *field, uint64_t value)
+int bt_ctf_field_integer_unsigned_set_value(struct bt_ctf_field *field,
+ uint64_t value)
{
- return bt_field_common_integer_unsigned_set_value((void *) field, value);
+ struct bt_field_common_integer *integer = (void *) field;
+ struct bt_field_type_common_integer *integer_type;
+
+ BT_ASSERT_PRE_NON_NULL(field, "Integer field");
+ BT_ASSERT_PRE_FIELD_COMMON_HOT(BT_TO_COMMON(integer), "Integer field");
+ BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(BT_TO_COMMON(integer),
+ BT_FIELD_TYPE_ID_INTEGER, "Field");
+ integer_type = BT_FROM_COMMON(integer->common.type);
+ BT_ASSERT_PRE(
+ !bt_field_type_common_integer_is_signed(integer->common.type),
+ "Field's type is signed: %!+wf", field);
+ BT_ASSERT_PRE(value_is_in_range_unsigned(integer_type->size, value),
+ "Value is out of bounds: value=%" PRIu64 ", %![field-]+wf",
+ value, field);
+ integer->payload.unsignd = value;
+ bt_field_common_set(BT_TO_COMMON(integer), true);
+ return 0;
}
int bt_ctf_field_floating_point_get_value(struct bt_ctf_field *field,
if (integer) {
bt_field_common_initialize(BT_TO_COMMON(integer), (void *) type,
- bt_field_common_integer_destroy,
+ (bt_object_release_func) bt_ctf_field_integer_destroy,
&bt_ctf_field_integer_methods);
integer->common.spec.writer.serialize_func =
(bt_ctf_field_serialize_recursive_func) bt_ctf_field_integer_serialize;
struct bt_ctf_field *bt_ctf_field_enumeration_create(
struct bt_ctf_field_type *type)
{
- struct bt_field_common_enumeration *enumeration = g_new0(
- struct bt_field_common_enumeration, 1);
+ struct bt_field_type_common_enumeration *enum_ft = (void *) type;
+ struct bt_ctf_field_enumeration *enumeration = g_new0(
+ struct bt_ctf_field_enumeration, 1);
BT_LOGD("Creating CTF writer enumeration field object: ft-addr=%p", type);
- if (enumeration) {
- bt_field_common_initialize(BT_TO_COMMON(enumeration),
- (void *) type,
- bt_field_common_enumeration_destroy_recursive,
- &bt_ctf_field_enumeration_methods);
- enumeration->common.spec.writer.serialize_func =
- (bt_ctf_field_serialize_recursive_func) bt_ctf_field_enumeration_serialize_recursive;
- BT_LOGD("Created CTF writer enumeration field object: addr=%p, ft-addr=%p",
- enumeration, type);
- } else {
+ if (!enumeration) {
BT_LOGE_STR("Failed to allocate one enumeration field.");
+ goto end;
}
+ bt_field_common_initialize(BT_TO_COMMON(enumeration),
+ (void *) type,
+ (bt_object_release_func)
+ bt_ctf_field_enumeration_destroy_recursive,
+ &bt_ctf_field_enumeration_methods);
+ enumeration->container = (void *) bt_ctf_field_create(
+ BT_FROM_COMMON(enum_ft->container_ft));
+ if (!enumeration->container) {
+ BT_PUT(enumeration);
+ goto end;
+ }
+
+ enumeration->common.spec.writer.serialize_func =
+ (bt_ctf_field_serialize_recursive_func)
+ bt_ctf_field_enumeration_serialize_recursive;
+ BT_LOGD("Created CTF writer enumeration field object: addr=%p, ft-addr=%p",
+ enumeration, type);
+
+end:
return (void *) enumeration;
}
if (floating_point) {
bt_field_common_initialize(BT_TO_COMMON(floating_point),
(void *) type,
- bt_field_common_floating_point_destroy,
+ (bt_object_release_func)
+ bt_ctf_field_floating_point_destroy,
&bt_ctf_field_floating_point_methods);
floating_point->common.spec.writer.serialize_func =
(bt_ctf_field_serialize_recursive_func) bt_ctf_field_floating_point_serialize;
}
iret = bt_field_common_structure_initialize(BT_TO_COMMON(structure),
- (void *) type, bt_field_common_structure_destroy_recursive,
+ (void *) type,
+ (bt_object_release_func)
+ bt_ctf_field_structure_destroy_recursive,
&bt_ctf_field_structure_methods,
- (bt_field_common_create_func) bt_ctf_field_create);
+ (bt_field_common_create_func) bt_ctf_field_create,
+ (GDestroyNotify) bt_put);
structure->common.spec.writer.serialize_func =
(bt_ctf_field_serialize_recursive_func) bt_ctf_field_structure_serialize_recursive;
if (iret) {
static
struct bt_ctf_field *bt_ctf_field_variant_create(struct bt_ctf_field_type *type)
{
- struct bt_field_common_variant *variant = g_new0(
- struct bt_field_common_variant, 1);
+ struct bt_field_type_common_variant *var_ft = (void *) type;
+ struct bt_ctf_field_variant *variant = g_new0(
+ struct bt_ctf_field_variant, 1);
BT_LOGD("Creating CTF writer variant field object: ft-addr=%p", type);
- if (variant) {
- bt_field_common_initialize(BT_TO_COMMON(variant),
- (void *) type,
- bt_field_common_variant_destroy_recursive,
- &bt_ctf_field_variant_methods);
- variant->common.spec.writer.serialize_func =
- (bt_ctf_field_serialize_recursive_func) bt_ctf_field_variant_serialize_recursive;
- BT_LOGD("Created CTF writer variant field object: addr=%p, ft-addr=%p",
- variant, type);
- } else {
+ if (!variant) {
BT_LOGE_STR("Failed to allocate one variant field.");
+ goto end;
}
+ bt_field_common_variant_initialize(BT_TO_COMMON(BT_TO_COMMON(variant)),
+ (void *) type,
+ (bt_object_release_func)
+ bt_ctf_field_variant_destroy_recursive,
+ &bt_ctf_field_variant_methods,
+ (bt_field_common_create_func) bt_ctf_field_create,
+ (GDestroyNotify) bt_put);
+ variant->tag = (void *) bt_ctf_field_create(
+ BT_FROM_COMMON(var_ft->tag_ft));
+ variant->common.common.spec.writer.serialize_func =
+ (bt_ctf_field_serialize_recursive_func) bt_ctf_field_variant_serialize_recursive;
+ BT_LOGD("Created CTF writer variant field object: addr=%p, ft-addr=%p",
+ variant, type);
+
+end:
return (void *) variant;
}
ret = bt_field_common_array_initialize(BT_TO_COMMON(array),
(void *) type,
- bt_field_common_array_destroy_recursive,
- &bt_ctf_field_array_methods);
+ (bt_object_release_func)
+ bt_ctf_field_array_destroy_recursive,
+ &bt_ctf_field_array_methods,
+ (bt_field_common_create_func) bt_ctf_field_create,
+ (GDestroyNotify) bt_put);
array->common.spec.writer.serialize_func =
(bt_ctf_field_serialize_recursive_func) bt_ctf_field_array_serialize_recursive;
if (ret) {
BT_LOGD("Creating CTF writer sequence field object: ft-addr=%p", type);
if (sequence) {
- bt_field_common_initialize(BT_TO_COMMON(sequence),
+ bt_field_common_sequence_initialize(BT_TO_COMMON(sequence),
(void *) type,
- bt_field_common_sequence_destroy_recursive,
- &bt_ctf_field_sequence_methods);
+ (bt_object_release_func)
+ bt_ctf_field_sequence_destroy_recursive,
+ &bt_ctf_field_sequence_methods,
+ (GDestroyNotify) bt_put);
sequence->common.spec.writer.serialize_func =
(bt_ctf_field_serialize_recursive_func) bt_ctf_field_sequence_serialize_recursive;
BT_LOGD("Created CTF writer sequence field object: addr=%p, ft-addr=%p",
if (string) {
bt_field_common_initialize(BT_TO_COMMON(string),
(void *) type,
- bt_field_common_string_destroy,
+ (bt_object_release_func)
+ bt_ctf_field_string_destroy,
&bt_ctf_field_string_methods);
string->common.spec.writer.serialize_func =
(bt_ctf_field_serialize_recursive_func) bt_ctf_field_string_serialize;
return (void *) string;
}
+
+static
+void bt_ctf_field_enumeration_set_is_frozen_recursive(
+ struct bt_field_common *field, bool is_frozen)
+{
+ struct bt_ctf_field_enumeration *enumeration = (void *) field;
+
+ if (enumeration->container) {
+ bt_field_common_set_is_frozen_recursive(
+ (void *) enumeration->container, is_frozen);
+ }
+
+ bt_field_common_generic_set_is_frozen((void *) field, is_frozen);
+}
+
+static
+int bt_ctf_field_enumeration_validate_recursive(struct bt_field_common *field)
+{
+ int ret = -1;
+ struct bt_ctf_field_enumeration *enumeration = (void *) field;
+
+ if (enumeration->container) {
+ ret = bt_field_common_validate_recursive(
+ (void *) enumeration->container);
+ }
+
+ return ret;
+}
+
+static
+bt_bool bt_ctf_field_enumeration_is_set_recursive(struct bt_field_common *field)
+{
+ bt_bool is_set = BT_FALSE;
+ struct bt_ctf_field_enumeration *enumeration = (void *) field;
+
+ if (enumeration->container) {
+ is_set = bt_field_common_is_set_recursive(
+ (void *) enumeration->container);
+ }
+
+ return is_set;
+}
+
+static
+void bt_ctf_field_enumeration_reset_recursive(struct bt_field_common *field)
+{
+ struct bt_ctf_field_enumeration *enumeration = (void *) field;
+
+ if (enumeration->container) {
+ bt_field_common_reset_recursive(
+ (void *) enumeration->container);
+ }
+
+ bt_field_common_generic_reset((void *) field);
+}
+
+static
+void bt_ctf_field_variant_set_is_frozen_recursive(
+ struct bt_field_common *field, bool is_frozen)
+{
+ struct bt_ctf_field_variant *variant = (void *) field;
+
+ if (variant->tag) {
+ bt_field_common_set_is_frozen_recursive(
+ (void *) variant->tag, is_frozen);
+ }
+
+ bt_field_common_variant_set_is_frozen_recursive((void *) field,
+ is_frozen);
+}
+
+static
+int bt_ctf_field_variant_validate_recursive(struct bt_field_common *field)
+{
+ int ret;
+ struct bt_ctf_field_variant *variant = (void *) field;
+
+ if (variant->tag) {
+ ret = bt_field_common_validate_recursive(
+ (void *) variant->tag);
+ if (ret) {
+ goto end;
+ }
+ }
+
+ ret = bt_field_common_variant_validate_recursive((void *) field);
+
+end:
+ return ret;
+}
+
+static
+bt_bool bt_ctf_field_variant_is_set_recursive(struct bt_field_common *field)
+{
+ bt_bool is_set;
+ struct bt_ctf_field_variant *variant = (void *) field;
+
+ if (variant->tag) {
+ is_set = bt_field_common_is_set_recursive(
+ (void *) variant->tag);
+ if (is_set) {
+ goto end;
+ }
+ }
+
+ is_set = bt_field_common_variant_is_set_recursive((void *) field);
+
+end:
+ return is_set;
+}
+
+static
+void bt_ctf_field_variant_reset_recursive(struct bt_field_common *field)
+{
+ struct bt_ctf_field_variant *variant = (void *) field;
+
+ if (variant->tag) {
+ bt_field_common_reset_recursive(
+ (void *) variant->tag);
+ }
+
+ bt_field_common_variant_reset_recursive((void *) field);
+}
+
+BT_ASSERT_PRE_FUNC
+static inline bool field_to_set_has_expected_type(
+ struct bt_field_common *struct_field,
+ const char *name, struct bt_field_common *value)
+{
+ bool ret = true;
+ struct bt_field_type_common *expected_field_type = NULL;
+
+ expected_field_type =
+ bt_field_type_common_structure_borrow_field_type_by_name(
+ struct_field->type, name);
+
+ if (bt_field_type_common_compare(expected_field_type, value->type)) {
+ BT_ASSERT_PRE_MSG("Value field's type is different from the expected field type: "
+ "%![value-ft-]+_F, %![expected-ft-]+_F", value->type,
+ expected_field_type);
+ ret = false;
+ goto end;
+ }
+
+end:
+ return ret;
+}
+
+BT_HIDDEN
+int bt_ctf_field_structure_set_field_by_name(struct bt_ctf_field *field,
+ const char *name, struct bt_ctf_field *value)
+{
+ int ret = 0;
+ GQuark field_quark;
+ struct bt_field_common *common_field = (void *) field;
+ struct bt_field_common_structure *structure =
+ BT_FROM_COMMON(common_field);
+ struct bt_field_common *common_value = (void *) value;
+ size_t index;
+ GHashTable *field_name_to_index;
+ struct bt_field_type_common_structure *structure_ft;
+
+ BT_ASSERT_PRE_NON_NULL(field, "Parent field");
+ BT_ASSERT_PRE_NON_NULL(name, "Field name");
+ BT_ASSERT_PRE_NON_NULL(value, "Value field");
+ BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(common_field,
+ BT_FIELD_TYPE_ID_STRUCT, "Parent field");
+ BT_ASSERT_PRE(field_to_set_has_expected_type(common_field,
+ name, common_value),
+ "Value field's type is different from the expected field type.");
+ field_quark = g_quark_from_string(name);
+ structure_ft = BT_FROM_COMMON(common_field->type);
+ field_name_to_index = structure_ft->field_name_to_index;
+ if (!g_hash_table_lookup_extended(field_name_to_index,
+ GUINT_TO_POINTER(field_quark), NULL,
+ (gpointer *) &index)) {
+ BT_LOGV("Invalid parameter: no such field in structure field's type: "
+ "struct-field-addr=%p, struct-ft-addr=%p, "
+ "field-ft-addr=%p, name=\"%s\"",
+ field, common_field->type, common_value->type, name);
+ ret = -1;
+ goto end;
+ }
+ bt_get(value);
+ BT_MOVE(structure->fields->pdata[index], value);
+
+end:
+ return ret;
+}
case BT_CTF_FIELD_TYPE_ID_SEQUENCE:
{
uint64_t i;
- int64_t len = bt_field_common_sequence_get_int_length(
+ int64_t len = bt_field_common_sequence_get_length(
(void *) field);
if (len < 0) {
stream, bt_ctf_stream_get_name(stream), event);
id_field = bt_ctf_field_structure_get_field_by_name(
- (void *) event->common.header_field, "id");
+ (void *) event->common.header_field->field, "id");
event_class_id = bt_event_class_common_get_id(event->common.class);
BT_ASSERT(event_class_id >= 0);
* 3. The "timestamp" field is not set.
*/
timestamp_field = bt_ctf_field_structure_get_field_by_name(
- (void *) event->common.header_field, "timestamp");
+ (void *) event->common.header_field->field, "timestamp");
if (timestamp_field && stream_class->clock &&
bt_ctf_field_get_type_id(id_field) == BT_CTF_FIELD_TYPE_ID_INTEGER &&
!bt_ctf_field_is_set_recursive(timestamp_field)) {
/* Make sure the various scopes of the event are set */
BT_LOGV_STR("Validating event to append.");
- ret = bt_event_common_validate(BT_TO_COMMON(event));
- if (ret) {
- goto error;
- }
+ BT_ASSERT_PRE(bt_event_common_validate(BT_TO_COMMON(event)) == 0,
+ "Invalid event: %!+we", event);
/* Save the new event and freeze it */
BT_LOGV_STR("Freezing the event to append.");
if (event->common.header_field) {
BT_LOGV_STR("Serializing event's header field.");
ret = bt_ctf_field_serialize_recursive(
- (void *) event->common.header_field,
+ (void *) event->common.header_field->field,
&stream->pos, native_byte_order);
if (ret) {
BT_LOGW("Cannot serialize event's header field: "
"field-addr=%p",
- event->common.header_field);
+ event->common.header_field->field);
goto end;
}
}
(struct bt_notification_event *) obj;
BT_LOGD("Destroying event notification: addr=%p", notification);
- BT_LOGD_STR("Putting event.");
- BT_PUT(notification->event);
+ BT_LOGD_STR("Recycling event.");
+ bt_event_recycle(notification->event);
+ notification->event = NULL;
BT_LOGD_STR("Putting clock class priority map.");
BT_PUT(notification->cc_prio_map);
g_free(notification);
}
-BT_ASSERT_PRE_FUNC static inline
-bt_bool validate_clock_classes(struct bt_notification_event *notif)
-{
- /*
- * For each clock class found in the notification's clock class
- * priority map, make sure the event has a clock value set for
- * this clock class. Also make sure that those clock classes
- * are part of the trace to which the event belongs.
- */
- bt_bool is_valid = BT_TRUE;
-
- int trace_cc_count;
- int cc_prio_map_cc_count;
- size_t cc_prio_map_cc_i, trace_cc_i;
- struct bt_clock_value *clock_value = NULL;
- struct bt_clock_class *clock_class = NULL;
- struct bt_event_class *event_class = NULL;
- struct bt_stream_class *stream_class = NULL;
- struct bt_trace *trace = NULL;
-
- event_class = bt_event_borrow_class(notif->event);
- BT_ASSERT(event_class);
- stream_class = bt_event_class_borrow_stream_class(event_class);
- BT_ASSERT(stream_class);
- trace = bt_stream_class_borrow_trace(stream_class);
- BT_ASSERT(trace);
- trace_cc_count = bt_trace_get_clock_class_count(trace);
- BT_ASSERT(trace_cc_count >= 0);
- cc_prio_map_cc_count =
- bt_clock_class_priority_map_get_clock_class_count(
- notif->cc_prio_map);
- BT_ASSERT(cc_prio_map_cc_count >= 0);
-
- for (cc_prio_map_cc_i = 0; cc_prio_map_cc_i < cc_prio_map_cc_count;
- cc_prio_map_cc_i++) {
- bt_bool found_in_trace = BT_FALSE;
-
- clock_class =
- bt_clock_class_priority_map_get_clock_class_by_index(
- notif->cc_prio_map, cc_prio_map_cc_i);
- BT_ASSERT(clock_class);
- clock_value = bt_event_get_clock_value(notif->event,
- clock_class);
- if (!clock_value) {
- BT_ASSERT_PRE_MSG("Event has no clock value for a clock class which exists in the notification's clock class priority map: "
- "notif-addr=%p, event-addr=%p, "
- "event-class-addr=%p, event-class-name=\"%s\", "
- "event-class-id=%" PRId64 ", "
- "cc-prio-map-addr=%p, "
- "clock-class-addr=%p, clock-class-name=\"%s\"",
- notif, notif->event, event_class,
- bt_event_class_get_name(event_class),
- bt_event_class_get_id(event_class),
- notif->cc_prio_map, clock_class,
- bt_clock_class_get_name(clock_class));
- is_valid = BT_FALSE;
- goto end;
- }
-
- for (trace_cc_i = 0; trace_cc_i < trace_cc_count;
- trace_cc_i++) {
- struct bt_clock_class *trace_clock_class =
- bt_trace_get_clock_class_by_index(trace,
- trace_cc_i);
-
- BT_ASSERT(trace_clock_class);
- bt_put(trace_clock_class);
-
- if (trace_clock_class == clock_class) {
- found_in_trace = BT_TRUE;
- break;
- }
- }
-
- if (!found_in_trace) {
- BT_ASSERT_PRE_MSG("A clock class found in the event notification's clock class priority map does not exist in the notification's event's trace: "
- "notif-addr=%p, trace-addr=%p, "
- "trace-name=\"%s\", cc-prio-map-addr=%p, "
- "clock-class-addr=%p, clock-class-name=\"%s\"",
- notif, trace, bt_trace_get_name(trace),
- notif->cc_prio_map, clock_class,
- bt_clock_class_get_name(clock_class));
- is_valid = BT_FALSE;
- goto end;
- }
-
- BT_PUT(clock_value);
- BT_PUT(clock_class);
- }
-
-end:
- bt_put(clock_value);
- bt_put(clock_class);
- return is_valid;
-}
-
BT_ASSERT_PRE_FUNC
-static inline bool event_has_trace(struct bt_event *event)
+static inline bool event_class_has_trace(struct bt_event_class *event_class)
{
- struct bt_event_class *event_class;
struct bt_stream_class *stream_class;
- event_class = bt_event_borrow_class(event);
- BT_ASSERT(event_class);
stream_class = bt_event_class_borrow_stream_class(event_class);
BT_ASSERT(stream_class);
return bt_stream_class_borrow_trace(stream_class) != NULL;
}
-struct bt_notification *bt_notification_event_create(struct bt_event *event,
+struct bt_notification *bt_notification_event_create(
+ struct bt_event_class *event_class,
+ struct bt_packet *packet,
struct bt_clock_class_priority_map *cc_prio_map)
{
struct bt_notification_event *notification = NULL;
- struct bt_event_class *event_class;
- BT_ASSERT_PRE_NON_NULL(event, "Event");
+ BT_ASSERT_PRE_NON_NULL(event_class, "Event class");
+ BT_ASSERT_PRE_NON_NULL(packet, "Packet");
if (cc_prio_map) {
/* Function's reference, released at the end */
}
BT_ASSERT(cc_prio_map);
- event_class = bt_event_borrow_class(event);
- BT_ASSERT(event_class);
BT_LOGD("Creating event notification object: "
- "event-addr=%p, event-class-addr=%p, "
+ "event-class-addr=%p, "
"event-class-name=\"%s\", event-class-id=%" PRId64 ", "
"cc-prio-map-addr=%p",
- event, event_class,
+ event_class,
bt_event_class_get_name(event_class),
bt_event_class_get_id(event_class), cc_prio_map);
- BT_ASSERT_PRE(bt_event_borrow_packet(event),
- "Event has no packet: %!+e", event);
- BT_ASSERT_PRE(event_has_trace(event),
- "Event has no trace: %!+e", event);
+ BT_ASSERT_PRE(event_class_has_trace(event_class),
+ "Event class is not part of a trace: %!+E", event_class);
notification = g_new0(struct bt_notification_event, 1);
if (!notification) {
BT_LOGE_STR("Failed to allocate one event notification.");
bt_notification_init(¬ification->parent, BT_NOTIFICATION_TYPE_EVENT,
bt_notification_event_destroy);
- notification->event = bt_get(event);
+ notification->event = bt_event_create(event_class, packet);
+ if (!notification->event) {
+ BT_LIB_LOGE("Cannot create event from event class: "
+ "%![event-class-]+E", event_class);
+ goto error;
+ }
+
notification->cc_prio_map = bt_get(cc_prio_map);
- BT_ASSERT_PRE(validate_clock_classes(notification),
- "Invalid clock classes: %![event-]+e", event);
- BT_LOGD_STR("Freezing event notification's event.");
- bt_event_freeze(notification->event);
BT_LOGD_STR("Freezing event notification's clock class priority map.");
bt_clock_class_priority_map_freeze(notification->cc_prio_map);
BT_LOGD("Created event notification object: "
"event-addr=%p, event-class-addr=%p, "
"event-class-name=\"%s\", event-class-id=%" PRId64 ", "
"cc-prio-map-addr=%p, notif-addr=%p",
- event, event_class,
+ notification->event, event_class,
bt_event_class_get_name(event_class),
bt_event_class_get_id(event_class), cc_prio_map,
notification);
{
struct bt_notification_inactivity *notification;
struct bt_notification *ret_notif = NULL;
+ uint64_t i;
if (cc_prio_map) {
/* Function's reference, released at the end */
bt_notification_inactivity_destroy);
ret_notif = ¬ification->parent;
notification->clock_values = g_hash_table_new_full(g_direct_hash,
- g_direct_equal, bt_put, bt_put);
+ g_direct_equal, NULL, (GDestroyNotify) bt_clock_value_recycle);
if (!notification->clock_values) {
BT_LOGE_STR("Failed to allocate a GHashTable.");
goto error;
}
+ for (i = 0; i < cc_prio_map->entries->len; i++) {
+ struct bt_clock_value *clock_value;
+ struct bt_clock_class *clock_class =
+ cc_prio_map->entries->pdata[i];
+
+ clock_value = bt_clock_value_create(clock_class);
+ if (!clock_value) {
+ BT_LIB_LOGE("Cannot create clock value from clock class: "
+ "%![cc-]+K", clock_class);
+ goto error;
+ }
+
+ g_hash_table_insert(notification->clock_values,
+ clock_class, clock_value);
+ }
+
notification->cc_prio_map = bt_get(cc_prio_map);
BT_LOGD_STR("Freezing inactivity notification's clock class priority map.");
bt_clock_class_priority_map_freeze(cc_prio_map);
struct bt_notification_inactivity *inactivity_notification;
BT_ASSERT_PRE_NON_NULL(notification, "Notification");
- BT_ASSERT_PRE_NON_NULL(clock_class, "Clock_class");
+ BT_ASSERT_PRE_NON_NULL(clock_class, "Clock class");
BT_ASSERT_PRE_NOTIF_IS_TYPE(notification,
BT_NOTIFICATION_TYPE_INACTIVITY);
inactivity_notification = container_of(notification,
return g_hash_table_lookup(
inactivity_notification->clock_values, clock_class);
}
-
-BT_ASSERT_PRE_FUNC
-static inline bool cc_prio_map_contains_clock_class(
- struct bt_clock_class_priority_map *cc_prio_map,
- struct bt_clock_class *clock_class)
-{
- int ret = 0;
- uint64_t prio;
-
- ret = bt_clock_class_priority_map_get_clock_class_priority(
- cc_prio_map, clock_class, &prio);
- return ret == 0;
-}
-
-int bt_notification_inactivity_set_clock_value(
- struct bt_notification *notification,
- struct bt_clock_value *clock_value)
-{
- struct bt_notification_inactivity *inactivity_notification;
-
- BT_ASSERT_PRE_NON_NULL(notification, "Notification");
- BT_ASSERT_PRE_NON_NULL(clock_value, "Clock value");
- BT_ASSERT_PRE_HOT(notification, "Notification",
- ": +%!+n", notification);
- BT_ASSERT_PRE_NOTIF_IS_TYPE(notification,
- BT_NOTIFICATION_TYPE_INACTIVITY);
- inactivity_notification = container_of(notification,
- struct bt_notification_inactivity, parent);
- BT_ASSERT_PRE(cc_prio_map_contains_clock_class(
- inactivity_notification->cc_prio_map, clock_value->clock_class),
- "Clock value's class is not mapped to a priority within the scope of the inactivity notification: "
- "notif-addr=%p, cc-prio-map-addr=%p, "
- "clock-class-addr=%p, clock-class-name=\"%s\", "
- "clock-value-addr=%p",
- inactivity_notification,
- inactivity_notification->cc_prio_map,
- clock_value->clock_class,
- bt_clock_class_get_name(clock_value->clock_class), clock_value);
- g_hash_table_insert(inactivity_notification->clock_values,
- clock_value->clock_class, bt_get(clock_value));
- BT_LOGV("Set inactivity notification's clock value: "
- "notif-addr=%p, cc-prio-map-addr=%p, "
- "clock-class-addr=%p, clock-class-name=\"%s\", "
- "clock-value-addr=%p",
- inactivity_notification,
- inactivity_notification->cc_prio_map,
- clock_value->clock_class,
- bt_clock_class_get_name(clock_value->clock_class), clock_value);
- return 0;
-}
#include <glib.h>
#include <babeltrace/common-internal.h>
#include <babeltrace/lib-logging-internal.h>
-#include <babeltrace/object-internal.h>
#include <babeltrace/ref-internal.h>
#include <babeltrace/values-internal.h>
+#include <babeltrace/object-pool-internal.h>
#include <babeltrace/ctf-ir/field-types-internal.h>
#include <babeltrace/ctf-ir/fields-internal.h>
#include <babeltrace/ctf-ir/event-class-internal.h>
BUF_APPEND(", %sref-count=%lu", prefix, obj->ref_count.count);
}
+static inline void format_object_pool(char **buf_ch, bool extended,
+ const char *prefix, struct bt_object_pool *pool)
+{
+ BUF_APPEND(", %ssize=%zu", PRFIELD(pool->size));
+
+ if (pool->objects) {
+ BUF_APPEND(", %scap=%u", PRFIELD(pool->objects->len));
+ }
+}
+
static inline void format_field_type_common(char **buf_ch, bool extended,
const char *prefix, struct bt_field_type_common *field_type)
{
struct bt_field_type_common_variant *variant =
BT_FROM_COMMON(field_type);
- BUF_APPEND(", %stag-name=\"%s\", %stag-ft-addr=%p, "
- "%sfield-count=%u",
+ BUF_APPEND(", %stag-name=\"%s\", %sfield-count=%u",
PRFIELD(variant->tag_name->str),
- PRFIELD(variant->tag_ft), PRFIELD(variant->fields->len));
+ PRFIELD(variant->choices->len));
break;
}
default:
BT_FROM_COMMON(field->type);
const char *fmt = NULL;
+ BT_ASSERT(field_type);
+
if (field_type->base == 8) {
fmt = ", %svalue=%" PRIo64;
} else if (field_type->base == 16) {
BUF_APPEND(", %sis-frozen=%d", PRFIELD(field->frozen));
}
- BUF_APPEND(", %stype-addr=%p, %stype-id=%s",
- PRFIELD(field->type),
+ BUF_APPEND(", %stype-addr=%p", PRFIELD(field->type));
+
+ if (!field->type) {
+ return;
+ }
+
+ BUF_APPEND(", %stype-id=%s",
PRFIELD(bt_common_field_type_id_string(field->type->id)));
if (!extended || field->type->id == BT_FIELD_TYPE_ID_UNKNOWN ||
BUF_APPEND(", %svalue=%f", PRFIELD(flt->payload));
break;
}
- case BT_FIELD_TYPE_ID_ENUM:
- {
- struct bt_field_common_enumeration *enm =
- BT_FROM_COMMON(field);
-
- if (enm->payload) {
- format_field_common_integer_extended(buf_ch, prefix,
- enm->payload);
- }
- break;
- }
case BT_FIELD_TYPE_ID_STRING:
{
struct bt_field_common_string *str =
BT_FROM_COMMON(field);
- BT_ASSERT(str->payload);
- BUF_APPEND(", %spartial-value=\"%.32s\"",
- PRFIELD(str->payload->str));
+ if (str->payload) {
+ BT_ASSERT(str->payload);
+ BUF_APPEND(", %spartial-value=\"%.32s\"",
+ PRFIELD(str->payload->str));
+
+ }
break;
}
case BT_FIELD_TYPE_ID_SEQUENCE:
struct bt_field_common_sequence *seq =
BT_FROM_COMMON(field);
- BUF_APPEND(", %slength-field-addr=%p", PRFIELD(seq->length));
+ BUF_APPEND(", %slength=%" PRIu64, PRFIELD(seq->length));
+
+ if (seq->elements) {
+ BUF_APPEND(", %sallocated-length=%u",
+ PRFIELD(seq->elements->len));
+ }
break;
}
case BT_FIELD_TYPE_ID_VARIANT:
struct bt_field_common_variant *variant =
BT_FROM_COMMON(field);
- BUF_APPEND(", %stag-field-addr=%p, %svalue-field-addr=%p",
- PRFIELD(variant->tag), PRFIELD(variant->payload));
+ BUF_APPEND(", %scur-field-addr=%p",
+ PRFIELD(variant->current_field));
break;
}
default:
static inline void format_field(char **buf_ch, bool extended,
const char *prefix, struct bt_field *field)
{
+ struct bt_field_common *common_field = (void *) field;
+
format_field_common(buf_ch, extended, prefix, (void *) field);
+
+ if (!extended) {
+ return;
+ }
+
+ if (!common_field->type) {
+ return;
+ }
+
+ switch (common_field->type->id) {
+ case BT_FIELD_TYPE_ID_ENUM:
+ {
+ struct bt_field_common_integer *integer = (void *) field;
+ struct bt_field_type_common_enumeration *enum_ft =
+ BT_FROM_COMMON(common_field->type);
+
+ if (enum_ft->container_ft) {
+ if (enum_ft->container_ft->is_signed) {
+ BUF_APPEND(", %svalue=%" PRId64,
+ PRFIELD(integer->payload.signd));
+ } else {
+ BUF_APPEND(", %svalue=%" PRIu64,
+ PRFIELD(integer->payload.unsignd));
+ }
+ }
+ break;
+ }
+ default:
+ break;
+ }
}
static inline void format_writer_field(char **buf_ch, bool extended,
const char *prefix, struct bt_ctf_field *field)
{
+ struct bt_field_common *common_field = (void *) field;
+
format_field_common(buf_ch, extended, prefix, (void *) field);
+
+ if (!extended) {
+ return;
+ }
+
+ if (!common_field->type) {
+ return;
+ }
+
+ switch (common_field->type->id) {
+ case BT_FIELD_TYPE_ID_ENUM:
+ {
+ struct bt_ctf_field_enumeration *enumeration = (void *) field;
+
+ if (enumeration->container) {
+ format_writer_field(buf_ch, extended, prefix,
+ (void *) enumeration->container);
+ }
+ break;
+ }
+ case BT_FIELD_TYPE_ID_VARIANT:
+ {
+ struct bt_ctf_field_variant *variant = (void *) field;
+
+ BUF_APPEND(", %stag-field-addr=%p", PRFIELD(variant->tag));
+ break;
+ }
+ default:
+ break;
+ }
}
static inline void format_field_path(char **buf_ch, bool extended,
{
uint64_t i;
- BT_ASSERT(field_path->indexes);
- BUF_APPEND(", %sindex-count=%u", PRFIELD(field_path->indexes->len));
+ if (field_path->indexes) {
+ BT_ASSERT(field_path->indexes);
+ BUF_APPEND(", %sindex-count=%u", PRFIELD(field_path->indexes->len));
+ }
- if (!extended) {
+ if (!extended || !field_path->indexes) {
return;
}
BUF_APPEND_UUID(trace->uuid);
}
- BUF_APPEND(", %sclock-class-count=%u, %sstream-class-count=%u, "
- "%sstream-count=%u, %spacket-header-ft-addr=%p",
- PRFIELD(trace->clock_classes->len),
- PRFIELD(trace->stream_classes->len),
- PRFIELD(trace->streams->len),
+ if (trace->clock_classes) {
+ BUF_APPEND(", %sclock-class-count=%u",
+ PRFIELD(trace->clock_classes->len));
+ }
+
+ if (trace->stream_classes) {
+ BUF_APPEND(", %sstream-class-count=%u",
+ PRFIELD(trace->stream_classes->len));
+ }
+
+ if (trace->streams) {
+ BUF_APPEND(", %sstream-count=%u",
+ PRFIELD(trace->streams->len));
+ }
+
+ BUF_APPEND(", %spacket-header-ft-addr=%p",
PRFIELD(trace->packet_header_field_type));
}
static inline void format_trace(char **buf_ch, bool extended,
const char *prefix, struct bt_trace *trace)
{
+ char tmp_prefix[64];
+
format_trace_common(buf_ch, extended, prefix, BT_TO_COMMON(trace));
- if (extended) {
- BUF_APPEND(", %sis-static=%d", PRFIELD(trace->is_static));
+ if (!extended) {
+ return;
}
+
+ BUF_APPEND(", %sis-static=%d", PRFIELD(trace->is_static));
+ SET_TMP_PREFIX("phf-pool-");
+ format_object_pool(buf_ch, extended, prefix,
+ &trace->packet_header_field_pool);
}
static inline void format_writer_trace(char **buf_ch, bool extended,
}
BUF_APPEND(", %sis-frozen=%d", PRFIELD(stream_class->frozen));
- BUF_APPEND(", %sevent-class-count=%u, %spacket-context-ft-addr=%p, "
+
+ if (stream_class->event_classes) {
+ BUF_APPEND(", %sevent-class-count=%u",
+ PRFIELD(stream_class->event_classes->len));
+ }
+
+ BUF_APPEND(", %spacket-context-ft-addr=%p, "
"%sevent-header-ft-addr=%p, %sevent-context-ft-addr=%p",
- PRFIELD(stream_class->event_classes->len),
PRFIELD(stream_class->packet_context_field_type),
PRFIELD(stream_class->event_header_field_type),
PRFIELD(stream_class->event_context_field_type));
static inline void format_stream_class(char **buf_ch, bool extended,
const char *prefix, struct bt_stream_class *stream_class)
{
+ char tmp_prefix[64];
+
format_stream_class_common(buf_ch, extended, prefix,
BT_TO_COMMON(stream_class), (format_func) format_trace);
+
+ if (!extended) {
+ return;
+ }
+
+ SET_TMP_PREFIX("ehf-pool-");
+ format_object_pool(buf_ch, extended, prefix,
+ &stream_class->event_header_field_pool);
}
static inline void format_writer_stream_class(char **buf_ch, bool extended,
static inline void format_event_class(char **buf_ch, bool extended,
const char *prefix, struct bt_event_class *event_class)
{
+ char tmp_prefix[64];
+
format_event_class_common(buf_ch, extended, prefix,
BT_TO_COMMON(event_class), (format_func) format_stream_class,
(format_func) format_trace);
+
+ if (!extended) {
+ return;
+ }
+
+ SET_TMP_PREFIX("event-pool-");
+ format_object_pool(buf_ch, extended, prefix, &event_class->event_pool);
}
static inline void format_writer_event_class(char **buf_ch, bool extended,
static inline void format_stream(char **buf_ch, bool extended,
const char *prefix, struct bt_stream *stream)
{
+ char tmp_prefix[64];
+
format_stream_common(buf_ch, extended, prefix, BT_TO_COMMON(stream),
(format_func) format_stream_class,
(format_func) format_trace);
+ SET_TMP_PREFIX("packet-pool-");
+ format_object_pool(buf_ch, extended, prefix, &stream->packet_pool);
}
static inline void format_writer_stream(char **buf_ch, bool extended,
PRFIELD(stream->flushed_packet_count),
PRFIELD(stream->discarded_events),
PRFIELD(stream->size), PRFIELD(stream->last_ts_end));
+
+ if (stream->events) {
+ BUF_APPEND(", %sevent-count=%u", PRFIELD(stream->events->len));
+ }
+
+ BUF_APPEND(", %sheader-field-addr=%p, %scontext-field-addr=%p"
+ ", %sfd=%d, %smmap-offset=%zu, "
+ "%smmap-base-offset=%zu, %spacket-size=%" PRIu64 ", "
+ "%soffset=%" PRId64 ", "
+ "%sflushed-packet-count=%u, "
+ "%sdiscarded-event-count=%" PRIu64 ", "
+ "%ssize=%" PRIu64 ", %slast-ts-end=%" PRIu64,
+ PRFIELD(stream->packet_header),
+ PRFIELD(stream->packet_context),
+ PRFIELD(stream->pos.fd),
+ PRFIELD((size_t) stream->pos.mmap_offset),
+ PRFIELD((size_t) stream->pos.mmap_base_offset),
+ PRFIELD(stream->pos.packet_size),
+ PRFIELD(stream->pos.offset),
+ PRFIELD(stream->flushed_packet_count),
+ PRFIELD(stream->discarded_events),
+ PRFIELD(stream->size), PRFIELD(stream->last_ts_end));
}
static inline void format_packet(char **buf_ch, bool extended,
BUF_APPEND(", %sis-frozen=%d, %sheader-field-addr=%p, "
"%scontext-field-addr=%p",
PRFIELD(packet->frozen),
- PRFIELD(packet->header),
+ PRFIELD(packet->header ? packet->header->field : NULL),
PRFIELD(packet->context));
stream = bt_packet_borrow_stream(packet);
if (!stream) {
"%sstream-context-field-addr=%p, "
"%scontext-field-addr=%p, %spayload-field-addr=%p, ",
PRFIELD(event->frozen),
- PRFIELD(event->header_field),
+ PRFIELD(event->header_field ? event->header_field->field : NULL),
PRFIELD(event->stream_event_context_field),
PRFIELD(event->context_field),
PRFIELD(event->payload_field));
BUF_APPEND(", %sevent-class-addr=%p", PRFIELD(event->class));
+
+ if (!event->class) {
+ return;
+ }
+
SET_TMP_PREFIX("event-class-");
format_event_class_func(buf_ch, false, tmp_prefix, event->class);
stream_class = bt_event_class_common_borrow_stream_class(event->class);
return;
}
- BUF_APPEND(", %sclock-value-count=%u",
- PRFIELD(g_hash_table_size(event->clock_values)));
+ if (event->clock_values) {
+ BUF_APPEND(", %sclock-value-count=%u",
+ PRFIELD(g_hash_table_size(event->clock_values)));
+ }
packet = bt_event_borrow_packet(event);
if (!packet) {
static inline void format_clock_class(char **buf_ch, bool extended,
const char *prefix, struct bt_clock_class *clock_class)
{
+ char tmp_prefix[64];
+
BUF_APPEND(", %sname=\"%s\", %sfreq=%" PRIu64,
PRFIELD(clock_class->name->str),
PRFIELD(clock_class->frequency));
if (clock_class->uuid_set) {
BUF_APPEND_UUID(clock_class->uuid);
}
+
+ SET_TMP_PREFIX("cv-pool-");
+ format_object_pool(buf_ch, extended, prefix, &clock_class->cv_pool);
}
static inline void format_clock_value(char **buf_ch, bool extended,
return;
}
+ BUF_APPEND(", %sis-frozen=%d, %sis-set=%d",
+ PRFIELD(clock_value->frozen), PRFIELD(clock_value->is_set));
BUF_APPEND(", %sclock-class-addr=%p",
PRFIELD(clock_value->clock_class));
SET_TMP_PREFIX("clock-class-");
BUF_APPEND(", %stype=%s, %sname=\"%s\"",
PRFIELD(bt_component_class_type_string(comp_class->type)),
- PRFIELD(comp_class->name->str));
+ PRFIELD(comp_class->name ? comp_class->name->str : NULL));
if (comp_class->description) {
BUF_APPEND(", %spartial-descr=\"%.32s\"",
return;
}
- BUF_APPEND(", %sinput-port-count=%u, %soutput-port-count=%u",
- PRFIELD(component->input_ports ? component->input_ports->len : 0),
- PRFIELD(component->output_ports ? component->output_ports->len : 0));
+ if (component->input_ports) {
+ BUF_APPEND(", %sinput-port-count=%u",
+ PRFIELD(component->input_ports->len));
+ }
+
+ if (component->output_ports) {
+ BUF_APPEND(", %soutput-port-count=%u",
+ PRFIELD(component->output_ports->len));
+ }
}
static inline void format_port(char **buf_ch, bool extended,
return;
}
- BUF_APPEND(", %scomp-count=%u, %sconn-count=%u",
- PRFIELD(graph->components->len),
- PRFIELD(graph->connections->len));
+ if (graph->components) {
+ BUF_APPEND(", %scomp-count=%u",
+ PRFIELD(graph->components->len));
+ }
+
+ if (graph->connections) {
+ BUF_APPEND(", %sconn-count=%u",
+ PRFIELD(graph->connections->len));
+ }
}
static inline void format_notification_iterator(char **buf_ch,
case 'g':
format_graph(buf_ch, extended, prefix, obj);
break;
+ case 'o':
+ format_object_pool(buf_ch, extended, prefix, obj);
+ break;
default:
abort();
}
--- /dev/null
+/*
+ * Copyright (c) 2018 EfficiOS Inc. and Linux Foundation
+ * Copyright (c) 2018 Philippe Proulx <pproulx@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#define BT_LOG_TAG "OBJECT-POOL"
+#include <babeltrace/lib-logging-internal.h>
+
+#include <stdint.h>
+#include <babeltrace/assert-internal.h>
+#include <babeltrace/object-pool-internal.h>
+
+int bt_object_pool_initialize(struct bt_object_pool *pool,
+ bt_object_pool_new_object_func new_object_func,
+ bt_object_pool_destroy_object_func destroy_object_func,
+ void *data)
+{
+ int ret = 0;
+
+ BT_ASSERT(new_object_func);
+ BT_ASSERT(destroy_object_func);
+ BT_LOGD("Initializing object pool: addr=%p, data-addr=%p",
+ pool, data);
+ pool->objects = g_ptr_array_new();
+ if (!pool->objects) {
+ BT_LOGE_STR("Failed to allocate a GPtrArray.");
+ goto error;
+ }
+
+ pool->funcs.new_object = new_object_func;
+ pool->funcs.destroy_object = destroy_object_func;
+ pool->data = data;
+ pool->size = 0;
+ BT_LIB_LOGD("Initialized object pool: %!+o", pool);
+ goto end;
+
+error:
+ if (pool) {
+ bt_object_pool_finalize(pool);
+ }
+
+ ret = -1;
+
+end:
+ return ret;
+}
+
+void bt_object_pool_finalize(struct bt_object_pool *pool)
+{
+ uint64_t i;
+
+ BT_ASSERT(pool);
+ BT_LIB_LOGD("Finalizing object pool: %!+o", pool);
+
+ if (pool->objects) {
+ for (i = 0; i < pool->size; i++) {
+ void *obj = pool->objects->pdata[i];
+
+ if (obj) {
+ pool->funcs.destroy_object(obj, pool->data);
+ }
+ }
+
+ g_ptr_array_free(pool->objects, TRUE);
+ pool->objects = NULL;
+ }
+}
#define BT_LOG_TAG "REF"
#include <babeltrace/lib-logging-internal.h>
+#include <babeltrace/assert-pre-internal.h>
#include <babeltrace/ref-internal.h>
#include <babeltrace/object-internal.h>
goto end;
}
+ BT_ASSERT_PRE(obj->is_shared, "Object is not shared: addr=%p", obj);
+
if (unlikely(!obj->ref_count.release)) {
goto end;
}
return;
}
+ BT_ASSERT_PRE(obj->is_shared, "Object is not shared: addr=%p", obj);
+
if (unlikely(!obj->ref_count.release)) {
return;
}
},
.release = NULL,
.parent = NULL,
+ .is_shared = true,
},
.type = BT_VALUE_TYPE_NULL,
.frozen = BT_TRUE,
-SUBDIRS = ctf text utils
-#libctfcopytrace
+SUBDIRS = text utils ctf
+# libctfcopytrace
if ENABLE_DEBUG_INFO
#SUBDIRS += lttng-utils
*/
enum bt_btr_status {
/** Out of memory. */
- BT_BTR_STATUS_ENOMEM = -5,
+ BT_BTR_STATUS_ENOMEM = -5,
/**
* The binary stream reader reached the end of the user-provided
* buffer, but data is still needed to finish decoding the
BT_BTR_STATUS_EOF = 1,
/** Invalid argument. */
- BT_BTR_STATUS_INVAL = -3,
+ BT_BTR_STATUS_INVAL = -3,
/** General error. */
- BT_BTR_STATUS_ERROR = -1,
+ BT_BTR_STATUS_ERROR = -1,
/** Everything okay. */
BT_BTR_STATUS_OK = 0,
* * sequence
* * variant
*
- * Field is owned by this.
+ * Field is borrowed.
*/
struct bt_field *base;
/*
* Current dynamic scope field pointer.
*
- * This is set when a dynamic scope field is first created by
- * btr_compound_begin_cb(). It points to one of the fields in
- * dscopes below.
+ * This is set by read_dscope_begin_state() and contains the
+ * value of one of the pointers in `dscopes` below.
*/
- struct bt_field **cur_dscope_field;
+ struct bt_field *cur_dscope_field;
/* Trace and classes (owned by this) */
struct {
struct bt_trace *trace;
struct bt_stream_class *stream_class;
struct bt_event_class *event_class;
+ struct bt_clock_class_priority_map *cc_prio_map;
} meta;
+ /* Current packet header field wrapper (NULL if not created yet) */
+ struct bt_packet_header_field *packet_header_field;
+
+ /* Current packet header field wrapper (NULL if not created yet) */
+ struct bt_packet_context_field *packet_context_field;
+
+ /* Current event header field (NULL if not created yet) */
+ struct bt_event_header_field *event_header_field;
+
/* Current packet (NULL if not created yet) */
struct bt_packet *packet;
/* Current stream (NULL if not set yet) */
struct bt_stream *stream;
+ /* Current event (NULL if not created yet) */
+ struct bt_event *event;
+
+ /* Current event notification (NULL if not created yet) */
+ struct bt_notification *event_notif;
+
/*
- * Current timestamp_end field (to consider before switching packets).
+ * Current `timestamp_end` field (to consider before switching
+ * packets). If it's set, it's a field which is within
+ * `dscopes.stream_packet_context` below, which is in `packet`
+ * above.
*/
struct bt_field *cur_timestamp_end;
static
void stack_entry_free_func(gpointer data)
{
- struct stack_entry *entry = data;
-
- bt_put(entry->base);
- g_free(entry);
+ g_free(data);
}
static
goto end;
}
- entry->base = bt_get(base);
+ entry->base = base;
g_ptr_array_add(stack->entries, entry);
end:
struct bt_notif_iter *notit,
struct bt_field_type *dscope_field_type,
enum state done_state, enum state continue_state,
- struct bt_field **dscope_field)
+ struct bt_field *dscope_field)
{
enum bt_notif_iter_status status = BT_NOTIF_ITER_STATUS_OK;
enum bt_btr_status btr_status;
size_t consumed_bits;
- bt_put(*dscope_field);
notit->cur_dscope_field = dscope_field;
BT_LOGV("Starting BTR: notit-addr=%p, btr-addr=%p, ft-addr=%p",
notit, notit->btr, dscope_field_type);
}
static
-void put_event_dscopes(struct bt_notif_iter *notit)
+void release_event_dscopes(struct bt_notif_iter *notit)
{
- BT_LOGV_STR("Putting event header field.");
- BT_PUT(notit->dscopes.stream_event_header);
- BT_LOGV_STR("Putting stream event context field.");
- BT_PUT(notit->dscopes.stream_event_context);
- BT_LOGV_STR("Putting event context field.");
- BT_PUT(notit->dscopes.event_context);
- BT_LOGV_STR("Putting event payload field.");
- BT_PUT(notit->dscopes.event_payload);
+ notit->dscopes.stream_event_header = NULL;
+
+ if (notit->event_header_field) {
+ bt_event_header_field_release(notit->event_header_field);
+ notit->event_header_field = NULL;
+ }
+
+ notit->dscopes.stream_event_context = NULL;
+ notit->dscopes.event_context = NULL;
+ notit->dscopes.event_payload = NULL;
}
static
-void put_all_dscopes(struct bt_notif_iter *notit)
+void release_all_dscopes(struct bt_notif_iter *notit)
{
- BT_LOGV_STR("Putting packet header field.");
- BT_PUT(notit->dscopes.trace_packet_header);
- BT_LOGV_STR("Putting packet context field.");
- BT_PUT(notit->dscopes.stream_packet_context);
- put_event_dscopes(notit);
+ notit->dscopes.trace_packet_header = NULL;
+
+ if (notit->packet_header_field) {
+ bt_packet_header_field_release(notit->packet_header_field);
+ notit->packet_header_field = NULL;
+ }
+
+ notit->dscopes.stream_packet_context = NULL;
+
+ if (notit->packet_context_field) {
+ bt_packet_context_field_release(notit->packet_context_field);
+ notit->packet_context_field = NULL;
+ }
+
+ release_event_dscopes(notit);
}
static
goto end;
}
+ /*
+ * Create free packet header field from trace. This field is
+ * going to be moved to the packet once we create it. We cannot
+ * create the packet now because:
+ *
+ * 1. A packet is created from a stream.
+ * 2. A stream is created from a stream class.
+ * 3. We need the packet header field's content to know the ID
+ * of the stream class to select.
+ */
+ BT_ASSERT(!notit->packet_header_field);
+ notit->packet_header_field = bt_trace_create_packet_header_field(
+ notit->meta.trace);
+ if (!notit->packet_header_field) {
+ BT_LOGE_STR("Cannot create packet header field wrapper from trace.");
+ ret = BT_NOTIF_ITER_STATUS_ERROR;
+ goto end;
+ }
+
+ notit->dscopes.trace_packet_header =
+ bt_packet_header_field_borrow_field(notit->packet_header_field);
+ BT_ASSERT(notit->dscopes.trace_packet_header);
BT_LOGV("Decoding packet header field:"
"notit-addr=%p, trace-addr=%p, trace-name=\"%s\", ft-addr=%p",
notit, notit->meta.trace,
ret = read_dscope_begin_state(notit, packet_header_type,
STATE_AFTER_TRACE_PACKET_HEADER,
STATE_DSCOPE_TRACE_PACKET_HEADER_CONTINUE,
- ¬it->dscopes.trace_packet_header);
+ notit->dscopes.trace_packet_header);
if (ret < 0) {
BT_LOGW("Cannot decode packet header field: "
"notit-addr=%p, trace-addr=%p, "
STATE_AFTER_TRACE_PACKET_HEADER);
}
-static inline
-bool is_struct_type(struct bt_field_type *field_type)
-{
- return bt_field_type_get_type_id(field_type) ==
- BT_FIELD_TYPE_ID_STRUCT;
-}
-
-static inline
-bool is_variant_type(struct bt_field_type *field_type)
-{
- return bt_field_type_get_type_id(field_type) ==
- BT_FIELD_TYPE_ID_VARIANT;
-}
-
static
struct stream_class_field_path_cache *
create_stream_class_field_path_cache_entry(
goto single_stream_class;
}
- BT_ASSERT(is_struct_type(packet_header_type));
+ BT_ASSERT(bt_field_type_is_structure(packet_header_type));
// TODO: optimalize!
stream_id_field_type =
BT_ASSERT(notit->dscopes.trace_packet_header);
// TODO: optimalize!
- stream_id_field = bt_field_structure_get_field_by_name(
+ stream_id_field = bt_field_structure_borrow_field_by_name(
notit->dscopes.trace_packet_header, "stream_id");
BT_ASSERT(stream_id_field);
ret = bt_field_integer_unsigned_get_value(
stream_id_field, &stream_id);
BT_ASSERT(!ret);
- BT_PUT(stream_id_field);
} else {
single_stream_class:
/* Only one stream: pick the first stream class */
return status;
}
+static inline
+uint64_t get_cur_stream_instance_id(struct bt_notif_iter *notit)
+{
+ struct bt_field *stream_instance_id_field = NULL;
+ uint64_t stream_instance_id = -1ULL;
+ int ret;
+
+ if (!notit->dscopes.trace_packet_header) {
+ goto end;
+ }
+
+ stream_instance_id_field = bt_field_structure_borrow_field_by_name(
+ notit->dscopes.trace_packet_header, "stream_instance_id");
+ if (!stream_instance_id_field) {
+ goto end;
+ }
+
+ ret = bt_field_integer_unsigned_get_value(stream_instance_id_field,
+ &stream_instance_id);
+ if (ret) {
+ stream_instance_id = -1ULL;
+ goto end;
+ }
+
+end:
+ return stream_instance_id;
+}
+
+static inline
+enum bt_notif_iter_status set_current_stream(struct bt_notif_iter *notit)
+{
+ enum bt_notif_iter_status status = BT_NOTIF_ITER_STATUS_OK;
+ struct bt_stream *stream = NULL;
+
+ BT_LOGV("Calling user function (get stream): notit-addr=%p, "
+ "stream-class-addr=%p, stream-class-name=\"%s\", "
+ "stream-class-id=%" PRId64,
+ notit, notit->meta.stream_class,
+ bt_stream_class_get_name(notit->meta.stream_class),
+ bt_stream_class_get_id(notit->meta.stream_class));
+ stream = bt_get(notit->medium.medops.borrow_stream(
+ notit->meta.stream_class, get_cur_stream_instance_id(notit),
+ notit->medium.data));
+ BT_LOGV("User function returned: stream-addr=%p", stream);
+ if (!stream) {
+ BT_LOGW_STR("User function failed to return a stream object for the given stream class.");
+ status = BT_NOTIF_ITER_STATUS_ERROR;
+ goto end;
+ }
+
+ if (notit->stream && stream != notit->stream) {
+ BT_LOGW("User function returned a different stream than the previous one for the same sequence of packets.");
+ status = BT_NOTIF_ITER_STATUS_ERROR;
+ goto end;
+ }
+
+ BT_MOVE(notit->stream, stream);
+
+end:
+ bt_put(stream);
+ return status;
+}
+
+static inline
+enum bt_notif_iter_status set_current_packet(struct bt_notif_iter *notit)
+{
+ enum bt_notif_iter_status status = BT_NOTIF_ITER_STATUS_OK;
+ struct bt_packet *packet = NULL;
+
+ BT_LOGV("Creating packet for packet notification: "
+ "notit-addr=%p", notit);
+ BT_LOGV("Creating packet from stream: "
+ "notit-addr=%p, stream-addr=%p, "
+ "stream-class-addr=%p, "
+ "stream-class-name=\"%s\", "
+ "stream-class-id=%" PRId64,
+ notit, notit->stream, notit->meta.stream_class,
+ bt_stream_class_get_name(notit->meta.stream_class),
+ bt_stream_class_get_id(notit->meta.stream_class));
+
+ /* Create packet */
+ BT_ASSERT(notit->stream);
+ packet = bt_packet_create(notit->stream);
+ if (!packet) {
+ BT_LOGE("Cannot create packet from stream: "
+ "notit-addr=%p, stream-addr=%p, "
+ "stream-class-addr=%p, "
+ "stream-class-name=\"%s\", "
+ "stream-class-id=%" PRId64,
+ notit, notit->stream, notit->meta.stream_class,
+ bt_stream_class_get_name(notit->meta.stream_class),
+ bt_stream_class_get_id(notit->meta.stream_class));
+ goto error;
+ }
+
+ goto end;
+
+error:
+ BT_PUT(packet);
+ status = BT_NOTIF_ITER_STATUS_ERROR;
+
+end:
+ BT_MOVE(notit->packet, packet);
+ return status;
+}
+
static
enum bt_notif_iter_status after_packet_header_state(
struct bt_notif_iter *notit)
enum bt_notif_iter_status status;
status = set_current_stream_class(notit);
- if (status == BT_NOTIF_ITER_STATUS_OK) {
- notit->state = STATE_DSCOPE_STREAM_PACKET_CONTEXT_BEGIN;
+ if (status != BT_NOTIF_ITER_STATUS_OK) {
+ goto end;
}
+ notit->state = STATE_DSCOPE_STREAM_PACKET_CONTEXT_BEGIN;
+
+end:
return status;
}
goto end;
}
+ /*
+ * Create free packet context field from stream class. This
+ * field is going to be moved to the packet once we create it.
+ * We cannot create the packet now because a packet is created
+ * from a stream, and this API must be able to return the packet
+ * header and context fields without creating a stream
+ * (bt_notif_iter_get_packet_header_context_fields()).
+ */
+ BT_ASSERT(!notit->packet_context_field);
+ notit->packet_context_field =
+ bt_stream_class_create_packet_context_field(
+ notit->meta.stream_class);
+ if (!notit->packet_context_field) {
+ BT_LOGE_STR("Cannot create packet context field wrapper from stream class.");
+ status = BT_NOTIF_ITER_STATUS_ERROR;
+ goto end;
+ }
+
+ notit->dscopes.stream_packet_context =
+ bt_packet_context_field_borrow_field(notit->packet_context_field);
+ BT_ASSERT(notit->dscopes.stream_packet_context);
BT_LOGV("Decoding packet context field: "
"notit-addr=%p, stream-class-addr=%p, "
"stream-class-name=\"%s\", stream-class-id=%" PRId64 ", "
status = read_dscope_begin_state(notit, packet_context_type,
STATE_AFTER_STREAM_PACKET_CONTEXT,
STATE_DSCOPE_STREAM_PACKET_CONTEXT_CONTINUE,
- ¬it->dscopes.stream_packet_context);
+ notit->dscopes.stream_packet_context);
if (status < 0) {
BT_LOGW("Cannot decode packet context field: "
"notit-addr=%p, stream-class-addr=%p, "
goto end;
}
- packet_size_field = bt_field_structure_get_field_by_name(
+ packet_size_field = bt_field_structure_borrow_field_by_name(
notit->dscopes.stream_packet_context, "packet_size");
- content_size_field = bt_field_structure_get_field_by_name(
+ content_size_field = bt_field_structure_borrow_field_by_name(
notit->dscopes.stream_packet_context, "content_size");
if (packet_size_field) {
int ret = bt_field_integer_unsigned_get_value(
"notit-addr=%p, packet-size=%" PRIu64 ", content-size=%" PRIu64,
notit, packet_size, content_size);
end:
- BT_PUT(packet_size_field);
- BT_PUT(content_size_field);
return status;
}
}
}
+ release_event_dscopes(notit);
+ BT_ASSERT(notit->meta.stream_class);
event_header_type = bt_stream_class_borrow_event_header_field_type(
notit->meta.stream_class);
if (!event_header_type) {
goto end;
}
- put_event_dscopes(notit);
+ BT_ASSERT(!notit->event_header_field);
+ notit->event_header_field = bt_stream_class_create_event_header_field(
+ notit->meta.stream_class);
+ if (!notit->event_header_field) {
+ BT_LOGE_STR("Cannot create event header field wrapper from trace.");
+ status = BT_NOTIF_ITER_STATUS_ERROR;
+ goto end;
+ }
+
+ notit->dscopes.stream_event_header =
+ bt_event_header_field_borrow_field(notit->event_header_field);
+ BT_ASSERT(notit->dscopes.stream_event_header);
BT_LOGV("Decoding event header field: "
"notit-addr=%p, stream-class-addr=%p, "
"stream-class-name=\"%s\", stream-class-id=%" PRId64 ", "
status = read_dscope_begin_state(notit, event_header_type,
STATE_AFTER_STREAM_EVENT_HEADER,
STATE_DSCOPE_STREAM_EVENT_HEADER_CONTINUE,
- ¬it->dscopes.stream_event_header);
+ notit->dscopes.stream_event_header);
if (status < 0) {
BT_LOGW("Cannot decode event header field: "
"notit-addr=%p, stream-class-addr=%p, "
}
/* Is there any "id"/"v" field in the event header? */
- BT_ASSERT(is_struct_type(event_header_type));
+ BT_ASSERT(bt_field_type_is_structure(event_header_type));
id_field_type = bt_field_type_structure_borrow_field_type_by_name(
event_header_type, "id");
v_field_type = bt_field_type_structure_borrow_field_type_by_name(
struct bt_field *v_struct_id_field = NULL;
// TODO: optimalize!
- v_field = bt_field_structure_get_field_by_name(
+ v_field = bt_field_structure_borrow_field_by_name(
notit->dscopes.stream_event_header, "v");
BT_ASSERT(v_field);
v_struct_field =
- bt_field_variant_get_current_field(v_field);
+ bt_field_variant_borrow_current_field(v_field);
if (!v_struct_field) {
goto end_v_field_type;
}
// TODO: optimalize!
- v_struct_id_field =
- bt_field_structure_get_field_by_name(v_struct_field, "id");
+ v_struct_id_field = bt_field_structure_borrow_field_by_name(
+ v_struct_field, "id");
if (!v_struct_id_field) {
goto end_v_field_type;
}
event_id = -1ULL;
}
}
-
-end_v_field_type:
- BT_PUT(v_field);
- BT_PUT(v_struct_field);
- BT_PUT(v_struct_id_field);
}
+end_v_field_type:
if (id_field_type && event_id == -1ULL) {
/* Check "id" field */
struct bt_field *id_field = NULL;
int ret_get_value = 0;
// TODO: optimalize!
- id_field = bt_field_structure_get_field_by_name(
+ id_field = bt_field_structure_borrow_field_by_name(
notit->dscopes.stream_event_header, "id");
if (!id_field) {
goto check_event_id;
}
- if (bt_field_is_integer(id_field)) {
- ret_get_value = bt_field_integer_unsigned_get_value(
- id_field, &event_id);
- } else if (bt_field_is_enumeration(id_field)) {
- struct bt_field *container;
-
- container = bt_field_enumeration_get_container(
- id_field);
- BT_ASSERT(container);
- ret_get_value = bt_field_integer_unsigned_get_value(
- container, &event_id);
- BT_PUT(container);
- }
-
+ ret_get_value = bt_field_integer_unsigned_get_value(
+ id_field, &event_id);
BT_ASSERT(ret_get_value == 0);
- BT_PUT(id_field);
}
check_event_id:
return status;
}
+static inline
+enum bt_notif_iter_status set_current_event_notification(
+ struct bt_notif_iter *notit)
+{
+ enum bt_notif_iter_status status = BT_NOTIF_ITER_STATUS_OK;
+ struct bt_notification *notif = NULL;
+
+ BT_ASSERT(notit->meta.event_class);
+ BT_ASSERT(notit->packet);
+ BT_LOGV("Creating event notification from event class and packet: "
+ "notit-addr=%p, ec-addr=%p, ec-name=\"%s\", packet-addr=%p",
+ notit, notit->meta.event_class,
+ bt_event_class_get_name(notit->meta.event_class),
+ notit->packet);
+ notif = bt_notification_event_create(notit->meta.event_class,
+ notit->packet, notit->meta.cc_prio_map);
+ if (!notif) {
+ BT_LOGE("Cannot create event notification: "
+ "notit-addr=%p, ec-addr=%p, ec-name=\"%s\", "
+ "packet-addr=%p",
+ notit, notit->meta.event_class,
+ bt_event_class_get_name(notit->meta.event_class),
+ notit->packet);
+ goto error;
+ }
+
+ goto end;
+
+error:
+ BT_PUT(notif);
+ status = BT_NOTIF_ITER_STATUS_ERROR;
+
+end:
+ BT_MOVE(notit->event_notif, notif);
+ return status;
+}
+
static
enum bt_notif_iter_status after_event_header_state(
struct bt_notif_iter *notit)
goto end;
}
+ status = set_current_event_notification(notit);
+ if (status != BT_NOTIF_ITER_STATUS_OK) {
+ goto end;
+ }
+
+ notit->event = bt_notification_event_borrow_event(notit->event_notif);
+ BT_ASSERT(notit->event);
+
+ if (notit->event_header_field) {
+ int ret;
+
+ BT_ASSERT(notit->event);
+ ret = bt_event_move_header(notit->event,
+ notit->event_header_field);
+
+ if (ret) {
+ status = BT_NOTIF_ITER_STATUS_ERROR;
+ goto end;
+ }
+
+ notit->event_header_field = NULL;
+
+ /*
+ * At this point notit->dscopes.stream_event_header has
+ * the same value as the event header field within
+ * notit->event.
+ */
+ BT_ASSERT(bt_event_borrow_header(notit->event) ==
+ notit->dscopes.stream_event_header);
+ }
+
notit->state = STATE_DSCOPE_STREAM_EVENT_CONTEXT_BEGIN;
end:
goto end;
}
+ BT_ASSERT(!notit->dscopes.stream_event_context);
+ notit->dscopes.stream_event_context =
+ bt_event_borrow_stream_event_context(notit->event);
+ BT_ASSERT(notit->dscopes.stream_event_context);
BT_LOGV("Decoding stream event context field: "
"notit-addr=%p, stream-class-addr=%p, "
"stream-class-name=\"%s\", stream-class-id=%" PRId64 ", "
status = read_dscope_begin_state(notit, stream_event_context_type,
STATE_DSCOPE_EVENT_CONTEXT_BEGIN,
STATE_DSCOPE_STREAM_EVENT_CONTEXT_CONTINUE,
- ¬it->dscopes.stream_event_context);
+ notit->dscopes.stream_event_context);
if (status < 0) {
BT_LOGW("Cannot decode stream event context field: "
"notit-addr=%p, stream-class-addr=%p, "
goto end;
}
+ BT_ASSERT(!notit->dscopes.event_context);
+ notit->dscopes.event_context = bt_event_borrow_context(notit->event);
+ BT_ASSERT(notit->dscopes.event_context);
BT_LOGV("Decoding event context field: "
"notit-addr=%p, event-class-addr=%p, "
"event-class-name=\"%s\", event-class-id=%" PRId64 ", "
status = read_dscope_begin_state(notit, event_context_type,
STATE_DSCOPE_EVENT_PAYLOAD_BEGIN,
STATE_DSCOPE_EVENT_CONTEXT_CONTINUE,
- ¬it->dscopes.event_context);
+ notit->dscopes.event_context);
if (status < 0) {
BT_LOGW("Cannot decode event context field: "
"notit-addr=%p, event-class-addr=%p, "
goto end;
}
+ BT_ASSERT(!notit->dscopes.event_payload);
+ notit->dscopes.event_payload = bt_event_borrow_payload(notit->event);
+ BT_ASSERT(notit->dscopes.event_payload);
BT_LOGV("Decoding event payload field: "
"notit-addr=%p, event-class-addr=%p, "
"event-class-name=\"%s\", event-class-id=%" PRId64 ", "
status = read_dscope_begin_state(notit, event_payload_type,
STATE_EMIT_NOTIF_EVENT,
STATE_DSCOPE_EVENT_PAYLOAD_CONTINUE,
- ¬it->dscopes.event_payload);
+ notit->dscopes.event_payload);
if (status < 0) {
BT_LOGW("Cannot decode event payload field: "
"notit-addr=%p, event-class-addr=%p, "
notit->meta.event_class = NULL;
BT_PUT(notit->packet);
BT_PUT(notit->stream);
- put_all_dscopes(notit);
+ BT_PUT(notit->event_notif);
+ release_all_dscopes(notit);
+ notit->cur_dscope_field = NULL;
+
+ if (notit->packet_header_field) {
+ bt_packet_header_field_release(notit->packet_header_field);
+ notit->packet_header_field = NULL;
+ }
+
+ if (notit->packet_context_field) {
+ bt_packet_context_field_release(notit->packet_context_field);
+ notit->packet_context_field = NULL;
+ }
+
+ if (notit->event_header_field) {
+ bt_event_header_field_release(notit->event_header_field);
+ notit->event_header_field = NULL;
+ }
+
notit->buf.addr = NULL;
notit->buf.sz = 0;
notit->buf.at = 0;
notit->cur_packet_size = -1;
notit->cur_packet_offset = -1;
notit->stream_begin_emitted = false;
+ notit->cur_timestamp_end = NULL;
}
static
* iterator refer to the same stream class (the first one).
*/
BT_ASSERT(notit);
+
if (notit->cur_packet_size != -1) {
notit->cur_packet_offset += notit->cur_packet_size;
}
+
BT_LOGV("Switching packet: notit-addr=%p, cur=%zu, "
"packet-offset=%" PRId64, notit, notit->buf.at,
notit->cur_packet_offset);
stack_clear(notit->stack);
notit->meta.event_class = NULL;
BT_PUT(notit->packet);
- BT_PUT(notit->cur_timestamp_end);
- put_all_dscopes(notit);
+ BT_PUT(notit->event_notif);
+ notit->cur_timestamp_end = NULL;
+ release_all_dscopes(notit);
+ notit->cur_dscope_field = NULL;
/*
* Adjust current buffer so that addr points to the beginning of the new
}
static
-struct bt_field *get_next_field(struct bt_notif_iter *notit)
+struct bt_field *borrow_next_field(struct bt_notif_iter *notit)
{
struct bt_field *next_field = NULL;
struct bt_field *base_field;
switch (bt_field_type_get_type_id(base_type)) {
case BT_FIELD_TYPE_ID_STRUCT:
{
- next_field = bt_field_structure_get_field_by_index(
+ next_field = bt_field_structure_borrow_field_by_index(
base_field, index);
break;
}
case BT_FIELD_TYPE_ID_ARRAY:
- next_field = bt_field_array_get_field(base_field, index);
+ next_field = bt_field_array_borrow_field(base_field, index);
break;
case BT_FIELD_TYPE_ID_SEQUENCE:
- next_field = bt_field_sequence_get_field(base_field, index);
+ next_field = bt_field_sequence_borrow_field(base_field, index);
break;
case BT_FIELD_TYPE_ID_VARIANT:
- next_field = bt_field_variant_get_current_field(base_field);
+ next_field = bt_field_variant_borrow_current_field(base_field);
break;
default:
BT_LOGF("Unknown base field type ID: "
}
static
-void update_clock_state(uint64_t *state,
- struct bt_field *value_field)
+void update_clock_state(uint64_t *state, struct bt_field *value_field,
+ struct bt_field_type *value_type)
{
- struct bt_field_type *value_type = NULL;
uint64_t requested_new_value;
uint64_t requested_new_value_mask;
uint64_t cur_value_masked;
int requested_new_value_size;
int ret;
- value_type = bt_field_borrow_type(value_field);
BT_ASSERT(value_type);
BT_ASSERT(bt_field_type_is_integer(value_type));
requested_new_value_size =
int_field_type = bt_field_borrow_type(int_field);
BT_ASSERT(int_field_type);
+
+ if (bt_field_type_is_enumeration(int_field_type)) {
+ int_field_type =
+ bt_field_type_enumeration_borrow_container_field_type(
+ int_field_type);
+ }
+
clock_class = bt_field_type_integer_borrow_mapped_clock_class(
int_field_type);
if (likely(!clock_class)) {
"clock-class-name=\"%s\", value=%" PRIu64,
notit, clock_class,
bt_clock_class_get_name(clock_class), *clock_state);
- update_clock_state(clock_state, int_field);
+ update_clock_state(clock_state, int_field, int_field_type);
end:
return ret;
static
enum bt_btr_status btr_unsigned_int_common(uint64_t value,
struct bt_field_type *type, void *data,
- struct bt_field **out_int_field)
+ struct bt_field **out_field)
{
enum bt_btr_status status = BT_BTR_STATUS_OK;
struct bt_field *field = NULL;
- struct bt_field *int_field = NULL;
struct bt_notif_iter *notit = data;
int ret;
bt_common_field_type_id_string(
bt_field_type_get_type_id(type)),
value);
-
- /* Create next field */
- field = get_next_field(notit);
+ field = borrow_next_field(notit);
if (!field) {
- BT_LOGW("Cannot get next field: notit-addr=%p", notit);
+ BT_LOGW("Cannot borrow next field: notit-addr=%p", notit);
status = BT_BTR_STATUS_ERROR;
- goto end_no_put;
- }
-
- switch(bt_field_type_get_type_id(type)) {
- case BT_FIELD_TYPE_ID_INTEGER:
- /* Integer field is created field */
- BT_MOVE(int_field, field);
- break;
- case BT_FIELD_TYPE_ID_ENUM:
- int_field = bt_field_enumeration_get_container(field);
- BT_ASSERT(int_field);
- type = bt_field_borrow_type(int_field);
- BT_ASSERT(type);
- break;
- default:
- BT_LOGF("Unexpected field type ID: "
- "notit-addr=%p, ft-addr=%p, ft-id=%s",
- notit, type,
- bt_common_field_type_id_string(
- bt_field_type_get_type_id(type)));
- abort();
+ goto end;
}
- BT_ASSERT(int_field);
- ret = bt_field_integer_unsigned_set_value(int_field, value);
+ BT_ASSERT(bt_field_is_integer(field) || bt_field_is_enumeration(field));
+ ret = bt_field_integer_unsigned_set_value(field, value);
BT_ASSERT(ret == 0);
stack_top(notit->stack)->index++;
- *out_int_field = int_field;
- BT_PUT(field);
+ *out_field = field;
-end_no_put:
+end:
return status;
}
enum bt_btr_status status;
struct bt_field *field = NULL;
struct bt_notif_iter *notit = data;
+ uint64_t uvalue = *((uint64_t *) value);
BT_LOGV("`timestamp_end` unsigned integer function called from BTR: "
"notit-addr=%p, btr-addr=%p, ft-addr=%p, "
notit, notit->btr, type,
bt_common_field_type_id_string(
bt_field_type_get_type_id(type)));
- status = btr_unsigned_int_common(*((uint64_t *) value), type, data,
- &field);
- /* Set as the current packet's timestamp_end field. */
- BT_MOVE(notit->cur_timestamp_end, field);
+ status = btr_unsigned_int_common(uvalue, type, data, &field);
+
+ /* Set as the current packet's end timestamp field */
+ notit->cur_timestamp_end = field;
return status;
}
}
status = update_clock(notit, field);
- BT_PUT(field);
+
end:
return status;
}
{
enum bt_btr_status status = BT_BTR_STATUS_OK;
struct bt_field *field = NULL;
- struct bt_field *int_field = NULL;
struct bt_notif_iter *notit = data;
int ret;
bt_common_field_type_id_string(
bt_field_type_get_type_id(type)),
value);
-
- /* create next field */
- field = get_next_field(notit);
+ field = borrow_next_field(notit);
if (!field) {
- BT_LOGW("Cannot get next field: notit-addr=%p", notit);
+ BT_LOGW("Cannot borrow next field: notit-addr=%p", notit);
status = BT_BTR_STATUS_ERROR;
- goto end_no_put;
- }
-
- switch(bt_field_type_get_type_id(type)) {
- case BT_FIELD_TYPE_ID_INTEGER:
- /* Integer field is created field */
- BT_MOVE(int_field, field);
- break;
- case BT_FIELD_TYPE_ID_ENUM:
- int_field = bt_field_enumeration_get_container(field);
- BT_ASSERT(int_field);
- type = bt_field_borrow_type(int_field);
- BT_ASSERT(type);
- break;
- default:
- BT_LOGF("Unexpected field type ID: "
- "notit-addr=%p, ft-addr=%p, ft-id=%s",
- notit, type,
- bt_common_field_type_id_string(
- bt_field_type_get_type_id(type)));
- abort();
+ goto end;
}
- BT_ASSERT(int_field);
- ret = bt_field_integer_signed_set_value(int_field, value);
- BT_ASSERT(!ret);
+ BT_ASSERT(bt_field_is_integer(field) || bt_field_is_enumeration(field));
+ ret = bt_field_integer_signed_set_value(field, value);
+ BT_ASSERT(ret == 0);
stack_top(notit->stack)->index++;
- status = update_clock(notit, int_field);
- BT_PUT(field);
- BT_PUT(int_field);
-end_no_put:
+end:
return status;
}
bt_common_field_type_id_string(
bt_field_type_get_type_id(type)),
value);
-
- /* Create next field */
- field = get_next_field(notit);
+ field = borrow_next_field(notit);
if (!field) {
- BT_LOGW("Cannot get next field: notit-addr=%p", notit);
+ BT_LOGW("Cannot borrow next field: notit-addr=%p", notit);
status = BT_BTR_STATUS_ERROR;
goto end;
}
stack_top(notit->stack)->index++;
end:
- BT_PUT(field);
return status;
}
notit, notit->btr, type,
bt_common_field_type_id_string(
bt_field_type_get_type_id(type)));
-
- /* Create next field */
- field = get_next_field(notit);
+ field = borrow_next_field(notit);
if (!field) {
BT_LOGW("Cannot get next field: notit-addr=%p", notit);
status = BT_BTR_STATUS_ERROR;
goto end;
}
+ ret = bt_field_string_clear(field);
+ BT_ASSERT(ret == 0);
+
/*
* Push on stack. Not a compound type per se, but we know that only
* btr_string_cb() may be called between this call and a subsequent
goto end;
}
- /*
- * Initialize string field payload to an empty string since in the
- * case of a length 0 string the btr_string_cb won't be called and
- * we will end up with an unset string payload.
- */
- ret = bt_field_string_set_value(field, "");
- if (ret) {
- BT_LOGE("Cannot initialize string field's value to an empty string: "
- "notit-addr=%p, field-addr=%p, ret=%d",
- notit, field, ret);
- status = BT_BTR_STATUS_ERROR;
- goto end;
- }
-
end:
- BT_PUT(field);
-
return status;
}
bt_common_field_type_id_string(
bt_field_type_get_type_id(type)),
len);
-
- /* Get string field */
field = stack_top(notit->stack)->base;
BT_ASSERT(field);
- /* Append current string */
+ /* Append current substring */
ret = bt_field_string_append_len(field, value, len);
if (ret) {
BT_LOGE("Cannot append substring to string field's value: "
bt_common_field_type_id_string(
bt_field_type_get_type_id(type)));
- /* Create field */
+ /* Borrow field */
if (stack_empty(notit->stack)) {
- /* Root: create dynamic scope field */
- *notit->cur_dscope_field = bt_field_create(type);
- field = *notit->cur_dscope_field;
-
- /*
- * Field will be put at the end of this function
- * (stack_push() will take one reference, but this
- * reference is lost upon the equivalent stack_pop()
- * later), so also get it for our context to own it.
- */
- bt_get(*notit->cur_dscope_field);
-
- if (!field) {
- BT_LOGE("Cannot create compound field: "
- "notit-addr=%p, ft-addr=%p, ft-id=%s",
- notit, type,
- bt_common_field_type_id_string(
- bt_field_type_get_type_id(type)));
- status = BT_BTR_STATUS_ERROR;
- goto end;
- }
+ /* Root: already set by read_dscope_begin_state() */
+ field = notit->cur_dscope_field;
} else {
- field = get_next_field(notit);
+ field = borrow_next_field(notit);
if (!field) {
- BT_LOGW("Cannot get next field: notit-addr=%p", notit);
+ BT_LOGW("Cannot borrow next field: notit-addr=%p", notit);
status = BT_BTR_STATUS_ERROR;
goto end;
}
}
end:
- BT_PUT(field);
return status;
}
goto end;
}
- bt_get(field);
-
for (i = 0; i < bt_field_path_get_index_count(path); ++i) {
struct bt_field *next_field = NULL;
struct bt_field_type *field_type;
field_type = bt_field_borrow_type(field);
BT_ASSERT(field_type);
- if (is_struct_type(field_type)) {
- next_field = bt_field_structure_get_field_by_index(
+ if (bt_field_type_is_structure(field_type)) {
+ next_field = bt_field_structure_borrow_field_by_index(
field, index);
- } else if (is_variant_type(field_type)) {
+ } else if (bt_field_type_is_variant(field_type)) {
next_field =
- bt_field_variant_get_current_field(field);
+ bt_field_variant_borrow_current_field(field);
}
- BT_PUT(field);
+ field = NULL;
if (!next_field) {
BT_LOGW("Cannot find next field: "
}
/* Move next field -> field */
- BT_MOVE(field, next_field);
+ field = next_field;
}
end:
}
seq_field = stack_top(notit->stack)->base;
- iret = bt_field_sequence_set_length(seq_field, length_field);
+ iret = bt_field_sequence_set_length(seq_field, length);
if (iret) {
BT_LOGE("Cannot set sequence field's length field: "
"notit-addr=%p, seq-field-addr=%p, "
- "length-field-addr=%p, ",
- notit, seq_field, length_field);
+ "length=%" PRIu64,
+ notit, seq_field, length);
goto end;
}
ret = (int64_t) length;
end:
- BT_PUT(length_field);
return ret;
}
struct bt_field_type *btr_borrow_variant_field_type_cb(
struct bt_field_type *type, void *data)
{
+ int ret;
struct bt_field_path *path;
struct bt_notif_iter *notit = data;
struct bt_field *var_field;
struct bt_field *tag_field = NULL;
+ struct bt_field_type *tag_ft = NULL;
+ struct bt_field_type *tag_int_ft = NULL;
struct bt_field *selected_field = NULL;
struct bt_field_type *selected_field_type = NULL;
* able to select a current field for this variant. This
* callback function we're in is called _after_
* compound_begin(), so the current stack top's base field is
- * the variant field in question. We get the selected field here
- * thanks to this tag field (thus creating the selected field),
- * which will also provide us with its type. Then, this field
- * will remain the current selected one until the next callback
- * function call which is used to fill the current selected
- * field.
+ * the variant field in question. We set the variant field's tag
+ * here and then get the current (selected) field thanks to this
+ * tag field's value. This current field will also provide us
+ * with its type. Then, this current field will remain the
+ * current selected one until the next callback function call
+ * which is used to fill it.
*/
var_field = stack_top(notit->stack)->base;
- selected_field = bt_field_variant_get_field(var_field, tag_field);
+ tag_ft = bt_field_borrow_type(tag_field);
+ tag_int_ft = bt_field_type_enumeration_borrow_container_field_type(
+ tag_ft);
+
+ if (bt_field_type_integer_is_signed(tag_int_ft)) {
+ int64_t tag_value;
+
+ ret = bt_field_integer_signed_get_value(tag_field, &tag_value);
+ BT_ASSERT(ret == 0);
+ ret = bt_field_variant_set_tag_signed(var_field, tag_value);
+ BT_ASSERT(ret == 0);
+ } else {
+ uint64_t tag_value;
+
+ ret = bt_field_integer_unsigned_get_value(tag_field,
+ &tag_value);
+ BT_ASSERT(ret == 0);
+ ret = bt_field_variant_set_tag_unsigned(var_field, tag_value);
+ BT_ASSERT(ret == 0);
+ }
+
+ selected_field = bt_field_variant_borrow_current_field(var_field);
if (!selected_field) {
- BT_LOGW("Cannot get variant field's selection using tag field: "
- "notit-addr=%p, var-field-addr=%p, tag-field-addr=%p",
- notit, var_field, tag_field);
+ BT_LOGW("Cannot borrow variant field's current field: "
+ "notit-addr=%p, var-field-addr=%p",
+ notit, var_field);
goto end;
}
selected_field_type = bt_field_borrow_type(selected_field);
end:
- BT_PUT(tag_field);
- BT_PUT(selected_field);
return selected_field_type;
}
static
-int set_event_clocks(struct bt_event *event,
- struct bt_notif_iter *notit)
+int set_event_clocks(struct bt_notif_iter *notit)
{
int ret;
GHashTableIter iter;
g_hash_table_iter_init(&iter, notit->clock_states);
while (g_hash_table_iter_next(&iter, (gpointer) &clock_class,
- (gpointer) &clock_state)) {
+ (gpointer) &clock_state)) {
struct bt_clock_value *clock_value;
- clock_value = bt_clock_value_create(clock_class,
- *clock_state);
+ clock_value = bt_event_borrow_clock_value(notit->event,
+ clock_class);
if (!clock_value) {
- BT_LOGE("Cannot create clock value from clock class: "
+ BT_LOGE("Cannot borrow clock value from event with given clock class: "
"notit-addr=%p, clock-class-addr=%p, "
"clock-class-name=\"%s\"",
notit, clock_class,
ret = -1;
goto end;
}
- ret = bt_event_set_clock_value(event, clock_value);
- bt_put(clock_value);
- if (ret) {
- struct bt_event_class *event_class =
- bt_event_borrow_class(event);
-
- BT_ASSERT(event_class);
- BT_LOGE("Cannot set event's clock value: "
- "notit-addr=%p, event-addr=%p, "
- "event-class-name=\"%s\", "
- "event-class-id=%" PRId64 ", "
- "clock-class-addr=%p, "
- "clock-class-name=\"%s\", "
- "clock-value-addr=%p",
- notit, event,
- bt_event_class_get_name(event_class),
- bt_event_class_get_id(event_class),
- clock_class,
- bt_clock_class_get_name(clock_class),
- clock_value);
- goto end;
- }
- }
-
- ret = 0;
-end:
- return ret;
-}
-
-static
-struct bt_event *create_event(struct bt_notif_iter *notit)
-{
- int ret;
- struct bt_event *event;
-
- BT_LOGV("Creating event for event notification: "
- "notit-addr=%p, event-class-addr=%p, "
- "event-class-name=\"%s\", "
- "event-class-id=%" PRId64,
- notit, notit->meta.event_class,
- bt_event_class_get_name(notit->meta.event_class),
- bt_event_class_get_id(notit->meta.event_class));
-
- /* Create event object. */
- event = bt_event_create(notit->meta.event_class);
- if (!event) {
- BT_LOGE("Cannot create event: "
- "notit-addr=%p, event-class-addr=%p, "
- "event-class-name=\"%s\", "
- "event-class-id=%" PRId64,
- notit, notit->meta.event_class,
- bt_event_class_get_name(notit->meta.event_class),
- bt_event_class_get_id(notit->meta.event_class));
- goto error;
- }
-
- /* Set header, stream event context, context, and payload fields. */
- ret = bt_event_set_header(event,
- notit->dscopes.stream_event_header);
- if (ret) {
- BT_LOGE("Cannot set event's header field: "
- "notit-addr=%p, event-addr=%p, event-class-addr=%p, "
- "event-class-name=\"%s\", "
- "event-class-id=%" PRId64 ", field-addr=%p",
- notit, event, notit->meta.event_class,
- bt_event_class_get_name(notit->meta.event_class),
- bt_event_class_get_id(notit->meta.event_class),
- notit->dscopes.stream_event_header);
- goto error;
- }
-
- ret = bt_event_set_stream_event_context(event,
- notit->dscopes.stream_event_context);
- if (ret) {
- BT_LOGE("Cannot set event's context field: "
- "notit-addr=%p, event-addr=%p, event-class-addr=%p, "
- "event-class-name=\"%s\", "
- "event-class-id=%" PRId64 ", field-addr=%p",
- notit, event, notit->meta.event_class,
- bt_event_class_get_name(notit->meta.event_class),
- bt_event_class_get_id(notit->meta.event_class),
- notit->dscopes.stream_event_context);
- goto error;
- }
-
- ret = bt_event_set_context(event,
- notit->dscopes.event_context);
- if (ret) {
- BT_LOGE("Cannot set event's stream event context field: "
- "notit-addr=%p, event-addr=%p, event-class-addr=%p, "
- "event-class-name=\"%s\", "
- "event-class-id=%" PRId64 ", field-addr=%p",
- notit, event, notit->meta.event_class,
- bt_event_class_get_name(notit->meta.event_class),
- bt_event_class_get_id(notit->meta.event_class),
- notit->dscopes.event_context);
- goto error;
- }
-
- ret = bt_event_set_payload(event,
- notit->dscopes.event_payload);
- if (ret) {
- BT_LOGE("Cannot set event's payload field: "
- "notit-addr=%p, event-addr=%p, event-class-addr=%p, "
- "event-class-name=\"%s\", "
- "event-class-id=%" PRId64 ", field-addr=%p",
- notit, event, notit->meta.event_class,
- bt_event_class_get_name(notit->meta.event_class),
- bt_event_class_get_id(notit->meta.event_class),
- notit->dscopes.event_payload);
- goto error;
- }
-
- ret = set_event_clocks(event, notit);
- if (ret) {
- BT_LOGE("Cannot set event's clock values: "
- "notit-addr=%p, event-addr=%p, event-class-addr=%p, "
- "event-class-name=\"%s\", "
- "event-class-id=%" PRId64,
- notit, event, notit->meta.event_class,
- bt_event_class_get_name(notit->meta.event_class),
- bt_event_class_get_id(notit->meta.event_class));
- goto error;
- }
-
- /* Associate with current packet. */
- BT_ASSERT(notit->packet);
- ret = bt_event_set_packet(event, notit->packet);
- if (ret) {
- BT_LOGE("Cannot set event's header field: "
- "notit-addr=%p, event-addr=%p, event-class-addr=%p, "
- "event-class-name=\"%s\", "
- "event-class-id=%" PRId64 ", packet-addr=%p",
- notit, event, notit->meta.event_class,
- bt_event_class_get_name(notit->meta.event_class),
- bt_event_class_get_id(notit->meta.event_class),
- notit->packet);
- goto error;
- }
-
- goto end;
-
-error:
- BT_PUT(event);
-
-end:
- return event;
-}
-
-static
-uint64_t get_cur_stream_instance_id(struct bt_notif_iter *notit)
-{
- struct bt_field *stream_instance_id_field = NULL;
- uint64_t stream_instance_id = -1ULL;
- int ret;
-
- if (!notit->dscopes.trace_packet_header) {
- goto end;
- }
-
- stream_instance_id_field = bt_field_structure_get_field_by_name(
- notit->dscopes.trace_packet_header, "stream_instance_id");
- if (!stream_instance_id_field) {
- goto end;
- }
-
- ret = bt_field_integer_unsigned_get_value(stream_instance_id_field,
- &stream_instance_id);
- if (ret) {
- stream_instance_id = -1ULL;
- goto end;
- }
-
-end:
- bt_put(stream_instance_id_field);
- return stream_instance_id;
-}
-
-static
-int set_stream(struct bt_notif_iter *notit)
-{
- int ret = 0;
- struct bt_stream *stream = NULL;
-
- BT_LOGV("Calling user function (get stream): notit-addr=%p, "
- "stream-class-addr=%p, stream-class-name=\"%s\", "
- "stream-class-id=%" PRId64,
- notit, notit->meta.stream_class,
- bt_stream_class_get_name(notit->meta.stream_class),
- bt_stream_class_get_id(notit->meta.stream_class));
- stream = bt_get(notit->medium.medops.get_stream(
- notit->meta.stream_class, get_cur_stream_instance_id(notit),
- notit->medium.data));
- BT_LOGV("User function returned: stream-addr=%p", stream);
- if (!stream) {
- BT_LOGW_STR("User function failed to return a stream object for the given stream class.");
- ret = -1;
- goto end;
- }
- if (notit->stream && stream != notit->stream) {
- BT_LOGW("User function returned a different stream than the previous one for the same sequence of packets.");
- ret = -1;
- goto end;
+ ret = bt_clock_value_set_value(clock_value, *clock_state);
+ BT_ASSERT(ret == 0);
}
- BT_MOVE(notit->stream, stream);
-
+ ret = 0;
end:
- bt_put(stream);
return ret;
}
-static
-void create_packet(struct bt_notif_iter *notit)
-{
- int ret;
- struct bt_packet *packet = NULL;
-
- BT_LOGV("Creating packet for packet notification: "
- "notit-addr=%p", notit);
- BT_LOGV("Creating packet from stream: "
- "notit-addr=%p, stream-addr=%p, "
- "stream-class-addr=%p, "
- "stream-class-name=\"%s\", "
- "stream-class-id=%" PRId64,
- notit, notit->stream, notit->meta.stream_class,
- bt_stream_class_get_name(notit->meta.stream_class),
- bt_stream_class_get_id(notit->meta.stream_class));
-
- /* Create packet */
- BT_ASSERT(notit->stream);
- packet = bt_packet_create(notit->stream);
- if (!packet) {
- BT_LOGE("Cannot create packet from stream: "
- "notit-addr=%p, stream-addr=%p, "
- "stream-class-addr=%p, "
- "stream-class-name=\"%s\", "
- "stream-class-id=%" PRId64,
- notit, notit->stream, notit->meta.stream_class,
- bt_stream_class_get_name(notit->meta.stream_class),
- bt_stream_class_get_id(notit->meta.stream_class));
- goto error;
- }
-
- /* Set packet's context and header fields */
- if (notit->dscopes.trace_packet_header) {
- ret = bt_packet_set_header(packet,
- notit->dscopes.trace_packet_header);
- if (ret) {
- BT_LOGE("Cannot set packet's header field: "
- "notit-addr=%p, packet-addr=%p, "
- "stream-addr=%p, "
- "stream-class-addr=%p, "
- "stream-class-name=\"%s\", "
- "stream-class-id=%" PRId64 ", "
- "field-addr=%p",
- notit, packet, notit->stream, notit->meta.stream_class,
- bt_stream_class_get_name(notit->meta.stream_class),
- bt_stream_class_get_id(notit->meta.stream_class),
- notit->dscopes.trace_packet_header);
- goto error;
- }
- }
-
- if (notit->dscopes.stream_packet_context) {
- ret = bt_packet_set_context(packet,
- notit->dscopes.stream_packet_context);
- if (ret) {
- BT_LOGE("Cannot set packet's context field: "
- "notit-addr=%p, packet-addr=%p, "
- "stream-addr=%p, "
- "stream-class-addr=%p, "
- "stream-class-name=\"%s\", "
- "stream-class-id=%" PRId64 ", "
- "field-addr=%p",
- notit, packet, notit->stream, notit->meta.stream_class,
- bt_stream_class_get_name(notit->meta.stream_class),
- bt_stream_class_get_id(notit->meta.stream_class),
- notit->dscopes.trace_packet_header);
- goto error;
- }
- }
-
- goto end;
-
-error:
- BT_PUT(packet);
-
-end:
- BT_MOVE(notit->packet, packet);
-}
-
static
void notify_new_stream(struct bt_notif_iter *notit,
struct bt_notification **notification)
{
+ enum bt_notif_iter_status status;
struct bt_notification *ret = NULL;
- int iret;
- /* Ask the user for the stream */
- iret = set_stream(notit);
- if (iret) {
+ status = set_current_stream(notit);
+ if (status != BT_NOTIF_ITER_STATUS_OK) {
+ BT_PUT(ret);
goto end;
}
void notify_new_packet(struct bt_notif_iter *notit,
struct bt_notification **notification)
{
- struct bt_notification *ret;
+ int ret;
+ enum bt_notif_iter_status status;
+ struct bt_notification *notif = NULL;
- /* Initialize the iterator's current packet */
- create_packet(notit);
- if (!notit->packet) {
- BT_LOGE("Cannot create packet for packet notification: "
- "notit-addr=%p", notit);
- return;
+ status = set_current_packet(notit);
+ if (status != BT_NOTIF_ITER_STATUS_OK) {
+ goto end;
}
- ret = bt_notification_packet_begin_create(notit->packet);
- if (!ret) {
+ BT_ASSERT(notit->packet);
+
+ if (notit->packet_header_field) {
+ ret = bt_packet_move_header(notit->packet,
+ notit->packet_header_field);
+ if (ret) {
+ goto end;
+ }
+
+ notit->packet_header_field = NULL;
+
+ /*
+ * At this point notit->dscopes.trace_packet_header has
+ * the same value as the packet header field within
+ * notit->packet.
+ */
+ BT_ASSERT(bt_packet_borrow_header(notit->packet) ==
+ notit->dscopes.trace_packet_header);
+ }
+
+ if (notit->packet_context_field) {
+ ret = bt_packet_move_context(notit->packet,
+ notit->packet_context_field);
+ if (ret) {
+ goto end;
+ }
+
+ notit->packet_context_field = NULL;
+
+ /*
+ * At this point notit->dscopes.trace_packet_header has
+ * the same value as the packet header field within
+ * notit->packet.
+ */
+ BT_ASSERT(bt_packet_borrow_context(notit->packet) ==
+ notit->dscopes.stream_packet_context);
+ }
+
+ notif = bt_notification_packet_begin_create(notit->packet);
+ if (!notif) {
BT_LOGE("Cannot create packet beginning notification: "
"notit-addr=%p, packet-addr=%p",
notit, notit->packet);
return;
}
- *notification = ret;
+
+end:
+ *notification = notif;
}
static
void notify_end_of_packet(struct bt_notif_iter *notit,
struct bt_notification **notification)
{
- struct bt_notification *ret;
+ struct bt_notification *notif;
if (!notit->packet) {
return;
}
- ret = bt_notification_packet_end_create(notit->packet);
- if (!ret) {
+ notif = bt_notification_packet_end_create(notit->packet);
+ if (!notif) {
BT_LOGE("Cannot create packet end notification: "
"notit-addr=%p, packet-addr=%p",
notit, notit->packet);
return;
}
- BT_PUT(notit->packet);
- *notification = ret;
-}
-
-static
-void notify_event(struct bt_notif_iter *notit,
- struct bt_clock_class_priority_map *cc_prio_map,
- struct bt_notification **notification)
-{
- struct bt_event *event = NULL;
- struct bt_notification *ret = NULL;
- /* Make sure that the event contains at least one bit of data */
- if (notit->buf.at == notit->buf.last_eh_at) {
- BT_LOGE("Cannot create empty event with 0 bits of data: "
- "notit-addr=%p, packet-cur=%zu",
- notit, packet_at(notit));
- goto end;
- }
-
- /* Create event */
- event = create_event(notit);
- if (!event) {
- BT_LOGE("Cannot create event for event notification: "
- "notit-addr=%p", notit);
- goto end;
- }
-
- ret = bt_notification_event_create(event, cc_prio_map);
- if (!ret) {
- BT_LOGE("Cannot create event notification: "
- "notit-addr=%p, event-addr=%p, "
- "cc-prio-map-addr=%p",
- notit, event, cc_prio_map);
- goto end;
- }
- *notification = ret;
-end:
- BT_PUT(event);
+ BT_PUT(notit->packet);
+ *notification = notif;
}
static
BT_ASSERT(trace);
BT_ASSERT(medops.request_bytes);
- BT_ASSERT(medops.get_stream);
+ BT_ASSERT(medops.borrow_stream);
BT_LOGD("Creating CTF plugin notification iterator: "
"trace-addr=%p, trace-name=\"%s\", max-request-size=%zu, "
"data=%p",
{
BT_PUT(notit->packet);
BT_PUT(notit->stream);
- BT_PUT(notit->cur_timestamp_end);
- put_all_dscopes(notit);
+ BT_PUT(notit->meta.cc_prio_map);
+ release_all_dscopes(notit);
BT_LOGD("Destroying CTF plugin notification iterator: addr=%p", notit);
struct bt_clock_class_priority_map *cc_prio_map,
struct bt_notification **notification)
{
+ int ret;
enum bt_notif_iter_status status = BT_NOTIF_ITER_STATUS_OK;
BT_ASSERT(notit);
BT_ASSERT(notification);
+ if (cc_prio_map != notit->meta.cc_prio_map) {
+ bt_put(notit->meta.cc_prio_map);
+ notit->meta.cc_prio_map = bt_get(cc_prio_map);
+ }
+
if (notit->state == STATE_DONE) {
status = BT_NOTIF_ITER_STATUS_EOF;
goto end;
BT_LOGV_STR("Medium returned BT_NOTIF_ITER_STATUS_AGAIN.");
goto end;
}
+
if (status != BT_NOTIF_ITER_STATUS_OK) {
if (status == BT_NOTIF_ITER_STATUS_EOF) {
enum state next_state = notit->state;
BT_LOGV_STR("Medium returned BT_NOTIF_ITER_STATUS_EOF.");
if (notit->packet) {
- notify_end_of_packet(notit, notification);
+ notify_end_of_packet(notit,
+ notification);
} else {
- notify_end_of_stream(notit, notification);
+ notify_end_of_stream(notit,
+ notification);
next_state = STATE_DONE;
}
status = BT_NOTIF_ITER_STATUS_OK;
notit->state = next_state;
- goto end;
} else {
BT_LOGW("Cannot handle state: "
"notit-addr=%p, state=%s",
notit, state_string(notit->state));
}
+
goto end;
}
if (!*notification) {
status = BT_NOTIF_ITER_STATUS_ERROR;
}
+
goto end;
case STATE_EMIT_NOTIF_EVENT:
- /* notify_event() logs errors */
- notify_event(notit, cc_prio_map, notification);
- if (!*notification) {
+ BT_ASSERT(notit->event_notif);
+ ret = set_event_clocks(notit);
+ if (ret) {
status = BT_NOTIF_ITER_STATUS_ERROR;
+ goto end;
}
+
+ BT_MOVE(*notification, notit->event_notif);
goto end;
case STATE_EMIT_NOTIF_END_OF_PACKET:
/* Update clock with timestamp_end field. */
if (notit->cur_timestamp_end) {
enum bt_btr_status btr_status;
- struct bt_field_type *field_type =
- bt_field_borrow_type(
- notit->cur_timestamp_end);
- BT_ASSERT(field_type);
btr_status = update_clock(notit,
notit->cur_timestamp_end);
if (btr_status != BT_BTR_STATUS_OK) {
if (!*notification) {
status = BT_NOTIF_ITER_STATUS_ERROR;
}
+
goto end;
default:
/* Non-emitting state: continue */
}
BT_HIDDEN
-enum bt_notif_iter_status bt_notif_iter_get_packet_header_context_fields(
+enum bt_notif_iter_status bt_notif_iter_borrow_packet_header_context_fields(
struct bt_notif_iter *notit,
struct bt_field **packet_header_field,
struct bt_field **packet_context_field)
}
set_fields:
+ ret = set_current_packet_content_sizes(notit);
+ if (ret) {
+ status = BT_NOTIF_ITER_STATUS_ERROR;
+ goto end;
+ }
+
if (packet_header_field) {
- *packet_header_field = bt_get(notit->dscopes.trace_packet_header);
+ *packet_header_field = notit->dscopes.trace_packet_header;
}
if (packet_context_field) {
- *packet_context_field = bt_get(notit->dscopes.stream_packet_context);
+ *packet_context_field = notit->dscopes.stream_packet_context;
}
- ret = set_current_packet_content_sizes(notit);
- if (ret) {
- status = BT_NOTIF_ITER_STATUS_ERROR;
- goto end;
- }
end:
return status;
}
* @returns Stream instance (weak reference) or
* \c NULL on error
*/
- struct bt_stream * (* get_stream)(
+ struct bt_stream * (* borrow_stream)(
struct bt_stream_class *stream_class,
uint64_t stream_id, void *data);
};
/**
* Returns the first packet header and context fields. This function
- * never needs to call the `get_stream()` medium operation because
+ * never needs to call the `borrow_stream()` medium operation because
* it does not create packet or event objects.
*
* @param notif_iter CTF notification iterator
* @returns One of #bt_notif_iter_status values
*/
BT_HIDDEN
-enum bt_notif_iter_status bt_notif_iter_get_packet_header_context_fields(
+enum bt_notif_iter_status bt_notif_iter_borrow_packet_header_context_fields(
struct bt_notif_iter *notit,
struct bt_field **packet_header_field,
struct bt_field **packet_context_field);
}
static
-struct bt_stream *medop_get_stream(
+struct bt_stream *medop_borrow_stream(
struct bt_stream_class *stream_class, uint64_t stream_id,
void *data)
{
BT_HIDDEN
struct bt_notif_iter_medium_ops ctf_fs_ds_file_medops = {
.request_bytes = medop_request_bytes,
- .get_stream = medop_get_stream,
+ .borrow_stream = medop_borrow_stream,
.seek = medop_seek,
};
struct bt_clock_class **timestamp_end_cc)
{
struct bt_field *packet_context = NULL;
- int ret = ctf_fs_ds_file_get_packet_header_context_fields(ds_file,
- NULL, &packet_context);
+ int ret = ctf_fs_ds_file_borrow_packet_header_context_fields(ds_file,
+ NULL, &packet_context);
if (ret || !packet_context) {
- BT_LOGD("Cannot retrieve packet context field of stream \'%s\'",
+ BT_LOGD("Cannot retrieve packet context field: ds-file-path=\"%s\"",
ds_file->file->path->str);
ret = -1;
goto end;
timestamp_end_cc, NULL);
end:
- bt_put(packet_context);
return ret;
}
int convert_cycles_to_ns(struct bt_clock_class *clock_class,
uint64_t cycles, int64_t *ns)
{
- int ret = 0;
- struct bt_clock_value *clock_value;
-
- BT_ASSERT(ns);
- clock_value = bt_clock_value_create(clock_class, cycles);
- if (!clock_value) {
- ret = -1;
- goto end;
- }
-
- ret = bt_clock_value_get_value_ns_from_epoch(clock_value, ns);
- if (ret) {
- goto end;
- }
-end:
- bt_put(clock_value);
- return ret;
+ return bt_clock_class_cycles_to_ns(clock_class, cycles, ns);
}
static
int ret;
struct ctf_fs_ds_index *index = NULL;
enum bt_notif_iter_status iter_status;
- struct bt_field *packet_context = NULL;
BT_LOGD("Indexing stream file %s", ds_file->file->path->str);
off_t next_packet_offset;
off_t current_packet_size, current_packet_size_bytes;
struct ctf_fs_ds_index_entry *entry;
+ struct bt_field *packet_context = NULL;
- iter_status = bt_notif_iter_get_packet_header_context_fields(
- ds_file->notif_iter, NULL, &packet_context);
+ iter_status = bt_notif_iter_borrow_packet_header_context_fields(
+ ds_file->notif_iter, NULL, &packet_context);
if (iter_status != BT_NOTIF_ITER_STATUS_OK) {
if (iter_status == BT_NOTIF_ITER_STATUS_EOF) {
break;
}
goto error;
}
+
current_packet_offset =
- bt_notif_iter_get_current_packet_offset(
+ bt_notif_iter_get_current_packet_offset(
ds_file->notif_iter);
if (current_packet_offset < 0) {
BT_LOGE_STR("Cannot get the current packet's offset.");
}
current_packet_size = bt_notif_iter_get_current_packet_size(
- ds_file->notif_iter);
+ ds_file->notif_iter);
if (current_packet_size < 0) {
BT_LOGE("Cannot get packet size: packet-offset=%jd",
current_packet_offset);
goto error;
}
current_packet_size_bytes =
- ((current_packet_size + 7) & ~7) / CHAR_BIT;
+ ((current_packet_size + 7) & ~7) / CHAR_BIT;
if (current_packet_offset + current_packet_size_bytes >
ds_file->file->size) {
}
next_packet_offset = current_packet_offset +
- current_packet_size_bytes;
+ current_packet_size_bytes;
BT_LOGD("Seeking to next packet: current-packet-offset=%jd, "
- "next-packet-offset=%jd", current_packet_offset,
- next_packet_offset);
+ "next-packet-offset=%jd", current_packet_offset,
+ next_packet_offset);
entry = ctf_fs_ds_index_add_new_entry(index);
if (!entry) {
}
ret = init_index_entry(entry, packet_context,
- current_packet_size_bytes,
- current_packet_offset);
+ current_packet_size_bytes,
+ current_packet_offset);
if (ret) {
goto error;
}
iter_status = bt_notif_iter_seek(ds_file->notif_iter,
next_packet_offset);
- BT_PUT(packet_context);
} while (iter_status == BT_NOTIF_ITER_STATUS_OK);
if (iter_status != BT_NOTIF_ITER_STATUS_EOF) {
goto error;
}
+
end:
- bt_put(packet_context);
return index;
+
error:
ctf_fs_ds_index_destroy(index);
index = NULL;
}
BT_HIDDEN
-int ctf_fs_ds_file_get_packet_header_context_fields(
+int ctf_fs_ds_file_borrow_packet_header_context_fields(
struct ctf_fs_ds_file *ds_file,
struct bt_field **packet_header_field,
struct bt_field **packet_context_field)
int ret = 0;
BT_ASSERT(ds_file);
- notif_iter_status = bt_notif_iter_get_packet_header_context_fields(
+ notif_iter_status = bt_notif_iter_borrow_packet_header_context_fields(
ds_file->notif_iter, packet_header_field, packet_context_field);
switch (notif_iter_status) {
case BT_NOTIF_ITER_STATUS_EOF:
error:
ret = -1;
- if (packet_header_field) {
- bt_put(*packet_header_field);
- }
-
- if (packet_context_field) {
- bt_put(*packet_context_field);
- }
-
end:
return ret;
}
struct bt_stream *stream, const char *path);
BT_HIDDEN
-int ctf_fs_ds_file_get_packet_header_context_fields(
+int ctf_fs_ds_file_borrow_packet_header_context_fields(
struct ctf_fs_ds_file *ds_file,
struct bt_field **packet_header_field,
struct bt_field **packet_context_field);
}
end:
- bt_put(stream_instance_id_field);
return stream_instance_id;
}
uint64_t timestamp_begin_ns = -1ULL;
int64_t timestamp_begin_ns_signed;
struct bt_clock_class *timestamp_begin_clock_class = NULL;
- struct bt_clock_value *clock_value = NULL;
if (!packet_context_field) {
goto end;
goto end;
}
- clock_value = bt_clock_value_create(timestamp_begin_clock_class,
- timestamp_begin_raw_value);
- if (!clock_value) {
- goto end;
- }
-
- ret = bt_clock_value_get_value_ns_from_epoch(clock_value,
- ×tamp_begin_ns_signed);
+ ret = bt_clock_class_cycles_to_ns(timestamp_begin_clock_class,
+ timestamp_begin_raw_value, ×tamp_begin_ns_signed);
if (ret) {
goto end;
}
timestamp_begin_ns = (uint64_t) timestamp_begin_ns_signed;
end:
- bt_put(clock_value);
return timestamp_begin_ns;
}
goto error;
}
- ret = ctf_fs_ds_file_get_packet_header_context_fields(ds_file,
+ ret = ctf_fs_ds_file_borrow_packet_header_context_fields(ds_file,
&packet_header_field, &packet_context_field);
if (ret) {
BT_LOGE("Cannot get stream file's first packet's header and context fields (`%s`).",
}
ctf_fs_ds_index_destroy(index);
- bt_put(packet_header_field);
- bt_put(packet_context_field);
return ret;
}
AM_CPPFLAGS += -I$(top_srcdir)/plugins
-SUBDIRS = pretty .
-# dmesg
+SUBDIRS = pretty dmesg
plugindir = "$(PLUGINSDIR)"
plugin_LTLIBRARIES = babeltrace-plugin-text.la
-avoid-version -module
babeltrace_plugin_text_la_LIBADD = \
- pretty/libbabeltrace-plugin-text-pretty-cc.la
-
-# dmesg/libbabeltrace-plugin-text-dmesg-cc.la
+ pretty/libbabeltrace-plugin-text-pretty-cc.la \
+ dmesg/libbabeltrace-plugin-text-dmesg-cc.la
if !ENABLE_BUILT_IN_PLUGINS
babeltrace_plugin_text_la_LIBADD += \
char *linebuf;
size_t linebuf_len;
FILE *fp;
+ struct bt_notification *tmp_event_notif;
+
+ enum {
+ STATE_EMIT_STREAM_BEGINNING,
+ STATE_EMIT_PACKET_BEGINNING,
+ STATE_EMIT_EVENT,
+ STATE_EMIT_PACKET_END,
+ STATE_EMIT_STREAM_END,
+ STATE_DONE,
+ } state;
};
struct dmesg_component {
return root_ft;
}
-static
-struct bt_field_type *create_packet_context_ft(void)
-{
- struct bt_field_type *root_ft = NULL;
- struct bt_field_type *ft = NULL;
- int ret;
-
- root_ft = bt_field_type_structure_create();
- if (!root_ft) {
- BT_LOGE_STR("Cannot create an empty structure field type object.");
- goto error;
- }
-
- ft = bt_field_type_integer_create(64);
- if (!ft) {
- BT_LOGE_STR("Cannot create an integer field type object.");
- goto error;
- }
-
- ret = bt_field_type_structure_add_field(root_ft,
- ft, "content_size");
- if (ret) {
- BT_LOGE("Cannot add `content_size` field type to structure field type: "
- "ret=%d", ret);
- goto error;
- }
-
- BT_PUT(ft);
- ft = bt_field_type_integer_create(64);
- if (!ft) {
- BT_LOGE_STR("Cannot create an integer field type object.");
- goto error;
- }
-
- ret = bt_field_type_structure_add_field(root_ft,
- ft, "packet_size");
- if (ret) {
- BT_LOGE("Cannot add `packet_size` field type to structure field type: "
- "ret=%d", ret);
- goto error;
- }
-
- goto end;
-
-error:
- BT_PUT(root_ft);
-
-end:
- bt_put(ft);
- return root_ft;
-}
-
static
struct bt_field_type *create_event_header_ft(
struct bt_clock_class *clock_class)
goto error;
}
- ret = bt_trace_set_packet_header_type(dmesg_comp->trace, ft);
+ ret = bt_trace_set_packet_header_field_type(dmesg_comp->trace, ft);
if (ret) {
BT_LOGE_STR("Cannot set trace's packet header field type.");
goto error;
}
}
- dmesg_comp->stream_class = bt_stream_class_create_empty(NULL);
+ dmesg_comp->stream_class = bt_stream_class_create(NULL);
if (!dmesg_comp->stream_class) {
BT_LOGE_STR("Cannot create an empty stream class object.");
goto error;
}
- bt_put(ft);
- ft = create_packet_context_ft();
- if (!ft) {
- BT_LOGE_STR("Cannot create packet context field type.");
- goto error;
- }
-
- ret = bt_stream_class_set_packet_context_type(
- dmesg_comp->stream_class, ft);
- if (ret) {
- BT_LOGE_STR("Cannot set stream class's packet context field type.");
- goto error;
- }
-
dmesg_comp->cc_prio_map = bt_clock_class_priority_map_create();
if (!dmesg_comp->cc_prio_map) {
BT_LOGE_STR("Cannot create empty clock class priority map.");
goto error;
}
- ret = bt_stream_class_set_event_header_type(
+ ret = bt_stream_class_set_event_header_field_type(
dmesg_comp->stream_class, ft);
if (ret) {
BT_LOGE_STR("Cannot set stream class's event header field type.");
goto error;
}
- ret = bt_event_class_set_payload_type(dmesg_comp->event_class, ft);
+ ret = bt_event_class_set_payload_field_type(dmesg_comp->event_class, ft);
if (ret) {
BT_LOGE_STR("Cannot set event class's event payload field type.");
goto error;
}
static
-struct bt_field *create_packet_header_field(struct bt_field_type *ft)
+int fill_packet_header_field(struct bt_packet *packet)
{
struct bt_field *ph = NULL;
struct bt_field *magic = NULL;
int ret;
- ph = bt_field_create(ft);
- if (!ph) {
- BT_LOGE_STR("Cannot create field object.");
- goto error;
- }
-
- magic = bt_field_structure_get_field_by_name(ph, "magic");
+ ph = bt_packet_borrow_header(packet);
+ BT_ASSERT(ph);
+ magic = bt_field_structure_borrow_field_by_name(ph, "magic");
if (!magic) {
- BT_LOGE_STR("Cannot get `magic` field from structure field.");
- goto error;
- }
-
- ret = bt_field_unsigned_integer_set_value(magic, 0xc1fc1fc1);
- if (ret) {
- BT_LOGE_STR("Cannot set integer field's value.");
+ BT_LOGE_STR("Cannot borrow `magic` field from structure field.");
goto error;
}
+ ret = bt_field_integer_unsigned_set_value(magic, 0xc1fc1fc1);
+ BT_ASSERT(ret == 0);
goto end;
error:
- BT_PUT(ph);
-
-end:
- bt_put(magic);
- return ph;
-}
-
-static
-struct bt_field *create_packet_context_field(struct bt_field_type *ft)
-{
- struct bt_field *pc = NULL;
- struct bt_field *field = NULL;
- int ret;
-
- pc = bt_field_create(ft);
- if (!pc) {
- BT_LOGE_STR("Cannot create field object.");
- goto error;
- }
-
- field = bt_field_structure_get_field_by_name(pc, "content_size");
- if (!field) {
- BT_LOGE_STR("Cannot get `content_size` field from structure field.");
- goto error;
- }
-
- ret = bt_field_unsigned_integer_set_value(field, 0);
- if (ret) {
- BT_LOGE_STR("Cannot set integer field's value.");
- goto error;
- }
-
- bt_put(field);
- field = bt_field_structure_get_field_by_name(pc, "packet_size");
- if (!field) {
- BT_LOGE_STR("Cannot get `packet_size` field from structure field.");
- goto error;
- }
-
- ret = bt_field_unsigned_integer_set_value(field, 0);
- if (ret) {
- BT_LOGE_STR("Cannot set integer field's value.");
- goto error;
- }
-
- goto end;
-
-error:
- BT_PUT(pc);
+ ret = -1;
end:
- bt_put(field);
- return pc;
+ return ret;
}
static
int create_packet_and_stream(struct dmesg_component *dmesg_comp)
{
int ret = 0;
- struct bt_field_type *ft = NULL;
- struct bt_field *field = NULL;
dmesg_comp->stream = bt_stream_create(dmesg_comp->stream_class,
- NULL);
+ NULL, 0);
if (!dmesg_comp->stream) {
BT_LOGE_STR("Cannot create stream object.");
goto error;
goto error;
}
- ft = bt_trace_get_packet_header_type(dmesg_comp->trace);
- BT_ASSERT(ft);
- field = create_packet_header_field(ft);
- if (!field) {
- BT_LOGE_STR("Cannot create packet header field.");
- goto error;
- }
-
- ret = bt_packet_set_header(dmesg_comp->packet, field);
- if (ret) {
- BT_LOGE_STR("Cannot set packet's header field.");
- goto error;
- }
-
- bt_put(ft);
- bt_put(field);
- ft = bt_stream_class_get_packet_context_type(
- dmesg_comp->stream_class);
- BT_ASSERT(ft);
- field = create_packet_context_field(ft);
- if (!field) {
- BT_LOGE_STR("Cannot create packet context field.");
- goto error;
- }
-
- ret = bt_packet_set_context(dmesg_comp->packet, field);
+ ret = fill_packet_header_field(dmesg_comp->packet);
if (ret) {
- BT_LOGE_STR("Cannot set packet's context field.");
+ BT_LOGE_STR("Cannot fill packet header field.");
goto error;
}
ret = -1;
end:
- bt_put(field);
- bt_put(ft);
return ret;
}
}
static
-int create_event_header_from_line(
+struct bt_notification *create_init_event_notif_from_line(
struct dmesg_component *dmesg_comp,
- const char *line, const char **new_start,
- struct bt_field **user_field,
- struct bt_clock_value **user_clock_value)
+ const char *line, const char **new_start)
{
+ struct bt_event *event;
+ struct bt_notification *notif = NULL;
bool has_timestamp = false;
unsigned long sec, usec, msec;
unsigned int year, mon, mday, hour, min;
uint64_t ts = 0;
- struct bt_clock_value *clock_value = NULL;
- struct bt_field_type *ft = NULL;
struct bt_field *eh_field = NULL;
struct bt_field *ts_field = NULL;
int ret = 0;
- BT_ASSERT(user_clock_value);
- BT_ASSERT(user_field);
*new_start = line;
if (dmesg_comp->params.no_timestamp) {
goto error;
}
- if (dmesg_comp->clock_class) {
- clock_value = bt_clock_value_create(dmesg_comp->clock_class,
- ts);
- if (!clock_value) {
- BT_LOGE_STR("Cannot create clock value object.");
- goto error;
- }
+ notif = bt_notification_event_create(dmesg_comp->event_class,
+ dmesg_comp->packet, dmesg_comp->cc_prio_map);
+ if (!notif) {
+ BT_LOGE_STR("Cannot create event notification.");
+ goto error;
+ }
- ft = bt_stream_class_get_event_header_type(
- dmesg_comp->stream_class);
- BT_ASSERT(ft);
- eh_field = bt_field_create(ft);
- if (!eh_field) {
- BT_LOGE_STR("Cannot create event header field object.");
- goto error;
- }
+ event = bt_notification_event_borrow_event(notif);
+ BT_ASSERT(event);
- ts_field = bt_field_structure_get_field_by_name(eh_field,
+ if (dmesg_comp->clock_class) {
+ struct bt_clock_value *cv = bt_event_borrow_clock_value(event,
+ dmesg_comp->clock_class);
+
+ ret = bt_clock_value_set_value(cv, ts);
+ BT_ASSERT(ret == 0);
+ eh_field = bt_event_borrow_header(event);
+ BT_ASSERT(eh_field);
+ ts_field = bt_field_structure_borrow_field_by_name(eh_field,
"timestamp");
if (!ts_field) {
- BT_LOGE_STR("Cannot get `timestamp` field from structure field.");
- goto error;
- }
-
- ret = bt_field_unsigned_integer_set_value(ts_field, ts);
- if (ret) {
- BT_LOGE_STR("Cannot set integer field's value.");
+ BT_LOGE_STR("Cannot borrow `timestamp` field from event header structure field.");
goto error;
}
- *user_clock_value = clock_value;
- clock_value = NULL;
- *user_field = eh_field;
- eh_field = NULL;
+ ret = bt_field_integer_unsigned_set_value(ts_field, ts);
+ BT_ASSERT(ret == 0);
}
goto end;
error:
- ret = -1;
+ BT_PUT(notif);
end:
- bt_put(ft);
- bt_put(ts_field);
- bt_put(clock_value);
- bt_put(eh_field);
- return ret;
+ return notif;
}
static
-int create_event_payload_from_line(
- struct dmesg_component *dmesg_comp,
- const char *line, struct bt_field **user_field)
+int fill_event_payload_from_line(struct dmesg_component *dmesg_comp,
+ const char *line, struct bt_event *event)
{
- struct bt_field_type *ft = NULL;
struct bt_field *ep_field = NULL;
struct bt_field *str_field = NULL;
size_t len;
int ret;
- BT_ASSERT(user_field);
- ft = bt_event_class_get_payload_type(dmesg_comp->event_class);
- BT_ASSERT(ft);
- ep_field = bt_field_create(ft);
- if (!ep_field) {
- BT_LOGE_STR("Cannot create event payload field object.");
- goto error;
- }
-
- str_field = bt_field_structure_get_field_by_name(ep_field, "str");
+ ep_field = bt_event_borrow_payload(event);
+ BT_ASSERT(ep_field);
+ str_field = bt_field_structure_borrow_field_by_name(ep_field, "str");
if (!str_field) {
- BT_LOGE_STR("Cannot get `timestamp` field from structure field.");
+ BT_LOGE_STR("Cannot borrow `timestamp` field from event payload structure field.");
goto error;
}
len--;
}
+ ret = bt_field_string_clear(str_field);
+ if (ret) {
+ BT_LOGE_STR("Cannot clear string field object.");
+ goto error;
+ }
+
ret = bt_field_string_append_len(str_field, line, len);
if (ret) {
BT_LOGE("Cannot append value to string field object: "
goto error;
}
- *user_field = ep_field;
- ep_field = NULL;
goto end;
error:
ret = -1;
end:
- bt_put(ft);
- bt_put(ep_field);
- bt_put(str_field);
return ret;
}
struct bt_notification *create_notif_from_line(
struct dmesg_component *dmesg_comp, const char *line)
{
- struct bt_field *eh_field = NULL;
- struct bt_field *ep_field = NULL;
- struct bt_clock_value *clock_value = NULL;
struct bt_event *event = NULL;
struct bt_notification *notif = NULL;
const char *new_start;
int ret;
- ret = create_event_header_from_line(dmesg_comp, line, &new_start,
- &eh_field, &clock_value);
- if (ret) {
- BT_LOGE("Cannot create event header field from line: "
- "ret=%d", ret);
+ notif = create_init_event_notif_from_line(dmesg_comp, line, &new_start);
+ if (!notif) {
+ BT_LOGE_STR("Cannot create and initialize event notification from line.");
goto error;
}
- ret = create_event_payload_from_line(dmesg_comp, new_start,
- &ep_field);
+ event = bt_notification_event_borrow_event(notif);
+ BT_ASSERT(event);
+ ret = fill_event_payload_from_line(dmesg_comp, new_start,
+ event);
if (ret) {
- BT_LOGE("Cannot create event payload field from line: "
+ BT_LOGE("Cannot fill event payload field from line: "
"ret=%d", ret);
goto error;
}
- BT_ASSERT(ep_field);
- event = bt_event_create(dmesg_comp->event_class);
- if (!event) {
- BT_LOGE_STR("Cannot create event object.");
- goto error;
- }
-
- ret = bt_event_set_packet(event, dmesg_comp->packet);
- if (ret) {
- BT_LOGE_STR("Cannot set event's packet.");
- goto error;
- }
-
- if (eh_field) {
- ret = bt_event_set_header(event, eh_field);
- if (ret) {
- BT_LOGE_STR("Cannot set event's header field.");
- goto error;
- }
- }
-
- ret = bt_event_set_event_payload(event, ep_field);
- if (ret) {
- BT_LOGE_STR("Cannot set event's payload field.");
- goto error;
- }
-
- if (clock_value) {
- ret = bt_event_set_clock_value(event, clock_value);
- if (ret) {
- BT_LOGE_STR("Cannot set event's clock value.");
- goto error;
- }
- }
-
- notif = bt_notification_event_create(event, dmesg_comp->cc_prio_map);
- if (!notif) {
- BT_LOGE_STR("Cannot create event notification.");
- goto error;
- }
-
goto end;
error:
BT_PUT(notif);
end:
- bt_put(eh_field);
- bt_put(ep_field);
- bt_put(clock_value);
- bt_put(event);
return notif;
}
}
}
+ bt_put(dmesg_notif_iter->tmp_event_notif);
free(dmesg_notif_iter->linebuf);
g_free(dmesg_notif_iter);
}
dmesg_comp = dmesg_notif_iter->dmesg_comp;
BT_ASSERT(dmesg_comp);
+ if (dmesg_notif_iter->state == STATE_DONE) {
+ next_ret.status = BT_NOTIFICATION_ITERATOR_STATUS_END;
+ goto end;
+ }
+
+ if (dmesg_notif_iter->tmp_event_notif ||
+ dmesg_notif_iter->state == STATE_EMIT_PACKET_END ||
+ dmesg_notif_iter->state == STATE_EMIT_STREAM_END) {
+ goto handle_state;
+ }
+
while (true) {
const char *ch;
bool only_spaces = true;
next_ret.status =
BT_NOTIFICATION_ITERATOR_STATUS_NOMEM;
} else {
- next_ret.status =
- BT_NOTIFICATION_ITERATOR_STATUS_END;
+ if (dmesg_notif_iter->state == STATE_EMIT_STREAM_BEGINNING) {
+ /* Stream did not even begin */
+ next_ret.status =
+ BT_NOTIFICATION_ITERATOR_STATUS_END;
+ goto end;
+ } else {
+ /* End current packet now */
+ dmesg_notif_iter->state =
+ STATE_EMIT_PACKET_END;
+ goto handle_state;
+ }
}
goto end;
}
}
- next_ret.notification = create_notif_from_line(dmesg_comp,
+ dmesg_notif_iter->tmp_event_notif = create_notif_from_line(dmesg_comp,
dmesg_notif_iter->linebuf);
- if (!next_ret.notification) {
+ if (!dmesg_notif_iter->tmp_event_notif) {
BT_LOGE("Cannot create event notification from line: "
"dmesg-comp-addr=%p, line=\"%s\"", dmesg_comp,
dmesg_notif_iter->linebuf);
+ goto end;
+ }
+
+handle_state:
+ BT_ASSERT(dmesg_comp->trace);
+
+ switch (dmesg_notif_iter->state) {
+ case STATE_EMIT_STREAM_BEGINNING:
+ BT_ASSERT(dmesg_notif_iter->tmp_event_notif);
+ next_ret.notification = bt_notification_stream_begin_create(
+ dmesg_comp->stream);
+ dmesg_notif_iter->state = STATE_EMIT_PACKET_BEGINNING;
+ break;
+ case STATE_EMIT_PACKET_BEGINNING:
+ BT_ASSERT(dmesg_notif_iter->tmp_event_notif);
+ next_ret.notification = bt_notification_packet_begin_create(
+ dmesg_comp->packet);
+ dmesg_notif_iter->state = STATE_EMIT_EVENT;
+ break;
+ case STATE_EMIT_EVENT:
+ BT_ASSERT(dmesg_notif_iter->tmp_event_notif);
+ BT_MOVE(next_ret.notification,
+ dmesg_notif_iter->tmp_event_notif);
+ break;
+ case STATE_EMIT_PACKET_END:
+ next_ret.notification = bt_notification_packet_end_create(
+ dmesg_comp->packet);
+ dmesg_notif_iter->state = STATE_EMIT_STREAM_END;
+ break;
+ case STATE_EMIT_STREAM_END:
+ next_ret.notification = bt_notification_stream_end_create(
+ dmesg_comp->stream);
+ dmesg_notif_iter->state = STATE_DONE;
+ break;
+ default:
+ break;
+ }
+
+ if (!next_ret.notification) {
+ BT_LOGE("Cannot create notification: dmesg-comp-addr=%p",
+ dmesg_comp);
+ next_ret.status = BT_NOTIFICATION_ITERATOR_STATUS_ERROR;
}
end:
BT_PLUGIN_SINK_COMPONENT_CLASS_DESCRIPTION(pretty,
"Pretty-print notifications (`text` format of Babeltrace 1).");
-#if 0
/* dmesg source */
BT_PLUGIN_SOURCE_COMPONENT_CLASS(dmesg, dmesg_notif_iter_next);
BT_PLUGIN_SOURCE_COMPONENT_CLASS_DESCRIPTION(dmesg,
dmesg_notif_iter_init);
BT_PLUGIN_SOURCE_COMPONENT_CLASS_NOTIFICATION_ITERATOR_FINALIZE_METHOD(dmesg,
dmesg_notif_iter_finalize);
-#endif
enum bt_integer_base base;
enum bt_string_encoding encoding;
int signedness;
+ struct bt_field_type *int_ft;
union {
uint64_t u;
int64_t s;
} v;
bool rst_color = false;
+ enum bt_field_type_id ft_id;
field_type = bt_field_borrow_type(field);
if (!field_type) {
ret = BT_COMPONENT_STATUS_ERROR;
goto end;
}
- signedness = bt_field_type_integer_is_signed(field_type);
+
+ ft_id = bt_field_get_type_id(field);
+
+ switch (ft_id) {
+ case BT_FIELD_TYPE_ID_INTEGER:
+ int_ft = field_type;
+ break;
+ case BT_FIELD_TYPE_ID_ENUM:
+ int_ft = bt_field_type_enumeration_borrow_container_field_type(
+ field_type);
+ break;
+ default:
+ abort();
+ }
+
+ signedness = bt_field_type_integer_is_signed(int_ft);
if (signedness < 0) {
ret = BT_COMPONENT_STATUS_ERROR;
goto end;
}
if (!signedness) {
- if (bt_field_integer_unsigned_get_value(field, &v.u) < 0) {
- ret = BT_COMPONENT_STATUS_ERROR;
- goto end;
- }
+ ret = bt_field_integer_unsigned_get_value(field, &v.u);
} else {
- if (bt_field_integer_signed_get_value(field, &v.s) < 0) {
- ret = BT_COMPONENT_STATUS_ERROR;
- goto end;
- }
+ ret = bt_field_integer_signed_get_value(field, &v.s);
+ }
+
+ if (ret < 0) {
+ ret = BT_COMPONENT_STATUS_ERROR;
+ goto end;
}
- encoding = bt_field_type_integer_get_encoding(field_type);
+ encoding = bt_field_type_integer_get_encoding(int_ft);
switch (encoding) {
case BT_STRING_ENCODING_UTF8:
case BT_STRING_ENCODING_ASCII:
rst_color = true;
}
- base = bt_field_type_integer_get_base(field_type);
+ base = bt_field_type_integer_get_base(int_ft);
switch (base) {
case BT_INTEGER_BASE_BINARY:
{
int bitnr, len;
- len = bt_field_type_integer_get_size(field_type);
+ len = bt_field_type_integer_get_size(int_ft);
if (len < 0) {
ret = BT_COMPONENT_STATUS_ERROR;
goto end;
if (signedness) {
int len;
- len = bt_field_type_integer_get_size(field_type);
+ len = bt_field_type_integer_get_size(int_ft);
if (len < 0) {
ret = BT_COMPONENT_STATUS_ERROR;
goto end;
{
int len;
- len = bt_field_type_integer_get_size(field_type);
+ len = bt_field_type_integer_get_size(int_ft);
if (len < 0) {
ret = BT_COMPONENT_STATUS_ERROR;
goto end;
struct bt_field *field)
{
enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
- struct bt_field *container_field = NULL;
struct bt_field_type *enumeration_field_type = NULL;
struct bt_field_type *container_field_type = NULL;
struct bt_field_type_enumeration_mapping_iterator *iter = NULL;
int nr_mappings = 0;
- int is_signed;
enumeration_field_type = bt_field_borrow_type(field);
if (!enumeration_field_type) {
ret = BT_COMPONENT_STATUS_ERROR;
goto end;
}
- container_field = bt_field_enumeration_borrow_container(field);
- if (!container_field) {
- ret = BT_COMPONENT_STATUS_ERROR;
- goto end;
- }
- container_field_type = bt_field_borrow_type(container_field);
+ container_field_type =
+ bt_field_type_enumeration_borrow_container_field_type(
+ enumeration_field_type);
if (!container_field_type) {
ret = BT_COMPONENT_STATUS_ERROR;
goto end;
}
- is_signed = bt_field_type_integer_is_signed(container_field_type);
- if (is_signed < 0) {
+ iter = bt_field_enumeration_get_mappings(field);
+ if (!iter) {
ret = BT_COMPONENT_STATUS_ERROR;
goto end;
}
- if (is_signed) {
- int64_t value;
-
- if (bt_field_integer_signed_get_value(container_field,
- &value)) {
- ret = BT_COMPONENT_STATUS_ERROR;
- goto end;
- }
- iter = bt_field_type_enumeration_signed_find_mappings_by_value(
- enumeration_field_type, value);
- } else {
- uint64_t value;
-
- if (bt_field_integer_unsigned_get_value(container_field,
- &value)) {
- ret = BT_COMPONENT_STATUS_ERROR;
- goto end;
- }
- iter = bt_field_type_enumeration_unsigned_find_mappings_by_value(
- enumeration_field_type, value);
- }
g_string_append(pretty->string, "( ");
ret = bt_field_type_enumeration_mapping_iterator_next(iter);
if (ret) {
}
skip_loop:
g_string_append(pretty->string, " : container = ");
- ret = print_integer(pretty, container_field);
+ ret = print_integer(pretty, field);
if (ret != BT_COMPONENT_STATUS_OK) {
goto end;
}
{
enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
struct bt_field_type *seq_type = NULL, *field_type = NULL;
- struct bt_field *length_field = NULL;
enum bt_field_type_id type_id;
- uint64_t len;
+ int64_t len;
uint64_t i;
bool is_string = false;
ret = BT_COMPONENT_STATUS_ERROR;
goto end;
}
- length_field = bt_field_sequence_borrow_length(seq);
- if (!length_field) {
- ret = BT_COMPONENT_STATUS_ERROR;
- goto end;
- }
- if (bt_field_integer_unsigned_get_value(length_field, &len) < 0) {
+ len = bt_field_sequence_get_length(seq);
+ if (len < 0) {
ret = BT_COMPONENT_STATUS_ERROR;
goto end;
}
g_string_append(pretty->string, "{ ");
pretty->depth++;
if (print_names) {
- int iter_ret;
- struct bt_field *tag_field = NULL;
+ int iret;
+ struct bt_field_type *var_ft;
+ struct bt_field_type *tag_ft;
+ struct bt_field_type *container_ft;
const char *tag_choice;
+ bt_bool is_signed;
struct bt_field_type_enumeration_mapping_iterator *iter;
- tag_field = bt_field_variant_borrow_tag(variant);
- if (!tag_field) {
+ var_ft = bt_field_borrow_type(variant);
+ tag_ft = bt_field_type_variant_borrow_tag_field_type(
+ var_ft);
+ container_ft =
+ bt_field_type_enumeration_borrow_container_field_type(
+ tag_ft);
+ is_signed = bt_field_type_integer_is_signed(container_ft);
+
+ if (is_signed) {
+ int64_t tag;
+
+ iret = bt_field_variant_get_tag_signed(variant, &tag);
+ if (iret) {
+ ret = BT_COMPONENT_STATUS_ERROR;
+ goto end;
+ }
+
+ iter = bt_field_type_enumeration_signed_find_mappings_by_value(
+ tag_ft, tag);
+ } else {
+ uint64_t tag;
+
+ iret = bt_field_variant_get_tag_unsigned(variant, &tag);
+ if (iret) {
+ ret = BT_COMPONENT_STATUS_ERROR;
+ goto end;
+ }
+
+ iter = bt_field_type_enumeration_unsigned_find_mappings_by_value(
+ tag_ft, tag);
+ }
+
+ if (!iter) {
ret = BT_COMPONENT_STATUS_ERROR;
goto end;
}
- iter = bt_field_enumeration_get_mappings(tag_field);
- iter_ret = bt_field_type_enumeration_mapping_iterator_next(
+ iret = bt_field_type_enumeration_mapping_iterator_next(
iter);
if (!iter || ret) {
ret = BT_COMPONENT_STATUS_ERROR;
goto end;
}
- iter_ret =
+ iret =
bt_field_type_enumeration_mapping_iterator_signed_get(
iter, &tag_choice, NULL, NULL);
- if (iter_ret) {
+ if (iret) {
bt_put(iter);
ret = BT_COMPONENT_STATUS_ERROR;
goto end;
return BT_NOTIFICATION_ITERATOR_STATUS_OK;
}
-static
-struct bt_event *src_create_event(struct bt_packet *packet)
-{
- struct bt_event *event = bt_event_create(src_event_class);
- int ret;
-
- assert(event);
- ret = bt_event_set_packet(event, packet);
- assert(ret == 0);
- return event;
-}
-
static
struct bt_notification_iterator_next_method_return src_iter_next_seq(
struct src_iter_user_data *user_data)
}
if (event_packet) {
- struct bt_event *event = src_create_event(event_packet);
-
- assert(event);
- next_return.notification = bt_notification_event_create(event,
+ next_return.notification =
+ bt_notification_event_create(src_event_class,
+ event_packet,
src_empty_cc_prio_map);
- bt_put(event);
assert(next_return.notification);
}
struct bt_event *event;
test_event.type = TEST_EV_TYPE_NOTIF_EVENT;
- event = bt_notification_event_get_event(notification);
+ event = bt_notification_event_borrow_event(notification);
assert(event);
- test_event.packet = bt_event_get_packet(event);
- bt_put(event);
+ test_event.packet = bt_event_borrow_packet(event);
assert(test_event.packet);
- bt_put(test_event.packet);
break;
}
case BT_NOTIFICATION_TYPE_INACTIVITY:
case BT_NOTIFICATION_TYPE_STREAM_BEGIN:
test_event.type = TEST_EV_TYPE_NOTIF_STREAM_BEGIN;
test_event.stream =
- bt_notification_stream_begin_get_stream(notification);
+ bt_notification_stream_begin_borrow_stream(notification);
assert(test_event.stream);
- bt_put(test_event.stream);
break;
case BT_NOTIFICATION_TYPE_STREAM_END:
test_event.type = TEST_EV_TYPE_NOTIF_STREAM_END;
test_event.stream =
- bt_notification_stream_end_get_stream(notification);
+ bt_notification_stream_end_borrow_stream(notification);
assert(test_event.stream);
- bt_put(test_event.stream);
break;
case BT_NOTIFICATION_TYPE_PACKET_BEGIN:
test_event.type = TEST_EV_TYPE_NOTIF_PACKET_BEGIN;
test_event.packet =
- bt_notification_packet_begin_get_packet(notification);
+ bt_notification_packet_begin_borrow_packet(notification);
assert(test_event.packet);
- bt_put(test_event.packet);
break;
case BT_NOTIFICATION_TYPE_PACKET_END:
test_event.type = TEST_EV_TYPE_NOTIF_PACKET_END;
test_event.packet =
- bt_notification_packet_end_get_packet(notification);
+ bt_notification_packet_end_borrow_packet(notification);
assert(test_event.packet);
- bt_put(test_event.packet);
break;
default:
test_event.type = TEST_EV_TYPE_NOTIF_UNEXPECTED;
}
if (test_event.packet) {
- test_event.stream = bt_packet_get_stream(test_event.packet);
+ test_event.stream = bt_packet_borrow_stream(test_event.packet);
assert(test_event.stream);
- bt_put(test_event.stream);
}
end:
#define DEFAULT_CLOCK_TIME 0
#define DEFAULT_CLOCK_VALUE 0
-#define NR_TESTS 347
+#define NR_TESTS 346
struct bt_utsname {
char sysname[BABELTRACE_HOST_NAME_MAX];
*inner_structure_field, *complex_structure_field,
*a_sequence_field, *enum_variant_field, *enum_container_field,
*variant_field, *an_array_field, *stream_event_ctx_field,
- *stream_event_ctx_int_field, *ret_field;
+ *stream_event_ctx_int_field;
uint64_t ret_unsigned_int;
int64_t ret_signed_int;
const char *ret_string;
ok(bt_ctf_field_sequence_set_length(a_sequence_field,
uint_35_field) == 0, "Set a sequence field's length");
- ret_field = bt_ctf_field_sequence_get_length(a_sequence_field);
- ok(ret_field == uint_35_field,
- "bt_ctf_field_sequence_get_length returns the correct length field");
for (i = 0; i < SEQUENCE_TEST_LENGTH; i++) {
int_16_field = bt_ctf_field_sequence_get_field(
bt_put(enum_variant_field);
bt_put(enum_container_field);
bt_put(variant_field);
- bt_put(ret_field);
bt_put(packet_context_field);
bt_put(packet_context);
bt_put(uint_35_type);
struct bt_trace *trace;
struct bt_stream *stream;
struct bt_field_type *empty_struct_ft;
+ struct bt_field_type *eh_ft;
+ struct bt_field_type *eh_ts_ft;
/* Test events */
test_events = g_array_new(FALSE, TRUE, sizeof(struct test_event));
/* Metadata */
empty_struct_ft = bt_field_type_structure_create();
assert(empty_struct_ft);
+ src_clock_class = bt_clock_class_create("my-clock", 1000000000);
+ assert(src_clock_class);
trace = bt_trace_create();
assert(trace);
ret = bt_trace_set_native_byte_order(trace,
assert(ret == 0);
ret = bt_trace_set_packet_header_field_type(trace, empty_struct_ft);
assert(ret == 0);
- src_clock_class = bt_clock_class_create("my-clock", 1000000000);
- assert(src_clock_class);
ret = bt_clock_class_set_is_absolute(src_clock_class, 1);
assert(ret == 0);
ret = bt_trace_add_clock_class(trace, src_clock_class);
ret = bt_stream_class_set_packet_context_field_type(src_stream_class,
empty_struct_ft);
assert(ret == 0);
+ eh_ft = bt_field_type_structure_create();
+ assert(eh_ft);
+ eh_ts_ft = bt_field_type_integer_create(64);
+ assert(eh_ts_ft);
+ ret = bt_field_type_structure_add_field(eh_ft, eh_ts_ft, "ts");
+ assert(ret == 0);
+ ret = bt_field_type_integer_set_mapped_clock_class(eh_ts_ft,
+ src_clock_class);
+ assert(ret == 0);
ret = bt_stream_class_set_event_header_field_type(src_stream_class,
- empty_struct_ft);
+ eh_ft);
assert(ret == 0);
ret = bt_stream_class_set_event_context_field_type(src_stream_class,
empty_struct_ft);
bt_put(trace);
bt_put(empty_struct_ft);
+ bt_put(eh_ft);
+ bt_put(eh_ts_ft);
}
static
}
static
-struct bt_event *src_create_event(struct bt_packet *packet,
- int64_t ts_ns)
+struct bt_notification *src_create_event_notif(struct bt_packet *packet,
+ struct bt_clock_class_priority_map *cc_prio_map, int64_t ts_ns)
{
- struct bt_event *event = bt_event_create(src_event_class);
int ret;
-
+ struct bt_event *event;
+ struct bt_notification *notif;
+ struct bt_clock_value *clock_value;
+ struct bt_field *field;
+
+ notif = bt_notification_event_create(src_event_class,
+ packet, cc_prio_map);
+ assert(notif);
+ event = bt_notification_event_borrow_event(notif);
assert(event);
- ret = bt_event_set_packet(event, packet);
+ field = bt_event_borrow_header(event);
+ assert(field);
+ field = bt_field_structure_borrow_field_by_name(field, "ts");
+ assert(field);
+ ret = bt_field_integer_unsigned_set_value(field, (uint64_t) ts_ns);
assert(ret == 0);
-
- if (ts_ns != -1) {
- struct bt_clock_value *clock_value;
-
- clock_value = bt_clock_value_create(src_clock_class,
- (uint64_t) ts_ns);
- assert(clock_value);
- ret = bt_event_set_clock_value(event, clock_value);
- assert(ret == 0);
- bt_put(clock_value);
- }
-
- return event;
+ clock_value = bt_event_borrow_clock_value(event, src_clock_class);
+ assert(clock_value);
+ ret = bt_clock_value_set_value(clock_value, (uint64_t) ts_ns);
+ assert(ret == 0);
+ return notif;
}
static
break;
default:
{
- struct bt_event *event = src_create_event(
- user_data->packet, cur_ts_ns);
-
- assert(event);
- next_return.notification = bt_notification_event_create(event,
- src_cc_prio_map);
- bt_put(event);
+ next_return.notification = src_create_event_notif(
+ user_data->packet, src_cc_prio_map, cur_ts_ns);
assert(next_return.notification);
break;
}
user_data->packet);
assert(next_return.notification);
} else if (user_data->at < 7) {
- struct bt_event *event = src_create_event(
- user_data->packet, -1);
-
- assert(event);
next_return.notification =
- bt_notification_event_create(event,
- src_empty_cc_prio_map);
+ src_create_event_notif(
+ user_data->packet,
+ src_empty_cc_prio_map, 0);
assert(next_return.notification);
- bt_put(event);
} else if (user_data->at == 7) {
next_return.notification =
bt_notification_packet_end_create(
test_event.type = TEST_EV_TYPE_NOTIF_EVENT;
cc_prio_map =
- bt_notification_event_get_clock_class_priority_map(
+ bt_notification_event_borrow_clock_class_priority_map(
notification);
assert(cc_prio_map);
- event = bt_notification_event_get_event(notification);
+ event = bt_notification_event_borrow_event(notification);
assert(event);
if (bt_clock_class_priority_map_get_clock_class_count(cc_prio_map) > 0) {
struct bt_clock_value *clock_value;
struct bt_clock_class *clock_class =
- bt_clock_class_priority_map_get_highest_priority_clock_class(
+ bt_clock_class_priority_map_borrow_highest_priority_clock_class(
cc_prio_map);
assert(clock_class);
- clock_value = bt_event_get_clock_value(event,
+ clock_value = bt_event_borrow_clock_value(event,
clock_class);
assert(clock_value);
ret = bt_clock_value_get_value_ns_from_epoch(
clock_value, &test_event.ts_ns);
assert(ret == 0);
- bt_put(clock_value);
- bt_put(clock_class);
} else {
test_event.ts_ns = -1;
}
- bt_put(cc_prio_map);
- bt_put(event);
break;
}
case BT_NOTIFICATION_TYPE_INACTIVITY:
struct bt_clock_class_priority_map *cc_prio_map;
test_event.type = TEST_EV_TYPE_NOTIF_INACTIVITY;
- cc_prio_map = bt_notification_event_get_clock_class_priority_map(
+ cc_prio_map = bt_notification_inactivity_borrow_clock_class_priority_map(
notification);
assert(cc_prio_map);
if (bt_clock_class_priority_map_get_clock_class_count(cc_prio_map) > 0) {
struct bt_clock_value *clock_value;
struct bt_clock_class *clock_class =
- bt_clock_class_priority_map_get_highest_priority_clock_class(
+ bt_clock_class_priority_map_borrow_highest_priority_clock_class(
cc_prio_map);
assert(clock_class);
clock_value =
- bt_notification_inactivity_get_clock_value(
+ bt_notification_inactivity_borrow_clock_value(
notification, clock_class);
assert(clock_value);
ret = bt_clock_value_get_value_ns_from_epoch(
clock_value, &test_event.ts_ns);
assert(ret == 0);
- bt_put(clock_value);
- bt_put(clock_class);
} else {
test_event.ts_ns = -1;
}
- bt_put(cc_prio_map);
break;
}
case BT_NOTIFICATION_TYPE_PACKET_BEGIN: