grpc 1.22.0 → 1.23.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 (176) hide show
  1. checksums.yaml +4 -4
  2. data/Makefile +487 -649
  3. data/include/grpc/grpc_security.h +25 -0
  4. data/include/grpc/impl/codegen/grpc_types.h +11 -2
  5. data/include/grpc/impl/codegen/port_platform.h +12 -0
  6. data/src/core/ext/filters/client_channel/backup_poller.cc +4 -2
  7. data/src/core/ext/filters/client_channel/client_channel.cc +477 -182
  8. data/src/core/ext/filters/client_channel/client_channel_channelz.cc +25 -16
  9. data/src/core/ext/filters/client_channel/client_channel_channelz.h +11 -6
  10. data/src/core/ext/filters/client_channel/connector.h +10 -2
  11. data/src/core/ext/filters/client_channel/health/health_check_client.cc +3 -3
  12. data/src/core/ext/filters/client_channel/http_proxy.cc +9 -10
  13. data/src/core/ext/filters/client_channel/lb_policy.cc +2 -17
  14. data/src/core/ext/filters/client_channel/lb_policy.h +36 -8
  15. data/src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.cc +22 -8
  16. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc +86 -52
  17. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h +7 -0
  18. data/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc +73 -72
  19. data/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc +8 -12
  20. data/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h +25 -101
  21. data/src/core/ext/filters/client_channel/lb_policy/xds/xds.cc +5 -5
  22. data/src/core/ext/filters/client_channel/parse_address.cc +29 -26
  23. data/src/core/ext/filters/client_channel/resolver.h +3 -11
  24. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc +5 -3
  25. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc +405 -82
  26. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc +44 -51
  27. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_libuv.cc +0 -1
  28. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc +0 -1
  29. data/src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc +11 -6
  30. data/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc +130 -65
  31. data/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h +8 -3
  32. data/src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc +31 -14
  33. data/src/core/ext/filters/client_channel/resolver_factory.h +4 -0
  34. data/src/core/ext/filters/client_channel/resolver_registry.cc +11 -0
  35. data/src/core/ext/filters/client_channel/resolver_registry.h +3 -0
  36. data/src/core/ext/filters/client_channel/resolving_lb_policy.cc +10 -49
  37. data/src/core/ext/filters/client_channel/resolving_lb_policy.h +1 -14
  38. data/src/core/ext/filters/client_channel/retry_throttle.h +2 -3
  39. data/src/core/ext/filters/client_channel/subchannel.cc +65 -58
  40. data/src/core/ext/filters/client_channel/subchannel.h +65 -45
  41. data/src/core/ext/filters/client_channel/subchannel_interface.h +15 -30
  42. data/src/core/ext/filters/client_idle/client_idle_filter.cc +262 -0
  43. data/src/core/ext/filters/http/client/http_client_filter.cc +4 -5
  44. data/src/core/ext/filters/http/client_authority_filter.cc +2 -2
  45. data/src/core/ext/filters/http/message_compress/message_compress_filter.cc +140 -152
  46. data/src/core/ext/filters/max_age/max_age_filter.cc +3 -3
  47. data/src/core/ext/transport/chttp2/client/chttp2_connector.cc +3 -4
  48. data/src/core/ext/transport/chttp2/server/chttp2_server.cc +7 -6
  49. data/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +63 -38
  50. data/src/core/ext/transport/chttp2/transport/context_list.cc +3 -1
  51. data/src/core/ext/transport/chttp2/transport/frame_data.cc +4 -4
  52. data/src/core/ext/transport/chttp2/transport/frame_goaway.cc +1 -1
  53. data/src/core/ext/transport/chttp2/transport/frame_ping.cc +1 -0
  54. data/src/core/ext/transport/chttp2/transport/frame_rst_stream.cc +8 -0
  55. data/src/core/ext/transport/chttp2/transport/frame_rst_stream.h +7 -0
  56. data/src/core/ext/transport/chttp2/transport/frame_settings.cc +1 -0
  57. data/src/core/ext/transport/chttp2/transport/hpack_encoder.cc +37 -22
  58. data/src/core/ext/transport/chttp2/transport/hpack_parser.cc +136 -81
  59. data/src/core/ext/transport/chttp2/transport/hpack_parser.h +8 -0
  60. data/src/core/ext/transport/chttp2/transport/hpack_table.cc +7 -166
  61. data/src/core/ext/transport/chttp2/transport/hpack_table.h +41 -15
  62. data/src/core/ext/transport/chttp2/transport/internal.h +13 -2
  63. data/src/core/ext/transport/chttp2/transport/parsing.cc +35 -22
  64. data/src/core/ext/transport/chttp2/transport/stream_map.cc +28 -18
  65. data/src/core/ext/transport/chttp2/transport/writing.cc +1 -0
  66. data/src/core/ext/transport/inproc/inproc_transport.cc +1 -1
  67. data/src/core/lib/channel/channelz.cc +80 -33
  68. data/src/core/lib/channel/channelz.h +28 -13
  69. data/src/core/lib/compression/compression.cc +1 -2
  70. data/src/core/lib/compression/compression_args.cc +13 -6
  71. data/src/core/lib/compression/compression_args.h +3 -2
  72. data/src/core/lib/compression/compression_internal.cc +1 -1
  73. data/src/core/lib/gpr/env_linux.cc +10 -21
  74. data/src/core/lib/gpr/env_posix.cc +0 -5
  75. data/src/core/lib/gpr/string.cc +7 -2
  76. data/src/core/lib/gpr/string.h +1 -0
  77. data/src/core/lib/gpr/sync_posix.cc +0 -129
  78. data/src/core/lib/gprpp/debug_location.h +3 -2
  79. data/src/core/lib/gprpp/fork.cc +14 -21
  80. data/src/core/lib/gprpp/fork.h +15 -4
  81. data/src/core/lib/gprpp/host_port.cc +118 -0
  82. data/src/core/lib/{gpr → gprpp}/host_port.h +27 -11
  83. data/src/core/lib/gprpp/map.h +25 -0
  84. data/src/core/lib/gprpp/memory.h +26 -9
  85. data/src/core/lib/gprpp/ref_counted.h +63 -21
  86. data/src/core/lib/gprpp/string_view.h +143 -0
  87. data/src/core/lib/gprpp/thd.h +10 -1
  88. data/src/core/lib/gprpp/thd_posix.cc +25 -0
  89. data/src/core/lib/gprpp/thd_windows.cc +9 -1
  90. data/src/core/lib/http/httpcli_security_connector.cc +3 -1
  91. data/src/core/lib/iomgr/cfstream_handle.cc +6 -1
  92. data/src/core/lib/iomgr/cfstream_handle.h +8 -2
  93. data/src/core/lib/iomgr/combiner.cc +4 -4
  94. data/src/core/lib/iomgr/error.cc +18 -8
  95. data/src/core/lib/iomgr/error.h +2 -0
  96. data/src/core/lib/iomgr/ev_posix.cc +4 -2
  97. data/src/core/lib/iomgr/executor.cc +4 -1
  98. data/src/core/lib/iomgr/executor/mpmcqueue.cc +183 -0
  99. data/src/core/lib/iomgr/executor/mpmcqueue.h +178 -0
  100. data/src/core/lib/iomgr/executor/threadpool.cc +138 -0
  101. data/src/core/lib/iomgr/executor/threadpool.h +153 -0
  102. data/src/core/lib/iomgr/fork_posix.cc +4 -2
  103. data/src/core/lib/iomgr/iocp_windows.cc +2 -2
  104. data/src/core/lib/iomgr/iomgr_posix_cfstream.cc +14 -0
  105. data/src/core/lib/iomgr/iomgr_uv.cc +3 -0
  106. data/src/core/lib/iomgr/lockfree_event.cc +3 -3
  107. data/src/core/lib/iomgr/resolve_address_custom.cc +16 -20
  108. data/src/core/lib/iomgr/resolve_address_posix.cc +8 -10
  109. data/src/core/lib/iomgr/resolve_address_windows.cc +6 -8
  110. data/src/core/lib/iomgr/sockaddr_utils.cc +5 -3
  111. data/src/core/lib/iomgr/socket_utils_common_posix.cc +0 -1
  112. data/src/core/lib/iomgr/socket_windows.h +1 -1
  113. data/src/core/lib/iomgr/tcp_client_cfstream.cc +7 -6
  114. data/src/core/lib/iomgr/tcp_client_custom.cc +1 -0
  115. data/src/core/lib/iomgr/tcp_custom.cc +4 -0
  116. data/src/core/lib/iomgr/tcp_posix.cc +8 -2
  117. data/src/core/lib/iomgr/tcp_server_custom.cc +1 -0
  118. data/src/core/lib/iomgr/tcp_server_windows.cc +1 -1
  119. data/src/core/lib/iomgr/tcp_windows.cc +7 -7
  120. data/src/core/lib/iomgr/timer_custom.cc +1 -0
  121. data/src/core/lib/iomgr/timer_manager.cc +0 -29
  122. data/src/core/lib/security/credentials/credentials.cc +84 -0
  123. data/src/core/lib/security/credentials/credentials.h +58 -2
  124. data/src/core/lib/security/credentials/jwt/json_token.cc +6 -2
  125. data/src/core/lib/security/credentials/jwt/json_token.h +1 -1
  126. data/src/core/lib/security/credentials/oauth2/oauth2_credentials.cc +245 -24
  127. data/src/core/lib/security/credentials/oauth2/oauth2_credentials.h +16 -0
  128. data/src/core/lib/security/security_connector/alts/alts_security_connector.cc +3 -2
  129. data/src/core/lib/security/security_connector/fake/fake_security_connector.cc +21 -25
  130. data/src/core/lib/security/security_connector/local/local_security_connector.cc +3 -2
  131. data/src/core/lib/security/security_connector/security_connector.cc +1 -1
  132. data/src/core/lib/security/security_connector/security_connector.h +1 -1
  133. data/src/core/lib/security/security_connector/ssl/ssl_security_connector.cc +19 -19
  134. data/src/core/lib/security/security_connector/ssl_utils.cc +26 -31
  135. data/src/core/lib/security/security_connector/ssl_utils.h +11 -8
  136. data/src/core/lib/security/security_connector/tls/spiffe_security_connector.cc +16 -20
  137. data/src/core/lib/security/security_connector/tls/spiffe_security_connector.h +4 -3
  138. data/src/core/lib/security/transport/client_auth_filter.cc +1 -2
  139. data/src/core/lib/security/util/json_util.cc +19 -5
  140. data/src/core/lib/security/util/json_util.h +3 -1
  141. data/src/core/lib/slice/slice.cc +69 -50
  142. data/src/core/lib/slice/slice_buffer.cc +6 -5
  143. data/src/core/lib/slice/slice_hash_table.h +3 -7
  144. data/src/core/lib/slice/slice_intern.cc +130 -39
  145. data/src/core/lib/slice/slice_internal.h +8 -0
  146. data/src/core/lib/slice/slice_utils.h +120 -0
  147. data/src/core/lib/slice/slice_weak_hash_table.h +2 -7
  148. data/src/core/lib/surface/call.cc +8 -3
  149. data/src/core/lib/surface/channel.cc +31 -8
  150. data/src/core/lib/surface/completion_queue.cc +17 -7
  151. data/src/core/lib/surface/init_secure.cc +4 -1
  152. data/src/core/lib/surface/lame_client.cc +2 -2
  153. data/src/core/lib/surface/server.cc +34 -35
  154. data/src/core/lib/surface/server.h +8 -17
  155. data/src/core/lib/surface/version.cc +1 -1
  156. data/src/core/lib/transport/byte_stream.cc +3 -5
  157. data/src/core/lib/transport/byte_stream.h +1 -2
  158. data/src/core/lib/transport/error_utils.cc +10 -1
  159. data/src/core/lib/transport/metadata.cc +202 -35
  160. data/src/core/lib/transport/metadata.h +81 -6
  161. data/src/core/lib/transport/static_metadata.cc +1257 -465
  162. data/src/core/lib/transport/static_metadata.h +190 -347
  163. data/src/core/lib/transport/timeout_encoding.cc +7 -0
  164. data/src/core/lib/transport/timeout_encoding.h +3 -2
  165. data/src/core/plugin_registry/grpc_plugin_registry.cc +4 -0
  166. data/src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc +0 -1
  167. data/src/core/tsi/ssl/session_cache/ssl_session_cache.h +2 -7
  168. data/src/core/tsi/ssl_transport_security.cc +35 -43
  169. data/src/core/tsi/ssl_transport_security.h +2 -1
  170. data/src/ruby/ext/grpc/rb_grpc_imports.generated.c +2 -0
  171. data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +3 -0
  172. data/src/ruby/lib/grpc/generic/rpc_server.rb +1 -1
  173. data/src/ruby/lib/grpc/grpc.rb +1 -1
  174. data/src/ruby/lib/grpc/version.rb +1 -1
  175. metadata +39 -33
  176. data/src/core/lib/gpr/host_port.cc +0 -98
