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.

Files changed (146) hide show
  1. checksums.yaml +4 -4
  2. data/Makefile +301 -33
  3. data/include/grpc/grpc_security.h +195 -0
  4. data/include/grpc/impl/codegen/grpc_types.h +17 -1
  5. data/include/grpc/impl/codegen/port_platform.h +36 -0
  6. data/include/grpc/impl/codegen/slice.h +1 -1
  7. data/src/core/ext/filters/client_channel/channel_connectivity.cc +2 -0
  8. data/src/core/ext/filters/client_channel/client_channel.cc +74 -69
  9. data/src/core/ext/filters/client_channel/client_channel.h +2 -2
  10. data/src/core/ext/filters/client_channel/client_channel_channelz.cc +5 -6
  11. data/src/core/ext/filters/client_channel/client_channel_channelz.h +5 -4
  12. data/src/core/ext/filters/client_channel/client_channel_factory.cc +2 -2
  13. data/src/core/ext/filters/client_channel/client_channel_factory.h +4 -4
  14. data/src/core/ext/filters/client_channel/client_channel_plugin.cc +3 -3
  15. data/src/core/ext/filters/client_channel/global_subchannel_pool.cc +176 -0
  16. data/src/core/ext/filters/client_channel/global_subchannel_pool.h +68 -0
  17. data/src/core/ext/filters/client_channel/health/health_check_client.cc +10 -8
  18. data/src/core/ext/filters/client_channel/health/health_check_client.h +1 -1
  19. data/src/core/ext/filters/client_channel/http_connect_handshaker.cc +146 -156
  20. data/src/core/ext/filters/client_channel/lb_policy.cc +30 -1
  21. data/src/core/ext/filters/client_channel/lb_policy.h +29 -1
  22. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc +28 -30
  23. data/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc +5 -8
  24. data/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc +5 -8
  25. data/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h +23 -24
  26. data/src/core/ext/filters/client_channel/lb_policy/xds/xds.cc +80 -15
  27. data/src/core/ext/filters/client_channel/lb_policy_factory.h +6 -1
  28. data/src/core/ext/filters/client_channel/lb_policy_registry.cc +2 -2
  29. data/src/core/ext/filters/client_channel/lb_policy_registry.h +1 -1
  30. data/src/core/ext/filters/client_channel/local_subchannel_pool.cc +96 -0
  31. data/src/core/ext/filters/client_channel/local_subchannel_pool.h +56 -0
  32. data/src/core/ext/filters/client_channel/parse_address.cc +24 -5
  33. data/src/core/ext/filters/client_channel/request_routing.cc +13 -3
  34. data/src/core/ext/filters/client_channel/request_routing.h +5 -1
  35. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc +11 -6
  36. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc +2 -2
  37. data/src/core/ext/filters/client_channel/resolver_result_parsing.cc +7 -35
  38. data/src/core/ext/filters/client_channel/subchannel.cc +698 -791
  39. data/src/core/ext/filters/client_channel/subchannel.h +213 -123
  40. data/src/core/ext/filters/client_channel/subchannel_pool_interface.cc +97 -0
  41. data/src/core/ext/filters/client_channel/subchannel_pool_interface.h +94 -0
  42. data/src/core/ext/filters/http/client_authority_filter.cc +5 -2
  43. data/src/core/ext/filters/max_age/max_age_filter.cc +1 -1
  44. data/src/core/ext/transport/chttp2/client/chttp2_connector.cc +13 -12
  45. data/src/core/ext/transport/chttp2/client/insecure/channel_create.cc +5 -7
  46. data/src/core/ext/transport/chttp2/client/secure/secure_channel_create.cc +19 -27
  47. data/src/core/ext/transport/chttp2/server/chttp2_server.cc +18 -19
  48. data/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +27 -6
  49. data/src/core/ext/transport/chttp2/transport/flow_control.cc +1 -1
  50. data/src/core/ext/transport/chttp2/transport/frame_window_update.cc +3 -2
  51. data/src/core/ext/transport/chttp2/transport/hpack_encoder.cc +1 -1
  52. data/src/core/ext/transport/chttp2/transport/writing.cc +8 -5
  53. data/src/core/lib/channel/handshaker.cc +141 -214
  54. data/src/core/lib/channel/handshaker.h +110 -101
  55. data/src/core/lib/channel/handshaker_factory.h +11 -19
  56. data/src/core/lib/channel/handshaker_registry.cc +64 -52
  57. data/src/core/lib/channel/handshaker_registry.h +21 -16
  58. data/src/core/lib/gpr/log_posix.cc +2 -1
  59. data/src/core/lib/gpr/time.cc +8 -0
  60. data/src/core/lib/gpr/time_posix.cc +8 -2
  61. data/src/core/lib/gprpp/optional.h +47 -0
  62. data/src/core/lib/http/httpcli_security_connector.cc +13 -14
  63. data/src/core/lib/iomgr/buffer_list.cc +182 -24
  64. data/src/core/lib/iomgr/buffer_list.h +70 -8
  65. data/src/core/lib/iomgr/combiner.cc +11 -3
  66. data/src/core/lib/iomgr/error.cc +9 -5
  67. data/src/core/lib/iomgr/ev_epoll1_linux.cc +3 -0
  68. data/src/core/lib/iomgr/ev_epollex_linux.cc +136 -162
  69. data/src/core/lib/iomgr/ev_poll_posix.cc +3 -0
  70. data/src/core/lib/iomgr/ev_posix.cc +4 -0
  71. data/src/core/lib/iomgr/ev_posix.h +4 -0
  72. data/src/core/lib/iomgr/exec_ctx.cc +1 -0
  73. data/src/core/lib/iomgr/exec_ctx.h +137 -8
  74. data/src/core/lib/iomgr/executor.cc +122 -87
  75. data/src/core/lib/iomgr/executor.h +53 -48
  76. data/src/core/lib/iomgr/fork_posix.cc +6 -4
  77. data/src/core/lib/iomgr/{network_status_tracker.cc → grpc_if_nametoindex.h} +8 -14
  78. data/src/core/lib/iomgr/grpc_if_nametoindex_posix.cc +42 -0
  79. data/src/core/lib/iomgr/{network_status_tracker.h → grpc_if_nametoindex_unsupported.cc} +15 -9
  80. data/src/core/lib/iomgr/internal_errqueue.h +105 -3
  81. data/src/core/lib/iomgr/iomgr.cc +6 -5
  82. data/src/core/lib/iomgr/iomgr.h +8 -0
  83. data/src/core/lib/iomgr/iomgr_custom.cc +6 -2
  84. data/src/core/lib/iomgr/iomgr_internal.cc +4 -0
  85. data/src/core/lib/iomgr/iomgr_internal.h +4 -0
  86. data/src/core/lib/iomgr/iomgr_posix.cc +10 -1
  87. data/src/core/lib/iomgr/iomgr_windows.cc +8 -1
  88. data/src/core/lib/iomgr/port.h +1 -0
  89. data/src/core/lib/iomgr/resolve_address_posix.cc +4 -3
  90. data/src/core/lib/iomgr/resolve_address_windows.cc +2 -1
  91. data/src/core/lib/iomgr/tcp_custom.cc +0 -4
  92. data/src/core/lib/iomgr/tcp_posix.cc +58 -44
  93. data/src/core/lib/iomgr/tcp_uv.cc +0 -1
  94. data/src/core/lib/iomgr/tcp_windows.cc +0 -4
  95. data/src/core/lib/iomgr/timer_manager.cc +8 -0
  96. data/src/core/lib/iomgr/udp_server.cc +6 -4
  97. data/src/core/lib/json/json.cc +1 -4
  98. data/src/core/lib/security/credentials/alts/alts_credentials.cc +1 -1
  99. data/src/core/lib/security/credentials/alts/check_gcp_environment_no_op.cc +2 -2
  100. data/src/core/lib/security/credentials/composite/composite_credentials.h +4 -0
  101. data/src/core/lib/security/credentials/credentials.h +9 -1
  102. data/src/core/lib/security/credentials/google_default/google_default_credentials.cc +15 -2
  103. data/src/core/lib/security/credentials/google_default/google_default_credentials.h +2 -0
  104. data/src/core/lib/security/credentials/jwt/json_token.cc +1 -1
  105. data/src/core/lib/security/credentials/jwt/jwt_credentials.cc +1 -0
  106. data/src/core/lib/security/credentials/jwt/jwt_verifier.cc +3 -2
  107. data/src/core/lib/security/credentials/oauth2/oauth2_credentials.cc +2 -2
  108. data/src/core/lib/security/credentials/plugin/plugin_credentials.cc +1 -0
  109. data/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc +192 -0
  110. data/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h +213 -0
  111. data/src/core/lib/security/security_connector/alts/alts_security_connector.cc +10 -8
  112. data/src/core/lib/security/security_connector/fake/fake_security_connector.cc +6 -10
  113. data/src/core/lib/security/security_connector/local/local_security_connector.cc +10 -8
  114. data/src/core/lib/security/security_connector/security_connector.h +2 -2
  115. data/src/core/lib/security/security_connector/ssl/ssl_security_connector.cc +4 -6
  116. data/src/core/lib/security/security_connector/ssl_utils.h +33 -0
  117. data/src/core/lib/security/transport/security_handshaker.cc +267 -300
  118. data/src/core/lib/security/transport/security_handshaker.h +11 -2
  119. data/src/core/lib/security/transport/server_auth_filter.cc +1 -0
  120. data/src/core/lib/surface/call.cc +5 -1
  121. data/src/core/lib/surface/channel_init.h +5 -0
  122. data/src/core/lib/surface/completion_queue.cc +4 -7
  123. data/src/core/lib/surface/init.cc +5 -3
  124. data/src/core/lib/surface/init_secure.cc +1 -1
  125. data/src/core/lib/surface/server.cc +19 -17
  126. data/src/core/lib/surface/version.cc +1 -1
  127. data/src/core/lib/transport/service_config.h +1 -0
  128. data/src/core/lib/transport/static_metadata.cc +279 -279
  129. data/src/core/lib/transport/transport.cc +5 -3
  130. data/src/core/tsi/ssl_transport_security.cc +10 -4
  131. data/src/ruby/ext/grpc/extconf.rb +12 -4
  132. data/src/ruby/ext/grpc/rb_call_credentials.c +8 -5
  133. data/src/ruby/ext/grpc/rb_channel.c +14 -10
  134. data/src/ruby/ext/grpc/rb_channel_credentials.c +8 -4
  135. data/src/ruby/ext/grpc/rb_compression_options.c +9 -7
  136. data/src/ruby/ext/grpc/rb_event_thread.c +2 -0
  137. data/src/ruby/ext/grpc/rb_grpc.c +22 -23
  138. data/src/ruby/ext/grpc/rb_grpc.h +4 -2
  139. data/src/ruby/ext/grpc/rb_grpc_imports.generated.c +18 -0
  140. data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +27 -0
  141. data/src/ruby/ext/grpc/rb_server.c +8 -4
  142. data/src/ruby/lib/grpc/version.rb +1 -1
  143. metadata +46 -39
  144. data/src/core/ext/filters/client_channel/subchannel_index.cc +0 -248
  145. data/src/core/ext/filters/client_channel/subchannel_index.h +0 -76
  146. 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
