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"
25 #include <babeltrace2/lib-logging-internal.h>
27 #include <babeltrace2/assert-pre-internal.h>
28 #include <babeltrace2/assert-internal.h>
29 #include <babeltrace2/compiler-internal.h>
30 #include <babeltrace2/ctf-writer/attributes-internal.h>
31 #include <babeltrace2/ctf-writer/event-class-internal.h>
32 #include <babeltrace2/ctf-writer/event-internal.h>
33 #include <babeltrace2/ctf-writer/event.h>
34 #include <babeltrace2/ctf-writer/field-types-internal.h>
35 #include <babeltrace2/ctf-writer/field-types.h>
36 #include <babeltrace2/ctf-writer/fields-internal.h>
37 #include <babeltrace2/ctf-writer/stream-class-internal.h>
38 #include <babeltrace2/ctf-writer/stream-class.h>
39 #include <babeltrace2/ctf-writer/trace-internal.h>
40 #include <babeltrace2/ctf-writer/utils-internal.h>
41 #include <babeltrace2/ctf-writer/utils.h>
42 #include <babeltrace2/ctf-writer/validation-internal.h>
43 #include <babeltrace2/ctf-writer/writer-internal.h>
44 #include <babeltrace2/endian-internal.h>
45 #include <babeltrace2/ctf-writer/object.h>
46 #include <babeltrace2/types.h>
47 #include <babeltrace2/ctf-writer/values-internal.h>
54 void bt_ctf_event_class_common_finalize(struct bt_ctf_object
*obj
)
56 struct bt_ctf_event_class_common
*event_class
;
58 event_class
= container_of(obj
, struct bt_ctf_event_class_common
, base
);
59 BT_LOGD("Finalizing common event class: addr=%p, name=\"%s\", id=%" PRId64
,
60 event_class
, bt_ctf_event_class_common_get_name(event_class
),
61 bt_ctf_event_class_common_get_id(event_class
));
63 if (event_class
->name
) {
64 g_string_free(event_class
->name
, TRUE
);
67 if (event_class
->emf_uri
) {
68 g_string_free(event_class
->emf_uri
, TRUE
);
71 BT_LOGD_STR("Putting context field type.");
72 bt_ctf_object_put_ref(event_class
->context_field_type
);
73 BT_LOGD_STR("Putting payload field type.");
74 bt_ctf_object_put_ref(event_class
->payload_field_type
);
78 int bt_ctf_event_class_common_initialize(struct bt_ctf_event_class_common
*event_class
,
79 const char *name
, bt_ctf_object_release_func release_func
,
80 bt_ctf_field_type_structure_create_func ft_struct_create_func
)
84 BT_LOGD("Initializing common event class object: name=\"%s\"",
86 bt_ctf_object_init_shared_with_parent(&event_class
->base
, release_func
);
87 event_class
->payload_field_type
= ft_struct_create_func();
88 if (!event_class
->payload_field_type
) {
89 BT_LOGE_STR("Cannot create event class's initial payload field type object.");
94 event_class
->name
= g_string_new(name
);
95 if (!event_class
->name
) {
96 BT_LOGE_STR("Failed to allocate a GString.");
100 event_class
->emf_uri
= g_string_new(NULL
);
101 if (!event_class
->emf_uri
) {
102 BT_LOGE_STR("Failed to allocate a GString.");
106 event_class
->log_level
= BT_CTF_EVENT_CLASS_LOG_LEVEL_UNSPECIFIED
;
107 BT_LOGD("Initialized common event class object: addr=%p, name=\"%s\"",
108 event_class
, bt_ctf_event_class_common_get_name(event_class
));
117 void bt_ctf_event_class_common_freeze(struct bt_ctf_event_class_common
*event_class
)
119 BT_ASSERT(event_class
);
121 if (event_class
->frozen
) {
125 BT_LOGD("Freezing event class: addr=%p, name=\"%s\", id=%" PRId64
,
126 event_class
, bt_ctf_event_class_common_get_name(event_class
),
127 bt_ctf_event_class_common_get_id(event_class
));
128 event_class
->frozen
= 1;
129 BT_LOGD_STR("Freezing event class's context field type.");
130 bt_ctf_field_type_common_freeze(event_class
->context_field_type
);
131 BT_LOGD_STR("Freezing event class's payload field type.");
132 bt_ctf_field_type_common_freeze(event_class
->payload_field_type
);
136 int bt_ctf_event_class_common_validate_single_clock_class(
137 struct bt_ctf_event_class_common
*event_class
,
138 struct bt_ctf_clock_class
**expected_clock_class
)
142 BT_ASSERT(event_class
);
143 BT_ASSERT(expected_clock_class
);
144 ret
= bt_ctf_field_type_common_validate_single_clock_class(
145 event_class
->context_field_type
,
146 expected_clock_class
);
148 BT_LOGW("Event class's context 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
->context_field_type
);
162 ret
= bt_ctf_field_type_common_validate_single_clock_class(
163 event_class
->payload_field_type
,
164 expected_clock_class
);
166 BT_LOGW("Event class's payload field type "
167 "is not recursively mapped to the "
168 "expected clock class: "
169 "event-class-addr=%p, "
170 "event-class-name=\"%s\", "
171 "event-class-id=%" PRId64
", "
174 bt_ctf_event_class_common_get_name(event_class
),
176 event_class
->payload_field_type
);
185 void bt_ctf_event_class_destroy(struct bt_ctf_object
*obj
)
187 bt_ctf_event_class_common_finalize(obj
);
191 struct bt_ctf_event_class
*bt_ctf_event_class_create(const char *name
)
193 struct bt_ctf_event_class
*ctf_event_class
= NULL
;
197 BT_LOGW_STR("Invalid parameter: name is NULL.");
201 BT_LOGD("Creating event class object: name=\"%s\"",
203 ctf_event_class
= g_new0(struct bt_ctf_event_class
, 1);
204 if (!ctf_event_class
) {
205 BT_LOGE_STR("Failed to allocate one event class.");
209 ret
= bt_ctf_event_class_common_initialize(BT_CTF_TO_COMMON(ctf_event_class
),
210 name
, bt_ctf_event_class_destroy
,
211 (bt_ctf_field_type_structure_create_func
)
212 bt_ctf_field_type_structure_create
);
220 bt_ctf_object_put_ref(ctf_event_class
);
223 return ctf_event_class
;
226 const char *bt_ctf_event_class_get_name(struct bt_ctf_event_class
*event_class
)
228 return bt_ctf_event_class_common_get_name(BT_CTF_TO_COMMON(event_class
));
231 int64_t bt_ctf_event_class_get_id(struct bt_ctf_event_class
*event_class
)
233 return bt_ctf_event_class_common_get_id(BT_CTF_TO_COMMON(event_class
));
236 int bt_ctf_event_class_set_id(struct bt_ctf_event_class
*event_class
,
239 return bt_ctf_event_class_common_set_id(BT_CTF_TO_COMMON(event_class
), id
);
242 enum bt_ctf_event_class_log_level
bt_ctf_event_class_get_log_level(
243 struct bt_ctf_event_class
*event_class
)
245 return bt_ctf_event_class_common_get_log_level(BT_CTF_TO_COMMON(event_class
));
248 int bt_ctf_event_class_set_log_level(struct bt_ctf_event_class
*event_class
,
249 enum bt_ctf_event_class_log_level log_level
)
251 return bt_ctf_event_class_common_set_log_level(BT_CTF_TO_COMMON(event_class
),
255 const char *bt_ctf_event_class_get_emf_uri(
256 struct bt_ctf_event_class
*event_class
)
258 return bt_ctf_event_class_common_get_emf_uri(BT_CTF_TO_COMMON(event_class
));
261 int bt_ctf_event_class_set_emf_uri(struct bt_ctf_event_class
*event_class
,
264 return bt_ctf_event_class_common_set_emf_uri(BT_CTF_TO_COMMON(event_class
),
268 struct bt_ctf_stream_class
*bt_ctf_event_class_get_stream_class(
269 struct bt_ctf_event_class
*event_class
)
271 BT_ASSERT_PRE_NON_NULL(event_class
, "Event class");
272 return bt_ctf_object_get_ref(bt_ctf_event_class_common_borrow_stream_class(
273 BT_CTF_TO_COMMON(event_class
)));
276 struct bt_ctf_field_type
*bt_ctf_event_class_get_payload_field_type(
277 struct bt_ctf_event_class
*event_class
)
279 return bt_ctf_object_get_ref(bt_ctf_event_class_common_borrow_payload_field_type(
280 BT_CTF_TO_COMMON(event_class
)));
283 int bt_ctf_event_class_set_payload_field_type(
284 struct bt_ctf_event_class
*event_class
,
285 struct bt_ctf_field_type
*field_type
)
287 return bt_ctf_event_class_common_set_payload_field_type(
288 BT_CTF_TO_COMMON(event_class
), (void *) field_type
);
291 struct bt_ctf_field_type
*bt_ctf_event_class_get_context_field_type(
292 struct bt_ctf_event_class
*event_class
)
294 return bt_ctf_object_get_ref(bt_ctf_event_class_common_borrow_context_field_type(
295 BT_CTF_TO_COMMON(event_class
)));
298 int bt_ctf_event_class_set_context_field_type(
299 struct bt_ctf_event_class
*event_class
,
300 struct bt_ctf_field_type
*field_type
)
302 return bt_ctf_event_class_common_set_context_field_type(
303 BT_CTF_TO_COMMON(event_class
), (void *) field_type
);
306 int bt_ctf_event_class_add_field(struct bt_ctf_event_class
*event_class
,
307 struct bt_ctf_field_type
*type
,
312 if (!event_class
|| !type
) {
313 BT_LOGW("Invalid parameter: event class or field type is NULL: "
314 "event-class-addr=%p, field-type-addr=%p",
320 if (!bt_ctf_identifier_is_valid(name
)) {
321 BT_LOGW("Invalid parameter: event class's payload field type's field name is not a valid CTF identifier: "
322 "addr=%p, name=\"%s\", id=%" PRId64
", field-name=\"%s\"",
323 event_class
, bt_ctf_event_class_get_name(event_class
),
324 bt_ctf_event_class_get_id(event_class
),
330 if (event_class
->common
.frozen
) {
331 BT_LOGW("Invalid parameter: event class is frozen: "
332 "addr=%p, name=\"%s\", id=%" PRId64
,
333 event_class
, bt_ctf_event_class_get_name(event_class
),
334 bt_ctf_event_class_get_id(event_class
));
339 if (!event_class
->common
.payload_field_type
) {
340 BT_LOGW("Event class has no payload field type: "
341 "addr=%p, name=\"%s\", id=%" PRId64
,
342 event_class
, bt_ctf_event_class_get_name(event_class
),
343 bt_ctf_event_class_get_id(event_class
));
348 BT_ASSERT(bt_ctf_field_type_common_get_type_id(
349 event_class
->common
.payload_field_type
) ==
350 BT_CTF_FIELD_TYPE_ID_STRUCT
);
351 ret
= bt_ctf_field_type_structure_add_field(
352 (void *) event_class
->common
.payload_field_type
,
353 (void *) type
, name
);
354 BT_LOGV("Added field to event class's payload field type: "
355 "event-class-addr=%p, event-class-name=\"%s\", "
356 "event-class-id=%" PRId64
", field-name=\"%s\", ft-addr=%p",
357 event_class
, bt_ctf_event_class_get_name(event_class
),
358 bt_ctf_event_class_get_id(event_class
), name
, type
);
363 int64_t bt_ctf_event_class_get_payload_type_field_count(
364 struct bt_ctf_event_class
*event_class
)
369 BT_LOGW_STR("Invalid parameter: event class is NULL.");
374 if (!event_class
->common
.payload_field_type
) {
375 BT_LOGV("Event class has no payload field type: "
376 "addr=%p, name=\"%s\", id=%" PRId64
,
377 event_class
, bt_ctf_event_class_get_name(event_class
),
378 bt_ctf_event_class_get_id(event_class
));
383 BT_ASSERT(bt_ctf_field_type_common_get_type_id(
384 event_class
->common
.payload_field_type
) ==
385 BT_CTF_FIELD_TYPE_ID_STRUCT
);
386 ret
= bt_ctf_field_type_common_structure_get_field_count(
387 event_class
->common
.payload_field_type
);
392 int bt_ctf_event_class_get_payload_type_field_by_index(
393 struct bt_ctf_event_class
*event_class
,
394 const char **field_name
, struct bt_ctf_field_type
**field_type
,
400 BT_LOGW_STR("Invalid parameter: event class is NULL.");
405 if (!event_class
->common
.payload_field_type
) {
406 BT_LOGV("Event class has no payload field type: "
407 "addr=%p, name=\"%s\", id=%" PRId64
", index=%" PRIu64
,
408 event_class
, bt_ctf_event_class_get_name(event_class
),
409 bt_ctf_event_class_get_id(event_class
), index
);
414 BT_ASSERT(bt_ctf_field_type_common_get_type_id(
415 event_class
->common
.payload_field_type
) ==
416 BT_CTF_FIELD_TYPE_ID_STRUCT
);
417 ret
= bt_ctf_field_type_structure_get_field_by_index(
418 (void *) event_class
->common
.payload_field_type
,
419 field_name
, (void *) field_type
, index
);
425 struct bt_ctf_field_type
*
426 bt_ctf_event_class_get_payload_type_field_type_by_name(
427 struct bt_ctf_event_class
*event_class
, const char *name
)
430 struct bt_ctf_field_type
*field_type
= NULL
;
432 if (!event_class
|| !name
) {
433 BT_LOGW("Invalid parameter: event class or name is NULL: "
434 "event-class-addr=%p, name-addr=%p",
439 if (!event_class
->common
.payload_field_type
) {
440 BT_LOGV("Event class has no payload field type: "
441 "addr=%p, name=\"%s\", id=%" PRId64
,
442 event_class
, bt_ctf_event_class_get_name(event_class
),
443 bt_ctf_event_class_get_id(event_class
));
447 BT_ASSERT(bt_ctf_field_type_common_get_type_id(
448 event_class
->common
.payload_field_type
) ==
449 BT_CTF_FIELD_TYPE_ID_STRUCT
);
450 name_quark
= g_quark_try_string(name
);
452 BT_LOGE("Cannot get GQuark: string=\"%s\"", name
);
457 * No need to increment field_type's reference count since getting it
458 * from the structure already does.
460 field_type
= (void *)
461 bt_ctf_field_type_structure_get_field_type_by_name(
462 (void *) event_class
->common
.payload_field_type
, name
);
469 int bt_ctf_event_class_serialize(struct bt_ctf_event_class
*event_class
,
470 struct metadata_context
*context
)
473 struct bt_ctf_value
*attr_value
= NULL
;
475 BT_ASSERT(event_class
);
477 BT_LOGD("Serializing event class's metadata: "
478 "event-class-addr=%p, event-class-name=\"%s\", "
479 "event-class-id=%" PRId64
", metadata-context-addr=%p",
480 event_class
, bt_ctf_event_class_get_name(event_class
),
481 bt_ctf_event_class_get_id(event_class
), context
);
482 context
->current_indentation_level
= 1;
483 g_string_assign(context
->field_name
, "");
484 g_string_append(context
->string
, "event {\n");
486 /* Serialize attributes */
487 g_string_append_printf(context
->string
, "\tname = \"%s\";\n",
488 event_class
->common
.name
->str
);
489 BT_ASSERT(event_class
->common
.id
>= 0);
490 g_string_append_printf(context
->string
, "\tid = %" PRId64
";\n",
491 event_class
->common
.id
);
492 g_string_append_printf(context
->string
, "\tstream_id = %" PRId64
";\n",
493 bt_ctf_stream_class_common_get_id(
494 bt_ctf_event_class_common_borrow_stream_class(
495 BT_CTF_TO_COMMON(event_class
))));
497 if (event_class
->common
.log_level
!=
498 BT_CTF_EVENT_CLASS_LOG_LEVEL_UNSPECIFIED
) {
499 g_string_append_printf(context
->string
, "\tloglevel = %d;\n",
500 (int) event_class
->common
.log_level
);
503 if (event_class
->common
.emf_uri
->len
> 0) {
504 g_string_append_printf(context
->string
, "\tmodel.emf.uri = \"%s\";\n",
505 event_class
->common
.emf_uri
->str
);
508 /* Serialize context field type */
509 if (event_class
->common
.context_field_type
) {
510 g_string_append(context
->string
, "\tcontext := ");
511 BT_LOGD_STR("Serializing event class's context field type metadata.");
512 ret
= bt_ctf_field_type_serialize_recursive(
513 (void *) event_class
->common
.context_field_type
,
516 BT_LOGW("Cannot serialize event class's context field type's metadata: "
520 g_string_append(context
->string
, ";\n");
523 /* Serialize payload field type */
524 if (event_class
->common
.payload_field_type
) {
525 g_string_append(context
->string
, "\tfields := ");
526 BT_LOGD_STR("Serializing event class's payload field type metadata.");
527 ret
= bt_ctf_field_type_serialize_recursive(
528 (void *) event_class
->common
.payload_field_type
,
531 BT_LOGW("Cannot serialize event class's payload field type's metadata: "
535 g_string_append(context
->string
, ";\n");
538 g_string_append(context
->string
, "};\n\n");
541 context
->current_indentation_level
= 0;
542 BT_CTF_OBJECT_PUT_REF_AND_RESET(attr_value
);
546 struct bt_ctf_field_type
*bt_ctf_event_class_get_field_by_name(
547 struct bt_ctf_event_class
*event_class
, const char *name
)
550 struct bt_ctf_field_type
*field_type
= NULL
;
552 if (!event_class
|| !name
) {
553 BT_LOGW("Invalid parameter: event class or name is NULL: "
554 "event-class-addr=%p, name-addr=%p",
559 if (!event_class
->common
.payload_field_type
) {
560 BT_LOGV("Event class has no payload field type: "
561 "addr=%p, name=\"%s\", id=%" PRId64
,
563 bt_ctf_event_class_get_name(event_class
),
564 bt_ctf_event_class_get_id(event_class
));
568 BT_ASSERT(event_class
->common
.payload_field_type
->id
==
569 BT_CTF_FIELD_TYPE_ID_STRUCT
);
570 name_quark
= g_quark_try_string(name
);
572 BT_LOGE("Cannot get GQuark: string=\"%s\"", name
);
577 * No need to increment field_type's reference count since getting it
578 * from the structure already does.
580 field_type
= bt_ctf_object_get_ref(
581 bt_ctf_field_type_common_structure_borrow_field_type_by_name(
582 event_class
->common
.payload_field_type
, name
));