@@ -34,31 +34,22 @@ extern grpc_core::TraceFlag grpc_server_channel_trace;
34
34
 
35
35
  /* Add a listener to the server: when the server starts, it will call start,
36
36
  and when it shuts down, it will call destroy */
37
- void grpc_server_add_listener(grpc_server* server, void* listener,
38
- void (*start)(grpc_server* server, void* arg,
39
- grpc_pollset** pollsets,
40
- size_t npollsets),
41
- void (*destroy)(grpc_server* server, void* arg,
42
- grpc_closure* on_done),
43
- intptr_t socket_uuid);
37
+ void grpc_server_add_listener(
38
+ grpc_server* server, void* listener_arg,
39
+ void (*start)(grpc_server* server, void* arg, grpc_pollset** pollsets,
40
+ size_t npollsets),
41
+ void (*destroy)(grpc_server* server, void* arg, grpc_closure* on_done),
42
+ grpc_core::RefCountedPtr<grpc_core::channelz::ListenSocketNode> node);
44
43
 
45
44
  /* Setup a transport - creates a channel stack, binds the transport to the
46
45
  server */
47
46
  void grpc_server_setup_transport(
48
47
  grpc_server* server, grpc_transport* transport,
49
48
  grpc_pollset* accepting_pollset, const grpc_channel_args* args,
50
- grpc_core::RefCountedPtr<grpc_core::channelz::SocketNode> socket_node,
49
+ const grpc_core::RefCountedPtr<grpc_core::channelz::SocketNode>&
50
+ socket_node,
51
51
  grpc_resource_user* resource_user = nullptr);
