MCPcopy Create free account
hub / github.com/apache/datafusion / poll_scan

Method poll_scan

datafusion/datasource/src/file_stream/scan_state.rs:125–291  ·  view source on GitHub ↗

Drives one iteration of the active scan state. Work is attempted in this order: 1. resolve any pending planner I/O 2. poll the active reader 3. turn a ready morsel into the active reader 4. run CPU planning on a ready planner 5. morselize the next unopened file The return [`ScanAndReturn`] tells `poll_inner` how to update the outer `FileStreamState`.

(&mut self, cx: &mut Context<'_>)

Source from the content-addressed store, hash-verified

123 /// The return [`ScanAndReturn`] tells `poll_inner` how to update the
124 /// outer `FileStreamState`.
125 pub(super) fn poll_scan(&mut self, cx: &mut Context<'_>) -> ScanAndReturn {
126 let _processing_timer: ScopedTimerGuard<'_> =
127 self.metrics.time_processing.timer();
128
129 // Try and resolve outstanding IO first. If it is still pending, check
130 // the current reader or ready morsels before yielding. New planning
131 // work must still wait for this I/O to resolve.
132 if let Some(mut pending_planner) = self.pending_planner.take() {
133 match pending_planner.poll_unpin(cx) {
134 // IO is still pending
135 Poll::Pending => {
136 self.pending_planner = Some(pending_planner);
137 }
138 // IO resolved, and the planner is ready for CPU work
139 Poll::Ready(Ok(planner)) => {
140 self.ready_planners.push_back(planner);
141 }
142 // IO Error
143 Poll::Ready(Err(err)) => {
144 self.metrics.file_open_errors.add(1);
145 self.metrics.time_opening.stop();
146 return match self.on_error {
147 OnError::Skip => {
148 self.metrics.files_processed.add(1);
149 ScanAndReturn::Continue
150 }
151 OnError::Fail => ScanAndReturn::Error(err),
152 };
153 }
154 }
155 }
156
157 // Next try and get the next batch from the active reader, if any.
158 if let Some(reader) = self.reader.as_mut() {
159 match reader.poll_next_unpin(cx) {
160 // Morsels should ideally only expose ready-to-decode streams,
161 // but tolerate pending readers here.
162 Poll::Pending => return ScanAndReturn::Return(Poll::Pending),
163 Poll::Ready(Some(Ok(batch))) => {
164 self.metrics.time_scanning_until_data.stop();
165 self.metrics.time_scanning_total.stop();
166 // Apply any remaining row limit.
167 let (batch, finished) = match &mut self.remain {
168 Some(remain) => {
169 if *remain > batch.num_rows() {
170 *remain -= batch.num_rows();
171 self.metrics.time_scanning_total.start();
172 (batch, false)
173 } else {
174 let batch = batch.slice(0, *remain);
175 let done = 1 + self.work_source.skipped_on_limit();
176 self.metrics.files_processed.add(done);
177 *remain = 0;
178 (batch, true)
179 }
180 }
181 None => {
182 self.metrics.time_scanning_total.start();

Callers 1

poll_innerMethod · 0.80

Calls 15

timerMethod · 0.80
sliceMethod · 0.80
skipped_on_limitMethod · 0.80
pop_frontMethod · 0.80
take_morselsMethod · 0.80
take_ready_plannersMethod · 0.80
take_pending_plannerMethod · 0.80
ErrorEnum · 0.50
takeMethod · 0.45
addMethod · 0.45
stopMethod · 0.45
startMethod · 0.45

Tested by

no test coverage detected