Add trace moficiation notification handler interface
[babeltrace.git] / formats / ctf / ir / trace.c
CommitLineData
bc37ae52
JG
1/*
2 * trace.c
3 *
4 * Babeltrace CTF IR - Trace
5 *
6 * Copyright 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-ir/trace-internal.h>
30#include <babeltrace/ctf-ir/clock-internal.h>
31#include <babeltrace/ctf-ir/stream-internal.h>
32#include <babeltrace/ctf-ir/stream-class-internal.h>
09840de5 33#include <babeltrace/ctf-ir/event-internal.h>
272df73e
PP
34#include <babeltrace/ctf-ir/event-class.h>
35#include <babeltrace/ctf-ir/event-class-internal.h>
bc37ae52 36#include <babeltrace/ctf-writer/functor-internal.h>
2e33ac5a 37#include <babeltrace/ctf-ir/field-types-internal.h>
44e0a4f5 38#include <babeltrace/ctf-ir/attributes-internal.h>
09840de5 39#include <babeltrace/ctf-ir/validation-internal.h>
654c1444 40#include <babeltrace/ctf-ir/utils.h>
bc37ae52 41#include <babeltrace/compiler.h>
dac5c838 42#include <babeltrace/values.h>
83509119 43#include <babeltrace/ref.h>
a0b720b2 44#include <babeltrace/endian.h>
bc37ae52
JG
45
46#define DEFAULT_IDENTIFIER_SIZE 128
47#define DEFAULT_METADATA_STRING_SIZE 4096
48
2204c381
JG
49struct notification_handler {
50 bt_ctf_notification_cb func;
51 void *data;
52};
53
bc37ae52 54static
83509119 55void bt_ctf_trace_destroy(struct bt_object *obj);
bc37ae52
JG
56static
57int init_trace_packet_header(struct bt_ctf_trace *trace);
f67f3a6e 58static
09840de5 59void bt_ctf_trace_freeze(struct bt_ctf_trace *trace);
bc37ae52 60
bc37ae52
JG
61static
62const unsigned int field_type_aliases_alignments[] = {
63 [FIELD_TYPE_ALIAS_UINT5_T] = 1,
64 [FIELD_TYPE_ALIAS_UINT8_T ... FIELD_TYPE_ALIAS_UINT16_T] = 8,
65 [FIELD_TYPE_ALIAS_UINT27_T] = 1,
66 [FIELD_TYPE_ALIAS_UINT32_T ... FIELD_TYPE_ALIAS_UINT64_T] = 8,
67};
68
69static
70const unsigned int field_type_aliases_sizes[] = {
71 [FIELD_TYPE_ALIAS_UINT5_T] = 5,
72 [FIELD_TYPE_ALIAS_UINT8_T] = 8,
73 [FIELD_TYPE_ALIAS_UINT16_T] = 16,
74 [FIELD_TYPE_ALIAS_UINT27_T] = 27,
75 [FIELD_TYPE_ALIAS_UINT32_T] = 32,
76 [FIELD_TYPE_ALIAS_UINT64_T] = 64,
77};
78
bc37ae52
JG
79struct bt_ctf_trace *bt_ctf_trace_create(void)
80{
81 struct bt_ctf_trace *trace = NULL;
82
83 trace = g_new0(struct bt_ctf_trace, 1);
84 if (!trace) {
85 goto error;
86 }
87
88 bt_ctf_trace_set_byte_order(trace, BT_CTF_BYTE_ORDER_NATIVE);
83509119 89 bt_object_init(trace, bt_ctf_trace_destroy);
bc37ae52 90 trace->clocks = g_ptr_array_new_with_free_func(
83509119 91 (GDestroyNotify) bt_put);
bc37ae52 92 trace->streams = g_ptr_array_new_with_free_func(
e6a8e8e4 93 (GDestroyNotify) bt_object_release);
bc37ae52 94 trace->stream_classes = g_ptr_array_new_with_free_func(
e6a8e8e4 95 (GDestroyNotify) bt_object_release);
7f800dc7 96 if (!trace->clocks || !trace->stream_classes || !trace->streams) {
83509119 97 goto error;
bc37ae52
JG
98 }
99
100 /* Generate a trace UUID */
101 uuid_generate(trace->uuid);
102 if (init_trace_packet_header(trace)) {
83509119 103 goto error;
bc37ae52
JG
104 }
105
7f800dc7
PP
106 /* Create the environment array object */
107 trace->environment = bt_ctf_attributes_create();
108 if (!trace->environment) {
83509119 109 goto error;
7f800dc7
PP
110 }
111
bc37ae52
JG
112 return trace;
113
bc37ae52 114error:
83509119 115 BT_PUT(trace);
bc37ae52
JG
116 return trace;
117}
118
83509119 119void bt_ctf_trace_destroy(struct bt_object *obj)
bc37ae52
JG
120{
121 struct bt_ctf_trace *trace;
bc37ae52 122
83509119 123 trace = container_of(obj, struct bt_ctf_trace, base);
bc37ae52 124 if (trace->environment) {
7f800dc7 125 bt_ctf_attributes_destroy(trace->environment);
bc37ae52
JG
126 }
127
128 if (trace->clocks) {
129 g_ptr_array_free(trace->clocks, TRUE);
130 }
131
132 if (trace->streams) {
133 g_ptr_array_free(trace->streams, TRUE);
134 }
135
136 if (trace->stream_classes) {
137 g_ptr_array_free(trace->stream_classes, TRUE);
138 }
139
83509119 140 bt_put(trace->packet_header_type);
bc37ae52
JG
141 g_free(trace);
142}
143
7f800dc7 144int bt_ctf_trace_set_environment_field(struct bt_ctf_trace *trace,
dac5c838 145 const char *name, struct bt_value *value)
bc37ae52 146{
bc37ae52
JG
147 int ret = 0;
148
a0d12916 149 if (!trace || !name || !value ||
7f800dc7 150 bt_ctf_validate_identifier(name) ||
dac5c838 151 !(bt_value_is_integer(value) || bt_value_is_string(value))) {
bc37ae52 152 ret = -1;
7f800dc7 153 goto end;
bc37ae52
JG
154 }
155
156 if (strchr(name, ' ')) {
157 ret = -1;
7f800dc7 158 goto end;
bc37ae52
JG
159 }
160
a0d12916
JG
161 if (trace->frozen) {
162 /*
163 * New environment fields may be added to a frozen trace,
164 * but existing fields may not be changed.
165 *
166 * The object passed is frozen like all other attributes.
167 */
dac5c838 168 struct bt_value *attribute =
a0d12916
JG
169 bt_ctf_attributes_get_field_value_by_name(
170 trace->environment, name);
171
172 if (attribute) {
83509119 173 BT_PUT(attribute);
a0d12916
JG
174 ret = -1;
175 goto end;
176 }
177
dac5c838 178 bt_value_freeze(value);
a0d12916
JG
179 }
180
7f800dc7
PP
181 ret = bt_ctf_attributes_set_field_value(trace->environment, name,
182 value);
bc37ae52 183
7f800dc7
PP
184end:
185 return ret;
186}
bc37ae52 187
7f800dc7
PP
188int bt_ctf_trace_set_environment_field_string(struct bt_ctf_trace *trace,
189 const char *name, const char *value)
190{
191 int ret = 0;
dac5c838 192 struct bt_value *env_value_string_obj = NULL;
7f800dc7
PP
193
194 if (!trace || !name || !value) {
bc37ae52 195 ret = -1;
7f800dc7 196 goto end;
bc37ae52
JG
197 }
198
a0d12916
JG
199 if (trace->frozen) {
200 /*
201 * New environment fields may be added to a frozen trace,
202 * but existing fields may not be changed.
203 */
dac5c838 204 struct bt_value *attribute =
a0d12916
JG
205 bt_ctf_attributes_get_field_value_by_name(
206 trace->environment, name);
207
208 if (attribute) {
83509119 209 BT_PUT(attribute);
a0d12916
JG
210 ret = -1;
211 goto end;
212 }
213 }
214
dac5c838 215 env_value_string_obj = bt_value_string_create_init(value);
bc37ae52 216
7f800dc7
PP
217 if (!env_value_string_obj) {
218 ret = -1;
219 goto end;
bc37ae52
JG
220 }
221
a0d12916 222 if (trace->frozen) {
dac5c838 223 bt_value_freeze(env_value_string_obj);
a0d12916 224 }
7f800dc7
PP
225 ret = bt_ctf_trace_set_environment_field(trace, name,
226 env_value_string_obj);
227
228end:
83509119 229 BT_PUT(env_value_string_obj);
3487c9f3
JG
230 return ret;
231}
232
7f800dc7
PP
233int bt_ctf_trace_set_environment_field_integer(struct bt_ctf_trace *trace,
234 const char *name, int64_t value)
3487c9f3 235{
3487c9f3 236 int ret = 0;
dac5c838 237 struct bt_value *env_value_integer_obj = NULL;
3487c9f3
JG
238
239 if (!trace || !name) {
240 ret = -1;
7f800dc7 241 goto end;
3487c9f3
JG
242 }
243
a0d12916
JG
244 if (trace->frozen) {
245 /*
246 * New environment fields may be added to a frozen trace,
247 * but existing fields may not be changed.
248 */
dac5c838 249 struct bt_value *attribute =
a0d12916
JG
250 bt_ctf_attributes_get_field_value_by_name(
251 trace->environment, name);
252
253 if (attribute) {
83509119 254 BT_PUT(attribute);
a0d12916
JG
255 ret = -1;
256 goto end;
257 }
258 }
259
dac5c838 260 env_value_integer_obj = bt_value_integer_create_init(value);
7f800dc7 261 if (!env_value_integer_obj) {
3487c9f3 262 ret = -1;
7f800dc7 263 goto end;
3487c9f3
JG
264 }
265
7f800dc7
PP
266 ret = bt_ctf_trace_set_environment_field(trace, name,
267 env_value_integer_obj);
a0d12916 268 if (trace->frozen) {
dac5c838 269 bt_value_freeze(env_value_integer_obj);
a0d12916 270 }
7f800dc7 271end:
83509119 272 BT_PUT(env_value_integer_obj);
bc37ae52
JG
273 return ret;
274}
275
e6fa2160
JG
276int bt_ctf_trace_get_environment_field_count(struct bt_ctf_trace *trace)
277{
278 int ret = 0;
279
280 if (!trace) {
281 ret = -1;
282 goto end;
283 }
284
7f800dc7 285 ret = bt_ctf_attributes_get_count(trace->environment);
e6fa2160 286
e6fa2160 287end:
7f800dc7 288 return ret;
e6fa2160
JG
289}
290
291const char *
292bt_ctf_trace_get_environment_field_name(struct bt_ctf_trace *trace,
293 int index)
294{
e6fa2160
JG
295 const char *ret = NULL;
296
7f800dc7 297 if (!trace) {
e6fa2160
JG
298 goto end;
299 }
300
7f800dc7
PP
301 ret = bt_ctf_attributes_get_field_name(trace->environment, index);
302
e6fa2160
JG
303end:
304 return ret;
305}
306
dac5c838 307struct bt_value *bt_ctf_trace_get_environment_field_value(
7f800dc7 308 struct bt_ctf_trace *trace, int index)
e6fa2160 309{
dac5c838 310 struct bt_value *ret = NULL;
e6fa2160 311
7f800dc7 312 if (!trace) {
e6fa2160
JG
313 goto end;
314 }
315
7f800dc7
PP
316 ret = bt_ctf_attributes_get_field_value(trace->environment, index);
317
e6fa2160
JG
318end:
319 return ret;
320}
321
dac5c838 322struct bt_value *bt_ctf_trace_get_environment_field_value_by_name(
7f800dc7 323 struct bt_ctf_trace *trace, const char *name)
e6fa2160 324{
dac5c838 325 struct bt_value *ret = NULL;
e6fa2160 326
7f800dc7 327 if (!trace || !name) {
e6fa2160
JG
328 goto end;
329 }
330
7f800dc7
PP
331 ret = bt_ctf_attributes_get_field_value_by_name(trace->environment,
332 name);
333
e6fa2160
JG
334end:
335 return ret;
336}
337
bc37ae52
JG
338int bt_ctf_trace_add_clock(struct bt_ctf_trace *trace,
339 struct bt_ctf_clock *clock)
340{
341 int ret = 0;
342 struct search_query query = { .value = clock, .found = 0 };
343
344 if (!trace || !clock) {
345 ret = -1;
346 goto end;
347 }
348
349 /* Check for duplicate clocks */
350 g_ptr_array_foreach(trace->clocks, value_exists, &query);
351 if (query.found) {
352 ret = -1;
353 goto end;
354 }
355
83509119 356 bt_get(clock);
bc37ae52 357 g_ptr_array_add(trace->clocks, clock);
6474e016 358
cfeb617e
PP
359 if (!trace->is_created_by_writer) {
360 /*
361 * Non-writer mode trace: disable clock value functions
362 * because clock values are per-stream in that
363 * situation.
364 */
365 clock->has_value = 0;
366 }
367
6474e016
PP
368 if (trace->frozen) {
369 bt_ctf_clock_freeze(clock);
370 }
bc37ae52
JG
371end:
372 return ret;
373}
374
884cd6c3
JG
375int bt_ctf_trace_get_clock_count(struct bt_ctf_trace *trace)
376{
377 int ret = -1;
378
379 if (!trace) {
380 goto end;
381 }
382
383 ret = trace->clocks->len;
384end:
385 return ret;
386}
387
388struct bt_ctf_clock *bt_ctf_trace_get_clock(struct bt_ctf_trace *trace,
389 int index)
390{
391 struct bt_ctf_clock *clock = NULL;
392
393 if (!trace || index < 0 || index >= trace->clocks->len) {
394 goto end;
395 }
396
397 clock = g_ptr_array_index(trace->clocks, index);
83509119 398 bt_get(clock);
884cd6c3
JG
399end:
400 return clock;
401}
402
ef0c4a15
JG
403int bt_ctf_trace_add_stream_class(struct bt_ctf_trace *trace,
404 struct bt_ctf_stream_class *stream_class)
405{
406 int ret, i;
407 int64_t stream_id;
09840de5
PP
408 struct bt_ctf_validation_output trace_sc_validation_output = { 0 };
409 struct bt_ctf_validation_output *ec_validation_outputs = NULL;
410 const enum bt_ctf_validation_flag trace_sc_validation_flags =
411 BT_CTF_VALIDATION_FLAG_TRACE |
412 BT_CTF_VALIDATION_FLAG_STREAM;
413 const enum bt_ctf_validation_flag ec_validation_flags =
414 BT_CTF_VALIDATION_FLAG_EVENT;
415 struct bt_ctf_field_type *packet_header_type = NULL;
416 struct bt_ctf_field_type *packet_context_type = NULL;
417 struct bt_ctf_field_type *event_header_type = NULL;
418 struct bt_ctf_field_type *stream_event_ctx_type = NULL;
419 int event_class_count;
fe13b5c0 420 struct bt_ctf_clock *clock_to_add_to_trace = NULL;
ef0c4a15
JG
421
422 if (!trace || !stream_class) {
423 ret = -1;
424 goto end;
425 }
426
09840de5
PP
427 event_class_count =
428 bt_ctf_stream_class_get_event_class_count(stream_class);
429 assert(event_class_count >= 0);
430
431 /* Check for duplicate stream classes */
ef0c4a15
JG
432 for (i = 0; i < trace->stream_classes->len; i++) {
433 if (trace->stream_classes->pdata[i] == stream_class) {
09840de5 434 /* Stream class already registered to the trace */
ef0c4a15
JG
435 ret = -1;
436 goto end;
437 }
438 }
439
fe13b5c0
PP
440 /*
441 * If the stream class has a clock, register this clock to this
442 * trace if not already done.
443 */
444 if (stream_class->clock) {
445 const char *clock_name =
446 bt_ctf_clock_get_name(stream_class->clock);
447 struct bt_ctf_clock *trace_clock;
448
449 assert(clock_name);
450 trace_clock = bt_ctf_trace_get_clock_by_name(trace, clock_name);
451 bt_put(trace_clock);
452 if (trace_clock) {
453 if (trace_clock != stream_class->clock) {
454 /*
455 * Error: two different clocks in the
456 * trace would share the same name.
457 */
458 ret = -1;
459 goto end;
460 }
461 } else {
462 clock_to_add_to_trace = bt_get(stream_class->clock);
463 }
464 }
465
09840de5
PP
466 /*
467 * We're about to freeze both the trace and the stream class.
468 * Also, each event class contained in this stream class are
469 * already frozen.
470 *
471 * This trace, this stream class, and all its event classes
472 * should be valid at this point.
473 *
474 * Validate trace and stream class first, then each event
475 * class of this stream class can be validated individually.
476 */
477 packet_header_type =
478 bt_ctf_trace_get_packet_header_type(trace);
479 packet_context_type =
480 bt_ctf_stream_class_get_packet_context_type(stream_class);
481 event_header_type =
482 bt_ctf_stream_class_get_event_header_type(stream_class);
483 stream_event_ctx_type =
484 bt_ctf_stream_class_get_event_context_type(stream_class);
485 ret = bt_ctf_validate_class_types(trace->environment,
486 packet_header_type, packet_context_type, event_header_type,
487 stream_event_ctx_type, NULL, NULL, trace->valid,
488 stream_class->valid, 1, &trace_sc_validation_output,
489 trace_sc_validation_flags);
490 BT_PUT(packet_header_type);
491 BT_PUT(packet_context_type);
492 BT_PUT(event_header_type);
493 BT_PUT(stream_event_ctx_type);
494
2bd7f864 495 if (ret) {
09840de5
PP
496 /*
497 * This means something went wrong during the validation
498 * process, not that the objects are invalid.
499 */
2bd7f864
JG
500 goto end;
501 }
502
09840de5
PP
503 if ((trace_sc_validation_output.valid_flags &
504 trace_sc_validation_flags) !=
505 trace_sc_validation_flags) {
506 /* Invalid trace/stream class */
507 ret = -1;
508 goto end;
509 }
510
511 if (event_class_count > 0) {
512 ec_validation_outputs = g_new0(struct bt_ctf_validation_output,
513 event_class_count);
514 if (!ec_validation_outputs) {
515 ret = -1;
516 goto end;
517 }
518 }
519
520 /* Validate each event class individually */
6474e016 521 for (i = 0; i < event_class_count; i++) {
09840de5
PP
522 struct bt_ctf_event_class *event_class =
523 bt_ctf_stream_class_get_event_class(stream_class, i);
524 struct bt_ctf_field_type *event_context_type = NULL;
525 struct bt_ctf_field_type *event_payload_type = NULL;
526
527 event_context_type =
528 bt_ctf_event_class_get_context_type(event_class);
529 event_payload_type =
530 bt_ctf_event_class_get_payload_type(event_class);
531
532 /*
533 * It is important to use the field types returned by
534 * the previous trace and stream class validation here
535 * because copies could have been made.
536 */
537 ret = bt_ctf_validate_class_types(trace->environment,
538 trace_sc_validation_output.packet_header_type,
539 trace_sc_validation_output.packet_context_type,
540 trace_sc_validation_output.event_header_type,
541 trace_sc_validation_output.stream_event_ctx_type,
542 event_context_type, event_payload_type,
543 1, 1, event_class->valid, &ec_validation_outputs[i],
544 ec_validation_flags);
545 BT_PUT(event_context_type);
546 BT_PUT(event_payload_type);
547 BT_PUT(event_class);
548
549 if (ret) {
550 goto end;
551 }
552
553 if ((ec_validation_outputs[i].valid_flags &
554 ec_validation_flags) != ec_validation_flags) {
555 /* Invalid event class */
556 ret = -1;
557 goto end;
558 }
559 }
560
ef0c4a15
JG
561 stream_id = bt_ctf_stream_class_get_id(stream_class);
562 if (stream_id < 0) {
563 stream_id = trace->next_stream_id++;
564
565 /* Try to assign a new stream id */
566 for (i = 0; i < trace->stream_classes->len; i++) {
567 if (stream_id == bt_ctf_stream_class_get_id(
568 trace->stream_classes->pdata[i])) {
569 /* Duplicate stream id found */
570 ret = -1;
571 goto end;
572 }
573 }
574
0ddffae5
JG
575 if (bt_ctf_stream_class_set_id_no_check(stream_class,
576 stream_id)) {
ef0c4a15
JG
577 /* TODO Should retry with a different stream id */
578 ret = -1;
579 goto end;
580 }
581 }
582
e6a8e8e4 583 bt_object_set_parent(stream_class, trace);
ef0c4a15
JG
584 g_ptr_array_add(trace->stream_classes, stream_class);
585
586 /*
09840de5
PP
587 * At this point we know that the function will be successful.
588 * Therefore we can replace the trace and stream class field
589 * types with what's in their validation output structure and
590 * mark them as valid. We can also replace the field types of
591 * all the event classes of the stream class and mark them as
592 * valid.
593 */
594 bt_ctf_validation_replace_types(trace, stream_class, NULL,
595 &trace_sc_validation_output, trace_sc_validation_flags);
596 trace->valid = 1;
597 stream_class->valid = 1;
598
599 /*
600 * Put what was not moved in bt_ctf_validation_replace_types().
601 */
602 bt_ctf_validation_output_put_types(&trace_sc_validation_output);
603
6474e016 604 for (i = 0; i < event_class_count; i++) {
09840de5
PP
605 struct bt_ctf_event_class *event_class =
606 bt_ctf_stream_class_get_event_class(stream_class, i);
607
608 bt_ctf_validation_replace_types(NULL, NULL, event_class,
609 &ec_validation_outputs[i], ec_validation_flags);
610 event_class->valid = 1;
611 BT_PUT(event_class);
612
613 /*
614 * Put what was not moved in
615 * bt_ctf_validation_replace_types().
616 */
617 bt_ctf_validation_output_put_types(&ec_validation_outputs[i]);
618 }
619
620 /*
ef0c4a15
JG
621 * All field type byte orders set as "native" byte ordering can now be
622 * safely set to trace's own endianness, including the stream class'.
623 */
624 bt_ctf_field_type_set_native_byte_order(trace->packet_header_type,
625 trace->byte_order);
445c3471 626 bt_ctf_stream_class_set_byte_order(stream_class, trace->byte_order);
ef0c4a15 627
fe13b5c0
PP
628 /* Add stream class's clock if it exists */
629 if (clock_to_add_to_trace) {
630 int add_clock_ret =
631 bt_ctf_trace_add_clock(trace, clock_to_add_to_trace);
632 assert(add_clock_ret == 0);
633 }
634
09840de5
PP
635 /*
636 * Freeze the trace and the stream class.
637 */
f67f3a6e 638 bt_ctf_stream_class_freeze(stream_class);
09840de5
PP
639 bt_ctf_trace_freeze(trace);
640
ef0c4a15 641end:
d3814b54 642 if (ret) {
e6a8e8e4 643 bt_object_set_parent(stream_class, NULL);
09840de5
PP
644
645 if (ec_validation_outputs) {
6474e016 646 for (i = 0; i < event_class_count; i++) {
09840de5
PP
647 bt_ctf_validation_output_put_types(
648 &ec_validation_outputs[i]);
649 }
650 }
d3814b54 651 }
09840de5
PP
652
653 g_free(ec_validation_outputs);
654 bt_ctf_validation_output_put_types(&trace_sc_validation_output);
fe13b5c0 655 BT_PUT(clock_to_add_to_trace);
09840de5
PP
656 assert(!packet_header_type);
657 assert(!packet_context_type);
658 assert(!event_header_type);
659 assert(!stream_event_ctx_type);
660
ef0c4a15
JG
661 return ret;
662}
663
664int bt_ctf_trace_get_stream_class_count(struct bt_ctf_trace *trace)
665{
666 int ret;
667
668 if (!trace) {
669 ret = -1;
670 goto end;
671 }
672
673 ret = trace->stream_classes->len;
674end:
675 return ret;
676}
677
678struct bt_ctf_stream_class *bt_ctf_trace_get_stream_class(
679 struct bt_ctf_trace *trace, int index)
680{
681 struct bt_ctf_stream_class *stream_class = NULL;
682
683 if (!trace || index < 0 || index >= trace->stream_classes->len) {
684 goto end;
685 }
686
687 stream_class = g_ptr_array_index(trace->stream_classes, index);
83509119 688 bt_get(stream_class);
ef0c4a15
JG
689end:
690 return stream_class;
691}
692
4841ccc1
PP
693struct bt_ctf_stream_class *bt_ctf_trace_get_stream_class_by_id(
694 struct bt_ctf_trace *trace, uint32_t id)
695{
696 int i;
697 struct bt_ctf_stream_class *stream_class = NULL;
698
699 if (!trace) {
700 goto end;
701 }
702
6474e016 703 for (i = 0; i < trace->stream_classes->len; i++) {
4841ccc1
PP
704 struct bt_ctf_stream_class *stream_class_candidate;
705
706 stream_class_candidate =
707 g_ptr_array_index(trace->stream_classes, i);
708
709 if (bt_ctf_stream_class_get_id(stream_class_candidate) ==
710 (int64_t) id) {
711 stream_class = stream_class_candidate;
83509119 712 bt_get(stream_class);
4841ccc1
PP
713 goto end;
714 }
715 }
716
717end:
718 return stream_class;
719}
720
7e4347a3
PP
721struct bt_ctf_clock *bt_ctf_trace_get_clock_by_name(
722 struct bt_ctf_trace *trace, const char *name)
723{
724 size_t i;
725 struct bt_ctf_clock *clock = NULL;
726
727 if (!trace || !name) {
728 goto end;
729 }
730
6474e016 731 for (i = 0; i < trace->clocks->len; i++) {
7e4347a3
PP
732 struct bt_ctf_clock *cur_clk =
733 g_ptr_array_index(trace->clocks, i);
734 const char *cur_clk_name = bt_ctf_clock_get_name(cur_clk);
735
736 if (!cur_clk_name) {
737 goto end;
738 }
739
740 if (!strcmp(cur_clk_name, name)) {
741 clock = cur_clk;
83509119 742 bt_get(clock);
7e4347a3
PP
743 goto end;
744 }
745 }
746
747end:
748 return clock;
749}
750
bc37ae52
JG
751BT_HIDDEN
752const char *get_byte_order_string(int byte_order)
753{
754 const char *string;
755
756 switch (byte_order) {
757 case LITTLE_ENDIAN:
758 string = "le";
759 break;
760 case BIG_ENDIAN:
761 string = "be";
762 break;
763 default:
764 string = "unknown";
765 break;
766 }
767
768 return string;
769}
770
771static
772int append_trace_metadata(struct bt_ctf_trace *trace,
773 struct metadata_context *context)
774{
775 unsigned char *uuid = trace->uuid;
776 int ret;
777
778 g_string_append(context->string, "trace {\n");
779
780 g_string_append(context->string, "\tmajor = 1;\n");
781 g_string_append(context->string, "\tminor = 8;\n");
782
783 g_string_append_printf(context->string,
784 "\tuuid = \"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\";\n",
785 uuid[0], uuid[1], uuid[2], uuid[3],
786 uuid[4], uuid[5], uuid[6], uuid[7],
787 uuid[8], uuid[9], uuid[10], uuid[11],
788 uuid[12], uuid[13], uuid[14], uuid[15]);
789 g_string_append_printf(context->string, "\tbyte_order = %s;\n",
790 get_byte_order_string(trace->byte_order));
791
792 g_string_append(context->string, "\tpacket.header := ");
793 context->current_indentation_level++;
794 g_string_assign(context->field_name, "");
d246b111 795 ret = bt_ctf_field_type_serialize(trace->packet_header_type,
bc37ae52
JG
796 context);
797 if (ret) {
798 goto end;
799 }
800 context->current_indentation_level--;
801
802 g_string_append(context->string, ";\n};\n\n");
803end:
804 return ret;
805}
806
bc37ae52
JG
807static
808void append_env_metadata(struct bt_ctf_trace *trace,
809 struct metadata_context *context)
810{
7f800dc7
PP
811 int i;
812 int env_size;
813
814 env_size = bt_ctf_attributes_get_count(trace->environment);
815
816 if (env_size <= 0) {
bc37ae52
JG
817 return;
818 }
819
820 g_string_append(context->string, "env {\n");
7f800dc7 821
6474e016 822 for (i = 0; i < env_size; i++) {
dac5c838 823 struct bt_value *env_field_value_obj = NULL;
7f800dc7 824 const char *entry_name;
7f800dc7
PP
825
826 entry_name = bt_ctf_attributes_get_field_name(
827 trace->environment, i);
828 env_field_value_obj = bt_ctf_attributes_get_field_value(
829 trace->environment, i);
830
831 if (!entry_name || !env_field_value_obj) {
832 goto loop_next;
833 }
834
dac5c838
PP
835 switch (bt_value_get_type(env_field_value_obj)) {
836 case BT_VALUE_TYPE_INTEGER:
b8248cc0
PP
837 {
838 int ret;
839 int64_t int_value;
840
dac5c838 841 ret = bt_value_integer_get(env_field_value_obj,
7f800dc7
PP
842 &int_value);
843
844 if (ret) {
845 goto loop_next;
846 }
847
848 g_string_append_printf(context->string,
849 "\t%s = %" PRId64 ";\n", entry_name,
850 int_value);
851 break;
b8248cc0 852 }
dac5c838 853 case BT_VALUE_TYPE_STRING:
7f800dc7
PP
854 {
855 int ret;
856 const char *str_value;
857 char *escaped_str = NULL;
858
dac5c838 859 ret = bt_value_string_get(env_field_value_obj,
7f800dc7
PP
860 &str_value);
861
862 if (ret) {
863 goto loop_next;
864 }
865
866 escaped_str = g_strescape(str_value, NULL);
867
868 if (!escaped_str) {
869 goto loop_next;
870 }
871
872 g_string_append_printf(context->string,
873 "\t%s = \"%s\";\n", entry_name, escaped_str);
874 free(escaped_str);
875 break;
876 }
877
878 default:
879 goto loop_next;
880 }
881
882loop_next:
83509119 883 BT_PUT(env_field_value_obj);
7f800dc7
PP
884 }
885
bc37ae52
JG
886 g_string_append(context->string, "};\n\n");
887}
888
889char *bt_ctf_trace_get_metadata_string(struct bt_ctf_trace *trace)
890{
891 char *metadata = NULL;
892 struct metadata_context *context = NULL;
893 int err = 0;
894 size_t i;
895
896 if (!trace) {
897 goto end;
898 }
899
900 context = g_new0(struct metadata_context, 1);
901 if (!context) {
902 goto end;
903 }
904
905 context->field_name = g_string_sized_new(DEFAULT_IDENTIFIER_SIZE);
906 context->string = g_string_sized_new(DEFAULT_METADATA_STRING_SIZE);
907 g_string_append(context->string, "/* CTF 1.8 */\n\n");
908 if (append_trace_metadata(trace, context)) {
909 goto error;
910 }
911 append_env_metadata(trace, context);
912 g_ptr_array_foreach(trace->clocks,
913 (GFunc)bt_ctf_clock_serialize, context);
914
915 for (i = 0; i < trace->stream_classes->len; i++) {
916 err = bt_ctf_stream_class_serialize(
917 trace->stream_classes->pdata[i], context);
918 if (err) {
919 goto error;
920 }
921 }
922
923 metadata = context->string->str;
924error:
925 g_string_free(context->string, err ? TRUE : FALSE);
926 g_string_free(context->field_name, TRUE);
927 g_free(context);
928end:
929 return metadata;
930}
931
4ed90fb3
JG
932enum bt_ctf_byte_order bt_ctf_trace_get_byte_order(struct bt_ctf_trace *trace)
933{
934 enum bt_ctf_byte_order ret = BT_CTF_BYTE_ORDER_UNKNOWN;
935
936 if (!trace) {
937 goto end;
938 }
939
940 switch (trace->byte_order) {
941 case BIG_ENDIAN:
942 ret = BT_CTF_BYTE_ORDER_BIG_ENDIAN;
943 break;
944 case LITTLE_ENDIAN:
945 ret = BT_CTF_BYTE_ORDER_LITTLE_ENDIAN;
946 break;
947 default:
948 break;
949 }
950end:
951 return ret;
952}
953
bc37ae52
JG
954int bt_ctf_trace_set_byte_order(struct bt_ctf_trace *trace,
955 enum bt_ctf_byte_order byte_order)
956{
957 int ret = 0;
958 int internal_byte_order;
959
960 if (!trace || trace->frozen) {
961 ret = -1;
962 goto end;
963 }
964
965 switch (byte_order) {
966 case BT_CTF_BYTE_ORDER_NATIVE:
c35a1669
JG
967 /*
968 * This doesn't make sense since the CTF specification defines
969 * the "native" byte order as "the byte order described in the
970 * trace description". However, this behavior had been
971 * implemented as part of v1.2 and is kept to maintain
972 * compatibility.
973 *
974 * This may be changed on a major version bump only.
975 */
976 internal_byte_order = (G_BYTE_ORDER == G_LITTLE_ENDIAN) ?
bc37ae52
JG
977 LITTLE_ENDIAN : BIG_ENDIAN;
978 break;
979 case BT_CTF_BYTE_ORDER_LITTLE_ENDIAN:
980 internal_byte_order = LITTLE_ENDIAN;
981 break;
982 case BT_CTF_BYTE_ORDER_BIG_ENDIAN:
983 case BT_CTF_BYTE_ORDER_NETWORK:
984 internal_byte_order = BIG_ENDIAN;
985 break;
986 default:
987 ret = -1;
988 goto end;
989 }
990
991 trace->byte_order = internal_byte_order;
bc37ae52
JG
992end:
993 return ret;
994}
995
d246b111
JG
996struct bt_ctf_field_type *bt_ctf_trace_get_packet_header_type(
997 struct bt_ctf_trace *trace)
998{
999 struct bt_ctf_field_type *field_type = NULL;
1000
1001 if (!trace) {
1002 goto end;
1003 }
1004
83509119 1005 bt_get(trace->packet_header_type);
d246b111
JG
1006 field_type = trace->packet_header_type;
1007end:
1008 return field_type;
1009}
1010
1011int bt_ctf_trace_set_packet_header_type(struct bt_ctf_trace *trace,
1012 struct bt_ctf_field_type *packet_header_type)
1013{
1014 int ret = 0;
1015
1016 if (!trace || !packet_header_type || trace->frozen) {
1017 ret = -1;
1018 goto end;
1019 }
1020
1021 /* packet_header_type must be a structure */
1022 if (bt_ctf_field_type_get_type_id(packet_header_type) !=
9a19a512 1023 BT_CTF_TYPE_ID_STRUCT) {
d246b111
JG
1024 ret = -1;
1025 goto end;
1026 }
1027
83509119
JG
1028 bt_get(packet_header_type);
1029 bt_put(trace->packet_header_type);
d246b111
JG
1030 trace->packet_header_type = packet_header_type;
1031end:
1032 return ret;
1033}
1034
2204c381
JG
1035int bt_ctf_trace_add_notification_handler_cb(struct bt_ctf_trace *trace,
1036 bt_ctf_notification_cb handler, void *handler_data)
1037{
1038 int ret = 0;
1039 struct notification_handler *handler_wrapper =
1040 g_new0(struct notification_handler, 1);
1041
1042 if (!trace || !handler || !handler_wrapper) {
1043 ret = -1;
1044 goto error;
1045 }
1046
1047 handler_wrapper->func = handler;
1048 handler_wrapper->data = handler_data;
1049 g_ptr_array_add(trace->notification_handlers, handler_wrapper);
1050 return ret;
1051error:
1052 g_free(handler_wrapper);
1053 return ret;
1054}
1055
bc37ae52
JG
1056BT_HIDDEN
1057struct bt_ctf_field_type *get_field_type(enum field_type_alias alias)
1058{
a25e0d14 1059 int ret;
bc37ae52 1060 unsigned int alignment, size;
8bdcb82e 1061 struct bt_ctf_field_type *field_type = NULL;
bc37ae52
JG
1062
1063 if (alias >= NR_FIELD_TYPE_ALIAS) {
8bdcb82e 1064 goto end;
bc37ae52
JG
1065 }
1066
1067 alignment = field_type_aliases_alignments[alias];
1068 size = field_type_aliases_sizes[alias];
1069 field_type = bt_ctf_field_type_integer_create(size);
a25e0d14
JG
1070 ret = bt_ctf_field_type_set_alignment(field_type, alignment);
1071 if (ret) {
1072 BT_PUT(field_type);
1073 }
8bdcb82e 1074end:
bc37ae52
JG
1075 return field_type;
1076}
1077
f67f3a6e 1078static
09840de5 1079void bt_ctf_trace_freeze(struct bt_ctf_trace *trace)
f67f3a6e 1080{
6474e016
PP
1081 int i;
1082
09840de5 1083 bt_ctf_field_type_freeze(trace->packet_header_type);
f67f3a6e 1084 bt_ctf_attributes_freeze(trace->environment);
6474e016
PP
1085
1086 for (i = 0; i < trace->clocks->len; i++) {
1087 struct bt_ctf_clock *clock =
1088 g_ptr_array_index(trace->clocks, i);
1089
1090 bt_ctf_clock_freeze(clock);
1091 }
1092
f67f3a6e
JG
1093 trace->frozen = 1;
1094}
1095
bc37ae52
JG
1096static
1097int init_trace_packet_header(struct bt_ctf_trace *trace)
1098{
bc37ae52 1099 int ret = 0;
d246b111 1100 struct bt_ctf_field *magic = NULL, *uuid_array = NULL;
bc37ae52
JG
1101 struct bt_ctf_field_type *_uint32_t =
1102 get_field_type(FIELD_TYPE_ALIAS_UINT32_T);
1103 struct bt_ctf_field_type *_uint8_t =
1104 get_field_type(FIELD_TYPE_ALIAS_UINT8_T);
1105 struct bt_ctf_field_type *trace_packet_header_type =
1106 bt_ctf_field_type_structure_create();
1107 struct bt_ctf_field_type *uuid_array_type =
1108 bt_ctf_field_type_array_create(_uint8_t, 16);
1109
1110 if (!trace_packet_header_type || !uuid_array_type) {
1111 ret = -1;
1112 goto end;
1113 }
1114
bc37ae52
JG
1115 ret = bt_ctf_field_type_structure_add_field(trace_packet_header_type,
1116 _uint32_t, "magic");
1117 if (ret) {
1118 goto end;
1119 }
1120
1121 ret = bt_ctf_field_type_structure_add_field(trace_packet_header_type,
1122 uuid_array_type, "uuid");
1123 if (ret) {
1124 goto end;
1125 }
1126
1127 ret = bt_ctf_field_type_structure_add_field(trace_packet_header_type,
1128 _uint32_t, "stream_id");
1129 if (ret) {
1130 goto end;
1131 }
1132
662e778c
JG
1133 ret = bt_ctf_trace_set_packet_header_type(trace,
1134 trace_packet_header_type);
1135 if (ret) {
1136 goto end;
1137 }
bc37ae52 1138end:
83509119
JG
1139 bt_put(uuid_array_type);
1140 bt_put(_uint32_t);
1141 bt_put(_uint8_t);
1142 bt_put(magic);
1143 bt_put(uuid_array);
1144 bt_put(trace_packet_header_type);
bc37ae52
JG
1145 return ret;
1146}
This page took 0.080347 seconds and 4 git commands to generate.