2 * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
3 * Copyright 2017-2018 Philippe Proulx <pproulx@efficios.com>
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 #define BT_LOG_TAG "CTF-WRITER/EVENT-CLASS"
31 #include <babeltrace2/ctf-writer/event.h>
32 #include <babeltrace2/ctf-writer/field-types.h>
33 #include <babeltrace2/ctf-writer/object.h>
34 #include <babeltrace2/ctf-writer/stream-class.h>
35 #include <babeltrace2/ctf-writer/utils.h>
36 #include <babeltrace2/types.h>
38 #include "common/assert.h"
39 #include "compat/compiler.h"
40 #include "compat/endian.h"
42 #include "assert-pre.h"
43 #include "attributes.h"
44 #include "event-class.h"
47 #include "field-types.h"
48 #include "stream-class.h"
51 #include "validation.h"
56 void bt_ctf_event_class_common_finalize(struct bt_ctf_object
*obj
)
58 struct bt_ctf_event_class_common
*event_class
;
60 event_class
= container_of(obj
, struct bt_ctf_event_class_common
, base
);
61 BT_LOGD("Finalizing common event class: addr=%p, name=\"%s\", id=%" PRId64
,
62 event_class
, bt_ctf_event_class_common_get_name(event_class
),
63 bt_ctf_event_class_common_get_id(event_class
));
65 if (event_class
->name
) {
66 g_string_free(event_class
->name
, TRUE
);
69 if (event_class
->emf_uri
) {
70 g_string_free(event_class
->emf_uri
, TRUE
);
73 BT_LOGD_STR("Putting context field type.");
74 bt_ctf_object_put_ref(event_class
->context_field_type
);
75 BT_LOGD_STR("Putting payload field type.");
76 bt_ctf_object_put_ref(event_class
->payload_field_type
);
80 int bt_ctf_event_class_common_initialize(struct bt_ctf_event_class_common
*event_class
,
81 const char *name
, bt_ctf_object_release_func release_func
,
82 bt_ctf_field_type_structure_create_func ft_struct_create_func
)
86 BT_LOGD("Initializing common event class object: name=\"%s\"",
88 bt_ctf_object_init_shared_with_parent(&event_class
->base
, release_func
);
89 event_class
->payload_field_type
= ft_struct_create_func();
90 if (!event_class
->payload_field_type
) {
91 BT_LOGE_STR("Cannot create event class's initial payload field type object.");
96 event_class
->name
= g_string_new(name
);
97 if (!event_class
->name
) {
98 BT_LOGE_STR("Failed to allocate a GString.");
102 event_class
->emf_uri
= g_string_new(NULL
);
103 if (!event_class
->emf_uri
) {
104 BT_LOGE_STR("Failed to allocate a GString.");
108 event_class
->log_level
= BT_CTF_EVENT_CLASS_LOG_LEVEL_UNSPECIFIED
;
109 BT_LOGD("Initialized common event class object: addr=%p, name=\"%s\"",
110 event_class
, bt_ctf_event_class_common_get_name(event_class
));
119 void bt_ctf_event_class_common_freeze(struct bt_ctf_event_class_common
*event_class
)
121 BT_ASSERT(event_class
);
123 if (event_class
->frozen
) {
127 BT_LOGD("Freezing event class: addr=%p, name=\"%s\", id=%" PRId64
,
128 event_class
, bt_ctf_event_class_common_get_name(event_class
),
129 bt_ctf_event_class_common_get_id(event_class
));
130 event_class
->frozen
= 1;
131 BT_LOGD_STR("Freezing event class's context field type.");
132 bt_ctf_field_type_common_freeze(event_class
->context_field_type
);
133 BT_LOGD_STR("Freezing event class's payload field type.");
134 bt_ctf_field_type_common_freeze(event_class
->payload_field_type
);
138 int bt_ctf_event_class_common_validate_single_clock_class(
139 struct bt_ctf_event_class_common
*event_class
,
140 struct bt_ctf_clock_class
**expected_clock_class
)
144 BT_ASSERT(event_class
);
145 BT_ASSERT(expected_clock_class
);
146 ret
= bt_ctf_field_type_common_validate_single_clock_class(
147 event_class
->context_field_type
,
148 expected_clock_class
);
150 BT_LOGW("Event class's context field type "
151 "is not recursively mapped to the "
152 "expected clock class: "
153 "event-class-addr=%p, "
154 "event-class-name=\"%s\", "
155 "event-class-id=%" PRId64
", "
158 bt_ctf_event_class_common_get_name(event_class
),
160 event_class
->context_field_type
);
164 ret
= bt_ctf_field_type_common_validate_single_clock_class(
165 event_class
->payload_field_type
,
166 expected_clock_class
);
168 BT_LOGW("Event class's payload field type "
169 "is not recursively mapped to the "
170 "expected clock class: "
171 "event-class-addr=%p, "
172 "event-class-name=\"%s\", "
173 "event-class-id=%" PRId64
", "
176 bt_ctf_event_class_common_get_name(event_class
),
178 event_class
->payload_field_type
);
187 void bt_ctf_event_class_destroy(struct bt_ctf_object
*obj
)
189 bt_ctf_event_class_common_finalize(obj
);
193 struct bt_ctf_event_class
*bt_ctf_event_class_create(const char *name
)
195 struct bt_ctf_event_class
*ctf_event_class
= NULL
;
199 BT_LOGW_STR("Invalid parameter: name is NULL.");
203 BT_LOGD("Creating event class object: name=\"%s\"",
205 ctf_event_class
= g_new0(struct bt_ctf_event_class
, 1);
206 if (!ctf_event_class
) {
207 BT_LOGE_STR("Failed to allocate one event class.");
211 ret
= bt_ctf_event_class_common_initialize(BT_CTF_TO_COMMON(ctf_event_class
),
212 name
, bt_ctf_event_class_destroy
,
213 (bt_ctf_field_type_structure_create_func
)
214 bt_ctf_field_type_structure_create
);
222 bt_ctf_object_put_ref(ctf_event_class
);
225 return ctf_event_class
;
228 const char *bt_ctf_event_class_get_name(struct bt_ctf_event_class
*event_class
)
230 return bt_ctf_event_class_common_get_name(BT_CTF_TO_COMMON(event_class
));
233 int64_t bt_ctf_event_class_get_id(struct bt_ctf_event_class
*event_class
)
235 return bt_ctf_event_class_common_get_id(BT_CTF_TO_COMMON(event_class
));
238 int bt_ctf_event_class_set_id(struct bt_ctf_event_class
*event_class
,
241 return bt_ctf_event_class_common_set_id(BT_CTF_TO_COMMON(event_class
), id
);
244 enum bt_ctf_event_class_log_level
bt_ctf_event_class_get_log_level(
245 struct bt_ctf_event_class
*event_class
)
247 return bt_ctf_event_class_common_get_log_level(BT_CTF_TO_COMMON(event_class
));
250 int bt_ctf_event_class_set_log_level(struct bt_ctf_event_class
*event_class
,
251 enum bt_ctf_event_class_log_level log_level
)
253 return bt_ctf_event_class_common_set_log_level(BT_CTF_TO_COMMON(event_class
),
257 const char *bt_ctf_event_class_get_emf_uri(
258 struct bt_ctf_event_class
*event_class
)
260 return bt_ctf_event_class_common_get_emf_uri(BT_CTF_TO_COMMON(event_class
));
263 int bt_ctf_event_class_set_emf_uri(struct bt_ctf_event_class
*event_class
,
266 return bt_ctf_event_class_common_set_emf_uri(BT_CTF_TO_COMMON(event_class
),
270 struct bt_ctf_stream_class
*bt_ctf_event_class_get_stream_class(
271 struct bt_ctf_event_class
*event_class
)
273 BT_CTF_ASSERT_PRE_NON_NULL(event_class
, "Event class");
274 return bt_ctf_object_get_ref(bt_ctf_event_class_common_borrow_stream_class(
275 BT_CTF_TO_COMMON(event_class
)));
278 struct bt_ctf_field_type
*bt_ctf_event_class_get_payload_field_type(
279 struct bt_ctf_event_class
*event_class
)
281 return bt_ctf_object_get_ref(bt_ctf_event_class_common_borrow_payload_field_type(
282 BT_CTF_TO_COMMON(event_class
)));
285 int bt_ctf_event_class_set_payload_field_type(
286 struct bt_ctf_event_class
*event_class
,
287 struct bt_ctf_field_type
*field_type
)
289 return bt_ctf_event_class_common_set_payload_field_type(
290 BT_CTF_TO_COMMON(event_class
), (void *) field_type
);
293 struct bt_ctf_field_type
*bt_ctf_event_class_get_context_field_type(
294 struct bt_ctf_event_class
*event_class
)
296 return bt_ctf_object_get_ref(bt_ctf_event_class_common_borrow_context_field_type(
297 BT_CTF_TO_COMMON(event_class
)));
300 int bt_ctf_event_class_set_context_field_type(
301 struct bt_ctf_event_class
*event_class
,
302 struct bt_ctf_field_type
*field_type
)
304 return bt_ctf_event_class_common_set_context_field_type(
305 BT_CTF_TO_COMMON(event_class
), (void *) field_type
);
308 int bt_ctf_event_class_add_field(struct bt_ctf_event_class
*event_class
,
309 struct bt_ctf_field_type
*type
,
314 if (!event_class
|| !type
) {
315 BT_LOGW("Invalid parameter: event class or field type is NULL: "
316 "event-class-addr=%p, field-type-addr=%p",
322 if (!bt_ctf_identifier_is_valid(name
)) {
323 BT_LOGW("Invalid parameter: event class's payload field type's field name is not a valid CTF identifier: "
324 "addr=%p, name=\"%s\", id=%" PRId64
", field-name=\"%s\"",
325 event_class
, bt_ctf_event_class_get_name(event_class
),
326 bt_ctf_event_class_get_id(event_class
),
332 if (event_class
->common
.frozen
) {
333 BT_LOGW("Invalid parameter: event class is frozen: "
334 "addr=%p, name=\"%s\", id=%" PRId64
,
335 event_class
, bt_ctf_event_class_get_name(event_class
),
336 bt_ctf_event_class_get_id(event_class
));
341 if (!event_class
->common
.payload_field_type
) {
342 BT_LOGW("Event class has no payload field type: "
343 "addr=%p, name=\"%s\", id=%" PRId64
,
344 event_class
, bt_ctf_event_class_get_name(event_class
),
345 bt_ctf_event_class_get_id(event_class
));
350 BT_ASSERT(bt_ctf_field_type_common_get_type_id(
351 event_class
->common
.payload_field_type
) ==
352 BT_CTF_FIELD_TYPE_ID_STRUCT
);
353 ret
= bt_ctf_field_type_structure_add_field(
354 (void *) event_class
->common
.payload_field_type
,
355 (void *) type
, name
);
356 BT_LOGV("Added field to event class's payload field type: "
357 "event-class-addr=%p, event-class-name=\"%s\", "
358 "event-class-id=%" PRId64
", field-name=\"%s\", ft-addr=%p",
359 event_class
, bt_ctf_event_class_get_name(event_class
),
360 bt_ctf_event_class_get_id(event_class
), name
, type
);
365 int64_t bt_ctf_event_class_get_payload_type_field_count(
366 struct bt_ctf_event_class
*event_class
)
371 BT_LOGW_STR("Invalid parameter: event class is NULL.");
376 if (!event_class
->common
.payload_field_type
) {
377 BT_LOGV("Event class has no payload field type: "
378 "addr=%p, name=\"%s\", id=%" PRId64
,
379 event_class
, bt_ctf_event_class_get_name(event_class
),
380 bt_ctf_event_class_get_id(event_class
));
385 BT_ASSERT(bt_ctf_field_type_common_get_type_id(
386 event_class
->common
.payload_field_type
) ==
387 BT_CTF_FIELD_TYPE_ID_STRUCT
);
388 ret
= bt_ctf_field_type_common_structure_get_field_count(
389 event_class
->common
.payload_field_type
);
394 int bt_ctf_event_class_get_payload_type_field_by_index(
395 struct bt_ctf_event_class
*event_class
,
396 const char **field_name
, struct bt_ctf_field_type
**field_type
,
402 BT_LOGW_STR("Invalid parameter: event class is NULL.");
407 if (!event_class
->common
.payload_field_type
) {
408 BT_LOGV("Event class has no payload field type: "
409 "addr=%p, name=\"%s\", id=%" PRId64
", index=%" PRIu64
,
410 event_class
, bt_ctf_event_class_get_name(event_class
),
411 bt_ctf_event_class_get_id(event_class
), index
);
416 BT_ASSERT(bt_ctf_field_type_common_get_type_id(
417 event_class
->common
.payload_field_type
) ==
418 BT_CTF_FIELD_TYPE_ID_STRUCT
);
419 ret
= bt_ctf_field_type_structure_get_field_by_index(
420 (void *) event_class
->common
.payload_field_type
,
421 field_name
, (void *) field_type
, index
);
427 struct bt_ctf_field_type
*
428 bt_ctf_event_class_get_payload_type_field_type_by_name(
429 struct bt_ctf_event_class
*event_class
, const char *name
)
432 struct bt_ctf_field_type
*field_type
= NULL
;
434 if (!event_class
|| !name
) {
435 BT_LOGW("Invalid parameter: event class or name is NULL: "
436 "event-class-addr=%p, name-addr=%p",
441 if (!event_class
->common
.payload_field_type
) {
442 BT_LOGV("Event class has no payload field type: "
443 "addr=%p, name=\"%s\", id=%" PRId64
,
444 event_class
, bt_ctf_event_class_get_name(event_class
),
445 bt_ctf_event_class_get_id(event_class
));
449 BT_ASSERT(bt_ctf_field_type_common_get_type_id(
450 event_class
->common
.payload_field_type
) ==
451 BT_CTF_FIELD_TYPE_ID_STRUCT
);
452 name_quark
= g_quark_try_string(name
);
454 BT_LOGE("Cannot get GQuark: string=\"%s\"", name
);
459 * No need to increment field_type's reference count since getting it
460 * from the structure already does.
462 field_type
= (void *)
463 bt_ctf_field_type_structure_get_field_type_by_name(
464 (void *) event_class
->common
.payload_field_type
, name
);
471 int bt_ctf_event_class_serialize(struct bt_ctf_event_class
*event_class
,
472 struct metadata_context
*context
)
475 struct bt_ctf_value
*attr_value
= NULL
;
477 BT_ASSERT(event_class
);
479 BT_LOGD("Serializing event class's metadata: "
480 "event-class-addr=%p, event-class-name=\"%s\", "
481 "event-class-id=%" PRId64
", metadata-context-addr=%p",
482 event_class
, bt_ctf_event_class_get_name(event_class
),
483 bt_ctf_event_class_get_id(event_class
), context
);
484 context
->current_indentation_level
= 1;
485 g_string_assign(context
->field_name
, "");
486 g_string_append(context
->string
, "event {\n");
488 /* Serialize attributes */
489 g_string_append_printf(context
->string
, "\tname = \"%s\";\n",
490 event_class
->common
.name
->str
);
491 BT_ASSERT(event_class
->common
.id
>= 0);
492 g_string_append_printf(context
->string
, "\tid = %" PRId64
";\n",
493 event_class
->common
.id
);
494 g_string_append_printf(context
->string
, "\tstream_id = %" PRId64
";\n",
495 bt_ctf_stream_class_common_get_id(
496 bt_ctf_event_class_common_borrow_stream_class(
497 BT_CTF_TO_COMMON(event_class
))));
499 if (event_class
->common
.log_level
!=
500 BT_CTF_EVENT_CLASS_LOG_LEVEL_UNSPECIFIED
) {
501 g_string_append_printf(context
->string
, "\tloglevel = %d;\n",
502 (int) event_class
->common
.log_level
);
505 if (event_class
->common
.emf_uri
->len
> 0) {
506 g_string_append_printf(context
->string
, "\tmodel.emf.uri = \"%s\";\n",
507 event_class
->common
.emf_uri
->str
);
510 /* Serialize context field type */
511 if (event_class
->common
.context_field_type
) {
512 g_string_append(context
->string
, "\tcontext := ");
513 BT_LOGD_STR("Serializing event class's context field type metadata.");
514 ret
= bt_ctf_field_type_serialize_recursive(
515 (void *) event_class
->common
.context_field_type
,
518 BT_LOGW("Cannot serialize event class's context field type's metadata: "
522 g_string_append(context
->string
, ";\n");
525 /* Serialize payload field type */
526 if (event_class
->common
.payload_field_type
) {
527 g_string_append(context
->string
, "\tfields := ");
528 BT_LOGD_STR("Serializing event class's payload field type metadata.");
529 ret
= bt_ctf_field_type_serialize_recursive(
530 (void *) event_class
->common
.payload_field_type
,
533 BT_LOGW("Cannot serialize event class's payload field type's metadata: "
537 g_string_append(context
->string
, ";\n");
540 g_string_append(context
->string
, "};\n\n");
543 context
->current_indentation_level
= 0;
544 BT_CTF_OBJECT_PUT_REF_AND_RESET(attr_value
);
548 struct bt_ctf_field_type
*bt_ctf_event_class_get_field_by_name(
549 struct bt_ctf_event_class
*event_class
, const char *name
)
552 struct bt_ctf_field_type
*field_type
= NULL
;
554 if (!event_class
|| !name
) {
555 BT_LOGW("Invalid parameter: event class or name is NULL: "
556 "event-class-addr=%p, name-addr=%p",
561 if (!event_class
->common
.payload_field_type
) {
562 BT_LOGV("Event class has no payload field type: "
563 "addr=%p, name=\"%s\", id=%" PRId64
,
565 bt_ctf_event_class_get_name(event_class
),
566 bt_ctf_event_class_get_id(event_class
));
570 BT_ASSERT(event_class
->common
.payload_field_type
->id
==
571 BT_CTF_FIELD_TYPE_ID_STRUCT
);
572 name_quark
= g_quark_try_string(name
);
574 BT_LOGE("Cannot get GQuark: string=\"%s\"", name
);
579 * No need to increment field_type's reference count since getting it
580 * from the structure already does.
582 field_type
= bt_ctf_object_get_ref(
583 bt_ctf_field_type_common_structure_borrow_field_type_by_name(
584 event_class
->common
.payload_field_type
, name
));