52
52
 
53
- /* fills in the uuids of all sockets used for connections on this server */
54
- void grpc_server_populate_server_sockets(
55
- grpc_server* server, grpc_core::channelz::ChildSocketsList* server_sockets,
56
- intptr_t start_idx);
57
-
58
- /* fills in the uuids of all listen sockets on this server */
59
- void grpc_server_populate_listen_sockets(
60
- grpc_server* server, grpc_core::channelz::ChildRefsList* listen_sockets);
61
-
62
53
  grpc_core::channelz::ServerNode* grpc_server_get_channelz_node(
63
54
  grpc_server* server);
64
55
 
@@ -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 "gale"; }
28
+ const char* grpc_g_stands_for(void) { return "gangnam"; }
@@ -55,17 +55,15 @@ void SliceBufferByteStream::Orphan() {
55
55
 
56
56
  bool SliceBufferByteStream::Next(size_t max_size_hint,
57
57
  grpc_closure* on_complete) {
58
- GPR_ASSERT(cursor_ < backing_buffer_.count);
58
+ GPR_DEBUG_ASSERT(backing_buffer_.count > 0);
59
59
  return true;
60
60
  }
61
61
 
62
62
  grpc_error* SliceBufferByteStream::Pull(grpc_slice* slice) {
63
- if (shutdown_error_ != GRPC_ERROR_NONE) {
63
+ if (GPR_UNLIKELY(shutdown_error_ != GRPC_ERROR_NONE)) {
64
64
  return GRPC_ERROR_REF(shutdown_error_);
65
65
  }
66
- GPR_ASSERT(cursor_ < backing_buffer_.count);
67
- *slice = grpc_slice_ref_internal(backing_buffer_.slices[cursor_]);
68
- ++cursor_;
66
+ *slice = grpc_slice_buffer_take_first(&backing_buffer_);
69
67
  return GRPC_ERROR_NONE;
70
68
  }
71
69
 
@@ -99,9 +99,8 @@ class SliceBufferByteStream : public ByteStream {
99
99
  void Shutdown(grpc_error* error) override;
100
100
 
101
101
  private:
102
- grpc_slice_buffer backing_buffer_;
103
- size_t cursor_ = 0;
104
102
  grpc_error* shutdown_error_ = GRPC_ERROR_NONE;
103
+ grpc_slice_buffer backing_buffer_;
105
104
  };
106
105
 
107
106
  //
@@ -22,6 +22,7 @@
22
22
 
23
23
  #include <grpc/support/string_util.h>
24
24
  #include "src/core/lib/iomgr/error_internal.h"
25
+ #include "src/core/lib/slice/slice_internal.h"
25
26
  #include "src/core/lib/transport/status_conversion.h"
26
27
 
27
28
  static grpc_error* recursively_find_error_with_field(grpc_error* error,
@@ -52,7 +53,15 @@ void grpc_error_get_status(grpc_error* error, grpc_millis deadline,
52
53
  if (GPR_LIKELY(error == GRPC_ERROR_NONE)) {
53
54
  if (code != nullptr) *code = GRPC_STATUS_OK;
54
55
  if (slice != nullptr) {
55
- grpc_error_get_str(error, GRPC_ERROR_STR_GRPC_MESSAGE, slice);
56
+ // Normally, we call grpc_error_get_str(
57
+ // error, GRPC_ERROR_STR_GRPC_MESSAGE, slice).
58
+ // We can fastpath since we know that:
59
+ // 1) Error is null
60
+ // 2) which == GRPC_ERROR_STR_GRPC_MESSAGE
61
+ // 3) The resulting slice is statically known.
62
+ // 4) Said resulting slice is of length 0 ("").
63
+ // This means 3 movs, instead of 10s of instructions and a strlen.
64
+ *slice = grpc_core::ExternallyManagedSlice("");
56
65
  }
57
66
  if (http_error != nullptr) {
58
67
  *http_error = GRPC_HTTP2_NO_ERROR;
@@ -68,8 +68,8 @@ void grpc_mdelem_trace_ref(void* md, const grpc_slice& key,
68
68
  char* key_str = grpc_slice_to_c_string(key);
69
69
  char* value_str = grpc_slice_to_c_string(value);
70
70
  gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
71
- "ELM REF:%p:%" PRIdPTR "->%" PRIdPTR ": '%s' = '%s'", md, refcnt,
72
- refcnt + 1, key_str, value_str);
71
+ "mdelem REF:%p:%" PRIdPTR "->%" PRIdPTR ": '%s' = '%s'", md,
72
+ refcnt, refcnt + 1, key_str, value_str);
73
73
  gpr_free(key_str);
74
74
  gpr_free(value_str);
75
75
  }
@@ -82,7 +82,7 @@ void grpc_mdelem_trace_unref(void* md, const grpc_slice& key,
82
82
  char* key_str = grpc_slice_to_c_string(key);
83
83
  char* value_str = grpc_slice_to_c_string(value);
84
84
  gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
85
- "ELM UNREF:%p:%" PRIdPTR "->%" PRIdPTR ": '%s' = '%s'", md,
85
+ "mdelem UNREF:%p:%" PRIdPTR "->%" PRIdPTR ": '%s' = '%s'", md,
86
86
  refcnt, refcnt - 1, key_str, value_str);
87
87
  gpr_free(key_str);
88
88
  gpr_free(value_str);
@@ -112,14 +112,33 @@ AllocatedMetadata::AllocatedMetadata(const grpc_slice& key,
112
112
  : RefcountedMdBase(grpc_slice_ref_internal(key),
113
113
  grpc_slice_ref_internal(value)) {
114
114
  #ifndef NDEBUG
115
- if (grpc_trace_metadata.enabled()) {
116
- char* key_str = grpc_slice_to_c_string(key);
117
- char* value_str = grpc_slice_to_c_string(value);
118
- gpr_log(GPR_DEBUG, "ELM ALLOC:%p:%" PRIdPTR ": '%s' = '%s'", this,
119
- RefValue(), key_str, value_str);
120
- gpr_free(key_str);
121
- gpr_free(value_str);
122
- }
115
+ TraceAtStart("ALLOC_MD");
116
+ #endif
117
+ }
118
+
119
+ AllocatedMetadata::AllocatedMetadata(const grpc_slice& key,
120
+ const grpc_slice& value, const NoRefKey*)
121
+ : RefcountedMdBase(key, grpc_slice_ref_internal(value)) {
122
+ #ifndef NDEBUG
123
+ TraceAtStart("ALLOC_MD_NOREF_KEY");
124
+ #endif
125
+ }
126
+
127
+ AllocatedMetadata::AllocatedMetadata(
128
+ const grpc_core::ManagedMemorySlice& key,
129
+ const grpc_core::UnmanagedMemorySlice& value)
130
+ : RefcountedMdBase(key, value) {
131
+ #ifndef NDEBUG
132
+ TraceAtStart("ALLOC_MD_NOREF_KEY_VAL");
133
+ #endif
134
+ }
135
+
136
+ AllocatedMetadata::AllocatedMetadata(
137
+ const grpc_core::ExternallyManagedSlice& key,
138
+ const grpc_core::UnmanagedMemorySlice& value)
139
+ : RefcountedMdBase(key, value) {
140
+ #ifndef NDEBUG
141
+ TraceAtStart("ALLOC_MD_NOREF_KEY_VAL");
123
142
  #endif
124
143
  }
125
144
 
@@ -134,6 +153,19 @@ AllocatedMetadata::~AllocatedMetadata() {
134
153
  }
135
154
  }
136
155
 
156
+ #ifndef NDEBUG
157
+ void grpc_core::RefcountedMdBase::TraceAtStart(const char* tag) {
158
+ if (grpc_trace_metadata.enabled()) {
159
+ char* key_str = grpc_slice_to_c_string(key());
160
+ char* value_str = grpc_slice_to_c_string(value());
161
+ gpr_log(GPR_DEBUG, "mdelem %s:%p:%" PRIdPTR ": '%s' = '%s'", tag, this,
162
+ RefValue(), key_str, value_str);
163
+ gpr_free(key_str);
164
+ gpr_free(value_str);
165
+ }
166
+ }
167
+ #endif
168
+
137
169
  InternedMetadata::InternedMetadata(const grpc_slice& key,
138
170
  const grpc_slice& value, uint32_t hash,
139
171
  InternedMetadata* next)
@@ -141,14 +173,16 @@ InternedMetadata::InternedMetadata(const grpc_slice& key,
141
173
  grpc_slice_ref_internal(value), hash),
142
174
  link_(next) {
143
175
  #ifndef NDEBUG
144
- if (grpc_trace_metadata.enabled()) {
145
- char* key_str = grpc_slice_to_c_string(key);
146
- char* value_str = grpc_slice_to_c_string(value);
147
- gpr_log(GPR_DEBUG, "ELM NEW:%p:%" PRIdPTR ": '%s' = '%s'", this,
148
- RefValue(), key_str, value_str);
149
- gpr_free(key_str);
150
- gpr_free(value_str);
151
- }
176
+ TraceAtStart("INTERNED_MD");
177
+ #endif
178
+ }
179
+
180
+ InternedMetadata::InternedMetadata(const grpc_slice& key,
181
+ const grpc_slice& value, uint32_t hash,
182
+ InternedMetadata* next, const NoRefKey*)
183
+ : RefcountedMdBase(key, grpc_slice_ref_internal(value), hash), link_(next) {
184
+ #ifndef NDEBUG
185
+ TraceAtStart("INTERNED_MD_NOREF_KEY");
152
186
  #endif
153
187
  }
154
188
 
@@ -222,7 +256,12 @@ void grpc_mdctx_global_shutdown() {
222
256
  abort();
223
257
  }
224
258
  }
259
+ // For ASAN builds, we don't want to crash here, because that will
260
+ // prevent ASAN from providing leak detection information, which is
261
+ // far more useful than this simple assertion.
262
+ #ifndef GRPC_ASAN_ENABLED
225
263
  GPR_DEBUG_ASSERT(shard->count == 0);
264
+ #endif
226
265
  gpr_free(shard->elems);
227
266
  }
228
267
  }
@@ -243,8 +282,8 @@ void InternedMetadata::RefWithShardLocked(mdtab_shard* shard) {
243
282
  char* value_str = grpc_slice_to_c_string(value());
244
283
  intptr_t value = RefValue();
245
284
  gpr_log(__FILE__, __LINE__, GPR_LOG_SEVERITY_DEBUG,
246
- "ELM REF:%p:%" PRIdPTR "->%" PRIdPTR ": '%s' = '%s'", this, value,
247
- value + 1, key_str, value_str);
285
+ "mdelem REF:%p:%" PRIdPTR "->%" PRIdPTR ": '%s' = '%s'", this,
286
+ value, value + 1, key_str, value_str);
248
287
  gpr_free(key_str);
249
288
  gpr_free(value_str);
250
289
  }
