Fix: Field types native byte order refers to the trace
[babeltrace.git] / formats / ctf / ir / stream-class.c
1 /*
2 * stream-class.c
3 *
4 * Babeltrace CTF IR - Stream Class
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/clock.h>
30 #include <babeltrace/ctf-ir/clock-internal.h>
31 #include <babeltrace/ctf-writer/event.h>
32 #include <babeltrace/ctf-ir/event-internal.h>
33 #include <babeltrace/ctf-ir/event-types-internal.h>
34 #include <babeltrace/ctf-ir/event-fields-internal.h>
35 #include <babeltrace/ctf-writer/stream.h>
36 #include <babeltrace/ctf-ir/stream-class-internal.h>
37 #include <babeltrace/ctf-writer/functor-internal.h>
38 #include <babeltrace/ctf-ir/utils.h>
39 #include <babeltrace/compiler.h>
40 #include <babeltrace/align.h>
41
42 static
43 void bt_ctf_stream_class_destroy(struct bt_ctf_ref *ref);
44 static
45 int init_event_header(struct bt_ctf_stream_class *stream_class,
46 enum bt_ctf_byte_order byte_order);
47 static
48 int init_packet_context(struct bt_ctf_stream_class *stream_class,
49 enum bt_ctf_byte_order byte_order);
50
51 struct bt_ctf_stream_class *bt_ctf_stream_class_create(const char *name)
52 {
53 int ret;
54 struct bt_ctf_stream_class *stream_class = NULL;
55
56 if (!name || !strlen(name) || bt_ctf_validate_identifier(name)) {
57 goto error;
58 }
59
60 stream_class = g_new0(struct bt_ctf_stream_class, 1);
61 if (!stream_class) {
62 goto error;
63 }
64
65 stream_class->name = g_string_new(name);
66 stream_class->event_classes = g_ptr_array_new_with_free_func(
67 (GDestroyNotify)bt_ctf_event_class_put);
68 if (!stream_class->event_classes) {
69 goto error_destroy;
70 }
71
72 ret = init_packet_context(stream_class, BT_CTF_BYTE_ORDER_NATIVE);
73 if (ret) {
74 goto error_destroy;
75 }
76
77 bt_ctf_ref_init(&stream_class->ref_count);
78 return stream_class;
79
80 error_destroy:
81 bt_ctf_stream_class_destroy(&stream_class->ref_count);
82 stream_class = NULL;
83 error:
84 return stream_class;
85 }
86
87 const char *bt_ctf_stream_class_get_name(
88 struct bt_ctf_stream_class *stream_class)
89 {
90 const char *name = NULL;
91
92 if (!stream_class) {
93 goto end;
94 }
95
96 name = stream_class->name->str;
97 end:
98 return name;
99 }
100
101 struct bt_ctf_clock *bt_ctf_stream_class_get_clock(
102 struct bt_ctf_stream_class *stream_class)
103 {
104 struct bt_ctf_clock *clock = NULL;
105
106 if (!stream_class || !stream_class->clock) {
107 goto end;
108 }
109
110 clock = stream_class->clock;
111 bt_ctf_clock_get(clock);
112 end:
113 return clock;
114 }
115
116 int bt_ctf_stream_class_set_clock(struct bt_ctf_stream_class *stream_class,
117 struct bt_ctf_clock *clock)
118 {
119 int ret = 0;
120
121 if (!stream_class || !clock || stream_class->frozen) {
122 ret = -1;
123 goto end;
124 }
125
126 if (stream_class->clock) {
127 bt_ctf_clock_put(stream_class->clock);
128 }
129
130 stream_class->clock = clock;
131 bt_ctf_clock_get(clock);
132 end:
133 return ret;
134 }
135
136 int64_t bt_ctf_stream_class_get_id(struct bt_ctf_stream_class *stream_class)
137 {
138 int64_t ret;
139
140 if (!stream_class || !stream_class->id_set) {
141 ret = -1;
142 goto end;
143 }
144
145 ret = (int64_t) stream_class->id;
146 end:
147 return ret;
148 }
149
150 int bt_ctf_stream_class_set_id(struct bt_ctf_stream_class *stream_class,
151 uint32_t id)
152 {
153 int ret = 0;
154
155 if (!stream_class || stream_class->frozen) {
156 ret = -1;
157 goto end;
158 }
159
160 stream_class->id = id;
161 stream_class->id_set = 1;
162 end:
163 return ret;
164 }
165
166 int bt_ctf_stream_class_add_event_class(
167 struct bt_ctf_stream_class *stream_class,
168 struct bt_ctf_event_class *event_class)
169 {
170 int ret = 0;
171 int64_t event_id;
172
173 if (!stream_class || !event_class) {
174 ret = -1;
175 goto end;
176 }
177
178 /* Check for duplicate event classes */
179 struct search_query query = { .value = event_class, .found = 0 };
180 g_ptr_array_foreach(stream_class->event_classes, value_exists, &query);
181 if (query.found) {
182 ret = -1;
183 goto end;
184 }
185
186 /* Only set an event id if none was explicitly set before */
187 event_id = bt_ctf_event_class_get_id(event_class);
188 if (event_id < 0) {
189 if (bt_ctf_event_class_set_id(event_class,
190 stream_class->next_event_id++)) {
191 ret = -1;
192 goto end;
193 }
194 }
195
196 ret = bt_ctf_event_class_set_stream_class(event_class, stream_class);
197 if (ret) {
198 goto end;
199 }
200
201 bt_ctf_event_class_get(event_class);
202 g_ptr_array_add(stream_class->event_classes, event_class);
203 end:
204 return ret;
205 }
206
207 int bt_ctf_stream_class_get_event_class_count(
208 struct bt_ctf_stream_class *stream_class)
209 {
210 int ret;
211
212 if (!stream_class) {
213 ret = -1;
214 goto end;
215 }
216
217 ret = (int) stream_class->event_classes->len;
218 end:
219 return ret;
220 }
221
222 struct bt_ctf_event_class *bt_ctf_stream_class_get_event_class(
223 struct bt_ctf_stream_class *stream_class, int index)
224 {
225 struct bt_ctf_event_class *event_class = NULL;
226
227 if (!stream_class || index < 0 ||
228 index >= stream_class->event_classes->len) {
229 goto end;
230 }
231
232 event_class = g_ptr_array_index(stream_class->event_classes, index);
233 bt_ctf_event_class_get(event_class);
234 end:
235 return event_class;
236 }
237
238 struct bt_ctf_event_class *bt_ctf_stream_class_get_event_class_by_name(
239 struct bt_ctf_stream_class *stream_class, const char *name)
240 {
241 size_t i;
242 GQuark name_quark;
243 struct bt_ctf_event_class *event_class = NULL;
244
245 if (!stream_class || !name) {
246 goto end;
247 }
248
249 name_quark = g_quark_try_string(name);
250 if (!name_quark) {
251 goto end;
252 }
253
254 for (i = 0; i < stream_class->event_classes->len; i++) {
255 struct bt_ctf_event_class *current_event_class =
256 g_ptr_array_index(stream_class->event_classes, i);
257
258 if (name_quark == current_event_class->name) {
259 event_class = current_event_class;
260 bt_ctf_event_class_get(event_class);
261 goto end;
262 }
263 }
264 end:
265 return event_class;
266 }
267
268 struct bt_ctf_field_type *bt_ctf_stream_class_get_packet_context_type(
269 struct bt_ctf_stream_class *stream_class)
270 {
271 struct bt_ctf_field_type *ret = NULL;
272
273 if (!stream_class) {
274 goto end;
275 }
276
277 assert(stream_class->packet_context_type);
278 bt_ctf_field_type_get(stream_class->packet_context_type);
279 ret = stream_class->packet_context_type;
280 end:
281 return ret;
282 }
283
284 int bt_ctf_stream_class_set_packet_context_type(
285 struct bt_ctf_stream_class *stream_class,
286 struct bt_ctf_field_type *packet_context_type)
287 {
288 int ret = 0;
289
290 if (!stream_class || !packet_context_type || stream_class->frozen) {
291 ret = -1;
292 goto end;
293 }
294
295 assert(stream_class->packet_context_type);
296 if (bt_ctf_field_type_get_type_id(packet_context_type) !=
297 CTF_TYPE_STRUCT) {
298 /* A packet context must be a structure */
299 ret = -1;
300 goto end;
301 }
302
303 bt_ctf_field_type_put(stream_class->packet_context_type);
304 bt_ctf_field_type_get(packet_context_type);
305 stream_class->packet_context_type = packet_context_type;
306 end:
307 return ret;
308 }
309
310 struct bt_ctf_field_type *bt_ctf_stream_class_get_event_context_type(
311 struct bt_ctf_stream_class *stream_class)
312 {
313 struct bt_ctf_field_type *ret = NULL;
314
315 if (!stream_class || !stream_class->event_context_type) {
316 goto end;
317 }
318
319 assert(stream_class->event_context_type);
320 bt_ctf_field_type_get(stream_class->event_context_type);
321 ret = stream_class->event_context_type;
322 end:
323 return ret;
324 }
325
326 int bt_ctf_stream_class_set_event_context_type(
327 struct bt_ctf_stream_class *stream_class,
328 struct bt_ctf_field_type *event_context_type)
329 {
330 int ret = 0;
331
332 if (!stream_class || !event_context_type || stream_class->frozen) {
333 ret = -1;
334 goto end;
335 }
336
337 if (bt_ctf_field_type_get_type_id(event_context_type) !=
338 CTF_TYPE_STRUCT) {
339 /* A packet context must be a structure */
340 ret = -1;
341 goto end;
342 }
343
344 bt_ctf_field_type_put(stream_class->event_context_type);
345 bt_ctf_field_type_get(event_context_type);
346 stream_class->event_context_type = event_context_type;
347 end:
348 return ret;
349 }
350
351 void bt_ctf_stream_class_get(struct bt_ctf_stream_class *stream_class)
352 {
353 if (!stream_class) {
354 return;
355 }
356
357 bt_ctf_ref_get(&stream_class->ref_count);
358 }
359
360 void bt_ctf_stream_class_put(struct bt_ctf_stream_class *stream_class)
361 {
362 if (!stream_class) {
363 return;
364 }
365
366 bt_ctf_ref_put(&stream_class->ref_count, bt_ctf_stream_class_destroy);
367 }
368
369 BT_HIDDEN
370 void bt_ctf_stream_class_freeze(struct bt_ctf_stream_class *stream_class)
371 {
372 size_t i;
373
374 if (!stream_class) {
375 return;
376 }
377
378 stream_class->frozen = 1;
379 bt_ctf_field_type_freeze(stream_class->packet_context_type);
380 bt_ctf_field_type_freeze(stream_class->event_context_type);
381 bt_ctf_clock_freeze(stream_class->clock);
382
383 bt_ctf_field_type_set_native_byte_order(
384 stream_class->event_header_type, stream_class->byte_order);
385 bt_ctf_field_type_set_native_byte_order(
386 stream_class->packet_context_type, stream_class->byte_order);
387 bt_ctf_field_type_set_native_byte_order(
388 stream_class->event_context_type, stream_class->byte_order);
389 for (i = 0; i < stream_class->event_classes->len; i++) {
390 bt_ctf_event_class_set_native_byte_order(
391 g_ptr_array_index(stream_class->event_classes, i),
392 stream_class->byte_order);
393 bt_ctf_event_class_freeze(
394 g_ptr_array_index(stream_class->event_classes, i));
395 }
396 }
397
398 BT_HIDDEN
399 int bt_ctf_stream_class_set_byte_order(struct bt_ctf_stream_class *stream_class,
400 enum bt_ctf_byte_order byte_order)
401 {
402 int ret = 0;
403 int internal_byte_order;
404
405 /* Note that "NATIVE" means the trace's endianness, not the host's. */
406 if (!stream_class || byte_order <= BT_CTF_BYTE_ORDER_UNKNOWN ||
407 byte_order > BT_CTF_BYTE_ORDER_NETWORK ||
408 stream_class->frozen) {
409 ret = -1;
410 goto end;
411 }
412
413 switch (byte_order) {
414 case BT_CTF_BYTE_ORDER_NETWORK:
415 case BT_CTF_BYTE_ORDER_BIG_ENDIAN:
416 internal_byte_order = BIG_ENDIAN;
417 break;
418 case BT_CTF_BYTE_ORDER_LITTLE_ENDIAN:
419 internal_byte_order = LITTLE_ENDIAN;
420 break;
421 default:
422 ret = -1;
423 goto end;
424 }
425
426 stream_class->byte_order = internal_byte_order;
427 end:
428 return ret;
429 }
430
431 BT_HIDDEN
432 int bt_ctf_stream_class_serialize(struct bt_ctf_stream_class *stream_class,
433 struct metadata_context *context)
434 {
435 int64_t ret = 0;
436 size_t i;
437
438 g_string_assign(context->field_name, "");
439 context->current_indentation_level = 1;
440 if (!stream_class->id_set) {
441 ret = -1;
442 goto end;
443 }
444
445 g_string_append_printf(context->string,
446 "stream {\n\tid = %" PRIu32 ";\n\tevent.header := ",
447 stream_class->id);
448 ret = bt_ctf_field_type_serialize(stream_class->event_header_type,
449 context);
450 if (ret) {
451 goto end;
452 }
453
454 g_string_append(context->string, ";\n\n\tpacket.context := ");
455 ret = bt_ctf_field_type_serialize(stream_class->packet_context_type,
456 context);
457 if (ret) {
458 goto end;
459 }
460
461 if (stream_class->event_context_type) {
462 g_string_append(context->string, ";\n\n\tevent.context := ");
463 ret = bt_ctf_field_type_serialize(
464 stream_class->event_context_type, context);
465 if (ret) {
466 goto end;
467 }
468 }
469
470 g_string_append(context->string, ";\n};\n\n");
471 for (i = 0; i < stream_class->event_classes->len; i++) {
472 struct bt_ctf_event_class *event_class =
473 stream_class->event_classes->pdata[i];
474
475 ret = bt_ctf_event_class_serialize(event_class, context);
476 if (ret) {
477 goto end;
478 }
479 }
480 end:
481 context->current_indentation_level = 0;
482 return ret;
483 }
484
485 static
486 void bt_ctf_stream_class_destroy(struct bt_ctf_ref *ref)
487 {
488 struct bt_ctf_stream_class *stream_class;
489
490 if (!ref) {
491 return;
492 }
493
494 stream_class = container_of(ref, struct bt_ctf_stream_class, ref_count);
495 bt_ctf_clock_put(stream_class->clock);
496
497 if (stream_class->event_classes) {
498 size_t i;
499
500 /* Unregister this stream class from the event classes */
501 for (i = 0; i < stream_class->event_classes->len; i++) {
502 struct bt_ctf_event_class *event_class =
503 g_ptr_array_index(stream_class->event_classes,
504 i);
505
506 bt_ctf_event_class_set_stream_class(event_class, NULL);
507 }
508
509 g_ptr_array_free(stream_class->event_classes, TRUE);
510 }
511
512 if (stream_class->name) {
513 g_string_free(stream_class->name, TRUE);
514 }
515
516 bt_ctf_field_type_put(stream_class->event_header_type);
517 bt_ctf_field_put(stream_class->event_header);
518 bt_ctf_field_type_put(stream_class->packet_context_type);
519 if (stream_class->event_context_type) {
520 bt_ctf_field_type_put(stream_class->event_context_type);
521 }
522 g_free(stream_class);
523 }
524
525 static
526 int init_event_header(struct bt_ctf_stream_class *stream_class,
527 enum bt_ctf_byte_order byte_order)
528 {
529 int ret = 0;
530 struct bt_ctf_field_type *event_header_type =
531 bt_ctf_field_type_structure_create();
532 struct bt_ctf_field_type *_uint32_t =
533 get_field_type(FIELD_TYPE_ALIAS_UINT32_T);
534 struct bt_ctf_field_type *_uint64_t =
535 get_field_type(FIELD_TYPE_ALIAS_UINT64_T);
536
537 if (!event_header_type) {
538 ret = -1;
539 goto end;
540 }
541
542 ret = bt_ctf_field_type_structure_add_field(event_header_type,
543 _uint32_t, "id");
544 if (ret) {
545 goto end;
546 }
547
548 ret = bt_ctf_field_type_structure_add_field(event_header_type,
549 _uint64_t, "timestamp");
550 if (ret) {
551 goto end;
552 }
553
554 stream_class->event_header_type = event_header_type;
555 stream_class->event_header = bt_ctf_field_create(
556 stream_class->event_header_type);
557 if (!stream_class->event_header) {
558 ret = -1;
559 }
560 end:
561 if (ret) {
562 bt_ctf_field_type_put(event_header_type);
563 }
564
565 bt_ctf_field_type_put(_uint32_t);
566 bt_ctf_field_type_put(_uint64_t);
567 return ret;
568 }
569
570 static
571 int init_packet_context(struct bt_ctf_stream_class *stream_class,
572 enum bt_ctf_byte_order byte_order)
573 {
574 int ret = 0;
575 struct bt_ctf_field_type *packet_context_type =
576 bt_ctf_field_type_structure_create();
577 struct bt_ctf_field_type *_uint64_t =
578 get_field_type(FIELD_TYPE_ALIAS_UINT64_T);
579
580 if (!packet_context_type) {
581 ret = -1;
582 goto end;
583 }
584
585 /*
586 * We create a stream packet context as proposed in the CTF
587 * specification.
588 */
589 ret = bt_ctf_field_type_structure_add_field(packet_context_type,
590 _uint64_t, "timestamp_begin");
591 if (ret) {
592 goto end;
593 }
594
595 ret = bt_ctf_field_type_structure_add_field(packet_context_type,
596 _uint64_t, "timestamp_end");
597 if (ret) {
598 goto end;
599 }
600
601 ret = bt_ctf_field_type_structure_add_field(packet_context_type,
602 _uint64_t, "content_size");
603 if (ret) {
604 goto end;
605 }
606
607 ret = bt_ctf_field_type_structure_add_field(packet_context_type,
608 _uint64_t, "packet_size");
609 if (ret) {
610 goto end;
611 }
612
613 ret = bt_ctf_field_type_structure_add_field(packet_context_type,
614 _uint64_t, "events_discarded");
615 if (ret) {
616 goto end;
617 }
618
619 stream_class->packet_context_type = packet_context_type;
620 end:
621 if (ret) {
622 bt_ctf_field_type_put(packet_context_type);
623 goto end;
624 }
625
626 bt_ctf_field_type_put(_uint64_t);
627 return ret;
628 }
This page took 0.050076 seconds and 5 git commands to generate.