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"
40 void bt_ctf_event_class_common_finalize(struct bt_ctf_object
*obj
)
42 struct bt_ctf_event_class_common
*event_class
;
44 event_class
= container_of(obj
, struct bt_ctf_event_class_common
, base
);
45 BT_LOGD("Finalizing common event class: addr=%p, name=\"%s\", id=%" PRId64
,
46 event_class
, bt_ctf_event_class_common_get_name(event_class
),
47 bt_ctf_event_class_common_get_id(event_class
));
49 if (event_class
->name
) {
50 g_string_free(event_class
->name
, TRUE
);
53 if (event_class
->emf_uri
) {
54 g_string_free(event_class
->emf_uri
, TRUE
);
57 BT_LOGD_STR("Putting context field type.");
58 bt_ctf_object_put_ref(event_class
->context_field_type
);
59 BT_LOGD_STR("Putting payload field type.");
60 bt_ctf_object_put_ref(event_class
->payload_field_type
);
64 int bt_ctf_event_class_common_initialize(struct bt_ctf_event_class_common
*event_class
,
65 const char *name
, bt_ctf_object_release_func release_func
,
66 bt_ctf_field_type_structure_create_func ft_struct_create_func
)
70 BT_LOGD("Initializing common event class object: name=\"%s\"",
72 bt_ctf_object_init_shared_with_parent(&event_class
->base
, release_func
);
73 event_class
->payload_field_type
= ft_struct_create_func();
74 if (!event_class
->payload_field_type
) {
75 BT_LOGE_STR("Cannot create event class's initial payload field type object.");
80 event_class
->name
= g_string_new(name
);
81 if (!event_class
->name
) {
82 BT_LOGE_STR("Failed to allocate a GString.");
86 event_class
->emf_uri
= g_string_new(NULL
);
87 if (!event_class
->emf_uri
) {
88 BT_LOGE_STR("Failed to allocate a GString.");
92 event_class
->log_level
= BT_CTF_EVENT_CLASS_LOG_LEVEL_UNSPECIFIED
;
93 BT_LOGD("Initialized common event class object: addr=%p, name=\"%s\"",
94 event_class
, bt_ctf_event_class_common_get_name(event_class
));
103 void bt_ctf_event_class_common_freeze(struct bt_ctf_event_class_common
*event_class
)
105 BT_ASSERT_DBG(event_class
);
107 if (event_class
->frozen
) {
111 BT_LOGD("Freezing event class: addr=%p, name=\"%s\", id=%" PRId64
,
112 event_class
, bt_ctf_event_class_common_get_name(event_class
),
113 bt_ctf_event_class_common_get_id(event_class
));
114 event_class
->frozen
= 1;
115 BT_LOGD_STR("Freezing event class's context field type.");
116 bt_ctf_field_type_common_freeze(event_class
->context_field_type
);
117 BT_LOGD_STR("Freezing event class's payload field type.");
118 bt_ctf_field_type_common_freeze(event_class
->payload_field_type
);
122 int bt_ctf_event_class_common_validate_single_clock_class(
123 struct bt_ctf_event_class_common
*event_class
,
124 struct bt_ctf_clock_class
**expected_clock_class
)
128 BT_ASSERT_DBG(event_class
);
129 BT_ASSERT_DBG(expected_clock_class
);
130 ret
= bt_ctf_field_type_common_validate_single_clock_class(
131 event_class
->context_field_type
,
132 expected_clock_class
);
134 BT_LOGW("Event class's context field type "
135 "is not recursively mapped to the "
136 "expected clock class: "
137 "event-class-addr=%p, "
138 "event-class-name=\"%s\", "
139 "event-class-id=%" PRId64
", "
142 bt_ctf_event_class_common_get_name(event_class
),
144 event_class
->context_field_type
);
148 ret
= bt_ctf_field_type_common_validate_single_clock_class(
149 event_class
->payload_field_type
,
150 expected_clock_class
);
152 BT_LOGW("Event class's payload field type "
153 "is not recursively mapped to the "
154 "expected clock class: "
155 "event-class-addr=%p, "
156 "event-class-name=\"%s\", "
157 "event-class-id=%" PRId64
", "
160 bt_ctf_event_class_common_get_name(event_class
),
162 event_class
->payload_field_type
);
171 void bt_ctf_event_class_destroy(struct bt_ctf_object
*obj
)
173 bt_ctf_event_class_common_finalize(obj
);
177 struct bt_ctf_event_class
*bt_ctf_event_class_create(const char *name
)
179 struct bt_ctf_event_class
*ctf_event_class
= NULL
;
183 BT_LOGW_STR("Invalid parameter: name is NULL.");
187 BT_LOGD("Creating event class object: name=\"%s\"",
189 ctf_event_class
= g_new0(struct bt_ctf_event_class
, 1);
190 if (!ctf_event_class
) {
191 BT_LOGE_STR("Failed to allocate one event class.");
195 ret
= bt_ctf_event_class_common_initialize(BT_CTF_TO_COMMON(ctf_event_class
),
196 name
, bt_ctf_event_class_destroy
,
197 (bt_ctf_field_type_structure_create_func
)
198 bt_ctf_field_type_structure_create
);
206 bt_ctf_object_put_ref(ctf_event_class
);
209 return ctf_event_class
;
212 const char *bt_ctf_event_class_get_name(struct bt_ctf_event_class
*event_class
)
214 return bt_ctf_event_class_common_get_name(BT_CTF_TO_COMMON(event_class
));
217 int64_t bt_ctf_event_class_get_id(struct bt_ctf_event_class
*event_class
)
219 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
);
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
));
234 int bt_ctf_event_class_set_log_level(struct bt_ctf_event_class
*event_class
,
235 enum bt_ctf_event_class_log_level log_level
)
237 return bt_ctf_event_class_common_set_log_level(BT_CTF_TO_COMMON(event_class
),
241 const char *bt_ctf_event_class_get_emf_uri(
242 struct bt_ctf_event_class
*event_class
)
244 return bt_ctf_event_class_common_get_emf_uri(BT_CTF_TO_COMMON(event_class
));
247 int bt_ctf_event_class_set_emf_uri(struct bt_ctf_event_class
*event_class
,
250 return bt_ctf_event_class_common_set_emf_uri(BT_CTF_TO_COMMON(event_class
),
254 struct bt_ctf_stream_class
*bt_ctf_event_class_get_stream_class(
255 struct bt_ctf_event_class
*event_class
)
257 BT_CTF_ASSERT_PRE_NON_NULL(event_class
, "Event class");
258 return bt_ctf_object_get_ref(bt_ctf_event_class_common_borrow_stream_class(
259 BT_CTF_TO_COMMON(event_class
)));
262 struct bt_ctf_field_type
*bt_ctf_event_class_get_payload_field_type(
263 struct bt_ctf_event_class
*event_class
)
265 return bt_ctf_object_get_ref(bt_ctf_event_class_common_borrow_payload_field_type(
266 BT_CTF_TO_COMMON(event_class
)));
269 int bt_ctf_event_class_set_payload_field_type(
270 struct bt_ctf_event_class
*event_class
,
271 struct bt_ctf_field_type
*field_type
)
273 return bt_ctf_event_class_common_set_payload_field_type(
274 BT_CTF_TO_COMMON(event_class
), (void *) field_type
);
277 struct bt_ctf_field_type
*bt_ctf_event_class_get_context_field_type(
278 struct bt_ctf_event_class
*event_class
)
280 return bt_ctf_object_get_ref(bt_ctf_event_class_common_borrow_context_field_type(
281 BT_CTF_TO_COMMON(event_class
)));
284 int bt_ctf_event_class_set_context_field_type(
285 struct bt_ctf_event_class
*event_class
,
286 struct bt_ctf_field_type
*field_type
)
288 return bt_ctf_event_class_common_set_context_field_type(
289 BT_CTF_TO_COMMON(event_class
), (void *) field_type
);
292 int bt_ctf_event_class_add_field(struct bt_ctf_event_class
*event_class
,
293 struct bt_ctf_field_type
*type
,
298 if (!event_class
|| !type
) {
299 BT_LOGW("Invalid parameter: event class or field type is NULL: "
300 "event-class-addr=%p, field-type-addr=%p",
306 if (!bt_ctf_identifier_is_valid(name
)) {
307 BT_LOGW("Invalid parameter: event class's payload field type's field name is not a valid CTF identifier: "
308 "addr=%p, name=\"%s\", id=%" PRId64
", field-name=\"%s\"",
309 event_class
, bt_ctf_event_class_get_name(event_class
),
310 bt_ctf_event_class_get_id(event_class
),
316 if (event_class
->common
.frozen
) {
317 BT_LOGW("Invalid parameter: event class is frozen: "
318 "addr=%p, name=\"%s\", id=%" PRId64
,
319 event_class
, bt_ctf_event_class_get_name(event_class
),
320 bt_ctf_event_class_get_id(event_class
));
325 if (!event_class
->common
.payload_field_type
) {
326 BT_LOGW("Event class has no payload field type: "
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 BT_ASSERT_DBG(bt_ctf_field_type_common_get_type_id(
335 event_class
->common
.payload_field_type
) ==
336 BT_CTF_FIELD_TYPE_ID_STRUCT
);
337 ret
= bt_ctf_field_type_structure_add_field(
338 (void *) event_class
->common
.payload_field_type
,
339 (void *) type
, name
);
340 BT_LOGT("Added field to event class's payload field type: "
341 "event-class-addr=%p, event-class-name=\"%s\", "
342 "event-class-id=%" PRId64
", field-name=\"%s\", ft-addr=%p",
343 event_class
, bt_ctf_event_class_get_name(event_class
),
344 bt_ctf_event_class_get_id(event_class
), name
, type
);
349 int64_t bt_ctf_event_class_get_payload_type_field_count(
350 struct bt_ctf_event_class
*event_class
)
355 BT_LOGW_STR("Invalid parameter: event class is NULL.");
360 if (!event_class
->common
.payload_field_type
) {
361 BT_LOGT("Event class has no payload field type: "
362 "addr=%p, name=\"%s\", id=%" PRId64
,
363 event_class
, bt_ctf_event_class_get_name(event_class
),
364 bt_ctf_event_class_get_id(event_class
));
369 BT_ASSERT_DBG(bt_ctf_field_type_common_get_type_id(
370 event_class
->common
.payload_field_type
) ==
371 BT_CTF_FIELD_TYPE_ID_STRUCT
);
372 ret
= bt_ctf_field_type_common_structure_get_field_count(
373 event_class
->common
.payload_field_type
);
378 int bt_ctf_event_class_get_payload_type_field_by_index(
379 struct bt_ctf_event_class
*event_class
,
380 const char **field_name
, struct bt_ctf_field_type
**field_type
,
386 BT_LOGW_STR("Invalid parameter: event class is NULL.");
391 if (!event_class
->common
.payload_field_type
) {
392 BT_LOGT("Event class has no payload field type: "
393 "addr=%p, name=\"%s\", id=%" PRId64
", index=%" PRIu64
,
394 event_class
, bt_ctf_event_class_get_name(event_class
),
395 bt_ctf_event_class_get_id(event_class
), index
);
400 BT_ASSERT_DBG(bt_ctf_field_type_common_get_type_id(
401 event_class
->common
.payload_field_type
) ==
402 BT_CTF_FIELD_TYPE_ID_STRUCT
);
403 ret
= bt_ctf_field_type_structure_get_field_by_index(
404 (void *) event_class
->common
.payload_field_type
,
405 field_name
, (void *) field_type
, index
);
411 struct bt_ctf_field_type
*
412 bt_ctf_event_class_get_payload_type_field_type_by_name(
413 struct bt_ctf_event_class
*event_class
, const char *name
)
416 struct bt_ctf_field_type
*field_type
= NULL
;
418 if (!event_class
|| !name
) {
419 BT_LOGW("Invalid parameter: event class or name is NULL: "
420 "event-class-addr=%p, name-addr=%p",
425 if (!event_class
->common
.payload_field_type
) {
426 BT_LOGT("Event class has no payload field type: "
427 "addr=%p, name=\"%s\", id=%" PRId64
,
428 event_class
, bt_ctf_event_class_get_name(event_class
),
429 bt_ctf_event_class_get_id(event_class
));
433 BT_ASSERT_DBG(bt_ctf_field_type_common_get_type_id(
434 event_class
->common
.payload_field_type
) ==
435 BT_CTF_FIELD_TYPE_ID_STRUCT
);
436 name_quark
= g_quark_try_string(name
);
438 BT_LOGE("Cannot get GQuark: string=\"%s\"", name
);
443 * No need to increment field_type's reference count since getting it
444 * from the structure already does.
446 field_type
= (void *)
447 bt_ctf_field_type_structure_get_field_type_by_name(
448 (void *) event_class
->common
.payload_field_type
, name
);
455 int bt_ctf_event_class_serialize(struct bt_ctf_event_class
*event_class
,
456 struct metadata_context
*context
)
459 struct bt_ctf_value
*attr_value
= NULL
;
461 BT_ASSERT_DBG(event_class
);
462 BT_ASSERT_DBG(context
);
463 BT_LOGD("Serializing event class's metadata: "
464 "event-class-addr=%p, event-class-name=\"%s\", "
465 "event-class-id=%" PRId64
", metadata-context-addr=%p",
466 event_class
, bt_ctf_event_class_get_name(event_class
),
467 bt_ctf_event_class_get_id(event_class
), context
);
468 context
->current_indentation_level
= 1;
469 g_string_assign(context
->field_name
, "");
470 g_string_append(context
->string
, "event {\n");
472 /* Serialize attributes */
473 g_string_append_printf(context
->string
, "\tname = \"%s\";\n",
474 event_class
->common
.name
->str
);
475 BT_ASSERT_DBG(event_class
->common
.id
>= 0);
476 g_string_append_printf(context
->string
, "\tid = %" PRId64
";\n",
477 event_class
->common
.id
);
478 g_string_append_printf(context
->string
, "\tstream_id = %" PRId64
";\n",
479 bt_ctf_stream_class_common_get_id(
480 bt_ctf_event_class_common_borrow_stream_class(
481 BT_CTF_TO_COMMON(event_class
))));
483 if (event_class
->common
.log_level
!=
484 BT_CTF_EVENT_CLASS_LOG_LEVEL_UNSPECIFIED
) {
485 g_string_append_printf(context
->string
, "\tloglevel = %d;\n",
486 (int) event_class
->common
.log_level
);
489 if (event_class
->common
.emf_uri
->len
> 0) {
490 g_string_append_printf(context
->string
, "\tmodel.emf.uri = \"%s\";\n",
491 event_class
->common
.emf_uri
->str
);
494 /* Serialize context field type */
495 if (event_class
->common
.context_field_type
) {
496 g_string_append(context
->string
, "\tcontext := ");
497 BT_LOGD_STR("Serializing event class's context field type metadata.");
498 ret
= bt_ctf_field_type_serialize_recursive(
499 (void *) event_class
->common
.context_field_type
,
502 BT_LOGW("Cannot serialize event class's context field type's metadata: "
506 g_string_append(context
->string
, ";\n");
509 /* Serialize payload field type */
510 if (event_class
->common
.payload_field_type
) {
511 g_string_append(context
->string
, "\tfields := ");
512 BT_LOGD_STR("Serializing event class's payload field type metadata.");
513 ret
= bt_ctf_field_type_serialize_recursive(
514 (void *) event_class
->common
.payload_field_type
,
517 BT_LOGW("Cannot serialize event class's payload field type's metadata: "
521 g_string_append(context
->string
, ";\n");
524 g_string_append(context
->string
, "};\n\n");
527 context
->current_indentation_level
= 0;
528 BT_CTF_OBJECT_PUT_REF_AND_RESET(attr_value
);
532 struct bt_ctf_field_type
*bt_ctf_event_class_get_field_by_name(
533 struct bt_ctf_event_class
*event_class
, const char *name
)
536 struct bt_ctf_field_type
*field_type
= NULL
;
538 if (!event_class
|| !name
) {
539 BT_LOGW("Invalid parameter: event class or name is NULL: "
540 "event-class-addr=%p, name-addr=%p",
545 if (!event_class
->common
.payload_field_type
) {
546 BT_LOGT("Event class has no payload field type: "
547 "addr=%p, name=\"%s\", id=%" PRId64
,
549 bt_ctf_event_class_get_name(event_class
),
550 bt_ctf_event_class_get_id(event_class
));
554 BT_ASSERT_DBG(event_class
->common
.payload_field_type
->id
==
555 BT_CTF_FIELD_TYPE_ID_STRUCT
);
556 name_quark
= g_quark_try_string(name
);
558 BT_LOGE("Cannot get GQuark: string=\"%s\"", name
);
563 * No need to increment field_type's reference count since getting it
564 * from the structure already does.
566 field_type
= bt_ctf_object_get_ref(
567 bt_ctf_field_type_common_structure_borrow_field_type_by_name(
568 event_class
->common
.payload_field_type
, name
));