47bcd2aba8af08f91984ed5eb769981c44e742d8
[babeltrace.git] / lib / 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 <babeltrace/lib-logging-internal.h>
26
27 #include <babeltrace/assert-pre-internal.h>
28 #include <babeltrace/assert-internal.h>
29 #include <babeltrace/compiler-internal.h>
30 #include <babeltrace/ctf-writer/attributes-internal.h>
31 #include <babeltrace/ctf-writer/event-class-internal.h>
32 #include <babeltrace/ctf-writer/event-internal.h>
33 #include <babeltrace/ctf-writer/event.h>
34 #include <babeltrace/ctf-writer/field-types-internal.h>
35 #include <babeltrace/ctf-writer/field-types.h>
36 #include <babeltrace/ctf-writer/fields-internal.h>
37 #include <babeltrace/ctf-writer/stream-class-internal.h>
38 #include <babeltrace/ctf-writer/stream-class.h>
39 #include <babeltrace/ctf-writer/trace-internal.h>
40 #include <babeltrace/ctf-writer/utils-internal.h>
41 #include <babeltrace/ctf-writer/utils.h>
42 #include <babeltrace/ctf-writer/validation-internal.h>
43 #include <babeltrace/ctf-writer/writer-internal.h>
44 #include <babeltrace/endian-internal.h>
45 #include <babeltrace/ctf-writer/object.h>
46 #include <babeltrace/types.h>
47 #include <babeltrace/ctf-writer/values-internal.h>
48 #include <glib.h>
49 #include <inttypes.h>
50 #include <inttypes.h>
51 #include <stdlib.h>
52
53 BT_HIDDEN
54 void bt_ctf_event_class_common_finalize(struct bt_ctf_object *obj)
55 {
56 struct bt_ctf_event_class_common *event_class;
57
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));
62
63 if (event_class->name) {
64 g_string_free(event_class->name, TRUE);
65 }
66
67 if (event_class->emf_uri) {
68 g_string_free(event_class->emf_uri, TRUE);
69 }
70
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);
75 }
76
77 BT_HIDDEN
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)
81 {
82 int ret = 0;
83
84 BT_LOGD("Initializing common event class object: name=\"%s\"",
85 name);
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.");
90 goto error;
91 }
92
93 event_class->id = -1;
94 event_class->name = g_string_new(name);
95 if (!event_class->name) {
96 BT_LOGE_STR("Failed to allocate a GString.");
97 goto error;
98 }
99
100 event_class->emf_uri = g_string_new(NULL);
101 if (!event_class->emf_uri) {
102 BT_LOGE_STR("Failed to allocate a GString.");
103 goto error;
104 }
105
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));
109 return ret;
110
111 error:
112 ret = -1;
113 return ret;
114 }
115
116 BT_HIDDEN
117 void bt_ctf_event_class_common_freeze(struct bt_ctf_event_class_common *event_class)
118 {
119 BT_ASSERT(event_class);
120
121 if (event_class->frozen) {
122 return;
123 }
124
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);
133 }
134
135 BT_HIDDEN
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)
139 {
140 int ret = 0;
141
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);
147 if (ret) {
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 ", "
154 "ft-addr=%p",
155 event_class,
156 bt_ctf_event_class_common_get_name(event_class),
157 event_class->id,
158 event_class->context_field_type);
159 goto end;
160 }
161
162 ret = bt_ctf_field_type_common_validate_single_clock_class(
163 event_class->payload_field_type,
164 expected_clock_class);
165 if (ret) {
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 ", "
172 "ft-addr=%p",
173 event_class,
174 bt_ctf_event_class_common_get_name(event_class),
175 event_class->id,
176 event_class->payload_field_type);
177 goto end;
178 }
179
180 end:
181 return ret;
182 }
183
184 static
185 void bt_ctf_event_class_destroy(struct bt_ctf_object *obj)
186 {
187 bt_ctf_event_class_common_finalize(obj);
188 g_free(obj);
189 }
190
191 struct bt_ctf_event_class *bt_ctf_event_class_create(const char *name)
192 {
193 struct bt_ctf_event_class *ctf_event_class = NULL;
194 int ret;
195
196 if (!name) {
197 BT_LOGW_STR("Invalid parameter: name is NULL.");
198 goto error;
199 }
200
201 BT_LOGD("Creating event class object: name=\"%s\"",
202 name);
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.");
206 goto error;
207 }
208
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);
213 if (ret) {
214 goto error;
215 }
216
217 goto end;
218
219 error:
220 bt_ctf_object_put_ref(ctf_event_class);
221
222 end:
223 return ctf_event_class;
224 }
225
226 const char *bt_ctf_event_class_get_name(struct bt_ctf_event_class *event_class)
227 {
228 return bt_ctf_event_class_common_get_name(BT_CTF_TO_COMMON(event_class));
229 }
230
231 int64_t bt_ctf_event_class_get_id(struct bt_ctf_event_class *event_class)
232 {
233 return bt_ctf_event_class_common_get_id(BT_CTF_TO_COMMON(event_class));
234 }
235
236 int bt_ctf_event_class_set_id(struct bt_ctf_event_class *event_class,
237 uint64_t id)
238 {
239 return bt_ctf_event_class_common_set_id(BT_CTF_TO_COMMON(event_class), id);
240 }
241
242 enum bt_ctf_event_class_log_level bt_ctf_event_class_get_log_level(
243 struct bt_ctf_event_class *event_class)
244 {
245 return bt_ctf_event_class_common_get_log_level(BT_CTF_TO_COMMON(event_class));
246 }
247
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)
250 {
251 return bt_ctf_event_class_common_set_log_level(BT_CTF_TO_COMMON(event_class),
252 log_level);
253 }
254
255 const char *bt_ctf_event_class_get_emf_uri(
256 struct bt_ctf_event_class *event_class)
257 {
258 return bt_ctf_event_class_common_get_emf_uri(BT_CTF_TO_COMMON(event_class));
259 }
260
261 int bt_ctf_event_class_set_emf_uri(struct bt_ctf_event_class *event_class,
262 const char *emf_uri)
263 {
264 return bt_ctf_event_class_common_set_emf_uri(BT_CTF_TO_COMMON(event_class),
265 emf_uri);
266 }
267
268 struct bt_ctf_stream_class *bt_ctf_event_class_get_stream_class(
269 struct bt_ctf_event_class *event_class)
270 {
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)));
274 }
275
276 struct bt_ctf_field_type *bt_ctf_event_class_get_payload_field_type(
277 struct bt_ctf_event_class *event_class)
278 {
279 return bt_ctf_object_get_ref(bt_ctf_event_class_common_borrow_payload_field_type(
280 BT_CTF_TO_COMMON(event_class)));
281 }
282
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)
286 {
287 return bt_ctf_event_class_common_set_payload_field_type(
288 BT_CTF_TO_COMMON(event_class), (void *) field_type);
289 }
290
291 struct bt_ctf_field_type *bt_ctf_event_class_get_context_field_type(
292 struct bt_ctf_event_class *event_class)
293 {
294 return bt_ctf_object_get_ref(bt_ctf_event_class_common_borrow_context_field_type(
295 BT_CTF_TO_COMMON(event_class)));
296 }
297
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)
301 {
302 return bt_ctf_event_class_common_set_context_field_type(
303 BT_CTF_TO_COMMON(event_class), (void *) field_type);
304 }
305
306 int bt_ctf_event_class_add_field(struct bt_ctf_event_class *event_class,
307 struct bt_ctf_field_type *type,
308 const char *name)
309 {
310 int ret = 0;
311
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",
315 event_class, type);
316 ret = -1;
317 goto end;
318 }
319
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),
325 name);
326 ret = -1;
327 goto end;
328 }
329
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));
335 ret = -1;
336 goto end;
337 }
338
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));
344 ret = -1;
345 goto end;
346 }
347
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);
359 end:
360 return ret;
361 }
362
363 int64_t bt_ctf_event_class_get_payload_type_field_count(
364 struct bt_ctf_event_class *event_class)
365 {
366 int64_t ret;
367
368 if (!event_class) {
369 BT_LOGW_STR("Invalid parameter: event class is NULL.");
370 ret = (int64_t) -1;
371 goto end;
372 }
373
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));
379 ret = (int64_t) -1;
380 goto end;
381 }
382
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);
388 end:
389 return ret;
390 }
391
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,
395 uint64_t index)
396 {
397 int ret;
398
399 if (!event_class) {
400 BT_LOGW_STR("Invalid parameter: event class is NULL.");
401 ret = -1;
402 goto end;
403 }
404
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);
410 ret = -1;
411 goto end;
412 }
413
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);
420
421 end:
422 return ret;
423 }
424
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)
428 {
429 GQuark name_quark;
430 struct bt_ctf_field_type *field_type = NULL;
431
432 if (!event_class || !name) {
433 BT_LOGW("Invalid parameter: event class or name is NULL: "
434 "event-class-addr=%p, name-addr=%p",
435 event_class, name);
436 goto end;
437 }
438
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));
444 goto end;
445 }
446
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);
451 if (!name_quark) {
452 BT_LOGE("Cannot get GQuark: string=\"%s\"", name);
453 goto end;
454 }
455
456 /*
457 * No need to increment field_type's reference count since getting it
458 * from the structure already does.
459 */
460 field_type = (void *)
461 bt_ctf_field_type_structure_get_field_type_by_name(
462 (void *) event_class->common.payload_field_type, name);
463
464 end:
465 return field_type;
466 }
467
468 BT_HIDDEN
469 int bt_ctf_event_class_serialize(struct bt_ctf_event_class *event_class,
470 struct metadata_context *context)
471 {
472 int ret = 0;
473 struct bt_ctf_value *attr_value = NULL;
474
475 BT_ASSERT(event_class);
476 BT_ASSERT(context);
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");
485
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))));
496
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);
501 }
502
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);
506 }
507
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,
514 context);
515 if (ret) {
516 BT_LOGW("Cannot serialize event class's context field type's metadata: "
517 "ret=%d", ret);
518 goto end;
519 }
520 g_string_append(context->string, ";\n");
521 }
522
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,
529 context);
530 if (ret) {
531 BT_LOGW("Cannot serialize event class's payload field type's metadata: "
532 "ret=%d", ret);
533 goto end;
534 }
535 g_string_append(context->string, ";\n");
536 }
537
538 g_string_append(context->string, "};\n\n");
539
540 end:
541 context->current_indentation_level = 0;
542 BT_CTF_OBJECT_PUT_REF_AND_RESET(attr_value);
543 return ret;
544 }
545
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)
548 {
549 GQuark name_quark;
550 struct bt_ctf_field_type *field_type = NULL;
551
552 if (!event_class || !name) {
553 BT_LOGW("Invalid parameter: event class or name is NULL: "
554 "event-class-addr=%p, name-addr=%p",
555 event_class, name);
556 goto end;
557 }
558
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,
562 event_class,
563 bt_ctf_event_class_get_name(event_class),
564 bt_ctf_event_class_get_id(event_class));
565 goto end;
566 }
567
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);
571 if (!name_quark) {
572 BT_LOGE("Cannot get GQuark: string=\"%s\"", name);
573 goto end;
574 }
575
576 /*
577 * No need to increment field_type's reference count since getting it
578 * from the structure already does.
579 */
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));
583
584 end:
585 return field_type;
586 }
This page took 0.040147 seconds and 4 git commands to generate.