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