Cleanup: update ifdef wrapper name
[babeltrace.git] / lib / iterator.c
CommitLineData
6f3077a2
JD
1/*
2 * iterator.c
3 *
4 * Babeltrace Library
5 *
6 * Copyright 2010-2011 EfficiOS Inc. and Linux Foundation
7 *
8 * Author: Mathieu Desnoyers <mathieu.desnoyers@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
21#include <stdlib.h>
22#include <babeltrace/babeltrace.h>
95d36295 23#include <babeltrace/context.h>
08c22d05 24#include <babeltrace/context-internal.h>
6f3077a2 25#include <babeltrace/iterator-internal.h>
6204d33c 26#include <babeltrace/iterator.h>
6f3077a2 27#include <babeltrace/prio_heap.h>
e4195791 28#include <babeltrace/ctf/metadata.h>
9843982d 29#include <babeltrace/ctf/events.h>
90fcbacc 30#include <inttypes.h>
6f3077a2 31
55c21ea5
JD
32static int babeltrace_filestream_seek(struct ctf_file_stream *file_stream,
33 const struct bt_iter_pos *begin_pos,
34 unsigned long stream_id);
35
6f3077a2
JD
36struct stream_saved_pos {
37 /*
38 * Use file_stream pointer to check if the trace collection we
39 * restore to match the one we saved from, for each stream.
40 */
41 struct ctf_file_stream *file_stream;
42 size_t cur_index; /* current index in packet index */
43 ssize_t offset; /* offset from base, in bits. EOF for end of file. */
03798a93
JD
44 uint64_t current_real_timestamp;
45 uint64_t current_cycles_timestamp;
6f3077a2
JD
46};
47
e8c92a62 48struct bt_saved_pos {
6f3077a2
JD
49 struct trace_collection *tc;
50 GArray *stream_saved_pos; /* Contains struct stream_saved_pos */
51};
52
53static int stream_read_event(struct ctf_file_stream *sin)
54{
55 int ret;
56
57 ret = sin->pos.parent.event_cb(&sin->pos.parent, &sin->parent);
58 if (ret == EOF)
59 return EOF;
60 else if (ret) {
3394d22e 61 fprintf(stderr, "[error] Reading event failed.\n");
6f3077a2
JD
62 return ret;
63 }
64 return 0;
65}
66
67/*
68 * returns true if a < b, false otherwise.
69 */
2002e48a 70static int stream_compare(void *a, void *b)
6f3077a2
JD
71{
72 struct ctf_file_stream *s_a = a, *s_b = b;
73
03798a93 74 if (s_a->parent.real_timestamp < s_b->parent.real_timestamp)
6f3077a2
JD
75 return 1;
76 else
77 return 0;
78}
79
90fcbacc
JD
80void bt_iter_free_pos(struct bt_iter_pos *iter_pos)
81{
6cba487f
MD
82 if (!iter_pos)
83 return;
84
5acdc773 85 if (iter_pos->type == BT_SEEK_RESTORE && iter_pos->u.restore) {
6cba487f
MD
86 if (iter_pos->u.restore->stream_saved_pos) {
87 g_array_free(
88 iter_pos->u.restore->stream_saved_pos,
89 TRUE);
90fcbacc 90 }
6cba487f 91 g_free(iter_pos->u.restore);
90fcbacc 92 }
6cba487f 93 g_free(iter_pos);
90fcbacc
JD
94}
95
dc81689e
JD
96/*
97 * seek_file_stream_by_timestamp
98 *
99 * Browse a filestream by index, if an index contains the timestamp passed in
100 * argument, seek inside the corresponding packet it until we find the event we
101 * are looking for (either the exact timestamp or the event just after the
102 * timestamp).
103 *
e32cb1e4
MD
104 * Return 0 if the seek succeded, EOF if we didn't find any packet
105 * containing the timestamp, or a positive integer for error.
f7ed6563
MD
106 *
107 * TODO: this should be turned into a binary search! It is currently
108 * doing a linear search in the packets. This is a O(n) operation on a
109 * very frequent code path.
dc81689e
JD
110 */
111static int seek_file_stream_by_timestamp(struct ctf_file_stream *cfs,
112 uint64_t timestamp)
113{
114 struct ctf_stream_pos *stream_pos;
115 struct packet_index *index;
116 int i, ret;
117
118 stream_pos = &cfs->pos;
03798a93
JD
119 for (i = 0; i < stream_pos->packet_real_index->len; i++) {
120 index = &g_array_index(stream_pos->packet_real_index,
dc81689e 121 struct packet_index, i);
e32cb1e4 122 if (index->timestamp_end < timestamp)
dc81689e
JD
123 continue;
124
20d0dcf9 125 stream_pos->packet_seek(&stream_pos->parent, i, SEEK_SET);
5d2a5af2 126 do {
dc81689e 127 ret = stream_read_event(cfs);
03798a93 128 } while (cfs->parent.real_timestamp < timestamp && ret == 0);
5d2a5af2 129
e32cb1e4
MD
130 /* Can return either EOF, 0, or error (> 0). */
131 return ret;
dc81689e 132 }
e32cb1e4
MD
133 /*
134 * Cannot find the timestamp within the stream packets, return
135 * EOF.
136 */
dc81689e
JD
137 return EOF;
138}
139
140/*
141 * seek_ctf_trace_by_timestamp : for each file stream, seek to the event with
142 * the corresponding timestamp
143 *
144 * Return 0 on success.
145 * If the timestamp is not part of any file stream, return EOF to inform the
e32cb1e4
MD
146 * user the timestamp is out of the scope.
147 * On other errors, return positive value.
dc81689e
JD
148 */
149static int seek_ctf_trace_by_timestamp(struct ctf_trace *tin,
150 uint64_t timestamp, struct ptr_heap *stream_heap)
151{
152 int i, j, ret;
e32cb1e4 153 int found = 0;
dc81689e
JD
154
155 /* for each stream_class */
156 for (i = 0; i < tin->streams->len; i++) {
f380e105 157 struct ctf_stream_declaration *stream_class;
dc81689e
JD
158
159 stream_class = g_ptr_array_index(tin->streams, i);
e32cb1e4
MD
160 if (!stream_class)
161 continue;
dc81689e
JD
162 /* for each file_stream */
163 for (j = 0; j < stream_class->streams->len; j++) {
9e88d150 164 struct ctf_stream_definition *stream;
dc81689e
JD
165 struct ctf_file_stream *cfs;
166
167 stream = g_ptr_array_index(stream_class->streams, j);
e32cb1e4
MD
168 if (!stream)
169 continue;
dc81689e
JD
170 cfs = container_of(stream, struct ctf_file_stream,
171 parent);
172 ret = seek_file_stream_by_timestamp(cfs, timestamp);
173 if (ret == 0) {
174 /* Add to heap */
175 ret = heap_insert(stream_heap, cfs);
e32cb1e4
MD
176 if (ret) {
177 /* Return positive error. */
178 return -ret;
179 }
180 found = 1;
181 } else if (ret > 0) {
182 /*
183 * Error in seek (not EOF), failure.
184 */
185 return ret;
dc81689e 186 }
e32cb1e4 187 /* on EOF just do not put stream into heap. */
dc81689e
JD
188 }
189 }
190
e32cb1e4 191 return found ? 0 : EOF;
dc81689e
JD
192}
193
f7ed6563
MD
194/*
195 * Find timestamp of last event in the stream.
196 *
197 * Return value: 0 if OK, positive error value on error, EOF if no
198 * events were found.
199 */
200static int find_max_timestamp_ctf_file_stream(struct ctf_file_stream *cfs,
201 uint64_t *timestamp_end)
202{
203 int ret, count = 0, i;
204 uint64_t timestamp = 0;
205 struct ctf_stream_pos *stream_pos;
206
207 stream_pos = &cfs->pos;
208 /*
209 * We start by the last packet, and iterate backwards until we
210 * either find at least one event, or we reach the first packet
211 * (some packets can be empty).
212 */
213 for (i = stream_pos->packet_real_index->len - 1; i >= 0; i--) {
214 stream_pos->packet_seek(&stream_pos->parent, i, SEEK_SET);
215 count = 0;
216 /* read each event until we reach the end of the stream */
217 do {
218 ret = stream_read_event(cfs);
219 if (ret == 0) {
220 count++;
221 timestamp = cfs->parent.real_timestamp;
222 }
223 } while (ret == 0);
224
225 /* Error */
226 if (ret > 0)
227 goto end;
228 assert(ret == EOF);
229 if (count)
230 break;
231 }
232
233 if (count) {
234 *timestamp_end = timestamp;
235 ret = 0;
236 } else {
237 /* Return EOF if no events were found */
238 ret = EOF;
239 }
240end:
241 return ret;
242}
243
244/*
245 * Find the stream within a stream class that contains the event with
246 * the largest timestamp, and save that timestamp.
247 *
248 * Return 0 if OK, EOF if no events were found in the streams, or
249 * positive value on error.
250 */
251static int find_max_timestamp_ctf_stream_class(
252 struct ctf_stream_declaration *stream_class,
253 struct ctf_file_stream **cfsp,
254 uint64_t *max_timestamp)
255{
256 int ret = EOF, i;
257
258 for (i = 0; i < stream_class->streams->len; i++) {
259 struct ctf_stream_definition *stream;
260 struct ctf_file_stream *cfs;
261 uint64_t current_max_ts = 0;
262
263 stream = g_ptr_array_index(stream_class->streams, i);
264 if (!stream)
265 continue;
266 cfs = container_of(stream, struct ctf_file_stream, parent);
267 ret = find_max_timestamp_ctf_file_stream(cfs, &current_max_ts);
268 if (ret == EOF)
269 continue;
270 if (ret != 0)
271 break;
272 if (current_max_ts >= *max_timestamp) {
273 *max_timestamp = current_max_ts;
274 *cfsp = cfs;
275 }
276 }
277 assert(ret >= 0 || ret == EOF);
278 return ret;
279}
280
281/*
282 * seek_last_ctf_trace_collection: seek trace collection to last event.
283 *
284 * Return 0 if OK, EOF if no events were found, or positive error value
285 * on error.
286 */
287static int seek_last_ctf_trace_collection(struct trace_collection *tc,
288 struct ctf_file_stream **cfsp)
289{
290 int i, j, ret;
291 int found = 0;
292 uint64_t max_timestamp = 0;
293
294 if (!tc)
295 return 1;
296
297 /* For each trace in the trace_collection */
298 for (i = 0; i < tc->array->len; i++) {
299 struct ctf_trace *tin;
300 struct trace_descriptor *td_read;
301
302 td_read = g_ptr_array_index(tc->array, i);
303 if (!td_read)
304 continue;
305 tin = container_of(td_read, struct ctf_trace, parent);
306 /* For each stream_class in the trace */
307 for (j = 0; j < tin->streams->len; j++) {
308 struct ctf_stream_declaration *stream_class;
309
310 stream_class = g_ptr_array_index(tin->streams, j);
311 if (!stream_class)
312 continue;
313 ret = find_max_timestamp_ctf_stream_class(stream_class,
314 cfsp, &max_timestamp);
315 if (ret > 0)
316 goto end;
317 if (ret == 0)
318 found = 1;
319 assert(ret == EOF || ret == 0);
320 }
321 }
322 /*
323 * Now we know in which file stream the last event is located,
324 * and we know its timestamp.
325 */
326 if (!found) {
327 ret = EOF;
328 } else {
329 ret = seek_file_stream_by_timestamp(*cfsp, max_timestamp);
330 assert(ret == 0);
331 }
332end:
333 return ret;
334}
335
90fcbacc
JD
336int bt_iter_set_pos(struct bt_iter *iter, const struct bt_iter_pos *iter_pos)
337{
dc81689e 338 struct trace_collection *tc;
90fcbacc
JD
339 int i, ret;
340
7f89ddce
MD
341 if (!iter || !iter_pos)
342 return -EINVAL;
343
dc81689e
JD
344 switch (iter_pos->type) {
345 case BT_SEEK_RESTORE:
346 if (!iter_pos->u.restore)
7344374e 347 return -EINVAL;
dc81689e 348
90fcbacc 349 heap_free(iter->stream_heap);
90fcbacc
JD
350 ret = heap_init(iter->stream_heap, 0, stream_compare);
351 if (ret < 0)
bed54c92 352 goto error_heap_init;
90fcbacc
JD
353
354 for (i = 0; i < iter_pos->u.restore->stream_saved_pos->len;
355 i++) {
356 struct stream_saved_pos *saved_pos;
357 struct ctf_stream_pos *stream_pos;
9e88d150 358 struct ctf_stream_definition *stream;
90fcbacc
JD
359
360 saved_pos = &g_array_index(
361 iter_pos->u.restore->stream_saved_pos,
362 struct stream_saved_pos, i);
363 stream = &saved_pos->file_stream->parent;
364 stream_pos = &saved_pos->file_stream->pos;
90fcbacc 365
06789ffd 366 stream_pos->packet_seek(&stream_pos->parent,
20d0dcf9 367 saved_pos->cur_index, SEEK_SET);
90fcbacc
JD
368
369 /*
370 * the timestamp needs to be restored after
06789ffd 371 * packet_seek, because this function resets
90fcbacc
JD
372 * the timestamp to the beginning of the packet
373 */
03798a93
JD
374 stream->real_timestamp = saved_pos->current_real_timestamp;
375 stream->cycles_timestamp = saved_pos->current_cycles_timestamp;
90fcbacc 376 stream_pos->offset = saved_pos->offset;
3a25e036 377 stream_pos->last_offset = LAST_OFFSET_POISON;
90fcbacc 378
03798a93
JD
379 stream->prev_real_timestamp = 0;
380 stream->prev_real_timestamp_end = 0;
381 stream->prev_cycles_timestamp = 0;
382 stream->prev_cycles_timestamp_end = 0;
90fcbacc
JD
383
384 printf_debug("restored to cur_index = %zd and "
385 "offset = %zd, timestamp = %" PRIu64 "\n",
386 stream_pos->cur_index,
03798a93 387 stream_pos->offset, stream->real_timestamp);
90fcbacc 388
28fcbaca
MD
389 ret = stream_read_event(saved_pos->file_stream);
390 if (ret != 0) {
391 goto error;
392 }
90fcbacc
JD
393
394 /* Add to heap */
395 ret = heap_insert(iter->stream_heap,
396 saved_pos->file_stream);
397 if (ret)
398 goto error;
399 }
5acdc773 400 return 0;
dc81689e
JD
401 case BT_SEEK_TIME:
402 tc = iter->ctx->tc;
403
dc81689e
JD
404 heap_free(iter->stream_heap);
405 ret = heap_init(iter->stream_heap, 0, stream_compare);
406 if (ret < 0)
bed54c92 407 goto error_heap_init;
dc81689e
JD
408
409 /* for each trace in the trace_collection */
410 for (i = 0; i < tc->array->len; i++) {
411 struct ctf_trace *tin;
412 struct trace_descriptor *td_read;
413
414 td_read = g_ptr_array_index(tc->array, i);
e32cb1e4
MD
415 if (!td_read)
416 continue;
dc81689e
JD
417 tin = container_of(td_read, struct ctf_trace, parent);
418
419 ret = seek_ctf_trace_by_timestamp(tin,
420 iter_pos->u.seek_time,
421 iter->stream_heap);
e32cb1e4
MD
422 /*
423 * Positive errors are failure. Negative value
424 * is EOF (for which we continue with other
425 * traces). 0 is success. Note: on EOF, it just
426 * means that no stream has been added to the
427 * iterator for that trace, which is fine.
428 */
429 if (ret != 0 && ret != EOF)
dc81689e
JD
430 goto error;
431 }
432 return 0;
55c21ea5
JD
433 case BT_SEEK_BEGIN:
434 tc = iter->ctx->tc;
db8a4511
JD
435 heap_free(iter->stream_heap);
436 ret = heap_init(iter->stream_heap, 0, stream_compare);
437 if (ret < 0)
bed54c92 438 goto error_heap_init;
db8a4511 439
55c21ea5
JD
440 for (i = 0; i < tc->array->len; i++) {
441 struct ctf_trace *tin;
442 struct trace_descriptor *td_read;
443 int stream_id;
444
445 td_read = g_ptr_array_index(tc->array, i);
e32cb1e4
MD
446 if (!td_read)
447 continue;
55c21ea5
JD
448 tin = container_of(td_read, struct ctf_trace, parent);
449
450 /* Populate heap with each stream */
451 for (stream_id = 0; stream_id < tin->streams->len;
452 stream_id++) {
f380e105 453 struct ctf_stream_declaration *stream;
55c21ea5
JD
454 int filenr;
455
456 stream = g_ptr_array_index(tin->streams,
457 stream_id);
458 if (!stream)
459 continue;
460 for (filenr = 0; filenr < stream->streams->len;
461 filenr++) {
462 struct ctf_file_stream *file_stream;
463 file_stream = g_ptr_array_index(
464 stream->streams,
465 filenr);
e32cb1e4
MD
466 if (!file_stream)
467 continue;
55c21ea5
JD
468 ret = babeltrace_filestream_seek(
469 file_stream, iter_pos,
470 stream_id);
e32cb1e4
MD
471 if (ret != 0 && ret != EOF) {
472 goto error;
473 }
db8a4511
JD
474 ret = heap_insert(iter->stream_heap, file_stream);
475 if (ret)
476 goto error;
55c21ea5
JD
477 }
478 }
479 }
480 break;
f7ed6563
MD
481 case BT_SEEK_LAST:
482 {
483 struct ctf_file_stream *cfs;
484
485 tc = iter->ctx->tc;
486 ret = seek_last_ctf_trace_collection(tc, &cfs);
487 if (ret != 0)
488 goto error;
489 /* remove all streams from the heap */
490 heap_free(iter->stream_heap);
491 /* Create a new empty heap */
492 ret = heap_init(iter->stream_heap, 0, stream_compare);
493 if (ret < 0)
494 goto error;
495 /* Insert the stream that contains the last event */
496 ret = heap_insert(iter->stream_heap, cfs);
497 if (ret)
498 goto error;
499 break;
500 }
dc81689e
JD
501 default:
502 /* not implemented */
7344374e 503 return -EINVAL;
90fcbacc
JD
504 }
505
506 return 0;
dc81689e 507
90fcbacc
JD
508error:
509 heap_free(iter->stream_heap);
bed54c92 510error_heap_init:
dc81689e
JD
511 if (heap_init(iter->stream_heap, 0, stream_compare) < 0) {
512 heap_free(iter->stream_heap);
513 g_free(iter->stream_heap);
514 iter->stream_heap = NULL;
515 ret = -ENOMEM;
516 }
bed54c92 517
dc81689e 518 return ret;
90fcbacc
JD
519}
520
521struct bt_iter_pos *bt_iter_get_pos(struct bt_iter *iter)
522{
523 struct bt_iter_pos *pos;
7f89ddce 524 struct trace_collection *tc;
6fabd7af
JD
525 struct ctf_file_stream *file_stream = NULL, *removed;
526 struct ptr_heap iter_heap_copy;
527 int ret;
90fcbacc 528
7f89ddce
MD
529 if (!iter)
530 return NULL;
531
532 tc = iter->ctx->tc;
90fcbacc 533 pos = g_new0(struct bt_iter_pos, 1);
5acdc773 534 pos->type = BT_SEEK_RESTORE;
90fcbacc 535 pos->u.restore = g_new0(struct bt_saved_pos, 1);
90fcbacc
JD
536 pos->u.restore->tc = tc;
537 pos->u.restore->stream_saved_pos = g_array_new(FALSE, TRUE,
538 sizeof(struct stream_saved_pos));
539 if (!pos->u.restore->stream_saved_pos)
540 goto error;
541
6fabd7af
JD
542 ret = heap_copy(&iter_heap_copy, iter->stream_heap);
543 if (ret < 0)
544 goto error_heap;
90fcbacc 545
6fabd7af
JD
546 /* iterate over each stream in the heap */
547 file_stream = heap_maximum(&iter_heap_copy);
548 while (file_stream != NULL) {
549 struct stream_saved_pos saved_pos;
90fcbacc 550
6fabd7af
JD
551 assert(file_stream->pos.last_offset != LAST_OFFSET_POISON);
552 saved_pos.offset = file_stream->pos.last_offset;
553 saved_pos.file_stream = file_stream;
554 saved_pos.cur_index = file_stream->pos.cur_index;
90fcbacc 555
03798a93
JD
556 saved_pos.current_real_timestamp = file_stream->parent.real_timestamp;
557 saved_pos.current_cycles_timestamp = file_stream->parent.cycles_timestamp;
90fcbacc 558
6fabd7af
JD
559 g_array_append_val(
560 pos->u.restore->stream_saved_pos,
561 saved_pos);
90fcbacc 562
6fabd7af
JD
563 printf_debug("stream : %" PRIu64 ", cur_index : %zd, "
564 "offset : %zd, "
565 "timestamp = %" PRIu64 "\n",
566 file_stream->parent.stream_id,
567 saved_pos.cur_index, saved_pos.offset,
03798a93 568 saved_pos.current_real_timestamp);
6fabd7af
JD
569
570 /* remove the stream from the heap copy */
571 removed = heap_remove(&iter_heap_copy);
572 assert(removed == file_stream);
573
574 file_stream = heap_maximum(&iter_heap_copy);
575 }
576 heap_free(&iter_heap_copy);
90fcbacc
JD
577 return pos;
578
6fabd7af
JD
579error_heap:
580 g_array_free(pos->u.restore->stream_saved_pos, TRUE);
90fcbacc 581error:
6fabd7af 582 g_free(pos);
90fcbacc
JD
583 return NULL;
584}
585
dc81689e
JD
586struct bt_iter_pos *bt_iter_create_time_pos(struct bt_iter *iter,
587 uint64_t timestamp)
588{
589 struct bt_iter_pos *pos;
590
7f89ddce
MD
591 if (!iter)
592 return NULL;
593
dc81689e
JD
594 pos = g_new0(struct bt_iter_pos, 1);
595 pos->type = BT_SEEK_TIME;
596 pos->u.seek_time = timestamp;
597 return pos;
598}
599
6f3077a2
JD
600/*
601 * babeltrace_filestream_seek: seek a filestream to given position.
602 *
603 * The stream_id parameter is only useful for BT_SEEK_RESTORE.
604 */
605static int babeltrace_filestream_seek(struct ctf_file_stream *file_stream,
e8c92a62 606 const struct bt_iter_pos *begin_pos,
6f3077a2
JD
607 unsigned long stream_id)
608{
609 int ret = 0;
610
7f89ddce
MD
611 if (!file_stream || !begin_pos)
612 return -EINVAL;
613
6f3077a2
JD
614 switch (begin_pos->type) {
615 case BT_SEEK_CUR:
616 /*
617 * just insert into the heap we should already know
618 * the timestamps
619 */
620 break;
621 case BT_SEEK_BEGIN:
06789ffd 622 file_stream->pos.packet_seek(&file_stream->pos.parent,
d6425aaf 623 0, SEEK_SET);
6f3077a2
JD
624 ret = stream_read_event(file_stream);
625 break;
626 case BT_SEEK_TIME:
627 case BT_SEEK_RESTORE:
628 case BT_SEEK_END:
629 default:
630 assert(0); /* Not yet defined */
631 }
632
633 return ret;
634}
635
e4195791
MD
636int bt_iter_init(struct bt_iter *iter,
637 struct bt_context *ctx,
04ae3991
MD
638 const struct bt_iter_pos *begin_pos,
639 const struct bt_iter_pos *end_pos)
6f3077a2
JD
640{
641 int i, stream_id;
642 int ret = 0;
6f3077a2 643
7f89ddce
MD
644 if (!iter || !ctx)
645 return -EINVAL;
646
e003e871
JD
647 if (ctx->current_iterator) {
648 ret = -1;
649 goto error_ctx;
650 }
651
6f3077a2 652 iter->stream_heap = g_new(struct ptr_heap, 1);
6f3077a2 653 iter->end_pos = end_pos;
6cba487f 654 bt_context_get(ctx);
95d36295 655 iter->ctx = ctx;
6f3077a2
JD
656
657 ret = heap_init(iter->stream_heap, 0, stream_compare);
658 if (ret < 0)
659 goto error_heap_init;
660
95d36295 661 for (i = 0; i < ctx->tc->array->len; i++) {
6f3077a2
JD
662 struct ctf_trace *tin;
663 struct trace_descriptor *td_read;
664
95d36295 665 td_read = g_ptr_array_index(ctx->tc->array, i);
e32cb1e4
MD
666 if (!td_read)
667 continue;
6f3077a2
JD
668 tin = container_of(td_read, struct ctf_trace, parent);
669
670 /* Populate heap with each stream */
671 for (stream_id = 0; stream_id < tin->streams->len;
672 stream_id++) {
f380e105 673 struct ctf_stream_declaration *stream;
6f3077a2
JD
674 int filenr;
675
676 stream = g_ptr_array_index(tin->streams, stream_id);
677 if (!stream)
678 continue;
679 for (filenr = 0; filenr < stream->streams->len;
680 filenr++) {
681 struct ctf_file_stream *file_stream;
682
683 file_stream = g_ptr_array_index(stream->streams,
684 filenr);
e32cb1e4
MD
685 if (!file_stream)
686 continue;
6f3077a2 687 if (begin_pos) {
b42d4e4e
JD
688 ret = babeltrace_filestream_seek(
689 file_stream,
690 begin_pos,
6f3077a2 691 stream_id);
b42d4e4e
JD
692 } else {
693 struct bt_iter_pos pos;
694 pos.type = BT_SEEK_BEGIN;
695 ret = babeltrace_filestream_seek(
696 file_stream, &pos,
697 stream_id);
698 }
699 if (ret == EOF) {
700 ret = 0;
701 continue;
702 } else if (ret) {
703 goto error;
6f3077a2
JD
704 }
705 /* Add to heap */
706 ret = heap_insert(iter->stream_heap, file_stream);
707 if (ret)
708 goto error;
709 }
710 }
711 }
712
e003e871 713 ctx->current_iterator = iter;
e4195791 714 return 0;
6f3077a2
JD
715
716error:
717 heap_free(iter->stream_heap);
718error_heap_init:
719 g_free(iter->stream_heap);
bed54c92 720 iter->stream_heap = NULL;
e003e871 721error_ctx:
e4195791 722 return ret;
6f3077a2
JD
723}
724
e4195791 725struct bt_iter *bt_iter_create(struct bt_context *ctx,
04ae3991
MD
726 const struct bt_iter_pos *begin_pos,
727 const struct bt_iter_pos *end_pos)
e4195791
MD
728{
729 struct bt_iter *iter;
730 int ret;
731
7f89ddce
MD
732 if (!ctx)
733 return NULL;
734
e4195791
MD
735 iter = g_new0(struct bt_iter, 1);
736 ret = bt_iter_init(iter, ctx, begin_pos, end_pos);
737 if (ret) {
738 g_free(iter);
739 return NULL;
740 }
741 return iter;
742}
743
744void bt_iter_fini(struct bt_iter *iter)
6f3077a2 745{
7f89ddce 746 assert(iter);
dc81689e
JD
747 if (iter->stream_heap) {
748 heap_free(iter->stream_heap);
749 g_free(iter->stream_heap);
750 }
e003e871 751 iter->ctx->current_iterator = NULL;
95d36295 752 bt_context_put(iter->ctx);
e4195791 753}
95d36295 754
e4195791
MD
755void bt_iter_destroy(struct bt_iter *iter)
756{
7f89ddce 757 assert(iter);
e4195791 758 bt_iter_fini(iter);
90fcbacc 759 g_free(iter);
6f3077a2
JD
760}
761
e8c92a62 762int bt_iter_next(struct bt_iter *iter)
6f3077a2
JD
763{
764 struct ctf_file_stream *file_stream, *removed;
765 int ret;
766
7f89ddce
MD
767 if (!iter)
768 return -EINVAL;
769
6f3077a2
JD
770 file_stream = heap_maximum(iter->stream_heap);
771 if (!file_stream) {
772 /* end of file for all streams */
773 ret = 0;
774 goto end;
775 }
776
777 ret = stream_read_event(file_stream);
778 if (ret == EOF) {
779 removed = heap_remove(iter->stream_heap);
780 assert(removed == file_stream);
781 ret = 0;
782 goto end;
783 } else if (ret) {
784 goto end;
785 }
786 /* Reinsert the file stream into the heap, and rebalance. */
787 removed = heap_replace_max(iter->stream_heap, file_stream);
788 assert(removed == file_stream);
789
790end:
791 return ret;
792}
This page took 0.104742 seconds and 4 git commands to generate.