grpc 1.21.0 → 1.22.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of grpc might be problematic. Click here for more details.

Files changed (141) hide show
  1. checksums.yaml +4 -4
  2. data/Makefile +422 -62
  3. data/include/grpc/grpc_security.h +61 -5
  4. data/include/grpc/grpc_security_constants.h +1 -1
  5. data/include/grpc/impl/codegen/gpr_types.h +1 -1
  6. data/include/grpc/slice.h +2 -2
  7. data/src/core/ext/filters/client_channel/backup_poller.cc +2 -3
  8. data/src/core/ext/filters/client_channel/backup_poller.h +5 -2
  9. data/src/core/ext/filters/client_channel/client_channel.cc +260 -122
  10. data/src/core/ext/filters/client_channel/client_channel.h +0 -8
  11. data/src/core/ext/filters/client_channel/client_channel_channelz.cc +3 -84
  12. data/src/core/ext/filters/client_channel/client_channel_channelz.h +2 -28
  13. data/src/core/ext/filters/client_channel/client_channel_plugin.cc +2 -8
  14. data/src/core/ext/filters/client_channel/health/health_check_client.cc +5 -4
  15. data/src/core/ext/filters/client_channel/lb_policy.cc +16 -2
  16. data/src/core/ext/filters/client_channel/lb_policy.h +92 -98
  17. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc +63 -87
  18. data/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc +6 -2
  19. data/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc +35 -87
  20. data/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc +18 -74
  21. data/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h +167 -217
  22. data/src/core/ext/filters/client_channel/lb_policy/xds/xds.cc +216 -190
  23. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_load_balancer_api.cc +6 -2
  24. data/src/core/ext/filters/client_channel/lb_policy_factory.h +1 -1
  25. data/src/core/ext/filters/client_channel/lb_policy_registry.cc +1 -1
  26. data/src/core/ext/filters/client_channel/lb_policy_registry.h +1 -1
  27. data/src/core/ext/filters/client_channel/resolver.h +1 -1
  28. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc +6 -3
  29. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc +0 -1
  30. data/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc +2 -0
  31. data/src/core/ext/filters/client_channel/resolver_result_parsing.cc +8 -8
  32. data/src/core/ext/filters/client_channel/resolver_result_parsing.h +7 -7
  33. data/src/core/ext/filters/client_channel/resolving_lb_policy.cc +28 -64
  34. data/src/core/ext/filters/client_channel/resolving_lb_policy.h +4 -12
  35. data/src/core/ext/filters/client_channel/server_address.cc +4 -6
  36. data/src/core/ext/filters/client_channel/server_address.h +1 -3
  37. data/src/core/ext/filters/client_channel/service_config.cc +20 -22
  38. data/src/core/ext/filters/client_channel/service_config.h +26 -28
  39. data/src/core/ext/filters/client_channel/subchannel.cc +261 -160
  40. data/src/core/ext/filters/client_channel/subchannel.h +97 -23
  41. data/src/core/ext/filters/client_channel/subchannel_interface.h +113 -0
  42. data/src/core/ext/filters/message_size/message_size_filter.cc +12 -12
  43. data/src/core/ext/filters/message_size/message_size_filter.h +2 -2
  44. data/src/core/ext/transport/chttp2/server/chttp2_server.cc +50 -2
  45. data/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +2 -2
  46. data/src/core/ext/transport/chttp2/transport/frame_data.cc +31 -36
  47. data/src/core/ext/transport/chttp2/transport/frame_rst_stream.cc +3 -2
  48. data/src/core/ext/transport/chttp2/transport/hpack_encoder.cc +71 -52
  49. data/src/core/ext/transport/chttp2/transport/hpack_parser.cc +18 -3
  50. data/src/core/ext/transport/chttp2/transport/hpack_table.cc +5 -12
  51. data/src/core/ext/transport/chttp2/transport/hpack_table.h +10 -1
  52. data/src/core/ext/transport/chttp2/transport/internal.h +3 -3
  53. data/src/core/ext/transport/chttp2/transport/parsing.cc +39 -57
  54. data/src/core/lib/channel/channelz.cc +136 -19
  55. data/src/core/lib/channel/channelz.h +36 -40
  56. data/src/core/lib/channel/channelz_registry.cc +74 -106
  57. data/src/core/lib/channel/channelz_registry.h +10 -28
  58. data/src/core/lib/channel/context.h +1 -1
  59. data/src/core/lib/channel/handshaker.cc +6 -0
  60. data/src/core/lib/compression/compression.cc +13 -8
  61. data/src/core/lib/compression/compression_internal.cc +14 -10
  62. data/src/core/lib/compression/compression_internal.h +1 -1
  63. data/src/core/lib/compression/stream_compression.cc +3 -2
  64. data/src/core/lib/compression/stream_compression.h +2 -2
  65. data/src/core/lib/compression/stream_compression_gzip.cc +9 -9
  66. data/src/core/lib/gpr/env.h +1 -1
  67. data/src/core/lib/gpr/string.cc +8 -1
  68. data/src/core/lib/gpr/string.h +6 -1
  69. data/src/core/lib/gprpp/fork.cc +1 -1
  70. data/src/core/lib/gprpp/fork.h +5 -1
  71. data/src/core/lib/gprpp/global_config.h +9 -0
  72. data/src/core/lib/gprpp/global_config_custom.h +1 -1
  73. data/src/core/lib/gprpp/inlined_vector.h +8 -0
  74. data/src/core/lib/gprpp/map.h +38 -21
  75. data/src/core/lib/gprpp/memory.h +2 -2
  76. data/src/core/lib/gprpp/orphanable.h +1 -1
  77. data/src/core/lib/gprpp/ref_counted.h +9 -4
  78. data/src/core/lib/http/httpcli.cc +3 -3
  79. data/src/core/lib/iomgr/buffer_list.h +1 -1
  80. data/src/core/lib/iomgr/call_combiner.cc +1 -1
  81. data/src/core/lib/iomgr/call_combiner.h +1 -1
  82. data/src/core/lib/iomgr/cfstream_handle.cc +3 -2
  83. data/src/core/lib/iomgr/cfstream_handle.h +4 -0
  84. data/src/core/lib/iomgr/error.cc +3 -3
  85. data/src/core/lib/iomgr/error.h +9 -3
  86. data/src/core/lib/iomgr/error_internal.h +1 -1
  87. data/src/core/lib/iomgr/ev_epoll1_linux.cc +1 -1
  88. data/src/core/lib/iomgr/ev_posix.cc +3 -3
  89. data/src/core/lib/iomgr/ev_posix.h +3 -2
  90. data/src/core/lib/iomgr/ev_windows.cc +2 -2
  91. data/src/core/lib/iomgr/iomgr.cc +4 -4
  92. data/src/core/lib/iomgr/lockfree_event.cc +1 -1
  93. data/src/core/lib/iomgr/port.h +5 -1
  94. data/src/core/lib/iomgr/tcp_posix.cc +1 -3
  95. data/src/core/lib/iomgr/tcp_server.cc +5 -0
  96. data/src/core/lib/iomgr/tcp_server.h +24 -0
  97. data/src/core/lib/iomgr/tcp_server_custom.cc +11 -9
  98. data/src/core/lib/iomgr/tcp_server_posix.cc +72 -11
  99. data/src/core/lib/iomgr/tcp_server_utils_posix.h +3 -0
  100. data/src/core/lib/iomgr/tcp_server_windows.cc +11 -9
  101. data/src/core/lib/iomgr/tcp_uv.cc +5 -6
  102. data/src/core/lib/iomgr/timer.h +2 -1
  103. data/src/core/lib/iomgr/udp_server.cc +2 -2
  104. data/src/core/lib/security/credentials/plugin/plugin_credentials.cc +1 -1
  105. data/src/core/lib/security/credentials/ssl/ssl_credentials.cc +20 -2
  106. data/src/core/lib/security/credentials/ssl/ssl_credentials.h +2 -2
  107. data/src/core/lib/security/security_connector/security_connector.h +1 -1
  108. data/src/core/lib/security/security_connector/ssl/ssl_security_connector.cc +1 -1
  109. data/src/core/lib/security/transport/auth_filters.h +3 -0
  110. data/src/core/lib/security/transport/client_auth_filter.cc +13 -0
  111. data/src/core/lib/security/transport/security_handshaker.cc +7 -7
  112. data/src/core/lib/slice/b64.h +2 -2
  113. data/src/core/lib/slice/slice.cc +82 -10
  114. data/src/core/lib/slice/slice_buffer.cc +49 -21
  115. data/src/core/lib/slice/slice_hash_table.h +2 -2
  116. data/src/core/lib/slice/slice_intern.cc +15 -16
  117. data/src/core/lib/slice/slice_internal.h +52 -0
  118. data/src/core/lib/slice/slice_string_helpers.cc +10 -1
  119. data/src/core/lib/slice/slice_string_helpers.h +3 -1
  120. data/src/core/lib/slice/slice_utils.h +50 -0
  121. data/src/core/lib/slice/slice_weak_hash_table.h +2 -2
  122. data/src/core/lib/surface/call.cc +14 -8
  123. data/src/core/lib/surface/channel.cc +89 -97
  124. data/src/core/lib/surface/channel.h +60 -6
  125. data/src/core/lib/surface/completion_queue.cc +49 -36
  126. data/src/core/lib/surface/completion_queue.h +2 -1
  127. data/src/core/lib/surface/server.cc +8 -8
  128. data/src/core/lib/surface/validate_metadata.cc +14 -8
  129. data/src/core/lib/surface/validate_metadata.h +13 -2
  130. data/src/core/lib/surface/version.cc +1 -1
  131. data/src/core/lib/transport/metadata.cc +56 -26
  132. data/src/core/lib/transport/metadata.h +91 -75
  133. data/src/core/lib/transport/static_metadata.cc +262 -176
  134. data/src/core/lib/transport/static_metadata.h +272 -180
  135. data/src/core/lib/transport/transport.cc +1 -1
  136. data/src/core/lib/transport/transport.h +8 -2
  137. data/src/core/tsi/alts/handshaker/alts_shared_resource.h +1 -1
  138. data/src/ruby/ext/grpc/rb_grpc_imports.generated.c +2 -0
  139. data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +5 -2
  140. data/src/ruby/lib/grpc/version.rb +1 -1
  141. metadata +33 -31
