| 481 | } |
| 482 | |
| 483 | Status FragmentInstanceState::ExecInternal() { |
| 484 | DCHECK_EQ(current_state_.Load(), FInstanceExecStatePB::WAITING_FOR_OPEN); |
| 485 | // Inject failure if debug actions are enabled. |
| 486 | RETURN_IF_ERROR(DebugAction(query_state_->query_options(), "FIS_IN_EXEC_INTERNAL")); |
| 487 | |
| 488 | RuntimeProfile::Counter* plan_exec_timer = |
| 489 | ADD_CHILD_TIMER(timings_profile_, "ExecTreeExecTime", EXEC_TIMER_NAME); |
| 490 | RuntimeProfile::SummaryStatsCounter* row_batch_mem_alloc_duration = |
| 491 | PROFILE_RowBatchMemPoolAllocDuration.Instantiate(profile()); |
| 492 | RuntimeProfile::SummaryStatsCounter* row_batch_mem_alloc_bytes = |
| 493 | PROFILE_RowBatchMemPoolAllocBytes.Instantiate(profile()); |
| 494 | RuntimeProfile::SummaryStatsCounter* row_batch_mem_free_duration = |
| 495 | PROFILE_RowBatchMemPoolFreeDuration.Instantiate(profile()); |
| 496 | RuntimeProfile::SummaryStatsCounter* row_batch_mem_free_bytes = |
| 497 | PROFILE_RowBatchMemPoolFreeBytes.Instantiate(profile()); |
| 498 | auto update_counters = MakeScopeExitTrigger([&]() { |
| 499 | MemPoolCounters mem_counters = row_batch_->GetMemPoolCounters(); |
| 500 | row_batch_mem_alloc_duration->Merge(mem_counters.sys_alloc_duration); |
| 501 | row_batch_mem_alloc_bytes->Merge(mem_counters.allocated_bytes); |
| 502 | row_batch_mem_free_duration->Merge(mem_counters.sys_free_duration); |
| 503 | row_batch_mem_free_bytes->Merge(mem_counters.freed_bytes); |
| 504 | }); |
| 505 | SCOPED_THREAD_COUNTER_MEASUREMENT(runtime_state_->total_thread_statistics()); |
| 506 | bool exec_tree_complete = false; |
| 507 | UpdateState(StateEvent::WAITING_FOR_FIRST_BATCH); |
| 508 | do { |
| 509 | Status status; |
| 510 | row_batch_->Reset(); |
| 511 | { |
| 512 | SCOPED_TIMER(plan_exec_timer); |
| 513 | RETURN_IF_ERROR( |
| 514 | exec_tree_->GetNext(runtime_state_, row_batch_.get(), &exec_tree_complete)); |
| 515 | } |
| 516 | UpdateState(StateEvent::BATCH_PRODUCED); |
| 517 | if (VLOG_ROW_IS_ON) row_batch_->VLogRows("FragmentInstanceState::ExecInternal()"); |
| 518 | COUNTER_ADD(rows_produced_counter_, row_batch_->num_rows()); |
| 519 | RETURN_IF_ERROR(sink_->Send(runtime_state_, row_batch_.get())); |
| 520 | UpdateState(StateEvent::BATCH_SENT); |
| 521 | } while (!exec_tree_complete); |
| 522 | // Release resources from final row batch. |
| 523 | row_batch_->Reset(); |
| 524 | |
| 525 | UpdateState(StateEvent::LAST_BATCH_SENT); |
| 526 | |
| 527 | // Close the tree before the sink is flushed to release 'exec_tree_' resources. |
| 528 | // This can significantly reduce resource consumption if 'sink_' is a join |
| 529 | // build, where FlushFinal() blocks until the consuming fragment is finished. |
| 530 | exec_tree_->Close(runtime_state_); |
| 531 | |
| 532 | // Flush the sink as a final step. |
| 533 | RETURN_IF_ERROR(sink_->FlushFinal(runtime_state())); |
| 534 | return Status::OK(); |
| 535 | } |
| 536 | |
| 537 | void FragmentInstanceState::Close() { |
| 538 | DCHECK(runtime_state_ != nullptr); |
nothing calls this directly
no test coverage detected