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