2 * SPDX-License-Identifier: MIT
4 * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
5 * Copyright 2017-2018 Philippe Proulx <pproulx@efficios.com>
8 #define BT_LOG_TAG "CTF-WRITER/EVENT-CLASS"
15 #include <babeltrace2-ctf-writer/event.h>
16 #include <babeltrace2-ctf-writer/field-types.h>
17 #include <babeltrace2-ctf-writer/object.h>
18 #include <babeltrace2-ctf-writer/stream-class.h>
19 #include <babeltrace2-ctf-writer/utils.h>
20 #include <babeltrace2/types.h>
22 #include "common/assert.h"
23 #include "compat/compiler.h"
24 #include "compat/endian.h"
26 #include "assert-pre.h"
27 #include "attributes.h"
28 #include "event-class.h"
31 #include "field-types.h"
32 #include "stream-class.h"
35 #include "validation.h"
39 void bt_ctf_event_class_common_finalize(struct bt_ctf_object
*obj
)
41 struct bt_ctf_event_class_common
*event_class
;
43 event_class
= container_of(obj
, struct bt_ctf_event_class_common
, base
);
44 BT_LOGD("Finalizing common event class: addr=%p, name=\"%s\", id=%" PRId64
,
45 event_class
, bt_ctf_event_class_common_get_name(event_class
),
46 bt_ctf_event_class_common_get_id(event_class
));
48 if (event_class
->name
) {
49 g_string_free(event_class
->name
, TRUE
);
52 if (event_class
->emf_uri
) {
53 g_string_free(event_class
->emf_uri
, TRUE
);
56 BT_LOGD_STR("Putting context field type.");
57 bt_ctf_object_put_ref(event_class
->context_field_type
);
58 BT_LOGD_STR("Putting payload field type.");
59 bt_ctf_object_put_ref(event_class
->payload_field_type
);
62 int bt_ctf_event_class_common_initialize(struct bt_ctf_event_class_common
*event_class
,
63 const char *name
, bt_ctf_object_release_func release_func
,
64 bt_ctf_field_type_structure_create_func ft_struct_create_func
)
68 BT_LOGD("Initializing common event class object: name=\"%s\"",
70 bt_ctf_object_init_shared_with_parent(&event_class
->base
, release_func
);
71 event_class
->payload_field_type
= ft_struct_create_func();
72 if (!event_class
->payload_field_type
) {
73 BT_LOGE_STR("Cannot create event class's initial payload field type object.");
78 event_class
->name
= g_string_new(name
);
79 if (!event_class
->name
) {
80 BT_LOGE_STR("Failed to allocate a GString.");
84 event_class
->emf_uri
= g_string_new(NULL
);
85 if (!event_class
->emf_uri
) {
86 BT_LOGE_STR("Failed to allocate a GString.");
90 event_class
->log_level
= BT_CTF_EVENT_CLASS_LOG_LEVEL_UNSPECIFIED
;
91 BT_LOGD("Initialized common event class object: addr=%p, name=\"%s\"",
92 event_class
, bt_ctf_event_class_common_get_name(event_class
));
100 void bt_ctf_event_class_common_freeze(struct bt_ctf_event_class_common
*event_class
)
102 BT_ASSERT_DBG(event_class
);
104 if (event_class
->frozen
) {
108 BT_LOGD("Freezing event class: addr=%p, name=\"%s\", id=%" PRId64
,
109 event_class
, bt_ctf_event_class_common_get_name(event_class
),
110 bt_ctf_event_class_common_get_id(event_class
));
111 event_class
->frozen
= 1;
112 BT_LOGD_STR("Freezing event class's context field type.");
113 bt_ctf_field_type_common_freeze(event_class
->context_field_type
);
114 BT_LOGD_STR("Freezing event class's payload field type.");
115 bt_ctf_field_type_common_freeze(event_class
->payload_field_type
);
118 int bt_ctf_event_class_common_validate_single_clock_class(
119 struct bt_ctf_event_class_common
*event_class
,
120 struct bt_ctf_clock_class
**expected_clock_class
)
124 BT_ASSERT_DBG(event_class
);
125 BT_ASSERT_DBG(expected_clock_class
);
126 ret
= bt_ctf_field_type_common_validate_single_clock_class(
127 event_class
->context_field_type
,
128 expected_clock_class
);
130 BT_LOGW("Event class's context field type "
131 "is not recursively mapped to the "
132 "expected clock class: "
133 "event-class-addr=%p, "
134 "event-class-name=\"%s\", "
135 "event-class-id=%" PRId64
", "
138 bt_ctf_event_class_common_get_name(event_class
),
140 event_class
->context_field_type
);
144 ret
= bt_ctf_field_type_common_validate_single_clock_class(
145 event_class
->payload_field_type
,
146 expected_clock_class
);
148 BT_LOGW("Event class's payload field type "
149 "is not recursively mapped to the "
150 "expected clock class: "
151 "event-class-addr=%p, "
152 "event-class-name=\"%s\", "
153 "event-class-id=%" PRId64
", "
156 bt_ctf_event_class_common_get_name(event_class
),
158 event_class
->payload_field_type
);
167 void bt_ctf_event_class_destroy(struct bt_ctf_object
*obj
)
169 bt_ctf_event_class_common_finalize(obj
);
174 struct bt_ctf_event_class
*bt_ctf_event_class_create(const char *name
)
176 struct bt_ctf_event_class
*ctf_event_class
= NULL
;
180 BT_LOGW_STR("Invalid parameter: name is NULL.");
184 BT_LOGD("Creating event class object: name=\"%s\"",
186 ctf_event_class
= g_new0(struct bt_ctf_event_class
, 1);
187 if (!ctf_event_class
) {
188 BT_LOGE_STR("Failed to allocate one event class.");
192 ret
= bt_ctf_event_class_common_initialize(BT_CTF_TO_COMMON(ctf_event_class
),
193 name
, bt_ctf_event_class_destroy
,
194 (bt_ctf_field_type_structure_create_func
)
195 bt_ctf_field_type_structure_create
);
203 bt_ctf_object_put_ref(ctf_event_class
);
206 return ctf_event_class
;
210 const char *bt_ctf_event_class_get_name(struct bt_ctf_event_class
*event_class
)
212 return bt_ctf_event_class_common_get_name(BT_CTF_TO_COMMON(event_class
));
216 int64_t bt_ctf_event_class_get_id(struct bt_ctf_event_class
*event_class
)
218 return bt_ctf_event_class_common_get_id(BT_CTF_TO_COMMON(event_class
));
222 int bt_ctf_event_class_set_id(struct bt_ctf_event_class
*event_class
,
225 return bt_ctf_event_class_common_set_id(BT_CTF_TO_COMMON(event_class
), id
);
229 enum bt_ctf_event_class_log_level
bt_ctf_event_class_get_log_level(
230 struct bt_ctf_event_class
*event_class
)
232 return bt_ctf_event_class_common_get_log_level(BT_CTF_TO_COMMON(event_class
));
236 int bt_ctf_event_class_set_log_level(struct bt_ctf_event_class
*event_class
,
237 enum bt_ctf_event_class_log_level log_level
)
239 return bt_ctf_event_class_common_set_log_level(BT_CTF_TO_COMMON(event_class
),
244 const char *bt_ctf_event_class_get_emf_uri(
245 struct bt_ctf_event_class
*event_class
)
247 return bt_ctf_event_class_common_get_emf_uri(BT_CTF_TO_COMMON(event_class
));
251 int bt_ctf_event_class_set_emf_uri(struct bt_ctf_event_class
*event_class
,
254 return bt_ctf_event_class_common_set_emf_uri(BT_CTF_TO_COMMON(event_class
),
259 struct bt_ctf_stream_class
*bt_ctf_event_class_get_stream_class(
260 struct bt_ctf_event_class
*event_class
)
262 BT_CTF_ASSERT_PRE_NON_NULL(event_class
, "Event class");
263 return bt_ctf_object_get_ref(bt_ctf_event_class_common_borrow_stream_class(
264 BT_CTF_TO_COMMON(event_class
)));
268 struct bt_ctf_field_type
*bt_ctf_event_class_get_payload_field_type(
269 struct bt_ctf_event_class
*event_class
)
271 return bt_ctf_object_get_ref(bt_ctf_event_class_common_borrow_payload_field_type(
272 BT_CTF_TO_COMMON(event_class
)));
276 int bt_ctf_event_class_set_payload_field_type(
277 struct bt_ctf_event_class
*event_class
,
278 struct bt_ctf_field_type
*field_type
)
280 return bt_ctf_event_class_common_set_payload_field_type(
281 BT_CTF_TO_COMMON(event_class
), (void *) field_type
);
285 struct bt_ctf_field_type
*bt_ctf_event_class_get_context_field_type(
286 struct bt_ctf_event_class
*event_class
)
288 return bt_ctf_object_get_ref(bt_ctf_event_class_common_borrow_context_field_type(
289 BT_CTF_TO_COMMON(event_class
)));
293 int bt_ctf_event_class_set_context_field_type(
294 struct bt_ctf_event_class
*event_class
,
295 struct bt_ctf_field_type
*field_type
)
297 return bt_ctf_event_class_common_set_context_field_type(
298 BT_CTF_TO_COMMON(event_class
), (void *) field_type
);
302 int bt_ctf_event_class_add_field(struct bt_ctf_event_class
*event_class
,
303 struct bt_ctf_field_type
*type
,
308 if (!event_class
|| !type
) {
309 BT_LOGW("Invalid parameter: event class or field type is NULL: "
310 "event-class-addr=%p, field-type-addr=%p",
316 if (!bt_ctf_identifier_is_valid(name
)) {
317 BT_LOGW("Invalid parameter: event class's payload field type's field name is not a valid CTF identifier: "
318 "addr=%p, name=\"%s\", id=%" PRId64
", field-name=\"%s\"",
319 event_class
, bt_ctf_event_class_get_name(event_class
),
320 bt_ctf_event_class_get_id(event_class
),
326 if (event_class
->common
.frozen
) {
327 BT_LOGW("Invalid parameter: event class is frozen: "
328 "addr=%p, name=\"%s\", id=%" PRId64
,
329 event_class
, bt_ctf_event_class_get_name(event_class
),
330 bt_ctf_event_class_get_id(event_class
));
335 if (!event_class
->common
.payload_field_type
) {
336 BT_LOGW("Event class has no payload field type: "
337 "addr=%p, name=\"%s\", id=%" PRId64
,
338 event_class
, bt_ctf_event_class_get_name(event_class
),
339 bt_ctf_event_class_get_id(event_class
));
344 BT_ASSERT_DBG(bt_ctf_field_type_common_get_type_id(
345 event_class
->common
.payload_field_type
) ==
346 BT_CTF_FIELD_TYPE_ID_STRUCT
);
347 ret
= bt_ctf_field_type_structure_add_field(
348 (void *) event_class
->common
.payload_field_type
,
349 (void *) type
, name
);
350 BT_LOGT("Added field to event class's payload field type: "
351 "event-class-addr=%p, event-class-name=\"%s\", "
352 "event-class-id=%" PRId64
", field-name=\"%s\", ft-addr=%p",
353 event_class
, bt_ctf_event_class_get_name(event_class
),
354 bt_ctf_event_class_get_id(event_class
), name
, type
);
360 int64_t bt_ctf_event_class_get_payload_type_field_count(
361 struct bt_ctf_event_class
*event_class
)
366 BT_LOGW_STR("Invalid parameter: event class is NULL.");
371 if (!event_class
->common
.payload_field_type
) {
372 BT_LOGT("Event class has no payload field type: "
373 "addr=%p, name=\"%s\", id=%" PRId64
,
374 event_class
, bt_ctf_event_class_get_name(event_class
),
375 bt_ctf_event_class_get_id(event_class
));
380 BT_ASSERT_DBG(bt_ctf_field_type_common_get_type_id(
381 event_class
->common
.payload_field_type
) ==
382 BT_CTF_FIELD_TYPE_ID_STRUCT
);
383 ret
= bt_ctf_field_type_common_structure_get_field_count(
384 event_class
->common
.payload_field_type
);
390 int bt_ctf_event_class_get_payload_type_field_by_index(
391 struct bt_ctf_event_class
*event_class
,
392 const char **field_name
, struct bt_ctf_field_type
**field_type
,
398 BT_LOGW_STR("Invalid parameter: event class is NULL.");
403 if (!event_class
->common
.payload_field_type
) {
404 BT_LOGT("Event class has no payload field type: "
405 "addr=%p, name=\"%s\", id=%" PRId64
", index=%" PRIu64
,
406 event_class
, bt_ctf_event_class_get_name(event_class
),
407 bt_ctf_event_class_get_id(event_class
), index
);
412 BT_ASSERT_DBG(bt_ctf_field_type_common_get_type_id(
413 event_class
->common
.payload_field_type
) ==
414 BT_CTF_FIELD_TYPE_ID_STRUCT
);
415 ret
= bt_ctf_field_type_structure_get_field_by_index(
416 (void *) event_class
->common
.payload_field_type
,
417 field_name
, (void *) field_type
, index
);
424 struct bt_ctf_field_type
*
425 bt_ctf_event_class_get_payload_type_field_type_by_name(
426 struct bt_ctf_event_class
*event_class
, const char *name
)
429 struct bt_ctf_field_type
*field_type
= NULL
;
431 if (!event_class
|| !name
) {
432 BT_LOGW("Invalid parameter: event class or name is NULL: "
433 "event-class-addr=%p, name-addr=%p",
438 if (!event_class
->common
.payload_field_type
) {
439 BT_LOGT("Event class has no payload field type: "
440 "addr=%p, name=\"%s\", id=%" PRId64
,
441 event_class
, bt_ctf_event_class_get_name(event_class
),
442 bt_ctf_event_class_get_id(event_class
));
446 BT_ASSERT_DBG(bt_ctf_field_type_common_get_type_id(
447 event_class
->common
.payload_field_type
) ==
448 BT_CTF_FIELD_TYPE_ID_STRUCT
);
449 name_quark
= g_quark_try_string(name
);
451 BT_LOGE("Cannot get GQuark: string=\"%s\"", name
);
456 * No need to increment field_type's reference count since getting it
457 * from the structure already does.
459 field_type
= (void *)
460 bt_ctf_field_type_structure_get_field_type_by_name(
461 (void *) event_class
->common
.payload_field_type
, name
);
467 int bt_ctf_event_class_serialize(struct bt_ctf_event_class
*event_class
,
468 struct metadata_context
*context
)
471 struct bt_ctf_value
*attr_value
= NULL
;
473 BT_ASSERT_DBG(event_class
);
474 BT_ASSERT_DBG(context
);
475 BT_LOGD("Serializing event class's metadata: "
476 "event-class-addr=%p, event-class-name=\"%s\", "
477 "event-class-id=%" PRId64
", metadata-context-addr=%p",
478 event_class
, bt_ctf_event_class_get_name(event_class
),
479 bt_ctf_event_class_get_id(event_class
), context
);
480 context
->current_indentation_level
= 1;
481 g_string_assign(context
->field_name
, "");
482 g_string_append(context
->string
, "event {\n");
484 /* Serialize attributes */
485 g_string_append_printf(context
->string
, "\tname = \"%s\";\n",
486 event_class
->common
.name
->str
);
487 BT_ASSERT_DBG(event_class
->common
.id
>= 0);
488 g_string_append_printf(context
->string
, "\tid = %" PRId64
";\n",
489 event_class
->common
.id
);
490 g_string_append_printf(context
->string
, "\tstream_id = %" PRId64
";\n",
491 bt_ctf_stream_class_common_get_id(
492 bt_ctf_event_class_common_borrow_stream_class(
493 BT_CTF_TO_COMMON(event_class
))));
495 if (event_class
->common
.log_level
!=
496 BT_CTF_EVENT_CLASS_LOG_LEVEL_UNSPECIFIED
) {
497 g_string_append_printf(context
->string
, "\tloglevel = %d;\n",
498 (int) event_class
->common
.log_level
);
501 if (event_class
->common
.emf_uri
->len
> 0) {
502 g_string_append_printf(context
->string
, "\tmodel.emf.uri = \"%s\";\n",
503 event_class
->common
.emf_uri
->str
);
506 /* Serialize context field type */
507 if (event_class
->common
.context_field_type
) {
508 g_string_append(context
->string
, "\tcontext := ");
509 BT_LOGD_STR("Serializing event class's context field type metadata.");
510 ret
= bt_ctf_field_type_serialize_recursive(
511 (void *) event_class
->common
.context_field_type
,
514 BT_LOGW("Cannot serialize event class's context field type's metadata: "
518 g_string_append(context
->string
, ";\n");
521 /* Serialize payload field type */
522 if (event_class
->common
.payload_field_type
) {
523 g_string_append(context
->string
, "\tfields := ");
524 BT_LOGD_STR("Serializing event class's payload field type metadata.");
525 ret
= bt_ctf_field_type_serialize_recursive(
526 (void *) event_class
->common
.payload_field_type
,
529 BT_LOGW("Cannot serialize event class's payload field type's metadata: "
533 g_string_append(context
->string
, ";\n");
536 g_string_append(context
->string
, "};\n\n");
539 context
->current_indentation_level
= 0;
540 BT_CTF_OBJECT_PUT_REF_AND_RESET(attr_value
);
545 struct bt_ctf_field_type
*bt_ctf_event_class_get_field_by_name(
546 struct bt_ctf_event_class
*event_class
, const char *name
)
549 struct bt_ctf_field_type
*field_type
= NULL
;
551 if (!event_class
|| !name
) {
552 BT_LOGW("Invalid parameter: event class or name is NULL: "
553 "event-class-addr=%p, name-addr=%p",
558 if (!event_class
->common
.payload_field_type
) {
559 BT_LOGT("Event class has no payload field type: "
560 "addr=%p, name=\"%s\", id=%" PRId64
,
562 bt_ctf_event_class_get_name(event_class
),
563 bt_ctf_event_class_get_id(event_class
));
567 BT_ASSERT_DBG(event_class
->common
.payload_field_type
->id
==
568 BT_CTF_FIELD_TYPE_ID_STRUCT
);
569 name_quark
= g_quark_try_string(name
);
571 BT_LOGE("Cannot get GQuark: string=\"%s\"", name
);
576 * No need to increment field_type's reference count since getting it
577 * from the structure already does.
579 field_type
= bt_ctf_object_get_ref(
580 bt_ctf_field_type_common_structure_borrow_field_type_by_name(
581 event_class
->common
.payload_field_type
, name
));