diff options
author | 2018-08-20 20:54:14 -0700 | |
---|---|---|
committer | 2018-08-28 17:00:20 -0700 | |
commit | 743d40d6354c710f91d0fcf918ea2b90aa799ebc (patch) | |
tree | 05994975c2b848e7eeff18969ef8f9c2f88bb9b5 /include | |
parent | ee65a5eaee45a765d1d4176a797bb8288faeb180 (diff) |
Lazily fill metadata map
Diffstat (limited to 'include')
-rw-r--r-- | include/grpcpp/impl/codegen/call.h | 11 | ||||
-rw-r--r-- | include/grpcpp/impl/codegen/client_context.h | 6 | ||||
-rw-r--r-- | include/grpcpp/impl/codegen/metadata_map.h | 29 | ||||
-rw-r--r-- | include/grpcpp/impl/codegen/server_context.h | 3 |
4 files changed, 36 insertions, 13 deletions
diff --git a/include/grpcpp/impl/codegen/call.h b/include/grpcpp/impl/codegen/call.h index a5e930aaa5..e94adada94 100644 --- a/include/grpcpp/impl/codegen/call.h +++ b/include/grpcpp/impl/codegen/call.h @@ -50,8 +50,6 @@ namespace internal { class Call; class CallHook; -const char kBinaryErrorDetailsKey[] = "grpc-status-details-bin"; - // TODO(yangg) if the map is changed before we send, the pointers will be a // mess. Make sure it does not happen. inline grpc_metadata* FillMetadataArray( @@ -531,7 +529,6 @@ class CallOpRecvInitialMetadata { void FinishOp(bool* status) { if (metadata_map_ == nullptr) return; - metadata_map_->FillMap(); metadata_map_ = nullptr; } @@ -566,13 +563,7 @@ class CallOpClientRecvStatus { void FinishOp(bool* status) { if (recv_status_ == nullptr) return; - metadata_map_->FillMap(); - grpc::string binary_error_details; - auto iter = metadata_map_->map()->find(kBinaryErrorDetailsKey); - if (iter != metadata_map_->map()->end()) { - binary_error_details = - grpc::string(iter->second.begin(), iter->second.length()); - } + grpc::string binary_error_details = metadata_map_->GetBinaryErrorDetails(); *recv_status_ = Status(static_cast<StatusCode>(status_code_), GRPC_SLICE_IS_EMPTY(error_message_) diff --git a/include/grpcpp/impl/codegen/client_context.h b/include/grpcpp/impl/codegen/client_context.h index 9dda4c7fac..cf1d901888 100644 --- a/include/grpcpp/impl/codegen/client_context.h +++ b/include/grpcpp/impl/codegen/client_context.h @@ -202,6 +202,7 @@ class ClientContext { const std::multimap<grpc::string_ref, grpc::string_ref>& GetServerInitialMetadata() const { GPR_CODEGEN_ASSERT(initial_metadata_received_); + recv_initial_metadata_.FillMap(); return *recv_initial_metadata_.map(); } @@ -214,6 +215,7 @@ class ClientContext { const std::multimap<grpc::string_ref, grpc::string_ref>& GetServerTrailingMetadata() const { // TODO(yangg) check finished + trailing_metadata_.FillMap(); return *trailing_metadata_.map(); } @@ -425,8 +427,8 @@ class ClientContext { mutable std::shared_ptr<const AuthContext> auth_context_; struct census_context* census_context_; std::multimap<grpc::string, grpc::string> send_initial_metadata_; - internal::MetadataMap recv_initial_metadata_; - internal::MetadataMap trailing_metadata_; + mutable internal::MetadataMap recv_initial_metadata_; + mutable internal::MetadataMap trailing_metadata_; grpc_call* propagate_from_call_; PropagationOptions propagation_options_; diff --git a/include/grpcpp/impl/codegen/metadata_map.h b/include/grpcpp/impl/codegen/metadata_map.h index 0866539d88..6e0c2a9637 100644 --- a/include/grpcpp/impl/codegen/metadata_map.h +++ b/include/grpcpp/impl/codegen/metadata_map.h @@ -19,11 +19,15 @@ #ifndef GRPCPP_IMPL_CODEGEN_METADATA_MAP_H #define GRPCPP_IMPL_CODEGEN_METADATA_MAP_H +#include <grpc/slice.h> #include <grpcpp/impl/codegen/slice.h> namespace grpc { namespace internal { + +const char kBinaryErrorDetailsKey[] = "grpc-status-details-bin"; + class MetadataMap { public: MetadataMap() { memset(&arr_, 0, sizeof(arr_)); } @@ -32,7 +36,31 @@ class MetadataMap { g_core_codegen_interface->grpc_metadata_array_destroy(&arr_); } + grpc::string GetBinaryErrorDetails() { + // if filled, extract from the multimap for O(log(n)) + if (filled) { + auto iter = map_.find(kBinaryErrorDetailsKey); + if (iter != map_.end()) { + return grpc::string(iter->second.begin(), iter->second.length()); + } + } + // if not yet filled, take the O(n) lookup to avoid allocating the + // multimap until it is requested. + else { + for (size_t i = 0; i < arr_.count; i++) { + if (grpc_slice_str_cmp(arr_.metadata[i].key, kBinaryErrorDetailsKey)) { + return grpc::string(reinterpret_cast<const char*>( + GRPC_SLICE_START_PTR(arr_.metadata[i].value)), + GRPC_SLICE_LENGTH(arr_.metadata[i].value)); + } + } + } + return grpc::string(); + } + void FillMap() { + if (filled) return; + filled = true; for (size_t i = 0; i < arr_.count; i++) { // TODO(yangg) handle duplicates? map_.insert(std::pair<grpc::string_ref, grpc::string_ref>( @@ -48,6 +76,7 @@ class MetadataMap { grpc_metadata_array* arr() { return &arr_; } private: + bool filled = false; grpc_metadata_array arr_; std::multimap<grpc::string_ref, grpc::string_ref> map_; }; diff --git a/include/grpcpp/impl/codegen/server_context.h b/include/grpcpp/impl/codegen/server_context.h index 6314364db6..506c51a5d9 100644 --- a/include/grpcpp/impl/codegen/server_context.h +++ b/include/grpcpp/impl/codegen/server_context.h @@ -169,6 +169,7 @@ class ServerContext { /// \return A multimap of initial metadata key-value pairs from the server. const std::multimap<grpc::string_ref, grpc::string_ref>& client_metadata() const { + client_metadata_.FillMap(); return *client_metadata_.map(); } @@ -294,7 +295,7 @@ class ServerContext { CompletionQueue* cq_; bool sent_initial_metadata_; mutable std::shared_ptr<const AuthContext> auth_context_; - internal::MetadataMap client_metadata_; + mutable internal::MetadataMap client_metadata_; std::multimap<grpc::string, grpc::string> initial_metadata_; std::multimap<grpc::string, grpc::string> trailing_metadata_; |