Visibility hidden by default
[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 #include <babeltrace2/types.h>
21
22 #include "common/assert.h"
23 #include "compat/compiler.h"
24 #include "compat/endian.h"
25
26 #include "assert-pre.h"
27 #include "attributes.h"
28 #include "event-class.h"
29 #include "event.h"
30 #include "fields.h"
31 #include "field-types.h"
32 #include "stream-class.h"
33 #include "trace.h"
34 #include "utils.h"
35 #include "validation.h"
36 #include "values.h"
37 #include "writer.h"
38
39 void bt_ctf_event_class_common_finalize(struct bt_ctf_object *obj)
40 {
41 struct bt_ctf_event_class_common *event_class;
42
43 event_class = container_of(obj, struct bt_ctf_event_class_common, base);
44 BT_LOGD("Finalizing common event class: addr=%p, name=\"%s\", id=%" PRId64,
45 event_class, bt_ctf_event_class_common_get_name(event_class),
46 bt_ctf_event_class_common_get_id(event_class));
47
48 if (event_class->name) {
49 g_string_free(event_class->name, TRUE);
50 }
51
52 if (event_class->emf_uri) {
53 g_string_free(event_class->emf_uri, TRUE);
54 }
55
56 BT_LOGD_STR("Putting context field type.");
57 bt_ctf_object_put_ref(event_class->context_field_type);
58 BT_LOGD_STR("Putting payload field type.");
59 bt_ctf_object_put_ref(event_class->payload_field_type);
60 }
61
62 int bt_ctf_event_class_common_initialize(struct bt_ctf_event_class_common *event_class,
63 const char *name, bt_ctf_object_release_func release_func,
64 bt_ctf_field_type_structure_create_func ft_struct_create_func)
65 {
66 int ret = 0;
67
68 BT_LOGD("Initializing common event class object: name=\"%s\"",
69 name);
70 bt_ctf_object_init_shared_with_parent(&event_class->base, release_func);
71 event_class->payload_field_type = ft_struct_create_func();
72 if (!event_class->payload_field_type) {
73 BT_LOGE_STR("Cannot create event class's initial payload field type object.");
74 goto error;
75 }
76
77 event_class->id = -1;
78 event_class->name = g_string_new(name);
79 if (!event_class->name) {
80 BT_LOGE_STR("Failed to allocate a GString.");
81 goto error;
82 }
83
84 event_class->emf_uri = g_string_new(NULL);
85 if (!event_class->emf_uri) {
86 BT_LOGE_STR("Failed to allocate a GString.");
87 goto error;
88 }
89
90 event_class->log_level = BT_CTF_EVENT_CLASS_LOG_LEVEL_UNSPECIFIED;
91 BT_LOGD("Initialized common event class object: addr=%p, name=\"%s\"",
92 event_class, bt_ctf_event_class_common_get_name(event_class));
93 return ret;
94
95 error:
96 ret = -1;
97 return ret;
98 }
99
100 void bt_ctf_event_class_common_freeze(struct bt_ctf_event_class_common *event_class)
101 {
102 BT_ASSERT_DBG(event_class);
103
104 if (event_class->frozen) {
105 return;
106 }
107
108 BT_LOGD("Freezing event class: addr=%p, name=\"%s\", id=%" PRId64,
109 event_class, bt_ctf_event_class_common_get_name(event_class),
110 bt_ctf_event_class_common_get_id(event_class));
111 event_class->frozen = 1;
112 BT_LOGD_STR("Freezing event class's context field type.");
113 bt_ctf_field_type_common_freeze(event_class->context_field_type);
114 BT_LOGD_STR("Freezing event class's payload field type.");
115 bt_ctf_field_type_common_freeze(event_class->payload_field_type);
116 }
117
118 int bt_ctf_event_class_common_validate_single_clock_class(
119 struct bt_ctf_event_class_common *event_class,
120 struct bt_ctf_clock_class **expected_clock_class)
121 {
122 int ret = 0;
123
124 BT_ASSERT_DBG(event_class);
125 BT_ASSERT_DBG(expected_clock_class);
126 ret = bt_ctf_field_type_common_validate_single_clock_class(
127 event_class->context_field_type,
128 expected_clock_class);
129 if (ret) {
130 BT_LOGW("Event class's context field type "
131 "is not recursively mapped to the "
132 "expected clock class: "
133 "event-class-addr=%p, "
134 "event-class-name=\"%s\", "
135 "event-class-id=%" PRId64 ", "
136 "ft-addr=%p",
137 event_class,
138 bt_ctf_event_class_common_get_name(event_class),
139 event_class->id,
140 event_class->context_field_type);
141 goto end;
142 }
143
144 ret = bt_ctf_field_type_common_validate_single_clock_class(
145 event_class->payload_field_type,
146 expected_clock_class);
147 if (ret) {
148 BT_LOGW("Event class's payload 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 ", "
154 "ft-addr=%p",
155 event_class,
156 bt_ctf_event_class_common_get_name(event_class),
157 event_class->id,
158 event_class->payload_field_type);
159 goto end;
160 }
161
162 end:
163 return ret;
164 }
165
166 static
167 void bt_ctf_event_class_destroy(struct bt_ctf_object *obj)
168 {
169 bt_ctf_event_class_common_finalize(obj);
170 g_free(obj);
171 }
172
173 BT_EXPORT
174 struct bt_ctf_event_class *bt_ctf_event_class_create(const char *name)
175 {
176 struct bt_ctf_event_class *ctf_event_class = NULL;
177 int ret;
178
179 if (!name) {
180 BT_LOGW_STR("Invalid parameter: name is NULL.");
181 goto error;
182 }
183
184 BT_LOGD("Creating event class object: name=\"%s\"",
185 name);
186 ctf_event_class = g_new0(struct bt_ctf_event_class, 1);
187 if (!ctf_event_class) {
188 BT_LOGE_STR("Failed to allocate one event class.");
189 goto error;
190 }
191
192 ret = bt_ctf_event_class_common_initialize(BT_CTF_TO_COMMON(ctf_event_class),
193 name, bt_ctf_event_class_destroy,
194 (bt_ctf_field_type_structure_create_func)
195 bt_ctf_field_type_structure_create);
196 if (ret) {
197 goto error;
198 }
199
200 goto end;
201
202 error:
203 bt_ctf_object_put_ref(ctf_event_class);
204
205 end:
206 return ctf_event_class;
207 }
208
209 BT_EXPORT
210 const char *bt_ctf_event_class_get_name(struct bt_ctf_event_class *event_class)
211 {
212 return bt_ctf_event_class_common_get_name(BT_CTF_TO_COMMON(event_class));
213 }
214
215 BT_EXPORT
216 int64_t bt_ctf_event_class_get_id(struct bt_ctf_event_class *event_class)
217 {
218 return bt_ctf_event_class_common_get_id(BT_CTF_TO_COMMON(event_class));
219 }
220
221 BT_EXPORT
222 int bt_ctf_event_class_set_id(struct bt_ctf_event_class *event_class,
223 uint64_t id)
224 {
225 return bt_ctf_event_class_common_set_id(BT_CTF_TO_COMMON(event_class), id);
226 }
227
228 BT_EXPORT
229 enum bt_ctf_event_class_log_level bt_ctf_event_class_get_log_level(
230 struct bt_ctf_event_class *event_class)
231 {
232 return bt_ctf_event_class_common_get_log_level(BT_CTF_TO_COMMON(event_class));
233 }
234
235 BT_EXPORT
236 int bt_ctf_event_class_set_log_level(struct bt_ctf_event_class *event_class,
237 enum bt_ctf_event_class_log_level log_level)
238 {
239 return bt_ctf_event_class_common_set_log_level(BT_CTF_TO_COMMON(event_class),
240 log_level);
241 }
242
243 BT_EXPORT
244 const char *bt_ctf_event_class_get_emf_uri(
245 struct bt_ctf_event_class *event_class)
246 {
247 return bt_ctf_event_class_common_get_emf_uri(BT_CTF_TO_COMMON(event_class));
248 }
249
250 BT_EXPORT
251 int bt_ctf_event_class_set_emf_uri(struct bt_ctf_event_class *event_class,
252 const char *emf_uri)
253 {
254 return bt_ctf_event_class_common_set_emf_uri(BT_CTF_TO_COMMON(event_class),
255 emf_uri);
256 }
257
258 BT_EXPORT
259 struct bt_ctf_stream_class *bt_ctf_event_class_get_stream_class(
260 struct bt_ctf_event_class *event_class)
261 {
262 BT_CTF_ASSERT_PRE_NON_NULL(event_class, "Event class");
263 return bt_ctf_object_get_ref(bt_ctf_event_class_common_borrow_stream_class(
264 BT_CTF_TO_COMMON(event_class)));
265 }
266
267 BT_EXPORT
268 struct bt_ctf_field_type *bt_ctf_event_class_get_payload_field_type(
269 struct bt_ctf_event_class *event_class)
270 {
271 return bt_ctf_object_get_ref(bt_ctf_event_class_common_borrow_payload_field_type(
272 BT_CTF_TO_COMMON(event_class)));
273 }
274
275 BT_EXPORT
276 int bt_ctf_event_class_set_payload_field_type(
277 struct bt_ctf_event_class *event_class,
278 struct bt_ctf_field_type *field_type)
279 {
280 return bt_ctf_event_class_common_set_payload_field_type(
281 BT_CTF_TO_COMMON(event_class), (void *) field_type);
282 }
283
284 BT_EXPORT
285 struct bt_ctf_field_type *bt_ctf_event_class_get_context_field_type(
286 struct bt_ctf_event_class *event_class)
287 {
288 return bt_ctf_object_get_ref(bt_ctf_event_class_common_borrow_context_field_type(
289 BT_CTF_TO_COMMON(event_class)));
290 }
291
292 BT_EXPORT
293 int bt_ctf_event_class_set_context_field_type(
294 struct bt_ctf_event_class *event_class,
295 struct bt_ctf_field_type *field_type)
296 {
297 return bt_ctf_event_class_common_set_context_field_type(
298 BT_CTF_TO_COMMON(event_class), (void *) field_type);
299 }
300
301 BT_EXPORT
302 int bt_ctf_event_class_add_field(struct bt_ctf_event_class *event_class,
303 struct bt_ctf_field_type *type,
304 const char *name)
305 {
306 int ret = 0;
307
308 if (!event_class || !type) {
309 BT_LOGW("Invalid parameter: event class or field type is NULL: "
310 "event-class-addr=%p, field-type-addr=%p",
311 event_class, type);
312 ret = -1;
313 goto end;
314 }
315
316 if (!bt_ctf_identifier_is_valid(name)) {
317 BT_LOGW("Invalid parameter: event class's payload field type's field name is not a valid CTF identifier: "
318 "addr=%p, name=\"%s\", id=%" PRId64 ", field-name=\"%s\"",
319 event_class, bt_ctf_event_class_get_name(event_class),
320 bt_ctf_event_class_get_id(event_class),
321 name);
322 ret = -1;
323 goto end;
324 }
325
326 if (event_class->common.frozen) {
327 BT_LOGW("Invalid parameter: event class is frozen: "
328 "addr=%p, name=\"%s\", id=%" PRId64,
329 event_class, bt_ctf_event_class_get_name(event_class),
330 bt_ctf_event_class_get_id(event_class));
331 ret = -1;
332 goto end;
333 }
334
335 if (!event_class->common.payload_field_type) {
336 BT_LOGW("Event class has no payload field type: "
337 "addr=%p, name=\"%s\", id=%" PRId64,
338 event_class, bt_ctf_event_class_get_name(event_class),
339 bt_ctf_event_class_get_id(event_class));
340 ret = -1;
341 goto end;
342 }
343
344 BT_ASSERT_DBG(bt_ctf_field_type_common_get_type_id(
345 event_class->common.payload_field_type) ==
346 BT_CTF_FIELD_TYPE_ID_STRUCT);
347 ret = bt_ctf_field_type_structure_add_field(
348 (void *) event_class->common.payload_field_type,
349 (void *) type, name);
350 BT_LOGT("Added field to event class's payload field type: "
351 "event-class-addr=%p, event-class-name=\"%s\", "
352 "event-class-id=%" PRId64 ", field-name=\"%s\", ft-addr=%p",
353 event_class, bt_ctf_event_class_get_name(event_class),
354 bt_ctf_event_class_get_id(event_class), name, type);
355 end:
356 return ret;
357 }
358
359 BT_EXPORT
360 int64_t bt_ctf_event_class_get_payload_type_field_count(
361 struct bt_ctf_event_class *event_class)
362 {
363 int64_t ret;
364
365 if (!event_class) {
366 BT_LOGW_STR("Invalid parameter: event class is NULL.");
367 ret = (int64_t) -1;
368 goto end;
369 }
370
371 if (!event_class->common.payload_field_type) {
372 BT_LOGT("Event class has no payload field type: "
373 "addr=%p, name=\"%s\", id=%" PRId64,
374 event_class, bt_ctf_event_class_get_name(event_class),
375 bt_ctf_event_class_get_id(event_class));
376 ret = (int64_t) -1;
377 goto end;
378 }
379
380 BT_ASSERT_DBG(bt_ctf_field_type_common_get_type_id(
381 event_class->common.payload_field_type) ==
382 BT_CTF_FIELD_TYPE_ID_STRUCT);
383 ret = bt_ctf_field_type_common_structure_get_field_count(
384 event_class->common.payload_field_type);
385 end:
386 return ret;
387 }
388
389 BT_EXPORT
390 int bt_ctf_event_class_get_payload_type_field_by_index(
391 struct bt_ctf_event_class *event_class,
392 const char **field_name, struct bt_ctf_field_type **field_type,
393 uint64_t index)
394 {
395 int ret;
396
397 if (!event_class) {
398 BT_LOGW_STR("Invalid parameter: event class is NULL.");
399 ret = -1;
400 goto end;
401 }
402
403 if (!event_class->common.payload_field_type) {
404 BT_LOGT("Event class has no payload field type: "
405 "addr=%p, name=\"%s\", id=%" PRId64 ", index=%" PRIu64,
406 event_class, bt_ctf_event_class_get_name(event_class),
407 bt_ctf_event_class_get_id(event_class), index);
408 ret = -1;
409 goto end;
410 }
411
412 BT_ASSERT_DBG(bt_ctf_field_type_common_get_type_id(
413 event_class->common.payload_field_type) ==
414 BT_CTF_FIELD_TYPE_ID_STRUCT);
415 ret = bt_ctf_field_type_structure_get_field_by_index(
416 (void *) event_class->common.payload_field_type,
417 field_name, (void *) field_type, index);
418
419 end:
420 return ret;
421 }
422
423 BT_EXPORT
424 struct bt_ctf_field_type *
425 bt_ctf_event_class_get_payload_type_field_type_by_name(
426 struct bt_ctf_event_class *event_class, const char *name)
427 {
428 GQuark name_quark;
429 struct bt_ctf_field_type *field_type = NULL;
430
431 if (!event_class || !name) {
432 BT_LOGW("Invalid parameter: event class or name is NULL: "
433 "event-class-addr=%p, name-addr=%p",
434 event_class, name);
435 goto end;
436 }
437
438 if (!event_class->common.payload_field_type) {
439 BT_LOGT("Event class has no payload field type: "
440 "addr=%p, name=\"%s\", id=%" PRId64,
441 event_class, bt_ctf_event_class_get_name(event_class),
442 bt_ctf_event_class_get_id(event_class));
443 goto end;
444 }
445
446 BT_ASSERT_DBG(bt_ctf_field_type_common_get_type_id(
447 event_class->common.payload_field_type) ==
448 BT_CTF_FIELD_TYPE_ID_STRUCT);
449 name_quark = g_quark_try_string(name);
450 if (!name_quark) {
451 BT_LOGE("Cannot get GQuark: string=\"%s\"", name);
452 goto end;
453 }
454
455 /*
456 * No need to increment field_type's reference count since getting it
457 * from the structure already does.
458 */
459 field_type = (void *)
460 bt_ctf_field_type_structure_get_field_type_by_name(
461 (void *) event_class->common.payload_field_type, name);
462
463 end:
464 return field_type;
465 }
466
467 int bt_ctf_event_class_serialize(struct bt_ctf_event_class *event_class,
468 struct metadata_context *context)
469 {
470 int ret = 0;
471 struct bt_ctf_value *attr_value = NULL;
472
473 BT_ASSERT_DBG(event_class);
474 BT_ASSERT_DBG(context);
475 BT_LOGD("Serializing event class's metadata: "
476 "event-class-addr=%p, event-class-name=\"%s\", "
477 "event-class-id=%" PRId64 ", metadata-context-addr=%p",
478 event_class, bt_ctf_event_class_get_name(event_class),
479 bt_ctf_event_class_get_id(event_class), context);
480 context->current_indentation_level = 1;
481 g_string_assign(context->field_name, "");
482 g_string_append(context->string, "event {\n");
483
484 /* Serialize attributes */
485 g_string_append_printf(context->string, "\tname = \"%s\";\n",
486 event_class->common.name->str);
487 BT_ASSERT_DBG(event_class->common.id >= 0);
488 g_string_append_printf(context->string, "\tid = %" PRId64 ";\n",
489 event_class->common.id);
490 g_string_append_printf(context->string, "\tstream_id = %" PRId64 ";\n",
491 bt_ctf_stream_class_common_get_id(
492 bt_ctf_event_class_common_borrow_stream_class(
493 BT_CTF_TO_COMMON(event_class))));
494
495 if (event_class->common.log_level !=
496 BT_CTF_EVENT_CLASS_LOG_LEVEL_UNSPECIFIED) {
497 g_string_append_printf(context->string, "\tloglevel = %d;\n",
498 (int) event_class->common.log_level);
499 }
500
501 if (event_class->common.emf_uri->len > 0) {
502 g_string_append_printf(context->string, "\tmodel.emf.uri = \"%s\";\n",
503 event_class->common.emf_uri->str);
504 }
505
506 /* Serialize context field type */
507 if (event_class->common.context_field_type) {
508 g_string_append(context->string, "\tcontext := ");
509 BT_LOGD_STR("Serializing event class's context field type metadata.");
510 ret = bt_ctf_field_type_serialize_recursive(
511 (void *) event_class->common.context_field_type,
512 context);
513 if (ret) {
514 BT_LOGW("Cannot serialize event class's context field type's metadata: "
515 "ret=%d", ret);
516 goto end;
517 }
518 g_string_append(context->string, ";\n");
519 }
520
521 /* Serialize payload field type */
522 if (event_class->common.payload_field_type) {
523 g_string_append(context->string, "\tfields := ");
524 BT_LOGD_STR("Serializing event class's payload field type metadata.");
525 ret = bt_ctf_field_type_serialize_recursive(
526 (void *) event_class->common.payload_field_type,
527 context);
528 if (ret) {
529 BT_LOGW("Cannot serialize event class's payload field type's metadata: "
530 "ret=%d", ret);
531 goto end;
532 }
533 g_string_append(context->string, ";\n");
534 }
535
536 g_string_append(context->string, "};\n\n");
537
538 end:
539 context->current_indentation_level = 0;
540 BT_CTF_OBJECT_PUT_REF_AND_RESET(attr_value);
541 return ret;
542 }
543
544 BT_EXPORT
545 struct bt_ctf_field_type *bt_ctf_event_class_get_field_by_name(
546 struct bt_ctf_event_class *event_class, const char *name)
547 {
548 GQuark name_quark;
549 struct bt_ctf_field_type *field_type = NULL;
550
551 if (!event_class || !name) {
552 BT_LOGW("Invalid parameter: event class or name is NULL: "
553 "event-class-addr=%p, name-addr=%p",
554 event_class, name);
555 goto end;
556 }
557
558 if (!event_class->common.payload_field_type) {
559 BT_LOGT("Event class has no payload field type: "
560 "addr=%p, name=\"%s\", id=%" PRId64,
561 event_class,
562 bt_ctf_event_class_get_name(event_class),
563 bt_ctf_event_class_get_id(event_class));
564 goto end;
565 }
566
567 BT_ASSERT_DBG(event_class->common.payload_field_type->id ==
568 BT_CTF_FIELD_TYPE_ID_STRUCT);
569 name_quark = g_quark_try_string(name);
570 if (!name_quark) {
571 BT_LOGE("Cannot get GQuark: string=\"%s\"", name);
572 goto end;
573 }
574
575 /*
576 * No need to increment field_type's reference count since getting it
577 * from the structure already does.
578 */
579 field_type = bt_ctf_object_get_ref(
580 bt_ctf_field_type_common_structure_borrow_field_type_by_name(
581 event_class->common.payload_field_type, name));
582
583 end:
584 return field_type;
585 }
This page took 0.040882 seconds and 4 git commands to generate.