int bt_iter_init(struct bt_iter *iter, struct bt_context *ctx, const struct bt_iter_pos *begin_pos, const struct bt_iter_pos *end_pos) { int i; int ret = 0; if (!iter || !ctx || !ctx->tc || !ctx->tc->array) return -EINVAL; if (ctx->current_iterator) { ret = -1; goto error_ctx; } iter->stream_heap = g_new(struct ptr_heap, 1); iter->end_pos = end_pos; bt_context_get(ctx); iter->ctx = ctx; ret = bt_heap_init(iter->stream_heap, 0, stream_compare); if (ret < 0) goto error_heap_init; for (i = 0; i < ctx->tc->array->len; i++) { struct bt_trace_descriptor *td_read; td_read = g_ptr_array_index(ctx->tc->array, i); if (!td_read) continue; ret = bt_iter_add_trace(iter, td_read); if (ret < 0) goto error; } ctx->current_iterator = iter; if (begin_pos && begin_pos->type != BT_SEEK_BEGIN) { ret = bt_iter_set_pos(iter, begin_pos); if (ret) { goto error; } } return ret; error: bt_heap_free(iter->stream_heap); error_heap_init: g_free(iter->stream_heap); iter->stream_heap = NULL; error_ctx: return ret; }
int bt_heap_copy(struct ptr_heap *dst, struct ptr_heap *src) { int ret; ret = bt_heap_init(dst, src->alloc_len, src->gt); if (ret < 0) goto end; ret = heap_set_len(dst, src->len); if (ret < 0) goto end; memcpy(dst->ptrs, src->ptrs, src->len * sizeof(void *)); end: return ret; }
int bt_iter_set_pos(struct bt_iter *iter, const struct bt_iter_pos *iter_pos) { struct trace_collection *tc; int i, ret; if (!iter || !iter_pos) return -EINVAL; switch (iter_pos->type) { case BT_SEEK_RESTORE: if (!iter_pos->u.restore) return -EINVAL; bt_heap_free(iter->stream_heap); ret = bt_heap_init(iter->stream_heap, 0, stream_compare); if (ret < 0) goto error_heap_init; for (i = 0; i < iter_pos->u.restore->stream_saved_pos->len; i++) { struct stream_saved_pos *saved_pos; struct ctf_stream_pos *stream_pos; struct ctf_stream_definition *stream; saved_pos = &g_array_index( iter_pos->u.restore->stream_saved_pos, struct stream_saved_pos, i); stream = &saved_pos->file_stream->parent; stream_pos = &saved_pos->file_stream->pos; stream_pos->packet_seek(&stream_pos->parent, saved_pos->cur_index, SEEK_SET); /* * the timestamp needs to be restored after * packet_seek, because this function resets * the timestamp to the beginning of the packet */ stream->real_timestamp = saved_pos->current_real_timestamp; stream->cycles_timestamp = saved_pos->current_cycles_timestamp; stream_pos->offset = saved_pos->offset; stream_pos->last_offset = LAST_OFFSET_POISON; stream->current.real.begin = 0; stream->current.real.end = 0; stream->current.cycles.begin = 0; stream->current.cycles.end = 0; stream->prev.real.begin = 0; stream->prev.real.end = 0; stream->prev.cycles.begin = 0; stream->prev.cycles.end = 0; printf_debug("restored to cur_index = %" PRId64 " and " "offset = %" PRId64 ", timestamp = %" PRIu64 "\n", stream_pos->cur_index, stream_pos->offset, stream->real_timestamp); ret = stream_read_event(saved_pos->file_stream); if (ret != 0) { goto error; } /* Add to heap */ ret = bt_heap_insert(iter->stream_heap, saved_pos->file_stream); if (ret) goto error; } return 0; case BT_SEEK_TIME: tc = iter->ctx->tc; bt_heap_free(iter->stream_heap); ret = bt_heap_init(iter->stream_heap, 0, stream_compare); if (ret < 0) goto error_heap_init; /* for each trace in the trace_collection */ for (i = 0; i < tc->array->len; i++) { struct ctf_trace *tin; struct bt_trace_descriptor *td_read; td_read = g_ptr_array_index(tc->array, i); if (!td_read) continue; tin = container_of(td_read, struct ctf_trace, parent); ret = seek_ctf_trace_by_timestamp(tin, iter_pos->u.seek_time, iter->stream_heap); /* * Positive errors are failure. Negative value * is EOF (for which we continue with other * traces). 0 is success. Note: on EOF, it just * means that no stream has been added to the * iterator for that trace, which is fine. */ if (ret != 0 && ret != EOF) goto error; } return 0; case BT_SEEK_BEGIN: tc = iter->ctx->tc; bt_heap_free(iter->stream_heap); ret = bt_heap_init(iter->stream_heap, 0, stream_compare); if (ret < 0) goto error_heap_init; for (i = 0; i < tc->array->len; i++) { struct ctf_trace *tin; struct bt_trace_descriptor *td_read; int stream_id; td_read = g_ptr_array_index(tc->array, i); if (!td_read) continue; tin = container_of(td_read, struct ctf_trace, parent); /* Populate heap with each stream */ for (stream_id = 0; stream_id < tin->streams->len; stream_id++) { struct ctf_stream_declaration *stream; int filenr; stream = g_ptr_array_index(tin->streams, stream_id); if (!stream) continue; for (filenr = 0; filenr < stream->streams->len; filenr++) { struct ctf_file_stream *file_stream; file_stream = g_ptr_array_index( stream->streams, filenr); if (!file_stream) continue; ret = babeltrace_filestream_seek( file_stream, iter_pos, stream_id); if (ret != 0 && ret != EOF) { goto error; } if (ret == EOF) { /* Do not add EOF streams */ continue; } ret = bt_heap_insert(iter->stream_heap, file_stream); if (ret) goto error; } } } break; case BT_SEEK_LAST: { struct ctf_file_stream *cfs = NULL; tc = iter->ctx->tc; ret = seek_last_ctf_trace_collection(tc, &cfs); if (ret != 0 || !cfs) goto error; /* remove all streams from the heap */ bt_heap_free(iter->stream_heap); /* Create a new empty heap */ ret = bt_heap_init(iter->stream_heap, 0, stream_compare); if (ret < 0) goto error; /* Insert the stream that contains the last event */ ret = bt_heap_insert(iter->stream_heap, cfs); if (ret) goto error; break; } default: /* not implemented */ return -EINVAL; } return 0; error: bt_heap_free(iter->stream_heap); error_heap_init: if (bt_heap_init(iter->stream_heap, 0, stream_compare) < 0) { bt_heap_free(iter->stream_heap); g_free(iter->stream_heap); iter->stream_heap = NULL; ret = -ENOMEM; } return ret; }