int bt_iter_next(struct bt_iter *iter) { struct ctf_file_stream *file_stream, *removed; int ret; bool event_outside_interval = false; if (!iter) return -EINVAL; file_stream = bt_heap_maximum(iter->stream_heap); if (!file_stream) { /* end of file for all streams */ ret = 0; goto end; } ret = stream_read_event(file_stream); if (file_stream->pos.parent.trace && file_stream->pos.parent.trace->interval_set) { event_outside_interval = file_stream->parent.real_timestamp > file_stream->pos.parent.trace->interval_real.timestamp_end; } if (ret == EOF || event_outside_interval) { removed = bt_heap_remove(iter->stream_heap); assert(removed == file_stream); ret = 0; goto end; } else if (ret == EAGAIN) { /* * Live streaming: the stream is inactive for now, we * just updated the timestamp_end to skip over this * stream up to a certain point in time. * * Since we can't guarantee that a stream will ever have * any activity, we can't rely on the fact that * bt_iter_next will be called for each stream and deal * with inactive streams. So instead, we return 0 here * to the caller and let the read API handle the * retry case. */ ret = 0; goto reinsert; } else if (ret) { goto end; } reinsert: /* Reinsert the file stream into the heap, and rebalance. */ removed = bt_heap_replace_max(iter->stream_heap, file_stream); assert(removed == file_stream); end: return ret; }
void *bt_heap_remove(struct ptr_heap *heap) { switch (heap->len) { case 0: return NULL; case 1: (void) heap_set_len(heap, 0); return heap->ptrs[0]; } /* Shrink, replace the current max by previous last entry and heapify */ heap_set_len(heap, heap->len - 1); /* len changed. previous last entry is at heap->len */ return bt_heap_replace_max(heap, heap->ptrs[heap->len]); }