Fix: duplicate function declaration in stream.h
[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>
33#include <babeltrace/ctf-writer/functor-internal.h>
34#include <babeltrace/ctf-ir/event-types-internal.h>
654c1444 35#include <babeltrace/ctf-ir/utils.h>
bc37ae52
JG
36#include <babeltrace/compiler.h>
37
38#define DEFAULT_IDENTIFIER_SIZE 128
39#define DEFAULT_METADATA_STRING_SIZE 4096
40
41static
42void environment_variable_destroy(struct environment_variable *var);
43static
44void bt_ctf_trace_destroy(struct bt_ctf_ref *ref);
45static
46int init_trace_packet_header(struct bt_ctf_trace *trace);
47
bc37ae52
JG
48static
49const unsigned int field_type_aliases_alignments[] = {
50 [FIELD_TYPE_ALIAS_UINT5_T] = 1,
51 [FIELD_TYPE_ALIAS_UINT8_T ... FIELD_TYPE_ALIAS_UINT16_T] = 8,
52 [FIELD_TYPE_ALIAS_UINT27_T] = 1,
53 [FIELD_TYPE_ALIAS_UINT32_T ... FIELD_TYPE_ALIAS_UINT64_T] = 8,
54};
55
56static
57const unsigned int field_type_aliases_sizes[] = {
58 [FIELD_TYPE_ALIAS_UINT5_T] = 5,
59 [FIELD_TYPE_ALIAS_UINT8_T] = 8,
60 [FIELD_TYPE_ALIAS_UINT16_T] = 16,
61 [FIELD_TYPE_ALIAS_UINT27_T] = 27,
62 [FIELD_TYPE_ALIAS_UINT32_T] = 32,
63 [FIELD_TYPE_ALIAS_UINT64_T] = 64,
64};
65
bc37ae52
JG
66struct bt_ctf_trace *bt_ctf_trace_create(void)
67{
68 struct bt_ctf_trace *trace = NULL;
69
70 trace = g_new0(struct bt_ctf_trace, 1);
71 if (!trace) {
72 goto error;
73 }
74
75 bt_ctf_trace_set_byte_order(trace, BT_CTF_BYTE_ORDER_NATIVE);
76 bt_ctf_ref_init(&trace->ref_count);
77 trace->environment = g_ptr_array_new_with_free_func(
78 (GDestroyNotify)environment_variable_destroy);
79 trace->clocks = g_ptr_array_new_with_free_func(
80 (GDestroyNotify)bt_ctf_clock_put);
81 trace->streams = g_ptr_array_new_with_free_func(
82 (GDestroyNotify)bt_ctf_stream_put);
83 trace->stream_classes = g_ptr_array_new_with_free_func(
84 (GDestroyNotify)bt_ctf_stream_class_put);
85 if (!trace->environment || !trace->clocks ||
86 !trace->stream_classes || !trace->streams) {
87 goto error_destroy;
88 }
89
90 /* Generate a trace UUID */
91 uuid_generate(trace->uuid);
92 if (init_trace_packet_header(trace)) {
93 goto error_destroy;
94 }
95
96 return trace;
97
98error_destroy:
99 bt_ctf_trace_destroy(&trace->ref_count);
100 trace = NULL;
101error:
102 return trace;
103}
104
105void bt_ctf_trace_destroy(struct bt_ctf_ref *ref)
106{
107 struct bt_ctf_trace *trace;
108
109 if (!ref) {
110 return;
111 }
112
113 trace = container_of(ref, struct bt_ctf_trace, ref_count);
114 if (trace->environment) {
115 g_ptr_array_free(trace->environment, TRUE);
116 }
117
118 if (trace->clocks) {
119 g_ptr_array_free(trace->clocks, TRUE);
120 }
121
122 if (trace->streams) {
123 g_ptr_array_free(trace->streams, TRUE);
124 }
125
126 if (trace->stream_classes) {
127 g_ptr_array_free(trace->stream_classes, TRUE);
128 }
129
d246b111 130 bt_ctf_field_type_put(trace->packet_header_type);
bc37ae52
JG
131 g_free(trace);
132}
133
134struct bt_ctf_stream *bt_ctf_trace_create_stream(struct bt_ctf_trace *trace,
135 struct bt_ctf_stream_class *stream_class)
136{
137 int ret;
138 int stream_class_found = 0;
139 size_t i;
140 struct bt_ctf_stream *stream = NULL;
141
142 if (!trace || !stream_class) {
143 goto error;
144 }
145
146 ret = bt_ctf_stream_class_set_byte_order(stream_class,
147 trace->byte_order == LITTLE_ENDIAN ?
148 BT_CTF_BYTE_ORDER_LITTLE_ENDIAN : BT_CTF_BYTE_ORDER_BIG_ENDIAN);
149 if (ret) {
150 goto error;
151 }
152
d246b111 153 stream = bt_ctf_stream_create(stream_class, trace);
bc37ae52
JG
154 if (!stream) {
155 goto error;
156 }
157
158 for (i = 0; i < trace->stream_classes->len; i++) {
159 if (trace->stream_classes->pdata[i] == stream_class) {
160 stream_class_found = 1;
161 }
162 }
163
164 if (!stream_class_found) {
165 int64_t stream_id = bt_ctf_stream_class_get_id(stream_class);
166
167 if (stream_id < 0) {
168 /* Try to assign a new stream id */
169 if (bt_ctf_stream_class_set_id(stream->stream_class,
170 trace->next_stream_id++)) {
171 goto error;
172 }
173 }
174
175 for (i = 0; i < trace->stream_classes->len; i++) {
176 if (stream_id == bt_ctf_stream_class_get_id(
177 trace->stream_classes->pdata[i])) {
178 /* Duplicate stream id found */
179 goto error;
180 }
181 }
182 bt_ctf_stream_class_get(stream->stream_class);
183 g_ptr_array_add(trace->stream_classes, stream->stream_class);
184 }
185
186 bt_ctf_stream_get(stream);
187 g_ptr_array_add(trace->streams, stream);
29d9d76c 188 bt_ctf_stream_class_freeze(stream_class);
bc37ae52
JG
189 trace->frozen = 1;
190 return stream;
191
192error:
193 bt_ctf_stream_put(stream);
194 return NULL;
195}
196
197int bt_ctf_trace_add_environment_field(struct bt_ctf_trace *trace,
198 const char *name,
199 const char *value)
200{
201 struct environment_variable *var = NULL;
202 char *escaped_value = NULL;
203 int ret = 0;
204
654c1444 205 if (!trace || !name || !value || bt_ctf_validate_identifier(name)) {
bc37ae52
JG
206 ret = -1;
207 goto error;
208 }
209
210 if (strchr(name, ' ')) {
211 ret = -1;
212 goto error;
213 }
214
215 var = g_new0(struct environment_variable, 1);
216 if (!var) {
217 ret = -1;
218 goto error;
219 }
220
221 escaped_value = g_strescape(value, NULL);
222 if (!escaped_value) {
223 ret = -1;
224 goto error;
225 }
226
227 var->name = g_string_new(name);
228 var->value = g_string_new(escaped_value);
229 g_free(escaped_value);
230 if (!var->name || !var->value) {
231 ret = -1;
232 goto error;
233 }
234
235 g_ptr_array_add(trace->environment, var);
236 return ret;
237
238error:
239 if (var && var->name) {
240 g_string_free(var->name, TRUE);
241 }
242
243 if (var && var->value) {
244 g_string_free(var->value, TRUE);
245 }
246
247 g_free(var);
248 return ret;
249}
250
251int bt_ctf_trace_add_clock(struct bt_ctf_trace *trace,
252 struct bt_ctf_clock *clock)
253{
254 int ret = 0;
255 struct search_query query = { .value = clock, .found = 0 };
256
257 if (!trace || !clock) {
258 ret = -1;
259 goto end;
260 }
261
262 /* Check for duplicate clocks */
263 g_ptr_array_foreach(trace->clocks, value_exists, &query);
264 if (query.found) {
265 ret = -1;
266 goto end;
267 }
268
269 bt_ctf_clock_get(clock);
270 g_ptr_array_add(trace->clocks, clock);
271end:
272 return ret;
273}
274
884cd6c3
JG
275int bt_ctf_trace_get_clock_count(struct bt_ctf_trace *trace)
276{
277 int ret = -1;
278
279 if (!trace) {
280 goto end;
281 }
282
283 ret = trace->clocks->len;
284end:
285 return ret;
286}
287
288struct bt_ctf_clock *bt_ctf_trace_get_clock(struct bt_ctf_trace *trace,
289 int index)
290{
291 struct bt_ctf_clock *clock = NULL;
292
293 if (!trace || index < 0 || index >= trace->clocks->len) {
294 goto end;
295 }
296
297 clock = g_ptr_array_index(trace->clocks, index);
298 bt_ctf_clock_get(clock);
299end:
300 return clock;
301}
302
bc37ae52
JG
303BT_HIDDEN
304const char *get_byte_order_string(int byte_order)
305{
306 const char *string;
307
308 switch (byte_order) {
309 case LITTLE_ENDIAN:
310 string = "le";
311 break;
312 case BIG_ENDIAN:
313 string = "be";
314 break;
315 default:
316 string = "unknown";
317 break;
318 }
319
320 return string;
321}
322
323static
324int append_trace_metadata(struct bt_ctf_trace *trace,
325 struct metadata_context *context)
326{
327 unsigned char *uuid = trace->uuid;
328 int ret;
329
330 g_string_append(context->string, "trace {\n");
331
332 g_string_append(context->string, "\tmajor = 1;\n");
333 g_string_append(context->string, "\tminor = 8;\n");
334
335 g_string_append_printf(context->string,
336 "\tuuid = \"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\";\n",
337 uuid[0], uuid[1], uuid[2], uuid[3],
338 uuid[4], uuid[5], uuid[6], uuid[7],
339 uuid[8], uuid[9], uuid[10], uuid[11],
340 uuid[12], uuid[13], uuid[14], uuid[15]);
341 g_string_append_printf(context->string, "\tbyte_order = %s;\n",
342 get_byte_order_string(trace->byte_order));
343
344 g_string_append(context->string, "\tpacket.header := ");
345 context->current_indentation_level++;
346 g_string_assign(context->field_name, "");
d246b111 347 ret = bt_ctf_field_type_serialize(trace->packet_header_type,
bc37ae52
JG
348 context);
349 if (ret) {
350 goto end;
351 }
352 context->current_indentation_level--;
353
354 g_string_append(context->string, ";\n};\n\n");
355end:
356 return ret;
357}
358
359static
360void append_env_field_metadata(struct environment_variable *var,
361 struct metadata_context *context)
362{
363 g_string_append_printf(context->string, "\t%s = \"%s\";\n",
364 var->name->str, var->value->str);
365}
366
367static
368void append_env_metadata(struct bt_ctf_trace *trace,
369 struct metadata_context *context)
370{
371 if (trace->environment->len == 0) {
372 return;
373 }
374
375 g_string_append(context->string, "env {\n");
376 g_ptr_array_foreach(trace->environment,
377 (GFunc)append_env_field_metadata, context);
378 g_string_append(context->string, "};\n\n");
379}
380
381char *bt_ctf_trace_get_metadata_string(struct bt_ctf_trace *trace)
382{
383 char *metadata = NULL;
384 struct metadata_context *context = NULL;
385 int err = 0;
386 size_t i;
387
388 if (!trace) {
389 goto end;
390 }
391
392 context = g_new0(struct metadata_context, 1);
393 if (!context) {
394 goto end;
395 }
396
397 context->field_name = g_string_sized_new(DEFAULT_IDENTIFIER_SIZE);
398 context->string = g_string_sized_new(DEFAULT_METADATA_STRING_SIZE);
399 g_string_append(context->string, "/* CTF 1.8 */\n\n");
400 if (append_trace_metadata(trace, context)) {
401 goto error;
402 }
403 append_env_metadata(trace, context);
404 g_ptr_array_foreach(trace->clocks,
405 (GFunc)bt_ctf_clock_serialize, context);
406
407 for (i = 0; i < trace->stream_classes->len; i++) {
408 err = bt_ctf_stream_class_serialize(
409 trace->stream_classes->pdata[i], context);
410 if (err) {
411 goto error;
412 }
413 }
414
415 metadata = context->string->str;
416error:
417 g_string_free(context->string, err ? TRUE : FALSE);
418 g_string_free(context->field_name, TRUE);
419 g_free(context);
420end:
421 return metadata;
422}
423
424int bt_ctf_trace_set_byte_order(struct bt_ctf_trace *trace,
425 enum bt_ctf_byte_order byte_order)
426{
427 int ret = 0;
428 int internal_byte_order;
429
430 if (!trace || trace->frozen) {
431 ret = -1;
432 goto end;
433 }
434
435 switch (byte_order) {
436 case BT_CTF_BYTE_ORDER_NATIVE:
437 internal_byte_order = (G_BYTE_ORDER == G_LITTLE_ENDIAN) ?
438 LITTLE_ENDIAN : BIG_ENDIAN;
439 break;
440 case BT_CTF_BYTE_ORDER_LITTLE_ENDIAN:
441 internal_byte_order = LITTLE_ENDIAN;
442 break;
443 case BT_CTF_BYTE_ORDER_BIG_ENDIAN:
444 case BT_CTF_BYTE_ORDER_NETWORK:
445 internal_byte_order = BIG_ENDIAN;
446 break;
447 default:
448 ret = -1;
449 goto end;
450 }
451
452 trace->byte_order = internal_byte_order;
d246b111 453 if (trace->packet_header_type) {
bc37ae52
JG
454 init_trace_packet_header(trace);
455 }
456end:
457 return ret;
458}
459
d246b111
JG
460struct bt_ctf_field_type *bt_ctf_trace_get_packet_header_type(
461 struct bt_ctf_trace *trace)
462{
463 struct bt_ctf_field_type *field_type = NULL;
464
465 if (!trace) {
466 goto end;
467 }
468
469 bt_ctf_field_type_get(trace->packet_header_type);
470 field_type = trace->packet_header_type;
471end:
472 return field_type;
473}
474
475int bt_ctf_trace_set_packet_header_type(struct bt_ctf_trace *trace,
476 struct bt_ctf_field_type *packet_header_type)
477{
478 int ret = 0;
479
480 if (!trace || !packet_header_type || trace->frozen) {
481 ret = -1;
482 goto end;
483 }
484
485 /* packet_header_type must be a structure */
486 if (bt_ctf_field_type_get_type_id(packet_header_type) !=
487 CTF_TYPE_STRUCT) {
488 ret = -1;
489 goto end;
490 }
491
492 bt_ctf_field_type_get(packet_header_type);
493 bt_ctf_field_type_put(trace->packet_header_type);
494 trace->packet_header_type = packet_header_type;
495end:
496 return ret;
497}
498
bc37ae52
JG
499void bt_ctf_trace_get(struct bt_ctf_trace *trace)
500{
501 if (!trace) {
502 return;
503 }
504
505 bt_ctf_ref_get(&trace->ref_count);
506}
507
508void bt_ctf_trace_put(struct bt_ctf_trace *trace)
509{
510 if (!trace) {
511 return;
512 }
513
514 bt_ctf_ref_put(&trace->ref_count, bt_ctf_trace_destroy);
515}
516
bc37ae52
JG
517BT_HIDDEN
518struct bt_ctf_field_type *get_field_type(enum field_type_alias alias)
519{
520 unsigned int alignment, size;
521 struct bt_ctf_field_type *field_type;
522
523 if (alias >= NR_FIELD_TYPE_ALIAS) {
524 return NULL;
525 }
526
527 alignment = field_type_aliases_alignments[alias];
528 size = field_type_aliases_sizes[alias];
529 field_type = bt_ctf_field_type_integer_create(size);
530 bt_ctf_field_type_set_alignment(field_type, alignment);
531 return field_type;
532}
533
534static
535int init_trace_packet_header(struct bt_ctf_trace *trace)
536{
bc37ae52 537 int ret = 0;
d246b111 538 struct bt_ctf_field *magic = NULL, *uuid_array = NULL;
bc37ae52
JG
539 struct bt_ctf_field_type *_uint32_t =
540 get_field_type(FIELD_TYPE_ALIAS_UINT32_T);
541 struct bt_ctf_field_type *_uint8_t =
542 get_field_type(FIELD_TYPE_ALIAS_UINT8_T);
543 struct bt_ctf_field_type *trace_packet_header_type =
544 bt_ctf_field_type_structure_create();
545 struct bt_ctf_field_type *uuid_array_type =
546 bt_ctf_field_type_array_create(_uint8_t, 16);
547
548 if (!trace_packet_header_type || !uuid_array_type) {
549 ret = -1;
550 goto end;
551 }
552
553 ret = bt_ctf_field_type_set_byte_order(_uint32_t,
554 (trace->byte_order == LITTLE_ENDIAN ?
555 BT_CTF_BYTE_ORDER_LITTLE_ENDIAN :
556 BT_CTF_BYTE_ORDER_BIG_ENDIAN));
557 if (ret) {
558 goto end;
559 }
560
561 ret = bt_ctf_field_type_structure_add_field(trace_packet_header_type,
562 _uint32_t, "magic");
563 if (ret) {
564 goto end;
565 }
566
567 ret = bt_ctf_field_type_structure_add_field(trace_packet_header_type,
568 uuid_array_type, "uuid");
569 if (ret) {
570 goto end;
571 }
572
573 ret = bt_ctf_field_type_structure_add_field(trace_packet_header_type,
574 _uint32_t, "stream_id");
575 if (ret) {
576 goto end;
577 }
578
d246b111
JG
579 bt_ctf_field_type_put(trace->packet_header_type);
580 trace->packet_header_type = trace_packet_header_type;
bc37ae52
JG
581end:
582 bt_ctf_field_type_put(uuid_array_type);
583 bt_ctf_field_type_put(_uint32_t);
584 bt_ctf_field_type_put(_uint8_t);
585 bt_ctf_field_put(magic);
586 bt_ctf_field_put(uuid_array);
587 if (ret) {
588 bt_ctf_field_type_put(trace_packet_header_type);
bc37ae52
JG
589 }
590
591 return ret;
592}
593
594static
595void environment_variable_destroy(struct environment_variable *var)
596{
597 g_string_free(var->name, TRUE);
598 g_string_free(var->value, TRUE);
599 g_free(var);
600}
This page took 0.045922 seconds and 4 git commands to generate.