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
@@ -39,12 +39,10 @@ ServerAddress::ServerAddress(const void* address, size_t address_len,
39
39
  address_.len = static_cast<socklen_t>(address_len);
40
40
  }
41
41
 
42
- int ServerAddress::Cmp(const ServerAddress& other) const {
43
- if (address_.len > other.address_.len) return 1;
44
- if (address_.len < other.address_.len) return -1;
45
- int retval = memcmp(address_.addr, other.address_.addr, address_.len);
46
- if (retval != 0) return retval;
47
- return grpc_channel_args_compare(args_, other.args_);
42
+ bool ServerAddress::operator==(const grpc_core::ServerAddress& other) const {
43
+ return address_.len == other.address_.len &&
44
+ memcmp(address_.addr, other.address_.addr, address_.len) == 0 &&
45
+ grpc_channel_args_compare(args_, other.args_) == 0;
48
46
  }
49
47
 
50
48
  bool ServerAddress::IsBalancer() const {
@@ -73,9 +73,7 @@ class ServerAddress {
73
73
  return *this;
74
74
  }
75
75
 
76
- bool operator==(const ServerAddress& other) const { return Cmp(other) == 0; }
77
-
78
- int Cmp(const ServerAddress& other) const;
76
+ bool operator==(const ServerAddress& other) const;
79
77
 
80
78
  const grpc_resolved_address& address() const { return address_; }
81
79
  const grpc_channel_args* args() const { return args_; }
@@ -96,16 +96,15 @@ grpc_error* ServiceConfig::ParseGlobalParams(const grpc_json* json_tree) {
96
96
  if (parser_error != GRPC_ERROR_NONE) {
97
97
  error_list.push_back(parser_error);
98
98
  }
99
- parsed_global_service_config_objects_.push_back(std::move(parsed_obj));
99
+ parsed_global_configs_.push_back(std::move(parsed_obj));
100
100
  }
101
101
  return GRPC_ERROR_CREATE_FROM_VECTOR("Global Params", &error_list);
102
102
  }
103
103
 
104
- grpc_error* ServiceConfig::ParseJsonMethodConfigToServiceConfigObjectsTable(
104
+ grpc_error* ServiceConfig::ParseJsonMethodConfigToServiceConfigVectorTable(
105
105
  const grpc_json* json,
106
- SliceHashTable<const ServiceConfigObjectsVector*>::Entry* entries,
107
- size_t* idx) {
108
- auto objs_vector = MakeUnique<ServiceConfigObjectsVector>();
106
+ SliceHashTable<const ParsedConfigVector*>::Entry* entries, size_t* idx) {
107
+ auto objs_vector = MakeUnique<ParsedConfigVector>();
109
108
  InlinedVector<grpc_error*, 4> error_list;
110
109
  for (size_t i = 0; i < g_registered_parsers->size(); i++) {
111
110
  grpc_error* parser_error = GRPC_ERROR_NONE;
@@ -116,10 +115,10 @@ grpc_error* ServiceConfig::ParseJsonMethodConfigToServiceConfigObjectsTable(
116
115
  }
117
116
  objs_vector->push_back(std::move(parsed_obj));
118
117
  }
119
- service_config_objects_vectors_storage_.push_back(std::move(objs_vector));
118
+ parsed_method_config_vectors_storage_.push_back(std::move(objs_vector));
120
119
  const auto* vector_ptr =
121
- service_config_objects_vectors_storage_
122
- [service_config_objects_vectors_storage_.size() - 1]
120
+ parsed_method_config_vectors_storage_
121
+ [parsed_method_config_vectors_storage_.size() - 1]
123
122
  .get();
124
123
  // Construct list of paths.
125
124
  InlinedVector<UniquePtr<char>, 10> paths;
@@ -160,7 +159,7 @@ wrap_error:
160
159
  grpc_error* ServiceConfig::ParsePerMethodParams(const grpc_json* json_tree) {
161
160
  GPR_DEBUG_ASSERT(json_tree_->type == GRPC_JSON_OBJECT);
162
161
  GPR_DEBUG_ASSERT(json_tree_->key == nullptr);
163
- SliceHashTable<const ServiceConfigObjectsVector*>::Entry* entries = nullptr;
162
+ SliceHashTable<const ParsedConfigVector*>::Entry* entries = nullptr;
164
163
  size_t num_entries = 0;
165
164
  InlinedVector<grpc_error*, 4> error_list;
166
165
  for (grpc_json* field = json_tree->child; field != nullptr;
@@ -187,14 +186,13 @@ grpc_error* ServiceConfig::ParsePerMethodParams(const grpc_json* json_tree) {
187
186
  }
188
187
  num_entries += static_cast<size_t>(count);
189
188
  }
190
- entries = static_cast<
191
- SliceHashTable<const ServiceConfigObjectsVector*>::Entry*>(gpr_zalloc(
192
- num_entries *
193
- sizeof(SliceHashTable<const ServiceConfigObjectsVector*>::Entry)));
189
+ entries = static_cast<SliceHashTable<const ParsedConfigVector*>::Entry*>(
190
+ gpr_zalloc(num_entries *
191
+ sizeof(SliceHashTable<const ParsedConfigVector*>::Entry)));
194
192
  size_t idx = 0;
195
193
  for (grpc_json* method = field->child; method != nullptr;
196
194
  method = method->next) {
197
- grpc_error* error = ParseJsonMethodConfigToServiceConfigObjectsTable(
195
+ grpc_error* error = ParseJsonMethodConfigToServiceConfigVectorTable(
198
196
  method, entries, &idx);
199
197
  if (error != GRPC_ERROR_NONE) {
200
198
  error_list.push_back(error);
@@ -206,9 +204,9 @@ grpc_error* ServiceConfig::ParsePerMethodParams(const grpc_json* json_tree) {
206
204
  }
207
205
  }
208
206
  if (entries != nullptr) {
209
- parsed_method_service_config_objects_table_ =
210
- SliceHashTable<const ServiceConfigObjectsVector*>::Create(
211
- num_entries, entries, nullptr);
207
+ parsed_method_configs_table_ =
208
+ SliceHashTable<const ParsedConfigVector*>::Create(num_entries, entries,
209
+ nullptr);
212
210
  gpr_free(entries);
213
211
  }
214
212
  return GRPC_ERROR_CREATE_FROM_VECTOR("Method Params", &error_list);
@@ -287,12 +285,12 @@ UniquePtr<char> ServiceConfig::ParseJsonMethodName(grpc_json* json,
287
285
  return UniquePtr<char>(path);
288
286
  }
289
287
 
290
- const ServiceConfig::ServiceConfigObjectsVector*
291
- ServiceConfig::GetMethodServiceConfigObjectsVector(const grpc_slice& path) {
292
- if (parsed_method_service_config_objects_table_.get() == nullptr) {
288
+ const ServiceConfig::ParsedConfigVector*
289
+ ServiceConfig::GetMethodParsedConfigVector(const grpc_slice& path) {
290
+ if (parsed_method_configs_table_.get() == nullptr) {
293
291
  return nullptr;
294
292
  }
295
- const auto* value = parsed_method_service_config_objects_table_->Get(path);
293
+ const auto* value = parsed_method_configs_table_->Get(path);
296
294
  // If we didn't find a match for the path, try looking for a wildcard
297
295
  // entry (i.e., change "/service/method" to "/service/*").
298
296
  if (value == nullptr) {
@@ -305,7 +303,7 @@ ServiceConfig::GetMethodServiceConfigObjectsVector(const grpc_slice& path) {
305
303
  buf[len + 1] = '\0';
306
304
  grpc_slice wildcard_path = grpc_slice_from_copied_string(buf);
307
305
  gpr_free(buf);
308
- value = parsed_method_service_config_objects_table_->Get(wildcard_path);
306
+ value = parsed_method_configs_table_->Get(wildcard_path);
309
307
  grpc_slice_unref_internal(wildcard_path);
310
308
  gpr_free(path_str);
311
309
  if (value == nullptr) return nullptr;
@@ -88,7 +88,7 @@ class ServiceConfig : public RefCounted<ServiceConfig> {
88
88
 
89
89
  static constexpr int kNumPreallocatedParsers = 4;
90
90
  typedef InlinedVector<UniquePtr<ParsedConfig>, kNumPreallocatedParsers>
91
- ServiceConfigObjectsVector;
91
+ ParsedConfigVector;
92
92
 
93
93
  /// When a service config is applied to a call in the client_channel_filter,
94
94
  /// we create an instance of this object and store it in the call_data for
@@ -102,25 +102,25 @@ class ServiceConfig : public RefCounted<ServiceConfig> {
102
102
  : service_config_(std::move(svc_cfg)) {
103
103
  if (service_config_ != nullptr) {
104
104
  method_params_vector_ =
105
- service_config_->GetMethodServiceConfigObjectsVector(path);
105
+ service_config_->GetMethodParsedConfigVector(path);
106
106
  }
107
107
  }
108
108
 
109
109
  ServiceConfig* service_config() { return service_config_.get(); }
110
110
 
111
- ParsedConfig* GetMethodParsedObject(size_t index) const {
111
+ ParsedConfig* GetMethodParsedConfig(size_t index) const {
112
112
  return method_params_vector_ != nullptr
113
113
  ? (*method_params_vector_)[index].get()
114
114
  : nullptr;
115
115
  }
116
116
 
117
- ParsedConfig* GetGlobalParsedObject(size_t index) const {
118
- return service_config_->GetParsedGlobalServiceConfigObject(index);
117
+ ParsedConfig* GetGlobalParsedConfig(size_t index) const {
118
+ return service_config_->GetGlobalParsedConfig(index);
119
119
  }
120
120
 
121
121
  private:
122
122
  RefCountedPtr<ServiceConfig> service_config_;
123
- const ServiceConfigObjectsVector* method_params_vector_ = nullptr;
123
+ const ParsedConfigVector* method_params_vector_ = nullptr;
124
124
  };
125
125
 
126
126
  /// Creates a new service config from parsing \a json_string.
@@ -132,25 +132,24 @@ class ServiceConfig : public RefCounted<ServiceConfig> {
132
132
 
133
133
  const char* service_config_json() const { return service_config_json_.get(); }
134
134
 
135
- /// Retrieves the parsed global service config object at index \a index. The
135
+ /// Retrieves the global parsed config at index \a index. The
136
136
  /// lifetime of the returned object is tied to the lifetime of the
137
137
  /// ServiceConfig object.
138
- ParsedConfig* GetParsedGlobalServiceConfigObject(size_t index) {
139
- GPR_DEBUG_ASSERT(index < parsed_global_service_config_objects_.size());
140
- return parsed_global_service_config_objects_[index].get();
138
+ ParsedConfig* GetGlobalParsedConfig(size_t index) {
139
+ GPR_DEBUG_ASSERT(index < parsed_global_configs_.size());
140
+ return parsed_global_configs_[index].get();
141
141
  }
142
142
 
143
- /// Retrieves the vector of method service config objects for a given path \a
144
- /// path. The lifetime of the returned vector and contained objects is tied to
145
- /// the lifetime of the ServiceConfig object.
146
- const ServiceConfigObjectsVector* GetMethodServiceConfigObjectsVector(
147
- const grpc_slice& path);
143
+ /// Retrieves the vector of parsed configs for the method identified
144
+ /// by \a path. The lifetime of the returned vector and contained objects
145
+ /// is tied to the lifetime of the ServiceConfig object.
146
+ const ParsedConfigVector* GetMethodParsedConfigVector(const grpc_slice& path);
148
147
 
149
148
  /// Globally register a service config parser. On successful registration, it
150
149
  /// returns the index at which the parser was registered. On failure, -1 is
151
150
  /// returned. Each new service config update will go through all the
152
151
  /// registered parser. Each parser is responsible for reading the service
153
- /// config json and returning a parsed object. This parsed object can later be
152
+ /// config json and returning a parsed config. This parsed config can later be
154
153
  /// retrieved using the same index that was returned at registration time.
155
154
  static size_t RegisterParser(UniquePtr<Parser> parser);
156
155
 
@@ -180,26 +179,25 @@ class ServiceConfig : public RefCounted<ServiceConfig> {
180
179
  static UniquePtr<char> ParseJsonMethodName(grpc_json* json,
181
180
  grpc_error** error);
182
181
 
183
- grpc_error* ParseJsonMethodConfigToServiceConfigObjectsTable(
182
+ grpc_error* ParseJsonMethodConfigToServiceConfigVectorTable(
184
183
  const grpc_json* json,
185
- SliceHashTable<const ServiceConfigObjectsVector*>::Entry* entries,
186
- size_t* idx);
184
+ SliceHashTable<const ParsedConfigVector*>::Entry* entries, size_t* idx);
187
185
 
188
186
  UniquePtr<char> service_config_json_;
189
187
  UniquePtr<char> json_string_; // Underlying storage for json_tree.
190
188
  grpc_json* json_tree_;
191
189
 
192
190
  InlinedVector<UniquePtr<ParsedConfig>, kNumPreallocatedParsers>
193
- parsed_global_service_config_objects_;
194
- // A map from the method name to the service config objects vector. Note that
195
- // we are using a raw pointer and not a unique pointer so that we can use the
196
- // same vector for multiple names.
197
- RefCountedPtr<SliceHashTable<const ServiceConfigObjectsVector*>>
198
- parsed_method_service_config_objects_table_;
191
+ parsed_global_configs_;
192
+ // A map from the method name to the parsed config vector. Note that we are
193
+ // using a raw pointer and not a unique pointer so that we can use the same
194
+ // vector for multiple names.
195
+ RefCountedPtr<SliceHashTable<const ParsedConfigVector*>>
196
+ parsed_method_configs_table_;
199
197
  // Storage for all the vectors that are being used in
200
- // parsed_method_service_config_objects_table_.
201
- InlinedVector<UniquePtr<ServiceConfigObjectsVector>, 32>
202
- service_config_objects_vectors_storage_;
198
+ // parsed_method_configs_table_.
199
+ InlinedVector<UniquePtr<ParsedConfigVector>, 32>
200
+ parsed_method_config_vectors_storage_;
203
201
  };
204
202
 
205
203
  } // namespace grpc_core
@@ -75,6 +75,9 @@
75
75
 
76
76
  namespace grpc_core {
77
77
 
78
+ TraceFlag grpc_trace_subchannel(false, "subchannel");
79
+ DebugOnlyTraceFlag grpc_trace_subchannel_refcount(false, "subchannel_refcount");
80
+
78
81
  //
79
82
  // ConnectedSubchannel
80
83
  //
@@ -83,7 +86,7 @@ ConnectedSubchannel::ConnectedSubchannel(
83
86
  grpc_channel_stack* channel_stack, const grpc_channel_args* args,
84
87
  RefCountedPtr<channelz::SubchannelNode> channelz_subchannel,
85
88
  intptr_t socket_uuid)
86
- : RefCounted<ConnectedSubchannel>(&grpc_trace_stream_refcount),
89
+ : ConnectedSubchannelInterface(&grpc_trace_subchannel_refcount),
87
90
  channel_stack_(channel_stack),
88
91
  args_(grpc_channel_args_copy(args)),
89
92
  channelz_subchannel_(std::move(channelz_subchannel)),
@@ -303,8 +306,7 @@ void SubchannelCall::IncrementRefCount(const grpc_core::DebugLocation& location,
303
306
  // Subchannel::ConnectedSubchannelStateWatcher
304
307
  //
305
308
 
306
- class Subchannel::ConnectedSubchannelStateWatcher
307
- : public InternallyRefCounted<ConnectedSubchannelStateWatcher> {
309
+ class Subchannel::ConnectedSubchannelStateWatcher {
308
310
  public:
309
311
  // Must be instantiated while holding c->mu.
310
312
  explicit ConnectedSubchannelStateWatcher(Subchannel* c) : subchannel_(c) {
@@ -312,38 +314,17 @@ class Subchannel::ConnectedSubchannelStateWatcher
312
314
  GRPC_SUBCHANNEL_WEAK_REF(subchannel_, "state_watcher");
313
315
  GRPC_SUBCHANNEL_WEAK_UNREF(subchannel_, "connecting");
314
316
  // Start watching for connectivity state changes.
315
- // Callback uses initial ref to this.
316
317
  GRPC_CLOSURE_INIT(&on_connectivity_changed_, OnConnectivityChanged, this,
317
318
  grpc_schedule_on_exec_ctx);
318
319
  c->connected_subchannel_->NotifyOnStateChange(c->pollset_set_,
319
320
  &pending_connectivity_state_,
320
321
  &on_connectivity_changed_);
321
- // Start health check if needed.
322
- grpc_connectivity_state health_state = GRPC_CHANNEL_READY;
323
- if (c->health_check_service_name_ != nullptr) {
324
- health_check_client_ = MakeOrphanable<HealthCheckClient>(
325
- c->health_check_service_name_.get(), c->connected_subchannel_,
326
- c->pollset_set_, c->channelz_node_);
327
- GRPC_CLOSURE_INIT(&on_health_changed_, OnHealthChanged, this,
328
- grpc_schedule_on_exec_ctx);
329
- Ref().release(); // Ref for health callback tracked manually.
330
- health_check_client_->NotifyOnHealthChange(&health_state_,
331
- &on_health_changed_);
332
- health_state = GRPC_CHANNEL_CONNECTING;
333
- }
334
- // Report initial state.
335
- c->SetConnectivityStateLocked(GRPC_CHANNEL_READY, "subchannel_connected");
336
- grpc_connectivity_state_set(&c->state_and_health_tracker_, health_state,
337
- "subchannel_connected");
338
322
  }
339
323
 
340
324
  ~ConnectedSubchannelStateWatcher() {
341
325
  GRPC_SUBCHANNEL_WEAK_UNREF(subchannel_, "state_watcher");
342
326
  }
343
327
 
344
- // Must be called while holding subchannel_->mu.
345
- void Orphan() override { health_check_client_.reset(); }
346
-
347
328
  private:
348
329
  static void OnConnectivityChanged(void* arg, grpc_error* error) {
349
330
  auto* self = static_cast<ConnectedSubchannelStateWatcher*>(arg);
@@ -354,7 +335,7 @@ class Subchannel::ConnectedSubchannelStateWatcher
354
335
  case GRPC_CHANNEL_TRANSIENT_FAILURE:
355
336
  case GRPC_CHANNEL_SHUTDOWN: {
356
337
  if (!c->disconnected_ && c->connected_subchannel_ != nullptr) {
357
- if (grpc_trace_stream_refcount.enabled()) {
338
+ if (grpc_trace_subchannel.enabled()) {
358
339
  gpr_log(GPR_INFO,
359
340
  "Connected subchannel %p of subchannel %p has gone into "
360
341
  "%s. Attempting to reconnect.",
@@ -363,20 +344,10 @@ class Subchannel::ConnectedSubchannelStateWatcher
363
344
  self->pending_connectivity_state_));
364
345
  }
365
346
  c->connected_subchannel_.reset();
366
- c->connected_subchannel_watcher_.reset();
367
- self->last_connectivity_state_ = GRPC_CHANNEL_TRANSIENT_FAILURE;
368
- c->SetConnectivityStateLocked(GRPC_CHANNEL_TRANSIENT_FAILURE,
369
- "reflect_child");
370
- grpc_connectivity_state_set(&c->state_and_health_tracker_,
371
- GRPC_CHANNEL_TRANSIENT_FAILURE,
372
- "reflect_child");
347
+ c->SetConnectivityStateLocked(GRPC_CHANNEL_TRANSIENT_FAILURE);
373
348
  c->backoff_begun_ = false;
374
349
  c->backoff_.Reset();
375
- c->MaybeStartConnectingLocked();
376
- } else {
377
- self->last_connectivity_state_ = GRPC_CHANNEL_SHUTDOWN;
378
350
  }
379
- self->health_check_client_.reset();
380
351
  break;
381
352
  }
382
353
  default: {
@@ -384,96 +355,230 @@ class Subchannel::ConnectedSubchannelStateWatcher
384
355
  // a callback for READY, because that was the state we started
385
356
  // this watch from. And a connected subchannel should never go
386
357
  // from READY to CONNECTING or IDLE.
387
- self->last_connectivity_state_ = self->pending_connectivity_state_;
388
- c->SetConnectivityStateLocked(self->pending_connectivity_state_,
389
- "reflect_child");
390
- if (self->pending_connectivity_state_ != GRPC_CHANNEL_READY) {
391
- grpc_connectivity_state_set(&c->state_and_health_tracker_,
392
- self->pending_connectivity_state_,
393
- "reflect_child");
394
- }
358
+ c->SetConnectivityStateLocked(self->pending_connectivity_state_);
395
359
  c->connected_subchannel_->NotifyOnStateChange(
396
360
  nullptr, &self->pending_connectivity_state_,
397
361
  &self->on_connectivity_changed_);
398
- self = nullptr; // So we don't unref below.
362
+ return; // So we don't delete ourself below.
399
363
  }
400
364
  }
401
365
  }
402
- // Don't unref until we've released the lock, because this might
366
+ // Don't delete until we've released the lock, because this might
403
367
  // cause the subchannel (which contains the lock) to be destroyed.
404
- if (self != nullptr) self->Unref();
368
+ Delete(self);
369
+ }
370
+
371
+ Subchannel* subchannel_;
372
+ grpc_closure on_connectivity_changed_;
373
+ grpc_connectivity_state pending_connectivity_state_ = GRPC_CHANNEL_READY;
374
+ };
375
+
376
+ //
377
+ // Subchannel::ConnectivityStateWatcherList
378
+ //
379
+
380
+ void Subchannel::ConnectivityStateWatcherList::AddWatcherLocked(
381
+ UniquePtr<ConnectivityStateWatcher> watcher) {
382
+ watchers_.insert(MakePair(watcher.get(), std::move(watcher)));
383
+ }
384
+
385
+ void Subchannel::ConnectivityStateWatcherList::RemoveWatcherLocked(
386
+ ConnectivityStateWatcher* watcher) {
387
+ watchers_.erase(watcher);
388
+ }
389
+
390
+ void Subchannel::ConnectivityStateWatcherList::NotifyLocked(
391
+ Subchannel* subchannel, grpc_connectivity_state state) {
392
+ for (const auto& p : watchers_) {
393
+ RefCountedPtr<ConnectedSubchannel> connected_subchannel;
394
+ if (state == GRPC_CHANNEL_READY) {
395
+ connected_subchannel = subchannel->connected_subchannel_;
396
+ }
397
+ // TODO(roth): In principle, it seems wrong to send this notification
398
+ // to the watcher while holding the subchannel's mutex, since it could
399
+ // lead to a deadlock if the watcher calls back into the subchannel
400
+ // before returning back to us. In practice, this doesn't happen,
401
+ // because the LB policy code that watches subchannels always bounces
402
+ // the notification into the client_channel control-plane combiner
403
+ // before processing it. But if we ever have any other callers here,
404
+ // we will probably need to change this.
405
+ p.second->OnConnectivityStateChange(state, std::move(connected_subchannel));
406
+ }
407
+ }
408
+
409
+ //
410
+ // Subchannel::HealthWatcherMap::HealthWatcher
411
+ //
412
+
413
+ // State needed for tracking the connectivity state with a particular
414
+ // health check service name.
415
+ class Subchannel::HealthWatcherMap::HealthWatcher
416
+ : public InternallyRefCounted<HealthWatcher> {
417
+ public:
418
+ HealthWatcher(Subchannel* c, UniquePtr<char> health_check_service_name,
419
+ grpc_connectivity_state subchannel_state)
420
+ : subchannel_(c),
421
+ health_check_service_name_(std::move(health_check_service_name)),
422
+ state_(subchannel_state == GRPC_CHANNEL_READY ? GRPC_CHANNEL_CONNECTING
423
+ : subchannel_state) {
424
+ GRPC_SUBCHANNEL_WEAK_REF(subchannel_, "health_watcher");
425
+ GRPC_CLOSURE_INIT(&on_health_changed_, OnHealthChanged, this,
426
+ grpc_schedule_on_exec_ctx);
427
+ // If the subchannel is already connected, start health checking.
428
+ if (subchannel_state == GRPC_CHANNEL_READY) StartHealthCheckingLocked();
429
+ }
430
+
431
+ ~HealthWatcher() {
432
+ GRPC_SUBCHANNEL_WEAK_UNREF(subchannel_, "health_watcher");
433
+ }
434
+
435
+ const char* health_check_service_name() const {
436
+ return health_check_service_name_.get();
437
+ }
438
+
439
+ grpc_connectivity_state state() const { return state_; }
440
+
441
+ void AddWatcherLocked(grpc_connectivity_state initial_state,
442
+ UniquePtr<ConnectivityStateWatcher> watcher) {
443
+ if (state_ != initial_state) {
444
+ RefCountedPtr<ConnectedSubchannel> connected_subchannel;
445
+ if (state_ == GRPC_CHANNEL_READY) {
446
+ connected_subchannel = subchannel_->connected_subchannel_;
447
+ }
448
+ watcher->OnConnectivityStateChange(state_,
449
+ std::move(connected_subchannel));
450
+ }
451
+ watcher_list_.AddWatcherLocked(std::move(watcher));
452
+ }
453
+
454
+ void RemoveWatcherLocked(ConnectivityStateWatcher* watcher) {
455
+ watcher_list_.RemoveWatcherLocked(watcher);
456
+ }
457
+
458
+ bool HasWatchers() const { return !watcher_list_.empty(); }
459
+
460
+ void NotifyLocked(grpc_connectivity_state state) {
461
+ if (state == GRPC_CHANNEL_READY) {
462
+ // If we had not already notified for CONNECTING state, do so now.
463
+ // (We may have missed this earlier, because if the transition
464
+ // from IDLE to CONNECTING to READY was too quick, the connected
465
+ // subchannel may not have sent us a notification for CONNECTING.)
466
+ if (state_ != GRPC_CHANNEL_CONNECTING) {
467
+ state_ = GRPC_CHANNEL_CONNECTING;
468
+ watcher_list_.NotifyLocked(subchannel_, state_);
469
+ }
470
+ // If we've become connected, start health checking.
471
+ StartHealthCheckingLocked();
472
+ } else {
473
+ state_ = state;
474
+ watcher_list_.NotifyLocked(subchannel_, state_);
475
+ // We're not connected, so stop health checking.
476
+ health_check_client_.reset();
477
+ }
478
+ }
479
+
480
+ void Orphan() override {
481
+ watcher_list_.Clear();
482
+ health_check_client_.reset();
483
+ Unref();
484
+ }
485
+
486
+ private:
487
+ void StartHealthCheckingLocked() {
488
+ GPR_ASSERT(health_check_client_ == nullptr);
489
+ health_check_client_ = MakeOrphanable<HealthCheckClient>(
490
+ health_check_service_name_.get(), subchannel_->connected_subchannel_,
491
+ subchannel_->pollset_set_, subchannel_->channelz_node_);
492
+ Ref().release(); // Ref for health callback tracked manually.
493
+ health_check_client_->NotifyOnHealthChange(&state_, &on_health_changed_);
405
494
  }
406
495
 
407
496
  static void OnHealthChanged(void* arg, grpc_error* error) {
408
- auto* self = static_cast<ConnectedSubchannelStateWatcher*>(arg);
497
+ auto* self = static_cast<HealthWatcher*>(arg);
409
498
  Subchannel* c = self->subchannel_;
410
499
  {
411
500
  MutexLock lock(&c->mu_);
412
- if (self->health_state_ != GRPC_CHANNEL_SHUTDOWN &&
501
+ if (self->state_ != GRPC_CHANNEL_SHUTDOWN &&
413
502
  self->health_check_client_ != nullptr) {
414
- if (self->last_connectivity_state_ == GRPC_CHANNEL_READY) {
415
- grpc_connectivity_state_set(&c->state_and_health_tracker_,
416
- self->health_state_, "health_changed");
417
- }
503
+ self->watcher_list_.NotifyLocked(c, self->state_);
504
+ // Renew watch.
418
505
  self->health_check_client_->NotifyOnHealthChange(
419
- &self->health_state_, &self->on_health_changed_);
420
- self = nullptr; // So we don't unref below.
506
+ &self->state_, &self->on_health_changed_);
507
+ return; // So we don't unref below.
421
508
  }
422
509
  }
423
510
  // Don't unref until we've released the lock, because this might
424
511
  // cause the subchannel (which contains the lock) to be destroyed.
425
- if (self != nullptr) self->Unref();
512
+ self->Unref();
426
513
  }
427
514
 
428
515
  Subchannel* subchannel_;
429
- grpc_closure on_connectivity_changed_;
430
- grpc_connectivity_state pending_connectivity_state_ = GRPC_CHANNEL_READY;
431
- grpc_connectivity_state last_connectivity_state_ = GRPC_CHANNEL_READY;
516
+ UniquePtr<char> health_check_service_name_;
432
517
  OrphanablePtr<HealthCheckClient> health_check_client_;
433
518
  grpc_closure on_health_changed_;
434
- grpc_connectivity_state health_state_ = GRPC_CHANNEL_CONNECTING;
519
+ grpc_connectivity_state state_;
520
+ ConnectivityStateWatcherList watcher_list_;
435
521
  };
436
522
 
437
523
  //
438
- // Subchannel::ExternalStateWatcher
524
+ // Subchannel::HealthWatcherMap
439
525
  //
440
526
 
441
- struct Subchannel::ExternalStateWatcher {
442
- ExternalStateWatcher(Subchannel* subchannel, grpc_pollset_set* pollset_set,
443
- grpc_closure* notify)
444
- : subchannel(subchannel), pollset_set(pollset_set), notify(notify) {
445
- GRPC_SUBCHANNEL_WEAK_REF(subchannel, "external_state_watcher+init");
446
- GRPC_CLOSURE_INIT(&on_state_changed, OnStateChanged, this,
447
- grpc_schedule_on_exec_ctx);
527
+ void Subchannel::HealthWatcherMap::AddWatcherLocked(
528
+ Subchannel* subchannel, grpc_connectivity_state initial_state,
529
+ UniquePtr<char> health_check_service_name,
530
+ UniquePtr<ConnectivityStateWatcher> watcher) {
531
+ // If the health check service name is not already present in the map,
532
+ // add it.
533
+ auto it = map_.find(health_check_service_name.get());
534
+ HealthWatcher* health_watcher;
535
+ if (it == map_.end()) {
536
+ const char* key = health_check_service_name.get();
537
+ auto w = MakeOrphanable<HealthWatcher>(
538
+ subchannel, std::move(health_check_service_name), subchannel->state_);
539
+ health_watcher = w.get();
540
+ map_[key] = std::move(w);
541
+ } else {
542
+ health_watcher = it->second.get();
448
543
  }
544
+ // Add the watcher to the entry.
545
+ health_watcher->AddWatcherLocked(initial_state, std::move(watcher));
546
+ }
449
547
 
450
- static void OnStateChanged(void* arg, grpc_error* error) {
451
- ExternalStateWatcher* w = static_cast<ExternalStateWatcher*>(arg);
452
- grpc_closure* follow_up = w->notify;
453
- if (w->pollset_set != nullptr) {
454
- grpc_pollset_set_del_pollset_set(w->subchannel->pollset_set_,
455
- w->pollset_set);
456
- }
457
- {
458
- MutexLock lock(&w->subchannel->mu_);
459
- if (w->subchannel->external_state_watcher_list_ == w) {
460
- w->subchannel->external_state_watcher_list_ = w->next;
461
- }
462
- if (w->next != nullptr) w->next->prev = w->prev;
463
- if (w->prev != nullptr) w->prev->next = w->next;
464
- }
465
- GRPC_SUBCHANNEL_WEAK_UNREF(w->subchannel, "external_state_watcher+done");
466
- Delete(w);
467
- GRPC_CLOSURE_SCHED(follow_up, GRPC_ERROR_REF(error));
548
+ void Subchannel::HealthWatcherMap::RemoveWatcherLocked(
549
+ const char* health_check_service_name, ConnectivityStateWatcher* watcher) {
550
+ auto it = map_.find(health_check_service_name);
551
+ GPR_ASSERT(it != map_.end());
552
+ it->second->RemoveWatcherLocked(watcher);
553
+ // If we just removed the last watcher for this service name, remove
554
+ // the map entry.
555
+ if (!it->second->HasWatchers()) map_.erase(it);
556
+ }
557
+
558
+ void Subchannel::HealthWatcherMap::NotifyLocked(grpc_connectivity_state state) {
559
+ for (const auto& p : map_) {
560
+ p.second->NotifyLocked(state);
468
561
  }
562
+ }
469
563
 
470
- Subchannel* subchannel;
471
- grpc_pollset_set* pollset_set;
472
- grpc_closure* notify;
473
- grpc_closure on_state_changed;
474
- ExternalStateWatcher* next = nullptr;
475
- ExternalStateWatcher* prev = nullptr;
476
- };
564
+ grpc_connectivity_state
565
+ Subchannel::HealthWatcherMap::CheckConnectivityStateLocked(
566
+ Subchannel* subchannel, const char* health_check_service_name) {
567
+ auto it = map_.find(health_check_service_name);
568
+ if (it == map_.end()) {
569
+ // If the health check service name is not found in the map, we're
570
+ // not currently doing a health check for that service name. If the
571
+ // subchannel's state without health checking is READY, report
572
+ // CONNECTING, since that's what we'd be in as soon as we do start a
573
+ // watch. Otherwise, report the channel's state without health checking.
574
+ return subchannel->state_ == GRPC_CHANNEL_READY ? GRPC_CHANNEL_CONNECTING
575
+ : subchannel->state_;
576
+ }
577
+ HealthWatcher* health_watcher = it->second.get();
578
+ return health_watcher->state();
579
+ }
580
+
581
+ void Subchannel::HealthWatcherMap::ShutdownLocked() { map_.clear(); }
477
582
 
478
583
  //
479
584
  // Subchannel
@@ -560,13 +665,6 @@ Subchannel::Subchannel(SubchannelKey* key, grpc_connector* connector,
560
665
  if (new_args != nullptr) grpc_channel_args_destroy(new_args);
561
666
  GRPC_CLOSURE_INIT(&on_connecting_finished_, OnConnectingFinished, this,
562
667
  grpc_schedule_on_exec_ctx);
563
- grpc_connectivity_state_init(&state_tracker_, GRPC_CHANNEL_IDLE,
564
- "subchannel");
565
- grpc_connectivity_state_init(&state_and_health_tracker_, GRPC_CHANNEL_IDLE,
566
- "subchannel");
567
- health_check_service_name_ =
568
- UniquePtr<char>(gpr_strdup(grpc_channel_arg_get_string(
569
- grpc_channel_args_find(args_, "grpc.temp.health_check"))));
570
668
  const grpc_arg* arg = grpc_channel_args_find(args_, GRPC_ARG_ENABLE_CHANNELZ);
571
669
  const bool channelz_enabled =
572
670
  grpc_channel_arg_get_bool(arg, GRPC_ENABLE_CHANNELZ_DEFAULT);
@@ -593,8 +691,6 @@ Subchannel::~Subchannel() {
593
691
  channelz_node_->MarkSubchannelDestroyed();
594
692
  }
595
693
  grpc_channel_args_destroy(args_);
596
- grpc_connectivity_state_destroy(&state_tracker_);
597
- grpc_connectivity_state_destroy(&state_and_health_tracker_);
598
694
  grpc_connector_unref(connector_);
599
695
  grpc_pollset_set_destroy(pollset_set_);
600
696
  Delete(key_);
@@ -698,55 +794,67 @@ const char* Subchannel::GetTargetAddress() {
698
794
  return addr_str;
699
795
  }
700
796
 
701
- RefCountedPtr<ConnectedSubchannel> Subchannel::connected_subchannel() {
702
- MutexLock lock(&mu_);
703
- return connected_subchannel_;
704
- }
705
-
706
797
  channelz::SubchannelNode* Subchannel::channelz_node() {
707
798
  return channelz_node_.get();
708
799
  }
709
800
 
710
- grpc_connectivity_state Subchannel::CheckConnectivity(
711
- bool inhibit_health_checking) {
712
- grpc_connectivity_state_tracker* tracker =
713
- inhibit_health_checking ? &state_tracker_ : &state_and_health_tracker_;
714
- grpc_connectivity_state state = grpc_connectivity_state_check(tracker);
801
+ grpc_connectivity_state Subchannel::CheckConnectivityState(
802
+ const char* health_check_service_name,
803
+ RefCountedPtr<ConnectedSubchannel>* connected_subchannel) {
804
+ MutexLock lock(&mu_);
805
+ grpc_connectivity_state state;
806
+ if (health_check_service_name == nullptr) {
807
+ state = state_;
808
+ } else {
809
+ state = health_watcher_map_.CheckConnectivityStateLocked(
810
+ this, health_check_service_name);
811
+ }
812
+ if (connected_subchannel != nullptr && state == GRPC_CHANNEL_READY) {
813
+ *connected_subchannel = connected_subchannel_;
814
+ }
715
815
  return state;
716
816
  }
717
817
 
718
- void Subchannel::NotifyOnStateChange(grpc_pollset_set* interested_parties,
719
- grpc_connectivity_state* state,
720
- grpc_closure* notify,
721
- bool inhibit_health_checking) {
722
- grpc_connectivity_state_tracker* tracker =
723
- inhibit_health_checking ? &state_tracker_ : &state_and_health_tracker_;
724
- ExternalStateWatcher* w;
725
- if (state == nullptr) {
726
- MutexLock lock(&mu_);
727
- for (w = external_state_watcher_list_; w != nullptr; w = w->next) {
728
- if (w->notify == notify) {
729
- grpc_connectivity_state_notify_on_state_change(tracker, nullptr,
730
- &w->on_state_changed);
731
- }
818
+ void Subchannel::WatchConnectivityState(
819
+ grpc_connectivity_state initial_state,
820
+ UniquePtr<char> health_check_service_name,
821
+ UniquePtr<ConnectivityStateWatcher> watcher) {
822
+ MutexLock lock(&mu_);
823
+ grpc_pollset_set* interested_parties = watcher->interested_parties();
824
+ if (interested_parties != nullptr) {
825
+ grpc_pollset_set_add_pollset_set(pollset_set_, interested_parties);
826
+ }
827
+ if (health_check_service_name == nullptr) {
828
+ if (state_ != initial_state) {
829
+ watcher->OnConnectivityStateChange(state_, connected_subchannel_);
732
830
  }
831
+ watcher_list_.AddWatcherLocked(std::move(watcher));
733
832
  } else {
734
- w = New<ExternalStateWatcher>(this, interested_parties, notify);
735
- if (interested_parties != nullptr) {
736
- grpc_pollset_set_add_pollset_set(pollset_set_, interested_parties);
737
- }
738
- MutexLock lock(&mu_);
739
- if (external_state_watcher_list_ != nullptr) {
740
- w->next = external_state_watcher_list_;
741
- w->next->prev = w;
742
- }
743
- external_state_watcher_list_ = w;
744
- grpc_connectivity_state_notify_on_state_change(tracker, state,
745
- &w->on_state_changed);
746
- MaybeStartConnectingLocked();
833
+ health_watcher_map_.AddWatcherLocked(this, initial_state,
834
+ std::move(health_check_service_name),
835
+ std::move(watcher));
747
836
  }
748
837
  }
749
838
 
839
+ void Subchannel::CancelConnectivityStateWatch(
840
+ const char* health_check_service_name, ConnectivityStateWatcher* watcher) {
841
+ MutexLock lock(&mu_);
842
+ grpc_pollset_set* interested_parties = watcher->interested_parties();
843
+ if (interested_parties != nullptr) {
844
+ grpc_pollset_set_del_pollset_set(pollset_set_, interested_parties);
845
+ }
846
+ if (health_check_service_name == nullptr) {
847
+ watcher_list_.RemoveWatcherLocked(watcher);
848
+ } else {
849
+ health_watcher_map_.RemoveWatcherLocked(health_check_service_name, watcher);
850
+ }
851
+ }
852
+
853
+ void Subchannel::AttemptToConnect() {
854
+ MutexLock lock(&mu_);
855
+ MaybeStartConnectingLocked();
856
+ }
857
+
750
858
  void Subchannel::ResetBackoff() {
751
859
  MutexLock lock(&mu_);
752
860
  backoff_.Reset();
@@ -818,15 +926,19 @@ const char* SubchannelConnectivityStateChangeString(
818
926
 
819
927
  } // namespace
820
928
 
821
- void Subchannel::SetConnectivityStateLocked(grpc_connectivity_state state,
822
- const char* reason) {
929
+ // Note: Must be called with a state that is different from the current state.
930
+ void Subchannel::SetConnectivityStateLocked(grpc_connectivity_state state) {
931
+ state_ = state;
823
932
  if (channelz_node_ != nullptr) {
824
933
  channelz_node_->AddTraceEvent(
825
934
  channelz::ChannelTrace::Severity::Info,
826
935
  grpc_slice_from_static_string(
827
936
  SubchannelConnectivityStateChangeString(state)));
828
937
  }
829
- grpc_connectivity_state_set(&state_tracker_, state, reason);
938
+ // Notify non-health watchers.
939
+ watcher_list_.NotifyLocked(this, state);
940
+ // Notify health watchers.
941
+ health_watcher_map_.NotifyLocked(state);
830
942
  }
831
943
 
832
944
  void Subchannel::MaybeStartConnectingLocked() {
@@ -842,11 +954,6 @@ void Subchannel::MaybeStartConnectingLocked() {
842
954
  // Already connected: don't restart.
843
955
  return;
844
956
  }
845
- if (!grpc_connectivity_state_has_watchers(&state_tracker_) &&
846
- !grpc_connectivity_state_has_watchers(&state_and_health_tracker_)) {
847
- // Nobody is interested in connecting: so don't just yet.
848
- return;
849
- }
850
957
  connecting_ = true;
851
958
  GRPC_SUBCHANNEL_WEAK_REF(this, "connecting");
852
959
  if (!backoff_begun_) {
@@ -903,9 +1010,7 @@ void Subchannel::ContinueConnectingLocked() {
903
1010
  next_attempt_deadline_ = backoff_.NextAttemptTime();
904
1011
  args.deadline = std::max(next_attempt_deadline_, min_deadline);
905
1012
  args.channel_args = args_;
906
- SetConnectivityStateLocked(GRPC_CHANNEL_CONNECTING, "connecting");
907
- grpc_connectivity_state_set(&state_and_health_tracker_,
908
- GRPC_CHANNEL_CONNECTING, "connecting");
1013
+ SetConnectivityStateLocked(GRPC_CHANNEL_CONNECTING);
909
1014
  grpc_connector_connect(connector_, &args, &connecting_result_,
910
1015
  &on_connecting_finished_);
911
1016
  }
@@ -924,12 +1029,7 @@ void Subchannel::OnConnectingFinished(void* arg, grpc_error* error) {
924
1029
  GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting");
925
1030
  } else {
926
1031
  gpr_log(GPR_INFO, "Connect failed: %s", grpc_error_string(error));
927
- c->SetConnectivityStateLocked(GRPC_CHANNEL_TRANSIENT_FAILURE,
928
- "connect_failed");
929
- grpc_connectivity_state_set(&c->state_and_health_tracker_,
930
- GRPC_CHANNEL_TRANSIENT_FAILURE,
931
- "connect_failed");
932
- c->MaybeStartConnectingLocked();
1032
+ c->SetConnectivityStateLocked(GRPC_CHANNEL_TRANSIENT_FAILURE);
933
1033
  GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting");
934
1034
  }
935
1035
  }
@@ -982,8 +1082,9 @@ bool Subchannel::PublishTransportLocked() {
982
1082
  gpr_log(GPR_INFO, "New connected subchannel at %p for subchannel %p",
983
1083
  connected_subchannel_.get(), this);
984
1084
  // Instantiate state watcher. Will clean itself up.
985
- connected_subchannel_watcher_ =
986
- MakeOrphanable<ConnectedSubchannelStateWatcher>(this);
1085
+ New<ConnectedSubchannelStateWatcher>(this);
1086
+ // Report initial state.
1087
+ SetConnectivityStateLocked(GRPC_CHANNEL_READY);
987
1088
  return true;
988
1089
  }
989
1090
 
@@ -1000,7 +1101,7 @@ void Subchannel::Disconnect() {
1000
1101
  grpc_connector_shutdown(connector_, GRPC_ERROR_CREATE_FROM_STATIC_STRING(
1001
1102
  "Subchannel disconnected"));
1002
1103
  connected_subchannel_.reset();
1003
- connected_subchannel_watcher_.reset();
1104
+ health_watcher_map_.ShutdownLocked();
1004
1105
  }
1005
1106
 
1006
1107
  gpr_atm Subchannel::RefMutate(
@@ -1008,7 +1109,7 @@ gpr_atm Subchannel::RefMutate(
1008
1109
  gpr_atm old_val = barrier ? gpr_atm_full_fetch_add(&ref_pair_, delta)
1009
1110
  : gpr_atm_no_barrier_fetch_add(&ref_pair_, delta);
1010
1111
  #ifndef NDEBUG
1011
- if (grpc_trace_stream_refcount.enabled()) {
1112
+ if (grpc_trace_subchannel_refcount.enabled()) {
1012
1113
  gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
1013
1114
  "SUBCHANNEL: %p %12s 0x%" PRIxPTR " -> 0x%" PRIxPTR " [%s]", this,
1014
1115
  purpose, old_val, old_val + delta, reason);