From fd7199f64ec05c46f6aebd8644bbcb78f2889898 Mon Sep 17 00:00:00 2001 From: Yang Gao <yangg@google.com> Date: Wed, 11 Feb 2015 23:14:49 -0800 Subject: [PATCH] Add client side WaitForInitialMetadata for streaming. --- include/grpc++/impl/call.h | 9 +++++++++ include/grpc++/stream.h | 29 +++++++++++++++++++++++++++++ src/cpp/common/call.cc | 6 ++++++ 3 files changed, 44 insertions(+) diff --git a/include/grpc++/impl/call.h b/include/grpc++/impl/call.h index a1ef9268f0..5fafd0e890 100644 --- a/include/grpc++/impl/call.h +++ b/include/grpc++/impl/call.h @@ -134,7 +134,16 @@ class Call final { grpc_call *call() { return call_; } CompletionQueue *cq() { return cq_; } + // TODO(yangg) change it to a general state query function. + bool initial_metadata_received() { + return initial_metadata_received_; + } + void set_initial_metadata_received() { + initial_metadata_received_ = true; + } + private: + bool initial_metadata_received_ = false; CallHook *call_hook_; CompletionQueue *cq_; grpc_call* call_; diff --git a/include/grpc++/stream.h b/include/grpc++/stream.h index a59ccd8c05..6da1be4e9f 100644 --- a/include/grpc++/stream.h +++ b/include/grpc++/stream.h @@ -98,7 +98,22 @@ class ClientReader final : public ClientStreamingInterface, cq_.Pluck(&buf); } + // Blocking wait for initial metadata from server. The received metadata + // can only be accessed after this call returns. Calling this method is + // optional as it will be called internally before the first Read. + void WaitForInitialMetadata() { + if (!call_.initial_metadata_received()) { + CallOpBuffer buf; + buf.AddRecvInitialMetadata(&context_->recv_initial_metadata_); + call_.PerformOps(&buf); + GPR_ASSERT(cq_.Pluck(&buf)); + call_.set_initial_metadata_received(); + } + } + + virtual bool Read(R *msg) override { + WaitForInitialMetadata(); CallOpBuffer buf; bool got_message; buf.AddRecvMessage(msg, &got_message); @@ -186,7 +201,21 @@ class ClientReaderWriter final : public ClientStreamingInterface, GPR_ASSERT(cq_.Pluck(&buf)); } + // Blocking wait for initial metadata from server. The received metadata + // can only be accessed after this call returns. Calling this method is + // optional as it will be called internally before the first Read. + void WaitForInitialMetadata() { + if (!call_.initial_metadata_received()) { + CallOpBuffer buf; + buf.AddRecvInitialMetadata(&context_->recv_initial_metadata_); + call_.PerformOps(&buf); + GPR_ASSERT(cq_.Pluck(&buf)); + call_.set_initial_metadata_received(); + } + } + virtual bool Read(R *msg) override { + WaitForInitialMetadata(); CallOpBuffer buf; bool got_message; buf.AddRecvMessage(msg, &got_message); diff --git a/src/cpp/common/call.cc b/src/cpp/common/call.cc index a20d4a0d9a..aae69084eb 100644 --- a/src/cpp/common/call.cc +++ b/src/cpp/common/call.cc @@ -121,6 +121,12 @@ void CallOpBuffer::AddSendInitialMetadata( initial_metadata_ = FillMetadataArray(metadata); } +void CallOpBuffer::AddRecvInitialMetadata( + std::multimap<grpc::string, grpc::string>* metadata) { + recv_initial_metadata_ = metadata; +} + + void CallOpBuffer::AddSendInitialMetadata(ClientContext *ctx) { AddSendInitialMetadata(&ctx->send_initial_metadata_); } -- GitLab