diff options
Diffstat (limited to 'include/grpcpp/impl/codegen/metadata_map.h')
-rw-r--r-- | include/grpcpp/impl/codegen/metadata_map.h | 71 |
1 files changed, 59 insertions, 12 deletions
diff --git a/include/grpcpp/impl/codegen/metadata_map.h b/include/grpcpp/impl/codegen/metadata_map.h index 0866539d88..9cec54d9f0 100644 --- a/include/grpcpp/impl/codegen/metadata_map.h +++ b/include/grpcpp/impl/codegen/metadata_map.h @@ -19,37 +19,84 @@ #ifndef GRPCPP_IMPL_CODEGEN_METADATA_MAP_H #define GRPCPP_IMPL_CODEGEN_METADATA_MAP_H +#include <map> + +#include <grpc/impl/codegen/log.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_)); } + MetadataMap() { Setup(); } - ~MetadataMap() { - g_core_codegen_interface->grpc_metadata_array_destroy(&arr_); - } + ~MetadataMap() { Destroy(); } - void FillMap() { - for (size_t i = 0; i < arr_.count; i++) { - // TODO(yangg) handle duplicates? - map_.insert(std::pair<grpc::string_ref, grpc::string_ref>( - StringRefFromSlice(&arr_.metadata[i].key), - StringRefFromSlice(&arr_.metadata[i].value))); + 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. + // TODO(ncteisen): plumb this through core as a first class object, just + // like code and message. + else { + for (size_t i = 0; i < arr_.count; i++) { + if (strncmp(reinterpret_cast<const char*>( + GRPC_SLICE_START_PTR(arr_.metadata[i].key)), + kBinaryErrorDetailsKey, + GRPC_SLICE_LENGTH(arr_.metadata[i].key)) == 0) { + 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(); } - std::multimap<grpc::string_ref, grpc::string_ref>* map() { return &map_; } - const std::multimap<grpc::string_ref, grpc::string_ref>* map() const { + std::multimap<grpc::string_ref, grpc::string_ref>* map() { + FillMap(); return &map_; } grpc_metadata_array* arr() { return &arr_; } + void Reset() { + filled_ = false; + map_.clear(); + Destroy(); + Setup(); + } + private: + bool filled_ = false; grpc_metadata_array arr_; std::multimap<grpc::string_ref, grpc::string_ref> map_; + + void Destroy() { + g_core_codegen_interface->grpc_metadata_array_destroy(&arr_); + } + + void Setup() { memset(&arr_, 0, sizeof(arr_)); } + + 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>( + StringRefFromSlice(&arr_.metadata[i].key), + StringRefFromSlice(&arr_.metadata[i].value))); + } + } }; } // namespace internal |