| 60 | } |
| 61 | |
| 62 | Status BufferedPlanRootSink::Send(RuntimeState* state, RowBatch* batch) { |
| 63 | SCOPED_TIMER(profile()->total_time_counter()); |
| 64 | // If the batch is empty, we have nothing to do so just return Status::OK(). |
| 65 | if (batch->num_rows() == 0) return Status::OK(); |
| 66 | |
| 67 | // Close should only be called by the producer thread, no RowBatches should be sent |
| 68 | // after the sink is closed. |
| 69 | DCHECK(!closed_); |
| 70 | DCHECK(batch_queue_->IsOpen()); |
| 71 | RETURN_IF_ERROR(PlanRootSink::UpdateAndCheckRowsProducedLimit(state, batch)); |
| 72 | |
| 73 | { |
| 74 | // Add the copied batch to the RowBatch queue and wake up the consumer thread if it is |
| 75 | // waiting for rows to process. |
| 76 | unique_lock<mutex> l(lock_); |
| 77 | |
| 78 | // If the queue is full, wait for the producer thread to read batches from it. |
| 79 | while (!state->is_cancelled() && batch_queue_->IsFull()) { |
| 80 | SCOPED_TIMER(profile()->inactive_timer()); |
| 81 | SCOPED_TIMER(row_batches_send_wait_timer_); |
| 82 | // Set this to true means the batch queue is full. |
| 83 | discard_result(all_results_spooled_.Set(true)); |
| 84 | batch_queue_has_capacity_.Wait(l); |
| 85 | } |
| 86 | RETURN_IF_CANCELLED(state); |
| 87 | |
| 88 | // Debug action before AddBatch is called. |
| 89 | RETURN_IF_ERROR(DebugAction(state->query_options(), "BPRS_BEFORE_ADD_BATCH")); |
| 90 | |
| 91 | // Add the batch to the queue and then notify the consumer that rows are available. |
| 92 | RETURN_IF_ERROR(batch_queue_->AddBatch(batch)); |
| 93 | rows_sent_counter_->Add(batch->num_rows()); |
| 94 | } |
| 95 | // Release the lock before calling notify so the consumer thread can immediately acquire |
| 96 | // the lock. |
| 97 | rows_available_.NotifyOne(); |
| 98 | return Status::OK(); |
| 99 | } |
| 100 | |
| 101 | Status BufferedPlanRootSink::FlushFinal(RuntimeState* state) { |
| 102 | SCOPED_TIMER(profile()->total_time_counter()); |
nothing calls this directly
no test coverage detected