@@ -302,36 +341,100 @@ static void rehash_mdtab(mdtab_shard* shard) {
302
341
  }
303
342
  }
304
343
 
305
- grpc_mdelem grpc_mdelem_create(
344
+ template <bool key_definitely_static, bool value_definitely_static = false>
345
+ static grpc_mdelem md_create_maybe_static(const grpc_slice& key,
346
+ const grpc_slice& value);
347
+ template <bool key_definitely_static>
348
+ static grpc_mdelem md_create_must_intern(const grpc_slice& key,
349
+ const grpc_slice& value,
350
+ uint32_t hash);
351
+
352
+ template <bool key_definitely_static, bool value_definitely_static = false>
353
+ static grpc_mdelem md_create(
306
354
  const grpc_slice& key, const grpc_slice& value,
307
355
  grpc_mdelem_data* compatible_external_backing_store) {
356
+ // Ensure slices are, in fact, static if we claimed they were.
357
+ GPR_DEBUG_ASSERT(!key_definitely_static ||
358
+ GRPC_IS_STATIC_METADATA_STRING(key));
359
+ GPR_DEBUG_ASSERT(!value_definitely_static ||
360
+ GRPC_IS_STATIC_METADATA_STRING(value));
361
+ const bool key_is_interned =
362
+ key_definitely_static || grpc_slice_is_interned(key);
363
+ const bool value_is_interned =
364
+ value_definitely_static || grpc_slice_is_interned(value);
308
365
  // External storage if either slice is not interned and the caller already
309
366
  // created a backing store. If no backing store, we allocate one.
310
- if (!grpc_slice_is_interned(key) || !grpc_slice_is_interned(value)) {
367
+ if (!key_is_interned || !value_is_interned) {
311
368
  if (compatible_external_backing_store != nullptr) {
312
369
  // Caller provided backing store.
313
370
  return GRPC_MAKE_MDELEM(compatible_external_backing_store,
314
371
  GRPC_MDELEM_STORAGE_EXTERNAL);
315
372
  } else {
316
373
  // We allocate backing store.
317
- return GRPC_MAKE_MDELEM(grpc_core::New<AllocatedMetadata>(key, value),
318
- GRPC_MDELEM_STORAGE_ALLOCATED);
374
+ return key_definitely_static
375
+ ? GRPC_MAKE_MDELEM(
376
+ grpc_core::New<AllocatedMetadata>(
377
+ key, value,
378
+ static_cast<const AllocatedMetadata::NoRefKey*>(
379
+ nullptr)),
380
+ GRPC_MDELEM_STORAGE_ALLOCATED)
381
+ : GRPC_MAKE_MDELEM(
382
+ grpc_core::New<AllocatedMetadata>(key, value),
383
+ GRPC_MDELEM_STORAGE_ALLOCATED);
319
384
  }
320
385
  }
386
+ return md_create_maybe_static<key_definitely_static, value_definitely_static>(
387
+ key, value);
388
+ }
389
+
390
+ template <bool key_definitely_static, bool value_definitely_static>
391
+ static grpc_mdelem md_create_maybe_static(const grpc_slice& key,
392
+ const grpc_slice& value) {
393
+ // Ensure slices are, in fact, static if we claimed they were.
394
+ GPR_DEBUG_ASSERT(!key_definitely_static ||
395
+ GRPC_IS_STATIC_METADATA_STRING(key));
396
+ GPR_DEBUG_ASSERT(!value_definitely_static ||
397
+ GRPC_IS_STATIC_METADATA_STRING(value));
398
+ GPR_DEBUG_ASSERT(key.refcount != nullptr);
399
+ GPR_DEBUG_ASSERT(value.refcount != nullptr);
400
+
401
+ const bool key_is_static_mdstr =
402
+ key_definitely_static ||
403
+ key.refcount->GetType() == grpc_slice_refcount::Type::STATIC;
404
+ const bool value_is_static_mdstr =
405
+ value_definitely_static ||
406
+ value.refcount->GetType() == grpc_slice_refcount::Type::STATIC;
407
+
408
+ const intptr_t kidx = GRPC_STATIC_METADATA_INDEX(key);
321
409
 
322
410
  // Not all static slice input yields a statically stored metadata element.
323
- // It may be worth documenting why.
324
- if (GRPC_IS_STATIC_METADATA_STRING(key) &&
325
- GRPC_IS_STATIC_METADATA_STRING(value)) {
411
+ if (key_is_static_mdstr && value_is_static_mdstr) {
326
412
  grpc_mdelem static_elem = grpc_static_mdelem_for_static_strings(
327
- GRPC_STATIC_METADATA_INDEX(key), GRPC_STATIC_METADATA_INDEX(value));
413
+ kidx, GRPC_STATIC_METADATA_INDEX(value));
328
414
  if (!GRPC_MDISNULL(static_elem)) {
329
415
  return static_elem;
330
416
  }
331
417
  }
332
418
 
333
- uint32_t hash = GRPC_MDSTR_KV_HASH(grpc_slice_hash_refcounted(key),
334
- grpc_slice_hash_refcounted(value));
419
+ uint32_t khash = key_definitely_static
420
+ ? grpc_static_metadata_hash_values[kidx]
421
+ : grpc_slice_hash_refcounted(key);
422
+
423
+ uint32_t hash = GRPC_MDSTR_KV_HASH(khash, grpc_slice_hash_refcounted(value));
424
+ return md_create_must_intern<key_definitely_static>(key, value, hash);
425
+ }
426
+
427
+ template <bool key_definitely_static>
428
+ static grpc_mdelem md_create_must_intern(const grpc_slice& key,
429
+ const grpc_slice& value,
430
+ uint32_t hash) {
431
+ // Here, we know both key and value are both at least interned, and both
432
+ // possibly static. We know that anything inside the shared interned table is
433
+ // also at least interned (and maybe static). Note that equality for a static
434
+ // and interned slice implies that they are both the same exact slice.
435
+ // The same applies to a pair of interned slices, or a pair of static slices.
436
+ // Rather than run the full equality check, we can therefore just do a pointer
437
+ // comparison of the refcounts.
335
438
  InternedMetadata* md;
336
439
  mdtab_shard* shard = &g_shards[SHARD_IDX(hash)];
337
440
  size_t idx;
@@ -343,7 +446,8 @@ grpc_mdelem grpc_mdelem_create(
343
446
  idx = TABLE_IDX(hash, shard->capacity);
344
447
  /* search for an existing pair */
345
448
  for (md = shard->elems[idx].next; md; md = md->bucket_next()) {
346
- if (grpc_slice_eq(key, md->key()) && grpc_slice_eq(value, md->value())) {
449
+ if (grpc_slice_static_interned_equal(key, md->key()) &&
450
+ grpc_slice_static_interned_equal(value, md->value())) {
347
451
  md->RefWithShardLocked(shard);
348
452
  gpr_mu_unlock(&shard->mu);
349
453
  return GRPC_MAKE_MDELEM(md, GRPC_MDELEM_STORAGE_INTERNED);
@@ -351,8 +455,12 @@ grpc_mdelem grpc_mdelem_create(
351
455
  }
352
456
 
353
457
  /* not found: create a new pair */
354
- md = grpc_core::New<InternedMetadata>(key, value, hash,
355
- shard->elems[idx].next);
458
+ md = key_definitely_static
459
+ ? grpc_core::New<InternedMetadata>(
460
+ key, value, hash, shard->elems[idx].next,
461
+ static_cast<const InternedMetadata::NoRefKey*>(nullptr))
462
+ : grpc_core::New<InternedMetadata>(key, value, hash,
463
+ shard->elems[idx].next);
356
464
  shard->elems[idx].next = md;
357
465
  shard->count++;
358
466
 
@@ -365,9 +473,68 @@ grpc_mdelem grpc_mdelem_create(
365
473
  return GRPC_MAKE_MDELEM(md, GRPC_MDELEM_STORAGE_INTERNED);
366
474
  }
367
475
 
476
+ grpc_mdelem grpc_mdelem_create(
477
+ const grpc_slice& key, const grpc_slice& value,
478
+ grpc_mdelem_data* compatible_external_backing_store) {
479
+ return md_create<false>(key, value, compatible_external_backing_store);
480
+ }
481
+
482
+ grpc_mdelem grpc_mdelem_create(
483
+ const grpc_core::StaticMetadataSlice& key, const grpc_slice& value,
484
+ grpc_mdelem_data* compatible_external_backing_store) {
485
+ return md_create<true>(key, value, compatible_external_backing_store);
486
+ }
487
+
488
+ /* Create grpc_mdelem from provided slices. We specify via template parameter
489
+ whether we know that the input key is static or not. If it is, we short
490
+ circuit various comparisons and a no-op unref. */
491
+ template <bool key_definitely_static>
492
+ static grpc_mdelem md_from_slices(const grpc_slice& key,
493
+ const grpc_slice& value) {
494
+ // Ensure key is, in fact, static if we claimed it was.
495
+ GPR_DEBUG_ASSERT(!key_definitely_static ||
496
+ GRPC_IS_STATIC_METADATA_STRING(key));
497
+ grpc_mdelem out = md_create<key_definitely_static>(key, value, nullptr);
498
+ if (!key_definitely_static) {
499
+ grpc_slice_unref_internal(key);
500
+ }
501
+ grpc_slice_unref_internal(value);
502
+ return out;
503
+ }
504
+
368
505
  grpc_mdelem grpc_mdelem_from_slices(const grpc_slice& key,
369
506
  const grpc_slice& value) {
370
- grpc_mdelem out = grpc_mdelem_create(key, value, nullptr);
507
+ return md_from_slices</*key_definitely_static=*/false>(key, value);
508
+ }
509
+
510
+ grpc_mdelem grpc_mdelem_from_slices(const grpc_core::StaticMetadataSlice& key,
511
+ const grpc_slice& value) {
512
+ return md_from_slices</*key_definitely_static=*/true>(key, value);
513
+ }
514
+
515
+ grpc_mdelem grpc_mdelem_from_slices(
516
+ const grpc_core::StaticMetadataSlice& key,
517
+ const grpc_core::StaticMetadataSlice& value) {
518
+ grpc_mdelem out = md_create_maybe_static<true, true>(key, value);
519
+ return out;
520
+ }
521
+
522
+ grpc_mdelem grpc_mdelem_from_slices(
523
+ const grpc_core::StaticMetadataSlice& key,
524
+ const grpc_core::ManagedMemorySlice& value) {
525
+ // TODO(arjunroy): We can save the unref if md_create_maybe_static ended up
526
+ // creating a new interned metadata. But otherwise - we need this here.
527
+ grpc_mdelem out = md_create_maybe_static<true>(key, value);
528
+ grpc_slice_unref_internal(value);
529
+ return out;
530
+ }
531
+
532
+ grpc_mdelem grpc_mdelem_from_slices(
533
+ const grpc_core::ManagedMemorySlice& key,
534
+ const grpc_core::ManagedMemorySlice& value) {
535
+ grpc_mdelem out = md_create_maybe_static<false>(key, value);
536
+ // TODO(arjunroy): We can save the unref if md_create_maybe_static ended up
537
+ // creating a new interned metadata. But otherwise - we need this here.
371
538
  grpc_slice_unref_internal(key);
372
539
  grpc_slice_unref_internal(value);
373
540
  return out;
@@ -118,10 +118,31 @@ struct grpc_mdelem {
118
118
  ((grpc_mdelem_data_storage)((md).payload & \
119
119
  (uintptr_t)GRPC_MDELEM_STORAGE_INTERNED_BIT))
120
120
 
121
- /* Unrefs the slices. */
121
+ /* Given arbitrary input slices, create a grpc_mdelem object. The caller refs
122
+ * the input slices; we unref them. This method is always safe to call; however,
123
+ * if we know data about the slices in question (e.g. if we knew our key was
124
+ * static) we can call specializations that save on cycle count. */
122
125
  grpc_mdelem grpc_mdelem_from_slices(const grpc_slice& key,
123
126
  const grpc_slice& value);
124
127
 
128
+ /* Like grpc_mdelem_from_slices, but we know that key is a static slice. This
129
+ saves us a few branches and a no-op call to md_unref() for the key. */
130
+ grpc_mdelem grpc_mdelem_from_slices(const grpc_core::StaticMetadataSlice& key,
131
+ const grpc_slice& value);
132
+
133
+ /* Like grpc_mdelem_from_slices, but key is static and val is static. */
134
+ grpc_mdelem grpc_mdelem_from_slices(
135
+ const grpc_core::StaticMetadataSlice& key,
136
+ const grpc_core::StaticMetadataSlice& value);
137
+
138
+ /* Like grpc_mdelem_from_slices, but key is static and val is interned. */
139
+ grpc_mdelem grpc_mdelem_from_slices(const grpc_core::StaticMetadataSlice& key,
140
+ const grpc_core::ManagedMemorySlice& value);
141
+
142
+ /* Like grpc_mdelem_from_slices, but key and val are interned. */
143
+ grpc_mdelem grpc_mdelem_from_slices(const grpc_core::ManagedMemorySlice& key,
144
+ const grpc_core::ManagedMemorySlice& value);
145
+
125
146
  /* Cheaply convert a grpc_metadata to a grpc_mdelem; may use the grpc_metadata
126
147
  object as backing storage (so lifetimes should align) */
127
148
  grpc_mdelem grpc_mdelem_from_grpc_metadata(grpc_metadata* metadata);
@@ -134,6 +155,11 @@ grpc_mdelem grpc_mdelem_create(
134
155
  const grpc_slice& key, const grpc_slice& value,
135
156
  grpc_mdelem_data* compatible_external_backing_store);
136
157
 
158
+ /* Like grpc_mdelem_create, but we know that key is static. */
159
+ grpc_mdelem grpc_mdelem_create(
160
+ const grpc_core::StaticMetadataSlice& key, const grpc_slice& value,
161
+ grpc_mdelem_data* compatible_external_backing_store);
162
+
137
163
  #define GRPC_MDKEY(md) (GRPC_MDELEM_DATA(md)->key)
138
164
  #define GRPC_MDVALUE(md) (GRPC_MDELEM_DATA(md)->value)
139
165
 
@@ -186,19 +212,21 @@ struct UserData {
186
212
 
187
213
  class StaticMetadata {
188
214
  public:
189
- StaticMetadata(const grpc_slice& key, const grpc_slice& value)
190
- : kv_({key, value}), hash_(0) {}
215
+ StaticMetadata(const grpc_slice& key, const grpc_slice& value, uintptr_t idx)
216
+ : kv_({key, value}), hash_(0), static_idx_(idx) {}
191
217
 
192
218
  const grpc_mdelem_data& data() const { return kv_; }
193
219
 
194
220
  void HashInit();
195
221
  uint32_t hash() { return hash_; }
222
+ uintptr_t StaticIndex() { return static_idx_; }
196
223
 
197
224
  private:
198
225
  grpc_mdelem_data kv_;
199
226
 
200
227
  /* private only data */
201
228
  uint32_t hash_;
229
+ uintptr_t static_idx_;
202
230
  };
203
231
 
204
232
  class RefcountedMdBase {
@@ -237,6 +265,10 @@ class RefcountedMdBase {
237
265
  }
238
266
 
239
267
  protected:
268
+ #ifndef NDEBUG
269
+ void TraceAtStart(const char* tag);
270
+ #endif
271
+
240
272
  intptr_t RefValue() { return refcnt_.Load(MemoryOrder::RELAXED); }
241
273
  bool AllRefsDropped() { return refcnt_.Load(MemoryOrder::ACQUIRE) == 0; }
242
274
  bool FirstRef() { return refcnt_.FetchAdd(1, MemoryOrder::RELAXED) == 0; }
@@ -251,16 +283,19 @@ class RefcountedMdBase {
251
283
 
252
284
  class InternedMetadata : public RefcountedMdBase {
253
285
  public:
286
+ // TODO(arjunroy): Change to use strongly typed slices instead.
287
+ struct NoRefKey {};
254
288
  struct BucketLink {
255
289
  explicit BucketLink(InternedMetadata* md) : next(md) {}
256
290
 
257
291
  InternedMetadata* next = nullptr;
258
292
  };
259
-
260
293
  InternedMetadata(const grpc_slice& key, const grpc_slice& value,
261
294
  uint32_t hash, InternedMetadata* next);
262
- ~InternedMetadata();
295
+ InternedMetadata(const grpc_slice& key, const grpc_slice& value,
296
+ uint32_t hash, InternedMetadata* next, const NoRefKey*);
263
297
 
298
+ ~InternedMetadata();
264
299
  void RefWithShardLocked(mdtab_shard* shard);
265
300
  UserData* user_data() { return &user_data_; }
266
301
  InternedMetadata* bucket_next() { return link_.next; }
@@ -276,7 +311,15 @@ class InternedMetadata : public RefcountedMdBase {
276
311
  /* Shadow structure for grpc_mdelem_data for allocated elements */
277
312
  class AllocatedMetadata : public RefcountedMdBase {
278
313
  public:
314
+ // TODO(arjunroy): Change to use strongly typed slices instead.
315
+ struct NoRefKey {};
279
316
  AllocatedMetadata(const grpc_slice& key, const grpc_slice& value);
317
+ AllocatedMetadata(const grpc_core::ManagedMemorySlice& key,
318
+ const grpc_core::UnmanagedMemorySlice& value);
319
+ AllocatedMetadata(const grpc_core::ExternallyManagedSlice& key,
320
+ const grpc_core::UnmanagedMemorySlice& value);
321
+ AllocatedMetadata(const grpc_slice& key, const grpc_slice& value,
322
+ const NoRefKey*);
280
323
  ~AllocatedMetadata();
281
324
 
282
325
  UserData* user_data() { return &user_data_; }
@@ -348,10 +391,11 @@ inline void grpc_mdelem_unref(grpc_mdelem gmd) {
348
391
  free an interned md at any time: it's unsafe from this point on to
349
392
  access it so we read the hash now. */
350
393
  uint32_t hash = md->hash();
351
- if (GPR_UNLIKELY(md->Unref())) {
352
394
  #ifndef NDEBUG
395
+ if (GPR_UNLIKELY(md->Unref(file, line))) {
353
396
  grpc_mdelem_on_final_unref(storage, md, hash, file, line);
354
397
  #else
398
+ if (GPR_UNLIKELY(md->Unref())) {
355
399
  grpc_mdelem_on_final_unref(storage, md, hash);
356
400
  #endif
357
401
  }
@@ -371,4 +415,35 @@ inline void grpc_mdelem_unref(grpc_mdelem gmd) {
371
415
  void grpc_mdctx_global_init(void);
372
416
  void grpc_mdctx_global_shutdown();
373
417
 
418
+ /* Like grpc_mdelem_from_slices, but we know that key is a static or interned
419
+ slice and value is not static or interned. This gives us an inlinable
420
+ fastpath - we know we must allocate metadata now, and that we do not need to
421
+ unref the value (rather, we just transfer the ref). We can avoid a ref since:
422
+ 1) the key slice is passed in already ref'd
423
+ 2) We're guaranteed to create a new Allocated slice, thus meaning the
424
+ ref can be considered 'transferred'.*/
425
+ inline grpc_mdelem grpc_mdelem_from_slices(
426
+ const grpc_core::ManagedMemorySlice& key,
427
+ const grpc_core::UnmanagedMemorySlice& value) {
428
+ using grpc_core::AllocatedMetadata;
429
+ return GRPC_MAKE_MDELEM(grpc_core::New<AllocatedMetadata>(key, value),
430
+ GRPC_MDELEM_STORAGE_ALLOCATED);
431
+ }
432
+
433
+ inline grpc_mdelem grpc_mdelem_from_slices(
434
+ const grpc_core::ExternallyManagedSlice& key,
435
+ const grpc_core::UnmanagedMemorySlice& value) {
436
+ using grpc_core::AllocatedMetadata;
437
+ return GRPC_MAKE_MDELEM(grpc_core::New<AllocatedMetadata>(key, value),
438
+ GRPC_MDELEM_STORAGE_ALLOCATED);
439
+ }
440
+
441
+ inline grpc_mdelem grpc_mdelem_from_slices(
442
+ const grpc_core::StaticMetadataSlice& key,
443
+ const grpc_core::UnmanagedMemorySlice& value) {
444
+ using grpc_core::AllocatedMetadata;
445
+ return GRPC_MAKE_MDELEM(grpc_core::New<AllocatedMetadata>(key, value),
446
+ GRPC_MDELEM_STORAGE_ALLOCATED);
447
+ }
448
+
374
449
  #endif /* GRPC_CORE_LIB_TRANSPORT_METADATA_H */