| 683 | } |
| 684 | |
| 685 | Status TopNNode::ReclaimTuplePool(RuntimeState* state) { |
| 686 | COUNTER_ADD(tuple_pool_reclaim_counter_, 1); |
| 687 | unique_ptr<MemPool> temp_pool(new MemPool(mem_tracker())); |
| 688 | |
| 689 | if (is_partitioned()) { |
| 690 | vector<unique_ptr<Heap>> rematerialized_heaps; |
| 691 | for (auto& entry : partition_heaps_) { |
| 692 | RETURN_IF_ERROR(entry.second->RematerializeTuples(this, state, temp_pool.get())); |
| 693 | DCHECK(entry.second->DCheckConsistency()); |
| 694 | } |
| 695 | // The second loop is needed for IMPALA-11631. We only move heaps from partition_heap_ |
| 696 | // to rematerialized_heaps once all have been rematerialized. Otherwise, in case of |
| 697 | // an error, we may call Close() on a nullptr or leak the memory by not explicitly |
| 698 | // calling Close() on the heap pointer. Maybe better to add Close() in the Heap |
| 699 | // destructor later. |
| 700 | for (auto& entry : partition_heaps_) { |
| 701 | // The key references memory in 'tuple_pool_'. Replace it with a rematerialized |
| 702 | // tuple. |
| 703 | rematerialized_heaps.push_back(move(entry.second)); |
| 704 | } |
| 705 | partition_heaps_.clear(); |
| 706 | for (auto& heap_ptr : rematerialized_heaps) { |
| 707 | const Tuple* key_tuple = heap_ptr->top(); |
| 708 | partition_heaps_.emplace(key_tuple, move(heap_ptr)); |
| 709 | } |
| 710 | } else { |
| 711 | RETURN_IF_ERROR(heap_->RematerializeTuples(this, state, temp_pool.get())); |
| 712 | DCHECK(heap_->DCheckConsistency()); |
| 713 | } |
| 714 | rows_to_reclaim_ = 0; |
| 715 | RETURN_IF_ERROR(InitTmpTuple(state, temp_pool.get())); |
| 716 | tuple_pool_->FreeAll(); |
| 717 | tuple_pool_ = move(temp_pool); |
| 718 | return Status::OK(); |
| 719 | } |
| 720 | |
| 721 | Status TopNNode::InitTmpTuple(RuntimeState* state, MemPool* pool) { |
| 722 | tmp_tuple_ = reinterpret_cast<Tuple*>(pool->TryAllocate( |
nothing calls this directly
no test coverage detected