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>
21 #include "common/assert.h"
22 #include "compat/compiler.h"
23 #include "compat/endian.h"
25 #include "assert-pre.h"
26 #include "attributes.h"
27 #include "event-class.h"
30 #include "field-types.h"
31 #include "stream-class.h"
34 #include "validation.h"
38 void bt_ctf_event_class_common_finalize(struct bt_ctf_object
*obj
)
40 struct bt_ctf_event_class_common
*event_class
;
42 event_class
= container_of(obj
, struct bt_ctf_event_class_common
, base
);
43 BT_LOGD("Finalizing common event class: addr=%p, name=\"%s\", id=%" PRId64
,
44 event_class
, bt_ctf_event_class_common_get_name(event_class
),
45 bt_ctf_event_class_common_get_id(event_class
));
47 if (event_class
->name
) {
48 g_string_free(event_class
->name
, TRUE
);
51 if (event_class
->emf_uri
) {
52 g_string_free(event_class
->emf_uri
, TRUE
);
55 BT_LOGD_STR("Putting context field type.");
56 bt_ctf_object_put_ref(event_class
->context_field_type
);
57 BT_LOGD_STR("Putting payload field type.");
58 bt_ctf_object_put_ref(event_class
->payload_field_type
);
61 int bt_ctf_event_class_common_initialize(struct bt_ctf_event_class_common
*event_class
,
62 const char *name
, bt_ctf_object_release_func release_func
,
63 bt_ctf_field_type_structure_create_func ft_struct_create_func
)
67 BT_LOGD("Initializing common event class object: name=\"%s\"",
69 bt_ctf_object_init_shared_with_parent(&event_class
->base
, release_func
);
70 event_class
->payload_field_type
= ft_struct_create_func();
71 if (!event_class
->payload_field_type
) {
72 BT_LOGE_STR("Cannot create event class's initial payload field type object.");
77 event_class
->name
= g_string_new(name
);
78 if (!event_class
->name
) {
79 BT_LOGE_STR("Failed to allocate a GString.");
83 event_class
->emf_uri
= g_string_new(NULL
);
84 if (!event_class
->emf_uri
) {
85 BT_LOGE_STR("Failed to allocate a GString.");
89 event_class
->log_level
= BT_CTF_EVENT_CLASS_LOG_LEVEL_UNSPECIFIED
;
90 BT_LOGD("Initialized common event class object: addr=%p, name=\"%s\"",
91 event_class
, bt_ctf_event_class_common_get_name(event_class
));
99 void bt_ctf_event_class_common_freeze(struct bt_ctf_event_class_common
*event_class
)
101 BT_ASSERT_DBG(event_class
);
103 if (event_class
->frozen
) {
107 BT_LOGD("Freezing event class: addr=%p, name=\"%s\", id=%" PRId64
,
108 event_class
, bt_ctf_event_class_common_get_name(event_class
),
109 bt_ctf_event_class_common_get_id(event_class
));
110 event_class
->frozen
= 1;
111 BT_LOGD_STR("Freezing event class's context field type.");
112 bt_ctf_field_type_common_freeze(event_class
->context_field_type
);
113 BT_LOGD_STR("Freezing event class's payload field type.");
114 bt_ctf_field_type_common_freeze(event_class
->payload_field_type
);
117 int bt_ctf_event_class_common_validate_single_clock_class(
118 struct bt_ctf_event_class_common
*event_class
,
119 struct bt_ctf_clock_class
**expected_clock_class
)
123 BT_ASSERT_DBG(event_class
);
124 BT_ASSERT_DBG(expected_clock_class
);
125 ret
= bt_ctf_field_type_common_validate_single_clock_class(
126 event_class
->context_field_type
,
127 expected_clock_class
);
129 BT_LOGW("Event class's context field type "
130 "is not recursively mapped to the "
131 "expected clock class: "
132 "event-class-addr=%p, "
133 "event-class-name=\"%s\", "
134 "event-class-id=%" PRId64
", "
137 bt_ctf_event_class_common_get_name(event_class
),
139 event_class
->context_field_type
);
143 ret
= bt_ctf_field_type_common_validate_single_clock_class(
144 event_class
->payload_field_type
,
145 expected_clock_class
);
147 BT_LOGW("Event class's payload field type "
148 "is not recursively mapped to the "
149 "expected clock class: "
150 "event-class-addr=%p, "
151 "event-class-name=\"%s\", "
152 "event-class-id=%" PRId64
", "
155 bt_ctf_event_class_common_get_name(event_class
),
157 event_class
->payload_field_type
);
166 void bt_ctf_event_class_destroy(struct bt_ctf_object
*obj
)
168 bt_ctf_event_class_common_finalize(obj
);
173 struct bt_ctf_event_class
*bt_ctf_event_class_create(const char *name
)
175 struct bt_ctf_event_class
*ctf_event_class
= NULL
;
179 BT_LOGW_STR("Invalid parameter: name is NULL.");
183 BT_LOGD("Creating event class object: name=\"%s\"",
185 ctf_event_class
= g_new0(struct bt_ctf_event_class
, 1);
186 if (!ctf_event_class
) {
187 BT_LOGE_STR("Failed to allocate one event class.");
191 ret
= bt_ctf_event_class_common_initialize(BT_CTF_TO_COMMON(ctf_event_class
),
192 name
, bt_ctf_event_class_destroy
,
193 (bt_ctf_field_type_structure_create_func
)
194 bt_ctf_field_type_structure_create
);
202 bt_ctf_object_put_ref(ctf_event_class
);
205 return ctf_event_class
;
209 const char *bt_ctf_event_class_get_name(struct bt_ctf_event_class
*event_class
)
211 return bt_ctf_event_class_common_get_name(BT_CTF_TO_COMMON(event_class
));
215 int64_t bt_ctf_event_class_get_id(struct bt_ctf_event_class
*event_class
)
217 return bt_ctf_event_class_common_get_id(BT_CTF_TO_COMMON(event_class
));
221 int bt_ctf_event_class_set_id(struct bt_ctf_event_class
*event_class
,
224 return bt_ctf_event_class_common_set_id(BT_CTF_TO_COMMON(event_class
), id
);
228 enum bt_ctf_event_class_log_level
bt_ctf_event_class_get_log_level(
229 struct bt_ctf_event_class
*event_class
)
231 return bt_ctf_event_class_common_get_log_level(BT_CTF_TO_COMMON(event_class
));
235 int bt_ctf_event_class_set_log_level(struct bt_ctf_event_class
*event_class
,
236 enum bt_ctf_event_class_log_level log_level
)
238 return bt_ctf_event_class_common_set_log_level(BT_CTF_TO_COMMON(event_class
),
243 const char *bt_ctf_event_class_get_emf_uri(
244 struct bt_ctf_event_class
*event_class
)
246 return bt_ctf_event_class_common_get_emf_uri(BT_CTF_TO_COMMON(event_class
));
250 int bt_ctf_event_class_set_emf_uri(struct bt_ctf_event_class
*event_class
,
253 return bt_ctf_event_class_common_set_emf_uri(BT_CTF_TO_COMMON(event_class
),
258 struct bt_ctf_stream_class
*bt_ctf_event_class_get_stream_class(
259 struct bt_ctf_event_class
*event_class
)
261 BT_CTF_ASSERT_PRE_NON_NULL(event_class
, "Event class");
262 return bt_ctf_object_get_ref(bt_ctf_event_class_common_borrow_stream_class(
263 BT_CTF_TO_COMMON(event_class
)));
267 struct bt_ctf_field_type
*bt_ctf_event_class_get_payload_field_type(
268 struct bt_ctf_event_class
*event_class
)
270 return bt_ctf_object_get_ref(bt_ctf_event_class_common_borrow_payload_field_type(
271 BT_CTF_TO_COMMON(event_class
)));
275 int bt_ctf_event_class_set_payload_field_type(
276 struct bt_ctf_event_class
*event_class
,
277 struct bt_ctf_field_type
*field_type
)
279 return bt_ctf_event_class_common_set_payload_field_type(
280 BT_CTF_TO_COMMON(event_class
), (void *) field_type
);
284 struct bt_ctf_field_type
*bt_ctf_event_class_get_context_field_type(
285 struct bt_ctf_event_class
*event_class
)
287 return bt_ctf_object_get_ref(bt_ctf_event_class_common_borrow_context_field_type(
288 BT_CTF_TO_COMMON(event_class
)));
292 int bt_ctf_event_class_set_context_field_type(
293 struct bt_ctf_event_class
*event_class
,
294 struct bt_ctf_field_type
*field_type
)
296 return bt_ctf_event_class_common_set_context_field_type(
297 BT_CTF_TO_COMMON(event_class
), (void *) field_type
);
301 int bt_ctf_event_class_add_field(struct bt_ctf_event_class
*event_class
,
302 struct bt_ctf_field_type
*type
,
307 if (!event_class
|| !type
) {
308 BT_LOGW("Invalid parameter: event class or field type is NULL: "
309 "event-class-addr=%p, field-type-addr=%p",
315 if (!bt_ctf_identifier_is_valid(name
)) {
316 BT_LOGW("Invalid parameter: event class's payload field type's field name is not a valid CTF identifier: "
317 "addr=%p, name=\"%s\", id=%" PRId64
", field-name=\"%s\"",
318 event_class
, bt_ctf_event_class_get_name(event_class
),
319 bt_ctf_event_class_get_id(event_class
),
325 if (event_class
->common
.frozen
) {
326 BT_LOGW("Invalid parameter: event class is frozen: "
327 "addr=%p, name=\"%s\", id=%" PRId64
,
328 event_class
, bt_ctf_event_class_get_name(event_class
),
329 bt_ctf_event_class_get_id(event_class
));
334 if (!event_class
->common
.payload_field_type
) {
335 BT_LOGW("Event class has no payload field type: "
336 "addr=%p, name=\"%s\", id=%" PRId64
,
337 event_class
, bt_ctf_event_class_get_name(event_class
),
338 bt_ctf_event_class_get_id(event_class
));
343 BT_ASSERT_DBG(bt_ctf_field_type_common_get_type_id(
344 event_class
->common
.payload_field_type
) ==
345 BT_CTF_FIELD_TYPE_ID_STRUCT
);
346 ret
= bt_ctf_field_type_structure_add_field(
347 (void *) event_class
->common
.payload_field_type
,
348 (void *) type
, name
);
349 BT_LOGT("Added field to event class's payload field type: "
350 "event-class-addr=%p, event-class-name=\"%s\", "
351 "event-class-id=%" PRId64
", field-name=\"%s\", ft-addr=%p",
352 event_class
, bt_ctf_event_class_get_name(event_class
),
353 bt_ctf_event_class_get_id(event_class
), name
, type
);
359 int64_t bt_ctf_event_class_get_payload_type_field_count(
360 struct bt_ctf_event_class
*event_class
)
365 BT_LOGW_STR("Invalid parameter: event class is NULL.");
370 if (!event_class
->common
.payload_field_type
) {
371 BT_LOGT("Event class has no payload field type: "
372 "addr=%p, name=\"%s\", id=%" PRId64
,
373 event_class
, bt_ctf_event_class_get_name(event_class
),
374 bt_ctf_event_class_get_id(event_class
));
379 BT_ASSERT_DBG(bt_ctf_field_type_common_get_type_id(
380 event_class
->common
.payload_field_type
) ==
381 BT_CTF_FIELD_TYPE_ID_STRUCT
);
382 ret
= bt_ctf_field_type_common_structure_get_field_count(
383 event_class
->common
.payload_field_type
);
389 int bt_ctf_event_class_get_payload_type_field_by_index(
390 struct bt_ctf_event_class
*event_class
,
391 const char **field_name
, struct bt_ctf_field_type
**field_type
,
397 BT_LOGW_STR("Invalid parameter: event class is NULL.");
402 if (!event_class
->common
.payload_field_type
) {
403 BT_LOGT("Event class has no payload field type: "
404 "addr=%p, name=\"%s\", id=%" PRId64
", index=%" PRIu64
,
405 event_class
, bt_ctf_event_class_get_name(event_class
),
406 bt_ctf_event_class_get_id(event_class
), index
);
411 BT_ASSERT_DBG(bt_ctf_field_type_common_get_type_id(
412 event_class
->common
.payload_field_type
) ==
413 BT_CTF_FIELD_TYPE_ID_STRUCT
);
414 ret
= bt_ctf_field_type_structure_get_field_by_index(
415 (void *) event_class
->common
.payload_field_type
,
416 field_name
, (void *) field_type
, index
);
423 struct bt_ctf_field_type
*
424 bt_ctf_event_class_get_payload_type_field_type_by_name(
425 struct bt_ctf_event_class
*event_class
, const char *name
)
428 struct bt_ctf_field_type
*field_type
= NULL
;
430 if (!event_class
|| !name
) {
431 BT_LOGW("Invalid parameter: event class or name is NULL: "
432 "event-class-addr=%p, name-addr=%p",
437 if (!event_class
->common
.payload_field_type
) {
438 BT_LOGT("Event class has no payload field type: "
439 "addr=%p, name=\"%s\", id=%" PRId64
,
440 event_class
, bt_ctf_event_class_get_name(event_class
),
441 bt_ctf_event_class_get_id(event_class
));
445 BT_ASSERT_DBG(bt_ctf_field_type_common_get_type_id(
446 event_class
->common
.payload_field_type
) ==
447 BT_CTF_FIELD_TYPE_ID_STRUCT
);
448 name_quark
= g_quark_try_string(name
);
450 BT_LOGE("Cannot get GQuark: string=\"%s\"", name
);
455 * No need to increment field_type's reference count since getting it
456 * from the structure already does.
458 field_type
= (void *)
459 bt_ctf_field_type_structure_get_field_type_by_name(
460 (void *) event_class
->common
.payload_field_type
, name
);
466 int bt_ctf_event_class_serialize(struct bt_ctf_event_class
*event_class
,
467 struct metadata_context
*context
)
470 struct bt_ctf_value
*attr_value
= NULL
;
472 BT_ASSERT_DBG(event_class
);
473 BT_ASSERT_DBG(context
);
474 BT_LOGD("Serializing event class's metadata: "
475 "event-class-addr=%p, event-class-name=\"%s\", "
476 "event-class-id=%" PRId64
", metadata-context-addr=%p",
477 event_class
, bt_ctf_event_class_get_name(event_class
),
478 bt_ctf_event_class_get_id(event_class
), context
);
479 context
->current_indentation_level
= 1;
480 g_string_assign(context
->field_name
, "");
481 g_string_append(context
->string
, "event {\n");
483 /* Serialize attributes */
484 g_string_append_printf(context
->string
, "\tname = \"%s\";\n",
485 event_class
->common
.name
->str
);
486 BT_ASSERT_DBG(event_class
->common
.id
>= 0);
487 g_string_append_printf(context
->string
, "\tid = %" PRId64
";\n",
488 event_class
->common
.id
);
489 g_string_append_printf(context
->string
, "\tstream_id = %" PRId64
";\n",
490 bt_ctf_stream_class_common_get_id(
491 bt_ctf_event_class_common_borrow_stream_class(
492 BT_CTF_TO_COMMON(event_class
))));
494 if (event_class
->common
.log_level
!=
495 BT_CTF_EVENT_CLASS_LOG_LEVEL_UNSPECIFIED
) {
496 g_string_append_printf(context
->string
, "\tloglevel = %d;\n",
497 (int) event_class
->common
.log_level
);
500 if (event_class
->common
.emf_uri
->len
> 0) {
501 g_string_append_printf(context
->string
, "\tmodel.emf.uri = \"%s\";\n",
502 event_class
->common
.emf_uri
->str
);
505 /* Serialize context field type */
506 if (event_class
->common
.context_field_type
) {
507 g_string_append(context
->string
, "\tcontext := ");
508 BT_LOGD_STR("Serializing event class's context field type metadata.");
509 ret
= bt_ctf_field_type_serialize_recursive(
510 (void *) event_class
->common
.context_field_type
,
513 BT_LOGW("Cannot serialize event class's context field type's metadata: "
517 g_string_append(context
->string
, ";\n");
520 /* Serialize payload field type */
521 if (event_class
->common
.payload_field_type
) {
522 g_string_append(context
->string
, "\tfields := ");
523 BT_LOGD_STR("Serializing event class's payload field type metadata.");
524 ret
= bt_ctf_field_type_serialize_recursive(
525 (void *) event_class
->common
.payload_field_type
,
528 BT_LOGW("Cannot serialize event class's payload field type's metadata: "
532 g_string_append(context
->string
, ";\n");
535 g_string_append(context
->string
, "};\n\n");
538 context
->current_indentation_level
= 0;
539 BT_CTF_OBJECT_PUT_REF_AND_RESET(attr_value
);
544 struct bt_ctf_field_type
*bt_ctf_event_class_get_field_by_name(
545 struct bt_ctf_event_class
*event_class
, const char *name
)
548 struct bt_ctf_field_type
*field_type
= NULL
;
550 if (!event_class
|| !name
) {
551 BT_LOGW("Invalid parameter: event class or name is NULL: "
552 "event-class-addr=%p, name-addr=%p",
557 if (!event_class
->common
.payload_field_type
) {
558 BT_LOGT("Event class has no payload field type: "
559 "addr=%p, name=\"%s\", id=%" PRId64
,
561 bt_ctf_event_class_get_name(event_class
),
562 bt_ctf_event_class_get_id(event_class
));
566 BT_ASSERT_DBG(event_class
->common
.payload_field_type
->id
==
567 BT_CTF_FIELD_TYPE_ID_STRUCT
);
568 name_quark
= g_quark_try_string(name
);
570 BT_LOGE("Cannot get GQuark: string=\"%s\"", name
);
575 * No need to increment field_type's reference count since getting it
576 * from the structure already does.
578 field_type
= bt_ctf_object_get_ref(
579 bt_ctf_field_type_common_structure_borrow_field_type_by_name(
580 event_class
->common
.payload_field_type
, name
));