grpc 1.21.0 → 1.22.0

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

Potentially problematic release.


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

Files changed (141) hide show
  1. checksums.yaml +4 -4
  2. data/Makefile +422 -62
  3. data/include/grpc/grpc_security.h +61 -5
  4. data/include/grpc/grpc_security_constants.h +1 -1
  5. data/include/grpc/impl/codegen/gpr_types.h +1 -1
  6. data/include/grpc/slice.h +2 -2
  7. data/src/core/ext/filters/client_channel/backup_poller.cc +2 -3
  8. data/src/core/ext/filters/client_channel/backup_poller.h +5 -2
  9. data/src/core/ext/filters/client_channel/client_channel.cc +260 -122
  10. data/src/core/ext/filters/client_channel/client_channel.h +0 -8
  11. data/src/core/ext/filters/client_channel/client_channel_channelz.cc +3 -84
  12. data/src/core/ext/filters/client_channel/client_channel_channelz.h +2 -28
  13. data/src/core/ext/filters/client_channel/client_channel_plugin.cc +2 -8
  14. data/src/core/ext/filters/client_channel/health/health_check_client.cc +5 -4
  15. data/src/core/ext/filters/client_channel/lb_policy.cc +16 -2
  16. data/src/core/ext/filters/client_channel/lb_policy.h +92 -98
  17. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc +63 -87
  18. data/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc +6 -2
  19. data/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc +35 -87
  20. data/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc +18 -74
  21. data/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h +167 -217
  22. data/src/core/ext/filters/client_channel/lb_policy/xds/xds.cc +216 -190
  23. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_load_balancer_api.cc +6 -2
  24. data/src/core/ext/filters/client_channel/lb_policy_factory.h +1 -1
  25. data/src/core/ext/filters/client_channel/lb_policy_registry.cc +1 -1
  26. data/src/core/ext/filters/client_channel/lb_policy_registry.h +1 -1
  27. data/src/core/ext/filters/client_channel/resolver.h +1 -1
  28. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc +6 -3
  29. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc +0 -1
  30. data/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc +2 -0
  31. data/src/core/ext/filters/client_channel/resolver_result_parsing.cc +8 -8
  32. data/src/core/ext/filters/client_channel/resolver_result_parsing.h +7 -7
  33. data/src/core/ext/filters/client_channel/resolving_lb_policy.cc +28 -64
  34. data/src/core/ext/filters/client_channel/resolving_lb_policy.h +4 -12
  35. data/src/core/ext/filters/client_channel/server_address.cc +4 -6
  36. data/src/core/ext/filters/client_channel/server_address.h +1 -3
  37. data/src/core/ext/filters/client_channel/service_config.cc +20 -22
  38. data/src/core/ext/filters/client_channel/service_config.h +26 -28
  39. data/src/core/ext/filters/client_channel/subchannel.cc +261 -160
  40. data/src/core/ext/filters/client_channel/subchannel.h +97 -23
  41. data/src/core/ext/filters/client_channel/subchannel_interface.h +113 -0
  42. data/src/core/ext/filters/message_size/message_size_filter.cc +12 -12
  43. data/src/core/ext/filters/message_size/message_size_filter.h +2 -2
  44. data/src/core/ext/transport/chttp2/server/chttp2_server.cc +50 -2
  45. data/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +2 -2
  46. data/src/core/ext/transport/chttp2/transport/frame_data.cc +31 -36
  47. data/src/core/ext/transport/chttp2/transport/frame_rst_stream.cc +3 -2
  48. data/src/core/ext/transport/chttp2/transport/hpack_encoder.cc +71 -52
  49. data/src/core/ext/transport/chttp2/transport/hpack_parser.cc +18 -3
  50. data/src/core/ext/transport/chttp2/transport/hpack_table.cc +5 -12
  51. data/src/core/ext/transport/chttp2/transport/hpack_table.h +10 -1
  52. data/src/core/ext/transport/chttp2/transport/internal.h +3 -3
  53. data/src/core/ext/transport/chttp2/transport/parsing.cc +39 -57
  54. data/src/core/lib/channel/channelz.cc +136 -19
  55. data/src/core/lib/channel/channelz.h +36 -40
  56. data/src/core/lib/channel/channelz_registry.cc +74 -106
  57. data/src/core/lib/channel/channelz_registry.h +10 -28
  58. data/src/core/lib/channel/context.h +1 -1
  59. data/src/core/lib/channel/handshaker.cc +6 -0
  60. data/src/core/lib/compression/compression.cc +13 -8
  61. data/src/core/lib/compression/compression_internal.cc +14 -10
  62. data/src/core/lib/compression/compression_internal.h +1 -1
  63. data/src/core/lib/compression/stream_compression.cc +3 -2
  64. data/src/core/lib/compression/stream_compression.h +2 -2
  65. data/src/core/lib/compression/stream_compression_gzip.cc +9 -9
  66. data/src/core/lib/gpr/env.h +1 -1
  67. data/src/core/lib/gpr/string.cc +8 -1
  68. data/src/core/lib/gpr/string.h +6 -1
  69. data/src/core/lib/gprpp/fork.cc +1 -1
  70. data/src/core/lib/gprpp/fork.h +5 -1
  71. data/src/core/lib/gprpp/global_config.h +9 -0
  72. data/src/core/lib/gprpp/global_config_custom.h +1 -1
  73. data/src/core/lib/gprpp/inlined_vector.h +8 -0
  74. data/src/core/lib/gprpp/map.h +38 -21
  75. data/src/core/lib/gprpp/memory.h +2 -2
  76. data/src/core/lib/gprpp/orphanable.h +1 -1
  77. data/src/core/lib/gprpp/ref_counted.h +9 -4
  78. data/src/core/lib/http/httpcli.cc +3 -3
  79. data/src/core/lib/iomgr/buffer_list.h +1 -1
  80. data/src/core/lib/iomgr/call_combiner.cc +1 -1
  81. data/src/core/lib/iomgr/call_combiner.h +1 -1
  82. data/src/core/lib/iomgr/cfstream_handle.cc +3 -2
  83. data/src/core/lib/iomgr/cfstream_handle.h +4 -0
  84. data/src/core/lib/iomgr/error.cc +3 -3
  85. data/src/core/lib/iomgr/error.h +9 -3
  86. data/src/core/lib/iomgr/error_internal.h +1 -1
  87. data/src/core/lib/iomgr/ev_epoll1_linux.cc +1 -1
  88. data/src/core/lib/iomgr/ev_posix.cc +3 -3
  89. data/src/core/lib/iomgr/ev_posix.h +3 -2
  90. data/src/core/lib/iomgr/ev_windows.cc +2 -2
  91. data/src/core/lib/iomgr/iomgr.cc +4 -4
  92. data/src/core/lib/iomgr/lockfree_event.cc +1 -1
  93. data/src/core/lib/iomgr/port.h +5 -1
  94. data/src/core/lib/iomgr/tcp_posix.cc +1 -3
  95. data/src/core/lib/iomgr/tcp_server.cc +5 -0
  96. data/src/core/lib/iomgr/tcp_server.h +24 -0
  97. data/src/core/lib/iomgr/tcp_server_custom.cc +11 -9
  98. data/src/core/lib/iomgr/tcp_server_posix.cc +72 -11
  99. data/src/core/lib/iomgr/tcp_server_utils_posix.h +3 -0
  100. data/src/core/lib/iomgr/tcp_server_windows.cc +11 -9
  101. data/src/core/lib/iomgr/tcp_uv.cc +5 -6
  102. data/src/core/lib/iomgr/timer.h +2 -1
  103. data/src/core/lib/iomgr/udp_server.cc +2 -2
  104. data/src/core/lib/security/credentials/plugin/plugin_credentials.cc +1 -1
  105. data/src/core/lib/security/credentials/ssl/ssl_credentials.cc +20 -2
  106. data/src/core/lib/security/credentials/ssl/ssl_credentials.h +2 -2
  107. data/src/core/lib/security/security_connector/security_connector.h +1 -1
  108. data/src/core/lib/security/security_connector/ssl/ssl_security_connector.cc +1 -1
  109. data/src/core/lib/security/transport/auth_filters.h +3 -0
  110. data/src/core/lib/security/transport/client_auth_filter.cc +13 -0
  111. data/src/core/lib/security/transport/security_handshaker.cc +7 -7
  112. data/src/core/lib/slice/b64.h +2 -2
  113. data/src/core/lib/slice/slice.cc +82 -10
  114. data/src/core/lib/slice/slice_buffer.cc +49 -21
  115. data/src/core/lib/slice/slice_hash_table.h +2 -2
  116. data/src/core/lib/slice/slice_intern.cc +15 -16
  117. data/src/core/lib/slice/slice_internal.h +52 -0
  118. data/src/core/lib/slice/slice_string_helpers.cc +10 -1
  119. data/src/core/lib/slice/slice_string_helpers.h +3 -1
  120. data/src/core/lib/slice/slice_utils.h +50 -0
  121. data/src/core/lib/slice/slice_weak_hash_table.h +2 -2
  122. data/src/core/lib/surface/call.cc +14 -8
  123. data/src/core/lib/surface/channel.cc +89 -97
  124. data/src/core/lib/surface/channel.h +60 -6
  125. data/src/core/lib/surface/completion_queue.cc +49 -36
  126. data/src/core/lib/surface/completion_queue.h +2 -1
  127. data/src/core/lib/surface/server.cc +8 -8
  128. data/src/core/lib/surface/validate_metadata.cc +14 -8
  129. data/src/core/lib/surface/validate_metadata.h +13 -2
  130. data/src/core/lib/surface/version.cc +1 -1
  131. data/src/core/lib/transport/metadata.cc +56 -26
  132. data/src/core/lib/transport/metadata.h +91 -75
  133. data/src/core/lib/transport/static_metadata.cc +262 -176
  134. data/src/core/lib/transport/static_metadata.h +272 -180
  135. data/src/core/lib/transport/transport.cc +1 -1
  136. data/src/core/lib/transport/transport.h +8 -2
  137. data/src/core/tsi/alts/handshaker/alts_shared_resource.h +1 -1
  138. data/src/ruby/ext/grpc/rb_grpc_imports.generated.c +2 -0
  139. data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +5 -2
  140. data/src/ruby/lib/grpc/version.rb +1 -1
  141. metadata +33 -31
