grpc 1.22.1 → 1.23.0.pre1

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 +264 -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 +41 -60
  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 +0 -1
  54. data/src/core/ext/transport/chttp2/transport/frame_rst_stream.cc +0 -8
  55. data/src/core/ext/transport/chttp2/transport/frame_rst_stream.h +0 -7
  56. data/src/core/ext/transport/chttp2/transport/frame_settings.cc +0 -1
  57. data/src/core/ext/transport/chttp2/transport/hpack_encoder.cc +37 -22
  58. data/src/core/ext/transport/chttp2/transport/hpack_parser.cc +137 -80
  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 +6 -9
  63. data/src/core/ext/transport/chttp2/transport/parsing.cc +37 -20
  64. data/src/core/ext/transport/chttp2/transport/stream_map.cc +28 -18
  65. data/src/core/ext/transport/chttp2/transport/writing.cc +0 -1
  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 +38 -32
  176. data/src/core/lib/gpr/host_port.cc +0 -98
@@ -328,6 +328,31 @@ GRPCAPI grpc_call_credentials* grpc_google_iam_credentials_create(
328
328
  const char* authorization_token, const char* authority_selector,
329
329
  void* reserved);
330
330
 
331
+ /** Options for creating STS Oauth Token Exchange credentials following the IETF
332
+ draft https://tools.ietf.org/html/draft-ietf-oauth-token-exchange-16.
333
+ Optional fields may be set to NULL or empty string. It is the responsibility
334
+ of the caller to ensure that the subject and actor tokens are refreshed on
335
+ disk at the specified paths. This API is used for experimental purposes for
336
+ now and may change in the future. */
337
+ typedef struct {
338
+ const char* token_exchange_service_uri; /* Required. */
339
+ const char* resource; /* Optional. */
340
+ const char* audience; /* Optional. */
341
+ const char* scope; /* Optional. */
342
+ const char* requested_token_type; /* Optional. */
343
+ const char* subject_token_path; /* Required. */
344
+ const char* subject_token_type; /* Required. */
345
+ const char* actor_token_path; /* Optional. */
346
+ const char* actor_token_type; /* Optional. */
347
+ } grpc_sts_credentials_options;
348
+
349
+ /** Creates an STS credentials following the STS Token Exchanged specifed in the
350
+ IETF draft https://tools.ietf.org/html/draft-ietf-oauth-token-exchange-16.
351
+ This API is used for experimental purposes for now and may change in the
352
+ future. */
353
+ GRPCAPI grpc_call_credentials* grpc_sts_credentials_create(
354
+ const grpc_sts_credentials_options* options, void* reserved);
355
+
331
356
  /** Callback function to be called by the metadata credentials plugin
332
357
  implementation when the metadata is ready.
333
358
  - user_data is the opaque pointer that was passed in the get_metadata method
@@ -157,8 +157,9 @@ typedef struct {
157
157
  /** Maximum message length that the channel can send. Int valued, bytes.
158
158
  -1 means unlimited. */
159
159
  #define GRPC_ARG_MAX_SEND_MESSAGE_LENGTH "grpc.max_send_message_length"
160
- /** Maximum time that a channel may have no outstanding rpcs. Int valued,
161
- milliseconds. INT_MAX means unlimited. */
160
+ /** Maximum time that a channel may have no outstanding rpcs, after which the
161
+ * server will close the connection. Int valued, milliseconds. INT_MAX means
162
+ * unlimited. */
162
163
  #define GRPC_ARG_MAX_CONNECTION_IDLE_MS "grpc.max_connection_idle_ms"
163
164
  /** Maximum time that a channel may exist. Int valued, milliseconds.
164
165
  * INT_MAX means unlimited. */
