| 477 | } |
| 478 | |
| 479 | void KrpcDataStreamRecvr::SenderQueue::AddBatch(const TransmitDataRequestPB* request, |
| 480 | TransmitDataResponsePB* response, RpcContext* rpc_context) { |
| 481 | // TODO: Add timers for time spent in this function and queue time in 'batch_queue_'. |
| 482 | const RowBatchHeaderPB& header = request->row_batch_header(); |
| 483 | kudu::Slice tuple_offsets; |
| 484 | kudu::Slice tuple_data; |
| 485 | int64_t batch_size = RowBatch::GetDeserializedSize(header); |
| 486 | Status status = UnpackRequest(request, rpc_context, &tuple_offsets, &tuple_data); |
| 487 | if (UNLIKELY(!status.ok())) { |
| 488 | { |
| 489 | unique_lock<SpinLock> l(lock_); |
| 490 | MarkErrorStatus(status, l); |
| 491 | } |
| 492 | TRACE_TO(rpc_context->trace(), "Error unpacking request: $0", status.GetDetail()); |
| 493 | DataStreamService::RespondRpc(status, response, rpc_context); |
| 494 | return; |
| 495 | } |
| 496 | COUNTER_ADD(recvr_->total_received_batches_counter_, 1); |
| 497 | // To be consistent with the senders, only count the sidecars size. |
| 498 | COUNTER_ADD(recvr_->bytes_received_counter_, tuple_data.size() + tuple_offsets.size()); |
| 499 | |
| 500 | { |
| 501 | unique_lock<SpinLock> l(lock_); |
| 502 | // There should be one or more senders left when this function is called. The reason |
| 503 | // is that EndDataStream RPC is not sent until all outstanding TransmitData() RPC has |
| 504 | // been replied to. There is at least one TransmitData() RPC which hasn't yet been |
| 505 | // responded to if we reach here. |
| 506 | DCHECK_GT(num_remaining_senders_, 0); |
| 507 | if (UNLIKELY(is_cancelled_)) { |
| 508 | lock_.unlock(); |
| 509 | Status cancel_status = Status::Expected(TErrorCode::DATASTREAM_RECVR_CLOSED, |
| 510 | PrintId(recvr_->fragment_instance_id()), recvr_->dest_node_id()); |
| 511 | TRACE_TO(rpc_context->trace(), "Receiver was cancelled"); |
| 512 | DataStreamService::RespondRpc(cancel_status, response, rpc_context); |
| 513 | return; |
| 514 | } |
| 515 | |
| 516 | // If there's something in the queue or this batch will push us over the buffer |
| 517 | // limit we need to wait until the queue gets drained. We store the rpc context |
| 518 | // so that we can signal it at a later time to resend the batch that we couldn't |
| 519 | // process here. If there are already deferred RPCs waiting in queue, the new |
| 520 | // batch needs to line up after the deferred RPCs to avoid starvation of senders |
| 521 | // in the non-merging case. |
| 522 | if (!deferred_rpcs_.empty() || !CanEnqueue(batch_size)) { |
| 523 | recvr_->deferred_rpc_tracker()->Consume(rpc_context->GetTransferSize()); |
| 524 | auto payload = make_unique<TransmitDataCtx>( |
| 525 | request, response, rpc_context); |
| 526 | EnqueueDeferredRpc(move(payload)); |
| 527 | return; |
| 528 | } |
| 529 | |
| 530 | // At this point, we are committed to inserting the row batch into 'batch_queue_'. |
| 531 | status = AddBatchWork(batch_size, header, tuple_offsets, tuple_data, &l, rpc_context); |
| 532 | } |
| 533 | |
| 534 | // Respond to the sender to ack the insertion of the row batches. |
| 535 | DataStreamService::RespondRpc(status, response, rpc_context); |
| 536 | } |
nothing calls this directly
no test coverage detected