- grpc_core::channelz::ChannelTrace::Severity::Info,
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 = grpc_core::InlinedVector<char*, 3>;
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
- grpc_integer_options integer_options = {false, false, true};
152
- request_service_config_ = !grpc_channel_arg_get_integer(arg, integer_options);
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_, true /* check_grpclb */,
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 != nullptr && gpr_stricmp(resolver_env, "ares") == 0;
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
- GRPC_CLOSURE_SCHED(on_done, GRPC_ERROR_NONE);
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
- GRPC_CLOSURE_SCHED(on_done, GRPC_ERROR_NONE);
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
- // Find the LB config global parameter.
145
- if (field->key == nullptr || strcmp(field->key, "loadBalancingConfig") != 0 ||
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
- // Find the first LB policy that this client supports.
150
- for (grpc_json* lb_config = field->child; lb_config != nullptr;
151
- lb_config = lb_config->next) {
152
- if (lb_config->type != GRPC_JSON_OBJECT) return;
153
- // Find the policy object.
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/subchannel_index.h"
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
- namespace {
68
- struct state_watcher {
69
- grpc_closure closure;
70
- grpc_subchannel* subchannel;
71
- grpc_connectivity_state connectivity_state;
72
- grpc_connectivity_state last_connectivity_state;
73
- grpc_core::OrphanablePtr<grpc_core::HealthCheckClient> health_check_client;
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
- class ConnectedSubchannelStateWatcher;
78
+ //
79
+ // ConnectedSubchannel
80
+ //
91
81
 
92
- } // namespace grpc_core
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
- struct grpc_subchannel {
95
- grpc_connector* connector;
92
+ ConnectedSubchannel::~ConnectedSubchannel() {
93
+ grpc_channel_args_destroy(args_);
94
+ GRPC_CHANNEL_STACK_UNREF(channel_stack_, "connected_subchannel_dtor");
95
+ }
96
96
 
97
- /** refcount
98
- - lower INTERNAL_REF_BITS bits are for internal references:
99
- these do not keep the subchannel open.
100
- - upper remaining bits are for public references: these do
101
- keep the subchannel open */
102
- gpr_atm ref_pair;
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
- /** non-transport related channel filters */
105
- const grpc_channel_filter** filters;
106
- size_t num_filters;
107
- /** channel arguments */
108
- grpc_channel_args* args;
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
- grpc_subchannel_key* key;
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
- /** set during connection */
113
- grpc_connect_out_args connecting_result;
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
- /** callback for connection finishing */
116
- grpc_closure on_connected;
165
+ //
166
+ // SubchannelCall
167
+ //
117
168
 
118
- /** callback for our alarm */
119
- grpc_closure on_alarm;
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
- /** pollset_set tracking who's interested in a connection
122
- being setup */
123
- grpc_pollset_set* pollset_set;
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
- grpc_core::UniquePtr<char> health_check_service_name;
185
+ grpc_call_stack* SubchannelCall::GetCallStack() {
186
+ return SUBCHANNEL_CALL_TO_CALL_STACK(this);
187
+ }
126
188
 
127
- /** mutex protecting remaining elements */
128
- gpr_mu mu;
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
- /** active connection, or null */
131
- grpc_core::RefCountedPtr<grpc_core::ConnectedSubchannel> connected_subchannel;
132
- grpc_core::OrphanablePtr<grpc_core::ConnectedSubchannelStateWatcher>
133
- connected_subchannel_watcher;
195
+ RefCountedPtr<SubchannelCall> SubchannelCall::Ref() {
196
+ IncrementRefCount();
197
+ return RefCountedPtr<SubchannelCall>(this);
198
+ }
134
199
 
135
- /** have we seen a disconnection? */
136
- bool disconnected;
137
- /** are we connecting */
138
- bool connecting;
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
- /** connectivity state tracking */
141
- grpc_connectivity_state_tracker state_tracker;
142
- grpc_connectivity_state_tracker state_and_health_tracker;
206
+ void SubchannelCall::Unref() {
207
+ GRPC_CALL_STACK_UNREF(SUBCHANNEL_CALL_TO_CALL_STACK(this), "");
208
+ }
143
209
 
144
- external_state_watcher root_external_state_watcher;
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
- /** backoff state */
147
- grpc_core::ManualConstructor<grpc_core::BackOff> backoff;
148
- grpc_millis next_attempt_deadline;
149
- grpc_millis min_connect_timeout_ms;
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
- /** do we have an active alarm? */
152
- bool have_alarm;
153
- /** have we started the backoff loop */
154
- bool backoff_begun;
155
- // reset_backoff() was called while alarm was pending
156
- bool retry_immediately;
157
- /** our alarm */
158
- grpc_timer alarm;
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
- grpc_core::RefCountedPtr<grpc_core::channelz::SubchannelNode>
161
- channelz_subchannel;
162
- };
255
+ namespace {
163
256
 
164
- struct grpc_subchannel_call {
165
- grpc_subchannel_call(grpc_core::ConnectedSubchannel* connection,
166
- const grpc_core::ConnectedSubchannel::CallArgs& args)
167
- : connection(connection), deadline(args.deadline) {}
168
-
169
- grpc_core::ConnectedSubchannel* connection;
170
- grpc_closure* schedule_closure_after_destroy = nullptr;
171
- // state needed to support channelz interception of recv trailing metadata.
172
- grpc_closure recv_trailing_metadata_ready;
173
- grpc_closure* original_recv_trailing_metadata;
174
- grpc_metadata_batch* recv_trailing_metadata = nullptr;
175
- grpc_millis deadline;
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
- static void maybe_start_connecting_locked(grpc_subchannel* c);
273
+ } // namespace
179
274
 
180
- static const char* subchannel_connectivity_state_change_string(
181
- grpc_connectivity_state state) {
182
- switch (state) {
183
- case GRPC_CHANNEL_IDLE:
184
- return "Subchannel state change to IDLE";
185
- case GRPC_CHANNEL_CONNECTING:
186
- return "Subchannel state change to CONNECTING";
187
- case GRPC_CHANNEL_READY:
188
- return "Subchannel state change to READY";
189
- case GRPC_CHANNEL_TRANSIENT_FAILURE:
190
- return "Subchannel state change to TRANSIENT_FAILURE";
191
- case GRPC_CHANNEL_SHUTDOWN:
192
- return "Subchannel state change to SHUTDOWN";
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
- GPR_UNREACHABLE_CODE(return "UNKNOWN");
289
+ GRPC_CLOSURE_RUN(call->original_recv_trailing_metadata_,
290
+ GRPC_ERROR_REF(error));
195
291
  }
196
292
 
197
- static void set_subchannel_connectivity_state_locked(
198
- grpc_subchannel* c, grpc_connectivity_state state, grpc_error* error,
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
- namespace grpc_core {
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(grpc_subchannel* c)
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->connected_subchannel->NotifyOnStateChange(c->pollset_set,
225
- &pending_connectivity_state_,
226
- &on_connectivity_changed_);
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->health_check_service_name != nullptr) {
230
- health_check_client_ = grpc_core::MakeOrphanable<HealthCheckClient>(
231
- c->health_check_service_name.get(), c->connected_subchannel,
232
- c->pollset_set, c->channelz_subchannel);
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
- set_subchannel_connectivity_state_locked(
242
- c, GRPC_CHANNEL_READY, GRPC_ERROR_NONE, "subchannel_connected");
243
- grpc_connectivity_state_set(&c->state_and_health_tracker, health_state,
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
- grpc_subchannel* c = self->subchannel_;
351
+ Subchannel* c = self->subchannel_;
257
352
  {
258
- MutexLock lock(&c->mu);
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->disconnected && c->connected_subchannel != nullptr) {
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->connected_subchannel.get(), c,
362
+ c->connected_subchannel_.get(), c,
268
363
  grpc_connectivity_state_name(
269
364
  self->pending_connectivity_state_));
270
365
  }
271
- c->connected_subchannel.reset();
272
- c->connected_subchannel_watcher.reset();
366
+ c->connected_subchannel_.reset();
367
+ c->connected_subchannel_watcher_.reset();
273
368
  self->last_connectivity_state_ = GRPC_CHANNEL_TRANSIENT_FAILURE;
274
- set_subchannel_connectivity_state_locked(
275
- c, GRPC_CHANNEL_TRANSIENT_FAILURE, GRPC_ERROR_REF(error),
276
- "reflect_child");
277
- grpc_connectivity_state_set(&c->state_and_health_tracker,
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->backoff_begun = false;
281
- c->backoff->Reset();
282
- maybe_start_connecting_locked(c);
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
- set_subchannel_connectivity_state_locked(
296
- c, self->pending_connectivity_state_, GRPC_ERROR_REF(error),
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->state_and_health_tracker,
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->connected_subchannel->NotifyOnStateChange(
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
- if (self->health_state_ == GRPC_CHANNEL_SHUTDOWN) {
318
- self->Unref();
319
- return;
320
- }
321
- grpc_subchannel* c = self->subchannel_;
322
- MutexLock lock(&c->mu);
323
- if (self->last_connectivity_state_ == GRPC_CHANNEL_READY) {
324
- grpc_connectivity_state_set(&c->state_and_health_tracker,
325
- self->health_state_, GRPC_ERROR_REF(error),
326
- "health_changed");
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
- self->health_check_client_->NotifyOnHealthChange(&self->health_state_,
329
- &self->on_health_changed_);
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
- grpc_subchannel* subchannel_;
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
- grpc_core::OrphanablePtr<grpc_core::HealthCheckClient> health_check_client_;
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
- } // namespace grpc_core
342
-
343
- #define SUBCHANNEL_CALL_TO_CALL_STACK(call) \
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
- static gpr_atm ref_mutate(grpc_subchannel* c, gpr_atm delta,
400
- int barrier REF_MUTATE_EXTRA_ARGS) {
401
- gpr_atm old_val = barrier ? gpr_atm_full_fetch_add(&c->ref_pair, delta)
402
- : gpr_atm_no_barrier_fetch_add(&c->ref_pair, delta);
403
- #ifndef NDEBUG
404
- if (grpc_trace_stream_refcount.enabled()) {
405
- gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
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
- grpc_subchannel* grpc_subchannel_ref_from_weak_ref(
431
- grpc_subchannel* c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
432
- if (!c) return nullptr;
433
- for (;;) {
434
- gpr_atm old_refs = gpr_atm_acq_load(&c->ref_pair);
435
- if (old_refs >= (1 << INTERNAL_REF_BITS)) {
436
- gpr_atm new_refs = old_refs + (1 << INTERNAL_REF_BITS);
437
- if (gpr_atm_rel_cas(&c->ref_pair, old_refs, new_refs)) {
438
- return c;
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
- static void disconnect(grpc_subchannel* c) {
447
- grpc_subchannel_index_unregister(c->key, c);
448
- gpr_mu_lock(&c->mu);
449
- GPR_ASSERT(!c->disconnected);
450
- c->disconnected = true;
451
- grpc_connector_shutdown(c->connector, GRPC_ERROR_CREATE_FROM_STATIC_STRING(
452
- "Subchannel disconnected"));
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
- void grpc_subchannel_unref(grpc_subchannel* c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
459
- gpr_atm old_refs;
460
- // add a weak ref and subtract a strong ref (atomically)
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
- void grpc_subchannel_weak_unref(
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
- static void parse_args_for_backoff_values(
483
- const grpc_channel_args* args, grpc_core::BackOff::Options* backoff_options,
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
- backoff_options->set_initial_backoff(initial_backoff_ms)
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
- c = static_cast<grpc_subchannel*>(gpr_zalloc(sizeof(*c)));
566
- c->key = key;
567
- gpr_atm_no_barrier_store(&c->ref_pair, 1 << INTERNAL_REF_BITS);
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
- grpc_get_subchannel_address_arg(args->args, addr);
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->args, &new_address,
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 = grpc_create_subchannel_address_arg(addr);
575
+ grpc_arg new_arg = CreateSubchannelAddressArg(addr);
593
576
  gpr_free(addr);
594
- c->args = grpc_channel_args_copy_and_add_and_remove(
595
- new_args != nullptr ? new_args : args->args, keys_to_remove,
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
- c->root_external_state_watcher.next = c->root_external_state_watcher.prev =
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(&c->state_tracker, GRPC_CHANNEL_IDLE,
584
+ grpc_connectivity_state_init(&state_tracker_, GRPC_CHANNEL_IDLE,
604
585
  "subchannel");
605
- grpc_connectivity_state_init(&c->state_and_health_tracker, GRPC_CHANNEL_IDLE,
586
+ grpc_connectivity_state_init(&state_and_health_tracker_, GRPC_CHANNEL_IDLE,
606
587
  "subchannel");
607
- grpc_core::BackOff::Options backoff_options;
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(c->args, GRPC_ARG_SERVICE_CONFIG));
591
+ grpc_channel_args_find(args_, GRPC_ARG_SERVICE_CONFIG));
616
592
  if (service_config_json != nullptr) {
617
- grpc_core::UniquePtr<grpc_core::ServiceConfig> service_config =
618
- grpc_core::ServiceConfig::Create(service_config_json);
593
+ UniquePtr<ServiceConfig> service_config =
594
+ ServiceConfig::Create(service_config_json);
619
595
  if (service_config != nullptr) {
620
- grpc_core::HealthCheckParams params;
621
- service_config->ParseGlobalParams(grpc_core::HealthCheckParams::Parse,
622
- &params);
623
- c->health_check_service_name = std::move(params.service_name);
596
+ HealthCheckParams params;
597
+ service_config->ParseGlobalParams(HealthCheckParams::Parse, &params);
598
+ health_check_service_name_ = std::move(params.service_name);
624
599
  }
625
600
  }
626
-
627
- const grpc_arg* arg =
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
- c->args, GRPC_ARG_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE);
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
- c->channelz_subchannel =
639
- grpc_core::MakeRefCounted<grpc_core::channelz::SubchannelNode>(
640
- c, channel_tracer_max_memory);
641
- c->channelz_subchannel->AddTraceEvent(
642
- grpc_core::channelz::ChannelTrace::Severity::Info,
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
- grpc_core::channelz::SubchannelNode* grpc_subchannel_get_channelz_node(
650
- grpc_subchannel* subchannel) {
651
- return subchannel->channelz_subchannel.get();
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
- intptr_t grpc_subchannel_get_child_socket_uuid(grpc_subchannel* subchannel) {
655
- if (subchannel->connected_subchannel != nullptr) {
656
- return subchannel->connected_subchannel->socket_uuid();
657
- } else {
658
- return 0;
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
- static void continue_connect_locked(grpc_subchannel* c) {
663
- grpc_connect_in_args args;
664
- args.interested_parties = c->pollset_set;
665
- const grpc_millis min_deadline =
666
- c->min_connect_timeout_ms + grpc_core::ExecCtx::Get()->Now();
667
- c->next_attempt_deadline = c->backoff->NextAttemptTime();
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
- grpc_connectivity_state grpc_subchannel_check_connectivity(
680
- grpc_subchannel* c, grpc_error** error, bool inhibit_health_checks) {
681
- gpr_mu_lock(&c->mu);
682
- grpc_connectivity_state_tracker* tracker =
683
- inhibit_health_checks ? &c->state_tracker : &c->state_and_health_tracker;
684
- grpc_connectivity_state state = grpc_connectivity_state_get(tracker, error);
685
- gpr_mu_unlock(&c->mu);
686
- return state;
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
- static void on_external_state_watcher_done(void* arg, grpc_error* error) {
690
- external_state_watcher* w = static_cast<external_state_watcher*>(arg);
691
- grpc_closure* follow_up = w->notify;
692
- if (w->pollset_set != nullptr) {
693
- grpc_pollset_set_del_pollset_set(w->subchannel->pollset_set,
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
- static void on_alarm(void* arg, grpc_error* error) {
706
- grpc_subchannel* c = static_cast<grpc_subchannel*>(arg);
707
- gpr_mu_lock(&c->mu);
708
- c->have_alarm = false;
709
- if (c->disconnected) {
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
- static void maybe_start_connecting_locked(grpc_subchannel* c) {
730
- if (c->disconnected) {
731
- /* Don't try to connect if we're already disconnected */
732
- return;
733
- }
734
- if (c->connecting) {
735
- /* Already connecting: don't restart */
736
- return;
737
- }
738
- if (c->connected_subchannel != nullptr) {
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
- void grpc_subchannel_notify_on_state_change(
769
- grpc_subchannel* c, grpc_pollset_set* interested_parties,
770
- grpc_connectivity_state* state, grpc_closure* notify,
771
- bool inhibit_health_checks) {
772
- grpc_connectivity_state_tracker* tracker =
773
- inhibit_health_checks ? &c->state_tracker : &c->state_and_health_tracker;
774
- external_state_watcher* w;
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
- void grpc_subchannel_reset_backoff(grpc_subchannel* subchannel) {
889
- gpr_mu_lock(&subchannel->mu);
890
- subchannel->backoff->Reset();
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
- subchannel->backoff_begun = false;
896
- maybe_start_connecting_locked(subchannel);
721
+ return 0;
897
722
  }
898
- gpr_mu_unlock(&subchannel->mu);
899
723
  }
900
724
 
901
- /*
902
- * grpc_subchannel_call implementation
903
- */
904
-
905
- static void subchannel_call_destroy(void* call, grpc_error* error) {
906
- GPR_TIMER_SCOPE("grpc_subchannel_call_unref.destroy", 0);
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
- void grpc_subchannel_call_set_cleanup_closure(grpc_subchannel_call* call,
916
- grpc_closure* closure) {
917
- GPR_ASSERT(call->schedule_closure_after_destroy == nullptr);
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
- grpc_subchannel_call* grpc_subchannel_call_ref(
923
- grpc_subchannel_call* c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
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
- void grpc_subchannel_call_unref(
929
- grpc_subchannel_call* c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
930
- GRPC_CALL_STACK_UNREF(SUBCHANNEL_CALL_TO_CALL_STACK(c), REF_REASON);
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
- // Sets *status based on md_batch and error.
934
- static void get_call_status(grpc_subchannel_call* call,
935
- grpc_metadata_batch* md_batch, grpc_error* error,
936
- grpc_status_code* status) {
937
- if (error != GRPC_ERROR_NONE) {
938
- grpc_error_get_status(error, call->deadline, status, nullptr, nullptr,
939
- nullptr);
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
- if (md_batch->idx.named.grpc_status != nullptr) {
942
- *status = grpc_get_status_code_from_metadata(
943
- md_batch->idx.named.grpc_status->md);
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
- static void recv_trailing_metadata_ready(void* arg, grpc_error* error) {
952
- grpc_subchannel_call* call = static_cast<grpc_subchannel_call*>(arg);
953
- GPR_ASSERT(call->recv_trailing_metadata != nullptr);
954
- grpc_status_code status = GRPC_STATUS_OK;
955
- grpc_metadata_batch* md_batch = call->recv_trailing_metadata;
956
- get_call_status(call, md_batch, GRPC_ERROR_REF(error), &status);
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
- channelz_subchannel->RecordCallFailed();
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
- // If channelz is enabled, intercept recv_trailing so that we may check the
970
- // status and associate it to a subchannel.
971
- static void maybe_intercept_recv_trailing_metadata(
972
- grpc_subchannel_call* call, grpc_transport_stream_op_batch* batch) {
973
- // only intercept payloads with recv trailing.
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
- void* grpc_connected_subchannel_call_get_parent_data(
1018
- grpc_subchannel_call* subchannel_call) {
1019
- grpc_channel_stack* chanstk = subchannel_call->connection->channel_stack();
1020
- return (char*)subchannel_call + sizeof(grpc_subchannel_call) +
1021
- chanstk->call_stack_size;
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
- grpc_call_stack* grpc_subchannel_call_get_call_stack(
1025
- grpc_subchannel_call* subchannel_call) {
1026
- return SUBCHANNEL_CALL_TO_CALL_STACK(subchannel_call);
1027
- }
811
+ namespace {
1028
812
 
1029
- static void grpc_uri_to_sockaddr(const char* uri_str,
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
- void grpc_get_subchannel_address_arg(const grpc_channel_args* args,
1038
- grpc_resolved_address* addr) {
1039
- const char* addr_uri_str = grpc_get_subchannel_address_uri_arg(args);
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
- grpc_uri_to_sockaddr(addr_uri_str, addr);
827
+ UriToSockaddr(addr_uri_str, addr);
1043
828
  }
1044
829
  }
1045
830
 
1046
- const char* grpc_subchannel_get_target(grpc_subchannel* subchannel) {
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
- const char* grpc_get_subchannel_address_uri_arg(const grpc_channel_args* args) {
1055
- const grpc_arg* addr_arg =
1056
- grpc_channel_args_find(args, GRPC_ARG_SUBCHANNEL_ADDRESS);
1057
- const char* addr_str = grpc_channel_arg_get_string(addr_arg);
1058
- GPR_ASSERT(addr_str != nullptr); // Should have been set by LB policy.
1059
- return addr_str;
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
- grpc_arg grpc_create_subchannel_address_arg(const grpc_resolved_address* addr) {
1063
- return grpc_channel_arg_string_create(
1064
- (char*)GRPC_ARG_SUBCHANNEL_ADDRESS,
1065
- addr->len > 0 ? grpc_sockaddr_to_uri(addr) : gpr_strdup(""));
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
- namespace grpc_core {
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
- ConnectedSubchannel::ConnectedSubchannel(
1071
- grpc_channel_stack* channel_stack, const grpc_channel_args* args,
1072
- grpc_core::RefCountedPtr<grpc_core::channelz::SubchannelNode>
1073
- channelz_subchannel,
1074
- intptr_t socket_uuid)
1075
- : RefCounted<ConnectedSubchannel>(&grpc_trace_stream_refcount),
1076
- channel_stack_(channel_stack),
1077
- args_(grpc_channel_args_copy(args)),
1078
- channelz_subchannel_(std::move(channelz_subchannel)),
1079
- socket_uuid_(socket_uuid) {}
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
- ConnectedSubchannel::~ConnectedSubchannel() {
1082
- grpc_channel_args_destroy(args_);
1083
- GRPC_CHANNEL_STACK_UNREF(channel_stack_, "connected_subchannel_dtor");
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 ConnectedSubchannel::NotifyOnStateChange(
1087
- grpc_pollset_set* interested_parties, grpc_connectivity_state* state,
1088
- grpc_closure* closure) {
1089
- grpc_transport_op* op = grpc_make_transport_op(nullptr);
1090
- grpc_channel_element* elem;
1091
- op->connectivity_state = state;
1092
- op->on_connectivity_state_change = closure;
1093
- op->bind_pollset_set = interested_parties;
1094
- elem = grpc_channel_stack_element(channel_stack_, 0);
1095
- elem->filter->start_transport_op(elem, op);
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
- void ConnectedSubchannel::Ping(grpc_closure* on_initiate,
1099
- grpc_closure* on_ack) {
1100
- grpc_transport_op* op = grpc_make_transport_op(nullptr);
1101
- grpc_channel_element* elem;
1102
- op->send_ping.on_initiate = on_initiate;
1103
- op->send_ping.on_ack = on_ack;
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
- grpc_error* ConnectedSubchannel::CreateCall(const CallArgs& args,
1109
- grpc_subchannel_call** call) {
1110
- const size_t allocation_size =
1111
- GetInitialCallSizeEstimate(args.parent_data_size);
1112
- *call = new (gpr_arena_alloc(args.arena, allocation_size))
1113
- grpc_subchannel_call(this, args);
1114
- grpc_call_stack* callstk = SUBCHANNEL_CALL_TO_CALL_STACK(*call);
1115
- RefCountedPtr<ConnectedSubchannel> connection =
1116
- Ref(DEBUG_LOCATION, "subchannel_call");
1117
- connection.release(); // Ref is passed to the grpc_subchannel_call object.
1118
- const grpc_call_element_args call_args = {
1119
- callstk, /* call_stack */
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
- grpc_call_stack_set_pollset_or_pollset_set(callstk, args.pollent);
1136
- if (channelz_subchannel_ != nullptr) {
1137
- channelz_subchannel_->RecordCallStarted();
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
- return GRPC_ERROR_NONE;
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
- size_t ConnectedSubchannel::GetInitialCallSizeEstimate(
1143
- size_t parent_data_size) const {
1144
- size_t allocation_size =
1145
- GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_subchannel_call));
1146
- if (parent_data_size > 0) {
1147
- allocation_size +=
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
- return allocation_size;
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