grpc 1.18.0 → 1.19.0.pre1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of grpc might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/Makefile +301 -33
- data/include/grpc/grpc_security.h +195 -0
- data/include/grpc/impl/codegen/grpc_types.h +17 -1
- data/include/grpc/impl/codegen/port_platform.h +36 -0
- data/include/grpc/impl/codegen/slice.h +1 -1
- data/src/core/ext/filters/client_channel/channel_connectivity.cc +2 -0
- data/src/core/ext/filters/client_channel/client_channel.cc +74 -69
- data/src/core/ext/filters/client_channel/client_channel.h +2 -2
- data/src/core/ext/filters/client_channel/client_channel_channelz.cc +5 -6
- data/src/core/ext/filters/client_channel/client_channel_channelz.h +5 -4
- data/src/core/ext/filters/client_channel/client_channel_factory.cc +2 -2
- data/src/core/ext/filters/client_channel/client_channel_factory.h +4 -4
- data/src/core/ext/filters/client_channel/client_channel_plugin.cc +3 -3
- data/src/core/ext/filters/client_channel/global_subchannel_pool.cc +176 -0
- data/src/core/ext/filters/client_channel/global_subchannel_pool.h +68 -0
- data/src/core/ext/filters/client_channel/health/health_check_client.cc +10 -8
- data/src/core/ext/filters/client_channel/health/health_check_client.h +1 -1
- data/src/core/ext/filters/client_channel/http_connect_handshaker.cc +146 -156
- data/src/core/ext/filters/client_channel/lb_policy.cc +30 -1
- data/src/core/ext/filters/client_channel/lb_policy.h +29 -1
- data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc +28 -30
- data/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc +5 -8
- data/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc +5 -8
- data/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h +23 -24
- data/src/core/ext/filters/client_channel/lb_policy/xds/xds.cc +80 -15
- data/src/core/ext/filters/client_channel/lb_policy_factory.h +6 -1
- data/src/core/ext/filters/client_channel/lb_policy_registry.cc +2 -2
- data/src/core/ext/filters/client_channel/lb_policy_registry.h +1 -1
- data/src/core/ext/filters/client_channel/local_subchannel_pool.cc +96 -0
- data/src/core/ext/filters/client_channel/local_subchannel_pool.h +56 -0
- data/src/core/ext/filters/client_channel/parse_address.cc +24 -5
- data/src/core/ext/filters/client_channel/request_routing.cc +13 -3
- data/src/core/ext/filters/client_channel/request_routing.h +5 -1
- data/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc +11 -6
- data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc +2 -2
- data/src/core/ext/filters/client_channel/resolver_result_parsing.cc +7 -35
- data/src/core/ext/filters/client_channel/subchannel.cc +698 -791
- data/src/core/ext/filters/client_channel/subchannel.h +213 -123
- data/src/core/ext/filters/client_channel/subchannel_pool_interface.cc +97 -0
- data/src/core/ext/filters/client_channel/subchannel_pool_interface.h +94 -0
- data/src/core/ext/filters/http/client_authority_filter.cc +5 -2
- data/src/core/ext/filters/max_age/max_age_filter.cc +1 -1
- data/src/core/ext/transport/chttp2/client/chttp2_connector.cc +13 -12
- data/src/core/ext/transport/chttp2/client/insecure/channel_create.cc +5 -7
- data/src/core/ext/transport/chttp2/client/secure/secure_channel_create.cc +19 -27
- data/src/core/ext/transport/chttp2/server/chttp2_server.cc +18 -19
- data/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +27 -6
- data/src/core/ext/transport/chttp2/transport/flow_control.cc +1 -1
- data/src/core/ext/transport/chttp2/transport/frame_window_update.cc +3 -2
- data/src/core/ext/transport/chttp2/transport/hpack_encoder.cc +1 -1
- data/src/core/ext/transport/chttp2/transport/writing.cc +8 -5
- data/src/core/lib/channel/handshaker.cc +141 -214
- data/src/core/lib/channel/handshaker.h +110 -101
- data/src/core/lib/channel/handshaker_factory.h +11 -19
- data/src/core/lib/channel/handshaker_registry.cc +64 -52
- data/src/core/lib/channel/handshaker_registry.h +21 -16
- data/src/core/lib/gpr/log_posix.cc +2 -1
- data/src/core/lib/gpr/time.cc +8 -0
- data/src/core/lib/gpr/time_posix.cc +8 -2
- data/src/core/lib/gprpp/optional.h +47 -0
- data/src/core/lib/http/httpcli_security_connector.cc +13 -14
- data/src/core/lib/iomgr/buffer_list.cc +182 -24
- data/src/core/lib/iomgr/buffer_list.h +70 -8
- data/src/core/lib/iomgr/combiner.cc +11 -3
- data/src/core/lib/iomgr/error.cc +9 -5
- data/src/core/lib/iomgr/ev_epoll1_linux.cc +3 -0
- data/src/core/lib/iomgr/ev_epollex_linux.cc +136 -162
- data/src/core/lib/iomgr/ev_poll_posix.cc +3 -0
- data/src/core/lib/iomgr/ev_posix.cc +4 -0
- data/src/core/lib/iomgr/ev_posix.h +4 -0
- data/src/core/lib/iomgr/exec_ctx.cc +1 -0
- data/src/core/lib/iomgr/exec_ctx.h +137 -8
- data/src/core/lib/iomgr/executor.cc +122 -87
- data/src/core/lib/iomgr/executor.h +53 -48
- data/src/core/lib/iomgr/fork_posix.cc +6 -4
- data/src/core/lib/iomgr/{network_status_tracker.cc → grpc_if_nametoindex.h} +8 -14
- data/src/core/lib/iomgr/grpc_if_nametoindex_posix.cc +42 -0
- data/src/core/lib/iomgr/{network_status_tracker.h → grpc_if_nametoindex_unsupported.cc} +15 -9
- data/src/core/lib/iomgr/internal_errqueue.h +105 -3
- data/src/core/lib/iomgr/iomgr.cc +6 -5
- data/src/core/lib/iomgr/iomgr.h +8 -0
- data/src/core/lib/iomgr/iomgr_custom.cc +6 -2
- data/src/core/lib/iomgr/iomgr_internal.cc +4 -0
- data/src/core/lib/iomgr/iomgr_internal.h +4 -0
- data/src/core/lib/iomgr/iomgr_posix.cc +10 -1
- data/src/core/lib/iomgr/iomgr_windows.cc +8 -1
- data/src/core/lib/iomgr/port.h +1 -0
- data/src/core/lib/iomgr/resolve_address_posix.cc +4 -3
- data/src/core/lib/iomgr/resolve_address_windows.cc +2 -1
- data/src/core/lib/iomgr/tcp_custom.cc +0 -4
- data/src/core/lib/iomgr/tcp_posix.cc +58 -44
- data/src/core/lib/iomgr/tcp_uv.cc +0 -1
- data/src/core/lib/iomgr/tcp_windows.cc +0 -4
- data/src/core/lib/iomgr/timer_manager.cc +8 -0
- data/src/core/lib/iomgr/udp_server.cc +6 -4
- data/src/core/lib/json/json.cc +1 -4
- data/src/core/lib/security/credentials/alts/alts_credentials.cc +1 -1
- data/src/core/lib/security/credentials/alts/check_gcp_environment_no_op.cc +2 -2
- data/src/core/lib/security/credentials/composite/composite_credentials.h +4 -0
- data/src/core/lib/security/credentials/credentials.h +9 -1
- data/src/core/lib/security/credentials/google_default/google_default_credentials.cc +15 -2
- data/src/core/lib/security/credentials/google_default/google_default_credentials.h +2 -0
- data/src/core/lib/security/credentials/jwt/json_token.cc +1 -1
- data/src/core/lib/security/credentials/jwt/jwt_credentials.cc +1 -0
- data/src/core/lib/security/credentials/jwt/jwt_verifier.cc +3 -2
- data/src/core/lib/security/credentials/oauth2/oauth2_credentials.cc +2 -2
- data/src/core/lib/security/credentials/plugin/plugin_credentials.cc +1 -0
- data/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc +192 -0
- data/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h +213 -0
- data/src/core/lib/security/security_connector/alts/alts_security_connector.cc +10 -8
- data/src/core/lib/security/security_connector/fake/fake_security_connector.cc +6 -10
- data/src/core/lib/security/security_connector/local/local_security_connector.cc +10 -8
- data/src/core/lib/security/security_connector/security_connector.h +2 -2
- data/src/core/lib/security/security_connector/ssl/ssl_security_connector.cc +4 -6
- data/src/core/lib/security/security_connector/ssl_utils.h +33 -0
- data/src/core/lib/security/transport/security_handshaker.cc +267 -300
- data/src/core/lib/security/transport/security_handshaker.h +11 -2
- data/src/core/lib/security/transport/server_auth_filter.cc +1 -0
- data/src/core/lib/surface/call.cc +5 -1
- data/src/core/lib/surface/channel_init.h +5 -0
- data/src/core/lib/surface/completion_queue.cc +4 -7
- data/src/core/lib/surface/init.cc +5 -3
- data/src/core/lib/surface/init_secure.cc +1 -1
- data/src/core/lib/surface/server.cc +19 -17
- data/src/core/lib/surface/version.cc +1 -1
- data/src/core/lib/transport/service_config.h +1 -0
- data/src/core/lib/transport/static_metadata.cc +279 -279
- data/src/core/lib/transport/transport.cc +5 -3
- data/src/core/tsi/ssl_transport_security.cc +10 -4
- data/src/ruby/ext/grpc/extconf.rb +12 -4
- data/src/ruby/ext/grpc/rb_call_credentials.c +8 -5
- data/src/ruby/ext/grpc/rb_channel.c +14 -10
- data/src/ruby/ext/grpc/rb_channel_credentials.c +8 -4
- data/src/ruby/ext/grpc/rb_compression_options.c +9 -7
- data/src/ruby/ext/grpc/rb_event_thread.c +2 -0
- data/src/ruby/ext/grpc/rb_grpc.c +22 -23
- data/src/ruby/ext/grpc/rb_grpc.h +4 -2
- data/src/ruby/ext/grpc/rb_grpc_imports.generated.c +18 -0
- data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +27 -0
- data/src/ruby/ext/grpc/rb_server.c +8 -4
- data/src/ruby/lib/grpc/version.rb +1 -1
- metadata +46 -39
- data/src/core/ext/filters/client_channel/subchannel_index.cc +0 -248
- data/src/core/ext/filters/client_channel/subchannel_index.h +0 -76
- data/src/core/lib/channel/handshaker_factory.cc +0 -42
@@ -32,8 +32,10 @@
|
|
32
32
|
#include <grpc/support/sync.h>
|
33
33
|
|
34
34
|
#include "src/core/ext/filters/client_channel/backup_poller.h"
|
35
|
+
#include "src/core/ext/filters/client_channel/global_subchannel_pool.h"
|
35
36
|
#include "src/core/ext/filters/client_channel/http_connect_handshaker.h"
|
36
37
|
#include "src/core/ext/filters/client_channel/lb_policy_registry.h"
|
38
|
+
#include "src/core/ext/filters/client_channel/local_subchannel_pool.h"
|
37
39
|
#include "src/core/ext/filters/client_channel/proxy_mapper_registry.h"
|
38
40
|
#include "src/core/ext/filters/client_channel/resolver_registry.h"
|
39
41
|
#include "src/core/ext/filters/client_channel/retry_throttle.h"
|
@@ -517,6 +519,14 @@ RequestRouter::RequestRouter(
|
|
517
519
|
tracer_(tracer),
|
518
520
|
process_resolver_result_(process_resolver_result),
|
519
521
|
process_resolver_result_user_data_(process_resolver_result_user_data) {
|
522
|
+
// Get subchannel pool.
|
523
|
+
const grpc_arg* arg =
|
524
|
+
grpc_channel_args_find(args, GRPC_ARG_USE_LOCAL_SUBCHANNEL_POOL);
|
525
|
+
if (grpc_channel_arg_get_bool(arg, false)) {
|
526
|
+
subchannel_pool_ = MakeRefCounted<LocalSubchannelPool>();
|
527
|
+
} else {
|
528
|
+
subchannel_pool_ = GlobalSubchannelPool::instance();
|
529
|
+
}
|
520
530
|
GRPC_CLOSURE_INIT(&on_resolver_result_changed_,
|
521
531
|
&RequestRouter::OnResolverResultChangedLocked, this,
|
522
532
|
grpc_combiner_scheduler(combiner));
|
@@ -666,6 +676,7 @@ void RequestRouter::CreateNewLbPolicyLocked(
|
|
666
676
|
LoadBalancingPolicy::Args lb_policy_args;
|
667
677
|
lb_policy_args.combiner = combiner_;
|
668
678
|
lb_policy_args.client_channel_factory = client_channel_factory_;
|
679
|
+
lb_policy_args.subchannel_pool = subchannel_pool_;
|
669
680
|
lb_policy_args.args = resolver_result_;
|
670
681
|
lb_policy_args.lb_config = lb_config;
|
671
682
|
OrphanablePtr<LoadBalancingPolicy> new_lb_policy =
|
@@ -751,9 +762,8 @@ void RequestRouter::ConcatenateAndAddChannelTraceLocked(
|
|
751
762
|
char* flat;
|
752
763
|
size_t flat_len = 0;
|
753
764
|
flat = gpr_strvec_flatten(&v, &flat_len);
|
754
|
-
channelz_node_->AddTraceEvent(
|
755
|
-
|
756
|
-
grpc_slice_new(flat, flat_len, gpr_free));
|
765
|
+
channelz_node_->AddTraceEvent(channelz::ChannelTrace::Severity::Info,
|
766
|
+
grpc_slice_new(flat, flat_len, gpr_free));
|
757
767
|
gpr_strvec_destroy(&v);
|
758
768
|
}
|
759
769
|
}
|
@@ -25,6 +25,7 @@
|
|
25
25
|
#include "src/core/ext/filters/client_channel/client_channel_factory.h"
|
26
26
|
#include "src/core/ext/filters/client_channel/lb_policy.h"
|
27
27
|
#include "src/core/ext/filters/client_channel/resolver.h"
|
28
|
+
#include "src/core/ext/filters/client_channel/subchannel_pool_interface.h"
|
28
29
|
#include "src/core/lib/channel/channel_args.h"
|
29
30
|
#include "src/core/lib/channel/channel_stack.h"
|
30
31
|
#include "src/core/lib/debug/trace.h"
|
@@ -126,7 +127,7 @@ class RequestRouter {
|
|
126
127
|
LoadBalancingPolicy* lb_policy() const { return lb_policy_.get(); }
|
127
128
|
|
128
129
|
private:
|
129
|
-
using TraceStringVector =
|
130
|
+
using TraceStringVector = InlinedVector<char*, 3>;
|
130
131
|
|
131
132
|
class ReresolutionRequestHandler;
|
132
133
|
class LbConnectivityWatcher;
|
@@ -169,6 +170,9 @@ class RequestRouter {
|
|
169
170
|
OrphanablePtr<LoadBalancingPolicy> lb_policy_;
|
170
171
|
bool exit_idle_when_lb_policy_arrives_ = false;
|
171
172
|
|
173
|
+
// Subchannel pool to pass to LB policy.
|
174
|
+
RefCountedPtr<SubchannelPoolInterface> subchannel_pool_;
|
175
|
+
|
172
176
|
grpc_connectivity_state_tracker state_tracker_;
|
173
177
|
};
|
174
178
|
|
@@ -125,6 +125,8 @@ class AresDnsResolver : public Resolver {
|
|
125
125
|
bool shutdown_initiated_ = false;
|
126
126
|
// timeout in milliseconds for active DNS queries
|
127
127
|
int query_timeout_ms_;
|
128
|
+
// whether or not to enable SRV DNS queries
|
129
|
+
bool enable_srv_queries_;
|
128
130
|
};
|
129
131
|
|
130
132
|
AresDnsResolver::AresDnsResolver(const ResolverArgs& args)
|
@@ -146,14 +148,18 @@ AresDnsResolver::AresDnsResolver(const ResolverArgs& args)
|
|
146
148
|
dns_server_ = gpr_strdup(args.uri->authority);
|
147
149
|
}
|
148
150
|
channel_args_ = grpc_channel_args_copy(args.args);
|
151
|
+
// Disable service config option
|
149
152
|
const grpc_arg* arg = grpc_channel_args_find(
|
150
153
|
channel_args_, GRPC_ARG_SERVICE_CONFIG_DISABLE_RESOLUTION);
|
151
|
-
|
152
|
-
|
154
|
+
request_service_config_ = !grpc_channel_arg_get_bool(arg, true);
|
155
|
+
// Min time b/t resolutions option
|
153
156
|
arg = grpc_channel_args_find(channel_args_,
|
154
157
|
GRPC_ARG_DNS_MIN_TIME_BETWEEN_RESOLUTIONS_MS);
|
155
158
|
min_time_between_resolutions_ =
|
156
159
|
grpc_channel_arg_get_integer(arg, {1000, 0, INT_MAX});
|
160
|
+
// Enable SRV queries option
|
161
|
+
arg = grpc_channel_args_find(channel_args_, GRPC_ARG_DNS_ENABLE_SRV_QUERIES);
|
162
|
+
enable_srv_queries_ = grpc_channel_arg_get_bool(arg, false);
|
157
163
|
interested_parties_ = grpc_pollset_set_create();
|
158
164
|
if (args.pollset_set != nullptr) {
|
159
165
|
grpc_pollset_set_add_pollset_set(interested_parties_, args.pollset_set);
|
@@ -419,7 +425,7 @@ void AresDnsResolver::StartResolvingLocked() {
|
|
419
425
|
service_config_json_ = nullptr;
|
420
426
|
pending_request_ = grpc_dns_lookup_ares_locked(
|
421
427
|
dns_server_, name_to_resolve_, kDefaultPort, interested_parties_,
|
422
|
-
&on_resolved_, &addresses_,
|
428
|
+
&on_resolved_, &addresses_, enable_srv_queries_ /* check_grpclb */,
|
423
429
|
request_service_config_ ? &service_config_json_ : nullptr,
|
424
430
|
query_timeout_ms_, combiner());
|
425
431
|
last_resolution_timestamp_ = grpc_core::ExecCtx::Get()->Now();
|
@@ -472,13 +478,12 @@ static grpc_address_resolver_vtable ares_resolver = {
|
|
472
478
|
grpc_resolve_address_ares, blocking_resolve_address_ares};
|
473
479
|
|
474
480
|
static bool should_use_ares(const char* resolver_env) {
|
475
|
-
return resolver_env
|
481
|
+
return resolver_env == nullptr || strlen(resolver_env) == 0 ||
|
482
|
+
gpr_stricmp(resolver_env, "ares") == 0;
|
476
483
|
}
|
477
484
|
|
478
485
|
void grpc_resolver_dns_ares_init() {
|
479
486
|
char* resolver_env = gpr_getenv("GRPC_DNS_RESOLVER");
|
480
|
-
/* TODO(zyc): Turn on c-ares based resolver by default after the address
|
481
|
-
sorter and the CNAME support are added. */
|
482
487
|
if (should_use_ares(resolver_env)) {
|
483
488
|
gpr_log(GPR_DEBUG, "Using ares dns resolver");
|
484
489
|
address_sorting_init();
|
@@ -548,13 +548,13 @@ static grpc_ares_request* grpc_dns_lookup_ares_locked_impl(
|
|
548
548
|
r, name, default_port);
|
549
549
|
// Early out if the target is an ipv4 or ipv6 literal.
|
550
550
|
if (resolve_as_ip_literal_locked(name, default_port, addrs)) {
|
551
|
-
|
551
|
+
grpc_ares_complete_request_locked(r);
|
552
552
|
return r;
|
553
553
|
}
|
554
554
|
// Early out if the target is localhost and we're on Windows.
|
555
555
|
if (grpc_ares_maybe_resolve_localhost_manually_locked(name, default_port,
|
556
556
|
addrs)) {
|
557
|
-
|
557
|
+
grpc_ares_complete_request_locked(r);
|
558
558
|
return r;
|
559
559
|
}
|
560
560
|
// Don't query for SRV and TXT records if the target is "localhost", so
|
@@ -141,42 +141,14 @@ void ProcessedResolverResult::ParseServiceConfig(
|
|
141
141
|
void ProcessedResolverResult::ParseLbConfigFromServiceConfig(
|
142
142
|
const grpc_json* field) {
|
143
143
|
if (lb_policy_config_ != nullptr) return; // Already found.
|
144
|
-
|
145
|
-
|
146
|
-
field->type != GRPC_JSON_ARRAY) {
|
147
|
-
return; // Not valid lb config array.
|
144
|
+
if (field->key == nullptr || strcmp(field->key, "loadBalancingConfig") != 0) {
|
145
|
+
return; // Not the LB config global parameter.
|
148
146
|
}
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
grpc_json* policy = nullptr;
|
155
|
-
for (grpc_json* field = lb_config->child; field != nullptr;
|
156
|
-
field = field->next) {
|
157
|
-
if (field->key == nullptr || strcmp(field->key, "policy") != 0 ||
|
158
|
-
field->type != GRPC_JSON_OBJECT) {
|
159
|
-
return;
|
160
|
-
}
|
161
|
-
if (policy != nullptr) return; // Duplicate.
|
162
|
-
policy = field;
|
163
|
-
}
|
164
|
-
// Find the specific policy content since the policy object is of type
|
165
|
-
// "oneof".
|
166
|
-
grpc_json* policy_content = nullptr;
|
167
|
-
for (grpc_json* field = policy->child; field != nullptr;
|
168
|
-
field = field->next) {
|
169
|
-
if (field->key == nullptr || field->type != GRPC_JSON_OBJECT) return;
|
170
|
-
if (policy_content != nullptr) return; // Violate "oneof" type.
|
171
|
-
policy_content = field;
|
172
|
-
}
|
173
|
-
// If we support this policy, then select it.
|
174
|
-
if (grpc_core::LoadBalancingPolicyRegistry::LoadBalancingPolicyExists(
|
175
|
-
policy_content->key)) {
|
176
|
-
lb_policy_name_.reset(gpr_strdup(policy_content->key));
|
177
|
-
lb_policy_config_ = policy_content->child;
|
178
|
-
return;
|
179
|
-
}
|
147
|
+
const grpc_json* policy =
|
148
|
+
LoadBalancingPolicy::ParseLoadBalancingConfig(field);
|
149
|
+
if (policy != nullptr) {
|
150
|
+
lb_policy_name_.reset(gpr_strdup(policy->key));
|
151
|
+
lb_policy_config_ = policy->child;
|
180
152
|
}
|
181
153
|
}
|
182
154
|
|
@@ -33,7 +33,7 @@
|
|
33
33
|
#include "src/core/ext/filters/client_channel/health/health_check_client.h"
|
34
34
|
#include "src/core/ext/filters/client_channel/parse_address.h"
|
35
35
|
#include "src/core/ext/filters/client_channel/proxy_mapper_registry.h"
|
36
|
-
#include "src/core/ext/filters/client_channel/
|
36
|
+
#include "src/core/ext/filters/client_channel/subchannel_pool_interface.h"
|
37
37
|
#include "src/core/lib/backoff/backoff.h"
|
38
38
|
#include "src/core/lib/channel/channel_args.h"
|
39
39
|
#include "src/core/lib/channel/connected_channel.h"
|
@@ -44,7 +44,6 @@
|
|
44
44
|
#include "src/core/lib/gprpp/mutex_lock.h"
|
45
45
|
#include "src/core/lib/gprpp/ref_counted_ptr.h"
|
46
46
|
#include "src/core/lib/iomgr/sockaddr_utils.h"
|
47
|
-
#include "src/core/lib/iomgr/timer.h"
|
48
47
|
#include "src/core/lib/profiling/timers.h"
|
49
48
|
#include "src/core/lib/slice/slice_internal.h"
|
50
49
|
#include "src/core/lib/surface/channel.h"
|
@@ -55,165 +54,260 @@
|
|
55
54
|
#include "src/core/lib/transport/status_metadata.h"
|
56
55
|
#include "src/core/lib/uri/uri_parser.h"
|
57
56
|
|
57
|
+
// Strong and weak refs.
|
58
58
|
#define INTERNAL_REF_BITS 16
|
59
59
|
#define STRONG_REF_MASK (~(gpr_atm)((1 << INTERNAL_REF_BITS) - 1))
|
60
60
|
|
61
|
+
// Backoff parameters.
|
61
62
|
#define GRPC_SUBCHANNEL_INITIAL_CONNECT_BACKOFF_SECONDS 1
|
62
63
|
#define GRPC_SUBCHANNEL_RECONNECT_BACKOFF_MULTIPLIER 1.6
|
63
64
|
#define GRPC_SUBCHANNEL_RECONNECT_MIN_TIMEOUT_SECONDS 20
|
64
65
|
#define GRPC_SUBCHANNEL_RECONNECT_MAX_BACKOFF_SECONDS 120
|
65
66
|
#define GRPC_SUBCHANNEL_RECONNECT_JITTER 0.2
|
66
67
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
grpc_closure health_check_closure;
|
75
|
-
grpc_connectivity_state health_state;
|
76
|
-
};
|
77
|
-
} // namespace
|
78
|
-
|
79
|
-
typedef struct external_state_watcher {
|
80
|
-
grpc_subchannel* subchannel;
|
81
|
-
grpc_pollset_set* pollset_set;
|
82
|
-
grpc_closure* notify;
|
83
|
-
grpc_closure closure;
|
84
|
-
struct external_state_watcher* next;
|
85
|
-
struct external_state_watcher* prev;
|
86
|
-
} external_state_watcher;
|
68
|
+
// Conversion between subchannel call and call stack.
|
69
|
+
#define SUBCHANNEL_CALL_TO_CALL_STACK(call) \
|
70
|
+
(grpc_call_stack*)((char*)(call) + \
|
71
|
+
GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(SubchannelCall)))
|
72
|
+
#define CALL_STACK_TO_SUBCHANNEL_CALL(callstack) \
|
73
|
+
(SubchannelCall*)(((char*)(call_stack)) - \
|
74
|
+
GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(SubchannelCall)))
|
87
75
|
|
88
76
|
namespace grpc_core {
|
89
77
|
|
90
|
-
|
78
|
+
//
|
79
|
+
// ConnectedSubchannel
|
80
|
+
//
|
91
81
|
|
92
|
-
|
82
|
+
ConnectedSubchannel::ConnectedSubchannel(
|
83
|
+
grpc_channel_stack* channel_stack, const grpc_channel_args* args,
|
84
|
+
RefCountedPtr<channelz::SubchannelNode> channelz_subchannel,
|
85
|
+
intptr_t socket_uuid)
|
86
|
+
: RefCounted<ConnectedSubchannel>(&grpc_trace_stream_refcount),
|
87
|
+
channel_stack_(channel_stack),
|
88
|
+
args_(grpc_channel_args_copy(args)),
|
89
|
+
channelz_subchannel_(std::move(channelz_subchannel)),
|
90
|
+
socket_uuid_(socket_uuid) {}
|
93
91
|
|
94
|
-
|
95
|
-
|
92
|
+
ConnectedSubchannel::~ConnectedSubchannel() {
|
93
|
+
grpc_channel_args_destroy(args_);
|
94
|
+
GRPC_CHANNEL_STACK_UNREF(channel_stack_, "connected_subchannel_dtor");
|
95
|
+
}
|
96
96
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
97
|
+
void ConnectedSubchannel::NotifyOnStateChange(
|
98
|
+
grpc_pollset_set* interested_parties, grpc_connectivity_state* state,
|
99
|
+
grpc_closure* closure) {
|
100
|
+
grpc_transport_op* op = grpc_make_transport_op(nullptr);
|
101
|
+
grpc_channel_element* elem;
|
102
|
+
op->connectivity_state = state;
|
103
|
+
op->on_connectivity_state_change = closure;
|
104
|
+
op->bind_pollset_set = interested_parties;
|
105
|
+
elem = grpc_channel_stack_element(channel_stack_, 0);
|
106
|
+
elem->filter->start_transport_op(elem, op);
|
107
|
+
}
|
103
108
|
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
+
void ConnectedSubchannel::Ping(grpc_closure* on_initiate,
|
110
|
+
grpc_closure* on_ack) {
|
111
|
+
grpc_transport_op* op = grpc_make_transport_op(nullptr);
|
112
|
+
grpc_channel_element* elem;
|
113
|
+
op->send_ping.on_initiate = on_initiate;
|
114
|
+
op->send_ping.on_ack = on_ack;
|
115
|
+
elem = grpc_channel_stack_element(channel_stack_, 0);
|
116
|
+
elem->filter->start_transport_op(elem, op);
|
117
|
+
}
|
109
118
|
|
110
|
-
|
119
|
+
RefCountedPtr<SubchannelCall> ConnectedSubchannel::CreateCall(
|
120
|
+
const CallArgs& args, grpc_error** error) {
|
121
|
+
const size_t allocation_size =
|
122
|
+
GetInitialCallSizeEstimate(args.parent_data_size);
|
123
|
+
RefCountedPtr<SubchannelCall> call(
|
124
|
+
new (gpr_arena_alloc(args.arena, allocation_size))
|
125
|
+
SubchannelCall(Ref(DEBUG_LOCATION, "subchannel_call"), args));
|
126
|
+
grpc_call_stack* callstk = SUBCHANNEL_CALL_TO_CALL_STACK(call.get());
|
127
|
+
const grpc_call_element_args call_args = {
|
128
|
+
callstk, /* call_stack */
|
129
|
+
nullptr, /* server_transport_data */
|
130
|
+
args.context, /* context */
|
131
|
+
args.path, /* path */
|
132
|
+
args.start_time, /* start_time */
|
133
|
+
args.deadline, /* deadline */
|
134
|
+
args.arena, /* arena */
|
135
|
+
args.call_combiner /* call_combiner */
|
136
|
+
};
|
137
|
+
*error = grpc_call_stack_init(channel_stack_, 1, SubchannelCall::Destroy,
|
138
|
+
call.get(), &call_args);
|
139
|
+
if (GPR_UNLIKELY(*error != GRPC_ERROR_NONE)) {
|
140
|
+
const char* error_string = grpc_error_string(*error);
|
141
|
+
gpr_log(GPR_ERROR, "error: %s", error_string);
|
142
|
+
return call;
|
143
|
+
}
|
144
|
+
grpc_call_stack_set_pollset_or_pollset_set(callstk, args.pollent);
|
145
|
+
if (channelz_subchannel_ != nullptr) {
|
146
|
+
channelz_subchannel_->RecordCallStarted();
|
147
|
+
}
|
148
|
+
return call;
|
149
|
+
}
|
111
150
|
|
112
|
-
|
113
|
-
|
151
|
+
size_t ConnectedSubchannel::GetInitialCallSizeEstimate(
|
152
|
+
size_t parent_data_size) const {
|
153
|
+
size_t allocation_size =
|
154
|
+
GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(SubchannelCall));
|
155
|
+
if (parent_data_size > 0) {
|
156
|
+
allocation_size +=
|
157
|
+
GPR_ROUND_UP_TO_ALIGNMENT_SIZE(channel_stack_->call_stack_size) +
|
158
|
+
parent_data_size;
|
159
|
+
} else {
|
160
|
+
allocation_size += channel_stack_->call_stack_size;
|
161
|
+
}
|
162
|
+
return allocation_size;
|
163
|
+
}
|
114
164
|
|
115
|
-
|
116
|
-
|
165
|
+
//
|
166
|
+
// SubchannelCall
|
167
|
+
//
|
117
168
|
|
118
|
-
|
119
|
-
|
169
|
+
void SubchannelCall::StartTransportStreamOpBatch(
|
170
|
+
grpc_transport_stream_op_batch* batch) {
|
171
|
+
GPR_TIMER_SCOPE("subchannel_call_process_op", 0);
|
172
|
+
MaybeInterceptRecvTrailingMetadata(batch);
|
173
|
+
grpc_call_stack* call_stack = SUBCHANNEL_CALL_TO_CALL_STACK(this);
|
174
|
+
grpc_call_element* top_elem = grpc_call_stack_element(call_stack, 0);
|
175
|
+
GRPC_CALL_LOG_OP(GPR_INFO, top_elem, batch);
|
176
|
+
top_elem->filter->start_transport_stream_op_batch(top_elem, batch);
|
177
|
+
}
|
120
178
|
|
121
|
-
|
122
|
-
|
123
|
-
|
179
|
+
void* SubchannelCall::GetParentData() {
|
180
|
+
grpc_channel_stack* chanstk = connected_subchannel_->channel_stack();
|
181
|
+
return (char*)this + GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(SubchannelCall)) +
|
182
|
+
GPR_ROUND_UP_TO_ALIGNMENT_SIZE(chanstk->call_stack_size);
|
183
|
+
}
|
124
184
|
|
125
|
-
|
185
|
+
grpc_call_stack* SubchannelCall::GetCallStack() {
|
186
|
+
return SUBCHANNEL_CALL_TO_CALL_STACK(this);
|
187
|
+
}
|
126
188
|
|
127
|
-
|
128
|
-
|
189
|
+
void SubchannelCall::SetAfterCallStackDestroy(grpc_closure* closure) {
|
190
|
+
GPR_ASSERT(after_call_stack_destroy_ == nullptr);
|
191
|
+
GPR_ASSERT(closure != nullptr);
|
192
|
+
after_call_stack_destroy_ = closure;
|
193
|
+
}
|
129
194
|
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
195
|
+
RefCountedPtr<SubchannelCall> SubchannelCall::Ref() {
|
196
|
+
IncrementRefCount();
|
197
|
+
return RefCountedPtr<SubchannelCall>(this);
|
198
|
+
}
|
134
199
|
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
200
|
+
RefCountedPtr<SubchannelCall> SubchannelCall::Ref(
|
201
|
+
const grpc_core::DebugLocation& location, const char* reason) {
|
202
|
+
IncrementRefCount(location, reason);
|
203
|
+
return RefCountedPtr<SubchannelCall>(this);
|
204
|
+
}
|
139
205
|
|
140
|
-
|
141
|
-
|
142
|
-
|
206
|
+
void SubchannelCall::Unref() {
|
207
|
+
GRPC_CALL_STACK_UNREF(SUBCHANNEL_CALL_TO_CALL_STACK(this), "");
|
208
|
+
}
|
143
209
|
|
144
|
-
|
210
|
+
void SubchannelCall::Unref(const DebugLocation& location, const char* reason) {
|
211
|
+
GRPC_CALL_STACK_UNREF(SUBCHANNEL_CALL_TO_CALL_STACK(this), reason);
|
212
|
+
}
|
145
213
|
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
214
|
+
void SubchannelCall::Destroy(void* arg, grpc_error* error) {
|
215
|
+
GPR_TIMER_SCOPE("subchannel_call_destroy", 0);
|
216
|
+
SubchannelCall* self = static_cast<SubchannelCall*>(arg);
|
217
|
+
// Keep some members before destroying the subchannel call.
|
218
|
+
grpc_closure* after_call_stack_destroy = self->after_call_stack_destroy_;
|
219
|
+
RefCountedPtr<ConnectedSubchannel> connected_subchannel =
|
220
|
+
std::move(self->connected_subchannel_);
|
221
|
+
// Destroy the subchannel call.
|
222
|
+
self->~SubchannelCall();
|
223
|
+
// Destroy the call stack. This should be after destroying the subchannel
|
224
|
+
// call, because call->after_call_stack_destroy(), if not null, will free the
|
225
|
+
// call arena.
|
226
|
+
grpc_call_stack_destroy(SUBCHANNEL_CALL_TO_CALL_STACK(self), nullptr,
|
227
|
+
after_call_stack_destroy);
|
228
|
+
// Automatically reset connected_subchannel. This should be after destroying
|
229
|
+
// the call stack, because destroying call stack needs access to the channel
|
230
|
+
// stack.
|
231
|
+
}
|
150
232
|
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
233
|
+
void SubchannelCall::MaybeInterceptRecvTrailingMetadata(
|
234
|
+
grpc_transport_stream_op_batch* batch) {
|
235
|
+
// only intercept payloads with recv trailing.
|
236
|
+
if (!batch->recv_trailing_metadata) {
|
237
|
+
return;
|
238
|
+
}
|
239
|
+
// only add interceptor is channelz is enabled.
|
240
|
+
if (connected_subchannel_->channelz_subchannel() == nullptr) {
|
241
|
+
return;
|
242
|
+
}
|
243
|
+
GRPC_CLOSURE_INIT(&recv_trailing_metadata_ready_, RecvTrailingMetadataReady,
|
244
|
+
this, grpc_schedule_on_exec_ctx);
|
245
|
+
// save some state needed for the interception callback.
|
246
|
+
GPR_ASSERT(recv_trailing_metadata_ == nullptr);
|
247
|
+
recv_trailing_metadata_ =
|
248
|
+
batch->payload->recv_trailing_metadata.recv_trailing_metadata;
|
249
|
+
original_recv_trailing_metadata_ =
|
250
|
+
batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready;
|
251
|
+
batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready =
|
252
|
+
&recv_trailing_metadata_ready_;
|
253
|
+
}
|
159
254
|
|
160
|
-
|
161
|
-
channelz_subchannel;
|
162
|
-
};
|
255
|
+
namespace {
|
163
256
|
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
}
|
257
|
+
// Sets *status based on the rest of the parameters.
|
258
|
+
void GetCallStatus(grpc_status_code* status, grpc_millis deadline,
|
259
|
+
grpc_metadata_batch* md_batch, grpc_error* error) {
|
260
|
+
if (error != GRPC_ERROR_NONE) {
|
261
|
+
grpc_error_get_status(error, deadline, status, nullptr, nullptr, nullptr);
|
262
|
+
} else {
|
263
|
+
if (md_batch->idx.named.grpc_status != nullptr) {
|
264
|
+
*status = grpc_get_status_code_from_metadata(
|
265
|
+
md_batch->idx.named.grpc_status->md);
|
266
|
+
} else {
|
267
|
+
*status = GRPC_STATUS_UNKNOWN;
|
268
|
+
}
|
269
|
+
}
|
270
|
+
GRPC_ERROR_UNREF(error);
|
271
|
+
}
|
177
272
|
|
178
|
-
|
273
|
+
} // namespace
|
179
274
|
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
275
|
+
void SubchannelCall::RecvTrailingMetadataReady(void* arg, grpc_error* error) {
|
276
|
+
SubchannelCall* call = static_cast<SubchannelCall*>(arg);
|
277
|
+
GPR_ASSERT(call->recv_trailing_metadata_ != nullptr);
|
278
|
+
grpc_status_code status = GRPC_STATUS_OK;
|
279
|
+
GetCallStatus(&status, call->deadline_, call->recv_trailing_metadata_,
|
280
|
+
GRPC_ERROR_REF(error));
|
281
|
+
channelz::SubchannelNode* channelz_subchannel =
|
282
|
+
call->connected_subchannel_->channelz_subchannel();
|
283
|
+
GPR_ASSERT(channelz_subchannel != nullptr);
|
284
|
+
if (status == GRPC_STATUS_OK) {
|
285
|
+
channelz_subchannel->RecordCallSucceeded();
|
286
|
+
} else {
|
287
|
+
channelz_subchannel->RecordCallFailed();
|
193
288
|
}
|
194
|
-
|
289
|
+
GRPC_CLOSURE_RUN(call->original_recv_trailing_metadata_,
|
290
|
+
GRPC_ERROR_REF(error));
|
195
291
|
}
|
196
292
|
|
197
|
-
|
198
|
-
|
199
|
-
const char* reason) {
|
200
|
-
if (c->channelz_subchannel != nullptr) {
|
201
|
-
c->channelz_subchannel->AddTraceEvent(
|
202
|
-
grpc_core::channelz::ChannelTrace::Severity::Info,
|
203
|
-
grpc_slice_from_static_string(
|
204
|
-
subchannel_connectivity_state_change_string(state)));
|
205
|
-
}
|
206
|
-
grpc_connectivity_state_set(&c->state_tracker, state, error, reason);
|
293
|
+
void SubchannelCall::IncrementRefCount() {
|
294
|
+
GRPC_CALL_STACK_REF(SUBCHANNEL_CALL_TO_CALL_STACK(this), "");
|
207
295
|
}
|
208
296
|
|
209
|
-
|
297
|
+
void SubchannelCall::IncrementRefCount(const grpc_core::DebugLocation& location,
|
298
|
+
const char* reason) {
|
299
|
+
GRPC_CALL_STACK_REF(SUBCHANNEL_CALL_TO_CALL_STACK(this), reason);
|
300
|
+
}
|
301
|
+
|
302
|
+
//
|
303
|
+
// Subchannel::ConnectedSubchannelStateWatcher
|
304
|
+
//
|
210
305
|
|
211
|
-
class ConnectedSubchannelStateWatcher
|
306
|
+
class Subchannel::ConnectedSubchannelStateWatcher
|
212
307
|
: public InternallyRefCounted<ConnectedSubchannelStateWatcher> {
|
213
308
|
public:
|
214
309
|
// Must be instantiated while holding c->mu.
|
215
|
-
explicit ConnectedSubchannelStateWatcher(
|
216
|
-
: subchannel_(c) {
|
310
|
+
explicit ConnectedSubchannelStateWatcher(Subchannel* c) : subchannel_(c) {
|
217
311
|
// Steal subchannel ref for connecting.
|
218
312
|
GRPC_SUBCHANNEL_WEAK_REF(subchannel_, "state_watcher");
|
219
313
|
GRPC_SUBCHANNEL_WEAK_UNREF(subchannel_, "connecting");
|
@@ -221,15 +315,15 @@ class ConnectedSubchannelStateWatcher
|
|
221
315
|
// Callback uses initial ref to this.
|
222
316
|
GRPC_CLOSURE_INIT(&on_connectivity_changed_, OnConnectivityChanged, this,
|
223
317
|
grpc_schedule_on_exec_ctx);
|
224
|
-
c->
|
225
|
-
|
226
|
-
|
318
|
+
c->connected_subchannel_->NotifyOnStateChange(c->pollset_set_,
|
319
|
+
&pending_connectivity_state_,
|
320
|
+
&on_connectivity_changed_);
|
227
321
|
// Start health check if needed.
|
228
322
|
grpc_connectivity_state health_state = GRPC_CHANNEL_READY;
|
229
|
-
if (c->
|
230
|
-
health_check_client_ =
|
231
|
-
c->
|
232
|
-
c->
|
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_);
|
233
327
|
GRPC_CLOSURE_INIT(&on_health_changed_, OnHealthChanged, this,
|
234
328
|
grpc_schedule_on_exec_ctx);
|
235
329
|
Ref().release(); // Ref for health callback tracked manually.
|
@@ -238,9 +332,9 @@ class ConnectedSubchannelStateWatcher
|
|
238
332
|
health_state = GRPC_CHANNEL_CONNECTING;
|
239
333
|
}
|
240
334
|
// Report initial state.
|
241
|
-
|
242
|
-
|
243
|
-
grpc_connectivity_state_set(&c->
|
335
|
+
c->SetConnectivityStateLocked(GRPC_CHANNEL_READY, GRPC_ERROR_NONE,
|
336
|
+
"subchannel_connected");
|
337
|
+
grpc_connectivity_state_set(&c->state_and_health_tracker_, health_state,
|
244
338
|
GRPC_ERROR_NONE, "subchannel_connected");
|
245
339
|
}
|
246
340
|
|
@@ -248,38 +342,39 @@ class ConnectedSubchannelStateWatcher
|
|
248
342
|
GRPC_SUBCHANNEL_WEAK_UNREF(subchannel_, "state_watcher");
|
249
343
|
}
|
250
344
|
|
345
|
+
// Must be called while holding subchannel_->mu.
|
251
346
|
void Orphan() override { health_check_client_.reset(); }
|
252
347
|
|
253
348
|
private:
|
254
349
|
static void OnConnectivityChanged(void* arg, grpc_error* error) {
|
255
350
|
auto* self = static_cast<ConnectedSubchannelStateWatcher*>(arg);
|
256
|
-
|
351
|
+
Subchannel* c = self->subchannel_;
|
257
352
|
{
|
258
|
-
MutexLock lock(&c->
|
353
|
+
MutexLock lock(&c->mu_);
|
259
354
|
switch (self->pending_connectivity_state_) {
|
260
355
|
case GRPC_CHANNEL_TRANSIENT_FAILURE:
|
261
356
|
case GRPC_CHANNEL_SHUTDOWN: {
|
262
|
-
if (!c->
|
357
|
+
if (!c->disconnected_ && c->connected_subchannel_ != nullptr) {
|
263
358
|
if (grpc_trace_stream_refcount.enabled()) {
|
264
359
|
gpr_log(GPR_INFO,
|
265
360
|
"Connected subchannel %p of subchannel %p has gone into "
|
266
361
|
"%s. Attempting to reconnect.",
|
267
|
-
c->
|
362
|
+
c->connected_subchannel_.get(), c,
|
268
363
|
grpc_connectivity_state_name(
|
269
364
|
self->pending_connectivity_state_));
|
270
365
|
}
|
271
|
-
c->
|
272
|
-
c->
|
366
|
+
c->connected_subchannel_.reset();
|
367
|
+
c->connected_subchannel_watcher_.reset();
|
273
368
|
self->last_connectivity_state_ = GRPC_CHANNEL_TRANSIENT_FAILURE;
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
grpc_connectivity_state_set(&c->
|
369
|
+
c->SetConnectivityStateLocked(GRPC_CHANNEL_TRANSIENT_FAILURE,
|
370
|
+
GRPC_ERROR_REF(error),
|
371
|
+
"reflect_child");
|
372
|
+
grpc_connectivity_state_set(&c->state_and_health_tracker_,
|
278
373
|
GRPC_CHANNEL_TRANSIENT_FAILURE,
|
279
374
|
GRPC_ERROR_REF(error), "reflect_child");
|
280
|
-
c->
|
281
|
-
c->
|
282
|
-
|
375
|
+
c->backoff_begun_ = false;
|
376
|
+
c->backoff_.Reset();
|
377
|
+
c->MaybeStartConnectingLocked();
|
283
378
|
} else {
|
284
379
|
self->last_connectivity_state_ = GRPC_CHANNEL_SHUTDOWN;
|
285
380
|
}
|
@@ -292,15 +387,14 @@ class ConnectedSubchannelStateWatcher
|
|
292
387
|
// this watch from. And a connected subchannel should never go
|
293
388
|
// from READY to CONNECTING or IDLE.
|
294
389
|
self->last_connectivity_state_ = self->pending_connectivity_state_;
|
295
|
-
|
296
|
-
|
297
|
-
"reflect_child");
|
390
|
+
c->SetConnectivityStateLocked(self->pending_connectivity_state_,
|
391
|
+
GRPC_ERROR_REF(error), "reflect_child");
|
298
392
|
if (self->pending_connectivity_state_ != GRPC_CHANNEL_READY) {
|
299
|
-
grpc_connectivity_state_set(&c->
|
393
|
+
grpc_connectivity_state_set(&c->state_and_health_tracker_,
|
300
394
|
self->pending_connectivity_state_,
|
301
395
|
GRPC_ERROR_REF(error), "reflect_child");
|
302
396
|
}
|
303
|
-
c->
|
397
|
+
c->connected_subchannel_->NotifyOnStateChange(
|
304
398
|
nullptr, &self->pending_connectivity_state_,
|
305
399
|
&self->on_connectivity_changed_);
|
306
400
|
self = nullptr; // So we don't unref below.
|
@@ -314,174 +408,83 @@ class ConnectedSubchannelStateWatcher
|
|
314
408
|
|
315
409
|
static void OnHealthChanged(void* arg, grpc_error* error) {
|
316
410
|
auto* self = static_cast<ConnectedSubchannelStateWatcher*>(arg);
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
411
|
+
Subchannel* c = self->subchannel_;
|
412
|
+
{
|
413
|
+
MutexLock lock(&c->mu_);
|
414
|
+
if (self->health_state_ != GRPC_CHANNEL_SHUTDOWN &&
|
415
|
+
self->health_check_client_ != nullptr) {
|
416
|
+
if (self->last_connectivity_state_ == GRPC_CHANNEL_READY) {
|
417
|
+
grpc_connectivity_state_set(&c->state_and_health_tracker_,
|
418
|
+
self->health_state_,
|
419
|
+
GRPC_ERROR_REF(error), "health_changed");
|
420
|
+
}
|
421
|
+
self->health_check_client_->NotifyOnHealthChange(
|
422
|
+
&self->health_state_, &self->on_health_changed_);
|
423
|
+
self = nullptr; // So we don't unref below.
|
424
|
+
}
|
327
425
|
}
|
328
|
-
|
329
|
-
|
426
|
+
// Don't unref until we've released the lock, because this might
|
427
|
+
// cause the subchannel (which contains the lock) to be destroyed.
|
428
|
+
if (self != nullptr) self->Unref();
|
330
429
|
}
|
331
430
|
|
332
|
-
|
431
|
+
Subchannel* subchannel_;
|
333
432
|
grpc_closure on_connectivity_changed_;
|
334
433
|
grpc_connectivity_state pending_connectivity_state_ = GRPC_CHANNEL_READY;
|
335
434
|
grpc_connectivity_state last_connectivity_state_ = GRPC_CHANNEL_READY;
|
336
|
-
|
435
|
+
OrphanablePtr<HealthCheckClient> health_check_client_;
|
337
436
|
grpc_closure on_health_changed_;
|
338
437
|
grpc_connectivity_state health_state_ = GRPC_CHANNEL_CONNECTING;
|
339
438
|
};
|
340
439
|
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
(grpc_call_stack*)((char*)(call) + GPR_ROUND_UP_TO_ALIGNMENT_SIZE( \
|
345
|
-
sizeof(grpc_subchannel_call)))
|
346
|
-
#define CALLSTACK_TO_SUBCHANNEL_CALL(callstack) \
|
347
|
-
(grpc_subchannel_call*)(((char*)(call_stack)) - \
|
348
|
-
GPR_ROUND_UP_TO_ALIGNMENT_SIZE( \
|
349
|
-
sizeof(grpc_subchannel_call)))
|
350
|
-
|
351
|
-
static void on_subchannel_connected(void* subchannel, grpc_error* error);
|
352
|
-
|
353
|
-
#ifndef NDEBUG
|
354
|
-
#define REF_REASON reason
|
355
|
-
#define REF_MUTATE_EXTRA_ARGS \
|
356
|
-
GRPC_SUBCHANNEL_REF_EXTRA_ARGS, const char* purpose
|
357
|
-
#define REF_MUTATE_PURPOSE(x) , file, line, reason, x
|
358
|
-
#else
|
359
|
-
#define REF_REASON ""
|
360
|
-
#define REF_MUTATE_EXTRA_ARGS
|
361
|
-
#define REF_MUTATE_PURPOSE(x)
|
362
|
-
#endif
|
363
|
-
|
364
|
-
/*
|
365
|
-
* connection implementation
|
366
|
-
*/
|
367
|
-
|
368
|
-
static void connection_destroy(void* arg, grpc_error* error) {
|
369
|
-
grpc_channel_stack* stk = static_cast<grpc_channel_stack*>(arg);
|
370
|
-
grpc_channel_stack_destroy(stk);
|
371
|
-
gpr_free(stk);
|
372
|
-
}
|
373
|
-
|
374
|
-
/*
|
375
|
-
* grpc_subchannel implementation
|
376
|
-
*/
|
377
|
-
|
378
|
-
static void subchannel_destroy(void* arg, grpc_error* error) {
|
379
|
-
grpc_subchannel* c = static_cast<grpc_subchannel*>(arg);
|
380
|
-
if (c->channelz_subchannel != nullptr) {
|
381
|
-
c->channelz_subchannel->AddTraceEvent(
|
382
|
-
grpc_core::channelz::ChannelTrace::Severity::Info,
|
383
|
-
grpc_slice_from_static_string("Subchannel destroyed"));
|
384
|
-
c->channelz_subchannel->MarkSubchannelDestroyed();
|
385
|
-
c->channelz_subchannel.reset();
|
386
|
-
}
|
387
|
-
gpr_free((void*)c->filters);
|
388
|
-
c->health_check_service_name.reset();
|
389
|
-
grpc_channel_args_destroy(c->args);
|
390
|
-
grpc_connectivity_state_destroy(&c->state_tracker);
|
391
|
-
grpc_connectivity_state_destroy(&c->state_and_health_tracker);
|
392
|
-
grpc_connector_unref(c->connector);
|
393
|
-
grpc_pollset_set_destroy(c->pollset_set);
|
394
|
-
grpc_subchannel_key_destroy(c->key);
|
395
|
-
gpr_mu_destroy(&c->mu);
|
396
|
-
gpr_free(c);
|
397
|
-
}
|
440
|
+
//
|
441
|
+
// Subchannel::ExternalStateWatcher
|
442
|
+
//
|
398
443
|
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
"SUBCHANNEL: %p %12s 0x%" PRIxPTR " -> 0x%" PRIxPTR " [%s]", c,
|
407
|
-
purpose, old_val, old_val + delta, reason);
|
444
|
+
struct Subchannel::ExternalStateWatcher {
|
445
|
+
ExternalStateWatcher(Subchannel* subchannel, grpc_pollset_set* pollset_set,
|
446
|
+
grpc_closure* notify)
|
447
|
+
: subchannel(subchannel), pollset_set(pollset_set), notify(notify) {
|
448
|
+
GRPC_SUBCHANNEL_WEAK_REF(subchannel, "external_state_watcher+init");
|
449
|
+
GRPC_CLOSURE_INIT(&on_state_changed, OnStateChanged, this,
|
450
|
+
grpc_schedule_on_exec_ctx);
|
408
451
|
}
|
409
|
-
#endif
|
410
|
-
return old_val;
|
411
|
-
}
|
412
|
-
|
413
|
-
grpc_subchannel* grpc_subchannel_ref(
|
414
|
-
grpc_subchannel* c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
|
415
|
-
gpr_atm old_refs;
|
416
|
-
old_refs = ref_mutate(c, (1 << INTERNAL_REF_BITS),
|
417
|
-
0 REF_MUTATE_PURPOSE("STRONG_REF"));
|
418
|
-
GPR_ASSERT((old_refs & STRONG_REF_MASK) != 0);
|
419
|
-
return c;
|
420
|
-
}
|
421
|
-
|
422
|
-
grpc_subchannel* grpc_subchannel_weak_ref(
|
423
|
-
grpc_subchannel* c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
|
424
|
-
gpr_atm old_refs;
|
425
|
-
old_refs = ref_mutate(c, 1, 0 REF_MUTATE_PURPOSE("WEAK_REF"));
|
426
|
-
GPR_ASSERT(old_refs != 0);
|
427
|
-
return c;
|
428
|
-
}
|
429
452
|
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
} else {
|
441
|
-
return nullptr;
|
453
|
+
static void OnStateChanged(void* arg, grpc_error* error) {
|
454
|
+
ExternalStateWatcher* w = static_cast<ExternalStateWatcher*>(arg);
|
455
|
+
grpc_closure* follow_up = w->notify;
|
456
|
+
if (w->pollset_set != nullptr) {
|
457
|
+
grpc_pollset_set_del_pollset_set(w->subchannel->pollset_set_,
|
458
|
+
w->pollset_set);
|
459
|
+
}
|
460
|
+
gpr_mu_lock(&w->subchannel->mu_);
|
461
|
+
if (w->subchannel->external_state_watcher_list_ == w) {
|
462
|
+
w->subchannel->external_state_watcher_list_ = w->next;
|
442
463
|
}
|
464
|
+
if (w->next != nullptr) w->next->prev = w->prev;
|
465
|
+
if (w->prev != nullptr) w->prev->next = w->next;
|
466
|
+
gpr_mu_unlock(&w->subchannel->mu_);
|
467
|
+
GRPC_SUBCHANNEL_WEAK_UNREF(w->subchannel, "external_state_watcher+done");
|
468
|
+
Delete(w);
|
469
|
+
GRPC_CLOSURE_SCHED(follow_up, GRPC_ERROR_REF(error));
|
443
470
|
}
|
444
|
-
}
|
445
471
|
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
c->connected_subchannel.reset();
|
454
|
-
c->connected_subchannel_watcher.reset();
|
455
|
-
gpr_mu_unlock(&c->mu);
|
456
|
-
}
|
472
|
+
Subchannel* subchannel;
|
473
|
+
grpc_pollset_set* pollset_set;
|
474
|
+
grpc_closure* notify;
|
475
|
+
grpc_closure on_state_changed;
|
476
|
+
ExternalStateWatcher* next = nullptr;
|
477
|
+
ExternalStateWatcher* prev = nullptr;
|
478
|
+
};
|
457
479
|
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
old_refs = ref_mutate(
|
462
|
-
c, static_cast<gpr_atm>(1) - static_cast<gpr_atm>(1 << INTERNAL_REF_BITS),
|
463
|
-
1 REF_MUTATE_PURPOSE("STRONG_UNREF"));
|
464
|
-
if ((old_refs & STRONG_REF_MASK) == (1 << INTERNAL_REF_BITS)) {
|
465
|
-
disconnect(c);
|
466
|
-
}
|
467
|
-
GRPC_SUBCHANNEL_WEAK_UNREF(c, "strong-unref");
|
468
|
-
}
|
480
|
+
//
|
481
|
+
// Subchannel
|
482
|
+
//
|
469
483
|
|
470
|
-
|
471
|
-
grpc_subchannel* c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
|
472
|
-
gpr_atm old_refs;
|
473
|
-
old_refs = ref_mutate(c, -static_cast<gpr_atm>(1),
|
474
|
-
1 REF_MUTATE_PURPOSE("WEAK_UNREF"));
|
475
|
-
if (old_refs == 1) {
|
476
|
-
GRPC_CLOSURE_SCHED(
|
477
|
-
GRPC_CLOSURE_CREATE(subchannel_destroy, c, grpc_schedule_on_exec_ctx),
|
478
|
-
GRPC_ERROR_NONE);
|
479
|
-
}
|
480
|
-
}
|
484
|
+
namespace {
|
481
485
|
|
482
|
-
|
483
|
-
const grpc_channel_args* args,
|
484
|
-
grpc_millis* min_connect_timeout_ms) {
|
486
|
+
BackOff::Options ParseArgsForBackoffValues(
|
487
|
+
const grpc_channel_args* args, grpc_millis* min_connect_timeout_ms) {
|
485
488
|
grpc_millis initial_backoff_ms =
|
486
489
|
GRPC_SUBCHANNEL_INITIAL_CONNECT_BACKOFF_SECONDS * 1000;
|
487
490
|
*min_connect_timeout_ms =
|
@@ -518,7 +521,8 @@ static void parse_args_for_backoff_values(
|
|
518
521
|
}
|
519
522
|
}
|
520
523
|
}
|
521
|
-
|
524
|
+
return BackOff::Options()
|
525
|
+
.set_initial_backoff(initial_backoff_ms)
|
522
526
|
.set_multiplier(fixed_reconnect_backoff
|
523
527
|
? 1.0
|
524
528
|
: GRPC_SUBCHANNEL_RECONNECT_BACKOFF_MULTIPLIER)
|
@@ -527,9 +531,6 @@ static void parse_args_for_backoff_values(
|
|
527
531
|
.set_max_backoff(max_backoff_ms);
|
528
532
|
}
|
529
533
|
|
530
|
-
namespace grpc_core {
|
531
|
-
namespace {
|
532
|
-
|
533
534
|
struct HealthCheckParams {
|
534
535
|
UniquePtr<char> service_name;
|
535
536
|
|
@@ -550,607 +551,513 @@ struct HealthCheckParams {
|
|
550
551
|
};
|
551
552
|
|
552
553
|
} // namespace
|
553
|
-
} // namespace grpc_core
|
554
|
-
|
555
|
-
grpc_subchannel* grpc_subchannel_create(grpc_connector* connector,
|
556
|
-
const grpc_subchannel_args* args) {
|
557
|
-
grpc_subchannel_key* key = grpc_subchannel_key_create(args);
|
558
|
-
grpc_subchannel* c = grpc_subchannel_index_find(key);
|
559
|
-
if (c) {
|
560
|
-
grpc_subchannel_key_destroy(key);
|
561
|
-
return c;
|
562
|
-
}
|
563
554
|
|
555
|
+
Subchannel::Subchannel(SubchannelKey* key, grpc_connector* connector,
|
556
|
+
const grpc_channel_args* args)
|
557
|
+
: key_(key),
|
558
|
+
connector_(connector),
|
559
|
+
backoff_(ParseArgsForBackoffValues(args, &min_connect_timeout_ms_)) {
|
564
560
|
GRPC_STATS_INC_CLIENT_SUBCHANNELS_CREATED();
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
c->connector = connector;
|
569
|
-
grpc_connector_ref(c->connector);
|
570
|
-
c->num_filters = args->filter_count;
|
571
|
-
if (c->num_filters > 0) {
|
572
|
-
c->filters = static_cast<const grpc_channel_filter**>(
|
573
|
-
gpr_malloc(sizeof(grpc_channel_filter*) * c->num_filters));
|
574
|
-
memcpy((void*)c->filters, args->filters,
|
575
|
-
sizeof(grpc_channel_filter*) * c->num_filters);
|
576
|
-
} else {
|
577
|
-
c->filters = nullptr;
|
578
|
-
}
|
579
|
-
c->pollset_set = grpc_pollset_set_create();
|
561
|
+
gpr_atm_no_barrier_store(&ref_pair_, 1 << INTERNAL_REF_BITS);
|
562
|
+
grpc_connector_ref(connector_);
|
563
|
+
pollset_set_ = grpc_pollset_set_create();
|
580
564
|
grpc_resolved_address* addr =
|
581
565
|
static_cast<grpc_resolved_address*>(gpr_malloc(sizeof(*addr)));
|
582
|
-
|
566
|
+
GetAddressFromSubchannelAddressArg(args, addr);
|
583
567
|
grpc_resolved_address* new_address = nullptr;
|
584
568
|
grpc_channel_args* new_args = nullptr;
|
585
|
-
if (grpc_proxy_mappers_map_address(addr, args
|
586
|
-
&new_args)) {
|
569
|
+
if (grpc_proxy_mappers_map_address(addr, args, &new_address, &new_args)) {
|
587
570
|
GPR_ASSERT(new_address != nullptr);
|
588
571
|
gpr_free(addr);
|
589
572
|
addr = new_address;
|
590
573
|
}
|
591
574
|
static const char* keys_to_remove[] = {GRPC_ARG_SUBCHANNEL_ADDRESS};
|
592
|
-
grpc_arg new_arg =
|
575
|
+
grpc_arg new_arg = CreateSubchannelAddressArg(addr);
|
593
576
|
gpr_free(addr);
|
594
|
-
|
595
|
-
new_args != nullptr ? new_args : args
|
577
|
+
args_ = grpc_channel_args_copy_and_add_and_remove(
|
578
|
+
new_args != nullptr ? new_args : args, keys_to_remove,
|
596
579
|
GPR_ARRAY_SIZE(keys_to_remove), &new_arg, 1);
|
597
580
|
gpr_free(new_arg.value.string);
|
598
581
|
if (new_args != nullptr) grpc_channel_args_destroy(new_args);
|
599
|
-
|
600
|
-
&c->root_external_state_watcher;
|
601
|
-
GRPC_CLOSURE_INIT(&c->on_connected, on_subchannel_connected, c,
|
582
|
+
GRPC_CLOSURE_INIT(&on_connecting_finished_, OnConnectingFinished, this,
|
602
583
|
grpc_schedule_on_exec_ctx);
|
603
|
-
grpc_connectivity_state_init(&
|
584
|
+
grpc_connectivity_state_init(&state_tracker_, GRPC_CHANNEL_IDLE,
|
604
585
|
"subchannel");
|
605
|
-
grpc_connectivity_state_init(&
|
586
|
+
grpc_connectivity_state_init(&state_and_health_tracker_, GRPC_CHANNEL_IDLE,
|
606
587
|
"subchannel");
|
607
|
-
|
608
|
-
parse_args_for_backoff_values(args->args, &backoff_options,
|
609
|
-
&c->min_connect_timeout_ms);
|
610
|
-
c->backoff.Init(backoff_options);
|
611
|
-
gpr_mu_init(&c->mu);
|
612
|
-
|
588
|
+
gpr_mu_init(&mu_);
|
613
589
|
// Check whether we should enable health checking.
|
614
590
|
const char* service_config_json = grpc_channel_arg_get_string(
|
615
|
-
grpc_channel_args_find(
|
591
|
+
grpc_channel_args_find(args_, GRPC_ARG_SERVICE_CONFIG));
|
616
592
|
if (service_config_json != nullptr) {
|
617
|
-
|
618
|
-
|
593
|
+
UniquePtr<ServiceConfig> service_config =
|
594
|
+
ServiceConfig::Create(service_config_json);
|
619
595
|
if (service_config != nullptr) {
|
620
|
-
|
621
|
-
service_config->ParseGlobalParams(
|
622
|
-
|
623
|
-
c->health_check_service_name = std::move(params.service_name);
|
596
|
+
HealthCheckParams params;
|
597
|
+
service_config->ParseGlobalParams(HealthCheckParams::Parse, ¶ms);
|
598
|
+
health_check_service_name_ = std::move(params.service_name);
|
624
599
|
}
|
625
600
|
}
|
626
|
-
|
627
|
-
const
|
628
|
-
grpc_channel_args_find(c->args, GRPC_ARG_ENABLE_CHANNELZ);
|
629
|
-
bool channelz_enabled =
|
601
|
+
const grpc_arg* arg = grpc_channel_args_find(args_, GRPC_ARG_ENABLE_CHANNELZ);
|
602
|
+
const bool channelz_enabled =
|
630
603
|
grpc_channel_arg_get_bool(arg, GRPC_ENABLE_CHANNELZ_DEFAULT);
|
631
604
|
arg = grpc_channel_args_find(
|
632
|
-
|
605
|
+
args_, GRPC_ARG_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE);
|
633
606
|
const grpc_integer_options options = {
|
634
607
|
GRPC_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE_DEFAULT, 0, INT_MAX};
|
635
608
|
size_t channel_tracer_max_memory =
|
636
609
|
(size_t)grpc_channel_arg_get_integer(arg, options);
|
637
610
|
if (channelz_enabled) {
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
grpc_slice_from_static_string("Subchannel created"));
|
611
|
+
channelz_node_ = MakeRefCounted<channelz::SubchannelNode>(
|
612
|
+
this, channel_tracer_max_memory);
|
613
|
+
channelz_node_->AddTraceEvent(
|
614
|
+
channelz::ChannelTrace::Severity::Info,
|
615
|
+
grpc_slice_from_static_string("subchannel created"));
|
644
616
|
}
|
645
|
-
|
646
|
-
return grpc_subchannel_index_register(key, c);
|
647
617
|
}
|
648
618
|
|
649
|
-
|
650
|
-
|
651
|
-
|
619
|
+
Subchannel::~Subchannel() {
|
620
|
+
if (channelz_node_ != nullptr) {
|
621
|
+
channelz_node_->AddTraceEvent(
|
622
|
+
channelz::ChannelTrace::Severity::Info,
|
623
|
+
grpc_slice_from_static_string("Subchannel destroyed"));
|
624
|
+
channelz_node_->MarkSubchannelDestroyed();
|
625
|
+
}
|
626
|
+
grpc_channel_args_destroy(args_);
|
627
|
+
grpc_connectivity_state_destroy(&state_tracker_);
|
628
|
+
grpc_connectivity_state_destroy(&state_and_health_tracker_);
|
629
|
+
grpc_connector_unref(connector_);
|
630
|
+
grpc_pollset_set_destroy(pollset_set_);
|
631
|
+
Delete(key_);
|
632
|
+
gpr_mu_destroy(&mu_);
|
652
633
|
}
|
653
634
|
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
635
|
+
Subchannel* Subchannel::Create(grpc_connector* connector,
|
636
|
+
const grpc_channel_args* args) {
|
637
|
+
SubchannelKey* key = New<SubchannelKey>(args);
|
638
|
+
SubchannelPoolInterface* subchannel_pool =
|
639
|
+
SubchannelPoolInterface::GetSubchannelPoolFromChannelArgs(args);
|
640
|
+
GPR_ASSERT(subchannel_pool != nullptr);
|
641
|
+
Subchannel* c = subchannel_pool->FindSubchannel(key);
|
642
|
+
if (c != nullptr) {
|
643
|
+
Delete(key);
|
644
|
+
return c;
|
659
645
|
}
|
646
|
+
c = New<Subchannel>(key, connector, args);
|
647
|
+
// Try to register the subchannel before setting the subchannel pool.
|
648
|
+
// Otherwise, in case of a registration race, unreffing c in
|
649
|
+
// RegisterSubchannel() will cause c to be tried to be unregistered, while
|
650
|
+
// its key maps to a different subchannel.
|
651
|
+
Subchannel* registered = subchannel_pool->RegisterSubchannel(key, c);
|
652
|
+
if (registered == c) c->subchannel_pool_ = subchannel_pool->Ref();
|
653
|
+
return registered;
|
660
654
|
}
|
661
655
|
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
args.deadline = std::max(c->next_attempt_deadline, min_deadline);
|
669
|
-
args.channel_args = c->args;
|
670
|
-
set_subchannel_connectivity_state_locked(c, GRPC_CHANNEL_CONNECTING,
|
671
|
-
GRPC_ERROR_NONE, "connecting");
|
672
|
-
grpc_connectivity_state_set(&c->state_and_health_tracker,
|
673
|
-
GRPC_CHANNEL_CONNECTING, GRPC_ERROR_NONE,
|
674
|
-
"connecting");
|
675
|
-
grpc_connector_connect(c->connector, &args, &c->connecting_result,
|
676
|
-
&c->on_connected);
|
656
|
+
Subchannel* Subchannel::Ref(GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
|
657
|
+
gpr_atm old_refs;
|
658
|
+
old_refs = RefMutate((1 << INTERNAL_REF_BITS),
|
659
|
+
0 GRPC_SUBCHANNEL_REF_MUTATE_PURPOSE("STRONG_REF"));
|
660
|
+
GPR_ASSERT((old_refs & STRONG_REF_MASK) != 0);
|
661
|
+
return this;
|
677
662
|
}
|
678
663
|
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
686
|
-
|
664
|
+
void Subchannel::Unref(GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
|
665
|
+
gpr_atm old_refs;
|
666
|
+
// add a weak ref and subtract a strong ref (atomically)
|
667
|
+
old_refs = RefMutate(
|
668
|
+
static_cast<gpr_atm>(1) - static_cast<gpr_atm>(1 << INTERNAL_REF_BITS),
|
669
|
+
1 GRPC_SUBCHANNEL_REF_MUTATE_PURPOSE("STRONG_UNREF"));
|
670
|
+
if ((old_refs & STRONG_REF_MASK) == (1 << INTERNAL_REF_BITS)) {
|
671
|
+
Disconnect();
|
672
|
+
}
|
673
|
+
GRPC_SUBCHANNEL_WEAK_UNREF(this, "strong-unref");
|
687
674
|
}
|
688
675
|
|
689
|
-
|
690
|
-
|
691
|
-
|
692
|
-
|
693
|
-
|
694
|
-
w->pollset_set);
|
695
|
-
}
|
696
|
-
gpr_mu_lock(&w->subchannel->mu);
|
697
|
-
w->next->prev = w->prev;
|
698
|
-
w->prev->next = w->next;
|
699
|
-
gpr_mu_unlock(&w->subchannel->mu);
|
700
|
-
GRPC_SUBCHANNEL_WEAK_UNREF(w->subchannel, "external_state_watcher");
|
701
|
-
gpr_free(w);
|
702
|
-
GRPC_CLOSURE_SCHED(follow_up, GRPC_ERROR_REF(error));
|
676
|
+
Subchannel* Subchannel::WeakRef(GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
|
677
|
+
gpr_atm old_refs;
|
678
|
+
old_refs = RefMutate(1, 0 GRPC_SUBCHANNEL_REF_MUTATE_PURPOSE("WEAK_REF"));
|
679
|
+
GPR_ASSERT(old_refs != 0);
|
680
|
+
return this;
|
703
681
|
}
|
704
682
|
|
705
|
-
|
706
|
-
|
707
|
-
|
708
|
-
|
709
|
-
|
710
|
-
error = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING("Disconnected",
|
711
|
-
&error, 1);
|
712
|
-
} else if (c->retry_immediately) {
|
713
|
-
c->retry_immediately = false;
|
714
|
-
error = GRPC_ERROR_NONE;
|
715
|
-
} else {
|
716
|
-
GRPC_ERROR_REF(error);
|
717
|
-
}
|
718
|
-
if (error == GRPC_ERROR_NONE) {
|
719
|
-
gpr_log(GPR_INFO, "Failed to connect to channel, retrying");
|
720
|
-
continue_connect_locked(c);
|
721
|
-
gpr_mu_unlock(&c->mu);
|
722
|
-
} else {
|
723
|
-
gpr_mu_unlock(&c->mu);
|
724
|
-
GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting");
|
725
|
-
}
|
726
|
-
GRPC_ERROR_UNREF(error);
|
683
|
+
namespace {
|
684
|
+
|
685
|
+
void subchannel_destroy(void* arg, grpc_error* error) {
|
686
|
+
Subchannel* self = static_cast<Subchannel*>(arg);
|
687
|
+
Delete(self);
|
727
688
|
}
|
728
689
|
|
729
|
-
|
730
|
-
|
731
|
-
|
732
|
-
|
733
|
-
|
734
|
-
|
735
|
-
|
736
|
-
|
737
|
-
|
738
|
-
|
739
|
-
/* Already connected: don't restart */
|
740
|
-
return;
|
741
|
-
}
|
742
|
-
if (!grpc_connectivity_state_has_watchers(&c->state_tracker) &&
|
743
|
-
!grpc_connectivity_state_has_watchers(&c->state_and_health_tracker)) {
|
744
|
-
/* Nobody is interested in connecting: so don't just yet */
|
745
|
-
return;
|
746
|
-
}
|
747
|
-
c->connecting = true;
|
748
|
-
GRPC_SUBCHANNEL_WEAK_REF(c, "connecting");
|
749
|
-
if (!c->backoff_begun) {
|
750
|
-
c->backoff_begun = true;
|
751
|
-
continue_connect_locked(c);
|
752
|
-
} else {
|
753
|
-
GPR_ASSERT(!c->have_alarm);
|
754
|
-
c->have_alarm = true;
|
755
|
-
const grpc_millis time_til_next =
|
756
|
-
c->next_attempt_deadline - grpc_core::ExecCtx::Get()->Now();
|
757
|
-
if (time_til_next <= 0) {
|
758
|
-
gpr_log(GPR_INFO, "Subchannel %p: Retry immediately", c);
|
759
|
-
} else {
|
760
|
-
gpr_log(GPR_INFO, "Subchannel %p: Retry in %" PRId64 " milliseconds", c,
|
761
|
-
time_til_next);
|
762
|
-
}
|
763
|
-
GRPC_CLOSURE_INIT(&c->on_alarm, on_alarm, c, grpc_schedule_on_exec_ctx);
|
764
|
-
grpc_timer_init(&c->alarm, c->next_attempt_deadline, &c->on_alarm);
|
690
|
+
} // namespace
|
691
|
+
|
692
|
+
void Subchannel::WeakUnref(GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
|
693
|
+
gpr_atm old_refs;
|
694
|
+
old_refs = RefMutate(-static_cast<gpr_atm>(1),
|
695
|
+
1 GRPC_SUBCHANNEL_REF_MUTATE_PURPOSE("WEAK_UNREF"));
|
696
|
+
if (old_refs == 1) {
|
697
|
+
GRPC_CLOSURE_SCHED(GRPC_CLOSURE_CREATE(subchannel_destroy, this,
|
698
|
+
grpc_schedule_on_exec_ctx),
|
699
|
+
GRPC_ERROR_NONE);
|
765
700
|
}
|
766
701
|
}
|
767
702
|
|
768
|
-
|
769
|
-
|
770
|
-
|
771
|
-
|
772
|
-
|
773
|
-
|
774
|
-
|
775
|
-
if (state == nullptr) {
|
776
|
-
gpr_mu_lock(&c->mu);
|
777
|
-
for (w = c->root_external_state_watcher.next;
|
778
|
-
w != &c->root_external_state_watcher; w = w->next) {
|
779
|
-
if (w->notify == notify) {
|
780
|
-
grpc_connectivity_state_notify_on_state_change(tracker, nullptr,
|
781
|
-
&w->closure);
|
703
|
+
Subchannel* Subchannel::RefFromWeakRef(GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
|
704
|
+
for (;;) {
|
705
|
+
gpr_atm old_refs = gpr_atm_acq_load(&ref_pair_);
|
706
|
+
if (old_refs >= (1 << INTERNAL_REF_BITS)) {
|
707
|
+
gpr_atm new_refs = old_refs + (1 << INTERNAL_REF_BITS);
|
708
|
+
if (gpr_atm_rel_cas(&ref_pair_, old_refs, new_refs)) {
|
709
|
+
return this;
|
782
710
|
}
|
711
|
+
} else {
|
712
|
+
return nullptr;
|
783
713
|
}
|
784
|
-
gpr_mu_unlock(&c->mu);
|
785
|
-
} else {
|
786
|
-
w = static_cast<external_state_watcher*>(gpr_malloc(sizeof(*w)));
|
787
|
-
w->subchannel = c;
|
788
|
-
w->pollset_set = interested_parties;
|
789
|
-
w->notify = notify;
|
790
|
-
GRPC_CLOSURE_INIT(&w->closure, on_external_state_watcher_done, w,
|
791
|
-
grpc_schedule_on_exec_ctx);
|
792
|
-
if (interested_parties != nullptr) {
|
793
|
-
grpc_pollset_set_add_pollset_set(c->pollset_set, interested_parties);
|
794
|
-
}
|
795
|
-
GRPC_SUBCHANNEL_WEAK_REF(c, "external_state_watcher");
|
796
|
-
gpr_mu_lock(&c->mu);
|
797
|
-
w->next = &c->root_external_state_watcher;
|
798
|
-
w->prev = w->next->prev;
|
799
|
-
w->next->prev = w->prev->next = w;
|
800
|
-
grpc_connectivity_state_notify_on_state_change(tracker, state, &w->closure);
|
801
|
-
maybe_start_connecting_locked(c);
|
802
|
-
gpr_mu_unlock(&c->mu);
|
803
|
-
}
|
804
|
-
}
|
805
|
-
|
806
|
-
static bool publish_transport_locked(grpc_subchannel* c) {
|
807
|
-
/* construct channel stack */
|
808
|
-
grpc_channel_stack_builder* builder = grpc_channel_stack_builder_create();
|
809
|
-
grpc_channel_stack_builder_set_channel_arguments(
|
810
|
-
builder, c->connecting_result.channel_args);
|
811
|
-
grpc_channel_stack_builder_set_transport(builder,
|
812
|
-
c->connecting_result.transport);
|
813
|
-
|
814
|
-
if (!grpc_channel_init_create_stack(builder, GRPC_CLIENT_SUBCHANNEL)) {
|
815
|
-
grpc_channel_stack_builder_destroy(builder);
|
816
|
-
return false;
|
817
|
-
}
|
818
|
-
grpc_channel_stack* stk;
|
819
|
-
grpc_error* error = grpc_channel_stack_builder_finish(
|
820
|
-
builder, 0, 1, connection_destroy, nullptr,
|
821
|
-
reinterpret_cast<void**>(&stk));
|
822
|
-
if (error != GRPC_ERROR_NONE) {
|
823
|
-
grpc_transport_destroy(c->connecting_result.transport);
|
824
|
-
gpr_log(GPR_ERROR, "error initializing subchannel stack: %s",
|
825
|
-
grpc_error_string(error));
|
826
|
-
GRPC_ERROR_UNREF(error);
|
827
|
-
return false;
|
828
|
-
}
|
829
|
-
intptr_t socket_uuid = c->connecting_result.socket_uuid;
|
830
|
-
memset(&c->connecting_result, 0, sizeof(c->connecting_result));
|
831
|
-
|
832
|
-
if (c->disconnected) {
|
833
|
-
grpc_channel_stack_destroy(stk);
|
834
|
-
gpr_free(stk);
|
835
|
-
return false;
|
836
|
-
}
|
837
|
-
|
838
|
-
/* publish */
|
839
|
-
c->connected_subchannel.reset(grpc_core::New<grpc_core::ConnectedSubchannel>(
|
840
|
-
stk, c->args, c->channelz_subchannel, socket_uuid));
|
841
|
-
gpr_log(GPR_INFO, "New connected subchannel at %p for subchannel %p",
|
842
|
-
c->connected_subchannel.get(), c);
|
843
|
-
|
844
|
-
// Instantiate state watcher. Will clean itself up.
|
845
|
-
c->connected_subchannel_watcher =
|
846
|
-
grpc_core::MakeOrphanable<grpc_core::ConnectedSubchannelStateWatcher>(c);
|
847
|
-
|
848
|
-
return true;
|
849
|
-
}
|
850
|
-
|
851
|
-
static void on_subchannel_connected(void* arg, grpc_error* error) {
|
852
|
-
grpc_subchannel* c = static_cast<grpc_subchannel*>(arg);
|
853
|
-
grpc_channel_args* delete_channel_args = c->connecting_result.channel_args;
|
854
|
-
|
855
|
-
GRPC_SUBCHANNEL_WEAK_REF(c, "on_subchannel_connected");
|
856
|
-
gpr_mu_lock(&c->mu);
|
857
|
-
c->connecting = false;
|
858
|
-
if (c->connecting_result.transport != nullptr &&
|
859
|
-
publish_transport_locked(c)) {
|
860
|
-
/* do nothing, transport was published */
|
861
|
-
} else if (c->disconnected) {
|
862
|
-
GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting");
|
863
|
-
} else {
|
864
|
-
set_subchannel_connectivity_state_locked(
|
865
|
-
c, GRPC_CHANNEL_TRANSIENT_FAILURE,
|
866
|
-
grpc_error_set_int(GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
|
867
|
-
"Connect Failed", &error, 1),
|
868
|
-
GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE),
|
869
|
-
"connect_failed");
|
870
|
-
grpc_connectivity_state_set(
|
871
|
-
&c->state_and_health_tracker, GRPC_CHANNEL_TRANSIENT_FAILURE,
|
872
|
-
grpc_error_set_int(GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
|
873
|
-
"Connect Failed", &error, 1),
|
874
|
-
GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE),
|
875
|
-
"connect_failed");
|
876
|
-
|
877
|
-
const char* errmsg = grpc_error_string(error);
|
878
|
-
gpr_log(GPR_INFO, "Connect failed: %s", errmsg);
|
879
|
-
|
880
|
-
maybe_start_connecting_locked(c);
|
881
|
-
GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting");
|
882
714
|
}
|
883
|
-
gpr_mu_unlock(&c->mu);
|
884
|
-
GRPC_SUBCHANNEL_WEAK_UNREF(c, "connected");
|
885
|
-
grpc_channel_args_destroy(delete_channel_args);
|
886
715
|
}
|
887
716
|
|
888
|
-
|
889
|
-
|
890
|
-
|
891
|
-
if (subchannel->have_alarm) {
|
892
|
-
subchannel->retry_immediately = true;
|
893
|
-
grpc_timer_cancel(&subchannel->alarm);
|
717
|
+
intptr_t Subchannel::GetChildSocketUuid() {
|
718
|
+
if (connected_subchannel_ != nullptr) {
|
719
|
+
return connected_subchannel_->socket_uuid();
|
894
720
|
} else {
|
895
|
-
|
896
|
-
maybe_start_connecting_locked(subchannel);
|
721
|
+
return 0;
|
897
722
|
}
|
898
|
-
gpr_mu_unlock(&subchannel->mu);
|
899
723
|
}
|
900
724
|
|
901
|
-
|
902
|
-
*
|
903
|
-
|
904
|
-
|
905
|
-
|
906
|
-
|
907
|
-
grpc_subchannel_call* c = static_cast<grpc_subchannel_call*>(call);
|
908
|
-
grpc_core::ConnectedSubchannel* connection = c->connection;
|
909
|
-
grpc_call_stack_destroy(SUBCHANNEL_CALL_TO_CALL_STACK(c), nullptr,
|
910
|
-
c->schedule_closure_after_destroy);
|
911
|
-
connection->Unref(DEBUG_LOCATION, "subchannel_call");
|
912
|
-
c->~grpc_subchannel_call();
|
725
|
+
const char* Subchannel::GetTargetAddress() {
|
726
|
+
const grpc_arg* addr_arg =
|
727
|
+
grpc_channel_args_find(args_, GRPC_ARG_SUBCHANNEL_ADDRESS);
|
728
|
+
const char* addr_str = grpc_channel_arg_get_string(addr_arg);
|
729
|
+
GPR_ASSERT(addr_str != nullptr); // Should have been set by LB policy.
|
730
|
+
return addr_str;
|
913
731
|
}
|
914
732
|
|
915
|
-
|
916
|
-
|
917
|
-
|
918
|
-
GPR_ASSERT(closure != nullptr);
|
919
|
-
call->schedule_closure_after_destroy = closure;
|
733
|
+
RefCountedPtr<ConnectedSubchannel> Subchannel::connected_subchannel() {
|
734
|
+
MutexLock lock(&mu_);
|
735
|
+
return connected_subchannel_;
|
920
736
|
}
|
921
737
|
|
922
|
-
|
923
|
-
|
924
|
-
GRPC_CALL_STACK_REF(SUBCHANNEL_CALL_TO_CALL_STACK(c), REF_REASON);
|
925
|
-
return c;
|
738
|
+
channelz::SubchannelNode* Subchannel::channelz_node() {
|
739
|
+
return channelz_node_.get();
|
926
740
|
}
|
927
741
|
|
928
|
-
|
929
|
-
|
930
|
-
|
742
|
+
grpc_connectivity_state Subchannel::CheckConnectivity(
|
743
|
+
grpc_error** error, bool inhibit_health_checking) {
|
744
|
+
MutexLock lock(&mu_);
|
745
|
+
grpc_connectivity_state_tracker* tracker =
|
746
|
+
inhibit_health_checking ? &state_tracker_ : &state_and_health_tracker_;
|
747
|
+
grpc_connectivity_state state = grpc_connectivity_state_get(tracker, error);
|
748
|
+
return state;
|
931
749
|
}
|
932
750
|
|
933
|
-
|
934
|
-
|
935
|
-
|
936
|
-
|
937
|
-
|
938
|
-
|
939
|
-
|
751
|
+
void Subchannel::NotifyOnStateChange(grpc_pollset_set* interested_parties,
|
752
|
+
grpc_connectivity_state* state,
|
753
|
+
grpc_closure* notify,
|
754
|
+
bool inhibit_health_checking) {
|
755
|
+
grpc_connectivity_state_tracker* tracker =
|
756
|
+
inhibit_health_checking ? &state_tracker_ : &state_and_health_tracker_;
|
757
|
+
ExternalStateWatcher* w;
|
758
|
+
if (state == nullptr) {
|
759
|
+
MutexLock lock(&mu_);
|
760
|
+
for (w = external_state_watcher_list_; w != nullptr; w = w->next) {
|
761
|
+
if (w->notify == notify) {
|
762
|
+
grpc_connectivity_state_notify_on_state_change(tracker, nullptr,
|
763
|
+
&w->on_state_changed);
|
764
|
+
}
|
765
|
+
}
|
940
766
|
} else {
|
941
|
-
|
942
|
-
|
943
|
-
|
944
|
-
} else {
|
945
|
-
*status = GRPC_STATUS_UNKNOWN;
|
767
|
+
w = New<ExternalStateWatcher>(this, interested_parties, notify);
|
768
|
+
if (interested_parties != nullptr) {
|
769
|
+
grpc_pollset_set_add_pollset_set(pollset_set_, interested_parties);
|
946
770
|
}
|
771
|
+
MutexLock lock(&mu_);
|
772
|
+
if (external_state_watcher_list_ != nullptr) {
|
773
|
+
w->next = external_state_watcher_list_;
|
774
|
+
w->next->prev = w;
|
775
|
+
}
|
776
|
+
external_state_watcher_list_ = w;
|
777
|
+
grpc_connectivity_state_notify_on_state_change(tracker, state,
|
778
|
+
&w->on_state_changed);
|
779
|
+
MaybeStartConnectingLocked();
|
947
780
|
}
|
948
|
-
GRPC_ERROR_UNREF(error);
|
949
781
|
}
|
950
782
|
|
951
|
-
|
952
|
-
|
953
|
-
|
954
|
-
|
955
|
-
|
956
|
-
|
957
|
-
grpc_core::channelz::SubchannelNode* channelz_subchannel =
|
958
|
-
call->connection->channelz_subchannel();
|
959
|
-
GPR_ASSERT(channelz_subchannel != nullptr);
|
960
|
-
if (status == GRPC_STATUS_OK) {
|
961
|
-
channelz_subchannel->RecordCallSucceeded();
|
783
|
+
void Subchannel::ResetBackoff() {
|
784
|
+
MutexLock lock(&mu_);
|
785
|
+
backoff_.Reset();
|
786
|
+
if (have_retry_alarm_) {
|
787
|
+
retry_immediately_ = true;
|
788
|
+
grpc_timer_cancel(&retry_alarm_);
|
962
789
|
} else {
|
963
|
-
|
790
|
+
backoff_begun_ = false;
|
791
|
+
MaybeStartConnectingLocked();
|
964
792
|
}
|
965
|
-
GRPC_CLOSURE_RUN(call->original_recv_trailing_metadata,
|
966
|
-
GRPC_ERROR_REF(error));
|
967
793
|
}
|
968
794
|
|
969
|
-
|
970
|
-
|
971
|
-
|
972
|
-
|
973
|
-
|
974
|
-
if (!batch->recv_trailing_metadata) {
|
975
|
-
return;
|
976
|
-
}
|
977
|
-
// only add interceptor is channelz is enabled.
|
978
|
-
if (call->connection->channelz_subchannel() == nullptr) {
|
979
|
-
return;
|
980
|
-
}
|
981
|
-
GRPC_CLOSURE_INIT(&call->recv_trailing_metadata_ready,
|
982
|
-
recv_trailing_metadata_ready, call,
|
983
|
-
grpc_schedule_on_exec_ctx);
|
984
|
-
// save some state needed for the interception callback.
|
985
|
-
GPR_ASSERT(call->recv_trailing_metadata == nullptr);
|
986
|
-
call->recv_trailing_metadata =
|
987
|
-
batch->payload->recv_trailing_metadata.recv_trailing_metadata;
|
988
|
-
call->original_recv_trailing_metadata =
|
989
|
-
batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready;
|
990
|
-
batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready =
|
991
|
-
&call->recv_trailing_metadata_ready;
|
992
|
-
}
|
993
|
-
|
994
|
-
void grpc_subchannel_call_process_op(grpc_subchannel_call* call,
|
995
|
-
grpc_transport_stream_op_batch* batch) {
|
996
|
-
GPR_TIMER_SCOPE("grpc_subchannel_call_process_op", 0);
|
997
|
-
maybe_intercept_recv_trailing_metadata(call, batch);
|
998
|
-
grpc_call_stack* call_stack = SUBCHANNEL_CALL_TO_CALL_STACK(call);
|
999
|
-
grpc_call_element* top_elem = grpc_call_stack_element(call_stack, 0);
|
1000
|
-
GRPC_CALL_LOG_OP(GPR_INFO, top_elem, batch);
|
1001
|
-
top_elem->filter->start_transport_stream_op_batch(top_elem, batch);
|
1002
|
-
}
|
1003
|
-
|
1004
|
-
grpc_core::RefCountedPtr<grpc_core::ConnectedSubchannel>
|
1005
|
-
grpc_subchannel_get_connected_subchannel(grpc_subchannel* c) {
|
1006
|
-
gpr_mu_lock(&c->mu);
|
1007
|
-
auto copy = c->connected_subchannel;
|
1008
|
-
gpr_mu_unlock(&c->mu);
|
1009
|
-
return copy;
|
1010
|
-
}
|
1011
|
-
|
1012
|
-
const grpc_subchannel_key* grpc_subchannel_get_key(
|
1013
|
-
const grpc_subchannel* subchannel) {
|
1014
|
-
return subchannel->key;
|
795
|
+
grpc_arg Subchannel::CreateSubchannelAddressArg(
|
796
|
+
const grpc_resolved_address* addr) {
|
797
|
+
return grpc_channel_arg_string_create(
|
798
|
+
(char*)GRPC_ARG_SUBCHANNEL_ADDRESS,
|
799
|
+
addr->len > 0 ? grpc_sockaddr_to_uri(addr) : gpr_strdup(""));
|
1015
800
|
}
|
1016
801
|
|
1017
|
-
|
1018
|
-
|
1019
|
-
|
1020
|
-
|
1021
|
-
|
802
|
+
const char* Subchannel::GetUriFromSubchannelAddressArg(
|
803
|
+
const grpc_channel_args* args) {
|
804
|
+
const grpc_arg* addr_arg =
|
805
|
+
grpc_channel_args_find(args, GRPC_ARG_SUBCHANNEL_ADDRESS);
|
806
|
+
const char* addr_str = grpc_channel_arg_get_string(addr_arg);
|
807
|
+
GPR_ASSERT(addr_str != nullptr); // Should have been set by LB policy.
|
808
|
+
return addr_str;
|
1022
809
|
}
|
1023
810
|
|
1024
|
-
|
1025
|
-
grpc_subchannel_call* subchannel_call) {
|
1026
|
-
return SUBCHANNEL_CALL_TO_CALL_STACK(subchannel_call);
|
1027
|
-
}
|
811
|
+
namespace {
|
1028
812
|
|
1029
|
-
|
1030
|
-
grpc_resolved_address* addr) {
|
813
|
+
void UriToSockaddr(const char* uri_str, grpc_resolved_address* addr) {
|
1031
814
|
grpc_uri* uri = grpc_uri_parse(uri_str, 0 /* suppress_errors */);
|
1032
815
|
GPR_ASSERT(uri != nullptr);
|
1033
816
|
if (!grpc_parse_uri(uri, addr)) memset(addr, 0, sizeof(*addr));
|
1034
817
|
grpc_uri_destroy(uri);
|
1035
818
|
}
|
1036
819
|
|
1037
|
-
|
1038
|
-
|
1039
|
-
|
820
|
+
} // namespace
|
821
|
+
|
822
|
+
void Subchannel::GetAddressFromSubchannelAddressArg(
|
823
|
+
const grpc_channel_args* args, grpc_resolved_address* addr) {
|
824
|
+
const char* addr_uri_str = GetUriFromSubchannelAddressArg(args);
|
1040
825
|
memset(addr, 0, sizeof(*addr));
|
1041
826
|
if (*addr_uri_str != '\0') {
|
1042
|
-
|
827
|
+
UriToSockaddr(addr_uri_str, addr);
|
1043
828
|
}
|
1044
829
|
}
|
1045
830
|
|
1046
|
-
|
1047
|
-
const grpc_arg* addr_arg =
|
1048
|
-
grpc_channel_args_find(subchannel->args, GRPC_ARG_SUBCHANNEL_ADDRESS);
|
1049
|
-
const char* addr_str = grpc_channel_arg_get_string(addr_arg);
|
1050
|
-
GPR_ASSERT(addr_str != nullptr); // Should have been set by LB policy.
|
1051
|
-
return addr_str;
|
1052
|
-
}
|
831
|
+
namespace {
|
1053
832
|
|
1054
|
-
|
1055
|
-
|
1056
|
-
|
1057
|
-
|
1058
|
-
|
1059
|
-
|
833
|
+
// Returns a string indicating the subchannel's connectivity state change to
|
834
|
+
// \a state.
|
835
|
+
const char* SubchannelConnectivityStateChangeString(
|
836
|
+
grpc_connectivity_state state) {
|
837
|
+
switch (state) {
|
838
|
+
case GRPC_CHANNEL_IDLE:
|
839
|
+
return "Subchannel state change to IDLE";
|
840
|
+
case GRPC_CHANNEL_CONNECTING:
|
841
|
+
return "Subchannel state change to CONNECTING";
|
842
|
+
case GRPC_CHANNEL_READY:
|
843
|
+
return "Subchannel state change to READY";
|
844
|
+
case GRPC_CHANNEL_TRANSIENT_FAILURE:
|
845
|
+
return "Subchannel state change to TRANSIENT_FAILURE";
|
846
|
+
case GRPC_CHANNEL_SHUTDOWN:
|
847
|
+
return "Subchannel state change to SHUTDOWN";
|
848
|
+
}
|
849
|
+
GPR_UNREACHABLE_CODE(return "UNKNOWN");
|
1060
850
|
}
|
1061
851
|
|
1062
|
-
|
1063
|
-
|
1064
|
-
|
1065
|
-
|
852
|
+
} // namespace
|
853
|
+
|
854
|
+
void Subchannel::SetConnectivityStateLocked(grpc_connectivity_state state,
|
855
|
+
grpc_error* error,
|
856
|
+
const char* reason) {
|
857
|
+
if (channelz_node_ != nullptr) {
|
858
|
+
channelz_node_->AddTraceEvent(
|
859
|
+
channelz::ChannelTrace::Severity::Info,
|
860
|
+
grpc_slice_from_static_string(
|
861
|
+
SubchannelConnectivityStateChangeString(state)));
|
862
|
+
}
|
863
|
+
grpc_connectivity_state_set(&state_tracker_, state, error, reason);
|
1066
864
|
}
|
1067
865
|
|
1068
|
-
|
866
|
+
void Subchannel::MaybeStartConnectingLocked() {
|
867
|
+
if (disconnected_) {
|
868
|
+
// Don't try to connect if we're already disconnected.
|
869
|
+
return;
|
870
|
+
}
|
871
|
+
if (connecting_) {
|
872
|
+
// Already connecting: don't restart.
|
873
|
+
return;
|
874
|
+
}
|
875
|
+
if (connected_subchannel_ != nullptr) {
|
876
|
+
// Already connected: don't restart.
|
877
|
+
return;
|
878
|
+
}
|
879
|
+
if (!grpc_connectivity_state_has_watchers(&state_tracker_) &&
|
880
|
+
!grpc_connectivity_state_has_watchers(&state_and_health_tracker_)) {
|
881
|
+
// Nobody is interested in connecting: so don't just yet.
|
882
|
+
return;
|
883
|
+
}
|
884
|
+
connecting_ = true;
|
885
|
+
GRPC_SUBCHANNEL_WEAK_REF(this, "connecting");
|
886
|
+
if (!backoff_begun_) {
|
887
|
+
backoff_begun_ = true;
|
888
|
+
ContinueConnectingLocked();
|
889
|
+
} else {
|
890
|
+
GPR_ASSERT(!have_retry_alarm_);
|
891
|
+
have_retry_alarm_ = true;
|
892
|
+
const grpc_millis time_til_next =
|
893
|
+
next_attempt_deadline_ - ExecCtx::Get()->Now();
|
894
|
+
if (time_til_next <= 0) {
|
895
|
+
gpr_log(GPR_INFO, "Subchannel %p: Retry immediately", this);
|
896
|
+
} else {
|
897
|
+
gpr_log(GPR_INFO, "Subchannel %p: Retry in %" PRId64 " milliseconds",
|
898
|
+
this, time_til_next);
|
899
|
+
}
|
900
|
+
GRPC_CLOSURE_INIT(&on_retry_alarm_, OnRetryAlarm, this,
|
901
|
+
grpc_schedule_on_exec_ctx);
|
902
|
+
grpc_timer_init(&retry_alarm_, next_attempt_deadline_, &on_retry_alarm_);
|
903
|
+
}
|
904
|
+
}
|
1069
905
|
|
1070
|
-
|
1071
|
-
|
1072
|
-
|
1073
|
-
|
1074
|
-
|
1075
|
-
|
1076
|
-
|
1077
|
-
|
1078
|
-
|
1079
|
-
|
906
|
+
void Subchannel::OnRetryAlarm(void* arg, grpc_error* error) {
|
907
|
+
Subchannel* c = static_cast<Subchannel*>(arg);
|
908
|
+
gpr_mu_lock(&c->mu_);
|
909
|
+
c->have_retry_alarm_ = false;
|
910
|
+
if (c->disconnected_) {
|
911
|
+
error = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING("Disconnected",
|
912
|
+
&error, 1);
|
913
|
+
} else if (c->retry_immediately_) {
|
914
|
+
c->retry_immediately_ = false;
|
915
|
+
error = GRPC_ERROR_NONE;
|
916
|
+
} else {
|
917
|
+
GRPC_ERROR_REF(error);
|
918
|
+
}
|
919
|
+
if (error == GRPC_ERROR_NONE) {
|
920
|
+
gpr_log(GPR_INFO, "Failed to connect to channel, retrying");
|
921
|
+
c->ContinueConnectingLocked();
|
922
|
+
gpr_mu_unlock(&c->mu_);
|
923
|
+
} else {
|
924
|
+
gpr_mu_unlock(&c->mu_);
|
925
|
+
GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting");
|
926
|
+
}
|
927
|
+
GRPC_ERROR_UNREF(error);
|
928
|
+
}
|
1080
929
|
|
1081
|
-
|
1082
|
-
|
1083
|
-
|
930
|
+
void Subchannel::ContinueConnectingLocked() {
|
931
|
+
grpc_connect_in_args args;
|
932
|
+
args.interested_parties = pollset_set_;
|
933
|
+
const grpc_millis min_deadline =
|
934
|
+
min_connect_timeout_ms_ + ExecCtx::Get()->Now();
|
935
|
+
next_attempt_deadline_ = backoff_.NextAttemptTime();
|
936
|
+
args.deadline = std::max(next_attempt_deadline_, min_deadline);
|
937
|
+
args.channel_args = args_;
|
938
|
+
SetConnectivityStateLocked(GRPC_CHANNEL_CONNECTING, GRPC_ERROR_NONE,
|
939
|
+
"connecting");
|
940
|
+
grpc_connectivity_state_set(&state_and_health_tracker_,
|
941
|
+
GRPC_CHANNEL_CONNECTING, GRPC_ERROR_NONE,
|
942
|
+
"connecting");
|
943
|
+
grpc_connector_connect(connector_, &args, &connecting_result_,
|
944
|
+
&on_connecting_finished_);
|
1084
945
|
}
|
1085
946
|
|
1086
|
-
void
|
1087
|
-
|
1088
|
-
|
1089
|
-
|
1090
|
-
|
1091
|
-
|
1092
|
-
|
1093
|
-
|
1094
|
-
|
1095
|
-
|
947
|
+
void Subchannel::OnConnectingFinished(void* arg, grpc_error* error) {
|
948
|
+
auto* c = static_cast<Subchannel*>(arg);
|
949
|
+
grpc_channel_args* delete_channel_args = c->connecting_result_.channel_args;
|
950
|
+
GRPC_SUBCHANNEL_WEAK_REF(c, "on_connecting_finished");
|
951
|
+
gpr_mu_lock(&c->mu_);
|
952
|
+
c->connecting_ = false;
|
953
|
+
if (c->connecting_result_.transport != nullptr &&
|
954
|
+
c->PublishTransportLocked()) {
|
955
|
+
// Do nothing, transport was published.
|
956
|
+
} else if (c->disconnected_) {
|
957
|
+
GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting");
|
958
|
+
} else {
|
959
|
+
c->SetConnectivityStateLocked(
|
960
|
+
GRPC_CHANNEL_TRANSIENT_FAILURE,
|
961
|
+
grpc_error_set_int(GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
|
962
|
+
"Connect Failed", &error, 1),
|
963
|
+
GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE),
|
964
|
+
"connect_failed");
|
965
|
+
grpc_connectivity_state_set(
|
966
|
+
&c->state_and_health_tracker_, GRPC_CHANNEL_TRANSIENT_FAILURE,
|
967
|
+
grpc_error_set_int(GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
|
968
|
+
"Connect Failed", &error, 1),
|
969
|
+
GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE),
|
970
|
+
"connect_failed");
|
971
|
+
|
972
|
+
const char* errmsg = grpc_error_string(error);
|
973
|
+
gpr_log(GPR_INFO, "Connect failed: %s", errmsg);
|
974
|
+
|
975
|
+
c->MaybeStartConnectingLocked();
|
976
|
+
GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting");
|
977
|
+
}
|
978
|
+
gpr_mu_unlock(&c->mu_);
|
979
|
+
GRPC_SUBCHANNEL_WEAK_UNREF(c, "on_connecting_finished");
|
980
|
+
grpc_channel_args_destroy(delete_channel_args);
|
1096
981
|
}
|
1097
982
|
|
1098
|
-
|
1099
|
-
|
1100
|
-
|
1101
|
-
|
1102
|
-
|
1103
|
-
|
1104
|
-
elem = grpc_channel_stack_element(channel_stack_, 0);
|
1105
|
-
elem->filter->start_transport_op(elem, op);
|
983
|
+
namespace {
|
984
|
+
|
985
|
+
void ConnectionDestroy(void* arg, grpc_error* error) {
|
986
|
+
grpc_channel_stack* stk = static_cast<grpc_channel_stack*>(arg);
|
987
|
+
grpc_channel_stack_destroy(stk);
|
988
|
+
gpr_free(stk);
|
1106
989
|
}
|
1107
990
|
|
1108
|
-
|
1109
|
-
|
1110
|
-
|
1111
|
-
|
1112
|
-
*
|
1113
|
-
|
1114
|
-
|
1115
|
-
|
1116
|
-
|
1117
|
-
|
1118
|
-
|
1119
|
-
|
1120
|
-
nullptr, /* server_transport_data */
|
1121
|
-
args.context, /* context */
|
1122
|
-
args.path, /* path */
|
1123
|
-
args.start_time, /* start_time */
|
1124
|
-
args.deadline, /* deadline */
|
1125
|
-
args.arena, /* arena */
|
1126
|
-
args.call_combiner /* call_combiner */
|
1127
|
-
};
|
1128
|
-
grpc_error* error = grpc_call_stack_init(
|
1129
|
-
channel_stack_, 1, subchannel_call_destroy, *call, &call_args);
|
1130
|
-
if (GPR_UNLIKELY(error != GRPC_ERROR_NONE)) {
|
1131
|
-
const char* error_string = grpc_error_string(error);
|
1132
|
-
gpr_log(GPR_ERROR, "error: %s", error_string);
|
1133
|
-
return error;
|
991
|
+
} // namespace
|
992
|
+
|
993
|
+
bool Subchannel::PublishTransportLocked() {
|
994
|
+
// Construct channel stack.
|
995
|
+
grpc_channel_stack_builder* builder = grpc_channel_stack_builder_create();
|
996
|
+
grpc_channel_stack_builder_set_channel_arguments(
|
997
|
+
builder, connecting_result_.channel_args);
|
998
|
+
grpc_channel_stack_builder_set_transport(builder,
|
999
|
+
connecting_result_.transport);
|
1000
|
+
if (!grpc_channel_init_create_stack(builder, GRPC_CLIENT_SUBCHANNEL)) {
|
1001
|
+
grpc_channel_stack_builder_destroy(builder);
|
1002
|
+
return false;
|
1134
1003
|
}
|
1135
|
-
|
1136
|
-
|
1137
|
-
|
1004
|
+
grpc_channel_stack* stk;
|
1005
|
+
grpc_error* error = grpc_channel_stack_builder_finish(
|
1006
|
+
builder, 0, 1, ConnectionDestroy, nullptr,
|
1007
|
+
reinterpret_cast<void**>(&stk));
|
1008
|
+
if (error != GRPC_ERROR_NONE) {
|
1009
|
+
grpc_transport_destroy(connecting_result_.transport);
|
1010
|
+
gpr_log(GPR_ERROR, "error initializing subchannel stack: %s",
|
1011
|
+
grpc_error_string(error));
|
1012
|
+
GRPC_ERROR_UNREF(error);
|
1013
|
+
return false;
|
1014
|
+
}
|
1015
|
+
intptr_t socket_uuid = connecting_result_.socket_uuid;
|
1016
|
+
memset(&connecting_result_, 0, sizeof(connecting_result_));
|
1017
|
+
if (disconnected_) {
|
1018
|
+
grpc_channel_stack_destroy(stk);
|
1019
|
+
gpr_free(stk);
|
1020
|
+
return false;
|
1138
1021
|
}
|
1139
|
-
|
1022
|
+
// Publish.
|
1023
|
+
connected_subchannel_.reset(
|
1024
|
+
New<ConnectedSubchannel>(stk, args_, channelz_node_, socket_uuid));
|
1025
|
+
gpr_log(GPR_INFO, "New connected subchannel at %p for subchannel %p",
|
1026
|
+
connected_subchannel_.get(), this);
|
1027
|
+
// Instantiate state watcher. Will clean itself up.
|
1028
|
+
connected_subchannel_watcher_ =
|
1029
|
+
MakeOrphanable<ConnectedSubchannelStateWatcher>(this);
|
1030
|
+
return true;
|
1140
1031
|
}
|
1141
1032
|
|
1142
|
-
|
1143
|
-
|
1144
|
-
|
1145
|
-
|
1146
|
-
|
1147
|
-
|
1148
|
-
GPR_ROUND_UP_TO_ALIGNMENT_SIZE(channel_stack_->call_stack_size) +
|
1149
|
-
parent_data_size;
|
1150
|
-
} else {
|
1151
|
-
allocation_size += channel_stack_->call_stack_size;
|
1033
|
+
void Subchannel::Disconnect() {
|
1034
|
+
// The subchannel_pool is only used once here in this subchannel, so the
|
1035
|
+
// access can be outside of the lock.
|
1036
|
+
if (subchannel_pool_ != nullptr) {
|
1037
|
+
subchannel_pool_->UnregisterSubchannel(key_);
|
1038
|
+
subchannel_pool_.reset();
|
1152
1039
|
}
|
1153
|
-
|
1040
|
+
MutexLock lock(&mu_);
|
1041
|
+
GPR_ASSERT(!disconnected_);
|
1042
|
+
disconnected_ = true;
|
1043
|
+
grpc_connector_shutdown(connector_, GRPC_ERROR_CREATE_FROM_STATIC_STRING(
|
1044
|
+
"Subchannel disconnected"));
|
1045
|
+
connected_subchannel_.reset();
|
1046
|
+
connected_subchannel_watcher_.reset();
|
1047
|
+
}
|
1048
|
+
|
1049
|
+
gpr_atm Subchannel::RefMutate(
|
1050
|
+
gpr_atm delta, int barrier GRPC_SUBCHANNEL_REF_MUTATE_EXTRA_ARGS) {
|
1051
|
+
gpr_atm old_val = barrier ? gpr_atm_full_fetch_add(&ref_pair_, delta)
|
1052
|
+
: gpr_atm_no_barrier_fetch_add(&ref_pair_, delta);
|
1053
|
+
#ifndef NDEBUG
|
1054
|
+
if (grpc_trace_stream_refcount.enabled()) {
|
1055
|
+
gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
|
1056
|
+
"SUBCHANNEL: %p %12s 0x%" PRIxPTR " -> 0x%" PRIxPTR " [%s]", this,
|
1057
|
+
purpose, old_val, old_val + delta, reason);
|
1058
|
+
}
|
1059
|
+
#endif
|
1060
|
+
return old_val;
|
1154
1061
|
}
|
1155
1062
|
|
1156
1063
|
} // namespace grpc_core
|