@@ -63,8 +63,6 @@ class RoundRobin : public LoadBalancingPolicy {
63
63
 
64
64
  void UpdateLocked(UpdateArgs args) override;
65
65
  void ResetBackoffLocked() override;
66
- void FillChildRefsForChannelz(channelz::ChildRefsList* child_subchannels,
67
- channelz::ChildRefsList* ignored) override;
68
66
 
69
67
  private:
70
68
  ~RoundRobin();
@@ -83,9 +81,9 @@ class RoundRobin : public LoadBalancingPolicy {
83
81
  RoundRobinSubchannelData(
84
82
  SubchannelList<RoundRobinSubchannelList, RoundRobinSubchannelData>*
85
83
  subchannel_list,
86
- const ServerAddress& address, Subchannel* subchannel,
87
- grpc_combiner* combiner)
88
- : SubchannelData(subchannel_list, address, subchannel, combiner) {}
84
+ const ServerAddress& address,
85
+ RefCountedPtr<SubchannelInterface> subchannel)
86
+ : SubchannelData(subchannel_list, address, std::move(subchannel)) {}
89
87
 
90
88
  grpc_connectivity_state connectivity_state() const {
91
89
  return last_connectivity_state_;
@@ -150,32 +148,18 @@ class RoundRobin : public LoadBalancingPolicy {
150
148
  public:
151
149
  Picker(RoundRobin* parent, RoundRobinSubchannelList* subchannel_list);
152
150
 
153
- PickResult Pick(PickArgs* pick, grpc_error** error) override;
151
+ PickResult Pick(PickArgs args) override;
154
152
 
155
153
  private:
156
154
  // Using pointer value only, no ref held -- do not dereference!
157
155
  RoundRobin* parent_;
158
156
 
159
157
  size_t last_picked_index_;
160
- InlinedVector<RefCountedPtr<ConnectedSubchannel>, 10> subchannels_;
161
- };
162
-
163
- // Helper class to ensure that any function that modifies the child refs
164
- // data structures will update the channelz snapshot data structures before
165
- // returning.
166
- class AutoChildRefsUpdater {
167
- public:
168
- explicit AutoChildRefsUpdater(RoundRobin* rr) : rr_(rr) {}
169
- ~AutoChildRefsUpdater() { rr_->UpdateChildRefsLocked(); }
170
-
171
- private:
172
- RoundRobin* rr_;
158
+ InlinedVector<RefCountedPtr<ConnectedSubchannelInterface>, 10> subchannels_;
173
159
  };
174
160
 
175
161
  void ShutdownLocked() override;
176
162
 
177
- void UpdateChildRefsLocked();
178
-
179
163
  /** list of subchannels */
180
164
  OrphanablePtr<RoundRobinSubchannelList> subchannel_list_;
181
165
  /** Latest version of the subchannel list.
@@ -186,11 +170,6 @@ class RoundRobin : public LoadBalancingPolicy {
186
170
  OrphanablePtr<RoundRobinSubchannelList> latest_pending_subchannel_list_;
187
171
  /** are we shutting down? */
188
172
  bool shutdown_ = false;
189
- /// Lock and data used to capture snapshots of this channel's child
190
- /// channels and subchannels. This data is consumed by channelz.
191
- Mutex child_refs_mu_;
192
- channelz::ChildRefsList child_subchannels_;
193
- channelz::ChildRefsList child_channels_;
194
173
  };
195
174
 
196
175
  //
@@ -221,8 +200,7 @@ RoundRobin::Picker::Picker(RoundRobin* parent,
221
200
  }
222
201
  }
