aboutsummaryrefslogtreecommitdiffhomepage
path: root/include/grpcpp/impl/codegen/metadata_map.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/grpcpp/impl/codegen/metadata_map.h')
-rw-r--r--include/grpcpp/impl/codegen/metadata_map.h71
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