@@ -166,6 +167,14 @@ typedef struct {
166
167
  /** Grace period after the channel reaches its max age. Int valued,
167
168
  milliseconds. INT_MAX means unlimited. */
168
169
  #define GRPC_ARG_MAX_CONNECTION_AGE_GRACE_MS "grpc.max_connection_age_grace_ms"
170
+ /** Timeout after the last RPC finishes on the client channel at which the
171
+ * channel goes back into IDLE state. Int valued, milliseconds. INT_MAX means
172
+ * unlimited. */
173
+ /** TODO(qianchengz): Currently the default value is INT_MAX, which means the
174
+ * client idle filter is disabled by default. After the client idle filter
175
+ * proves no perfomance issue, we will change the default value to a reasonable
176
+ * value. */
177
+ #define GRPC_ARG_CLIENT_IDLE_TIMEOUT_MS "grpc.client_idle_timeout_ms"
169
178
  /** Enable/disable support for per-message compression. Defaults to 1, unless
170
179
  GRPC_ARG_MINIMAL_STACK is enabled, in which case it defaults to 0. */
171
180
  #define GRPC_ARG_ENABLE_PER_MESSAGE_COMPRESSION "grpc.per_message_compression"
@@ -394,6 +394,18 @@
394
394
  #endif
395
395
  #endif /* GPR_NO_AUTODETECT_PLATFORM */
396
396
 
397
+ #if defined(GPR_BACKWARDS_COMPATIBILITY_MODE)
398
+ /*
399
+ * For backward compatibility mode, reset _FORTIFY_SOURCE to prevent
400
+ * a library from having non-standard symbols such as __asprintf_chk.
401
+ * This helps non-glibc systems such as alpine using musl to find symbols.
402
+ */
403
+ #if defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0
404
+ #undef _FORTIFY_SOURCE
405
+ #define _FORTIFY_SOURCE 0
406
+ #endif
407
+ #endif
408
+
397
409
  /*
398
410
  * There are platforms for which TLS should not be used even though the
399
411
  * compiler makes it seem like it's supported (Android NDK < r12b for example).
@@ -24,10 +24,12 @@
24
24
  #include <grpc/support/alloc.h>
25
25
  #include <grpc/support/log.h>
26
26
  #include <grpc/support/sync.h>
27
+
27
28
  #include "src/core/ext/filters/client_channel/client_channel.h"
28
29
  #include "src/core/lib/gpr/string.h"
29
30
  #include "src/core/lib/gprpp/global_config.h"
30
31
  #include "src/core/lib/iomgr/error.h"
32
+ #include "src/core/lib/iomgr/iomgr.h"
31
33
  #include "src/core/lib/iomgr/pollset.h"
32
34
  #include "src/core/lib/iomgr/timer.h"
33
35
  #include "src/core/lib/surface/channel.h"
@@ -153,7 +155,7 @@ static void g_poller_init_locked() {
153
155
 
154
156
  void grpc_client_channel_start_backup_polling(
155
157
  grpc_pollset_set* interested_parties) {
156
- if (g_poll_interval_ms == 0) {
158
+ if (g_poll_interval_ms == 0 || grpc_iomgr_run_in_background()) {
157
159
  return;
158
160
  }
159
161
  gpr_mu_lock(&g_poller_mu);
@@ -171,7 +173,7 @@ void grpc_client_channel_start_backup_polling(
171
173
 
172
174
  void grpc_client_channel_stop_backup_polling(
173
175
  grpc_pollset_set* interested_parties) {
174
- if (g_poll_interval_ms == 0) {
176
+ if (g_poll_interval_ms == 0 || grpc_iomgr_run_in_background()) {
175
177
  return;
176
178
  }
177
179
  grpc_pollset_set_del_pollset(interested_parties, g_poller->pollset);
@@ -147,6 +147,9 @@ class ChannelData {
147
147
  return service_config_;
148
148
  }
149
149
 
150
+ RefCountedPtr<ConnectedSubchannel> GetConnectedSubchannelInDataPlane(
151
+ SubchannelInterface* subchannel) const;
152
+
150
153
  grpc_connectivity_state CheckConnectivityState(bool try_to_connect);
151
154
  void AddExternalConnectivityWatcher(grpc_polling_entity pollent,
152
155
  grpc_connectivity_state* state,
@@ -161,9 +164,9 @@ class ChannelData {
161
164
  }
162
165
 
163
166
  private:
167
+ class SubchannelWrapper;
164
168
  class ConnectivityStateAndPickerSetter;
165
169
  class ServiceConfigSetter;
166
- class GrpcSubchannel;
167
170
  class ClientChannelControlHelper;
168
171
 
169
172
  class ExternalConnectivityWatcher {
@@ -210,6 +213,10 @@ class ChannelData {
210
213
  ChannelData(grpc_channel_element_args* args, grpc_error** error);
211
214
  ~ChannelData();
212
215
 
216
+ void CreateResolvingLoadBalancingPolicyLocked();
217
+
218
+ void DestroyResolvingLoadBalancingPolicyLocked();
219
+
213
220
  static bool ProcessResolverResultLocked(
214
221
  void* arg, const Resolver::Result& result, const char** lb_policy_name,
215
222
  RefCountedPtr<LoadBalancingPolicy::Config>* lb_policy_config,
@@ -235,8 +242,10 @@ class ChannelData {
235
242
  const size_t per_rpc_retry_buffer_size_;
236
243
  grpc_channel_stack* owning_stack_;
237
244
  ClientChannelFactory* client_channel_factory_;
238
- UniquePtr<char> server_name_;
245
+ const grpc_channel_args* channel_args_;
239
246
  RefCountedPtr<ServiceConfig> default_service_config_;
247
+ UniquePtr<char> server_name_;
248
+ UniquePtr<char> target_uri_;
240
249
  channelz::ChannelNode* channelz_node_;
241
250
 
242
251
  //
@@ -262,7 +271,14 @@ class ChannelData {
262
271
  UniquePtr<char> health_check_service_name_;
263
272
  RefCountedPtr<ServiceConfig> saved_service_config_;
264
273
  bool received_first_resolver_result_ = false;
274
+ // The number of SubchannelWrapper instances referencing a given Subchannel.
265
275
  Map<Subchannel*, int> subchannel_refcount_map_;
276
+ // Pending ConnectedSubchannel updates for each SubchannelWrapper.
277
+ // Updates are queued here in the control plane combiner and then applied
278
+ // in the data plane combiner when the picker is updated.
279
+ Map<RefCountedPtr<SubchannelWrapper>, RefCountedPtr<ConnectedSubchannel>,
280
+ RefCountedPtrLess<SubchannelWrapper>>
281
+ pending_subchannel_updates_;
266
282
 
267
283
  //
268
284
  // Fields accessed from both data plane and control plane combiners.
@@ -304,6 +320,54 @@ class CallData {
304
320
  private:
305
321
  class QueuedPickCanceller;
306
322
 
323
+ class Metadata : public LoadBalancingPolicy::MetadataInterface {
324
+ public:
325
+ Metadata(CallData* calld, grpc_metadata_batch* batch)
326
+ : calld_(calld), batch_(batch) {}
327
+
328
+ void Add(StringView key, StringView value) override {
329
+ grpc_linked_mdelem* linked_mdelem = static_cast<grpc_linked_mdelem*>(
330
+ calld_->arena_->Alloc(sizeof(grpc_linked_mdelem)));
331
+ linked_mdelem->md = grpc_mdelem_from_slices(
332
+ grpc_core::ExternallyManagedSlice(key.data(), key.size()),
333
+ grpc_core::ExternallyManagedSlice(value.data(), value.size()));
334
+ GPR_ASSERT(grpc_metadata_batch_link_tail(batch_, linked_mdelem) ==
335
+ GRPC_ERROR_NONE);
336
+ }
337
+
338
+ Iterator Begin() const override {
339
+ static_assert(sizeof(grpc_linked_mdelem*) <= sizeof(Iterator),
340
+ "iterator size too large");
341
+ return reinterpret_cast<Iterator>(batch_->list.head);
342
+ }
343
+ bool IsEnd(Iterator it) const override {
344
+ return reinterpret_cast<grpc_linked_mdelem*>(it) == nullptr;
345
+ }
346
+ void Next(Iterator* it) const override {
347
+ *it = reinterpret_cast<Iterator>(
348
+ reinterpret_cast<grpc_linked_mdelem*>(*it)->next);
349
+ }
350
+ StringView Key(Iterator it) const override {
351
+ return StringView(
352
+ GRPC_MDKEY(reinterpret_cast<grpc_linked_mdelem*>(it)->md));
353
+ }
354
+ StringView Value(Iterator it) const override {
355
+ return StringView(
356
+ GRPC_MDVALUE(reinterpret_cast<grpc_linked_mdelem*>(it)->md));
357
+ }
358
+
359
+ void Erase(Iterator* it) override {
360
+ grpc_linked_mdelem* linked_mdelem =
361
+ reinterpret_cast<grpc_linked_mdelem*>(*it);
362
+ *it = reinterpret_cast<Iterator>(linked_mdelem->next);
363
+ grpc_metadata_batch_remove(batch_, linked_mdelem);
364
+ }
365
+
366
+ private:
367
+ CallData* calld_;
368
+ grpc_metadata_batch* batch_;
369
+ };
370
+
307
371
  class LbCallState : public LoadBalancingPolicy::CallState {
308
372
  public:
309
373
  explicit LbCallState(CallData* calld) : calld_(calld) {}
@@ -644,7 +708,8 @@ class CallData {
644
708
  LbCallState lb_call_state_;
645
709
  RefCountedPtr<ConnectedSubchannel> connected_subchannel_;
646
710
  void (*lb_recv_trailing_metadata_ready_)(
647
- void* user_data, grpc_metadata_batch* recv_trailing_metadata,
711
+ void* user_data,
712
+ LoadBalancingPolicy::MetadataInterface* recv_trailing_metadata,
648
713
  LoadBalancingPolicy::CallState* call_state) = nullptr;
649
714
  void* lb_recv_trailing_metadata_ready_user_data_ = nullptr;
650
715
  grpc_closure pick_closure_;
@@ -706,6 +771,247 @@ class CallData {
706
771
  grpc_metadata_batch send_trailing_metadata_;
707
772
  };
708
773
 
774
+ //
775
+ // ChannelData::SubchannelWrapper
776
+ //
777
+
778
+ // This class is a wrapper for Subchannel that hides details of the
779
+ // channel's implementation (such as the health check service name and
780
+ // connected subchannel) from the LB policy API.
781
+ //
782
+ // Note that no synchronization is needed here, because even if the
783
+ // underlying subchannel is shared between channels, this wrapper will only
784
+ // be used within one channel, so it will always be synchronized by the
785
+ // control plane combiner.
786
+ class ChannelData::SubchannelWrapper : public SubchannelInterface {
787
+ public:
788
+ SubchannelWrapper(ChannelData* chand, Subchannel* subchannel,
789
+ UniquePtr<char> health_check_service_name)
790
+ : SubchannelInterface(&grpc_client_channel_routing_trace),
791
+ chand_(chand),
792
+ subchannel_(subchannel),
793
+ health_check_service_name_(std::move(health_check_service_name)) {
794
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) {
795
+ gpr_log(GPR_INFO,
796
+ "chand=%p: creating subchannel wrapper %p for subchannel %p",
797
+ chand, this, subchannel_);
798
+ }
799
+ GRPC_CHANNEL_STACK_REF(chand_->owning_stack_, "SubchannelWrapper");
800
+ auto* subchannel_node = subchannel_->channelz_node();
801
+ if (subchannel_node != nullptr) {
802
+ intptr_t subchannel_uuid = subchannel_node->uuid();
803
+ auto it = chand_->subchannel_refcount_map_.find(subchannel_);
804
+ if (it == chand_->subchannel_refcount_map_.end()) {
805
+ chand_->channelz_node_->AddChildSubchannel(subchannel_uuid);
806
+ it = chand_->subchannel_refcount_map_.emplace(subchannel_, 0).first;
807
+ }
808
+ ++it->second;
809
+ }
810
+ }
811
+
812
+ ~SubchannelWrapper() {
813
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) {
814
+ gpr_log(GPR_INFO,
815
+ "chand=%p: destroying subchannel wrapper %p for subchannel %p",
816
+ chand_, this, subchannel_);
817
+ }
818
+ auto* subchannel_node = subchannel_->channelz_node();
819
+ if (subchannel_node != nullptr) {
820
+ intptr_t subchannel_uuid = subchannel_node->uuid();
821
+ auto it = chand_->subchannel_refcount_map_.find(subchannel_);
822
+ GPR_ASSERT(it != chand_->subchannel_refcount_map_.end());
823
+ --it->second;
824
+ if (it->second == 0) {
825
+ chand_->channelz_node_->RemoveChildSubchannel(subchannel_uuid);
826
+ chand_->subchannel_refcount_map_.erase(it);
827
+ }
828
+ }
829
+ GRPC_SUBCHANNEL_UNREF(subchannel_, "unref from LB");
830
+ GRPC_CHANNEL_STACK_UNREF(chand_->owning_stack_, "SubchannelWrapper");
831
+ }
832
+
833
+ grpc_connectivity_state CheckConnectivityState() override {
834
+ RefCountedPtr<ConnectedSubchannel> connected_subchannel;
835
+ grpc_connectivity_state connectivity_state =
836
+ subchannel_->CheckConnectivityState(health_check_service_name_.get(),
837
+ &connected_subchannel);
838
+ MaybeUpdateConnectedSubchannel(std::move(connected_subchannel));
839
+ return connectivity_state;
840
+ }
841
+
842
+ void WatchConnectivityState(
843
+ grpc_connectivity_state initial_state,
844
+ UniquePtr<ConnectivityStateWatcherInterface> watcher) override {
845
+ auto& watcher_wrapper = watcher_map_[watcher.get()];
846
+ GPR_ASSERT(watcher_wrapper == nullptr);
847
+ watcher_wrapper = New<WatcherWrapper>(
848
+ std::move(watcher), Ref(DEBUG_LOCATION, "WatcherWrapper"));
849
+ subchannel_->WatchConnectivityState(
850
+ initial_state,
851
+ UniquePtr<char>(gpr_strdup(health_check_service_name_.get())),
852
+ OrphanablePtr<Subchannel::ConnectivityStateWatcherInterface>(
853
+ watcher_wrapper));
854
+ }
855
+
856
+ void CancelConnectivityStateWatch(
857
+ ConnectivityStateWatcherInterface* watcher) override {
858
+ auto it = watcher_map_.find(watcher);
859
+ GPR_ASSERT(it != watcher_map_.end());
860
+ subchannel_->CancelConnectivityStateWatch(health_check_service_name_.get(),
861
+ it->second);
862
+ watcher_map_.erase(it);
863
+ }
864
+
865
+ void AttemptToConnect() override { subchannel_->AttemptToConnect(); }
866
+
867
+ void ResetBackoff() override { subchannel_->ResetBackoff(); }
868
+
869
+ const grpc_channel_args* channel_args() override {
870
+ return subchannel_->channel_args();
871
+ }
872
+
873
+ // Caller must be holding the control-plane combiner.
874
+ ConnectedSubchannel* connected_subchannel() const {
875
+ return connected_subchannel_.get();
876
+ }
877
+
878
+ // Caller must be holding the data-plane combiner.
879
+ ConnectedSubchannel* connected_subchannel_in_data_plane() const {
880
+ return connected_subchannel_in_data_plane_.get();
881
+ }
882
+ void set_connected_subchannel_in_data_plane(
883
+ RefCountedPtr<ConnectedSubchannel> connected_subchannel) {
884
+ connected_subchannel_in_data_plane_ = std::move(connected_subchannel);
885
+ }
886
+
887
+ private:
888
+ // Subchannel and SubchannelInterface have different interfaces for
889
+ // their respective ConnectivityStateWatcherInterface classes.
890
+ // The one in Subchannel updates the ConnectedSubchannel along with
891
+ // the state, whereas the one in SubchannelInterface does not expose
892
+ // the ConnectedSubchannel.
893
+ //
894
+ // This wrapper provides a bridge between the two. It implements
895
+ // Subchannel::ConnectivityStateWatcherInterface and wraps
896
+ // the instance of SubchannelInterface::ConnectivityStateWatcherInterface
897
+ // that was passed in by the LB policy. We pass an instance of this
898
+ // class to the underlying Subchannel, and when we get updates from
899
+ // the subchannel, we pass those on to the wrapped watcher to return
900
+ // the update to the LB policy. This allows us to set the connected
901
+ // subchannel before passing the result back to the LB policy.
902
+ class WatcherWrapper : public Subchannel::ConnectivityStateWatcherInterface {
903
+ public:
904
+ WatcherWrapper(
905
+ UniquePtr<SubchannelInterface::ConnectivityStateWatcherInterface>
906
+ watcher,
907
+ RefCountedPtr<SubchannelWrapper> parent)
908
+ : watcher_(std::move(watcher)), parent_(std::move(parent)) {}
909
+
910
+ ~WatcherWrapper() { parent_.reset(DEBUG_LOCATION, "WatcherWrapper"); }
911
+
912
+ void Orphan() override { Unref(); }
913
+
914
+ void OnConnectivityStateChange(
915
+ grpc_connectivity_state new_state,
916
+ RefCountedPtr<ConnectedSubchannel> connected_subchannel) override {
917
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) {
918
+ gpr_log(GPR_INFO,
919
+ "chand=%p: connectivity change for subchannel wrapper %p "
920
+ "subchannel %p (connected_subchannel=%p state=%s); "
921
+ "hopping into combiner",
922
+ parent_->chand_, parent_.get(), parent_->subchannel_,
923
+ connected_subchannel.get(),
924
+ grpc_connectivity_state_name(new_state));
925
+ }
926
+ // Will delete itself.
927
+ New<Updater>(Ref(), new_state, std::move(connected_subchannel));
928
+ }
929
+
930
+ grpc_pollset_set* interested_parties() override {
931
+ return watcher_->interested_parties();
932
+ }
933
+
934
+ private:
935
+ class Updater {
936
+ public:
937
+ Updater(RefCountedPtr<WatcherWrapper> parent,
938
+ grpc_connectivity_state new_state,
939
+ RefCountedPtr<ConnectedSubchannel> connected_subchannel)
940
+ : parent_(std::move(parent)),
941
+ state_(new_state),
942
+ connected_subchannel_(std::move(connected_subchannel)) {
943
+ GRPC_CLOSURE_INIT(
944
+ &closure_, ApplyUpdateInControlPlaneCombiner, this,
945
+ grpc_combiner_scheduler(parent_->parent_->chand_->combiner_));
946
+ GRPC_CLOSURE_SCHED(&closure_, GRPC_ERROR_NONE);
947
+ }
948
+
949
+ private:
950
+ static void ApplyUpdateInControlPlaneCombiner(void* arg,
951
+ grpc_error* error) {
952
+ Updater* self = static_cast<Updater*>(arg);
953
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) {
954
+ gpr_log(GPR_INFO,
955
+ "chand=%p: processing connectivity change in combiner "
956
+ "for subchannel wrapper %p subchannel %p "
957
+ "(connected_subchannel=%p state=%s)",
958
+ self->parent_->parent_->chand_, self->parent_->parent_.get(),
959
+ self->parent_->parent_->subchannel_,
960
+ self->connected_subchannel_.get(),
961
+ grpc_connectivity_state_name(self->state_));
962
+ }
963
+ self->parent_->parent_->MaybeUpdateConnectedSubchannel(
964
+ std::move(self->connected_subchannel_));
965
+ self->parent_->watcher_->OnConnectivityStateChange(self->state_);
966
+ Delete(self);
967
+ }
968
+
969
+ RefCountedPtr<WatcherWrapper> parent_;
970
+ grpc_connectivity_state state_;
971
+ RefCountedPtr<ConnectedSubchannel> connected_subchannel_;
972
+ grpc_closure closure_;
973
+ };
974
+
975
+ UniquePtr<SubchannelInterface::ConnectivityStateWatcherInterface> watcher_;
976
+ RefCountedPtr<SubchannelWrapper> parent_;
977
+ };
978
+
979
+ void MaybeUpdateConnectedSubchannel(
980
+ RefCountedPtr<ConnectedSubchannel> connected_subchannel) {
981
+ // Update the connected subchannel only if the channel is not shutting
982
+ // down. This is because once the channel is shutting down, we
983
+ // ignore picker updates from the LB policy, which means that
984
+ // ConnectivityStateAndPickerSetter will never process the entries
985
+ // in chand_->pending_subchannel_updates_. So we don't want to add
986
+ // entries there that will never be processed, since that would
987
+ // leave dangling refs to the channel and prevent its destruction.
988
+ grpc_error* disconnect_error = chand_->disconnect_error();
989
+ if (disconnect_error != GRPC_ERROR_NONE) return;
990
+ // Not shutting down, so do the update.
991
+ if (connected_subchannel_ != connected_subchannel) {
992
+ connected_subchannel_ = std::move(connected_subchannel);
993
+ // Record the new connected subchannel so that it can be updated
994
+ // in the data plane combiner the next time the picker is updated.
995
+ chand_->pending_subchannel_updates_[Ref(
996
+ DEBUG_LOCATION, "ConnectedSubchannelUpdate")] = connected_subchannel_;
997
+ }
998
+ }
999
+
1000
+ ChannelData* chand_;
1001
+ Subchannel* subchannel_;
1002
+ UniquePtr<char> health_check_service_name_;
1003
+ // Maps from the address of the watcher passed to us by the LB policy
1004
+ // to the address of the WrapperWatcher that we passed to the underlying
1005
+ // subchannel. This is needed so that when the LB policy calls
1006
+ // CancelConnectivityStateWatch() with its watcher, we know the
1007
+ // corresponding WrapperWatcher to cancel on the underlying subchannel.
1008
+ Map<ConnectivityStateWatcherInterface*, WatcherWrapper*> watcher_map_;
1009
+ // To be accessed only in the control plane combiner.
1010
+ RefCountedPtr<ConnectedSubchannel> connected_subchannel_;
1011
+ // To be accessed only in the data plane combiner.
1012
+ RefCountedPtr<ConnectedSubchannel> connected_subchannel_in_data_plane_;
1013
+ };
1014
+
709
1015
  //
710
1016
  // ChannelData::ConnectivityStateAndPickerSetter
711
1017
  //
@@ -720,6 +1026,13 @@ class ChannelData::ConnectivityStateAndPickerSetter {
720
1026
  ChannelData* chand, grpc_connectivity_state state, const char* reason,
721
1027
  UniquePtr<LoadBalancingPolicy::SubchannelPicker> picker)
722
1028
  : chand_(chand), picker_(std::move(picker)) {
1029
+ // Clean the control plane when entering IDLE, while holding control plane
1030
+ // combiner.
1031
+ if (picker_ == nullptr) {
1032
+ chand->health_check_service_name_.reset();
1033
+ chand->saved_service_config_.reset();
1034
+ chand->received_first_resolver_result_ = false;
1035
+ }
723
1036
  // Update connectivity state here, while holding control plane combiner.
724
1037
  grpc_connectivity_state_set(&chand->state_tracker_, state, reason);
725
1038
  if (chand->channelz_node_ != nullptr) {
@@ -727,44 +1040,59 @@ class ChannelData::ConnectivityStateAndPickerSetter {
727
1040
  chand->channelz_node_->AddTraceEvent(
728
1041
  channelz::ChannelTrace::Severity::Info,
729
1042
  grpc_slice_from_static_string(
730
- GetChannelConnectivityStateChangeString(state)));
1043
+ channelz::ChannelNode::GetChannelConnectivityStateChangeString(
1044
+ state)));
731
1045
  }
1046
+ // Grab any pending subchannel updates.
1047
+ pending_subchannel_updates_ =
1048
+ std::move(chand_->pending_subchannel_updates_);
732
1049
  // Bounce into the data plane combiner to reset the picker.
733
1050
  GRPC_CHANNEL_STACK_REF(chand->owning_stack_,
734
1051
  "ConnectivityStateAndPickerSetter");
735
- GRPC_CLOSURE_INIT(&closure_, SetPicker, this,
1052
+ GRPC_CLOSURE_INIT(&closure_, SetPickerInDataPlane, this,
736
1053
  grpc_combiner_scheduler(chand->data_plane_combiner_));
737
1054
  GRPC_CLOSURE_SCHED(&closure_, GRPC_ERROR_NONE);
738
1055
  }
739
1056
 
740
1057
  private:
741
- static const char* GetChannelConnectivityStateChangeString(
742
- grpc_connectivity_state state) {
743
- switch (state) {
744
- case GRPC_CHANNEL_IDLE:
745
- return "Channel state change to IDLE";
746
- case GRPC_CHANNEL_CONNECTING:
747
- return "Channel state change to CONNECTING";
748
- case GRPC_CHANNEL_READY:
749
- return "Channel state change to READY";
750
- case GRPC_CHANNEL_TRANSIENT_FAILURE:
751
- return "Channel state change to TRANSIENT_FAILURE";
752
- case GRPC_CHANNEL_SHUTDOWN:
753
- return "Channel state change to SHUTDOWN";
754
- }
755
- GPR_UNREACHABLE_CODE(return "UNKNOWN");
756
- }
757
-
758
- static void SetPicker(void* arg, grpc_error* ignored) {
1058
+ static void SetPickerInDataPlane(void* arg, grpc_error* ignored) {
759
1059
  auto* self = static_cast<ConnectivityStateAndPickerSetter*>(arg);
760
- // Update picker.
761
- self->chand_->picker_ = std::move(self->picker_);
1060
+ // Handle subchannel updates.
1061
+ for (auto& p : self->pending_subchannel_updates_) {
1062
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) {
1063
+ gpr_log(GPR_INFO,
1064
+ "chand=%p: updating subchannel wrapper %p data plane "
1065
+ "connected_subchannel to %p",
1066
+ self->chand_, p.first.get(), p.second.get());
1067
+ }
1068
+ p.first->set_connected_subchannel_in_data_plane(std::move(p.second));
1069
+ }
1070
+ // Swap out the picker. We hang on to the old picker so that it can
1071
+ // be deleted in the control-plane combiner, since that's where we need
1072
+ // to unref the subchannel wrappers that are reffed by the picker.
1073
+ self->picker_.swap(self->chand_->picker_);
1074
+ // Clean the data plane if the updated picker is nullptr.
1075
+ if (self->chand_->picker_ == nullptr) {
1076
+ self->chand_->received_service_config_data_ = false;
1077
+ self->chand_->retry_throttle_data_.reset();
1078
+ self->chand_->service_config_.reset();
1079
+ }
762
1080
  // Re-process queued picks.
763
1081
  for (QueuedPick* pick = self->chand_->queued_picks_; pick != nullptr;
764
1082
  pick = pick->next) {
765
1083
  CallData::StartPickLocked(pick->elem, GRPC_ERROR_NONE);
766
1084
  }
767
- // Clean up.
1085
+ // Pop back into the control plane combiner to delete ourself, so
1086
+ // that we make sure to unref subchannel wrappers there. This
1087
+ // includes both the ones reffed by the old picker (now stored in
1088
+ // self->picker_) and the ones in self->pending_subchannel_updates_.
1089
+ GRPC_CLOSURE_INIT(&self->closure_, CleanUpInControlPlane, self,
1090
+ grpc_combiner_scheduler(self->chand_->combiner_));
1091
+ GRPC_CLOSURE_SCHED(&self->closure_, GRPC_ERROR_NONE);
1092
+ }
1093
+
1094
+ static void CleanUpInControlPlane(void* arg, grpc_error* ignored) {
1095
+ auto* self = static_cast<ConnectivityStateAndPickerSetter*>(arg);
768
1096
  GRPC_CHANNEL_STACK_UNREF(self->chand_->owning_stack_,
769
1097
  "ConnectivityStateAndPickerSetter");
770
1098
  Delete(self);
@@ -772,6 +1100,9 @@ class ChannelData::ConnectivityStateAndPickerSetter {
772
1100
 
773
1101
  ChannelData* chand_;
774
1102
  UniquePtr<LoadBalancingPolicy::SubchannelPicker> picker_;
1103
+ Map<RefCountedPtr<SubchannelWrapper>, RefCountedPtr<ConnectedSubchannel>,
1104
+ RefCountedPtrLess<SubchannelWrapper>>
1105
+ pending_subchannel_updates_;
775
1106
  grpc_closure closure_;
776
1107
  };
777
1108
 
@@ -946,89 +1277,6 @@ void ChannelData::ExternalConnectivityWatcher::WatchConnectivityStateLocked(
946
1277
  &self->chand_->state_tracker_, self->state_, &self->my_closure_);
947
1278
  }
948
1279
 
949
- //
950
- // ChannelData::GrpcSubchannel
951
- //
952
-
953
- // This class is a wrapper for Subchannel that hides details of the
954
- // channel's implementation (such as the health check service name) from
955
- // the LB policy API.
956
- //
957
- // Note that no synchronization is needed here, because even if the
958
- // underlying subchannel is shared between channels, this wrapper will only
959
- // be used within one channel, so it will always be synchronized by the
960
- // control plane combiner.
961
- class ChannelData::GrpcSubchannel : public SubchannelInterface {
962
- public:
963
- GrpcSubchannel(ChannelData* chand, Subchannel* subchannel,
964
- UniquePtr<char> health_check_service_name)
965
- : chand_(chand),
966
- subchannel_(subchannel),
967
- health_check_service_name_(std::move(health_check_service_name)) {
968
- GRPC_CHANNEL_STACK_REF(chand_->owning_stack_, "GrpcSubchannel");
969
- auto* subchannel_node = subchannel_->channelz_node();
970
- if (subchannel_node != nullptr) {
971
- intptr_t subchannel_uuid = subchannel_node->uuid();
972
- auto it = chand_->subchannel_refcount_map_.find(subchannel_);
973
- if (it == chand_->subchannel_refcount_map_.end()) {
974
- chand_->channelz_node_->AddChildSubchannel(subchannel_uuid);
975
- it = chand_->subchannel_refcount_map_.emplace(subchannel_, 0).first;
976
- }
977
- ++it->second;
978
- }
979
- }
980
-
981
- ~GrpcSubchannel() {
982
- auto* subchannel_node = subchannel_->channelz_node();
983
- if (subchannel_node != nullptr) {
984
- intptr_t subchannel_uuid = subchannel_node->uuid();
985
- auto it = chand_->subchannel_refcount_map_.find(subchannel_);
986
- GPR_ASSERT(it != chand_->subchannel_refcount_map_.end());
987
- --it->second;
988
- if (it->second == 0) {
989
- chand_->channelz_node_->RemoveChildSubchannel(subchannel_uuid);
990
- chand_->subchannel_refcount_map_.erase(it);
991
- }
992
- }
993
- GRPC_SUBCHANNEL_UNREF(subchannel_, "unref from LB");
994
- GRPC_CHANNEL_STACK_UNREF(chand_->owning_stack_, "GrpcSubchannel");
995
- }
996
-
997
- grpc_connectivity_state CheckConnectivityState(
998
- RefCountedPtr<ConnectedSubchannelInterface>* connected_subchannel)
999
- override {
1000
- RefCountedPtr<ConnectedSubchannel> tmp;
1001
- auto retval = subchannel_->CheckConnectivityState(
1002
- health_check_service_name_.get(), &tmp);
1003
- *connected_subchannel = std::move(tmp);
1004
- return retval;
1005
- }
1006
-
1007
- void WatchConnectivityState(
1008
- grpc_connectivity_state initial_state,
1009
- UniquePtr<ConnectivityStateWatcher> watcher) override {
1010
- subchannel_->WatchConnectivityState(
1011
- initial_state,
1012
- UniquePtr<char>(gpr_strdup(health_check_service_name_.get())),
1013
- std::move(watcher));
1014
- }
1015
-
1016
- void CancelConnectivityStateWatch(
1017
- ConnectivityStateWatcher* watcher) override {
1018
- subchannel_->CancelConnectivityStateWatch(health_check_service_name_.get(),
1019
- watcher);
1020
- }
1021
-
1022
- void AttemptToConnect() override { subchannel_->AttemptToConnect(); }
1023
-
1024
- void ResetBackoff() override { subchannel_->ResetBackoff(); }
1025
-
1026
- private:
1027
- ChannelData* chand_;
1028
- Subchannel* subchannel_;
1029
- UniquePtr<char> health_check_service_name_;
1030
- };
1031
-
1032
1280
  //
1033
1281
  // ChannelData::ClientChannelControlHelper
1034
1282
  //
@@ -1066,8 +1314,8 @@ class ChannelData::ClientChannelControlHelper
1066
1314
  chand_->client_channel_factory_->CreateSubchannel(new_args);
1067
1315
  grpc_channel_args_destroy(new_args);
1068
1316
  if (subchannel == nullptr) return nullptr;
1069
- return MakeRefCounted<GrpcSubchannel>(chand_, subchannel,
1070
- std::move(health_check_service_name));
1317
+ return MakeRefCounted<SubchannelWrapper>(
1318
+ chand_, subchannel, std::move(health_check_service_name));
1071
1319
  }
1072
1320
 
1073
1321
  grpc_channel* CreateChannel(const char* target,
@@ -1078,8 +1326,7 @@ class ChannelData::ClientChannelControlHelper
1078
1326
  void UpdateState(
1079
1327
  grpc_connectivity_state state,
1080
1328
  UniquePtr<LoadBalancingPolicy::SubchannelPicker> picker) override {
1081
- grpc_error* disconnect_error =
1082
- chand_->disconnect_error_.Load(MemoryOrder::ACQUIRE);
1329
+ grpc_error* disconnect_error = chand_->disconnect_error();
1083
1330
  if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) {
1084
1331
  const char* extra = disconnect_error == GRPC_ERROR_NONE
1085
1332
  ? ""
@@ -1226,59 +1473,61 @@ ChannelData::ChannelData(grpc_channel_element_args* args, grpc_error** error)
1226
1473
  grpc_channel_args* new_args = nullptr;
1227
1474
  grpc_proxy_mappers_map_name(server_uri, args->channel_args, &proxy_name,
1228
1475
  &new_args);
1229
- UniquePtr<char> target_uri(proxy_name != nullptr ? proxy_name
1230
- : gpr_strdup(server_uri));
1476
+ target_uri_.reset(proxy_name != nullptr ? proxy_name
1477
+ : gpr_strdup(server_uri));
1478
+ channel_args_ = new_args != nullptr
1479
+ ? new_args
1480
+ : grpc_channel_args_copy(args->channel_args);
1481
+ if (!ResolverRegistry::IsValidTarget(target_uri_.get())) {
1482
+ *error =
1483
+ GRPC_ERROR_CREATE_FROM_STATIC_STRING("the target uri is not valid.");
1484
+ return;
1485
+ }
1486
+ *error = GRPC_ERROR_NONE;
1487
+ }
1488
+
1489
+ ChannelData::~ChannelData() {
1490
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) {
1491
+ gpr_log(GPR_INFO, "chand=%p: destroying channel", this);
1492
+ }
1493
+ DestroyResolvingLoadBalancingPolicyLocked();
1494
+ grpc_channel_args_destroy(channel_args_);
1495
+ // Stop backup polling.
1496
+ grpc_client_channel_stop_backup_polling(interested_parties_);
1497
+ grpc_pollset_set_destroy(interested_parties_);
1498
+ GRPC_COMBINER_UNREF(data_plane_combiner_, "client_channel");
1499
+ GRPC_COMBINER_UNREF(combiner_, "client_channel");
1500
+ GRPC_ERROR_UNREF(disconnect_error_.Load(MemoryOrder::RELAXED));
1501
+ grpc_connectivity_state_destroy(&state_tracker_);
1502
+ gpr_mu_destroy(&info_mu_);
1503
+ }
1504
+
1505
+ void ChannelData::CreateResolvingLoadBalancingPolicyLocked() {
1231
1506
  // Instantiate resolving LB policy.
1232
1507
  LoadBalancingPolicy::Args lb_args;
1233
1508
  lb_args.combiner = combiner_;
1234
1509
  lb_args.channel_control_helper =
1235
1510
  UniquePtr<LoadBalancingPolicy::ChannelControlHelper>(
1236
1511
  New<ClientChannelControlHelper>(this));
1237
- lb_args.args = new_args != nullptr ? new_args : args->channel_args;
1512
+ lb_args.args = channel_args_;
1513
+ UniquePtr<char> target_uri(gpr_strdup(target_uri_.get()));
1238
1514
  resolving_lb_policy_.reset(New<ResolvingLoadBalancingPolicy>(
1239
1515
  std::move(lb_args), &grpc_client_channel_routing_trace,
1240
- std::move(target_uri), ProcessResolverResultLocked, this, error));
1241
- grpc_channel_args_destroy(new_args);
1242
- if (*error != GRPC_ERROR_NONE) {
1243
- // Orphan the resolving LB policy and flush the exec_ctx to ensure
1244
- // that it finishes shutting down. This ensures that if we are
1245
- // failing, we destroy the ClientChannelControlHelper (and thus
1246
- // unref the channel stack) before we return.
1247
- // TODO(roth): This is not a complete solution, because it only
1248
- // catches the case where channel stack initialization fails in this
1249
- // particular filter. If there is a failure in a different filter, we
1250
- // will leave a dangling ref here, which can cause a crash. Fortunately,
1251
- // in practice, there are no other filters that can cause failures in
1252
- // channel stack initialization, so this works for now.
1253
- resolving_lb_policy_.reset();
1254
- ExecCtx::Get()->Flush();
1255
- } else {
1256
- grpc_pollset_set_add_pollset_set(resolving_lb_policy_->interested_parties(),
1257
- interested_parties_);
1258
- if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) {
1259
- gpr_log(GPR_INFO, "chand=%p: created resolving_lb_policy=%p", this,
1260
- resolving_lb_policy_.get());
1261
- }
1516
+ std::move(target_uri), ProcessResolverResultLocked, this));
1517
+ grpc_pollset_set_add_pollset_set(resolving_lb_policy_->interested_parties(),
1518
+ interested_parties_);
1519
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) {
1520
+ gpr_log(GPR_INFO, "chand=%p: created resolving_lb_policy=%p", this,
1521
+ resolving_lb_policy_.get());
1262
1522
  }
1263
1523
  }
1264
1524
 
1265
- ChannelData::~ChannelData() {
1266
- if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) {
1267
- gpr_log(GPR_INFO, "chand=%p: destroying channel", this);
1268
- }
1525
+ void ChannelData::DestroyResolvingLoadBalancingPolicyLocked() {
1269
1526
  if (resolving_lb_policy_ != nullptr) {
1270
1527
  grpc_pollset_set_del_pollset_set(resolving_lb_policy_->interested_parties(),
1271
1528
  interested_parties_);
1272
1529
  resolving_lb_policy_.reset();
1273
1530
  }
1274
- // Stop backup polling.
1275
- grpc_client_channel_stop_backup_polling(interested_parties_);
1276
- grpc_pollset_set_destroy(interested_parties_);
1277
- GRPC_COMBINER_UNREF(data_plane_combiner_, "client_channel");
1278
- GRPC_COMBINER_UNREF(combiner_, "client_channel");
1279
- GRPC_ERROR_UNREF(disconnect_error_.Load(MemoryOrder::RELAXED));
1280
- grpc_connectivity_state_destroy(&state_tracker_);
1281
- gpr_mu_destroy(&info_mu_);
1282
1531
  }
1283
1532
 
1284
1533
  void ChannelData::ProcessLbPolicy(
@@ -1451,9 +1700,13 @@ grpc_error* ChannelData::DoPingLocked(grpc_transport_op* op) {
1451
1700
  }
1452
1701
  LoadBalancingPolicy::PickResult result =
1453
1702
  picker_->Pick(LoadBalancingPolicy::PickArgs());
1454
- if (result.connected_subchannel != nullptr) {
1455
- ConnectedSubchannel* connected_subchannel =
1456
- static_cast<ConnectedSubchannel*>(result.connected_subchannel.get());
1703
+ ConnectedSubchannel* connected_subchannel = nullptr;
1704
+ if (result.subchannel != nullptr) {
1705
+ SubchannelWrapper* subchannel =
1706
+ static_cast<SubchannelWrapper*>(result.subchannel.get());
1707
+ connected_subchannel = subchannel->connected_subchannel();
1708
+ }
1709
+ if (connected_subchannel != nullptr) {
1457
1710
  connected_subchannel->Ping(op->send_ping.on_initiate, op->send_ping.on_ack);
1458
1711
  } else {
1459
1712
  if (result.error == GRPC_ERROR_NONE) {
@@ -1494,22 +1747,35 @@ void ChannelData::StartTransportOpLocked(void* arg, grpc_error* ignored) {
1494
1747
  chand->resolving_lb_policy_->ResetBackoffLocked();
1495
1748
  }
1496
1749
  }
1497
- // Disconnect.
1750
+ // Disconnect or enter IDLE.
1498
1751
  if (op->disconnect_with_error != GRPC_ERROR_NONE) {
1499
- grpc_error* error = GRPC_ERROR_NONE;
1500
- GPR_ASSERT(chand->disconnect_error_.CompareExchangeStrong(
1501
- &error, op->disconnect_with_error, MemoryOrder::ACQ_REL,
1502
- MemoryOrder::ACQUIRE));
1503
- grpc_pollset_set_del_pollset_set(
1504
- chand->resolving_lb_policy_->interested_parties(),
1505
- chand->interested_parties_);
1506
- chand->resolving_lb_policy_.reset();
1507
- // Will delete itself.
1508
- New<ConnectivityStateAndPickerSetter>(
1509
- chand, GRPC_CHANNEL_SHUTDOWN, "shutdown from API",
1510
- UniquePtr<LoadBalancingPolicy::SubchannelPicker>(
1511
- New<LoadBalancingPolicy::TransientFailurePicker>(
1512
- GRPC_ERROR_REF(op->disconnect_with_error))));
1752
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) {
1753
+ gpr_log(GPR_INFO, "chand=%p: disconnect_with_error: %s", chand,
1754
+ grpc_error_string(op->disconnect_with_error));
1755
+ }
1756
+ chand->DestroyResolvingLoadBalancingPolicyLocked();
1757
+ intptr_t value;
1758
+ if (grpc_error_get_int(op->disconnect_with_error,
1759
+ GRPC_ERROR_INT_CHANNEL_CONNECTIVITY_STATE, &value) &&
1760
+ static_cast<grpc_connectivity_state>(value) == GRPC_CHANNEL_IDLE) {
1761
+ if (chand->disconnect_error() == GRPC_ERROR_NONE) {
1762
+ // Enter IDLE state.
1763
+ New<ConnectivityStateAndPickerSetter>(chand, GRPC_CHANNEL_IDLE,
1764
+ "channel entering IDLE", nullptr);
1765
+ }
1766
+ GRPC_ERROR_UNREF(op->disconnect_with_error);
1767
+ } else {
1768
+ // Disconnect.
1769
+ GPR_ASSERT(chand->disconnect_error_.Load(MemoryOrder::RELAXED) ==
1770
+ GRPC_ERROR_NONE);
1771
+ chand->disconnect_error_.Store(op->disconnect_with_error,
1772
+ MemoryOrder::RELEASE);
1773
+ New<ConnectivityStateAndPickerSetter>(
1774
+ chand, GRPC_CHANNEL_SHUTDOWN, "shutdown from API",
1775
+ UniquePtr<LoadBalancingPolicy::SubchannelPicker>(
1776
+ New<LoadBalancingPolicy::TransientFailurePicker>(
1777
+ GRPC_ERROR_REF(op->disconnect_with_error))));
1778
+ }
1513
1779
  }
1514
1780
  GRPC_CHANNEL_STACK_UNREF(chand->owning_stack_, "start_transport_op");
1515
1781
  GRPC_CLOSURE_SCHED(op->on_consumed, GRPC_ERROR_NONE);
@@ -1570,10 +1836,23 @@ void ChannelData::RemoveQueuedPick(QueuedPick* to_remove,
1570
1836
  }
1571
1837
  }
1572
1838
 
1839
+ RefCountedPtr<ConnectedSubchannel>
1840
+ ChannelData::GetConnectedSubchannelInDataPlane(
1841
+ SubchannelInterface* subchannel) const {
1842
+ SubchannelWrapper* subchannel_wrapper =
1843
+ static_cast<SubchannelWrapper*>(subchannel);
1844
+ ConnectedSubchannel* connected_subchannel =
1845
+ subchannel_wrapper->connected_subchannel_in_data_plane();
1846
+ if (connected_subchannel == nullptr) return nullptr;
1847
+ return connected_subchannel->Ref();
1848
+ }
1849
+
1573
1850
  void ChannelData::TryToConnectLocked(void* arg, grpc_error* error_ignored) {
1574
1851
  auto* chand = static_cast<ChannelData*>(arg);
1575
1852
  if (chand->resolving_lb_policy_ != nullptr) {
1576
1853
  chand->resolving_lb_policy_->ExitIdleLocked();
1854
+ } else {
1855
+ chand->CreateResolvingLoadBalancingPolicyLocked();
1577
1856
  }
1578
1857
  GRPC_CHANNEL_STACK_UNREF(chand->owning_stack_, "TryToConnect");
1579
1858
  }
@@ -1879,9 +2158,10 @@ void CallData::RecvTrailingMetadataReadyForLoadBalancingPolicy(
1879
2158
  void* arg, grpc_error* error) {
1880
2159
  CallData* calld = static_cast<CallData*>(arg);
1881
2160
  // Invoke callback to LB policy.
2161
+ Metadata trailing_metadata(calld, calld->recv_trailing_metadata_);
1882
2162
  calld->lb_recv_trailing_metadata_ready_(
1883
- calld->lb_recv_trailing_metadata_ready_user_data_,
1884
- calld->recv_trailing_metadata_, &calld->lb_call_state_);
2163
+ calld->lb_recv_trailing_metadata_ready_user_data_, &trailing_metadata,
2164
+ &calld->lb_call_state_);
1885
2165
  // Chain to original callback.
1886
2166
  GRPC_CLOSURE_RUN(calld->original_recv_trailing_metadata_ready_,
1887
2167
  GRPC_ERROR_REF(error));
@@ -2157,9 +2437,8 @@ void CallData::DoRetry(grpc_call_element* elem,
2157
2437
  GPR_ASSERT(method_params_ != nullptr);
2158
2438
  const auto* retry_policy = method_params_->retry_policy();
2159
2439
  GPR_ASSERT(retry_policy != nullptr);
2160
- // Reset subchannel call and connected subchannel.
2440
+ // Reset subchannel call.
2161
2441
  subchannel_call_.reset();
2162
- connected_subchannel_.reset();
2163
2442
  // Compute backoff delay.
2164
2443
  grpc_millis next_attempt_time;
2165
2444
  if (server_pushback_ms >= 0) {
@@ -3277,13 +3556,14 @@ void CallData::CreateSubchannelCall(grpc_call_element* elem) {
3277
3556
  ChannelData* chand = static_cast<ChannelData*>(elem->channel_data);
3278
3557
  const size_t parent_data_size =
3279
3558
  enable_retries_ ? sizeof(SubchannelCallRetryState) : 0;
3280
- const ConnectedSubchannel::CallArgs call_args = {
3281
- pollent_, path_, call_start_time_, deadline_, arena_,
3559
+ SubchannelCall::Args call_args = {
3560
+ std::move(connected_subchannel_), pollent_, path_, call_start_time_,
3561
+ deadline_, arena_,
3282
3562
  // TODO(roth): When we implement hedging support, we will probably
3283
3563
  // need to use a separate call context for each subchannel call.
3284
3564
  call_context_, call_combiner_, parent_data_size};
3285
3565
  grpc_error* error = GRPC_ERROR_NONE;
3286
- subchannel_call_ = connected_subchannel_->CreateCall(call_args, &error);
3566
+ subchannel_call_ = SubchannelCall::Create(std::move(call_args), &error);
3287
3567
  if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) {
3288
3568
  gpr_log(GPR_INFO, "chand=%p calld=%p: create subchannel_call=%p: error=%s",
3289
3569
  chand, this, subchannel_call_.get(), grpc_error_string(error));
@@ -3463,6 +3743,15 @@ void CallData::StartPickLocked(void* arg, grpc_error* error) {
3463
3743
  ChannelData* chand = static_cast<ChannelData*>(elem->channel_data);
3464
3744
  GPR_ASSERT(calld->connected_subchannel_ == nullptr);
3465
3745
  GPR_ASSERT(calld->subchannel_call_ == nullptr);
3746
+ // picker's being null means the channel is currently in IDLE state. The
3747
+ // incoming call will make the channel exit IDLE and queue itself.
3748
+ if (chand->picker() == nullptr) {
3749
+ // We are currently in the data plane.
3750
+ // Bounce into the control plane to exit IDLE.
3751
+ chand->CheckConnectivityState(true);
3752
+ calld->AddCallToQueuedPicksLocked(elem);
3753
+ return;
3754
+ }
3466
3755
  // Apply service config to call if needed.
3467
3756
  calld->MaybeApplyServiceConfigToCallLocked(elem);
3468
3757
  // If this is a retry, use the send_initial_metadata payload that
@@ -3477,11 +3766,13 @@ void CallData::StartPickLocked(void* arg, grpc_error* error) {
3477
3766
  // attempt) to the LB policy instead the one from the parent channel.
3478
3767
  LoadBalancingPolicy::PickArgs pick_args;
3479
3768
  pick_args.call_state = &calld->lb_call_state_;
3480
- pick_args.initial_metadata =
3769
+ Metadata initial_metadata(
3770
+ calld,
3481
3771
  calld->seen_send_initial_metadata_
3482
3772
  ? &calld->send_initial_metadata_
3483
3773
  : calld->pending_batches_[0]
3484
- .batch->payload->send_initial_metadata.send_initial_metadata;
3774
+ .batch->payload->send_initial_metadata.send_initial_metadata);
3775
+ pick_args.initial_metadata = &initial_metadata;
3485
3776
  // Grab initial metadata flags so that we can check later if the call has
3486
3777
  // wait_for_ready enabled.
3487
3778
  const uint32_t send_initial_metadata_flags =
@@ -3497,10 +3788,9 @@ void CallData::StartPickLocked(void* arg, grpc_error* error) {
3497
3788
  auto result = chand->picker()->Pick(pick_args);
3498
3789
  if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) {
3499
3790
  gpr_log(GPR_INFO,
3500
- "chand=%p calld=%p: LB pick returned %s (connected_subchannel=%p, "
3501
- "error=%s)",
3791
+ "chand=%p calld=%p: LB pick returned %s (subchannel=%p, error=%s)",
3502
3792
  chand, calld, PickResultTypeName(result.type),
3503
- result.connected_subchannel.get(), grpc_error_string(result.error));
3793
+ result.subchannel.get(), grpc_error_string(result.error));
3504
3794
  }
3505
3795
  switch (result.type) {
3506
3796
  case LoadBalancingPolicy::PickResult::PICK_TRANSIENT_FAILURE: {
@@ -3542,11 +3832,16 @@ void CallData::StartPickLocked(void* arg, grpc_error* error) {
3542
3832
  break;
3543
3833
  default: // PICK_COMPLETE
3544
3834
  // Handle drops.
3545
- if (GPR_UNLIKELY(result.connected_subchannel == nullptr)) {
3835
+ if (GPR_UNLIKELY(result.subchannel == nullptr)) {
3546
3836
  result.error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
3547
3837
  "Call dropped by load balancing policy");
3838
+ } else {
3839
+ // Grab a ref to the connected subchannel while we're still
3840
+ // holding the data plane combiner.
3841
+ calld->connected_subchannel_ =
3842
+ chand->GetConnectedSubchannelInDataPlane(result.subchannel.get());
3843
+ GPR_ASSERT(calld->connected_subchannel_ != nullptr);
3548
3844
  }
3549
- calld->connected_subchannel_ = std::move(result.connected_subchannel);
3550
3845
  calld->lb_recv_trailing_metadata_ready_ =
3551
3846
  result.recv_trailing_metadata_ready;
3552
3847
  calld->lb_recv_trailing_metadata_ready_user_data_ =