223
202
 
224
- RoundRobin::PickResult RoundRobin::Picker::Pick(PickArgs* pick,
225
- grpc_error** error) {
203
+ RoundRobin::PickResult RoundRobin::Picker::Pick(PickArgs args) {
226
204
  last_picked_index_ = (last_picked_index_ + 1) % subchannels_.size();
227
205
  if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_round_robin_trace)) {
228
206
  gpr_log(GPR_INFO,
@@ -231,8 +209,10 @@ RoundRobin::PickResult RoundRobin::Picker::Pick(PickArgs* pick,
231
209
  parent_, this, last_picked_index_,
232
210
  subchannels_[last_picked_index_].get());
233
211
  }
234
- pick->connected_subchannel = subchannels_[last_picked_index_];
235
- return PICK_COMPLETE;
212
+ PickResult result;
213
+ result.type = PickResult::PICK_COMPLETE;
214
+ result.connected_subchannel = subchannels_[last_picked_index_];
215
+ return result;
236
216
  }
237
217
 
238
218
  //
@@ -254,7 +234,6 @@ RoundRobin::~RoundRobin() {
254
234
  }
255
235
 
256
236
  void RoundRobin::ShutdownLocked() {
257
- AutoChildRefsUpdater guard(this);
258
237
  if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_round_robin_trace)) {
259
238
  gpr_log(GPR_INFO, "[RR %p] Shutting down", this);
260
239
  }
@@ -270,40 +249,6 @@ void RoundRobin::ResetBackoffLocked() {
270
249
  }
271
250
  }
272
251
 
