Fix: Field types native byte order refers to the trace
[babeltrace.git] / formats / ctf / ir / event.c
1 /*
2 * event.c
3 *
4 * Babeltrace CTF IR - Event
5 *
6 * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
7 *
8 * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
9 *
10 * Permission is hereby granted, free of charge, to any person obtaining a copy
11 * of this software and associated documentation files (the "Software"), to deal
12 * in the Software without restriction, including without limitation the rights
13 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 * copies of the Software, and to permit persons to whom the Software is
15 * furnished to do so, subject to the following conditions:
16 *
17 * The above copyright notice and this permission notice shall be included in
18 * all copies or substantial portions of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 * SOFTWARE.
27 */
28
29 #include <babeltrace/ctf-writer/event.h>
30 #include <babeltrace/ctf-writer/event-types.h>
31 #include <babeltrace/ctf-writer/event-fields.h>
32 #include <babeltrace/ctf-ir/event-fields-internal.h>
33 #include <babeltrace/ctf-ir/event-types-internal.h>
34 #include <babeltrace/ctf-ir/event-internal.h>
35 #include <babeltrace/ctf-ir/stream-class.h>
36 #include <babeltrace/ctf-ir/stream-class-internal.h>
37 #include <babeltrace/ctf-ir/trace-internal.h>
38 #include <babeltrace/ctf-ir/utils.h>
39 #include <babeltrace/compiler.h>
40
41 static
42 void bt_ctf_event_class_destroy(struct bt_ctf_ref *ref);
43 static
44 void bt_ctf_event_destroy(struct bt_ctf_ref *ref);
45
46 struct bt_ctf_event_class *bt_ctf_event_class_create(const char *name)
47 {
48 struct bt_ctf_event_class *event_class = NULL;
49
50 if (bt_ctf_validate_identifier(name)) {
51 goto end;
52 }
53
54 event_class = g_new0(struct bt_ctf_event_class, 1);
55 if (!event_class) {
56 goto end;
57 }
58
59 bt_ctf_ref_init(&event_class->ref_count);
60 event_class->name = g_quark_from_string(name);
61 end:
62 return event_class;
63 }
64
65 const char *bt_ctf_event_class_get_name(struct bt_ctf_event_class *event_class)
66 {
67 const char *name = NULL;
68
69 if (!event_class) {
70 goto end;
71 }
72
73 name = g_quark_to_string(event_class->name);
74 end:
75 return name;
76 }
77
78 int64_t bt_ctf_event_class_get_id(struct bt_ctf_event_class *event_class)
79 {
80 int64_t ret;
81
82 if (!event_class || !event_class->id_set) {
83 ret = -1;
84 goto end;
85 }
86
87 ret = (int64_t) event_class->id;
88 end:
89 return ret;
90 }
91
92 int bt_ctf_event_class_set_id(struct bt_ctf_event_class *event_class,
93 uint32_t id)
94 {
95 int ret = 0;
96
97 if (!event_class) {
98 ret = -1;
99 goto end;
100 }
101
102 if (event_class->stream_class) {
103 /*
104 * We don't allow changing the id if the event class has already
105 * been added to a stream class.
106 */
107 ret = -1;
108 goto end;
109 }
110
111 event_class->id = id;
112 event_class->id_set = 1;
113 end:
114 return ret;
115 }
116
117 struct bt_ctf_stream_class *bt_ctf_event_class_get_stream_class(
118 struct bt_ctf_event_class *event_class)
119 {
120 struct bt_ctf_stream_class *stream_class = NULL;
121
122 if (!event_class) {
123 goto end;
124 }
125
126 stream_class = event_class->stream_class;
127 bt_ctf_stream_class_get(stream_class);
128 end:
129 return stream_class;
130 }
131
132 int bt_ctf_event_class_add_field(struct bt_ctf_event_class *event_class,
133 struct bt_ctf_field_type *type,
134 const char *name)
135 {
136 int ret = 0;
137
138 if (!event_class || !type || bt_ctf_validate_identifier(name) ||
139 event_class->frozen) {
140 ret = -1;
141 goto end;
142 }
143
144 if (!event_class->fields) {
145 event_class->fields = bt_ctf_field_type_structure_create();
146 if (!event_class->fields) {
147 ret = -1;
148 goto end;
149 }
150 }
151
152 ret = bt_ctf_field_type_structure_add_field(event_class->fields,
153 type, name);
154 end:
155 return ret;
156 }
157
158 int bt_ctf_event_class_get_field_count(
159 struct bt_ctf_event_class *event_class)
160 {
161 int ret;
162
163 if (!event_class) {
164 ret = -1;
165 goto end;
166 }
167
168 ret = bt_ctf_field_type_structure_get_field_count(event_class->fields);
169 end:
170 return ret;
171 }
172
173 int bt_ctf_event_class_get_field(struct bt_ctf_event_class *event_class,
174 const char **field_name, struct bt_ctf_field_type **field_type,
175 int index)
176 {
177 int ret;
178
179 if (!event_class || index < 0) {
180 ret = -1;
181 goto end;
182 }
183
184 ret = bt_ctf_field_type_structure_get_field(event_class->fields,
185 field_name, field_type, index);
186 end:
187 return ret;
188 }
189
190 struct bt_ctf_field_type *bt_ctf_event_class_get_field_by_name(
191 struct bt_ctf_event_class *event_class, const char *name)
192 {
193 GQuark name_quark;
194 struct bt_ctf_field_type *field_type = NULL;
195
196 if (!event_class || !name) {
197 goto end;
198 }
199
200 name_quark = g_quark_try_string(name);
201 if (!name_quark) {
202 goto end;
203 }
204
205 /*
206 * No need to increment field_type's reference count since getting it
207 * from the structure already does.
208 */
209 field_type = bt_ctf_field_type_structure_get_field_type_by_name(
210 event_class->fields, name);
211 end:
212 return field_type;
213 }
214
215 struct bt_ctf_field_type *bt_ctf_event_class_get_context_type(
216 struct bt_ctf_event_class *event_class)
217 {
218 struct bt_ctf_field_type *context_type = NULL;
219
220 if (!event_class || !event_class->context) {
221 goto end;
222 }
223
224 bt_ctf_field_type_get(event_class->context);
225 context_type = event_class->context;
226 end:
227 return context_type;
228 }
229
230 int bt_ctf_event_class_set_context_type(
231 struct bt_ctf_event_class *event_class,
232 struct bt_ctf_field_type *context)
233 {
234 int ret = 0;
235
236 if (!event_class || !context || event_class->frozen) {
237 ret = -1;
238 goto end;
239 }
240
241 if (bt_ctf_field_type_get_type_id(context) != CTF_TYPE_STRUCT) {
242 ret = -1;
243 goto end;
244 }
245
246 bt_ctf_field_type_get(context);
247 bt_ctf_field_type_put(event_class->context);
248 event_class->context = context;
249 end:
250 return ret;
251
252 }
253
254 void bt_ctf_event_class_get(struct bt_ctf_event_class *event_class)
255 {
256 if (!event_class) {
257 return;
258 }
259
260 bt_ctf_ref_get(&event_class->ref_count);
261 }
262
263 void bt_ctf_event_class_put(struct bt_ctf_event_class *event_class)
264 {
265 if (!event_class) {
266 return;
267 }
268
269 bt_ctf_ref_put(&event_class->ref_count, bt_ctf_event_class_destroy);
270 }
271
272 struct bt_ctf_event *bt_ctf_event_create(struct bt_ctf_event_class *event_class)
273 {
274 struct bt_ctf_event *event = NULL;
275
276 if (!event_class) {
277 goto end;
278 }
279
280 event = g_new0(struct bt_ctf_event, 1);
281 if (!event) {
282 goto end;
283 }
284
285 bt_ctf_ref_init(&event->ref_count);
286 bt_ctf_event_class_get(event_class);
287 bt_ctf_event_class_freeze(event_class);
288 event->event_class = event_class;
289 if (event_class->context) {
290 event->context_payload = bt_ctf_field_create(
291 event_class->context);
292 }
293 event->fields_payload = bt_ctf_field_create(event_class->fields);
294 end:
295 return event;
296 }
297
298 struct bt_ctf_event_class *bt_ctf_event_get_class(struct bt_ctf_event *event)
299 {
300 struct bt_ctf_event_class *event_class = NULL;
301
302 if (!event) {
303 goto end;
304 }
305
306 event_class = event->event_class;
307 bt_ctf_event_class_get(event_class);
308 end:
309 return event_class;
310 }
311
312 struct bt_ctf_clock *bt_ctf_event_get_clock(struct bt_ctf_event *event)
313 {
314 struct bt_ctf_clock *clock = NULL;
315 struct bt_ctf_event_class *event_class;
316 struct bt_ctf_stream_class *stream_class;
317
318 if (!event) {
319 goto end;
320 }
321
322 event_class = bt_ctf_event_get_class(event);
323 if (!event_class) {
324 goto end;
325 }
326
327 stream_class = bt_ctf_event_class_get_stream_class(event_class);
328 if (!stream_class) {
329 goto error_put_event_class;
330 }
331
332 clock = bt_ctf_stream_class_get_clock(stream_class);
333 if (!clock) {
334 goto error_put_stream_class;
335 }
336
337 error_put_stream_class:
338 bt_ctf_stream_class_put(stream_class);
339 error_put_event_class:
340 bt_ctf_event_class_put(event_class);
341 end:
342 return clock;
343 }
344
345 int bt_ctf_event_set_payload(struct bt_ctf_event *event,
346 const char *name,
347 struct bt_ctf_field *value)
348 {
349 int ret = 0;
350
351 if (!event || !value || bt_ctf_validate_identifier(name)) {
352 ret = -1;
353 goto end;
354 }
355
356 ret = bt_ctf_field_structure_set_field(event->fields_payload,
357 name, value);
358 end:
359 return ret;
360 }
361
362
363 struct bt_ctf_field *bt_ctf_event_get_payload(struct bt_ctf_event *event,
364 const char *name)
365 {
366 struct bt_ctf_field *field = NULL;
367
368 if (!event || !name) {
369 goto end;
370 }
371
372 field = bt_ctf_field_structure_get_field(event->fields_payload, name);
373 end:
374 return field;
375 }
376
377 struct bt_ctf_field *bt_ctf_event_get_payload_by_index(
378 struct bt_ctf_event *event, int index)
379 {
380 struct bt_ctf_field *field = NULL;
381
382 if (!event || index < 0) {
383 goto end;
384 }
385
386 field = bt_ctf_field_structure_get_field_by_index(event->fields_payload,
387 index);
388 end:
389 return field;
390 }
391
392 struct bt_ctf_field *bt_ctf_event_get_event_context(
393 struct bt_ctf_event *event)
394 {
395 struct bt_ctf_field *context = NULL;
396
397 if (!event || !event->context_payload) {
398 goto end;
399 }
400
401 context = event->context_payload;
402 bt_ctf_field_get(context);
403 end:
404 return context;
405 }
406
407 int bt_ctf_event_set_event_context(struct bt_ctf_event *event,
408 struct bt_ctf_field *context)
409 {
410 int ret = 0;
411 struct bt_ctf_field_type *field_type = NULL;
412
413 if (!event || !context) {
414 ret = -1;
415 goto end;
416 }
417
418 field_type = bt_ctf_field_get_type(context);
419 if (field_type != event->event_class->context) {
420 ret = -1;
421 goto end;
422 }
423
424 bt_ctf_field_get(context);
425 bt_ctf_field_put(event->context_payload);
426 event->context_payload = context;
427 end:
428 if (field_type) {
429 bt_ctf_field_type_put(field_type);
430 }
431 return ret;
432 }
433
434 void bt_ctf_event_get(struct bt_ctf_event *event)
435 {
436 if (!event) {
437 return;
438 }
439
440 bt_ctf_ref_get(&event->ref_count);
441 }
442
443 void bt_ctf_event_put(struct bt_ctf_event *event)
444 {
445 if (!event) {
446 return;
447 }
448
449 bt_ctf_ref_put(&event->ref_count, bt_ctf_event_destroy);
450 }
451
452 static
453 void bt_ctf_event_class_destroy(struct bt_ctf_ref *ref)
454 {
455 struct bt_ctf_event_class *event_class;
456
457 if (!ref) {
458 return;
459 }
460
461 /*
462 * Don't call put() on the stream class. See comment in
463 * bt_ctf_event_class_set_stream_class for explanation.
464 */
465 event_class = container_of(ref, struct bt_ctf_event_class, ref_count);
466 if (event_class->context) {
467 bt_ctf_field_type_put(event_class->context);
468 }
469 if (event_class->fields) {
470 bt_ctf_field_type_put(event_class->fields);
471 }
472 g_free(event_class);
473 }
474
475 static
476 void bt_ctf_event_destroy(struct bt_ctf_ref *ref)
477 {
478 struct bt_ctf_event *event;
479
480 if (!ref) {
481 return;
482 }
483
484 event = container_of(ref, struct bt_ctf_event,
485 ref_count);
486 if (event->event_class) {
487 bt_ctf_event_class_put(event->event_class);
488 }
489 if (event->context_payload) {
490 bt_ctf_field_put(event->context_payload);
491 }
492 if (event->fields_payload) {
493 bt_ctf_field_put(event->fields_payload);
494 }
495 g_free(event);
496 }
497
498 BT_HIDDEN
499 void bt_ctf_event_class_freeze(struct bt_ctf_event_class *event_class)
500 {
501 assert(event_class);
502 event_class->frozen = 1;
503 bt_ctf_field_type_freeze(event_class->context);
504 bt_ctf_field_type_freeze(event_class->fields);
505 }
506
507 BT_HIDDEN
508 int bt_ctf_event_class_set_stream_class(struct bt_ctf_event_class *event_class,
509 struct bt_ctf_stream_class *stream_class)
510 {
511 int ret = 0;
512
513 if (!event_class) {
514 ret = -1;
515 goto end;
516 }
517
518 /* Allow a NULL stream_class to unset the current stream_class */
519 if (stream_class && event_class->stream_class) {
520 ret = -1;
521 goto end;
522 }
523
524 event_class->stream_class = stream_class;
525 /*
526 * We don't get() the stream_class since doing so would introduce
527 * a circular ownership between event classes and stream classes.
528 *
529 * A stream class will always unset itself from its events before
530 * being destroyed. This ensures that a user won't get a pointer
531 * to a stale stream class instance from an event class.
532 */
533 end:
534 return ret;
535 }
536
537 BT_HIDDEN
538 int bt_ctf_event_class_serialize(struct bt_ctf_event_class *event_class,
539 struct metadata_context *context)
540 {
541 int ret = 0;
542 int64_t stream_id;
543
544 assert(event_class);
545 assert(context);
546 stream_id = bt_ctf_stream_class_get_id(event_class->stream_class);
547 if (stream_id < 0) {
548 ret = -1;
549 goto end;
550 }
551
552 context->current_indentation_level = 1;
553 g_string_assign(context->field_name, "");
554 g_string_append_printf(context->string, "event {\n\tname = \"%s\";\n\tid = %u;\n\tstream_id = %" PRId64 ";\n",
555 g_quark_to_string(event_class->name),
556 event_class->id,
557 stream_id);
558
559 if (event_class->context) {
560 g_string_append(context->string, "\tcontext := ");
561 ret = bt_ctf_field_type_serialize(event_class->context,
562 context);
563 if (ret) {
564 goto end;
565 }
566 g_string_append(context->string, ";\n");
567 }
568
569 if (event_class->fields) {
570 g_string_append(context->string, "\tfields := ");
571 ret = bt_ctf_field_type_serialize(event_class->fields, context);
572 if (ret) {
573 goto end;
574 }
575 g_string_append(context->string, ";\n");
576 }
577
578 g_string_append(context->string, "};\n\n");
579 end:
580 context->current_indentation_level = 0;
581 return ret;
582 }
583
584 void bt_ctf_event_class_set_native_byte_order(
585 struct bt_ctf_event_class *event_class,
586 int byte_order)
587 {
588 if (!event_class) {
589 return;
590 }
591
592 bt_ctf_field_type_set_native_byte_order(event_class->context,
593 byte_order);
594 bt_ctf_field_type_set_native_byte_order(event_class->fields,
595 byte_order);
596 }
597
598 BT_HIDDEN
599 int bt_ctf_event_validate(struct bt_ctf_event *event)
600 {
601 /* Make sure each field's payload has been set */
602 int ret;
603
604 assert(event);
605 ret = bt_ctf_field_validate(event->fields_payload);
606 if (ret) {
607 goto end;
608 }
609
610 if (event->event_class->context) {
611 ret = bt_ctf_field_validate(event->context_payload);
612 }
613 end:
614 return ret;
615 }
616
617 BT_HIDDEN
618 int bt_ctf_event_serialize(struct bt_ctf_event *event,
619 struct ctf_stream_pos *pos)
620 {
621 int ret = 0;
622
623 assert(event);
624 assert(pos);
625 if (event->context_payload) {
626 ret = bt_ctf_field_serialize(event->context_payload, pos);
627 if (ret) {
628 goto end;
629 }
630 }
631
632 if (event->fields_payload) {
633 ret = bt_ctf_field_serialize(event->fields_payload, pos);
634 if (ret) {
635 goto end;
636 }
637 }
638 end:
639 return ret;
640 }
641
642 BT_HIDDEN
643 int bt_ctf_event_set_timestamp(struct bt_ctf_event *event,
644 uint64_t timestamp)
645 {
646 int ret = 0;
647
648 assert(event);
649 if (event->timestamp) {
650 ret = -1;
651 goto end;
652 }
653
654 event->timestamp = timestamp;
655 end:
656 return ret;
657 }
658
659 BT_HIDDEN
660 uint64_t bt_ctf_event_get_timestamp(struct bt_ctf_event *event)
661 {
662 assert(event);
663 return event->timestamp;
664 }
This page took 0.043686 seconds and 5 git commands to generate.