| 1541 | ReadStats stats() const override { return stats_.poll(); } |
| 1542 | |
| 1543 | Result<AsyncGenerator<std::shared_ptr<RecordBatch>>> GetRecordBatchGenerator( |
| 1544 | const bool coalesce, const io::IOContext& io_context, |
| 1545 | const io::CacheOptions cache_options, |
| 1546 | arrow::internal::Executor* executor) override { |
| 1547 | auto state = std::dynamic_pointer_cast<RecordBatchFileReaderImpl>(shared_from_this()); |
| 1548 | // Prebuffering causes us to use a lot of futures which, at the moment, |
| 1549 | // can only slow things down when we are doing zero-copy in-memory reads. |
| 1550 | // |
| 1551 | // Prebuffering's read patterns are also slightly worse than the alternative |
| 1552 | // when doing whole-file reads because the logic is not in place to recognize |
| 1553 | // we can just read the entire file up-front |
| 1554 | if (!options_.included_fields.empty() && |
| 1555 | options_.included_fields.size() != schema_->fields().size() && |
| 1556 | !file_->supports_zero_copy()) { |
| 1557 | RETURN_NOT_OK(state->PreBufferMetadata({})); |
| 1558 | return SelectiveIpcFileRecordBatchGenerator(std::move(state)); |
| 1559 | } |
| 1560 | |
| 1561 | std::shared_ptr<io::internal::ReadRangeCache> cached_source; |
| 1562 | if (coalesce && !file_->supports_zero_copy()) { |
| 1563 | if (!owned_file_) return Status::Invalid("Cannot coalesce without an owned file"); |
| 1564 | // Since the user is asking for all fields then we can cache the entire |
| 1565 | // file (up to the footer) |
| 1566 | cached_source = std::make_shared<io::internal::ReadRangeCache>(file_, io_context, |
| 1567 | cache_options); |
| 1568 | RETURN_NOT_OK(cached_source->Cache({{0, footer_offset_}})); |
| 1569 | } |
| 1570 | return WholeIpcFileRecordBatchGenerator(std::move(state), std::move(cached_source), |
| 1571 | io_context, executor); |
| 1572 | } |
| 1573 | |
| 1574 | Status DoPreBufferMetadata(const std::vector<int>& indices) { |
| 1575 | RETURN_NOT_OK(CacheMetadata(indices)); |