273
- void RoundRobin::FillChildRefsForChannelz(
274
- channelz::ChildRefsList* child_subchannels_to_fill,
275
- channelz::ChildRefsList* ignored) {
276
- MutexLock lock(&child_refs_mu_);
277
- for (size_t i = 0; i < child_subchannels_.size(); ++i) {
278
- // TODO(ncteisen): implement a de dup loop that is not O(n^2). Might
279
- // have to implement lightweight set. For now, we don't care about
280
- // performance when channelz requests are made.
281
- bool found = false;
282
- for (size_t j = 0; j < child_subchannels_to_fill->size(); ++j) {
283
- if ((*child_subchannels_to_fill)[j] == child_subchannels_[i]) {
284
- found = true;
285
- break;
286
- }
287
- }
288
- if (!found) {
289
- child_subchannels_to_fill->push_back(child_subchannels_[i]);
290
- }
291
- }
292
- }
293
-
294
- void RoundRobin::UpdateChildRefsLocked() {
295
- channelz::ChildRefsList cs;
296
- if (subchannel_list_ != nullptr) {
297
- subchannel_list_->PopulateChildRefsList(&cs);
298
- }
299
- if (latest_pending_subchannel_list_ != nullptr) {
300
- latest_pending_subchannel_list_->PopulateChildRefsList(&cs);
301
- }
302
- // atomically update the data that channelz will actually be looking at.
303
- MutexLock lock(&child_refs_mu_);
304
- child_subchannels_ = std::move(cs);
305
- }
306
-
307
252
  void RoundRobin::RoundRobinSubchannelList::StartWatchingLocked() {
308
253
  if (num_subchannels() == 0) return;
309
254
  // Check current state of each subchannel synchronously, since any
@@ -320,6 +265,7 @@ void RoundRobin::RoundRobinSubchannelList::StartWatchingLocked() {
320
265
  for (size_t i = 0; i < num_subchannels(); i++) {
321
266
  if (subchannel(i)->subchannel() != nullptr) {
322
267
  subchannel(i)->StartConnectivityWatchLocked();
268
+ subchannel(i)->subchannel()->AttemptToConnect();
323
269
  }
324
270
  }
325
271
  // Now set the LB policy's state based on the subchannels' states.
@@ -377,8 +323,8 @@ void RoundRobin::RoundRobinSubchannelList::
377
323
  } else if (num_connecting_ > 0) {
378
324
  /* 2) CONNECTING */
379
325
  p->channel_control_helper()->UpdateState(
380
- GRPC_CHANNEL_CONNECTING,
381
- UniquePtr<SubchannelPicker>(New<QueuePicker>(p->Ref())));
326
+ GRPC_CHANNEL_CONNECTING, UniquePtr<SubchannelPicker>(New<QueuePicker>(
327
+ p->Ref(DEBUG_LOCATION, "QueuePicker"))));
382
328
  } else if (num_transient_failure_ == num_subchannels()) {
383
329
  /* 3) TRANSIENT_FAILURE */
384
330
  grpc_error* error =
@@ -394,7 +340,6 @@ void RoundRobin::RoundRobinSubchannelList::
394
340
  void RoundRobin::RoundRobinSubchannelList::
395
341
  UpdateRoundRobinStateFromSubchannelStateCountsLocked() {
396
342
  RoundRobin* p = static_cast<RoundRobin*>(policy());
397
- AutoChildRefsUpdater guard(p);
398
343
  if (num_ready_ > 0) {
399
344
  if (p->subchannel_list_.get() != this) {
400
345
  // Promote this list to p->subchannel_list_.
@@ -448,6 +393,7 @@ void RoundRobin::RoundRobinSubchannelData::ProcessConnectivityChangeLocked(
448
393
  // Otherwise, if the subchannel was already in state TRANSIENT_FAILURE
449
394
  // when the subchannel list was created, we'd wind up in a constant
450
395
  // loop of re-resolution.
396
+ // Also attempt to reconnect.
451
397
  if (connectivity_state == GRPC_CHANNEL_TRANSIENT_FAILURE) {
452
398
  if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_round_robin_trace)) {
453
399
  gpr_log(GPR_INFO,
@@ -456,9 +402,8 @@ void RoundRobin::RoundRobinSubchannelData::ProcessConnectivityChangeLocked(
456
402
  p, subchannel());
457
403
  }
458
404
  p->channel_control_helper()->RequestReresolution();
405
+ subchannel()->AttemptToConnect();
459
406
  }
460
- // Renew connectivity watch.
461
- RenewConnectivityWatchLocked();
462
407
  // Update state counters.
463
408
  UpdateConnectivityStateLocked(connectivity_state);
464
409
  // Update overall state and renew notification.
@@ -466,7 +411,6 @@ void RoundRobin::RoundRobinSubchannelData::ProcessConnectivityChangeLocked(
466
411
  }
467
412
 
468
413
  void RoundRobin::UpdateLocked(UpdateArgs args) {
469
- AutoChildRefsUpdater guard(this);
470
414
  if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_round_robin_trace)) {
471
415
  gpr_log(GPR_INFO, "[RR %p] received update with %" PRIuPTR " addresses",
472
416
  this, args.addresses.size());
@@ -503,7 +447,7 @@ void RoundRobin::UpdateLocked(UpdateArgs args) {
503
447
  }
504
448
  }
505
449
 
506
- class ParsedRoundRobinConfig : public ParsedLoadBalancingConfig {
450
+ class ParsedRoundRobinConfig : public LoadBalancingPolicy::Config {
507
451
  public:
508
452
  const char* name() const override { return kRoundRobin; }
509
453
  };
@@ -521,12 +465,12 @@ class RoundRobinFactory : public LoadBalancingPolicyFactory {
521
465
 
522
466
  const char* name() const override { return kRoundRobin; }
523
467
 
524
- RefCountedPtr<ParsedLoadBalancingConfig> ParseLoadBalancingConfig(
468
+ RefCountedPtr<LoadBalancingPolicy::Config> ParseLoadBalancingConfig(
525
469
  const grpc_json* json, grpc_error** error) const override {
526
470
  if (json != nullptr) {
527
471
  GPR_DEBUG_ASSERT(strcmp(json->key, name()) == 0);
528
472
  }
529
- return RefCountedPtr<ParsedLoadBalancingConfig>(
473
+ return RefCountedPtr<LoadBalancingPolicy::Config>(
530
474
  New<ParsedRoundRobinConfig>());
531
475
  }
532
476
  };
@@ -27,7 +27,10 @@
27
27
 
28
28
  #include "src/core/ext/filters/client_channel/lb_policy_registry.h"
29
29
  #include "src/core/ext/filters/client_channel/server_address.h"
30
+ // TODO(roth): Should not need the include of subchannel.h here, since
31
+ // that implementation should be hidden from the LB policy API.
30
32
  #include "src/core/ext/filters/client_channel/subchannel.h"
33
+ #include "src/core/ext/filters/client_channel/subchannel_interface.h"
31
34
  #include "src/core/lib/channel/channel_args.h"
32
35
  #include "src/core/lib/debug/trace.h"
33
36
  #include "src/core/lib/gprpp/abstract.h"
@@ -88,25 +91,23 @@ class SubchannelData {
88
91
  }
89
92
 
90
93
  // Returns a pointer to the subchannel.
91
- Subchannel* subchannel() const { return subchannel_; }
94
+ SubchannelInterface* subchannel() const { return subchannel_.get(); }
92
95
 
93
96
  // Returns the connected subchannel. Will be null if the subchannel
94
97
  // is not connected.
95
- ConnectedSubchannel* connected_subchannel() const {
98
+ ConnectedSubchannelInterface* connected_subchannel() const {
96
99
  return connected_subchannel_.get();
97
100
  }
98
101
 
99
102
  // Synchronously checks the subchannel's connectivity state.
100
103
  // Must not be called while there is a connectivity notification
101
- // pending (i.e., between calling StartConnectivityWatchLocked() or
102
- // RenewConnectivityWatchLocked() and the resulting invocation of
103
- // ProcessConnectivityChangeLocked()).
104
+ // pending (i.e., between calling StartConnectivityWatchLocked() and
105
+ // calling CancelConnectivityWatchLocked()).
104
106
  grpc_connectivity_state CheckConnectivityStateLocked() {
105
- GPR_ASSERT(!connectivity_notification_pending_);
106
- pending_connectivity_state_unsafe_ = subchannel()->CheckConnectivity(
107
- subchannel_list_->inhibit_health_checking());
108
- UpdateConnectedSubchannelLocked();
109
- return pending_connectivity_state_unsafe_;
107
+ GPR_ASSERT(pending_watcher_ == nullptr);
108
+ connectivity_state_ =
109
+ subchannel()->CheckConnectivityState(&connected_subchannel_);
110
+ return connectivity_state_;
110
111
  }
111
112
 
112
113
  // Resets the connection backoff.
@@ -115,23 +116,11 @@ class SubchannelData {
115
116
  void ResetBackoffLocked();
116
117
 
117
118
  // Starts watching the connectivity state of the subchannel.
118
- // ProcessConnectivityChangeLocked() will be called when the
119
+ // ProcessConnectivityChangeLocked() will be called whenever the
119
120
  // connectivity state changes.
120
121
  void StartConnectivityWatchLocked();
121
122
 
122
- // Renews watching the connectivity state of the subchannel.
123
- void RenewConnectivityWatchLocked();
124
-
125
- // Stops watching the connectivity state of the subchannel.
126
- void StopConnectivityWatchLocked();
127
-
128
123
  // Cancels watching the connectivity state of the subchannel.
129
- // Must be called only while there is a connectivity notification
130
- // pending (i.e., between calling StartConnectivityWatchLocked() or
131
- // RenewConnectivityWatchLocked() and the resulting invocation of
132
- // ProcessConnectivityChangeLocked()).
133
- // From within ProcessConnectivityChangeLocked(), use
134
- // StopConnectivityWatchLocked() instead.
135
124
  void CancelConnectivityWatchLocked(const char* reason);
136
125
 
137
126
  // Cancels any pending connectivity watch and unrefs the subchannel.
@@ -142,44 +131,81 @@ class SubchannelData {
142
131
  protected:
143
132
  SubchannelData(
144
133
  SubchannelList<SubchannelListType, SubchannelDataType>* subchannel_list,
145
- const ServerAddress& address, Subchannel* subchannel,
146
- grpc_combiner* combiner);
134
+ const ServerAddress& address,
135
+ RefCountedPtr<SubchannelInterface> subchannel);
147
136
 
148
137
  virtual ~SubchannelData();
149
138
 
150
- // After StartConnectivityWatchLocked() or RenewConnectivityWatchLocked()
151
- // is called, this method will be invoked when the subchannel's connectivity
152
- // state changes.
153
- // Implementations must invoke either RenewConnectivityWatchLocked() or
154
- // StopConnectivityWatchLocked() before returning.
139
+ // After StartConnectivityWatchLocked() is called, this method will be
140
+ // invoked whenever the subchannel's connectivity state changes.
141
+ // To stop watching, use CancelConnectivityWatchLocked().
155
142
  virtual void ProcessConnectivityChangeLocked(
156
143
  grpc_connectivity_state connectivity_state) GRPC_ABSTRACT;
157
144
 
158
- // Unrefs the subchannel.
159
- void UnrefSubchannelLocked(const char* reason);
160
-
161
145
  private:
162
- // Updates connected_subchannel_ based on pending_connectivity_state_unsafe_.
163
- // Returns true if the connectivity state should be reported.
164
- bool UpdateConnectedSubchannelLocked();
146
+ // Watcher for subchannel connectivity state.
147
+ class Watcher : public SubchannelInterface::ConnectivityStateWatcher {
148
+ public:
149
+ Watcher(
150
+ SubchannelData<SubchannelListType, SubchannelDataType>* subchannel_data,
151
+ RefCountedPtr<SubchannelListType> subchannel_list)
152
+ : subchannel_data_(subchannel_data),
153
+ subchannel_list_(std::move(subchannel_list)) {}
154
+
155
+ ~Watcher() { subchannel_list_.reset(DEBUG_LOCATION, "Watcher dtor"); }
156
+
157
+ void OnConnectivityStateChange(grpc_connectivity_state new_state,
158
+ RefCountedPtr<ConnectedSubchannelInterface>
159
+ connected_subchannel) override;
160
+
161
+ grpc_pollset_set* interested_parties() override {
162
+ return subchannel_list_->policy()->interested_parties();
163
+ }
164
+
165
+ private:
166
+ // A fire-and-forget class that bounces into the combiner to process
167
+ // a connectivity state update.
168
+ class Updater {
169
+ public:
170
+ Updater(
171
+ SubchannelData<SubchannelListType, SubchannelDataType>*
172
+ subchannel_data,
173
+ RefCountedPtr<SubchannelList<SubchannelListType, SubchannelDataType>>
174
+ subchannel_list,
175
+ grpc_connectivity_state state,
176
+ RefCountedPtr<ConnectedSubchannelInterface> connected_subchannel);
177
+
178
+ ~Updater() {
179
+ subchannel_list_.reset(DEBUG_LOCATION, "Watcher::Updater dtor");
180
+ }
181
+
182
+ private:
183
+ static void OnUpdateLocked(void* arg, grpc_error* error);
184
+
185
+ SubchannelData<SubchannelListType, SubchannelDataType>* subchannel_data_;
186
+ RefCountedPtr<SubchannelList<SubchannelListType, SubchannelDataType>>
187
+ subchannel_list_;
188
+ const grpc_connectivity_state state_;
189
+ RefCountedPtr<ConnectedSubchannelInterface> connected_subchannel_;
190
+ grpc_closure closure_;
191
+ };
165
192
 
166
- static void OnConnectivityChangedLocked(void* arg, grpc_error* error);
193
+ SubchannelData<SubchannelListType, SubchannelDataType>* subchannel_data_;
194
+ RefCountedPtr<SubchannelListType> subchannel_list_;
195
+ };
196
+
197
+ // Unrefs the subchannel.
198
+ void UnrefSubchannelLocked(const char* reason);
167
199
 
168
200
  // Backpointer to owning subchannel list. Not owned.
169
201
  SubchannelList<SubchannelListType, SubchannelDataType>* subchannel_list_;
170
-
171
- // The subchannel and connected subchannel.
172
- Subchannel* subchannel_;
173
- RefCountedPtr<ConnectedSubchannel> connected_subchannel_;
174
-
175
- // Notification that connectivity has changed on subchannel.
176
- grpc_closure connectivity_changed_closure_;
177
- // Is a connectivity notification pending?
178
- bool connectivity_notification_pending_ = false;
179
- // Connectivity state to be updated by
180
- // grpc_subchannel_notify_on_state_change(), not guarded by
181
- // the combiner.
182
- grpc_connectivity_state pending_connectivity_state_unsafe_;
202
+ // The subchannel.
203
+ RefCountedPtr<SubchannelInterface> subchannel_;
204
+ // Will be non-null when the subchannel's state is being watched.
205
+ SubchannelInterface::ConnectivityStateWatcher* pending_watcher_ = nullptr;
206
+ // Data updated by the watcher.
207
+ grpc_connectivity_state connectivity_state_;
208
+ RefCountedPtr<ConnectedSubchannelInterface> connected_subchannel_;
183
209
  };
184
210
 
185
211
  // A list of subchannels.
@@ -197,23 +223,9 @@ class SubchannelList : public InternallyRefCounted<SubchannelListType> {
197
223
  // Returns true if the subchannel list is shutting down.
198
224
  bool shutting_down() const { return shutting_down_; }
199
225
 
200
- // Populates refs_list with the uuids of this SubchannelLists's subchannels.
201
- void PopulateChildRefsList(channelz::ChildRefsList* refs_list) {
202
- for (size_t i = 0; i < subchannels_.size(); ++i) {
203
- if (subchannels_[i].subchannel() != nullptr) {
204
- grpc_core::channelz::SubchannelNode* subchannel_node =
205
- subchannels_[i].subchannel()->channelz_node();
206
- if (subchannel_node != nullptr) {
207
- refs_list->push_back(subchannel_node->uuid());
208
- }
209
- }
210
- }
211
- }
212
-
213
226
  // Accessors.
214
227
  LoadBalancingPolicy* policy() const { return policy_; }
215
228
  TraceFlag* tracer() const { return tracer_; }
216
- bool inhibit_health_checking() const { return inhibit_health_checking_; }
217
229
 
218
230
  // Resets connection backoff of all subchannels.
219
231
  // TODO(roth): We will probably need to rethink this as part of moving
@@ -251,8 +263,6 @@ class SubchannelList : public InternallyRefCounted<SubchannelListType> {
251
263
 
252
264
  TraceFlag* tracer_;
253
265
 
254
- bool inhibit_health_checking_;
255
-
256
266
  grpc_combiner* combiner_;
257
267
 
258
268
  // The list of subchannels.
@@ -268,6 +278,67 @@ class SubchannelList : public InternallyRefCounted<SubchannelListType> {
268
278
  // implementation -- no user-servicable parts below
269
279
  //
270
280
 
281
+ //
282
+ // SubchannelData::Watcher
283
+ //
284
+
285
+ template <typename SubchannelListType, typename SubchannelDataType>
286
+ void SubchannelData<SubchannelListType, SubchannelDataType>::Watcher::
287
+ OnConnectivityStateChange(
288
+ grpc_connectivity_state new_state,
289
+ RefCountedPtr<ConnectedSubchannelInterface> connected_subchannel) {
290
+ // Will delete itself.
291
+ New<Updater>(subchannel_data_,
292
+ subchannel_list_->Ref(DEBUG_LOCATION, "Watcher::Updater"),
293
+ new_state, std::move(connected_subchannel));
294
+ }
295
+
296
+ template <typename SubchannelListType, typename SubchannelDataType>
297
+ SubchannelData<SubchannelListType, SubchannelDataType>::Watcher::Updater::
298
+ Updater(
299
+ SubchannelData<SubchannelListType, SubchannelDataType>* subchannel_data,
300
+ RefCountedPtr<SubchannelList<SubchannelListType, SubchannelDataType>>
301
+ subchannel_list,
302
+ grpc_connectivity_state state,
303
+ RefCountedPtr<ConnectedSubchannelInterface> connected_subchannel)
304
+ : subchannel_data_(subchannel_data),
305
+ subchannel_list_(std::move(subchannel_list)),
306
+ state_(state),
307
+ connected_subchannel_(std::move(connected_subchannel)) {
308
+ GRPC_CLOSURE_INIT(&closure_, &OnUpdateLocked, this,
309
+ grpc_combiner_scheduler(subchannel_list_->combiner_));
310
+ GRPC_CLOSURE_SCHED(&closure_, GRPC_ERROR_NONE);
311
+ }
312
+
313
+ template <typename SubchannelListType, typename SubchannelDataType>
314
+ void SubchannelData<SubchannelListType, SubchannelDataType>::Watcher::Updater::
315
+ OnUpdateLocked(void* arg, grpc_error* error) {
316
+ Updater* self = static_cast<Updater*>(arg);
317
+ SubchannelData* sd = self->subchannel_data_;
318
+ if (GRPC_TRACE_FLAG_ENABLED(*sd->subchannel_list_->tracer())) {
319
+ gpr_log(GPR_INFO,
320
+ "[%s %p] subchannel list %p index %" PRIuPTR " of %" PRIuPTR
321
+ " (subchannel %p): connectivity changed: state=%s, "
322
+ "connected_subchannel=%p, shutting_down=%d, pending_watcher=%p",
323
+ sd->subchannel_list_->tracer()->name(),
324
+ sd->subchannel_list_->policy(), sd->subchannel_list_, sd->Index(),
325
+ sd->subchannel_list_->num_subchannels(), sd->subchannel_.get(),
326
+ grpc_connectivity_state_name(self->state_),
327
+ self->connected_subchannel_.get(),
328
+ sd->subchannel_list_->shutting_down(), sd->pending_watcher_);
329
+ }
330
+ if (!sd->subchannel_list_->shutting_down() &&
331
+ sd->pending_watcher_ != nullptr) {
332
+ sd->connectivity_state_ = self->state_;
333
+ // Get or release ref to connected subchannel.
334
+ sd->connected_subchannel_ = std::move(self->connected_subchannel_);
335
+ // Call the subclass's ProcessConnectivityChangeLocked() method.
336
+ sd->ProcessConnectivityChangeLocked(sd->connectivity_state_);
337
+ }
338
+ // Clean up.
339
+ Delete(self);
340
+ }
341
+
271
342
  //
272
343
  // SubchannelData
273
344
  //
@@ -275,23 +346,16 @@ class SubchannelList : public InternallyRefCounted<SubchannelListType> {
275
346
  template <typename SubchannelListType, typename SubchannelDataType>
276
347
  SubchannelData<SubchannelListType, SubchannelDataType>::SubchannelData(
277
348
  SubchannelList<SubchannelListType, SubchannelDataType>* subchannel_list,
278
- const ServerAddress& address, Subchannel* subchannel,
279
- grpc_combiner* combiner)
349
+ const ServerAddress& address, RefCountedPtr<SubchannelInterface> subchannel)
280
350
  : subchannel_list_(subchannel_list),
281
- subchannel_(subchannel),
351
+ subchannel_(std::move(subchannel)),
282
352
  // We assume that the current state is IDLE. If not, we'll get a
283
353
  // callback telling us that.
284
- pending_connectivity_state_unsafe_(GRPC_CHANNEL_IDLE) {
285
- GRPC_CLOSURE_INIT(
286
- &connectivity_changed_closure_,
287
- (&SubchannelData<SubchannelListType,
288
- SubchannelDataType>::OnConnectivityChangedLocked),
289
- this, grpc_combiner_scheduler(combiner));
290
- }
354
+ connectivity_state_(GRPC_CHANNEL_IDLE) {}
291
355
 
292
356
  template <typename SubchannelListType, typename SubchannelDataType>
293
357
  SubchannelData<SubchannelListType, SubchannelDataType>::~SubchannelData() {
294
- UnrefSubchannelLocked("subchannel_data_destroy");
358
+ GPR_ASSERT(subchannel_ == nullptr);
295
359
  }
296
360
 
297
361
  template <typename SubchannelListType, typename SubchannelDataType>
@@ -304,10 +368,9 @@ void SubchannelData<SubchannelListType, SubchannelDataType>::
304
368
  " (subchannel %p): unreffing subchannel",
305
369
  subchannel_list_->tracer()->name(), subchannel_list_->policy(),
306
370
  subchannel_list_, Index(), subchannel_list_->num_subchannels(),
307
- subchannel_);
371
+ subchannel_.get());
308
372
  }
309
- GRPC_SUBCHANNEL_UNREF(subchannel_, reason);
310
- subchannel_ = nullptr;
373
+ subchannel_.reset();
311
374
  connected_subchannel_.reset();
312
375
  }
313
376
  }
@@ -326,56 +389,19 @@ void SubchannelData<SubchannelListType,
326
389
  if (GRPC_TRACE_FLAG_ENABLED(*subchannel_list_->tracer())) {
327
390
  gpr_log(GPR_INFO,
328
391
  "[%s %p] subchannel list %p index %" PRIuPTR " of %" PRIuPTR
329
- " (subchannel %p): starting watch: requesting connectivity change "
330
- "notification (from %s)",
392
+ " (subchannel %p): starting watch (from %s)",
331
393
  subchannel_list_->tracer()->name(), subchannel_list_->policy(),
332
394
  subchannel_list_, Index(), subchannel_list_->num_subchannels(),
333
- subchannel_,
334
- grpc_connectivity_state_name(pending_connectivity_state_unsafe_));
395
+ subchannel_.get(),
396
+ grpc_connectivity_state_name(connectivity_state_));
335
397
  }
336
- GPR_ASSERT(!connectivity_notification_pending_);
337
- connectivity_notification_pending_ = true;
338
- subchannel_list()->Ref(DEBUG_LOCATION, "connectivity_watch").release();
339
- subchannel_->NotifyOnStateChange(
340
- subchannel_list_->policy()->interested_parties(),
341
- &pending_connectivity_state_unsafe_, &connectivity_changed_closure_,
342
- subchannel_list_->inhibit_health_checking());
343
- }
344
-
345
- template <typename SubchannelListType, typename SubchannelDataType>
346
- void SubchannelData<SubchannelListType,
347
- SubchannelDataType>::RenewConnectivityWatchLocked() {
348
- if (GRPC_TRACE_FLAG_ENABLED(*subchannel_list_->tracer())) {
349
- gpr_log(GPR_INFO,
350
- "[%s %p] subchannel list %p index %" PRIuPTR " of %" PRIuPTR
351
- " (subchannel %p): renewing watch: requesting connectivity change "
352
- "notification (from %s)",
353
- subchannel_list_->tracer()->name(), subchannel_list_->policy(),
354
- subchannel_list_, Index(), subchannel_list_->num_subchannels(),
355
- subchannel_,
356
- grpc_connectivity_state_name(pending_connectivity_state_unsafe_));
357
- }
358
- GPR_ASSERT(connectivity_notification_pending_);
359
- subchannel_->NotifyOnStateChange(
360
- subchannel_list_->policy()->interested_parties(),
361
- &pending_connectivity_state_unsafe_, &connectivity_changed_closure_,
362
- subchannel_list_->inhibit_health_checking());
363
- }
364
-
365
- template <typename SubchannelListType, typename SubchannelDataType>
366
- void SubchannelData<SubchannelListType,
367
- SubchannelDataType>::StopConnectivityWatchLocked() {
368
- if (GRPC_TRACE_FLAG_ENABLED(*subchannel_list_->tracer())) {
369
- gpr_log(GPR_INFO,
370
- "[%s %p] subchannel list %p index %" PRIuPTR " of %" PRIuPTR
371
- " (subchannel %p): stopping connectivity watch",
372
- subchannel_list_->tracer()->name(), subchannel_list_->policy(),
373
- subchannel_list_, Index(), subchannel_list_->num_subchannels(),
374
- subchannel_);
375
- }
376
- GPR_ASSERT(connectivity_notification_pending_);
377
- connectivity_notification_pending_ = false;
378
- subchannel_list()->Unref(DEBUG_LOCATION, "connectivity_watch");
398
+ GPR_ASSERT(pending_watcher_ == nullptr);
399
+ pending_watcher_ =
400
+ New<Watcher>(this, subchannel_list()->Ref(DEBUG_LOCATION, "Watcher"));
401
+ subchannel_->WatchConnectivityState(
402
+ connectivity_state_,
403
+ UniquePtr<SubchannelInterface::ConnectivityStateWatcher>(
404
+ pending_watcher_));
379
405
  }
380
406
 
381
407
  template <typename SubchannelListType, typename SubchannelDataType>
@@ -387,93 +413,18 @@ void SubchannelData<SubchannelListType, SubchannelDataType>::
387
413
  " (subchannel %p): canceling connectivity watch (%s)",
388
414
  subchannel_list_->tracer()->name(), subchannel_list_->policy(),
389
415
  subchannel_list_, Index(), subchannel_list_->num_subchannels(),
390
- subchannel_, reason);
391
- }
392
- GPR_ASSERT(connectivity_notification_pending_);
393
- subchannel_->NotifyOnStateChange(nullptr, nullptr,
394
- &connectivity_changed_closure_,
395
- subchannel_list_->inhibit_health_checking());
396
- }
397
-
398
- template <typename SubchannelListType, typename SubchannelDataType>
399
- bool SubchannelData<SubchannelListType,
400
- SubchannelDataType>::UpdateConnectedSubchannelLocked() {
401
- // If the subchannel is READY, take a ref to the connected subchannel.
402
- if (pending_connectivity_state_unsafe_ == GRPC_CHANNEL_READY) {
403
- connected_subchannel_ = subchannel_->connected_subchannel();
404
- // If the subchannel became disconnected between the time that READY
405
- // was reported and the time we got here (e.g., between when a
406
- // notification callback is scheduled and when it was actually run in
407
- // the combiner), then the connected subchannel may have disappeared out
408
- // from under us. In that case, we don't actually want to consider the
409
- // subchannel to be in state READY. Instead, we use IDLE as the
410
- // basis for any future connectivity watch; this is the one state that
411
- // the subchannel will never transition back into, so this ensures
412
- // that we will get a notification for the next state, even if that state
413
- // is READY again (e.g., if the subchannel has transitioned back to
414
- // READY before the next watch gets requested).
415
- if (connected_subchannel_ == nullptr) {
416
- if (GRPC_TRACE_FLAG_ENABLED(*subchannel_list_->tracer())) {
417
- gpr_log(GPR_INFO,
418
- "[%s %p] subchannel list %p index %" PRIuPTR " of %" PRIuPTR
419
- " (subchannel %p): state is READY but connected subchannel is "
420
- "null; moving to state IDLE",
421
- subchannel_list_->tracer()->name(), subchannel_list_->policy(),
422
- subchannel_list_, Index(), subchannel_list_->num_subchannels(),
423
- subchannel_);
424
- }
425
- pending_connectivity_state_unsafe_ = GRPC_CHANNEL_IDLE;
426
- return false;
427
- }
428
- } else {
429
- // For any state other than READY, unref the connected subchannel.
430
- connected_subchannel_.reset();
416
+ subchannel_.get(), reason);
431
417
  }
