cpp-common/bt2c/fmt.hpp: use `wise_enum::string_type` in `EnableIfIsWiseEnum` definition
[babeltrace.git] / src / ctf-writer / event-class.c
1 /*
2 * SPDX-License-Identifier: MIT
3 *
4 * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
5 * Copyright 2017-2018 Philippe Proulx <pproulx@efficios.com>
6 */
7
8 #define BT_LOG_TAG "CTF-WRITER/EVENT-CLASS"
9 #include "logging.h"
10
11 #include <glib.h>
12 #include <inttypes.h>
13 #include <stdlib.h>
14
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
21 #include "common/assert.h"
22 #include "compat/compiler.h"
23 #include "compat/endian.h"
24
25 #include "assert-pre.h"
26 #include "attributes.h"
27 #include "event-class.h"
28 #include "event.h"
29 #include "fields.h"
30 #include "field-types.h"
31 #include "stream-class.h"
32 #include "trace.h"
33 #include "utils.h"
34 #include "validation.h"
35 #include "values.h"
36 #include "writer.h"
37
38 void bt_ctf_event_class_common_finalize(struct bt_ctf_object *obj)
39 {
40 struct bt_ctf_event_class_common *event_class;
41
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));
46
47 if (event_class->name) {
48 g_string_free(event_class->name, TRUE);
49 }
50
51 if (event_class->emf_uri) {
52 g_string_free(event_class->emf_uri, TRUE);
53 }
54
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);
59 }
60
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)
64 {
65 int ret = 0;
66
67 BT_LOGD("Initializing common event class object: name=\"%s\"",
68 name);
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.");
73 goto error;
74 }
75
76 event_class->id = -1;
77 event_class->name = g_string_new(name);
78 if (!event_class->name) {
79 BT_LOGE_STR("Failed to allocate a GString.");
80 goto error;
81 }
82
83 event_class->emf_uri = g_string_new(NULL);
84 if (!event_class->emf_uri) {
85 BT_LOGE_STR("Failed to allocate a GString.");
86 goto error;
87 }
88
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));
92 return ret;
93
94 error:
95 ret = -1;
96 return ret;
97 }
98
99 void bt_ctf_event_class_common_freeze(struct bt_ctf_event_class_common *event_class)
100 {
101 BT_ASSERT_DBG(event_class);
102
103 if (event_class->frozen) {
104 return;
105 }
106
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);
115 }
116
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)
120 {
121 int ret = 0;
122
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);
128 if (ret) {
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 ", "
135 "ft-addr=%p",
136 event_class,
137 bt_ctf_event_class_common_get_name(event_class),
138 event_class->id,
139 event_class->context_field_type);
140 goto end;
141 }
142
143 ret = bt_ctf_field_type_common_validate_single_clock_class(
144 event_class->payload_field_type,
145 expected_clock_class);
146 if (ret) {
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 ", "
153 "ft-addr=%p",
154 event_class,
155 bt_ctf_event_class_common_get_name(event_class),
156 event_class->id,
157 event_class->payload_field_type);
158 goto end;
159 }
160
161 end:
162 return ret;
163 }
164
165 static
166 void bt_ctf_event_class_destroy(struct bt_ctf_object *obj)
167 {
168 bt_ctf_event_class_common_finalize(obj);
169 g_free(obj);
170 }
171
172 BT_EXPORT
173 struct bt_ctf_event_class *bt_ctf_event_class_create(const char *name)
174 {
175 struct bt_ctf_event_class *ctf_event_class = NULL;
176 int ret;
177
178 if (!name) {
179 BT_LOGW_STR("Invalid parameter: name is NULL.");
180 goto error;
181 }
182
183 BT_LOGD("Creating event class object: name=\"%s\"",
184 name);
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.");
188 goto error;
189 }
190
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);
195 if (ret) {
196 goto error;
197 }
198
199 goto end;
200
201 error:
202 bt_ctf_object_put_ref(ctf_event_class);
203
204 end:
205 return ctf_event_class;
206 }
207
208 BT_EXPORT
209 const char *bt_ctf_event_class_get_name(struct bt_ctf_event_class *event_class)
210 {
211 return bt_ctf_event_class_common_get_name(BT_CTF_TO_COMMON(event_class));
212 }
213
214 BT_EXPORT
215 int64_t bt_ctf_event_class_get_id(struct bt_ctf_event_class *event_class)
216 {
217 return bt_ctf_event_class_common_get_id(BT_CTF_TO_COMMON(event_class));
218 }
219
220 BT_EXPORT
221 int bt_ctf_event_class_set_id(struct bt_ctf_event_class *event_class,
222 uint64_t id)
223 {
224 return bt_ctf_event_class_common_set_id(BT_CTF_TO_COMMON(event_class), id);
225 }
226
227 BT_EXPORT
228 enum bt_ctf_event_class_log_level bt_ctf_event_class_get_log_level(
229 struct bt_ctf_event_class *event_class)
230 {
231 return bt_ctf_event_class_common_get_log_level(BT_CTF_TO_COMMON(event_class));
232 }
233
234 BT_EXPORT
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)
237 {
238 return bt_ctf_event_class_common_set_log_level(BT_CTF_TO_COMMON(event_class),
239 log_level);
240 }
241
242 BT_EXPORT
243 const char *bt_ctf_event_class_get_emf_uri(
244 struct bt_ctf_event_class *event_class)
245 {
246 return bt_ctf_event_class_common_get_emf_uri(BT_CTF_TO_COMMON(event_class));
247 }
248
249 BT_EXPORT
250 int bt_ctf_event_class_set_emf_uri(struct bt_ctf_event_class *event_class,
251 const char *emf_uri)
252 {
253 return bt_ctf_event_class_common_set_emf_uri(BT_CTF_TO_COMMON(event_class),
254 emf_uri);
255 }
256
257 BT_EXPORT
258 struct bt_ctf_stream_class *bt_ctf_event_class_get_stream_class(
259 struct bt_ctf_event_class *event_class)
260 {
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)));
264 }
265
266 BT_EXPORT
267 struct bt_ctf_field_type *bt_ctf_event_class_get_payload_field_type(
268 struct bt_ctf_event_class *event_class)
269 {
270 return bt_ctf_object_get_ref(bt_ctf_event_class_common_borrow_payload_field_type(
271 BT_CTF_TO_COMMON(event_class)));
272 }
273
274 BT_EXPORT
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)
278 {
279 return bt_ctf_event_class_common_set_payload_field_type(
280 BT_CTF_TO_COMMON(event_class), (void *) field_type);
281 }
282
283 BT_EXPORT
284 struct bt_ctf_field_type *bt_ctf_event_class_get_context_field_type(
285 struct bt_ctf_event_class *event_class)
286 {
287 return bt_ctf_object_get_ref(bt_ctf_event_class_common_borrow_context_field_type(
288 BT_CTF_TO_COMMON(event_class)));
289 }
290
291 BT_EXPORT
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)
295 {
296 return bt_ctf_event_class_common_set_context_field_type(
297 BT_CTF_TO_COMMON(event_class), (void *) field_type);
298 }
299
300 BT_EXPORT
301 int bt_ctf_event_class_add_field(struct bt_ctf_event_class *event_class,
302 struct bt_ctf_field_type *type,
303 const char *name)
304 {
305 int ret = 0;
306
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",
310 event_class, type);
311 ret = -1;
312 goto end;
313 }
314
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),
320 name);
321 ret = -1;
322 goto end;
323 }
324
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));
330 ret = -1;
331 goto end;
332 }
333
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));
339 ret = -1;
340 goto end;
341 }
342
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);
354 end:
355 return ret;
356 }
357
358 BT_EXPORT
359 int64_t bt_ctf_event_class_get_payload_type_field_count(
360 struct bt_ctf_event_class *event_class)
361 {
362 int64_t ret;
363
364 if (!event_class) {
365 BT_LOGW_STR("Invalid parameter: event class is NULL.");
366 ret = (int64_t) -1;
367 goto end;
368 }
369
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));
375 ret = (int64_t) -1;
376 goto end;
377 }
378
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);
384 end:
385 return ret;
386 }
387
388 BT_EXPORT
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,
392 uint64_t index)
393 {
394 int ret;
395
396 if (!event_class) {
397 BT_LOGW_STR("Invalid parameter: event class is NULL.");
398 ret = -1;
399 goto end;
400 }
401
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);
407 ret = -1;
408 goto end;
409 }
410
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);
417
418 end:
419 return ret;
420 }
421
422 BT_EXPORT
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)
426 {
427 GQuark name_quark;
428 struct bt_ctf_field_type *field_type = NULL;
429
430 if (!event_class || !name) {
431 BT_LOGW("Invalid parameter: event class or name is NULL: "
432 "event-class-addr=%p, name-addr=%p",
433 event_class, name);
434 goto end;
435 }
436
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));
442 goto end;
443 }
444
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);
449 if (!name_quark) {
450 BT_LOGE("Cannot get GQuark: string=\"%s\"", name);
451 goto end;
452 }
453
454 /*
455 * No need to increment field_type's reference count since getting it
456 * from the structure already does.
457 */
458 field_type = (void *)
459 bt_ctf_field_type_structure_get_field_type_by_name(
460 (void *) event_class->common.payload_field_type, name);
461
462 end:
463 return field_type;
464 }
465
466 int bt_ctf_event_class_serialize(struct bt_ctf_event_class *event_class,
467 struct metadata_context *context)
468 {
469 int ret = 0;
470 struct bt_ctf_value *attr_value = NULL;
471
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");
482
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))));
493
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);
498 }
499
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);
503 }
504
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,
511 context);
512 if (ret) {
513 BT_LOGW("Cannot serialize event class's context field type's metadata: "
514 "ret=%d", ret);
515 goto end;
516 }
517 g_string_append(context->string, ";\n");
518 }
519
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,
526 context);
527 if (ret) {
528 BT_LOGW("Cannot serialize event class's payload field type's metadata: "
529 "ret=%d", ret);
530 goto end;
531 }
532 g_string_append(context->string, ";\n");
533 }
534
535 g_string_append(context->string, "};\n\n");
536
537 end:
538 context->current_indentation_level = 0;
539 BT_CTF_OBJECT_PUT_REF_AND_RESET(attr_value);
540 return ret;
541 }
542
543 BT_EXPORT
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)
546 {
547 GQuark name_quark;
548 struct bt_ctf_field_type *field_type = NULL;
549
550 if (!event_class || !name) {
551 BT_LOGW("Invalid parameter: event class or name is NULL: "
552 "event-class-addr=%p, name-addr=%p",
553 event_class, name);
554 goto end;
555 }
556
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,
560 event_class,
561 bt_ctf_event_class_get_name(event_class),
562 bt_ctf_event_class_get_id(event_class));
563 goto end;
564 }
565
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);
569 if (!name_quark) {
570 BT_LOGE("Cannot get GQuark: string=\"%s\"", name);
571 goto end;
572 }
573
574 /*
575 * No need to increment field_type's reference count since getting it
576 * from the structure already does.
577 */
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));
581
582 end:
583 return field_type;
584 }
This page took 0.042866 seconds and 4 git commands to generate.