Cleanup (messages): Make the wording of the signedness warning clearer
[babeltrace.git] / formats / ctf / ctf.c
CommitLineData
fc93b2bd
MD
1/*
2 * BabelTrace - Common Trace Format (CTF)
3 *
4 * Format registration.
5 *
64fa3fec
MD
6 * Copyright 2010-2011 EfficiOS Inc. and Linux Foundation
7 *
8 * Author: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
fc93b2bd 9 *
ccd7e1c8
MD
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:
fc93b2bd 16 *
ccd7e1c8
MD
17 * The above copyright notice and this permission notice shall be included in
18 * all copies or substantial portions of the Software.
fc93b2bd
MD
19 */
20
21#include <babeltrace/format.h>
22#include <babeltrace/ctf/types.h>
bbefb8dd 23#include <babeltrace/ctf/metadata.h>
70bd0a12 24#include <babeltrace/babeltrace-internal.h>
e4195791 25#include <babeltrace/ctf/events-internal.h>
98a04903
JD
26#include <babeltrace/trace-handle-internal.h>
27#include <babeltrace/context-internal.h>
43e34335
MD
28#include <babeltrace/uuid.h>
29#include <babeltrace/endian.h>
0f980a35 30#include <inttypes.h>
b4c19c1e 31#include <stdio.h>
0f980a35 32#include <sys/mman.h>
bbefb8dd 33#include <errno.h>
bbefb8dd 34#include <sys/types.h>
65102a8c 35#include <sys/stat.h>
bbefb8dd 36#include <fcntl.h>
65102a8c 37#include <dirent.h>
bbefb8dd 38#include <glib.h>
65102a8c
MD
39#include <unistd.h>
40#include <stdlib.h>
41
65102a8c
MD
42#include "metadata/ctf-scanner.h"
43#include "metadata/ctf-parser.h"
44#include "metadata/ctf-ast.h"
c34ea0fa 45#include "events-private.h"
f8370579 46#include "memstream.h"
65102a8c 47
0f980a35
MD
48/*
49 * We currently simply map a page to read the packet header and packet
8c572eba 50 * context to get the packet length and content length. (in bits)
0f980a35 51 */
8c572eba
MD
52#define MAX_PACKET_HEADER_LEN (getpagesize() * CHAR_BIT)
53#define WRITE_PACKET_LEN (getpagesize() * 8 * CHAR_BIT)
0f980a35 54
a0fe7d97
MD
55#ifndef min
56#define min(a, b) (((a) < (b)) ? (a) : (b))
57#endif
58
7d97fad9
MD
59#define NSEC_PER_SEC 1000000000ULL
60
61int opt_clock_raw,
62 opt_clock_seconds,
63 opt_clock_date,
64 opt_clock_gmt;
65
66uint64_t opt_clock_offset;
67
65102a8c 68extern int yydebug;
bbefb8dd 69
e9378815 70static
5b80ddfb 71struct trace_descriptor *ctf_open_trace(const char *path, int flags,
20d0dcf9
MD
72 void (*packet_seek)(struct stream_pos *pos, size_t index,
73 int whence),
74 FILE *metadata_fp);
e9378815 75static
f571dfb1
JD
76struct trace_descriptor *ctf_open_mmap_trace(
77 struct mmap_stream_list *mmap_list,
20d0dcf9
MD
78 void (*packet_seek)(struct stream_pos *pos, size_t index,
79 int whence),
f571dfb1 80 FILE *metadata_fp);
98a04903
JD
81static
82void ctf_set_context(struct trace_descriptor *descriptor,
83 struct bt_context *ctx);
84static
85void ctf_set_handle(struct trace_descriptor *descriptor,
86 struct bt_trace_handle *handle);
f571dfb1
JD
87
88static
bbefb8dd 89void ctf_close_trace(struct trace_descriptor *descriptor);
30c276af
JD
90static
91uint64_t ctf_timestamp_begin(struct trace_descriptor *descriptor,
92 struct bt_trace_handle *handle);
93static
94uint64_t ctf_timestamp_end(struct trace_descriptor *descriptor,
95 struct bt_trace_handle *handle);
fc93b2bd 96
1ae19169
MD
97static
98rw_dispatch read_dispatch_table[] = {
d11e9c49
MD
99 [ CTF_TYPE_INTEGER ] = ctf_integer_read,
100 [ CTF_TYPE_FLOAT ] = ctf_float_read,
101 [ CTF_TYPE_ENUM ] = ctf_enum_read,
102 [ CTF_TYPE_STRING ] = ctf_string_read,
103 [ CTF_TYPE_STRUCT ] = ctf_struct_rw,
104 [ CTF_TYPE_VARIANT ] = ctf_variant_rw,
81dee1bb
MD
105 [ CTF_TYPE_ARRAY ] = ctf_array_read,
106 [ CTF_TYPE_SEQUENCE ] = ctf_sequence_read,
d11e9c49
MD
107};
108
1ae19169
MD
109static
110rw_dispatch write_dispatch_table[] = {
d11e9c49
MD
111 [ CTF_TYPE_INTEGER ] = ctf_integer_write,
112 [ CTF_TYPE_FLOAT ] = ctf_float_write,
113 [ CTF_TYPE_ENUM ] = ctf_enum_write,
114 [ CTF_TYPE_STRING ] = ctf_string_write,
115 [ CTF_TYPE_STRUCT ] = ctf_struct_rw,
116 [ CTF_TYPE_VARIANT ] = ctf_variant_rw,
81dee1bb
MD
117 [ CTF_TYPE_ARRAY ] = ctf_array_write,
118 [ CTF_TYPE_SEQUENCE ] = ctf_sequence_write,
d11e9c49
MD
119};
120
1ae19169 121static
d11e9c49 122struct format ctf_format = {
bbefb8dd 123 .open_trace = ctf_open_trace,
f571dfb1 124 .open_mmap_trace = ctf_open_mmap_trace,
bbefb8dd 125 .close_trace = ctf_close_trace,
98a04903
JD
126 .set_context = ctf_set_context,
127 .set_handle = ctf_set_handle,
30c276af
JD
128 .timestamp_begin = ctf_timestamp_begin,
129 .timestamp_end = ctf_timestamp_end,
fc93b2bd
MD
130};
131
30c276af
JD
132static
133uint64_t ctf_timestamp_begin(struct trace_descriptor *descriptor,
134 struct bt_trace_handle *handle)
135{
136 struct ctf_trace *tin;
137 uint64_t begin = ULLONG_MAX;
138 int i, j;
139
140 tin = container_of(descriptor, struct ctf_trace, parent);
141
142 if (!tin)
143 goto error;
144
145 /* for each stream_class */
146 for (i = 0; i < tin->streams->len; i++) {
147 struct ctf_stream_declaration *stream_class;
148
149 stream_class = g_ptr_array_index(tin->streams, i);
1b01ffc2
MD
150 if (!stream_class)
151 continue;
30c276af
JD
152 /* for each file_stream */
153 for (j = 0; j < stream_class->streams->len; j++) {
154 struct ctf_stream_definition *stream;
155 struct ctf_file_stream *cfs;
156 struct ctf_stream_pos *stream_pos;
157 struct packet_index *index;
158
159 stream = g_ptr_array_index(stream_class->streams, j);
160 cfs = container_of(stream, struct ctf_file_stream,
161 parent);
162 stream_pos = &cfs->pos;
163
164 index = &g_array_index(stream_pos->packet_index,
165 struct packet_index, 0);
166 if (index->timestamp_begin < begin)
167 begin = index->timestamp_begin;
168 }
169 }
170
171 return begin;
172
173error:
174 return -1ULL;
175}
176
177static
178uint64_t ctf_timestamp_end(struct trace_descriptor *descriptor,
179 struct bt_trace_handle *handle)
180{
181 struct ctf_trace *tin;
182 uint64_t end = 0;
183 int i, j;
184
185 tin = container_of(descriptor, struct ctf_trace, parent);
186
187 if (!tin)
188 goto error;
189
190 /* for each stream_class */
191 for (i = 0; i < tin->streams->len; i++) {
192 struct ctf_stream_declaration *stream_class;
193
194 stream_class = g_ptr_array_index(tin->streams, i);
1b01ffc2
MD
195 if (!stream_class)
196 continue;
30c276af
JD
197 /* for each file_stream */
198 for (j = 0; j < stream_class->streams->len; j++) {
199 struct ctf_stream_definition *stream;
200 struct ctf_file_stream *cfs;
201 struct ctf_stream_pos *stream_pos;
202 struct packet_index *index;
203
204 stream = g_ptr_array_index(stream_class->streams, j);
205 cfs = container_of(stream, struct ctf_file_stream,
206 parent);
207 stream_pos = &cfs->pos;
208
209 index = &g_array_index(stream_pos->packet_index,
210 struct packet_index,
211 stream_pos->packet_index->len - 1);
212 if (index->timestamp_end > end)
213 end = index->timestamp_end;
214 }
215 }
216
217 return end;
218
219error:
220 return -1ULL;
221}
222
25ccc85b
MD
223/*
224 * Update stream current timestamp, keep at clock frequency.
225 */
2b9a764d 226static
9e88d150 227void ctf_update_timestamp(struct ctf_stream_definition *stream,
2b9a764d
MD
228 struct definition_integer *integer_definition)
229{
230 struct declaration_integer *integer_declaration =
231 integer_definition->declaration;
232 uint64_t oldval, newval, updateval;
233
7f3f572b 234 if (unlikely(integer_declaration->len == 64)) {
2b9a764d
MD
235 stream->timestamp = integer_definition->value._unsigned;
236 return;
237 }
238 /* keep low bits */
239 oldval = stream->timestamp;
240 oldval &= (1ULL << integer_declaration->len) - 1;
241 newval = integer_definition->value._unsigned;
242 /* Test for overflow by comparing low bits */
243 if (newval < oldval)
244 newval += 1ULL << integer_declaration->len;
245 /* updateval contains old high bits, and new low bits (sum) */
246 updateval = stream->timestamp;
247 updateval &= ~((1ULL << integer_declaration->len) - 1);
248 updateval += newval;
fca04958 249 stream->prev_timestamp = stream->timestamp;
2b9a764d
MD
250 stream->timestamp = updateval;
251}
252
25ccc85b
MD
253/*
254 * Print timestamp, rescaling clock frequency to nanoseconds and
255 * applying offsets as needed (unix time).
256 */
7d97fad9 257void ctf_print_timestamp(FILE *fp,
9e88d150 258 struct ctf_stream_definition *stream,
7d97fad9
MD
259 uint64_t timestamp)
260{
261 uint64_t ts_sec = 0, ts_nsec;
7d97fad9 262
c34ea0fa
MD
263 if (opt_clock_raw) {
264 ts_nsec = ctf_get_timestamp_raw(stream, timestamp);
25ccc85b 265 } else {
c34ea0fa 266 ts_nsec = ctf_get_timestamp(stream, timestamp);
25ccc85b 267 }
7d97fad9 268
c34ea0fa 269 /* Add command-line offset */
7d97fad9
MD
270 ts_sec += opt_clock_offset;
271
272 ts_sec += ts_nsec / NSEC_PER_SEC;
273 ts_nsec = ts_nsec % NSEC_PER_SEC;
274
275 if (!opt_clock_seconds) {
276 struct tm tm;
277 time_t time_s = (time_t) ts_sec;
278
279 if (!opt_clock_gmt) {
280 struct tm *res;
281
282 res = localtime_r(&time_s, &tm);
283 if (!res) {
284 fprintf(stderr, "[warning] Unable to get localtime.\n");
285 goto seconds;
286 }
287 } else {
288 struct tm *res;
289
290 res = gmtime_r(&time_s, &tm);
291 if (!res) {
292 fprintf(stderr, "[warning] Unable to get gmtime.\n");
293 goto seconds;
294 }
295 }
296 if (opt_clock_date) {
297 char timestr[26];
298 size_t res;
299
300 /* Print date and time */
301 res = strftime(timestr, sizeof(timestr),
302 "%F ", &tm);
303 if (!res) {
304 fprintf(stderr, "[warning] Unable to print ascii time.\n");
305 goto seconds;
306 }
307 fprintf(fp, "%s", timestr);
308 }
309 /* Print time in HH:MM:SS.ns */
310 fprintf(fp, "%02d:%02d:%02d.%09" PRIu64,
311 tm.tm_hour, tm.tm_min, tm.tm_sec, ts_nsec);
312 goto end;
313 }
314seconds:
315 fprintf(fp, "%3" PRIu64 ".%09" PRIu64,
316 ts_sec, ts_nsec);
317
318end:
319 return;
320}
321
31262354 322static
9e88d150 323int ctf_read_event(struct stream_pos *ppos, struct ctf_stream_definition *stream)
31262354
MD
324{
325 struct ctf_stream_pos *pos =
326 container_of(ppos, struct ctf_stream_pos, parent);
f380e105 327 struct ctf_stream_declaration *stream_class = stream->stream_class;
c716f83b 328 struct ctf_event_definition *event;
31262354 329 uint64_t id = 0;
31262354
MD
330 int ret;
331
3abe83c7
MD
332 /* We need to check for EOF here for empty files. */
333 if (unlikely(pos->offset == EOF))
334 return EOF;
335
5f643ed7
MD
336 ctf_pos_get_event(pos);
337
90fcbacc
JD
338 /* save the current position as a restore point */
339 pos->last_offset = pos->offset;
90fcbacc 340
3abe83c7
MD
341 /*
342 * This is the EOF check after we've advanced the position in
343 * ctf_pos_get_event.
344 */
7f3f572b 345 if (unlikely(pos->offset == EOF))
31262354 346 return EOF;
5f643ed7 347 assert(pos->offset < pos->content_size);
31262354
MD
348
349 /* Read event header */
7f3f572b 350 if (likely(stream->stream_event_header)) {
a35173fe 351 struct definition_integer *integer_definition;
ccdb988e 352 struct definition *variant;
a35173fe 353
e28d4618 354 ret = generic_rw(ppos, &stream->stream_event_header->p);
7f3f572b 355 if (unlikely(ret))
31262354
MD
356 goto error;
357 /* lookup event id */
e28d4618 358 integer_definition = lookup_integer(&stream->stream_event_header->p, "id", FALSE);
a35173fe
MD
359 if (integer_definition) {
360 id = integer_definition->value._unsigned;
361 } else {
362 struct definition_enum *enum_definition;
363
e28d4618 364 enum_definition = lookup_enum(&stream->stream_event_header->p, "id", FALSE);
a35173fe
MD
365 if (enum_definition) {
366 id = enum_definition->integer->value._unsigned;
367 }
31262354 368 }
764af3f4 369
e28d4618 370 variant = lookup_variant(&stream->stream_event_header->p, "v");
ccdb988e
MD
371 if (variant) {
372 integer_definition = lookup_integer(variant, "id", FALSE);
373 if (integer_definition) {
374 id = integer_definition->value._unsigned;
375 }
376 }
c87a8eb2 377 stream->event_id = id;
ccdb988e 378
764af3f4 379 /* lookup timestamp */
5e2eb0ae 380 stream->has_timestamp = 0;
e28d4618 381 integer_definition = lookup_integer(&stream->stream_event_header->p, "timestamp", FALSE);
a35173fe 382 if (integer_definition) {
2b9a764d 383 ctf_update_timestamp(stream, integer_definition);
5e2eb0ae 384 stream->has_timestamp = 1;
a35173fe 385 } else {
ccdb988e
MD
386 if (variant) {
387 integer_definition = lookup_integer(variant, "timestamp", FALSE);
a35173fe 388 if (integer_definition) {
2b9a764d 389 ctf_update_timestamp(stream, integer_definition);
5e2eb0ae 390 stream->has_timestamp = 1;
a35173fe
MD
391 }
392 }
764af3f4 393 }
31262354
MD
394 }
395
396 /* Read stream-declared event context */
e28d4618
MD
397 if (stream->stream_event_context) {
398 ret = generic_rw(ppos, &stream->stream_event_context->p);
31262354
MD
399 if (ret)
400 goto error;
401 }
402
7f3f572b 403 if (unlikely(id >= stream_class->events_by_id->len)) {
3394d22e 404 fprintf(stderr, "[error] Event id %" PRIu64 " is outside range.\n", id);
31262354
MD
405 return -EINVAL;
406 }
e28d4618 407 event = g_ptr_array_index(stream->events_by_id, id);
7f3f572b 408 if (unlikely(!event)) {
3394d22e 409 fprintf(stderr, "[error] Event id %" PRIu64 " is unknown.\n", id);
31262354
MD
410 return -EINVAL;
411 }
412
413 /* Read event-declared event context */
e28d4618
MD
414 if (event->event_context) {
415 ret = generic_rw(ppos, &event->event_context->p);
31262354
MD
416 if (ret)
417 goto error;
418 }
419
420 /* Read event payload */
7f3f572b 421 if (likely(event->event_fields)) {
e28d4618 422 ret = generic_rw(ppos, &event->event_fields->p);
31262354
MD
423 if (ret)
424 goto error;
425 }
426
427 return 0;
428
429error:
3394d22e 430 fprintf(stderr, "[error] Unexpected end of stream. Either the trace data stream is corrupted or metadata description does not match data layout.\n");
31262354
MD
431 return ret;
432}
433
434static
9e88d150 435int ctf_write_event(struct stream_pos *pos, struct ctf_stream_definition *stream)
31262354 436{
f380e105 437 struct ctf_stream_declaration *stream_class = stream->stream_class;
c716f83b 438 struct ctf_event_definition *event;
c87a8eb2 439 uint64_t id;
31262354
MD
440 int ret;
441
c87a8eb2
MD
442 id = stream->event_id;
443
31262354 444 /* print event header */
7f3f572b 445 if (likely(stream->stream_event_header)) {
e28d4618 446 ret = generic_rw(pos, &stream->stream_event_header->p);
31262354
MD
447 if (ret)
448 goto error;
449 }
450
451 /* print stream-declared event context */
e28d4618
MD
452 if (stream->stream_event_context) {
453 ret = generic_rw(pos, &stream->stream_event_context->p);
31262354
MD
454 if (ret)
455 goto error;
456 }
457
7f3f572b 458 if (unlikely(id >= stream_class->events_by_id->len)) {
3394d22e 459 fprintf(stderr, "[error] Event id %" PRIu64 " is outside range.\n", id);
31262354
MD
460 return -EINVAL;
461 }
e28d4618 462 event = g_ptr_array_index(stream->events_by_id, id);
7f3f572b 463 if (unlikely(!event)) {
3394d22e 464 fprintf(stderr, "[error] Event id %" PRIu64 " is unknown.\n", id);
31262354
MD
465 return -EINVAL;
466 }
467
468 /* print event-declared event context */
e28d4618
MD
469 if (event->event_context) {
470 ret = generic_rw(pos, &event->event_context->p);
31262354
MD
471 if (ret)
472 goto error;
473 }
474
475 /* Read and print event payload */
7f3f572b 476 if (likely(event->event_fields)) {
e28d4618 477 ret = generic_rw(pos, &event->event_fields->p);
31262354
MD
478 if (ret)
479 goto error;
480 }
481
482 return 0;
483
484error:
3394d22e 485 fprintf(stderr, "[error] Unexpected end of stream. Either the trace data stream is corrupted or metadata description does not match data layout.\n");
31262354
MD
486 return ret;
487}
488
8563e754 489void ctf_init_pos(struct ctf_stream_pos *pos, int fd, int open_flags)
8c572eba
MD
490{
491 pos->fd = fd;
492 pos->mmap_offset = 0;
493 pos->packet_size = 0;
494 pos->content_size = 0;
495 pos->content_size_loc = NULL;
aee35fcc 496 pos->base_mma = NULL;
8c572eba
MD
497 pos->offset = 0;
498 pos->dummy = false;
8c572eba 499 pos->cur_index = 0;
8563e754
MD
500 if (fd >= 0)
501 pos->packet_index = g_array_new(FALSE, TRUE,
502 sizeof(struct packet_index));
503 else
504 pos->packet_index = NULL;
8563e754
MD
505 switch (open_flags & O_ACCMODE) {
506 case O_RDONLY:
507 pos->prot = PROT_READ;
508 pos->flags = MAP_PRIVATE;
509 pos->parent.rw_table = read_dispatch_table;
31262354 510 pos->parent.event_cb = ctf_read_event;
8563e754 511 break;
8563e754
MD
512 case O_RDWR:
513 pos->prot = PROT_WRITE; /* Write has priority */
514 pos->flags = MAP_SHARED;
515 pos->parent.rw_table = write_dispatch_table;
31262354 516 pos->parent.event_cb = ctf_write_event;
8563e754 517 if (fd >= 0)
06789ffd 518 ctf_packet_seek(&pos->parent, 0, SEEK_SET); /* position for write */
8563e754
MD
519 break;
520 default:
521 assert(0);
8c572eba
MD
522 }
523}
524
46322b33 525void ctf_fini_pos(struct ctf_stream_pos *pos)
8c572eba
MD
526{
527 int ret;
528
529 if (pos->prot == PROT_WRITE && pos->content_size_loc)
530 *pos->content_size_loc = pos->offset;
aee35fcc 531 if (pos->base_mma) {
8c572eba 532 /* unmap old base */
aee35fcc 533 ret = munmap_align(pos->base_mma);
8c572eba 534 if (ret) {
3394d22e 535 fprintf(stderr, "[error] Unable to unmap old base: %s.\n",
8c572eba
MD
536 strerror(errno));
537 assert(0);
538 }
539 }
540 (void) g_array_free(pos->packet_index, TRUE);
541}
542
20d0dcf9
MD
543/*
544 * for SEEK_CUR: go to next packet.
545 * for SEEK_POS: go to packet numer (index).
546 */
547void ctf_packet_seek(struct stream_pos *stream_pos, size_t index, int whence)
0f980a35 548{
d6425aaf
MD
549 struct ctf_stream_pos *pos =
550 container_of(stream_pos, struct ctf_stream_pos, parent);
75cc2c35
MD
551 struct ctf_file_stream *file_stream =
552 container_of(pos, struct ctf_file_stream, pos);
0f980a35 553 int ret;
8c572eba 554 off_t off;
20d0dcf9 555 struct packet_index *packet_index;
0f980a35 556
8c572eba
MD
557 if (pos->prot == PROT_WRITE && pos->content_size_loc)
558 *pos->content_size_loc = pos->offset;
0f980a35 559
aee35fcc 560 if (pos->base_mma) {
0f980a35 561 /* unmap old base */
aee35fcc 562 ret = munmap_align(pos->base_mma);
0f980a35 563 if (ret) {
3394d22e 564 fprintf(stderr, "[error] Unable to unmap old base: %s.\n",
0f980a35
MD
565 strerror(errno));
566 assert(0);
567 }
aee35fcc 568 pos->base_mma = NULL;
0f980a35
MD
569 }
570
8c572eba 571 /*
46322b33 572 * The caller should never ask for ctf_move_pos across packets,
8c572eba
MD
573 * except to get exactly at the beginning of the next packet.
574 */
575 if (pos->prot == PROT_WRITE) {
989c73bc
MD
576 switch (whence) {
577 case SEEK_CUR:
578 /* The writer will add padding */
8c572eba 579 pos->mmap_offset += WRITE_PACKET_LEN / CHAR_BIT;
989c73bc
MD
580 break;
581 case SEEK_SET:
20d0dcf9 582 assert(index == 0); /* only seek supported for now */
989c73bc
MD
583 pos->cur_index = 0;
584 break;
585 default:
586 assert(0);
587 }
8c572eba
MD
588 pos->content_size = -1U; /* Unknown at this point */
589 pos->packet_size = WRITE_PACKET_LEN;
989c73bc
MD
590 off = posix_fallocate(pos->fd, pos->mmap_offset,
591 pos->packet_size / CHAR_BIT);
8c572eba 592 assert(off >= 0);
847bf71a 593 pos->offset = 0;
8c572eba 594 } else {
5f643ed7 595 read_next_packet:
847bf71a
MD
596 switch (whence) {
597 case SEEK_CUR:
41e82e00 598 {
4c4ba021 599 uint64_t events_discarded_diff;
41e82e00 600
7d97fad9
MD
601 if (pos->offset == EOF) {
602 return;
603 }
3217ac37 604 /* For printing discarded event count */
20d0dcf9 605 packet_index = &g_array_index(pos->packet_index,
41e82e00 606 struct packet_index, pos->cur_index);
20d0dcf9 607 events_discarded_diff = packet_index->events_discarded;
3217ac37 608 file_stream->parent.prev_timestamp_end =
20d0dcf9 609 packet_index->timestamp_end;
41e82e00 610 if (pos->cur_index > 0) {
20d0dcf9 611 packet_index = &g_array_index(pos->packet_index,
41e82e00
MD
612 struct packet_index,
613 pos->cur_index - 1);
20d0dcf9 614 events_discarded_diff -= packet_index->events_discarded;
4c4ba021
MD
615 /*
616 * Deal with 32-bit wrap-around if the
617 * tracer provided a 32-bit field.
618 */
619 if (packet_index->events_discarded_len == 32) {
620 events_discarded_diff = (uint32_t) events_discarded_diff;
621 }
41e82e00 622 }
fca04958 623 file_stream->parent.events_discarded = events_discarded_diff;
7d97fad9 624 file_stream->parent.prev_timestamp = file_stream->parent.timestamp;
847bf71a 625 /* The reader will expect us to skip padding */
8c572eba 626 ++pos->cur_index;
847bf71a 627 break;
41e82e00 628 }
847bf71a 629 case SEEK_SET:
20d0dcf9 630 pos->cur_index = index;
fca04958 631 file_stream->parent.prev_timestamp = 0;
3217ac37 632 file_stream->parent.prev_timestamp_end = 0;
847bf71a
MD
633 break;
634 default:
635 assert(0);
636 }
637 if (pos->cur_index >= pos->packet_index->len) {
7d97fad9
MD
638 /*
639 * When a stream reaches the end of the
640 * file, we need to show the number of
641 * events discarded ourselves, because
642 * there is no next event scheduled to
643 * be printed in the output.
644 */
645 if (file_stream->parent.events_discarded) {
badea1a2
JD
646 /*
647 * We need to check if we are in trace
648 * read or called from packet indexing.
649 * In this last case, the collection is
650 * not there, so we cannot print the
651 * timestamps.
652 */
653 if ((&file_stream->parent)->stream_class->trace->collection) {
654 fflush(stdout);
4c4ba021 655 fprintf(stderr, "[warning] Tracer discarded %" PRIu64 " events at end of stream between [",
badea1a2
JD
656 file_stream->parent.events_discarded);
657 ctf_print_timestamp(stderr, &file_stream->parent,
658 file_stream->parent.prev_timestamp);
659 fprintf(stderr, "] and [");
660 ctf_print_timestamp(stderr, &file_stream->parent,
661 file_stream->parent.prev_timestamp_end);
a0b34fbb 662 fprintf(stderr, "]. You should consider recording a new trace with larger buffers or with fewer events enabled.\n");
badea1a2
JD
663 fflush(stderr);
664 }
7d97fad9
MD
665 file_stream->parent.events_discarded = 0;
666 }
670977d3 667 pos->offset = EOF;
847bf71a
MD
668 return;
669 }
20d0dcf9 670 packet_index = &g_array_index(pos->packet_index, struct packet_index,
8c572eba 671 pos->cur_index);
20d0dcf9 672 pos->mmap_offset = packet_index->offset;
8c572eba
MD
673
674 /* Lookup context/packet size in index */
20d0dcf9
MD
675 file_stream->parent.timestamp = packet_index->timestamp_begin;
676 pos->content_size = packet_index->content_size;
677 pos->packet_size = packet_index->packet_size;
678 if (packet_index->data_offset < packet_index->content_size) {
75cc2c35 679 pos->offset = 0; /* will read headers */
20d0dcf9 680 } else if (packet_index->data_offset == packet_index->content_size) {
5f643ed7 681 /* empty packet */
20d0dcf9 682 pos->offset = packet_index->data_offset;
3abe83c7 683 whence = SEEK_CUR;
5f643ed7 684 goto read_next_packet;
7eda6fc7 685 } else {
2b9a764d
MD
686 pos->offset = EOF;
687 return;
688 }
8c572eba 689 }
0f980a35 690 /* map new base. Need mapping length from header. */
aee35fcc
MD
691 pos->base_mma = mmap_align(pos->packet_size / CHAR_BIT, pos->prot,
692 pos->flags, pos->fd, pos->mmap_offset);
693 if (pos->base_mma == MAP_FAILED) {
3394d22e 694 fprintf(stderr, "[error] mmap error %s.\n",
847bf71a
MD
695 strerror(errno));
696 assert(0);
697 }
75cc2c35
MD
698
699 /* update trace_packet_header and stream_packet_context */
2d0bea29 700 if (pos->prot != PROT_WRITE && file_stream->parent.trace_packet_header) {
75cc2c35 701 /* Read packet header */
2d0bea29 702 ret = generic_rw(&pos->parent, &file_stream->parent.trace_packet_header->p);
75cc2c35
MD
703 assert(!ret);
704 }
2d0bea29 705 if (pos->prot != PROT_WRITE && file_stream->parent.stream_packet_context) {
75cc2c35 706 /* Read packet context */
2d0bea29 707 ret = generic_rw(&pos->parent, &file_stream->parent.stream_packet_context->p);
75cc2c35
MD
708 assert(!ret);
709 }
0f980a35
MD
710}
711
b4c19c1e
MD
712static
713int packet_metadata(struct ctf_trace *td, FILE *fp)
714{
715 uint32_t magic;
716 size_t len;
717 int ret = 0;
718
719 len = fread(&magic, sizeof(magic), 1, fp);
a0fe7d97 720 if (len != 1) {
b4c19c1e
MD
721 goto end;
722 }
723 if (magic == TSDL_MAGIC) {
724 ret = 1;
725 td->byte_order = BYTE_ORDER;
0d336fdf 726 CTF_TRACE_SET_FIELD(td, byte_order);
b4c19c1e
MD
727 } else if (magic == GUINT32_SWAP_LE_BE(TSDL_MAGIC)) {
728 ret = 1;
729 td->byte_order = (BYTE_ORDER == BIG_ENDIAN) ?
730 LITTLE_ENDIAN : BIG_ENDIAN;
0d336fdf 731 CTF_TRACE_SET_FIELD(td, byte_order);
b4c19c1e
MD
732 }
733end:
734 rewind(fp);
735 return ret;
736}
737
5c262147
MD
738/*
739 * Returns 0 on success, -1 on error.
740 */
741static
742int check_version(unsigned int major, unsigned int minor)
743{
744 switch (major) {
745 case 1:
746 switch (minor) {
747 case 8:
748 return 0;
749 default:
750 goto warning;
751 }
752 default:
753 goto warning;
754
755 }
756
757 /* eventually return an error instead of warning */
758warning:
3394d22e 759 fprintf(stderr, "[warning] Unsupported CTF specification version %u.%u. Trying anyway.\n",
5c262147
MD
760 major, minor);
761 return 0;
762}
763
b4c19c1e
MD
764static
765int ctf_open_trace_metadata_packet_read(struct ctf_trace *td, FILE *in,
766 FILE *out)
767{
768 struct metadata_packet_header header;
a0fe7d97 769 size_t readlen, writelen, toread;
f8254867 770 char buf[4096 + 1]; /* + 1 for debug-mode \0 */
b4c19c1e
MD
771 int ret = 0;
772
a91a962e 773 readlen = fread(&header, header_sizeof(header), 1, in);
a0fe7d97 774 if (readlen < 1)
b4c19c1e
MD
775 return -EINVAL;
776
777 if (td->byte_order != BYTE_ORDER) {
778 header.magic = GUINT32_SWAP_LE_BE(header.magic);
779 header.checksum = GUINT32_SWAP_LE_BE(header.checksum);
780 header.content_size = GUINT32_SWAP_LE_BE(header.content_size);
781 header.packet_size = GUINT32_SWAP_LE_BE(header.packet_size);
782 }
783 if (header.checksum)
3394d22e 784 fprintf(stderr, "[warning] checksum verification not supported yet.\n");
b4c19c1e 785 if (header.compression_scheme) {
3394d22e 786 fprintf(stderr, "[error] compression (%u) not supported yet.\n",
b4c19c1e
MD
787 header.compression_scheme);
788 return -EINVAL;
789 }
790 if (header.encryption_scheme) {
3394d22e 791 fprintf(stderr, "[error] encryption (%u) not supported yet.\n",
b4c19c1e
MD
792 header.encryption_scheme);
793 return -EINVAL;
794 }
795 if (header.checksum_scheme) {
3394d22e 796 fprintf(stderr, "[error] checksum (%u) not supported yet.\n",
b4c19c1e
MD
797 header.checksum_scheme);
798 return -EINVAL;
799 }
5c262147
MD
800 if (check_version(header.major, header.minor) < 0)
801 return -EINVAL;
b4c19c1e
MD
802 if (!CTF_TRACE_FIELD_IS_SET(td, uuid)) {
803 memcpy(td->uuid, header.uuid, sizeof(header.uuid));
804 CTF_TRACE_SET_FIELD(td, uuid);
805 } else {
43e34335 806 if (babeltrace_uuid_compare(header.uuid, td->uuid))
b4c19c1e
MD
807 return -EINVAL;
808 }
809
255b2138 810 toread = (header.content_size / CHAR_BIT) - header_sizeof(header);
a0fe7d97
MD
811
812 for (;;) {
f8254867 813 readlen = fread(buf, sizeof(char), min(sizeof(buf) - 1, toread), in);
b4c19c1e
MD
814 if (ferror(in)) {
815 ret = -EINVAL;
816 break;
817 }
4152822b 818 if (babeltrace_debug) {
f8254867 819 buf[readlen] = '\0';
3394d22e 820 fprintf(stderr, "[debug] metadata packet read: %s\n",
4152822b
MD
821 buf);
822 }
823
b4c19c1e
MD
824 writelen = fwrite(buf, sizeof(char), readlen, out);
825 if (writelen < readlen) {
826 ret = -EIO;
827 break;
828 }
829 if (ferror(out)) {
830 ret = -EINVAL;
831 break;
832 }
a0fe7d97
MD
833 toread -= readlen;
834 if (!toread) {
7f4b5c4d 835 ret = 0; /* continue reading next packet */
ddbc52af 836 goto read_padding;
a0fe7d97 837 }
b4c19c1e
MD
838 }
839 return ret;
ddbc52af
MD
840
841read_padding:
842 toread = (header.packet_size - header.content_size) / CHAR_BIT;
843 ret = fseek(in, toread, SEEK_CUR);
844 if (ret < 0) {
3394d22e 845 fprintf(stderr, "[warning] Missing padding at end of file\n");
ddbc52af
MD
846 ret = 0;
847 }
848 return ret;
b4c19c1e
MD
849}
850
851static
852int ctf_open_trace_metadata_stream_read(struct ctf_trace *td, FILE **fp,
853 char **buf)
854{
855 FILE *in, *out;
856 size_t size;
857 int ret;
858
859 in = *fp;
c4f5487e
MD
860 /*
861 * Using strlen on *buf instead of size of open_memstream
862 * because its size includes garbage at the end (after final
863 * \0). This is the allocated size, not the actual string size.
864 */
f8370579 865 out = babeltrace_open_memstream(buf, &size);
a569a564
MD
866 if (out == NULL) {
867 perror("Metadata open_memstream");
b4c19c1e 868 return -errno;
a569a564 869 }
b4c19c1e
MD
870 for (;;) {
871 ret = ctf_open_trace_metadata_packet_read(td, in, out);
7f4b5c4d 872 if (ret) {
b4c19c1e 873 break;
7f4b5c4d
MD
874 }
875 if (feof(in)) {
876 ret = 0;
b4c19c1e
MD
877 break;
878 }
879 }
f8370579
MD
880 /* close to flush the buffer */
881 ret = babeltrace_close_memstream(buf, &size, out);
882 if (ret < 0) {
883 perror("babeltrace_flush_memstream");
884 fclose(in);
885 return -errno;
886 }
b4c19c1e
MD
887 fclose(in);
888 /* open for reading */
f8370579 889 *fp = babeltrace_fmemopen(*buf, strlen(*buf), "rb");
a569a564
MD
890 if (!*fp) {
891 perror("Metadata fmemopen");
892 return -errno;
893 }
b4c19c1e
MD
894 return 0;
895}
896
65102a8c 897static
b086c01a 898int ctf_open_trace_metadata_read(struct ctf_trace *td,
20d0dcf9 899 void (*packet_seek)(struct stream_pos *pos, size_t index,
ae23d232 900 int whence), FILE *metadata_fp)
65102a8c
MD
901{
902 struct ctf_scanner *scanner;
2d0bea29 903 struct ctf_file_stream *metadata_stream;
65102a8c 904 FILE *fp;
b4c19c1e 905 char *buf = NULL;
65102a8c
MD
906 int ret = 0;
907
2d0bea29 908 metadata_stream = g_new0(struct ctf_file_stream, 1);
3a25e036 909 metadata_stream->pos.last_offset = LAST_OFFSET_POISON;
b086c01a 910
06789ffd
MD
911 if (packet_seek) {
912 metadata_stream->pos.packet_seek = packet_seek;
b086c01a 913 } else {
06789ffd 914 fprintf(stderr, "[error] packet_seek function undefined.\n");
b086c01a
JD
915 ret = -1;
916 goto end_stream;
917 }
918
ae23d232
JD
919 if (metadata_fp) {
920 fp = metadata_fp;
921 } else {
922 td->metadata = &metadata_stream->parent;
923 metadata_stream->pos.fd = openat(td->dirfd, "metadata", O_RDONLY);
924 if (metadata_stream->pos.fd < 0) {
3394d22e 925 fprintf(stderr, "Unable to open metadata.\n");
ae23d232
JD
926 return metadata_stream->pos.fd;
927 }
65102a8c 928
ae23d232
JD
929 fp = fdopen(metadata_stream->pos.fd, "r");
930 if (!fp) {
3394d22e 931 fprintf(stderr, "[error] Unable to open metadata stream.\n");
a569a564 932 perror("Metadata stream open");
ae23d232
JD
933 ret = -errno;
934 goto end_stream;
935 }
936 }
65102a8c
MD
937 if (babeltrace_debug)
938 yydebug = 1;
939
b4c19c1e
MD
940 if (packet_metadata(td, fp)) {
941 ret = ctf_open_trace_metadata_stream_read(td, &fp, &buf);
942 if (ret)
943 goto end_packet_read;
da75b0f7 944 } else {
5c262147
MD
945 unsigned int major, minor;
946 ssize_t nr_items;
8c2df3f5 947
da75b0f7 948 td->byte_order = BYTE_ORDER;
8c2df3f5 949
5c262147
MD
950 /* Check text-only metadata header and version */
951 nr_items = fscanf(fp, "/* CTF %u.%u", &major, &minor);
952 if (nr_items < 2)
3394d22e 953 fprintf(stderr, "[warning] Ill-shapen or missing \"/* CTF x.y\" header for text-only metadata.\n");
5c262147
MD
954 if (check_version(major, minor) < 0) {
955 ret = -EINVAL;
956 goto end_packet_read;
957 }
8c2df3f5 958 rewind(fp);
b4c19c1e
MD
959 }
960
65102a8c
MD
961 scanner = ctf_scanner_alloc(fp);
962 if (!scanner) {
3394d22e 963 fprintf(stderr, "[error] Error allocating scanner\n");
65102a8c
MD
964 ret = -ENOMEM;
965 goto end_scanner_alloc;
966 }
967 ret = ctf_scanner_append_ast(scanner);
968 if (ret) {
3394d22e 969 fprintf(stderr, "[error] Error creating AST\n");
65102a8c
MD
970 goto end;
971 }
972
973 if (babeltrace_debug) {
3394d22e 974 ret = ctf_visitor_print_xml(stderr, 0, &scanner->ast->root);
65102a8c 975 if (ret) {
3394d22e 976 fprintf(stderr, "[error] Error visiting AST for XML output\n");
65102a8c
MD
977 goto end;
978 }
979 }
980
3394d22e 981 ret = ctf_visitor_semantic_check(stderr, 0, &scanner->ast->root);
65102a8c 982 if (ret) {
3394d22e 983 fprintf(stderr, "[error] Error in CTF semantic validation %d\n", ret);
65102a8c
MD
984 goto end;
985 }
3394d22e 986 ret = ctf_visitor_construct_metadata(stderr, 0, &scanner->ast->root,
ac5c6ca0 987 td, td->byte_order);
65102a8c 988 if (ret) {
3394d22e 989 fprintf(stderr, "[error] Error in CTF metadata constructor %d\n", ret);
65102a8c
MD
990 goto end;
991 }
992end:
993 ctf_scanner_free(scanner);
994end_scanner_alloc:
b4c19c1e 995end_packet_read:
8210f9da
MD
996 if (fp)
997 fclose(fp);
b4c19c1e 998 free(buf);
65102a8c 999end_stream:
2d0bea29
MD
1000 close(metadata_stream->pos.fd);
1001 if (ret)
1002 g_free(metadata_stream);
0f980a35
MD
1003 return ret;
1004}
1005
e28d4618 1006static
c716f83b 1007struct ctf_event_definition *create_event_definitions(struct ctf_trace *td,
9e88d150 1008 struct ctf_stream_definition *stream,
4716614a 1009 struct ctf_event_declaration *event)
e28d4618 1010{
c716f83b 1011 struct ctf_event_definition *stream_event = g_new0(struct ctf_event_definition, 1);
e28d4618
MD
1012
1013 if (event->context_decl) {
1014 struct definition *definition =
1015 event->context_decl->p.definition_new(&event->context_decl->p,
1016 stream->parent_def_scope, 0, 0, "event.context");
1017 if (!definition) {
1018 goto error;
1019 }
42dc00b7 1020 stream_event->event_context = container_of(definition,
e28d4618 1021 struct definition_struct, p);
42dc00b7 1022 stream->parent_def_scope = stream_event->event_context->p.scope;
e28d4618
MD
1023 }
1024 if (event->fields_decl) {
1025 struct definition *definition =
1026 event->fields_decl->p.definition_new(&event->fields_decl->p,
1027 stream->parent_def_scope, 0, 0, "event.fields");
1028 if (!definition) {
1029 goto error;
1030 }
42dc00b7 1031 stream_event->event_fields = container_of(definition,
e28d4618 1032 struct definition_struct, p);
42dc00b7 1033 stream->parent_def_scope = stream_event->event_fields->p.scope;
e28d4618 1034 }
d3ded99d 1035 stream_event->stream = stream;
42dc00b7 1036 return stream_event;
e28d4618
MD
1037
1038error:
42dc00b7
MD
1039 if (stream_event->event_fields)
1040 definition_unref(&stream_event->event_fields->p);
1041 if (stream_event->event_context)
1042 definition_unref(&stream_event->event_context->p);
e28d4618
MD
1043 return NULL;
1044}
1045
1046static
9e88d150 1047int create_stream_definitions(struct ctf_trace *td, struct ctf_stream_definition *stream)
e28d4618 1048{
f380e105 1049 struct ctf_stream_declaration *stream_class;
e28d4618
MD
1050 int ret;
1051 int i;
1052
1053 if (stream->stream_definitions_created)
1054 return 0;
1055
1056 stream_class = stream->stream_class;
1057
1058 if (stream_class->packet_context_decl) {
1059 struct definition *definition =
1060 stream_class->packet_context_decl->p.definition_new(&stream_class->packet_context_decl->p,
1061 stream->parent_def_scope, 0, 0, "stream.packet.context");
1062 if (!definition) {
1063 ret = -EINVAL;
1064 goto error;
1065 }
1066 stream->stream_packet_context = container_of(definition,
1067 struct definition_struct, p);
1068 stream->parent_def_scope = stream->stream_packet_context->p.scope;
1069 }
1070 if (stream_class->event_header_decl) {
1071 struct definition *definition =
1072 stream_class->event_header_decl->p.definition_new(&stream_class->event_header_decl->p,
1073 stream->parent_def_scope, 0, 0, "stream.event.header");
1074 if (!definition) {
1075 ret = -EINVAL;
1076 goto error;
1077 }
1078 stream->stream_event_header =
1079 container_of(definition, struct definition_struct, p);
1080 stream->parent_def_scope = stream->stream_event_header->p.scope;
1081 }
1082 if (stream_class->event_context_decl) {
1083 struct definition *definition =
1084 stream_class->event_context_decl->p.definition_new(&stream_class->event_context_decl->p,
1085 stream->parent_def_scope, 0, 0, "stream.event.context");
1086 if (!definition) {
1087 ret = -EINVAL;
1088 goto error;
1089 }
1090 stream->stream_event_context =
1091 container_of(definition, struct definition_struct, p);
1092 stream->parent_def_scope = stream->stream_event_context->p.scope;
1093 }
1094 stream->events_by_id = g_ptr_array_new();
1095 g_ptr_array_set_size(stream->events_by_id, stream_class->events_by_id->len);
1096 for (i = 0; i < stream->events_by_id->len; i++) {
4716614a 1097 struct ctf_event_declaration *event = g_ptr_array_index(stream_class->events_by_id, i);
c716f83b 1098 struct ctf_event_definition *stream_event;
e28d4618
MD
1099
1100 if (!event)
1101 continue;
42dc00b7
MD
1102 stream_event = create_event_definitions(td, stream, event);
1103 if (!stream_event)
e28d4618 1104 goto error_event;
42dc00b7 1105 g_ptr_array_index(stream->events_by_id, i) = stream_event;
e28d4618
MD
1106 }
1107 return 0;
1108
1109error_event:
1110 for (i = 0; i < stream->events_by_id->len; i++) {
c716f83b 1111 struct ctf_event_definition *stream_event = g_ptr_array_index(stream->events_by_id, i);
42dc00b7
MD
1112 if (stream_event)
1113 g_free(stream_event);
e28d4618
MD
1114 }
1115 g_ptr_array_free(stream->events_by_id, TRUE);
1116error:
1117 if (stream->stream_event_context)
1118 definition_unref(&stream->stream_event_context->p);
1119 if (stream->stream_event_header)
1120 definition_unref(&stream->stream_event_header->p);
1121 if (stream->stream_packet_context)
1122 definition_unref(&stream->stream_packet_context->p);
1123 return ret;
1124}
1125
0f980a35
MD
1126
1127static
46322b33 1128int create_stream_packet_index(struct ctf_trace *td,
0f980a35
MD
1129 struct ctf_file_stream *file_stream)
1130{
f380e105 1131 struct ctf_stream_declaration *stream;
0f980a35 1132 int len_index;
46322b33 1133 struct ctf_stream_pos *pos;
0f980a35
MD
1134 struct stat filestats;
1135 struct packet_index packet_index;
1136 int first_packet = 1;
1137 int ret;
1138
1139 pos = &file_stream->pos;
1140
1141 ret = fstat(pos->fd, &filestats);
1142 if (ret < 0)
1143 return ret;
1144
8895362d
MD
1145 if (filestats.st_size < MAX_PACKET_HEADER_LEN / CHAR_BIT)
1146 return -EINVAL;
1147
0f980a35
MD
1148 for (pos->mmap_offset = 0; pos->mmap_offset < filestats.st_size; ) {
1149 uint64_t stream_id = 0;
1150
aee35fcc 1151 if (pos->base_mma) {
0f980a35 1152 /* unmap old base */
aee35fcc 1153 ret = munmap_align(pos->base_mma);
0f980a35 1154 if (ret) {
3394d22e 1155 fprintf(stderr, "[error] Unable to unmap old base: %s.\n",
0f980a35
MD
1156 strerror(errno));
1157 return ret;
1158 }
aee35fcc 1159 pos->base_mma = NULL;
0f980a35
MD
1160 }
1161 /* map new base. Need mapping length from header. */
aee35fcc 1162 pos->base_mma = mmap_align(MAX_PACKET_HEADER_LEN / CHAR_BIT, PROT_READ,
0f980a35 1163 MAP_PRIVATE, pos->fd, pos->mmap_offset);
aee35fcc 1164 assert(pos->base_mma != MAP_FAILED);
dc48ecad
MD
1165 pos->content_size = MAX_PACKET_HEADER_LEN; /* Unknown at this point */
1166 pos->packet_size = MAX_PACKET_HEADER_LEN; /* Unknown at this point */
0f980a35
MD
1167 pos->offset = 0; /* Position of the packet header */
1168
8c572eba
MD
1169 packet_index.offset = pos->mmap_offset;
1170 packet_index.content_size = 0;
1171 packet_index.packet_size = 0;
75cc2c35
MD
1172 packet_index.timestamp_begin = 0;
1173 packet_index.timestamp_end = 0;
41e82e00 1174 packet_index.events_discarded = 0;
8c572eba 1175
0f980a35 1176 /* read and check header, set stream id (and check) */
2d0bea29 1177 if (file_stream->parent.trace_packet_header) {
0f980a35 1178 /* Read packet header */
2d0bea29 1179 ret = generic_rw(&pos->parent, &file_stream->parent.trace_packet_header->p);
c5e74408
MD
1180 if (ret)
1181 return ret;
2d0bea29 1182 len_index = struct_declaration_lookup_field_index(file_stream->parent.trace_packet_header->declaration, g_quark_from_static_string("magic"));
0f980a35 1183 if (len_index >= 0) {
b1a2f580 1184 struct definition *field;
f4c56ac2 1185 uint64_t magic;
0f980a35 1186
2d0bea29 1187 field = struct_definition_get_field_from_index(file_stream->parent.trace_packet_header, len_index);
f4c56ac2
MD
1188 magic = get_unsigned_int(field);
1189 if (magic != CTF_MAGIC) {
3394d22e 1190 fprintf(stderr, "[error] Invalid magic number 0x%" PRIX64 " at packet %u (file offset %zd).\n",
f4c56ac2 1191 magic,
8c572eba
MD
1192 file_stream->pos.packet_index->len,
1193 (ssize_t) pos->mmap_offset);
0f980a35
MD
1194 return -EINVAL;
1195 }
1196 }
1197
1198 /* check uuid */
2d0bea29 1199 len_index = struct_declaration_lookup_field_index(file_stream->parent.trace_packet_header->declaration, g_quark_from_static_string("uuid"));
0f980a35
MD
1200 if (len_index >= 0) {
1201 struct definition_array *defarray;
b1a2f580 1202 struct definition *field;
0f980a35 1203 uint64_t i;
43e34335 1204 uint8_t uuidval[BABELTRACE_UUID_LEN];
0f980a35 1205
2d0bea29 1206 field = struct_definition_get_field_from_index(file_stream->parent.trace_packet_header, len_index);
b1a2f580
MD
1207 assert(field->declaration->id == CTF_TYPE_ARRAY);
1208 defarray = container_of(field, struct definition_array, p);
43e34335 1209 assert(array_len(defarray) == BABELTRACE_UUID_LEN);
0f980a35 1210
43e34335 1211 for (i = 0; i < BABELTRACE_UUID_LEN; i++) {
0f980a35 1212 struct definition *elem;
0f980a35
MD
1213
1214 elem = array_index(defarray, i);
f4c56ac2 1215 uuidval[i] = get_unsigned_int(elem);
0f980a35 1216 }
43e34335 1217 ret = babeltrace_uuid_compare(td->uuid, uuidval);
0f980a35 1218 if (ret) {
3394d22e 1219 fprintf(stderr, "[error] Unique Universal Identifiers do not match.\n");
0f980a35
MD
1220 return -EINVAL;
1221 }
1222 }
1223
1224
2d0bea29 1225 len_index = struct_declaration_lookup_field_index(file_stream->parent.trace_packet_header->declaration, g_quark_from_static_string("stream_id"));
0f980a35 1226 if (len_index >= 0) {
b1a2f580 1227 struct definition *field;
0f980a35 1228
2d0bea29 1229 field = struct_definition_get_field_from_index(file_stream->parent.trace_packet_header, len_index);
f4c56ac2 1230 stream_id = get_unsigned_int(field);
0f980a35
MD
1231 }
1232 }
1233
2d0bea29 1234 if (!first_packet && file_stream->parent.stream_id != stream_id) {
3394d22e 1235 fprintf(stderr, "[error] Stream ID is changing within a stream.\n");
0f980a35
MD
1236 return -EINVAL;
1237 }
1238 if (first_packet) {
2d0bea29 1239 file_stream->parent.stream_id = stream_id;
46322b33 1240 if (stream_id >= td->streams->len) {
3394d22e 1241 fprintf(stderr, "[error] Stream %" PRIu64 " is not declared in metadata.\n", stream_id);
0f980a35
MD
1242 return -EINVAL;
1243 }
46322b33 1244 stream = g_ptr_array_index(td->streams, stream_id);
0f980a35 1245 if (!stream) {
3394d22e 1246 fprintf(stderr, "[error] Stream %" PRIu64 " is not declared in metadata.\n", stream_id);
0f980a35
MD
1247 return -EINVAL;
1248 }
2d0bea29 1249 file_stream->parent.stream_class = stream;
01c76b24 1250 ret = create_stream_definitions(td, &file_stream->parent);
862434ec
MD
1251 if (ret)
1252 return ret;
0f980a35
MD
1253 }
1254 first_packet = 0;
1255
2d0bea29 1256 if (file_stream->parent.stream_packet_context) {
dc48ecad 1257 /* Read packet context */
2d0bea29 1258 ret = generic_rw(&pos->parent, &file_stream->parent.stream_packet_context->p);
c5e74408
MD
1259 if (ret)
1260 return ret;
dc48ecad 1261 /* read content size from header */
2d0bea29 1262 len_index = struct_declaration_lookup_field_index(file_stream->parent.stream_packet_context->declaration, g_quark_from_static_string("content_size"));
dc48ecad 1263 if (len_index >= 0) {
b1a2f580 1264 struct definition *field;
dc48ecad 1265
2d0bea29 1266 field = struct_definition_get_field_from_index(file_stream->parent.stream_packet_context, len_index);
f4c56ac2 1267 packet_index.content_size = get_unsigned_int(field);
dc48ecad
MD
1268 } else {
1269 /* Use file size for packet size */
8c572eba 1270 packet_index.content_size = filestats.st_size * CHAR_BIT;
dc48ecad
MD
1271 }
1272
1273 /* read packet size from header */
2d0bea29 1274 len_index = struct_declaration_lookup_field_index(file_stream->parent.stream_packet_context->declaration, g_quark_from_static_string("packet_size"));
dc48ecad 1275 if (len_index >= 0) {
b1a2f580 1276 struct definition *field;
dc48ecad 1277
2d0bea29 1278 field = struct_definition_get_field_from_index(file_stream->parent.stream_packet_context, len_index);
f4c56ac2 1279 packet_index.packet_size = get_unsigned_int(field);
dc48ecad
MD
1280 } else {
1281 /* Use content size if non-zero, else file size */
8c572eba 1282 packet_index.packet_size = packet_index.content_size ? : filestats.st_size * CHAR_BIT;
dc48ecad 1283 }
75cc2c35
MD
1284
1285 /* read timestamp begin from header */
2d0bea29 1286 len_index = struct_declaration_lookup_field_index(file_stream->parent.stream_packet_context->declaration, g_quark_from_static_string("timestamp_begin"));
75cc2c35 1287 if (len_index >= 0) {
75cc2c35
MD
1288 struct definition *field;
1289
2d0bea29 1290 field = struct_definition_get_field_from_index(file_stream->parent.stream_packet_context, len_index);
f4c56ac2 1291 packet_index.timestamp_begin = get_unsigned_int(field);
75cc2c35
MD
1292 }
1293
1294 /* read timestamp end from header */
2d0bea29 1295 len_index = struct_declaration_lookup_field_index(file_stream->parent.stream_packet_context->declaration, g_quark_from_static_string("timestamp_end"));
75cc2c35 1296 if (len_index >= 0) {
75cc2c35
MD
1297 struct definition *field;
1298
2d0bea29 1299 field = struct_definition_get_field_from_index(file_stream->parent.stream_packet_context, len_index);
f4c56ac2 1300 packet_index.timestamp_end = get_unsigned_int(field);
75cc2c35 1301 }
41e82e00
MD
1302
1303 /* read events discarded from header */
1304 len_index = struct_declaration_lookup_field_index(file_stream->parent.stream_packet_context->declaration, g_quark_from_static_string("events_discarded"));
1305 if (len_index >= 0) {
1306 struct definition *field;
1307
1308 field = struct_definition_get_field_from_index(file_stream->parent.stream_packet_context, len_index);
1309 packet_index.events_discarded = get_unsigned_int(field);
4c4ba021 1310 packet_index.events_discarded_len = get_int_len(field);
41e82e00 1311 }
0f980a35
MD
1312 } else {
1313 /* Use file size for packet size */
8c572eba 1314 packet_index.content_size = filestats.st_size * CHAR_BIT;
0f980a35 1315 /* Use content size if non-zero, else file size */
8c572eba 1316 packet_index.packet_size = packet_index.content_size ? : filestats.st_size * CHAR_BIT;
0f980a35 1317 }
546293fa
MD
1318
1319 /* Validate content size and packet size values */
1320 if (packet_index.content_size > packet_index.packet_size) {
7e18eedf 1321 fprintf(stderr, "[error] Content size (%" PRIu64 " bits) is larger than packet size (%" PRIu64 " bits).\n",
546293fa
MD
1322 packet_index.content_size, packet_index.packet_size);
1323 return -EINVAL;
1324 }
1325
7e18eedf
JN
1326 if (packet_index.packet_size > ((uint64_t)filestats.st_size - packet_index.offset) * CHAR_BIT) {
1327 fprintf(stderr, "[error] Packet size (%" PRIu64 " bits) is larger than remaining file size (%" PRIu64 " bits).\n",
0fe3c2c9 1328 packet_index.packet_size, ((uint64_t)filestats.st_size - packet_index.offset) * CHAR_BIT);
546293fa
MD
1329 return -EINVAL;
1330 }
1331
847bf71a
MD
1332 /* Save position after header and context */
1333 packet_index.data_offset = pos->offset;
0f980a35 1334
0f980a35
MD
1335 /* add index to packet array */
1336 g_array_append_val(file_stream->pos.packet_index, packet_index);
1337
8c572eba 1338 pos->mmap_offset += packet_index.packet_size / CHAR_BIT;
0f980a35
MD
1339 }
1340
847bf71a 1341 /* Move pos back to beginning of file */
06789ffd 1342 ctf_packet_seek(&pos->parent, 0, SEEK_SET); /* position for write */
847bf71a 1343
0f980a35
MD
1344 return 0;
1345}
1346
e28d4618 1347static
9e88d150 1348int create_trace_definitions(struct ctf_trace *td, struct ctf_stream_definition *stream)
e28d4618
MD
1349{
1350 int ret;
1351
1352 if (td->packet_header_decl) {
1353 struct definition *definition =
1354 td->packet_header_decl->p.definition_new(&td->packet_header_decl->p,
1355 stream->parent_def_scope, 0, 0, "trace.packet.header");
1356 if (!definition) {
1357 ret = -EINVAL;
1358 goto error;
1359 }
1360 stream->trace_packet_header =
1361 container_of(definition, struct definition_struct, p);
1362 stream->parent_def_scope = stream->trace_packet_header->p.scope;
1363 }
1364
1365 return 0;
1366
1367error:
1368 return ret;
1369}
1370
0f980a35
MD
1371/*
1372 * Note: many file streams can inherit from the same stream class
1373 * description (metadata).
1374 */
1375static
b086c01a 1376int ctf_open_file_stream_read(struct ctf_trace *td, const char *path, int flags,
20d0dcf9 1377 void (*packet_seek)(struct stream_pos *pos, size_t index,
b086c01a 1378 int whence))
0f980a35 1379{
ff075710 1380 int ret, fd;
0f980a35 1381 struct ctf_file_stream *file_stream;
ff075710 1382 struct stat statbuf;
0f980a35 1383
ff075710
MD
1384 fd = openat(td->dirfd, path, flags);
1385 if (fd < 0) {
a569a564 1386 perror("File stream openat()");
ff075710 1387 ret = fd;
0f980a35 1388 goto error;
a569a564 1389 }
ff075710
MD
1390
1391 /* Don't try to mmap subdirectories. Skip them, return success. */
1392 ret = fstat(fd, &statbuf);
1393 if (ret) {
1394 perror("File stream fstat()");
1395 goto fstat_error;
1396 }
1397 if (S_ISDIR(statbuf.st_mode)) {
1398 fprintf(stderr, "[warning] Skipping directory '%s' found in trace\n", path);
1399 ret = 0;
1400 goto fd_is_dir_ok;
1401 }
1402
0f980a35 1403 file_stream = g_new0(struct ctf_file_stream, 1);
3a25e036 1404 file_stream->pos.last_offset = LAST_OFFSET_POISON;
b086c01a 1405
06789ffd
MD
1406 if (packet_seek) {
1407 file_stream->pos.packet_seek = packet_seek;
b086c01a 1408 } else {
06789ffd 1409 fprintf(stderr, "[error] packet_seek function undefined.\n");
b086c01a
JD
1410 ret = -1;
1411 goto error_def;
1412 }
1413
ff075710 1414 ctf_init_pos(&file_stream->pos, fd, flags);
2d0bea29 1415 ret = create_trace_definitions(td, &file_stream->parent);
e28d4618
MD
1416 if (ret)
1417 goto error_def;
25ccc85b
MD
1418 /*
1419 * For now, only a single slock is supported.
1420 */
1421 file_stream->parent.current_clock = td->single_clock;
0f980a35
MD
1422 ret = create_stream_packet_index(td, file_stream);
1423 if (ret)
1424 goto error_index;
1425 /* Add stream file to stream class */
2d0bea29
MD
1426 g_ptr_array_add(file_stream->parent.stream_class->streams,
1427 &file_stream->parent);
0f980a35
MD
1428 return 0;
1429
1430error_index:
2d0bea29
MD
1431 if (file_stream->parent.trace_packet_header)
1432 definition_unref(&file_stream->parent.trace_packet_header->p);
e28d4618 1433error_def:
46322b33 1434 ctf_fini_pos(&file_stream->pos);
0f980a35 1435 g_free(file_stream);
ff075710
MD
1436fd_is_dir_ok:
1437fstat_error:
1438 close(fd);
0f980a35 1439error:
65102a8c
MD
1440 return ret;
1441}
1442
bbefb8dd 1443static
5b80ddfb 1444int ctf_open_trace_read(struct ctf_trace *td,
8c250d87 1445 const char *path, int flags,
20d0dcf9 1446 void (*packet_seek)(struct stream_pos *pos, size_t index,
ae23d232 1447 int whence), FILE *metadata_fp)
bbefb8dd
MD
1448{
1449 int ret;
65102a8c
MD
1450 struct dirent *dirent;
1451 struct dirent *diriter;
1452 size_t dirent_len;
bbefb8dd 1453
46322b33 1454 td->flags = flags;
bbefb8dd
MD
1455
1456 /* Open trace directory */
46322b33
MD
1457 td->dir = opendir(path);
1458 if (!td->dir) {
6a6b384c 1459 fprintf(stderr, "[error] Unable to open trace directory \"%s\".\n", path);
bbefb8dd
MD
1460 ret = -ENOENT;
1461 goto error;
1462 }
1463
46322b33
MD
1464 td->dirfd = open(path, 0);
1465 if (td->dirfd < 0) {
6a6b384c 1466 fprintf(stderr, "[error] Unable to open trace directory file descriptor for path \"%s\".\n", path);
a569a564
MD
1467 perror("Trace directory open");
1468 ret = -errno;
65102a8c
MD
1469 goto error_dirfd;
1470 }
5b80ddfb
MD
1471 strncpy(td->path, path, sizeof(td->path));
1472 td->path[sizeof(td->path) - 1] = '\0';
0f980a35 1473
65102a8c
MD
1474 /*
1475 * Keep the metadata file separate.
1476 */
bbefb8dd 1477
06789ffd 1478 ret = ctf_open_trace_metadata_read(td, packet_seek, metadata_fp);
65102a8c 1479 if (ret) {
6a6b384c 1480 fprintf(stderr, "[warning] Unable to open trace metadata for path \"%s\".\n", path);
65102a8c
MD
1481 goto error_metadata;
1482 }
bbefb8dd
MD
1483
1484 /*
1485 * Open each stream: for each file, try to open, check magic
1486 * number, and get the stream ID to add to the right location in
1487 * the stream array.
bbefb8dd
MD
1488 */
1489
65102a8c 1490 dirent_len = offsetof(struct dirent, d_name) +
46322b33 1491 fpathconf(td->dirfd, _PC_NAME_MAX) + 1;
bbefb8dd 1492
65102a8c 1493 dirent = malloc(dirent_len);
bbefb8dd 1494
65102a8c 1495 for (;;) {
46322b33 1496 ret = readdir_r(td->dir, dirent, &diriter);
65102a8c 1497 if (ret) {
3394d22e 1498 fprintf(stderr, "[error] Readdir error.\n");
65102a8c 1499 goto readdir_error;
65102a8c
MD
1500 }
1501 if (!diriter)
1502 break;
d8ea2d29
MD
1503 /* Ignore hidden files, ., .. and metadata. */
1504 if (!strncmp(diriter->d_name, ".", 1)
65102a8c
MD
1505 || !strcmp(diriter->d_name, "..")
1506 || !strcmp(diriter->d_name, "metadata"))
1507 continue;
06789ffd
MD
1508 ret = ctf_open_file_stream_read(td, diriter->d_name,
1509 flags, packet_seek);
dc48ecad 1510 if (ret) {
3394d22e 1511 fprintf(stderr, "[error] Open file stream error.\n");
dc48ecad
MD
1512 goto readdir_error;
1513 }
65102a8c 1514 }
bbefb8dd 1515
65102a8c 1516 free(dirent);
bbefb8dd 1517 return 0;
65102a8c
MD
1518
1519readdir_error:
1520 free(dirent);
1521error_metadata:
46322b33 1522 close(td->dirfd);
65102a8c 1523error_dirfd:
46322b33 1524 closedir(td->dir);
bbefb8dd
MD
1525error:
1526 return ret;
1527}
1528
e9378815 1529static
5b80ddfb 1530struct trace_descriptor *ctf_open_trace(const char *path, int flags,
20d0dcf9 1531 void (*packet_seek)(struct stream_pos *pos, size_t index,
ae23d232 1532 int whence), FILE *metadata_fp)
bbefb8dd 1533{
46322b33 1534 struct ctf_trace *td;
bbefb8dd
MD
1535 int ret;
1536
2715de36
MD
1537 /*
1538 * If packet_seek is NULL, we provide our default version.
1539 */
1540 if (!packet_seek)
1541 packet_seek = ctf_packet_seek;
1542
46322b33 1543 td = g_new0(struct ctf_trace, 1);
bbefb8dd 1544
8c572eba 1545 switch (flags & O_ACCMODE) {
bbefb8dd 1546 case O_RDONLY:
b61922b5 1547 if (!path) {
3394d22e 1548 fprintf(stderr, "[error] Path missing for input CTF trace.\n");
b61922b5
MD
1549 goto error;
1550 }
06789ffd 1551 ret = ctf_open_trace_read(td, path, flags, packet_seek, metadata_fp);
bbefb8dd
MD
1552 if (ret)
1553 goto error;
1554 break;
989c73bc 1555 case O_RDWR:
3394d22e 1556 fprintf(stderr, "[error] Opening CTF traces for output is not supported yet.\n");
46322b33 1557 goto error;
bbefb8dd 1558 default:
3394d22e 1559 fprintf(stderr, "[error] Incorrect open flags.\n");
bbefb8dd
MD
1560 goto error;
1561 }
1562
46322b33 1563 return &td->parent;
bbefb8dd
MD
1564error:
1565 g_free(td);
1566 return NULL;
1567}
1568
f571dfb1
JD
1569
1570void ctf_init_mmap_pos(struct ctf_stream_pos *pos,
1571 struct mmap_stream *mmap_info)
1572{
1573 pos->mmap_offset = 0;
1574 pos->packet_size = 0;
1575 pos->content_size = 0;
1576 pos->content_size_loc = NULL;
1577 pos->fd = mmap_info->fd;
aee35fcc 1578 pos->base_mma = NULL;
f571dfb1
JD
1579 pos->offset = 0;
1580 pos->dummy = false;
1581 pos->cur_index = 0;
1582 pos->packet_index = NULL;
1583 pos->prot = PROT_READ;
1584 pos->flags = MAP_PRIVATE;
1585 pos->parent.rw_table = read_dispatch_table;
1586 pos->parent.event_cb = ctf_read_event;
1587}
1588
1589static
1590int prepare_mmap_stream_definition(struct ctf_trace *td,
1591 struct ctf_file_stream *file_stream)
1592{
f380e105 1593 struct ctf_stream_declaration *stream;
f571dfb1
JD
1594 uint64_t stream_id = 0;
1595 int ret;
1596
1597 file_stream->parent.stream_id = stream_id;
1598 if (stream_id >= td->streams->len) {
3394d22e 1599 fprintf(stderr, "[error] Stream %" PRIu64 " is not declared "
f571dfb1
JD
1600 "in metadata.\n", stream_id);
1601 ret = -EINVAL;
1602 goto end;
1603 }
1604 stream = g_ptr_array_index(td->streams, stream_id);
1605 if (!stream) {
3394d22e 1606 fprintf(stderr, "[error] Stream %" PRIu64 " is not declared "
f571dfb1
JD
1607 "in metadata.\n", stream_id);
1608 ret = -EINVAL;
1609 goto end;
1610 }
1611 file_stream->parent.stream_class = stream;
1612 ret = create_stream_definitions(td, &file_stream->parent);
1613end:
1614 return ret;
1615}
1616
1617static
1618int ctf_open_mmap_stream_read(struct ctf_trace *td,
1619 struct mmap_stream *mmap_info,
20d0dcf9 1620 void (*packet_seek)(struct stream_pos *pos, size_t index,
f571dfb1
JD
1621 int whence))
1622{
1623 int ret;
1624 struct ctf_file_stream *file_stream;
1625
1626 file_stream = g_new0(struct ctf_file_stream, 1);
3a25e036 1627 file_stream->pos.last_offset = LAST_OFFSET_POISON;
f571dfb1
JD
1628 ctf_init_mmap_pos(&file_stream->pos, mmap_info);
1629
06789ffd 1630 file_stream->pos.packet_seek = packet_seek;
f571dfb1
JD
1631
1632 ret = create_trace_definitions(td, &file_stream->parent);
1633 if (ret) {
1634 goto error_def;
1635 }
1636
1637 ret = prepare_mmap_stream_definition(td, file_stream);
1638 if (ret)
1639 goto error_index;
1640
1641 /* Add stream file to stream class */
1642 g_ptr_array_add(file_stream->parent.stream_class->streams,
1643 &file_stream->parent);
1644 return 0;
1645
1646error_index:
1647 if (file_stream->parent.trace_packet_header)
1648 definition_unref(&file_stream->parent.trace_packet_header->p);
1649error_def:
1650 g_free(file_stream);
1651 return ret;
1652}
1653
1654int ctf_open_mmap_trace_read(struct ctf_trace *td,
1655 struct mmap_stream_list *mmap_list,
20d0dcf9 1656 void (*packet_seek)(struct stream_pos *pos, size_t index,
f571dfb1
JD
1657 int whence),
1658 FILE *metadata_fp)
1659{
1660 int ret;
1661 struct mmap_stream *mmap_info;
1662
06789ffd 1663 ret = ctf_open_trace_metadata_read(td, ctf_packet_seek, metadata_fp);
f571dfb1
JD
1664 if (ret) {
1665 goto error;
1666 }
1667
1668 /*
1669 * for each stream, try to open, check magic number, and get the
1670 * stream ID to add to the right location in the stream array.
1671 */
3122e6f0 1672 bt_list_for_each_entry(mmap_info, &mmap_list->head, list) {
06789ffd 1673 ret = ctf_open_mmap_stream_read(td, mmap_info, packet_seek);
f571dfb1 1674 if (ret) {
3394d22e 1675 fprintf(stderr, "[error] Open file mmap stream error.\n");
f571dfb1
JD
1676 goto error;
1677 }
1678 }
1679
1680 return 0;
1681
1682error:
1683 return ret;
1684}
1685
1686static
1687struct trace_descriptor *ctf_open_mmap_trace(
1688 struct mmap_stream_list *mmap_list,
20d0dcf9
MD
1689 void (*packet_seek)(struct stream_pos *pos, size_t index,
1690 int whence),
f571dfb1
JD
1691 FILE *metadata_fp)
1692{
1693 struct ctf_trace *td;
1694 int ret;
1695
1696 if (!metadata_fp) {
1697 fprintf(stderr, "[error] No metadata file pointer associated, "
1698 "required for mmap parsing\n");
1699 goto error;
1700 }
06789ffd
MD
1701 if (!packet_seek) {
1702 fprintf(stderr, "[error] packet_seek function undefined.\n");
f571dfb1
JD
1703 goto error;
1704 }
1705 td = g_new0(struct ctf_trace, 1);
06789ffd 1706 ret = ctf_open_mmap_trace_read(td, mmap_list, packet_seek, metadata_fp);
f571dfb1
JD
1707 if (ret)
1708 goto error_free;
1709
1710 return &td->parent;
1711
1712error_free:
1713 g_free(td);
1714error:
1715 return NULL;
1716}
1717
0f980a35
MD
1718static
1719void ctf_close_file_stream(struct ctf_file_stream *file_stream)
1720{
46322b33 1721 ctf_fini_pos(&file_stream->pos);
0f980a35
MD
1722 close(file_stream->pos.fd);
1723}
1724
e9378815 1725static
46322b33 1726void ctf_close_trace(struct trace_descriptor *tdp)
bbefb8dd 1727{
46322b33 1728 struct ctf_trace *td = container_of(tdp, struct ctf_trace, parent);
0f980a35
MD
1729 int i;
1730
46322b33
MD
1731 if (td->streams) {
1732 for (i = 0; i < td->streams->len; i++) {
f380e105 1733 struct ctf_stream_declaration *stream;
0f980a35 1734 int j;
e9378815 1735
46322b33 1736 stream = g_ptr_array_index(td->streams, i);
e9378815
MD
1737 if (!stream)
1738 continue;
2d0bea29 1739 for (j = 0; j < stream->streams->len; j++) {
0f980a35 1740 struct ctf_file_stream *file_stream;
2d0bea29 1741 file_stream = container_of(g_ptr_array_index(stream->streams, j), struct ctf_file_stream, parent);
0f980a35
MD
1742 ctf_close_file_stream(file_stream);
1743 }
1744
1745 }
46322b33 1746 g_ptr_array_free(td->streams, TRUE);
0f980a35 1747 }
e003ab50
JD
1748
1749 if (td->event_declarations) {
1750 for (i = 0; i < td->event_declarations->len; i++) {
1751 struct bt_ctf_event_decl *event;
1752
1753 event = g_ptr_array_index(td->event_declarations, i);
64c2c249
JD
1754 if (event->context_decl)
1755 g_ptr_array_free(event->context_decl, TRUE);
1756 if (event->fields_decl)
1757 g_ptr_array_free(event->fields_decl, TRUE);
1758 if (event->packet_header_decl)
1759 g_ptr_array_free(event->packet_header_decl, TRUE);
1760 if (event->event_context_decl)
1761 g_ptr_array_free(event->event_context_decl, TRUE);
1762 if (event->event_header_decl)
1763 g_ptr_array_free(event->event_header_decl, TRUE);
1764 if (event->packet_context_decl)
1765 g_ptr_array_free(event->packet_context_decl, TRUE);
e003ab50
JD
1766 g_free(event);
1767 }
1768 g_ptr_array_free(td->event_declarations, TRUE);
1769 }
46322b33 1770 closedir(td->dir);
bbefb8dd
MD
1771 g_free(td);
1772}
1773
98a04903
JD
1774static
1775void ctf_set_context(struct trace_descriptor *descriptor,
1776 struct bt_context *ctx)
1777{
1778 struct ctf_trace *td = container_of(descriptor, struct ctf_trace,
1779 parent);
1780
1781 td->ctx = ctx;
1782}
1783
1784static
1785void ctf_set_handle(struct trace_descriptor *descriptor,
1786 struct bt_trace_handle *handle)
1787{
1788 struct ctf_trace *td = container_of(descriptor, struct ctf_trace,
1789 parent);
1790
1791 td->handle = handle;
1792}
1793
7fb21036 1794void __attribute__((constructor)) ctf_init(void)
fc93b2bd
MD
1795{
1796 int ret;
1797
4c8bfb7e 1798 ctf_format.name = g_quark_from_static_string("ctf");
fc93b2bd
MD
1799 ret = bt_register_format(&ctf_format);
1800 assert(!ret);
1801}
698f0fe4
MD
1802
1803/* TODO: finalize */
This page took 0.130835 seconds and 4 git commands to generate.