432
- return true;
433
- }
434
-
435
- template <typename SubchannelListType, typename SubchannelDataType>
436
- void SubchannelData<SubchannelListType, SubchannelDataType>::
437
- OnConnectivityChangedLocked(void* arg, grpc_error* error) {
438
- SubchannelData* sd = static_cast<SubchannelData*>(arg);
439
- if (GRPC_TRACE_FLAG_ENABLED(*sd->subchannel_list_->tracer())) {
440
- gpr_log(
441
- GPR_INFO,
442
- "[%s %p] subchannel list %p index %" PRIuPTR " of %" PRIuPTR
443
- " (subchannel %p): connectivity changed: state=%s, error=%s, "
444
- "shutting_down=%d",
445
- sd->subchannel_list_->tracer()->name(), sd->subchannel_list_->policy(),
446
- sd->subchannel_list_, sd->Index(),
447
- sd->subchannel_list_->num_subchannels(), sd->subchannel_,
448
- grpc_connectivity_state_name(sd->pending_connectivity_state_unsafe_),
449
- grpc_error_string(error), sd->subchannel_list_->shutting_down());
450
- }
451
- // If shutting down, unref subchannel and stop watching.
452
- if (sd->subchannel_list_->shutting_down() || error == GRPC_ERROR_CANCELLED) {
453
- sd->UnrefSubchannelLocked("connectivity_shutdown");
454
- sd->StopConnectivityWatchLocked();
455
- return;
418
+ if (pending_watcher_ != nullptr) {
419
+ subchannel_->CancelConnectivityStateWatch(pending_watcher_);
420
+ pending_watcher_ = nullptr;
456
421
  }
457
- // Get or release ref to connected subchannel.
458
- if (!sd->UpdateConnectedSubchannelLocked()) {
459
- // We don't want to report this connectivity state, so renew the watch.
460
- sd->RenewConnectivityWatchLocked();
461
- return;
462
- }
463
- // Call the subclass's ProcessConnectivityChangeLocked() method.
464
- sd->ProcessConnectivityChangeLocked(sd->pending_connectivity_state_unsafe_);
465
422
  }
466
423
 
467
424
  template <typename SubchannelListType, typename SubchannelDataType>
468
425
  void SubchannelData<SubchannelListType, SubchannelDataType>::ShutdownLocked() {
469
- // If there's a pending notification for this subchannel, cancel it;
470
- // the callback is responsible for unreffing the subchannel.
471
- // Otherwise, unref the subchannel directly.
472
- if (connectivity_notification_pending_) {
473
- CancelConnectivityWatchLocked("shutdown");
474
- } else if (subchannel_ != nullptr) {
475
- UnrefSubchannelLocked("shutdown");
476
- }
426
+ if (pending_watcher_ != nullptr) CancelConnectivityWatchLocked("shutdown");
427
+ UnrefSubchannelLocked("shutdown");
477
428
  }
478
429
 
479
430
  //
@@ -498,12 +449,10 @@ SubchannelList<SubchannelListType, SubchannelDataType>::SubchannelList(
498
449
  subchannels_.reserve(addresses.size());
499
450
  // We need to remove the LB addresses in order to be able to compare the
500
451
  // subchannel keys of subchannels from a different batch of addresses.
501
- // We also remove the inhibit-health-checking arg, since we are
502
- // handling that here.
503
- inhibit_health_checking_ = grpc_channel_arg_get_bool(
504
- grpc_channel_args_find(&args, GRPC_ARG_INHIBIT_HEALTH_CHECKING), false);
452
+ // We remove the service config, since it will be passed into the
453
+ // subchannel via call context.
505
454
  static const char* keys_to_remove[] = {GRPC_ARG_SUBCHANNEL_ADDRESS,
506
- GRPC_ARG_INHIBIT_HEALTH_CHECKING};
455
+ GRPC_ARG_SERVICE_CONFIG};
507
456
  // Create a subchannel for each address.
508
457
  for (size_t i = 0; i < addresses.size(); i++) {
509
458
  // TODO(roth): we should ideally hide this from the LB policy code. In
@@ -526,7 +475,8 @@ SubchannelList<SubchannelListType, SubchannelDataType>::SubchannelList(
526
475
  &args, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove),
527
476
  args_to_add.data(), args_to_add.size());
528
477
  gpr_free(args_to_add[subchannel_address_arg_index].value.string);
529
- Subchannel* subchannel = helper->CreateSubchannel(*new_args);
478
+ RefCountedPtr<SubchannelInterface> subchannel =
479
+ helper->CreateSubchannel(*new_args);
530
480
  grpc_channel_args_destroy(new_args);
531
481
  if (subchannel == nullptr) {
532
482
  // Subchannel could not be created.
@@ -545,11 +495,11 @@ SubchannelList<SubchannelListType, SubchannelDataType>::SubchannelList(
545
495
  gpr_log(GPR_INFO,
546
496
  "[%s %p] subchannel list %p index %" PRIuPTR
547
497
  ": Created subchannel %p for address uri %s",
548
- tracer_->name(), policy_, this, subchannels_.size(), subchannel,
549
- address_uri);
498
+ tracer_->name(), policy_, this, subchannels_.size(),
499
+ subchannel.get(), address_uri);
550
500
  gpr_free(address_uri);
551
501
  }
552
- subchannels_.emplace_back(this, addresses[i], subchannel, combiner);
502
+ subchannels_.emplace_back(this, addresses[i], std::move(subchannel));
553
503
  }
554
504
  }
555
505