419707e180e97a098cfa9e60c6c4a04e8da79a1e
[babeltrace.git] / src / ctf-writer / event-class.c
1 /*
2 * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
3 * Copyright 2017-2018 Philippe Proulx <pproulx@efficios.com>
4 *
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:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
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
21 * SOFTWARE.
22 */
23
24 #define BT_LOG_TAG "CTF-WRITER-EVENT-CLASS"
25 #include "logging.h"
26
27 #include <glib.h>
28 #include <inttypes.h>
29 #include <stdlib.h>
30
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>
37
38 #include "common/assert.h"
39 #include "compat/compiler.h"
40 #include "compat/endian.h"
41
42 #include "assert-pre.h"
43 #include "attributes.h"
44 #include "event-class.h"
45 #include "event.h"
46 #include "fields.h"
47 #include "field-types.h"
48 #include "stream-class.h"
49 #include "trace.h"
50 #include "utils.h"
51 #include "validation.h"
52 #include "values.h"
53 #include "writer.h"
54
55 BT_HIDDEN
56 void bt_ctf_event_class_common_finalize(struct bt_ctf_object *obj)
57 {
58 struct bt_ctf_event_class_common *event_class;
59
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));
64
65 if (event_class->name) {
66 g_string_free(event_class->name, TRUE);
67 }
68
69 if (event_class->emf_uri) {
70 g_string_free(event_class->emf_uri, TRUE);
71 }
72
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);
77 }
78
79 BT_HIDDEN
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)
83 {
84 int ret = 0;
85
86 BT_LOGD("Initializing common event class object: name=\"%s\"",
87 name);
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.");
92 goto error;
93 }
94
95 event_class->id = -1;
96 event_class->name = g_string_new(name);
97 if (!event_class->name) {
98 BT_LOGE_STR("Failed to allocate a GString.");
99 goto error;
100 }
101
102 event_class->emf_uri = g_string_new(NULL);
103 if (!event_class->emf_uri) {
104 BT_LOGE_STR("Failed to allocate a GString.");
105 goto error;
106 }
107
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));
111 return ret;
112
113 error:
114 ret = -1;
115 return ret;
116 }
117
118 BT_HIDDEN
119 void bt_ctf_event_class_common_freeze(struct bt_ctf_event_class_common *event_class)
120 {
121 BT_ASSERT(event_class);
122
123 if (event_class->frozen) {
124 return;
125 }
126
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);
135 }
136
137 BT_HIDDEN
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)
141 {
142 int ret = 0;
143
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);
149 if (ret) {
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 ", "
156 "ft-addr=%p",
157 event_class,
158 bt_ctf_event_class_common_get_name(event_class),
159 event_class->id,
160 event_class->context_field_type);
161 goto end;
162 }
163
164 ret = bt_ctf_field_type_common_validate_single_clock_class(
165 event_class->payload_field_type,
166 expected_clock_class);
167 if (ret) {
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 ", "
174 "ft-addr=%p",
175 event_class,
176 bt_ctf_event_class_common_get_name(event_class),
177 event_class->id,
178 event_class->payload_field_type);
179 goto end;
180 }
181
182 end:
183 return ret;
184 }
185
186 static
187 void bt_ctf_event_class_destroy(struct bt_ctf_object *obj)
188 {
189 bt_ctf_event_class_common_finalize(obj);
190 g_free(obj);
191 }
192
193 struct bt_ctf_event_class *bt_ctf_event_class_create(const char *name)
194 {
195 struct bt_ctf_event_class *ctf_event_class = NULL;
196 int ret;
197
198 if (!name) {
199 BT_LOGW_STR("Invalid parameter: name is NULL.");
200 goto error;
201 }
202
203 BT_LOGD("Creating event class object: name=\"%s\"",
204 name);
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.");
208 goto error;
209 }
210
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);
215 if (ret) {
216 goto error;
217 }
218
219 goto end;
220
221 error:
222 bt_ctf_object_put_ref(ctf_event_class);
223
224 end:
225 return ctf_event_class;
226 }
227
228 const char *bt_ctf_event_class_get_name(struct bt_ctf_event_class *event_class)
229 {
230 return bt_ctf_event_class_common_get_name(BT_CTF_TO_COMMON(event_class));
231 }
232
233 int64_t bt_ctf_event_class_get_id(struct bt_ctf_event_class *event_class)
234 {
235 return bt_ctf_event_class_common_get_id(BT_CTF_TO_COMMON(event_class));
236 }
237
238 int bt_ctf_event_class_set_id(struct bt_ctf_event_class *event_class,
239 uint64_t id)
240 {
241 return bt_ctf_event_class_common_set_id(BT_CTF_TO_COMMON(event_class), id);
242 }
243
244 enum bt_ctf_event_class_log_level bt_ctf_event_class_get_log_level(
245 struct bt_ctf_event_class *event_class)
246 {
247 return bt_ctf_event_class_common_get_log_level(BT_CTF_TO_COMMON(event_class));
248 }
249
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)
252 {
253 return bt_ctf_event_class_common_set_log_level(BT_CTF_TO_COMMON(event_class),
254 log_level);
255 }
256
257 const char *bt_ctf_event_class_get_emf_uri(
258 struct bt_ctf_event_class *event_class)
259 {
260 return bt_ctf_event_class_common_get_emf_uri(BT_CTF_TO_COMMON(event_class));
261 }
262
263 int bt_ctf_event_class_set_emf_uri(struct bt_ctf_event_class *event_class,
264 const char *emf_uri)
265 {
266 return bt_ctf_event_class_common_set_emf_uri(BT_CTF_TO_COMMON(event_class),
267 emf_uri);
268 }
269
270 struct bt_ctf_stream_class *bt_ctf_event_class_get_stream_class(
271 struct bt_ctf_event_class *event_class)
272 {
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)));
276 }
277
278 struct bt_ctf_field_type *bt_ctf_event_class_get_payload_field_type(
279 struct bt_ctf_event_class *event_class)
280 {
281 return bt_ctf_object_get_ref(bt_ctf_event_class_common_borrow_payload_field_type(
282 BT_CTF_TO_COMMON(event_class)));
283 }
284
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)
288 {
289 return bt_ctf_event_class_common_set_payload_field_type(
290 BT_CTF_TO_COMMON(event_class), (void *) field_type);
291 }
292
293 struct bt_ctf_field_type *bt_ctf_event_class_get_context_field_type(
294 struct bt_ctf_event_class *event_class)
295 {
296 return bt_ctf_object_get_ref(bt_ctf_event_class_common_borrow_context_field_type(
297 BT_CTF_TO_COMMON(event_class)));
298 }
299
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)
303 {
304 return bt_ctf_event_class_common_set_context_field_type(
305 BT_CTF_TO_COMMON(event_class), (void *) field_type);
306 }
307
308 int bt_ctf_event_class_add_field(struct bt_ctf_event_class *event_class,
309 struct bt_ctf_field_type *type,
310 const char *name)
311 {
312 int ret = 0;
313
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",
317 event_class, type);
318 ret = -1;
319 goto end;
320 }
321
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),
327 name);
328 ret = -1;
329 goto end;
330 }
331
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));
337 ret = -1;
338 goto end;
339 }
340
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));
346 ret = -1;
347 goto end;
348 }
349
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);
361 end:
362 return ret;
363 }
364
365 int64_t bt_ctf_event_class_get_payload_type_field_count(
366 struct bt_ctf_event_class *event_class)
367 {
368 int64_t ret;
369
370 if (!event_class) {
371 BT_LOGW_STR("Invalid parameter: event class is NULL.");
372 ret = (int64_t) -1;
373 goto end;
374 }
375
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));
381 ret = (int64_t) -1;
382 goto end;
383 }
384
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);
390 end:
391 return ret;
392 }
393
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,
397 uint64_t index)
398 {
399 int ret;
400
401 if (!event_class) {
402 BT_LOGW_STR("Invalid parameter: event class is NULL.");
403 ret = -1;
404 goto end;
405 }
406
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);
412 ret = -1;
413 goto end;
414 }
415
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);
422
423 end:
424 return ret;
425 }
426
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)
430 {
431 GQuark name_quark;
432 struct bt_ctf_field_type *field_type = NULL;
433
434 if (!event_class || !name) {
435 BT_LOGW("Invalid parameter: event class or name is NULL: "
436 "event-class-addr=%p, name-addr=%p",
437 event_class, name);
438 goto end;
439 }
440
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));
446 goto end;
447 }
448
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);
453 if (!name_quark) {
454 BT_LOGE("Cannot get GQuark: string=\"%s\"", name);
455 goto end;
456 }
457
458 /*
459 * No need to increment field_type's reference count since getting it
460 * from the structure already does.
461 */
462 field_type = (void *)
463 bt_ctf_field_type_structure_get_field_type_by_name(
464 (void *) event_class->common.payload_field_type, name);
465
466 end:
467 return field_type;
468 }
469
470 BT_HIDDEN
471 int bt_ctf_event_class_serialize(struct bt_ctf_event_class *event_class,
472 struct metadata_context *context)
473 {
474 int ret = 0;
475 struct bt_ctf_value *attr_value = NULL;
476
477 BT_ASSERT(event_class);
478 BT_ASSERT(context);
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");
487
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))));
498
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);
503 }
504
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);
508 }
509
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,
516 context);
517 if (ret) {
518 BT_LOGW("Cannot serialize event class's context field type's metadata: "
519 "ret=%d", ret);
520 goto end;
521 }
522 g_string_append(context->string, ";\n");
523 }
524
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,
531 context);
532 if (ret) {
533 BT_LOGW("Cannot serialize event class's payload field type's metadata: "
534 "ret=%d", ret);
535 goto end;
536 }
537 g_string_append(context->string, ";\n");
538 }
539
540 g_string_append(context->string, "};\n\n");
541
542 end:
543 context->current_indentation_level = 0;
544 BT_CTF_OBJECT_PUT_REF_AND_RESET(attr_value);
545 return ret;
546 }
547
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)
550 {
551 GQuark name_quark;
552 struct bt_ctf_field_type *field_type = NULL;
553
554 if (!event_class || !name) {
555 BT_LOGW("Invalid parameter: event class or name is NULL: "
556 "event-class-addr=%p, name-addr=%p",
557 event_class, name);
558 goto end;
559 }
560
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,
564 event_class,
565 bt_ctf_event_class_get_name(event_class),
566 bt_ctf_event_class_get_id(event_class));
567 goto end;
568 }
569
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);
573 if (!name_quark) {
574 BT_LOGE("Cannot get GQuark: string=\"%s\"", name);
575 goto end;
576 }
577
578 /*
579 * No need to increment field_type's reference count since getting it
580 * from the structure already does.
581 */
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));
585
586 end:
587 return field_type;
588 }
This page took 0.039873 seconds and 3 git commands to generate.