#include <inttypes.h>
#include <stdint.h>
#include <string.h>
+#include <stdlib.h>
#define DEFAULT_IDENTIFIER_SIZE 128
#define DEFAULT_METADATA_STRING_SIZE 4096
void *data;
};
+struct bt_ctf_trace_is_static_listener_elem {
+ bt_ctf_trace_is_static_listener func;
+ bt_ctf_trace_listener_removed removed;
+ void *data;
+};
+
static
void bt_ctf_trace_destroy(struct bt_object *obj);
static
struct bt_ctf_trace *bt_ctf_trace_create(void)
{
struct bt_ctf_trace *trace = NULL;
- struct bt_ctf_field_type *packet_header_type = NULL;
trace = g_new0(struct bt_ctf_trace, 1);
if (!trace) {
}
BT_LOGD_STR("Creating trace object.");
- trace->native_byte_order = BT_CTF_BYTE_ORDER_NATIVE;
+ trace->native_byte_order = BT_CTF_BYTE_ORDER_UNSPECIFIED;
bt_object_init(trace, bt_ctf_trace_destroy);
trace->clocks = g_ptr_array_new_with_free_func(
(GDestroyNotify) bt_put);
goto error;
}
- packet_header_type = bt_ctf_field_type_structure_create();
- if (!packet_header_type) {
- goto error;
- }
-
- BT_MOVE(trace->packet_header_type, packet_header_type);
-
/* Create the environment array object */
trace->environment = bt_ctf_attributes_create();
if (!trace->environment) {
goto error;
}
+ trace->is_static_listeners = g_array_new(FALSE, TRUE,
+ sizeof(struct bt_ctf_trace_is_static_listener_elem));
+ if (!trace->is_static_listeners) {
+ BT_LOGE_STR("Failed to allocate one GArray.");
+ goto error;
+ }
+
BT_LOGD("Created trace object: addr=%p", trace);
return trace;
error:
BT_PUT(trace);
- bt_put(packet_header_type);
return trace;
}
goto end;
}
- memcpy(trace->uuid, uuid, sizeof(uuid_t));
+ memcpy(trace->uuid, uuid, BABELTRACE_UUID_LEN);
trace->uuid_set = BT_TRUE;
BT_LOGV("Set trace's UUID: addr=%p, name=\"%s\", "
"uuid=\"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\"",
BT_LOGD("Destroying trace object: addr=%p, name=\"%s\"",
trace, bt_ctf_trace_get_name(trace));
+ /*
+ * Call remove listeners first so that everything else still
+ * exists in the trace.
+ */
+ if (trace->is_static_listeners) {
+ size_t i;
+
+ for (i = 0; i < trace->is_static_listeners->len; i++) {
+ struct bt_ctf_trace_is_static_listener_elem elem =
+ g_array_index(trace->is_static_listeners,
+ struct bt_ctf_trace_is_static_listener_elem, i);
+
+ if (elem.removed) {
+ elem.removed(trace, elem.data);
+ }
+ }
+
+ g_array_free(trace->is_static_listeners, TRUE);
+ }
+
+ if (trace->listeners) {
+ g_ptr_array_free(trace->listeners, TRUE);
+ }
+
if (trace->environment) {
BT_LOGD_STR("Destroying environment attributes.");
bt_ctf_attributes_destroy(trace->environment);
g_ptr_array_free(trace->stream_classes, TRUE);
}
- if (trace->listeners) {
- g_ptr_array_free(trace->listeners, TRUE);
- }
-
BT_LOGD_STR("Putting packet header field type.");
bt_put(trace->packet_header_type);
g_free(trace);
BT_PUT(field_type);
}
+ /*
+ * If there's a `packet_seq_num` field, it must be an unsigned
+ * integer field type.
+ */
+ field_type = bt_ctf_field_type_structure_get_field_type_by_name(
+ packet_header_type, "packet_seq_num");
+ if (field_type) {
+ if (!bt_ctf_field_type_is_integer(field_type)) {
+ BT_LOGW("Invalid packet header field type: `packet_seq_num` field must be an integer field type: "
+ "stream-id-ft-addr=%p, packet-seq-num-ft-id=%s",
+ field_type,
+ bt_ctf_field_type_id_string(field_type->id));
+ goto invalid;
+ }
+
+ if (bt_ctf_field_type_integer_is_signed(field_type)) {
+ BT_LOGW("Invalid packet header field type: `packet_seq_num` field must be an unsigned integer field type: "
+ "packet-seq-num-ft-addr=%p", field_type);
+ goto invalid;
+ }
+
+ BT_PUT(field_type);
+ }
+
goto end;
invalid:
stream_class, bt_ctf_stream_class_get_name(stream_class),
bt_ctf_stream_class_get_id(stream_class));
- /*
- * At the end of this function we freeze the trace, so its
- * native byte order must NOT be BT_CTF_BYTE_ORDER_NATIVE.
- */
- if (trace->native_byte_order == BT_CTF_BYTE_ORDER_NATIVE) {
- BT_LOGW_STR("Invalid parameter: trace's byte order cannot be BT_CTF_BYTE_ORDER_NATIVE at this point; "
- "set it with bt_ctf_trace_set_native_byte_order().");
- ret = -1;
- goto end;
- }
-
current_parent_trace = bt_ctf_stream_class_get_trace(stream_class);
if (current_parent_trace) {
/* Stream class is already associated to a trace, abort. */
string = "native";
break;
default:
- assert(BT_FALSE);
+ abort();
}
return string;
unsigned char *uuid = trace->uuid;
int ret = 0;
- if (trace->native_byte_order == BT_CTF_BYTE_ORDER_NATIVE) {
- BT_LOGW("Invalid parameter: trace's byte order cannot be BT_CTF_BYTE_ORDER_NATIVE at this point; "
+ if (trace->native_byte_order == BT_CTF_BYTE_ORDER_NATIVE ||
+ trace->native_byte_order == BT_CTF_BYTE_ORDER_UNSPECIFIED) {
+ BT_LOGW("Invalid parameter: trace's byte order cannot be BT_CTF_BYTE_ORDER_NATIVE or BT_CTF_BYTE_ORDER_UNSPECIFIED at this point; "
"set it with bt_ctf_trace_set_native_byte_order(): "
"addr=%p, name=\"%s\"",
trace, bt_ctf_trace_get_name(trace));
goto end;
}
+ if (trace->is_created_by_writer &&
+ byte_order == BT_CTF_BYTE_ORDER_UNSPECIFIED) {
+ BT_LOGW("Invalid parameter: BT_CTF_BYTE_ORDER_UNSPECIFIED byte order is not allowed for a CTF writer trace: "
+ "addr=%p, name=\"%s\"",
+ trace, bt_ctf_trace_get_name(trace));
+ ret = -1;
+ goto end;
+ }
+
if (byte_order != BT_CTF_BYTE_ORDER_LITTLE_ENDIAN &&
byte_order != BT_CTF_BYTE_ORDER_BIG_ENDIAN &&
byte_order != BT_CTF_BYTE_ORDER_NETWORK) {
int bt_ctf_trace_set_is_static(struct bt_ctf_trace *trace)
{
int ret = 0;
+ size_t i;
if (!trace) {
BT_LOGW_STR("Invalid parameter: trace is NULL.");
BT_LOGV("Set trace static: addr=%p, name=\"%s\"",
trace, bt_ctf_trace_get_name(trace));
+ /* Call all the "trace is static" listeners */
+ for (i = 0; i < trace->is_static_listeners->len; i++) {
+ struct bt_ctf_trace_is_static_listener_elem elem =
+ g_array_index(trace->is_static_listeners,
+ struct bt_ctf_trace_is_static_listener_elem, i);
+
+ if (elem.func) {
+ elem.func(trace, elem.data);
+ }
+ }
+
+end:
+ return ret;
+}
+
+int bt_ctf_trace_add_is_static_listener(struct bt_ctf_trace *trace,
+ bt_ctf_trace_is_static_listener listener,
+ bt_ctf_trace_listener_removed listener_removed, void *data)
+{
+ int i;
+ struct bt_ctf_trace_is_static_listener_elem new_elem = {
+ .func = listener,
+ .removed = listener_removed,
+ .data = data,
+ };
+
+ if (!trace) {
+ BT_LOGW_STR("Invalid parameter: trace is NULL.");
+ i = -1;
+ goto end;
+ }
+
+ if (!listener) {
+ BT_LOGW_STR("Invalid parameter: listener is NULL.");
+ i = -1;
+ goto end;
+ }
+
+ if (trace->is_static) {
+ BT_LOGW("Invalid parameter: trace is already static: "
+ "addr=%p, name=\"%s\"",
+ trace, bt_ctf_trace_get_name(trace));
+ i = -1;
+ goto end;
+ }
+
+ if (trace->in_remove_listener) {
+ BT_LOGW("Cannot call this function during the execution of a remove listener: "
+ "addr=%p, name=\"%s\"",
+ trace, bt_ctf_trace_get_name(trace));
+ i = -1;
+ goto end;
+ }
+
+ /* Find the next available spot */
+ for (i = 0; i < trace->is_static_listeners->len; i++) {
+ struct bt_ctf_trace_is_static_listener_elem elem =
+ g_array_index(trace->is_static_listeners,
+ struct bt_ctf_trace_is_static_listener_elem, i);
+
+ if (!elem.func) {
+ break;
+ }
+ }
+
+ if (i == trace->is_static_listeners->len) {
+ g_array_append_val(trace->is_static_listeners, new_elem);
+ } else {
+ g_array_insert_val(trace->is_static_listeners, i, new_elem);
+ }
+
+ BT_LOGV("Added \"trace is static\" listener: "
+ "trace-addr=%p, trace-name=\"%s\", func-addr=%p, "
+ "data-addr=%p, listener-id=%d",
+ trace, bt_ctf_trace_get_name(trace), listener, data, i);
+
+end:
+ return i;
+}
+
+int bt_ctf_trace_remove_is_static_listener(
+ struct bt_ctf_trace *trace, int listener_id)
+{
+ int ret = 0;
+ struct bt_ctf_trace_is_static_listener_elem *elem;
+
+ if (!trace) {
+ BT_LOGW_STR("Invalid parameter: trace is NULL.");
+ ret = -1;
+ goto end;
+ }
+
+ if (trace->in_remove_listener) {
+ BT_LOGW("Cannot call this function during the execution of a remove listener: "
+ "addr=%p, name=\"%s\", listener-id=%d",
+ trace, bt_ctf_trace_get_name(trace),
+ listener_id);
+ ret = -1;
+ goto end;
+ }
+
+ if (listener_id < 0) {
+ BT_LOGW("Invalid listener ID: must be zero or positive: "
+ "listener-id=%d", listener_id);
+ ret = -1;
+ goto end;
+ }
+
+ if (listener_id >= trace->is_static_listeners->len) {
+ BT_LOGW("Invalid parameter: no listener with this listener ID: "
+ "addr=%p, name=\"%s\", listener-id=%d",
+ trace, bt_ctf_trace_get_name(trace),
+ listener_id);
+ ret = -1;
+ goto end;
+ }
+
+ elem = &g_array_index(trace->is_static_listeners,
+ struct bt_ctf_trace_is_static_listener_elem,
+ listener_id);
+ if (!elem->func) {
+ BT_LOGW("Invalid parameter: no listener with this listener ID: "
+ "addr=%p, name=\"%s\", listener-id=%d",
+ trace, bt_ctf_trace_get_name(trace),
+ listener_id);
+ ret = -1;
+ goto end;
+ }
+
+ if (elem->removed) {
+ /* Call remove listener */
+ BT_LOGV("Calling remove listener: "
+ "trace-addr=%p, trace-name=\"%s\", "
+ "listener-id=%d", trace, bt_ctf_trace_get_name(trace),
+ listener_id);
+ trace->in_remove_listener = BT_TRUE;
+ elem->removed(trace, elem->data);
+ trace->in_remove_listener = BT_FALSE;
+ }
+
+ elem->func = NULL;
+ elem->removed = NULL;
+ elem->data = NULL;
+ BT_LOGV("Removed \"trace is static\" listener: "
+ "trace-addr=%p, trace-name=\"%s\", "
+ "listener-id=%d", trace, bt_ctf_trace_get_name(trace),
+ listener_id);
+
end:
return ret;
}