@@ -77,7 +77,8 @@ bool grpc_cq_begin_op(grpc_completion_queue* cc, void* tag);
77
77
  grpc_cq_begin_op */
78
78
  void grpc_cq_end_op(grpc_completion_queue* cc, void* tag, grpc_error* error,
79
79
  void (*done)(void* done_arg, grpc_cq_completion* storage),
80
- void* done_arg, grpc_cq_completion* storage);
80
+ void* done_arg, grpc_cq_completion* storage,
81
+ bool internal = false);
81
82
 
82
83
  grpc_pollset* grpc_cq_pollset(grpc_completion_queue* cc);
83
84
 
@@ -513,7 +513,7 @@ static void publish_call(grpc_server* server, call_data* calld, size_t cq_idx,
513
513
  }
514
514
 
515
515
  grpc_cq_end_op(calld->cq_new, rc->tag, GRPC_ERROR_NONE, done_request_event,
516
- rc, &rc->completion);
516
+ rc, &rc->completion, true);
517
517
  }
518
518
 
519
519
  static void publish_new_rpc(void* arg, grpc_error* error) {
@@ -625,8 +625,8 @@ static void start_new_rpc(grpc_call_element* elem) {
625
625
  if (chand->registered_methods && calld->path_set && calld->host_set) {
626
626
  /* TODO(ctiller): unify these two searches */
627
627
  /* check for an exact match with host */
628
- hash = GRPC_MDSTR_KV_HASH(grpc_slice_hash(calld->host),
629
- grpc_slice_hash(calld->path));
628
+ hash = GRPC_MDSTR_KV_HASH(grpc_slice_hash_internal(calld->host),
629
+ grpc_slice_hash_internal(calld->path));
630
630
  for (i = 0; i <= chand->registered_method_max_probes; i++) {
631
631
  rm = &chand->registered_methods[(hash + i) %
632
632
  chand->registered_method_slots];
@@ -644,7 +644,7 @@ static void start_new_rpc(grpc_call_element* elem) {
644
644
  return;
645
645
  }
646
646
  /* check for a wildcard method definition (no host set) */
647
- hash = GRPC_MDSTR_KV_HASH(0, grpc_slice_hash(calld->path));
647
+ hash = GRPC_MDSTR_KV_HASH(0, grpc_slice_hash_internal(calld->path));
648
648
  for (i = 0; i <= chand->registered_method_max_probes; i++) {
649
649
  rm = &chand->registered_methods[(hash + i) %
650
650
  chand->registered_method_slots];
@@ -1194,14 +1194,14 @@ void grpc_server_setup_transport(
1194
1194
  bool has_host;
1195
1195
  grpc_slice method;
1196
1196
  if (rm->host != nullptr) {
1197
- host = grpc_slice_intern(grpc_slice_from_static_string(rm->host));
1197
+ host = grpc_slice_from_static_string(rm->host);
1198
1198
  has_host = true;
1199
1199
  } else {
1200
1200
  has_host = false;
1201
1201
  }
1202
- method = grpc_slice_intern(grpc_slice_from_static_string(rm->method));
1203
- hash = GRPC_MDSTR_KV_HASH(has_host ? grpc_slice_hash(host) : 0,
1204
- grpc_slice_hash(method));
1202
+ method = grpc_slice_from_static_string(rm->method);
1203
+ hash = GRPC_MDSTR_KV_HASH(has_host ? grpc_slice_hash_internal(host) : 0,
1204
+ grpc_slice_hash_internal(method));
1205
1205
  for (probes = 0; chand->registered_methods[(hash + probes) % slots]
1206
1206
  .server_registered_method != nullptr;
1207
1207
  probes++)
@@ -24,12 +24,14 @@
24
24
  #include <grpc/grpc.h>
25
25
  #include <grpc/support/alloc.h>
26
26
 
27
+ #include "src/core/lib/gprpp/memory.h"
27
28
  #include "src/core/lib/iomgr/error.h"
28
29
  #include "src/core/lib/slice/slice_internal.h"
29
30
  #include "src/core/lib/slice/slice_string_helpers.h"
30
31
  #include "src/core/lib/surface/validate_metadata.h"
31
32
 
32
- static grpc_error* conforms_to(grpc_slice slice, const uint8_t* legal_bits,
33
+ static grpc_error* conforms_to(const grpc_slice& slice,
34
+ const uint8_t* legal_bits,
33
35
  const char* err_desc) {
34
36
  const uint8_t* p = GRPC_SLICE_START_PTR(slice);
35
37
  const uint8_t* e = GRPC_SLICE_END_PTR(slice);
@@ -38,13 +40,12 @@ static grpc_error* conforms_to(grpc_slice slice, const uint8_t* legal_bits,
38
40
  int byte = idx / 8;
39
41
  int bit = idx % 8;
40
42
  if ((legal_bits[byte] & (1 << bit)) == 0) {
41
- char* dump = grpc_dump_slice(slice, GPR_DUMP_HEX | GPR_DUMP_ASCII);
42
43
  grpc_error* error = grpc_error_set_str(
43
44
  grpc_error_set_int(GRPC_ERROR_CREATE_FROM_COPIED_STRING(err_desc),
44
45
  GRPC_ERROR_INT_OFFSET,
45
46
  p - GRPC_SLICE_START_PTR(slice)),
46
- GRPC_ERROR_STR_RAW_BYTES, grpc_slice_from_copied_string(dump));
47
- gpr_free(dump);
47
+ GRPC_ERROR_STR_RAW_BYTES,
48
+ grpc_dump_slice_to_slice(slice, GPR_DUMP_HEX | GPR_DUMP_ASCII));
48
49
  return error;
49
50
  }
50
51
  }
@@ -57,7 +58,7 @@ static int error2int(grpc_error* error) {
57
58
  return r;
58
59
  }
59
60
 
60
- grpc_error* grpc_validate_header_key_is_legal(grpc_slice slice) {
61
+ grpc_error* grpc_validate_header_key_is_legal(const grpc_slice& slice) {
61
62
  static const uint8_t legal_header_bits[256 / 8] = {
62
63
  0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xff, 0x03, 0x00, 0x00, 0x00,
63
64
  0x80, 0xfe, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -77,7 +78,8 @@ int grpc_header_key_is_legal(grpc_slice slice) {
77
78
  return error2int(grpc_validate_header_key_is_legal(slice));
78
79
  }
79
80
 
80
- grpc_error* grpc_validate_header_nonbin_value_is_legal(grpc_slice slice) {
81
+ grpc_error* grpc_validate_header_nonbin_value_is_legal(
82
+ const grpc_slice& slice) {
81
83
  static const uint8_t legal_header_bits[256 / 8] = {
82
84
  0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
83
85
  0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -89,7 +91,11 @@ int grpc_header_nonbin_value_is_legal(grpc_slice slice) {
89
91
  return error2int(grpc_validate_header_nonbin_value_is_legal(slice));
90
92
  }
91
93
 
94
+ int grpc_is_binary_header_internal(const grpc_slice& slice) {
95
+ return grpc_key_is_binary_header(GRPC_SLICE_START_PTR(slice),
96
+ GRPC_SLICE_LENGTH(slice));
97
+ }
98
+
92
99
  int grpc_is_binary_header(grpc_slice slice) {
93
- if (GRPC_SLICE_LENGTH(slice) < 5) return 0;
94
- return 0 == memcmp(GRPC_SLICE_END_PTR(slice) - 4, "-bin", 4);
100
+ return grpc_is_binary_header_internal(slice);
95
101
  }
@@ -24,7 +24,18 @@
24
24
  #include <grpc/slice.h>
25
25
  #include "src/core/lib/iomgr/error.h"
26
26
 
27
- grpc_error* grpc_validate_header_key_is_legal(grpc_slice slice);
28
- grpc_error* grpc_validate_header_nonbin_value_is_legal(grpc_slice slice);
27
+ grpc_error* grpc_validate_header_key_is_legal(const grpc_slice& slice);
28
+ grpc_error* grpc_validate_header_nonbin_value_is_legal(const grpc_slice& slice);
29
+
30
+ int grpc_is_binary_header_internal(const grpc_slice& slice);
31
+ inline int grpc_key_is_binary_header(const uint8_t* buf, size_t length) {
32
+ if (length < 5) return 0;
33
+ return 0 == memcmp(buf + length - 4, "-bin", 4);
34
+ }
35
+ inline int grpc_is_refcounted_slice_binary_header(const grpc_slice& slice) {
36
+ GPR_DEBUG_ASSERT(slice.refcount != nullptr);
37
+ return grpc_key_is_binary_header(slice.data.refcounted.bytes,
38
+ slice.data.refcounted.length);
39
+ }
29
40
 
30
41
  #endif /* GRPC_CORE_LIB_SURFACE_VALIDATE_METADATA_H */
@@ -25,4 +25,4 @@
25
25
 
26
26
  const char* grpc_version_string(void) { return "7.0.0"; }
27
27
 
28
- const char* grpc_g_stands_for(void) { return "gandalf"; }
28
+ const char* grpc_g_stands_for(void) { return "gale"; }
@@ -43,6 +43,7 @@
43
43
 
44
44
  using grpc_core::AllocatedMetadata;
45
45
  using grpc_core::InternedMetadata;
46
+ using grpc_core::StaticMetadata;
46
47
  using grpc_core::UserData;
47
48
 
48
49
  /* There are two kinds of mdelem and mdstr instances.
@@ -100,15 +101,20 @@ void grpc_mdelem_trace_unref(void* md, const grpc_slice& key,
100
101
  #define TABLE_IDX(hash, capacity) (((hash) >> (LOG2_SHARD_COUNT)) % (capacity))
101
102
  #define SHARD_IDX(hash) ((hash) & ((1 << (LOG2_SHARD_COUNT)) - 1))
102
103
 
104
+ void StaticMetadata::HashInit() {
105
+ uint32_t k_hash = grpc_slice_hash_internal(kv_.key);
106
+ uint32_t v_hash = grpc_slice_hash_internal(kv_.value);
107
+ hash_ = GRPC_MDSTR_KV_HASH(k_hash, v_hash);
108
+ }
109
+
103
110
  AllocatedMetadata::AllocatedMetadata(const grpc_slice& key,
104
111
  const grpc_slice& value)
105
- : key_(grpc_slice_ref_internal(key)),
106
- value_(grpc_slice_ref_internal(value)),
107
- refcnt_(1) {
112
+ : RefcountedMdBase(grpc_slice_ref_internal(key),
113
+ grpc_slice_ref_internal(value)) {
108
114
  #ifndef NDEBUG
109
115
  if (grpc_trace_metadata.enabled()) {
110
- char* key_str = grpc_slice_to_c_string(key_);
111
- char* value_str = grpc_slice_to_c_string(value_);
116
+ char* key_str = grpc_slice_to_c_string(key);
117
+ char* value_str = grpc_slice_to_c_string(value);
112
118
  gpr_log(GPR_DEBUG, "ELM ALLOC:%p:%" PRIdPTR ": '%s' = '%s'", this,
113
119
  RefValue(), key_str, value_str);
114
120
  gpr_free(key_str);
@@ -118,8 +124,8 @@ AllocatedMetadata::AllocatedMetadata(const grpc_slice& key,
118
124
  }
119
125
 
120
126
  AllocatedMetadata::~AllocatedMetadata() {
121
- grpc_slice_unref_internal(key_);
122
- grpc_slice_unref_internal(value_);
127
+ grpc_slice_unref_internal(key());
128
+ grpc_slice_unref_internal(value());
123
129
  void* user_data = user_data_.data.Load(grpc_core::MemoryOrder::RELAXED);
124
130
  if (user_data) {
125
131
  destroy_user_data_func destroy_user_data =
@@ -131,15 +137,13 @@ AllocatedMetadata::~AllocatedMetadata() {
131
137
  InternedMetadata::InternedMetadata(const grpc_slice& key,
132
138
  const grpc_slice& value, uint32_t hash,
133
139
  InternedMetadata* next)
134
- : key_(grpc_slice_ref_internal(key)),
135
- value_(grpc_slice_ref_internal(value)),
136
- refcnt_(1),
137
- hash_(hash),
140
+ : RefcountedMdBase(grpc_slice_ref_internal(key),
141
+ grpc_slice_ref_internal(value), hash),
138
142
  link_(next) {
139
143
  #ifndef NDEBUG
140
144
  if (grpc_trace_metadata.enabled()) {
141
- char* key_str = grpc_slice_to_c_string(key_);
142
- char* value_str = grpc_slice_to_c_string(value_);
145
+ char* key_str = grpc_slice_to_c_string(key);
146
+ char* value_str = grpc_slice_to_c_string(value);
143
147
  gpr_log(GPR_DEBUG, "ELM NEW:%p:%" PRIdPTR ": '%s' = '%s'", this,
144
148
  RefValue(), key_str, value_str);
145
149
  gpr_free(key_str);
@@ -149,8 +153,8 @@ InternedMetadata::InternedMetadata(const grpc_slice& key,
149
153
  }
150
154
 
151
155
  InternedMetadata::~InternedMetadata() {
152
- grpc_slice_unref_internal(key_);
153
- grpc_slice_unref_internal(value_);
156
+ grpc_slice_unref_internal(key());
157
+ grpc_slice_unref_internal(value());
154
158
  void* user_data = user_data_.data.Load(grpc_core::MemoryOrder::RELAXED);
155
159
  if (user_data) {
156
160
  destroy_user_data_func destroy_user_data =
@@ -223,17 +227,20 @@ void grpc_mdctx_global_shutdown() {
223
227
  }
224
228
  }
225
229
 
230
+ #ifndef NDEBUG
226
231
  static int is_mdelem_static(grpc_mdelem e) {
227
- return GRPC_MDELEM_DATA(e) >= &grpc_static_mdelem_table[0] &&
228
- GRPC_MDELEM_DATA(e) <
232
+ return reinterpret_cast<grpc_core::StaticMetadata*>(GRPC_MDELEM_DATA(e)) >=
233
+ &grpc_static_mdelem_table[0] &&
234
+ reinterpret_cast<grpc_core::StaticMetadata*>(GRPC_MDELEM_DATA(e)) <
229
235
  &grpc_static_mdelem_table[GRPC_STATIC_MDELEM_COUNT];
230
236
  }
237
+ #endif
231
238
 
232
239
  void InternedMetadata::RefWithShardLocked(mdtab_shard* shard) {
233
240
  #ifndef NDEBUG
234
241
  if (grpc_trace_metadata.enabled()) {
235
- char* key_str = grpc_slice_to_c_string(key_);
236
- char* value_str = grpc_slice_to_c_string(value_);
242
+ char* key_str = grpc_slice_to_c_string(key());
243
+ char* value_str = grpc_slice_to_c_string(value());
237
244
  intptr_t value = RefValue();
238
245
  gpr_log(__FILE__, __LINE__, GPR_LOG_SEVERITY_DEBUG,
239
246
  "ELM REF:%p:%" PRIdPTR "->%" PRIdPTR ": '%s' = '%s'", this, value,
@@ -323,8 +330,8 @@ grpc_mdelem grpc_mdelem_create(
323
330
  }
324
331
  }
325
332
 
326
- uint32_t hash =
327
- GRPC_MDSTR_KV_HASH(grpc_slice_hash(key), grpc_slice_hash(value));
333
+ uint32_t hash = GRPC_MDSTR_KV_HASH(grpc_slice_hash_refcounted(key),
334
+ grpc_slice_hash_refcounted(value));
328
335
  InternedMetadata* md;
329
336
  mdtab_shard* shard = &g_shards[SHARD_IDX(hash)];
330
337
  size_t idx;
@@ -391,8 +398,11 @@ void* grpc_mdelem_get_user_data(grpc_mdelem md, void (*destroy_func)(void*)) {
391
398
  case GRPC_MDELEM_STORAGE_EXTERNAL:
392
399
  return nullptr;
393
400
  case GRPC_MDELEM_STORAGE_STATIC:
394
- return (void*)grpc_static_mdelem_user_data[GRPC_MDELEM_DATA(md) -
395
- grpc_static_mdelem_table];
401
+ return reinterpret_cast<void*>(
402
+ grpc_static_mdelem_user_data
403
+ [reinterpret_cast<grpc_core::StaticMetadata*>(
404
+ GRPC_MDELEM_DATA(md)) -
405
+ grpc_static_mdelem_table]);
396
406
  case GRPC_MDELEM_STORAGE_ALLOCATED: {
397
407
  auto* am = reinterpret_cast<AllocatedMetadata*>(GRPC_MDELEM_DATA(md));
398
408
  return get_user_data(am->user_data(), destroy_func);
@@ -430,15 +440,18 @@ void* grpc_mdelem_set_user_data(grpc_mdelem md, void (*destroy_func)(void*),
430
440
  return nullptr;
431
441
  case GRPC_MDELEM_STORAGE_STATIC:
432
442
  destroy_func(data);
433
- return (void*)grpc_static_mdelem_user_data[GRPC_MDELEM_DATA(md) -
434
- grpc_static_mdelem_table];
443
+ return reinterpret_cast<void*>(
444
+ grpc_static_mdelem_user_data
445
+ [reinterpret_cast<grpc_core::StaticMetadata*>(
446
+ GRPC_MDELEM_DATA(md)) -
447
+ grpc_static_mdelem_table]);
435
448
  case GRPC_MDELEM_STORAGE_ALLOCATED: {
436
449
  auto* am = reinterpret_cast<AllocatedMetadata*>(GRPC_MDELEM_DATA(md));
437
450
  return set_user_data(am->user_data(), destroy_func, data);
438
451
  }
439
452
  case GRPC_MDELEM_STORAGE_INTERNED: {
440
453
  auto* im = reinterpret_cast<InternedMetadata*> GRPC_MDELEM_DATA(md);
441
- GPR_ASSERT(!is_mdelem_static(md));
454
+ GPR_DEBUG_ASSERT(!is_mdelem_static(md));
442
455
  return set_user_data(im->user_data(), destroy_func, data);
443
456
  }
444
457
  }
@@ -482,3 +495,20 @@ void grpc_mdelem_do_unref(grpc_mdelem gmd DEBUG_ARGS) {
482
495
  }
483
496
  }
484
497
  }
498
+
499
+ void grpc_mdelem_on_final_unref(grpc_mdelem_data_storage storage, void* ptr,
500
+ uint32_t hash DEBUG_ARGS) {
501
+ switch (storage) {
502
+ case GRPC_MDELEM_STORAGE_EXTERNAL:
503
+ case GRPC_MDELEM_STORAGE_STATIC:
504
+ return;
505
+ case GRPC_MDELEM_STORAGE_INTERNED: {
506
+ note_disposed_interned_metadata(hash);
507
+ break;
508
+ }
509
+ case GRPC_MDELEM_STORAGE_ALLOCATED: {
510
+ grpc_core::Delete(reinterpret_cast<AllocatedMetadata*>(ptr));
511
+ break;
512
+ }
513
+ }
514
+ }
@@ -21,7 +21,7 @@
21
21
 
22
22
  #include <grpc/support/port_platform.h>
23
23
 
24
- #include "include/grpc/impl/codegen/log.h"
24
+ #include <grpc/impl/codegen/log.h>
25
25
 
26
26
  #include <grpc/grpc.h>
27
27
  #include <grpc/slice.h>
@@ -30,6 +30,7 @@
30
30
  #include "src/core/lib/gpr/useful.h"
31
31
  #include "src/core/lib/gprpp/atomic.h"
32
32
  #include "src/core/lib/gprpp/sync.h"
33
+ #include "src/core/lib/slice/slice_utils.h"
33
34
 
34
35
  extern grpc_core::DebugOnlyTraceFlag grpc_trace_metadata;
35
36
 
@@ -79,17 +80,22 @@ typedef struct grpc_mdelem_data {
79
80
  this bit set in their integer value */
80
81
  #define GRPC_MDELEM_STORAGE_INTERNED_BIT 1
81
82
 
83
+ /* External and static storage metadata has no refcount to ref/unref. Allocated
84
+ * and interned metadata do have a refcount. Metadata ref and unref methods use
85
+ * a switch statement on this enum to determine which behaviour to execute.
86
+ * Keeping the no-ref cases together and the ref-cases together leads to
87
+ * slightly better code generation (9 inlined instructions rather than 10). */
82
88
  typedef enum {
83
89
  /* memory pointed to by grpc_mdelem::payload is owned by an external system */
84
90
  GRPC_MDELEM_STORAGE_EXTERNAL = 0,
85
- /* memory pointed to by grpc_mdelem::payload is interned by the metadata
86
- system */
87
- GRPC_MDELEM_STORAGE_INTERNED = GRPC_MDELEM_STORAGE_INTERNED_BIT,
91
+ /* memory is in the static metadata table */
92
+ GRPC_MDELEM_STORAGE_STATIC = GRPC_MDELEM_STORAGE_INTERNED_BIT,
88
93
  /* memory pointed to by grpc_mdelem::payload is allocated by the metadata
89
94
  system */
90
95
  GRPC_MDELEM_STORAGE_ALLOCATED = 2,
91
- /* memory is in the static metadata table */
92
- GRPC_MDELEM_STORAGE_STATIC = 2 | GRPC_MDELEM_STORAGE_INTERNED_BIT,
96
+ /* memory pointed to by grpc_mdelem::payload is interned by the metadata
97
+ system */
98
+ GRPC_MDELEM_STORAGE_INTERNED = 2 | GRPC_MDELEM_STORAGE_INTERNED_BIT,
93
99
  } grpc_mdelem_data_storage;
94
100
 
95
101
  struct grpc_mdelem {
@@ -138,7 +144,17 @@ bool grpc_mdelem_eq(grpc_mdelem a, grpc_mdelem b);
138
144
  * grpc_mdelem_eq and remove unnecessary checks. */
139
145
  inline bool grpc_mdelem_static_value_eq(grpc_mdelem a, grpc_mdelem b_static) {
140
146
  if (a.payload == b_static.payload) return true;
141
- return grpc_slice_eq(GRPC_MDVALUE(a), GRPC_MDVALUE(b_static));
147
+ return grpc_slice_eq_static_interned(GRPC_MDVALUE(a), GRPC_MDVALUE(b_static));
148
+ }
149
+ #define GRPC_MDISNULL(md) (GRPC_MDELEM_DATA(md) == NULL)
150
+
151
+ inline bool grpc_mdelem_both_interned_eq(grpc_mdelem a_interned,
152
+ grpc_mdelem b_interned) {
153
+ GPR_DEBUG_ASSERT(GRPC_MDELEM_IS_INTERNED(a_interned) ||
154
+ GRPC_MDISNULL(a_interned));
155
+ GPR_DEBUG_ASSERT(GRPC_MDELEM_IS_INTERNED(b_interned) ||
156
+ GRPC_MDISNULL(b_interned));
157
+ return a_interned.payload == b_interned.payload;
142
158
  }
143
159
 
144
160
  /* Mutator and accessor for grpc_mdelem user data. The destructor function
@@ -168,17 +184,34 @@ struct UserData {
168
184
  grpc_core::Atomic<void*> data;
169
185
  };
170
186
 
171
- class InternedMetadata {
187
+ class StaticMetadata {
172
188
  public:
173
- struct BucketLink {
174
- explicit BucketLink(InternedMetadata* md) : next(md) {}
189
+ StaticMetadata(const grpc_slice& key, const grpc_slice& value)
190
+ : kv_({key, value}), hash_(0) {}
175
191
 
176
- InternedMetadata* next = nullptr;
177
- };
192
+ const grpc_mdelem_data& data() const { return kv_; }
178
193
 
179
- InternedMetadata(const grpc_slice& key, const grpc_slice& value,
180
- uint32_t hash, InternedMetadata* next);
181
- ~InternedMetadata();
194
+ void HashInit();
195
+ uint32_t hash() { return hash_; }
196
+
197
+ private:
198
+ grpc_mdelem_data kv_;
199
+
200
+ /* private only data */
201
+ uint32_t hash_;
202
+ };
203
+
204
+ class RefcountedMdBase {
205
+ public:
206
+ RefcountedMdBase(const grpc_slice& key, const grpc_slice& value)
207
+ : key_(key), value_(value), refcnt_(1) {}
208
+ RefcountedMdBase(const grpc_slice& key, const grpc_slice& value,
209
+ uint32_t hash)
210
+ : key_(key), value_(value), refcnt_(1), hash_(hash) {}
211
+
212
+ const grpc_slice& key() const { return key_; }
213
+ const grpc_slice& value() const { return value_; }
214
+ uint32_t hash() { return hash_; }
182
215
 
183
216
  #ifndef NDEBUG
184
217
  void Ref(const char* file, int line) {
@@ -190,92 +223,65 @@ class InternedMetadata {
190
223
  grpc_mdelem_trace_unref(this, key_, value_, RefValue(), file, line);
191
224
  return Unref();
192
225
  }
193
- #else
194
- // We define a naked Ref() in the else-clause to make sure we don't
195
- // inadvertently skip the assert on debug builds.
226
+ #endif
196
227
  void Ref() {
197
228
  /* we can assume the ref count is >= 1 as the application is calling
198
229
  this function - meaning that no adjustment to mdtab_free is necessary,
199
230
  simplifying the logic here to be just an atomic increment */
200
231
  refcnt_.FetchAdd(1, MemoryOrder::RELAXED);
201
232
  }
202
- #endif // ifndef NDEBUG
203
233
  bool Unref() {
204
234
  const intptr_t prior = refcnt_.FetchSub(1, MemoryOrder::ACQ_REL);
205
235
  GPR_DEBUG_ASSERT(prior > 0);
206
236
  return prior == 1;
207
237
  }
208
238
 
209
- void RefWithShardLocked(mdtab_shard* shard);
210
- const grpc_slice& key() const { return key_; }
211
- const grpc_slice& value() const { return value_; }
212
- UserData* user_data() { return &user_data_; }
213
- uint32_t hash() { return hash_; }
214
- InternedMetadata* bucket_next() { return link_.next; }
215
- void set_bucket_next(InternedMetadata* md) { link_.next = md; }
216
-
217
- static size_t CleanupLinkedMetadata(BucketLink* head);
218
-
219
- private:
239
+ protected:
240
+ intptr_t RefValue() { return refcnt_.Load(MemoryOrder::RELAXED); }
220
241
  bool AllRefsDropped() { return refcnt_.Load(MemoryOrder::ACQUIRE) == 0; }
221
242
  bool FirstRef() { return refcnt_.FetchAdd(1, MemoryOrder::RELAXED) == 0; }
222
- intptr_t RefValue() { return refcnt_.Load(MemoryOrder::RELAXED); }
223
243
 
244
+ private:
224
245
  /* must be byte compatible with grpc_mdelem_data */
225
246
  grpc_slice key_;
226
247
  grpc_slice value_;
227
-
228
- /* private only data */
229
248
  grpc_core::Atomic<intptr_t> refcnt_;
230
- uint32_t hash_;
249
+ uint32_t hash_ = 0;
250
+ };
231
251
 
232
- UserData user_data_;
252
+ class InternedMetadata : public RefcountedMdBase {
253
+ public:
254
+ struct BucketLink {
255
+ explicit BucketLink(InternedMetadata* md) : next(md) {}
256
+
257
+ InternedMetadata* next = nullptr;
258
+ };
259
+
260
+ InternedMetadata(const grpc_slice& key, const grpc_slice& value,
261
+ uint32_t hash, InternedMetadata* next);
262
+ ~InternedMetadata();
263
+
264
+ void RefWithShardLocked(mdtab_shard* shard);
265
+ UserData* user_data() { return &user_data_; }
266
+ InternedMetadata* bucket_next() { return link_.next; }
267
+ void set_bucket_next(InternedMetadata* md) { link_.next = md; }
233
268
 
269
+ static size_t CleanupLinkedMetadata(BucketLink* head);
270
+
271
+ private:
272
+ UserData user_data_;
234
273
  BucketLink link_;
235
274
  };
236
275
 
237
276
  /* Shadow structure for grpc_mdelem_data for allocated elements */
238
- class AllocatedMetadata {
277
+ class AllocatedMetadata : public RefcountedMdBase {
239
278
  public:
240
279
  AllocatedMetadata(const grpc_slice& key, const grpc_slice& value);
241
280
  ~AllocatedMetadata();
242
281
 
243
- const grpc_slice& key() const { return key_; }
244
- const grpc_slice& value() const { return value_; }
245
282
  UserData* user_data() { return &user_data_; }
246
283
 
247
- #ifndef NDEBUG
248
- void Ref(const char* file, int line) {
249
- grpc_mdelem_trace_ref(this, key_, value_, RefValue(), file, line);
250
- Ref();
251
- }
252
- bool Unref(const char* file, int line) {
253
- grpc_mdelem_trace_unref(this, key_, value_, RefValue(), file, line);
254
- return Unref();
255
- }
256
- #endif // ifndef NDEBUG
257
- void Ref() {
258
- /* we can assume the ref count is >= 1 as the application is calling
259
- this function - meaning that no adjustment to mdtab_free is necessary,
260
- simplifying the logic here to be just an atomic increment */
261
- refcnt_.FetchAdd(1, MemoryOrder::RELAXED);
262
- }
263
- bool Unref() {
264
- const intptr_t prior = refcnt_.FetchSub(1, MemoryOrder::ACQ_REL);
265
- GPR_DEBUG_ASSERT(prior > 0);
266
- return prior == 1;
267
- }
268
-
269
284
  private:
270
- intptr_t RefValue() { return refcnt_.Load(MemoryOrder::RELAXED); }
271
-
272
- /* must be byte compatible with grpc_mdelem_data */
273
- grpc_slice key_;
274
- grpc_slice value_;
275
-
276
- /* private only data */
277
- grpc_core::Atomic<intptr_t> refcnt_;
278
-
279
285
  UserData user_data_;
280
286
  };
281
287
 
@@ -320,30 +326,40 @@ inline grpc_mdelem grpc_mdelem_ref(grpc_mdelem gmd) {
320
326
 
321
327
  #ifndef NDEBUG
322
328
  #define GRPC_MDELEM_UNREF(s) grpc_mdelem_unref((s), __FILE__, __LINE__)
323
- void grpc_mdelem_do_unref(grpc_mdelem gmd, const char* file, int line);
329
+ void grpc_mdelem_on_final_unref(grpc_mdelem_data_storage storage, void* ptr,
330
+ uint32_t hash, const char* file, int line);
324
331
  inline void grpc_mdelem_unref(grpc_mdelem gmd, const char* file, int line) {
325
332
  #else
326
333
  #define GRPC_MDELEM_UNREF(s) grpc_mdelem_unref((s))
327
- void grpc_mdelem_do_unref(grpc_mdelem gmd);
334
+ void grpc_mdelem_on_final_unref(grpc_mdelem_data_storage storage, void* ptr,
335
+ uint32_t hash);
328
336
  inline void grpc_mdelem_unref(grpc_mdelem gmd) {
329
337
  #endif
330
- switch (GRPC_MDELEM_STORAGE(gmd)) {
338
+ const grpc_mdelem_data_storage storage = GRPC_MDELEM_STORAGE(gmd);
339
+ switch (storage) {
331
340
  case GRPC_MDELEM_STORAGE_EXTERNAL:
332
341
  case GRPC_MDELEM_STORAGE_STATIC:
333
342
  return;
334
343
  case GRPC_MDELEM_STORAGE_INTERNED:
335
344
  case GRPC_MDELEM_STORAGE_ALLOCATED:
345
+ auto* md =
346
+ reinterpret_cast<grpc_core::RefcountedMdBase*> GRPC_MDELEM_DATA(gmd);
347
+ /* once the refcount hits zero, some other thread can come along and
348
+ free an interned md at any time: it's unsafe from this point on to
349
+ access it so we read the hash now. */
350
+ uint32_t hash = md->hash();
351
+ if (GPR_UNLIKELY(md->Unref())) {
336
352
  #ifndef NDEBUG
337
- grpc_mdelem_do_unref(gmd, file, line);
353
+ grpc_mdelem_on_final_unref(storage, md, hash, file, line);
338
354
  #else
339
- grpc_mdelem_do_unref(gmd);
355
+ grpc_mdelem_on_final_unref(storage, md, hash);
340
356
  #endif
357
+ }
341
358
  return;
342
359
  }
343
360
  }
344
361
 
345
362
  #define GRPC_MDNULL GRPC_MAKE_MDELEM(NULL, GRPC_MDELEM_STORAGE_EXTERNAL)
346
- #define GRPC_MDISNULL(md) (GRPC_MDELEM_DATA(md) == NULL)
347
363
 
348
364
  /* We add 32 bytes of padding as per RFC-7540 section 6.5.2. */
349
365
  #define GRPC_MDELEM_LENGTH(e) \