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.
- checksums.yaml +4 -4
- data/Makefile +422 -62
- data/include/grpc/grpc_security.h +61 -5
- data/include/grpc/grpc_security_constants.h +1 -1
- data/include/grpc/impl/codegen/gpr_types.h +1 -1
- data/include/grpc/slice.h +2 -2
- data/src/core/ext/filters/client_channel/backup_poller.cc +2 -3
- data/src/core/ext/filters/client_channel/backup_poller.h +5 -2
- data/src/core/ext/filters/client_channel/client_channel.cc +260 -122
- data/src/core/ext/filters/client_channel/client_channel.h +0 -8
- data/src/core/ext/filters/client_channel/client_channel_channelz.cc +3 -84
- data/src/core/ext/filters/client_channel/client_channel_channelz.h +2 -28
- data/src/core/ext/filters/client_channel/client_channel_plugin.cc +2 -8
- data/src/core/ext/filters/client_channel/health/health_check_client.cc +5 -4
- data/src/core/ext/filters/client_channel/lb_policy.cc +16 -2
- data/src/core/ext/filters/client_channel/lb_policy.h +92 -98
- data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc +63 -87
- data/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc +6 -2
- data/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc +35 -87
- data/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc +18 -74
- data/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h +167 -217
- data/src/core/ext/filters/client_channel/lb_policy/xds/xds.cc +216 -190
- data/src/core/ext/filters/client_channel/lb_policy/xds/xds_load_balancer_api.cc +6 -2
- data/src/core/ext/filters/client_channel/lb_policy_factory.h +1 -1
- data/src/core/ext/filters/client_channel/lb_policy_registry.cc +1 -1
- data/src/core/ext/filters/client_channel/lb_policy_registry.h +1 -1
- data/src/core/ext/filters/client_channel/resolver.h +1 -1
- data/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc +6 -3
- data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc +0 -1
- data/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc +2 -0
- data/src/core/ext/filters/client_channel/resolver_result_parsing.cc +8 -8
- data/src/core/ext/filters/client_channel/resolver_result_parsing.h +7 -7
- data/src/core/ext/filters/client_channel/resolving_lb_policy.cc +28 -64
- data/src/core/ext/filters/client_channel/resolving_lb_policy.h +4 -12
- data/src/core/ext/filters/client_channel/server_address.cc +4 -6
- data/src/core/ext/filters/client_channel/server_address.h +1 -3
- data/src/core/ext/filters/client_channel/service_config.cc +20 -22
- data/src/core/ext/filters/client_channel/service_config.h +26 -28
- data/src/core/ext/filters/client_channel/subchannel.cc +261 -160
- data/src/core/ext/filters/client_channel/subchannel.h +97 -23
- data/src/core/ext/filters/client_channel/subchannel_interface.h +113 -0
- data/src/core/ext/filters/message_size/message_size_filter.cc +12 -12
- data/src/core/ext/filters/message_size/message_size_filter.h +2 -2
- data/src/core/ext/transport/chttp2/server/chttp2_server.cc +50 -2
- data/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +2 -2
- data/src/core/ext/transport/chttp2/transport/frame_data.cc +31 -36
- data/src/core/ext/transport/chttp2/transport/frame_rst_stream.cc +3 -2
- data/src/core/ext/transport/chttp2/transport/hpack_encoder.cc +71 -52
- data/src/core/ext/transport/chttp2/transport/hpack_parser.cc +18 -3
- data/src/core/ext/transport/chttp2/transport/hpack_table.cc +5 -12
- data/src/core/ext/transport/chttp2/transport/hpack_table.h +10 -1
- data/src/core/ext/transport/chttp2/transport/internal.h +3 -3
- data/src/core/ext/transport/chttp2/transport/parsing.cc +39 -57
- data/src/core/lib/channel/channelz.cc +136 -19
- data/src/core/lib/channel/channelz.h +36 -40
- data/src/core/lib/channel/channelz_registry.cc +74 -106
- data/src/core/lib/channel/channelz_registry.h +10 -28
- data/src/core/lib/channel/context.h +1 -1
- data/src/core/lib/channel/handshaker.cc +6 -0
- data/src/core/lib/compression/compression.cc +13 -8
- data/src/core/lib/compression/compression_internal.cc +14 -10
- data/src/core/lib/compression/compression_internal.h +1 -1
- data/src/core/lib/compression/stream_compression.cc +3 -2
- data/src/core/lib/compression/stream_compression.h +2 -2
- data/src/core/lib/compression/stream_compression_gzip.cc +9 -9
- data/src/core/lib/gpr/env.h +1 -1
- data/src/core/lib/gpr/string.cc +8 -1
- data/src/core/lib/gpr/string.h +6 -1
- data/src/core/lib/gprpp/fork.cc +1 -1
- data/src/core/lib/gprpp/fork.h +5 -1
- data/src/core/lib/gprpp/global_config.h +9 -0
- data/src/core/lib/gprpp/global_config_custom.h +1 -1
- data/src/core/lib/gprpp/inlined_vector.h +8 -0
- data/src/core/lib/gprpp/map.h +38 -21
- data/src/core/lib/gprpp/memory.h +2 -2
- data/src/core/lib/gprpp/orphanable.h +1 -1
- data/src/core/lib/gprpp/ref_counted.h +9 -4
- data/src/core/lib/http/httpcli.cc +3 -3
- data/src/core/lib/iomgr/buffer_list.h +1 -1
- data/src/core/lib/iomgr/call_combiner.cc +1 -1
- data/src/core/lib/iomgr/call_combiner.h +1 -1
- data/src/core/lib/iomgr/cfstream_handle.cc +3 -2
- data/src/core/lib/iomgr/cfstream_handle.h +4 -0
- data/src/core/lib/iomgr/error.cc +3 -3
- data/src/core/lib/iomgr/error.h +9 -3
- data/src/core/lib/iomgr/error_internal.h +1 -1
- data/src/core/lib/iomgr/ev_epoll1_linux.cc +1 -1
- data/src/core/lib/iomgr/ev_posix.cc +3 -3
- data/src/core/lib/iomgr/ev_posix.h +3 -2
- data/src/core/lib/iomgr/ev_windows.cc +2 -2
- data/src/core/lib/iomgr/iomgr.cc +4 -4
- data/src/core/lib/iomgr/lockfree_event.cc +1 -1
- data/src/core/lib/iomgr/port.h +5 -1
- data/src/core/lib/iomgr/tcp_posix.cc +1 -3
- data/src/core/lib/iomgr/tcp_server.cc +5 -0
- data/src/core/lib/iomgr/tcp_server.h +24 -0
- data/src/core/lib/iomgr/tcp_server_custom.cc +11 -9
- data/src/core/lib/iomgr/tcp_server_posix.cc +72 -11
- data/src/core/lib/iomgr/tcp_server_utils_posix.h +3 -0
- data/src/core/lib/iomgr/tcp_server_windows.cc +11 -9
- data/src/core/lib/iomgr/tcp_uv.cc +5 -6
- data/src/core/lib/iomgr/timer.h +2 -1
- data/src/core/lib/iomgr/udp_server.cc +2 -2
- data/src/core/lib/security/credentials/plugin/plugin_credentials.cc +1 -1
- data/src/core/lib/security/credentials/ssl/ssl_credentials.cc +20 -2
- data/src/core/lib/security/credentials/ssl/ssl_credentials.h +2 -2
- data/src/core/lib/security/security_connector/security_connector.h +1 -1
- data/src/core/lib/security/security_connector/ssl/ssl_security_connector.cc +1 -1
- data/src/core/lib/security/transport/auth_filters.h +3 -0
- data/src/core/lib/security/transport/client_auth_filter.cc +13 -0
- data/src/core/lib/security/transport/security_handshaker.cc +7 -7
- data/src/core/lib/slice/b64.h +2 -2
- data/src/core/lib/slice/slice.cc +82 -10
- data/src/core/lib/slice/slice_buffer.cc +49 -21
- data/src/core/lib/slice/slice_hash_table.h +2 -2
- data/src/core/lib/slice/slice_intern.cc +15 -16
- data/src/core/lib/slice/slice_internal.h +52 -0
- data/src/core/lib/slice/slice_string_helpers.cc +10 -1
- data/src/core/lib/slice/slice_string_helpers.h +3 -1
- data/src/core/lib/slice/slice_utils.h +50 -0
- data/src/core/lib/slice/slice_weak_hash_table.h +2 -2
- data/src/core/lib/surface/call.cc +14 -8
- data/src/core/lib/surface/channel.cc +89 -97
- data/src/core/lib/surface/channel.h +60 -6
- data/src/core/lib/surface/completion_queue.cc +49 -36
- data/src/core/lib/surface/completion_queue.h +2 -1
- data/src/core/lib/surface/server.cc +8 -8
- data/src/core/lib/surface/validate_metadata.cc +14 -8
- data/src/core/lib/surface/validate_metadata.h +13 -2
- data/src/core/lib/surface/version.cc +1 -1
- data/src/core/lib/transport/metadata.cc +56 -26
- data/src/core/lib/transport/metadata.h +91 -75
- data/src/core/lib/transport/static_metadata.cc +262 -176
- data/src/core/lib/transport/static_metadata.h +272 -180
- data/src/core/lib/transport/transport.cc +1 -1
- data/src/core/lib/transport/transport.h +8 -2
- data/src/core/tsi/alts/handshaker/alts_shared_resource.h +1 -1
- data/src/ruby/ext/grpc/rb_grpc_imports.generated.c +2 -0
- data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +5 -2
- data/src/ruby/lib/grpc/version.rb +1 -1
- 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
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
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
|
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
|
-
|
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::
|
104
|
+
grpc_error* ServiceConfig::ParseJsonMethodConfigToServiceConfigVectorTable(
|
105
105
|
const grpc_json* json,
|
106
|
-
SliceHashTable<const
|
107
|
-
|
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
|
-
|
118
|
+
parsed_method_config_vectors_storage_.push_back(std::move(objs_vector));
|
120
119
|
const auto* vector_ptr =
|
121
|
-
|
122
|
-
[
|
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
|
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
|
-
|
192
|
-
|
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 =
|
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
|
-
|
210
|
-
SliceHashTable<const
|
211
|
-
|
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::
|
291
|
-
ServiceConfig::
|
292
|
-
if (
|
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 =
|
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 =
|
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
|
-
|
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_->
|
105
|
+
service_config_->GetMethodParsedConfigVector(path);
|
106
106
|
}
|
107
107
|
}
|
108
108
|
|
109
109
|
ServiceConfig* service_config() { return service_config_.get(); }
|
110
110
|
|
111
|
-
ParsedConfig*
|
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*
|
118
|
-
return service_config_->
|
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
|
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
|
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*
|
139
|
-
GPR_DEBUG_ASSERT(index <
|
140
|
-
return
|
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
|
144
|
-
/// path.
|
145
|
-
/// the lifetime of the ServiceConfig object.
|
146
|
-
const
|
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
|
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*
|
182
|
+
grpc_error* ParseJsonMethodConfigToServiceConfigVectorTable(
|
184
183
|
const grpc_json* json,
|
185
|
-
SliceHashTable<const
|
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
|
-
|
194
|
-
// A map from the method name to the
|
195
|
-
//
|
196
|
-
//
|
197
|
-
RefCountedPtr<SliceHashTable<const
|
198
|
-
|
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
|
-
//
|
201
|
-
InlinedVector<UniquePtr<
|
202
|
-
|
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
|
-
:
|
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 (
|
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->
|
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
|
-
|
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
|
-
|
362
|
+
return; // So we don't delete ourself below.
|
399
363
|
}
|
400
364
|
}
|
401
365
|
}
|
402
|
-
// Don't
|
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
|
-
|
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<
|
497
|
+
auto* self = static_cast<HealthWatcher*>(arg);
|
409
498
|
Subchannel* c = self->subchannel_;
|
410
499
|
{
|
411
500
|
MutexLock lock(&c->mu_);
|
412
|
-
if (self->
|
501
|
+
if (self->state_ != GRPC_CHANNEL_SHUTDOWN &&
|
413
502
|
self->health_check_client_ != nullptr) {
|
414
|
-
|
415
|
-
|
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->
|
420
|
-
|
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
|
-
|
512
|
+
self->Unref();
|
426
513
|
}
|
427
514
|
|
428
515
|
Subchannel* subchannel_;
|
429
|
-
|
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
|
519
|
+
grpc_connectivity_state state_;
|
520
|
+
ConnectivityStateWatcherList watcher_list_;
|
435
521
|
};
|
436
522
|
|
437
523
|
//
|
438
|
-
// Subchannel::
|
524
|
+
// Subchannel::HealthWatcherMap
|
439
525
|
//
|
440
526
|
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
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
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
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
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
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::
|
711
|
-
|
712
|
-
|
713
|
-
|
714
|
-
grpc_connectivity_state state
|
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::
|
719
|
-
|
720
|
-
|
721
|
-
|
722
|
-
|
723
|
-
|
724
|
-
|
725
|
-
|
726
|
-
|
727
|
-
|
728
|
-
|
729
|
-
|
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
|
-
|
735
|
-
|
736
|
-
|
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
|
-
|
822
|
-
|
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
|
-
|
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
|
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
|
-
|
986
|
-
|
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
|
-
|
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 (
|
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);
|