grpc 1.16.0 → 1.17.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 (173) hide show
  1. checksums.yaml +4 -4
  2. data/Makefile +299 -133
  3. data/include/grpc/grpc.h +11 -1
  4. data/include/grpc/grpc_posix.h +0 -8
  5. data/include/grpc/impl/codegen/grpc_types.h +3 -0
  6. data/src/core/ext/filters/client_channel/client_channel.cc +336 -345
  7. data/src/core/ext/filters/client_channel/client_channel.h +6 -2
  8. data/src/core/ext/filters/client_channel/client_channel_channelz.cc +3 -1
  9. data/src/core/ext/filters/client_channel/client_channel_channelz.h +0 -7
  10. data/src/core/ext/filters/client_channel/health/health.pb.c +23 -0
  11. data/src/core/ext/filters/client_channel/health/health.pb.h +73 -0
  12. data/src/core/ext/filters/client_channel/health/health_check_client.cc +652 -0
  13. data/src/core/ext/filters/client_channel/health/health_check_client.h +173 -0
  14. data/src/core/ext/filters/client_channel/http_connect_handshaker.cc +2 -1
  15. data/src/core/ext/filters/client_channel/http_proxy.cc +1 -1
  16. data/src/core/ext/filters/client_channel/lb_policy.h +17 -14
  17. data/src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.cc +15 -11
  18. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc +21 -15
  19. data/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc +18 -10
  20. data/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc +12 -9
  21. data/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h +19 -8
  22. data/src/core/ext/filters/client_channel/lb_policy/xds/xds.cc +1832 -0
  23. data/src/core/ext/filters/client_channel/lb_policy/xds/xds.h +36 -0
  24. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_channel.h +36 -0
  25. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_channel_secure.cc +107 -0
  26. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_client_stats.cc +85 -0
  27. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_client_stats.h +72 -0
  28. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_load_balancer_api.cc +307 -0
  29. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_load_balancer_api.h +89 -0
  30. data/src/core/ext/filters/client_channel/lb_policy_factory.h +1 -1
  31. data/src/core/ext/filters/client_channel/lb_policy_registry.cc +5 -0
  32. data/src/core/ext/filters/client_channel/lb_policy_registry.h +4 -0
  33. data/src/core/ext/filters/client_channel/parse_address.h +1 -1
  34. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc +19 -22
  35. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc +41 -39
  36. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h +3 -2
  37. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc +4 -1
  38. data/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc +15 -2
  39. data/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h +5 -1
  40. data/src/core/ext/filters/client_channel/resolver_factory.h +1 -1
  41. data/src/core/ext/filters/client_channel/resolver_result_parsing.cc +384 -0
  42. data/src/core/ext/filters/client_channel/resolver_result_parsing.h +146 -0
  43. data/src/core/ext/filters/client_channel/subchannel.cc +361 -103
  44. data/src/core/ext/filters/client_channel/subchannel.h +14 -8
  45. data/src/core/ext/filters/deadline/deadline_filter.cc +19 -23
  46. data/src/core/ext/filters/deadline/deadline_filter.h +9 -13
  47. data/src/core/ext/filters/http/client/http_client_filter.cc +29 -19
  48. data/src/core/ext/filters/http/client_authority_filter.cc +2 -3
  49. data/src/core/ext/filters/http/message_compress/message_compress_filter.cc +28 -16
  50. data/src/core/ext/filters/http/server/http_server_filter.cc +31 -20
  51. data/src/core/ext/filters/message_size/message_size_filter.cc +50 -45
  52. data/src/core/ext/transport/chttp2/client/chttp2_connector.cc +13 -6
  53. data/src/core/ext/transport/chttp2/client/secure/secure_channel_create.cc +1 -1
  54. data/src/core/ext/transport/chttp2/server/chttp2_server.cc +58 -8
  55. data/src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.cc +1 -1
  56. data/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +175 -173
  57. data/src/core/ext/transport/chttp2/transport/chttp2_transport.h +2 -1
  58. data/src/core/ext/transport/chttp2/transport/frame_data.cc +4 -10
  59. data/src/core/ext/transport/chttp2/transport/frame_data.h +10 -12
  60. data/src/core/ext/transport/chttp2/transport/frame_rst_stream.cc +1 -1
  61. data/src/core/ext/transport/chttp2/transport/hpack_encoder.cc +28 -25
  62. data/src/core/ext/transport/chttp2/transport/incoming_metadata.cc +0 -12
  63. data/src/core/ext/transport/chttp2/transport/incoming_metadata.h +12 -9
  64. data/src/core/ext/transport/chttp2/transport/internal.h +109 -94
  65. data/src/core/ext/transport/chttp2/transport/parsing.cc +4 -2
  66. data/src/core/ext/transport/inproc/inproc_transport.cc +280 -300
  67. data/src/core/lib/channel/channel_stack.cc +5 -4
  68. data/src/core/lib/channel/channel_stack.h +4 -4
  69. data/src/core/lib/channel/channel_stack_builder.cc +14 -2
  70. data/src/core/lib/channel/channel_stack_builder.h +8 -0
  71. data/src/core/lib/channel/channel_trace.cc +6 -2
  72. data/src/core/lib/channel/channelz.cc +137 -5
  73. data/src/core/lib/channel/channelz.h +32 -6
  74. data/src/core/lib/channel/channelz_registry.cc +134 -28
  75. data/src/core/lib/channel/channelz_registry.h +25 -3
  76. data/src/core/lib/channel/context.h +4 -4
  77. data/src/core/lib/channel/handshaker.cc +7 -6
  78. data/src/core/lib/channel/handshaker.h +7 -8
  79. data/src/core/lib/channel/handshaker_factory.cc +3 -2
  80. data/src/core/lib/channel/handshaker_factory.h +2 -0
  81. data/src/core/lib/channel/handshaker_registry.cc +6 -2
  82. data/src/core/lib/channel/handshaker_registry.h +1 -0
  83. data/src/core/lib/gpr/arena.cc +84 -37
  84. data/src/core/lib/gpr/arena.h +2 -0
  85. data/src/core/lib/gpr/mpscq.h +4 -2
  86. data/src/core/lib/gprpp/inlined_vector.h +8 -0
  87. data/src/core/lib/gprpp/ref_counted.h +105 -18
  88. data/src/core/lib/gprpp/ref_counted_ptr.h +11 -0
  89. data/src/core/lib/http/httpcli_security_connector.cc +7 -4
  90. data/src/core/lib/iomgr/call_combiner.cc +2 -0
  91. data/src/core/lib/iomgr/call_combiner.h +2 -2
  92. data/src/core/lib/iomgr/closure.h +1 -0
  93. data/src/core/lib/iomgr/error.cc +16 -31
  94. data/src/core/lib/iomgr/error.h +29 -4
  95. data/src/core/lib/iomgr/error_internal.h +0 -2
  96. data/src/core/lib/iomgr/ev_epoll1_linux.cc +7 -3
  97. data/src/core/lib/iomgr/ev_posix.cc +0 -2
  98. data/src/core/lib/iomgr/polling_entity.h +4 -4
  99. data/src/core/lib/iomgr/resource_quota.cc +64 -10
  100. data/src/core/lib/iomgr/resource_quota.h +21 -6
  101. data/src/core/lib/iomgr/socket_utils_common_posix.cc +11 -5
  102. data/src/core/lib/iomgr/tcp_client_custom.cc +14 -3
  103. data/src/core/lib/iomgr/tcp_client_posix.cc +2 -0
  104. data/src/core/lib/iomgr/tcp_posix.cc +4 -2
  105. data/src/core/lib/iomgr/timer_manager.cc +1 -1
  106. data/src/core/lib/iomgr/wakeup_fd_eventfd.cc +3 -4
  107. data/src/core/lib/security/context/security_context.cc +20 -13
  108. data/src/core/lib/security/context/security_context.h +27 -19
  109. data/src/core/lib/security/credentials/alts/alts_credentials.cc +1 -1
  110. data/src/core/lib/security/credentials/credentials.h +2 -2
  111. data/src/core/lib/security/credentials/fake/fake_credentials.cc +1 -0
  112. data/src/core/lib/security/credentials/google_default/google_default_credentials.cc +39 -54
  113. data/src/core/lib/security/credentials/google_default/google_default_credentials.h +3 -2
  114. data/src/core/lib/security/credentials/local/local_credentials.cc +1 -1
  115. data/src/core/lib/security/credentials/plugin/plugin_credentials.cc +1 -2
  116. data/src/core/lib/security/credentials/ssl/ssl_credentials.h +2 -0
  117. data/src/core/lib/security/security_connector/{alts_security_connector.cc → alts/alts_security_connector.cc} +10 -9
  118. data/src/core/lib/security/security_connector/{alts_security_connector.h → alts/alts_security_connector.h} +3 -3
  119. data/src/core/lib/security/security_connector/fake/fake_security_connector.cc +310 -0
  120. data/src/core/lib/security/security_connector/fake/fake_security_connector.h +42 -0
  121. data/src/core/lib/security/security_connector/{local_security_connector.cc → local/local_security_connector.cc} +4 -3
  122. data/src/core/lib/security/security_connector/{local_security_connector.h → local/local_security_connector.h} +3 -3
  123. data/src/core/lib/security/security_connector/security_connector.cc +4 -1039
  124. data/src/core/lib/security/security_connector/security_connector.h +6 -114
  125. data/src/core/lib/security/security_connector/ssl/ssl_security_connector.cc +474 -0
  126. data/src/core/lib/security/security_connector/ssl/ssl_security_connector.h +77 -0
  127. data/src/core/lib/security/security_connector/ssl_utils.cc +345 -0
  128. data/src/core/lib/security/security_connector/ssl_utils.h +93 -0
  129. data/src/core/lib/security/transport/client_auth_filter.cc +28 -17
  130. data/src/core/lib/security/transport/secure_endpoint.cc +51 -41
  131. data/src/core/lib/security/transport/security_handshaker.cc +6 -7
  132. data/src/core/lib/security/transport/server_auth_filter.cc +39 -31
  133. data/src/core/lib/surface/call.cc +100 -80
  134. data/src/core/lib/surface/call.h +4 -0
  135. data/src/core/lib/surface/channel.cc +27 -13
  136. data/src/core/lib/surface/channel.h +4 -3
  137. data/src/core/lib/surface/completion_queue.cc +8 -1
  138. data/src/core/lib/surface/init.cc +1 -0
  139. data/src/core/lib/surface/server.cc +111 -46
  140. data/src/core/lib/surface/server.h +16 -2
  141. data/src/core/lib/surface/version.cc +2 -2
  142. data/src/core/lib/transport/error_utils.cc +4 -2
  143. data/src/core/lib/transport/metadata.cc +3 -2
  144. data/src/core/lib/transport/metadata.h +3 -2
  145. data/src/core/lib/transport/metadata_batch.cc +1 -0
  146. data/src/core/lib/transport/metadata_batch.h +4 -2
  147. data/src/core/lib/transport/static_metadata.cc +225 -221
  148. data/src/core/lib/transport/static_metadata.h +74 -71
  149. data/src/core/lib/transport/transport.h +44 -26
  150. data/src/core/{ext/filters/client_channel → lib/uri}/uri_parser.cc +1 -1
  151. data/src/core/{ext/filters/client_channel → lib/uri}/uri_parser.h +3 -3
  152. data/src/core/plugin_registry/grpc_plugin_registry.cc +4 -4
  153. data/src/core/tsi/alts/handshaker/alts_handshaker_client.cc +356 -77
  154. data/src/core/tsi/alts/handshaker/alts_handshaker_client.h +46 -36
  155. data/src/core/tsi/alts/handshaker/alts_shared_resource.cc +83 -0
  156. data/src/core/tsi/alts/handshaker/alts_shared_resource.h +73 -0
  157. data/src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc +122 -175
  158. data/src/core/tsi/alts/handshaker/alts_tsi_handshaker.h +33 -22
  159. data/src/core/tsi/alts/handshaker/alts_tsi_handshaker_private.h +38 -10
  160. data/src/core/tsi/transport_security.cc +18 -1
  161. data/src/core/tsi/transport_security.h +2 -1
  162. data/src/ruby/ext/grpc/rb_grpc_imports.generated.c +4 -2
  163. data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +6 -3
  164. data/src/ruby/lib/grpc/version.rb +1 -1
  165. data/src/ruby/spec/pb/codegen/grpc/testing/package_options.proto +28 -0
  166. data/src/ruby/spec/pb/codegen/package_option_spec.rb +2 -3
  167. metadata +58 -40
  168. data/src/core/ext/filters/client_channel/method_params.cc +0 -178
  169. data/src/core/ext/filters/client_channel/method_params.h +0 -78
  170. data/src/core/tsi/alts/handshaker/alts_tsi_event.cc +0 -75
  171. data/src/core/tsi/alts/handshaker/alts_tsi_event.h +0 -93
  172. data/src/core/tsi/alts_transport_security.cc +0 -65
  173. data/src/core/tsi/alts_transport_security.h +0 -47
@@ -30,10 +30,10 @@
30
30
  #include <grpc/support/string_util.h>
31
31
 
32
32
  #include "src/core/ext/filters/client_channel/client_channel.h"
33
+ #include "src/core/ext/filters/client_channel/health/health_check_client.h"
33
34
  #include "src/core/ext/filters/client_channel/parse_address.h"
34
35
  #include "src/core/ext/filters/client_channel/proxy_mapper_registry.h"
35
36
  #include "src/core/ext/filters/client_channel/subchannel_index.h"
36
- #include "src/core/ext/filters/client_channel/uri_parser.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"
@@ -41,6 +41,7 @@
41
41
  #include "src/core/lib/gpr/alloc.h"
42
42
  #include "src/core/lib/gprpp/debug_location.h"
43
43
  #include "src/core/lib/gprpp/manual_constructor.h"
44
+ #include "src/core/lib/gprpp/mutex_lock.h"
44
45
  #include "src/core/lib/gprpp/ref_counted_ptr.h"
45
46
  #include "src/core/lib/iomgr/sockaddr_utils.h"
46
47
  #include "src/core/lib/iomgr/timer.h"
@@ -49,6 +50,10 @@
49
50
  #include "src/core/lib/surface/channel.h"
50
51
  #include "src/core/lib/surface/channel_init.h"
51
52
  #include "src/core/lib/transport/connectivity_state.h"
53
+ #include "src/core/lib/transport/error_utils.h"
54
+ #include "src/core/lib/transport/service_config.h"
55
+ #include "src/core/lib/transport/status_metadata.h"
56
+ #include "src/core/lib/uri/uri_parser.h"
52
57
 
53
58
  #define INTERNAL_REF_BITS 16
54
59
  #define STRONG_REF_MASK (~(gpr_atm)((1 << INTERNAL_REF_BITS) - 1))
@@ -64,6 +69,10 @@ struct state_watcher {
64
69
  grpc_closure closure;
65
70
  grpc_subchannel* subchannel;
66
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;
67
76
  };
68
77
  } // namespace
69
78
 
@@ -76,6 +85,12 @@ typedef struct external_state_watcher {
76
85
  struct external_state_watcher* prev;
77
86
  } external_state_watcher;
78
87
 
88
+ namespace grpc_core {
89
+
90
+ class ConnectedSubchannelStateWatcher;
91
+
92
+ } // namespace grpc_core
93
+
79
94
  struct grpc_subchannel {
80
95
  grpc_connector* connector;
81
96
 
@@ -107,19 +122,24 @@ struct grpc_subchannel {
107
122
  being setup */
108
123
  grpc_pollset_set* pollset_set;
109
124
 
125
+ grpc_core::UniquePtr<char> health_check_service_name;
126
+
110
127
  /** mutex protecting remaining elements */
111
128
  gpr_mu mu;
112
129
 
113
- /** active connection, or null; of type grpc_core::ConnectedSubchannel
114
- */
130
+ /** active connection, or null */
115
131
  grpc_core::RefCountedPtr<grpc_core::ConnectedSubchannel> connected_subchannel;
132
+ grpc_core::OrphanablePtr<grpc_core::ConnectedSubchannelStateWatcher>
133
+ connected_subchannel_watcher;
116
134
 
117
135
  /** have we seen a disconnection? */
118
136
  bool disconnected;
119
137
  /** are we connecting */
120
138
  bool connecting;
139
+
121
140
  /** connectivity state tracking */
122
141
  grpc_connectivity_state_tracker state_tracker;
142
+ grpc_connectivity_state_tracker state_and_health_tracker;
123
143
 
124
144
  external_state_watcher root_external_state_watcher;
125
145
 
@@ -142,10 +162,184 @@ struct grpc_subchannel {
142
162
  };
143
163
 
144
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
+
145
169
  grpc_core::ConnectedSubchannel* connection;
146
- grpc_closure* schedule_closure_after_destroy;
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;
147
176
  };
148
177
 
178
+ static void maybe_start_connecting_locked(grpc_subchannel* c);
179
+
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";
193
+ }
194
+ GPR_UNREACHABLE_CODE(return "UNKNOWN");
195
+ }
196
+
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);
207
+ }
208
+
209
+ namespace grpc_core {
210
+
211
+ class ConnectedSubchannelStateWatcher
212
+ : public InternallyRefCounted<ConnectedSubchannelStateWatcher> {
213
+ public:
214
+ // Must be instantiated while holding c->mu.
215
+ explicit ConnectedSubchannelStateWatcher(grpc_subchannel* c)
216
+ : subchannel_(c) {
217
+ // Steal subchannel ref for connecting.
218
+ GRPC_SUBCHANNEL_WEAK_REF(subchannel_, "state_watcher");
219
+ GRPC_SUBCHANNEL_WEAK_UNREF(subchannel_, "connecting");
220
+ // Start watching for connectivity state changes.
221
+ // Callback uses initial ref to this.
222
+ GRPC_CLOSURE_INIT(&on_connectivity_changed_, OnConnectivityChanged, this,
223
+ grpc_schedule_on_exec_ctx);
224
+ c->connected_subchannel->NotifyOnStateChange(c->pollset_set,
225
+ &pending_connectivity_state_,
226
+ &on_connectivity_changed_);
227
+ // Start health check if needed.
228
+ 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);
233
+ GRPC_CLOSURE_INIT(&on_health_changed_, OnHealthChanged, this,
234
+ grpc_schedule_on_exec_ctx);
235
+ Ref().release(); // Ref for health callback tracked manually.
236
+ health_check_client_->NotifyOnHealthChange(&health_state_,
237
+ &on_health_changed_);
238
+ health_state = GRPC_CHANNEL_CONNECTING;
239
+ }
240
+ // 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,
244
+ GRPC_ERROR_NONE, "subchannel_connected");
245
+ }
246
+
247
+ ~ConnectedSubchannelStateWatcher() {
248
+ GRPC_SUBCHANNEL_WEAK_UNREF(subchannel_, "state_watcher");
249
+ }
250
+
251
+ void Orphan() override { health_check_client_.reset(); }
252
+
253
+ private:
254
+ static void OnConnectivityChanged(void* arg, grpc_error* error) {
255
+ auto* self = static_cast<ConnectedSubchannelStateWatcher*>(arg);
256
+ grpc_subchannel* c = self->subchannel_;
257
+ {
258
+ MutexLock lock(&c->mu);
259
+ switch (self->pending_connectivity_state_) {
260
+ case GRPC_CHANNEL_TRANSIENT_FAILURE:
261
+ case GRPC_CHANNEL_SHUTDOWN: {
262
+ if (!c->disconnected && c->connected_subchannel != nullptr) {
263
+ if (grpc_trace_stream_refcount.enabled()) {
264
+ gpr_log(GPR_INFO,
265
+ "Connected subchannel %p of subchannel %p has gone into "
266
+ "%s. Attempting to reconnect.",
267
+ c->connected_subchannel.get(), c,
268
+ grpc_connectivity_state_name(
269
+ self->pending_connectivity_state_));
270
+ }
271
+ c->connected_subchannel.reset();
272
+ c->connected_subchannel_watcher.reset();
273
+ 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,
278
+ GRPC_CHANNEL_TRANSIENT_FAILURE,
279
+ GRPC_ERROR_REF(error), "reflect_child");
280
+ c->backoff_begun = false;
281
+ c->backoff->Reset();
282
+ maybe_start_connecting_locked(c);
283
+ } else {
284
+ self->last_connectivity_state_ = GRPC_CHANNEL_SHUTDOWN;
285
+ }
286
+ self->health_check_client_.reset();
287
+ break;
288
+ }
289
+ default: {
290
+ // In principle, this should never happen. We should not get
291
+ // a callback for READY, because that was the state we started
292
+ // this watch from. And a connected subchannel should never go
293
+ // from READY to CONNECTING or IDLE.
294
+ 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");
298
+ if (self->pending_connectivity_state_ != GRPC_CHANNEL_READY) {
299
+ grpc_connectivity_state_set(&c->state_and_health_tracker,
300
+ self->pending_connectivity_state_,
301
+ GRPC_ERROR_REF(error), "reflect_child");
302
+ }
303
+ c->connected_subchannel->NotifyOnStateChange(
304
+ nullptr, &self->pending_connectivity_state_,
305
+ &self->on_connectivity_changed_);
306
+ self = nullptr; // So we don't unref below.
307
+ }
308
+ }
309
+ }
310
+ // Don't unref until we've released the lock, because this might
311
+ // cause the subchannel (which contains the lock) to be destroyed.
312
+ if (self != nullptr) self->Unref();
313
+ }
314
+
315
+ static void OnHealthChanged(void* arg, grpc_error* error) {
316
+ 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");
327
+ }
328
+ self->health_check_client_->NotifyOnHealthChange(&self->health_state_,
329
+ &self->on_health_changed_);
330
+ }
331
+
332
+ grpc_subchannel* subchannel_;
333
+ grpc_closure on_connectivity_changed_;
334
+ grpc_connectivity_state pending_connectivity_state_ = GRPC_CHANNEL_READY;
335
+ grpc_connectivity_state last_connectivity_state_ = GRPC_CHANNEL_READY;
336
+ grpc_core::OrphanablePtr<grpc_core::HealthCheckClient> health_check_client_;
337
+ grpc_closure on_health_changed_;
338
+ grpc_connectivity_state health_state_ = GRPC_CHANNEL_CONNECTING;
339
+ };
340
+
341
+ } // namespace grpc_core
342
+
149
343
  #define SUBCHANNEL_CALL_TO_CALL_STACK(call) \
150
344
  (grpc_call_stack*)((char*)(call) + GPR_ROUND_UP_TO_ALIGNMENT_SIZE( \
151
345
  sizeof(grpc_subchannel_call)))
@@ -191,8 +385,10 @@ static void subchannel_destroy(void* arg, grpc_error* error) {
191
385
  c->channelz_subchannel.reset();
192
386
  }
193
387
  gpr_free((void*)c->filters);
388
+ c->health_check_service_name.reset();
194
389
  grpc_channel_args_destroy(c->args);
195
390
  grpc_connectivity_state_destroy(&c->state_tracker);
391
+ grpc_connectivity_state_destroy(&c->state_and_health_tracker);
196
392
  grpc_connector_unref(c->connector);
197
393
  grpc_pollset_set_destroy(c->pollset_set);
198
394
  grpc_subchannel_key_destroy(c->key);
@@ -255,6 +451,7 @@ static void disconnect(grpc_subchannel* c) {
255
451
  grpc_connector_shutdown(c->connector, GRPC_ERROR_CREATE_FROM_STATIC_STRING(
256
452
  "Subchannel disconnected"));
257
453
  c->connected_subchannel.reset();
454
+ c->connected_subchannel_watcher.reset();
258
455
  gpr_mu_unlock(&c->mu);
259
456
  }
260
457
 
@@ -330,6 +527,31 @@ static void parse_args_for_backoff_values(
330
527
  .set_max_backoff(max_backoff_ms);
331
528
  }
332
529
 
530
+ namespace grpc_core {
531
+ namespace {
532
+
533
+ struct HealthCheckParams {
534
+ UniquePtr<char> service_name;
535
+
536
+ static void Parse(const grpc_json* field, HealthCheckParams* params) {
537
+ if (strcmp(field->key, "healthCheckConfig") == 0) {
538
+ if (field->type != GRPC_JSON_OBJECT) return;
539
+ for (grpc_json* sub_field = field->child; sub_field != nullptr;
540
+ sub_field = sub_field->next) {
541
+ if (sub_field->key == nullptr) return;
542
+ if (strcmp(sub_field->key, "serviceName") == 0) {
543
+ if (params->service_name != nullptr) return; // Duplicate.
544
+ if (sub_field->type != GRPC_JSON_STRING) return;
545
+ params->service_name.reset(gpr_strdup(sub_field->value));
546
+ }
547
+ }
548
+ }
549
+ }
550
+ };
551
+
552
+ } // namespace
553
+ } // namespace grpc_core
554
+
333
555
  grpc_subchannel* grpc_subchannel_create(grpc_connector* connector,
334
556
  const grpc_subchannel_args* args) {
335
557
  grpc_subchannel_key* key = grpc_subchannel_key_create(args);
@@ -380,12 +602,28 @@ grpc_subchannel* grpc_subchannel_create(grpc_connector* connector,
380
602
  grpc_schedule_on_exec_ctx);
381
603
  grpc_connectivity_state_init(&c->state_tracker, GRPC_CHANNEL_IDLE,
382
604
  "subchannel");
605
+ grpc_connectivity_state_init(&c->state_and_health_tracker, GRPC_CHANNEL_IDLE,
606
+ "subchannel");
383
607
  grpc_core::BackOff::Options backoff_options;
384
608
  parse_args_for_backoff_values(args->args, &backoff_options,
385
609
  &c->min_connect_timeout_ms);
386
610
  c->backoff.Init(backoff_options);
387
611
  gpr_mu_init(&c->mu);
388
612
 
613
+ // Check whether we should enable health checking.
614
+ const char* service_config_json = grpc_channel_arg_get_string(
615
+ grpc_channel_args_find(c->args, GRPC_ARG_SERVICE_CONFIG));
616
+ if (service_config_json != nullptr) {
617
+ grpc_core::UniquePtr<grpc_core::ServiceConfig> service_config =
618
+ grpc_core::ServiceConfig::Create(service_config_json);
619
+ 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);
624
+ }
625
+ }
626
+
389
627
  const grpc_arg* arg =
390
628
  grpc_channel_args_find(c->args, GRPC_ARG_ENABLE_CHANNELZ);
391
629
  bool channelz_enabled =
@@ -429,17 +667,21 @@ static void continue_connect_locked(grpc_subchannel* c) {
429
667
  c->next_attempt_deadline = c->backoff->NextAttemptTime();
430
668
  args.deadline = std::max(c->next_attempt_deadline, min_deadline);
431
669
  args.channel_args = c->args;
432
- grpc_connectivity_state_set(&c->state_tracker, GRPC_CHANNEL_CONNECTING,
433
- GRPC_ERROR_NONE, "connecting");
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");
434
675
  grpc_connector_connect(c->connector, &args, &c->connecting_result,
435
676
  &c->on_connected);
436
677
  }
437
678
 
438
- grpc_connectivity_state grpc_subchannel_check_connectivity(grpc_subchannel* c,
439
- grpc_error** error) {
440
- grpc_connectivity_state state;
679
+ grpc_connectivity_state grpc_subchannel_check_connectivity(
680
+ grpc_subchannel* c, grpc_error** error, bool inhibit_health_checks) {
441
681
  gpr_mu_lock(&c->mu);
442
- state = grpc_connectivity_state_get(&c->state_tracker, error);
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);
443
685
  gpr_mu_unlock(&c->mu);
444
686
  return state;
445
687
  }
@@ -497,7 +739,8 @@ static void maybe_start_connecting_locked(grpc_subchannel* c) {
497
739
  /* Already connected: don't restart */
498
740
  return;
499
741
  }
500
- if (!grpc_connectivity_state_has_watchers(&c->state_tracker)) {
742
+ if (!grpc_connectivity_state_has_watchers(&c->state_tracker) &&
743
+ !grpc_connectivity_state_has_watchers(&c->state_and_health_tracker)) {
501
744
  /* Nobody is interested in connecting: so don't just yet */
502
745
  return;
503
746
  }
@@ -524,16 +767,18 @@ static void maybe_start_connecting_locked(grpc_subchannel* c) {
524
767
 
525
768
  void grpc_subchannel_notify_on_state_change(
526
769
  grpc_subchannel* c, grpc_pollset_set* interested_parties,
527
- grpc_connectivity_state* state, grpc_closure* notify) {
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;
528
774
  external_state_watcher* w;
529
-
530
775
  if (state == nullptr) {
531
776
  gpr_mu_lock(&c->mu);
532
777
  for (w = c->root_external_state_watcher.next;
533
778
  w != &c->root_external_state_watcher; w = w->next) {
534
779
  if (w->notify == notify) {
535
- grpc_connectivity_state_notify_on_state_change(&c->state_tracker,
536
- nullptr, &w->closure);
780
+ grpc_connectivity_state_notify_on_state_change(tracker, nullptr,
781
+ &w->closure);
537
782
  }
538
783
  }
539
784
  gpr_mu_unlock(&c->mu);
@@ -552,62 +797,12 @@ void grpc_subchannel_notify_on_state_change(
552
797
  w->next = &c->root_external_state_watcher;
553
798
  w->prev = w->next->prev;
554
799
  w->next->prev = w->prev->next = w;
555
- grpc_connectivity_state_notify_on_state_change(&c->state_tracker, state,
556
- &w->closure);
800
+ grpc_connectivity_state_notify_on_state_change(tracker, state, &w->closure);
557
801
  maybe_start_connecting_locked(c);
558
802
  gpr_mu_unlock(&c->mu);
559
803
  }
560
804
  }
561
805
 
562
- static void on_connected_subchannel_connectivity_changed(void* p,
563
- grpc_error* error) {
564
- state_watcher* connected_subchannel_watcher = static_cast<state_watcher*>(p);
565
- grpc_subchannel* c = connected_subchannel_watcher->subchannel;
566
- gpr_mu* mu = &c->mu;
567
-
568
- gpr_mu_lock(mu);
569
-
570
- switch (connected_subchannel_watcher->connectivity_state) {
571
- case GRPC_CHANNEL_TRANSIENT_FAILURE:
572
- case GRPC_CHANNEL_SHUTDOWN: {
573
- if (!c->disconnected && c->connected_subchannel != nullptr) {
574
- if (grpc_trace_stream_refcount.enabled()) {
575
- gpr_log(GPR_INFO,
576
- "Connected subchannel %p of subchannel %p has gone into %s. "
577
- "Attempting to reconnect.",
578
- c->connected_subchannel.get(), c,
579
- grpc_connectivity_state_name(
580
- connected_subchannel_watcher->connectivity_state));
581
- }
582
- c->connected_subchannel.reset();
583
- grpc_connectivity_state_set(&c->state_tracker,
584
- GRPC_CHANNEL_TRANSIENT_FAILURE,
585
- GRPC_ERROR_REF(error), "reflect_child");
586
- c->backoff_begun = false;
587
- c->backoff->Reset();
588
- maybe_start_connecting_locked(c);
589
- } else {
590
- connected_subchannel_watcher->connectivity_state =
591
- GRPC_CHANNEL_SHUTDOWN;
592
- }
593
- break;
594
- }
595
- default: {
596
- grpc_connectivity_state_set(
597
- &c->state_tracker, connected_subchannel_watcher->connectivity_state,
598
- GRPC_ERROR_REF(error), "reflect_child");
599
- GRPC_SUBCHANNEL_WEAK_REF(c, "state_watcher");
600
- c->connected_subchannel->NotifyOnStateChange(
601
- nullptr, &connected_subchannel_watcher->connectivity_state,
602
- &connected_subchannel_watcher->closure);
603
- connected_subchannel_watcher = nullptr;
604
- }
605
- }
606
- gpr_mu_unlock(mu);
607
- GRPC_SUBCHANNEL_WEAK_UNREF(c, "state_watcher");
608
- gpr_free(connected_subchannel_watcher);
609
- }
610
-
611
806
  static bool publish_transport_locked(grpc_subchannel* c) {
612
807
  /* construct channel stack */
613
808
  grpc_channel_stack_builder* builder = grpc_channel_stack_builder_create();
@@ -634,17 +829,7 @@ static bool publish_transport_locked(grpc_subchannel* c) {
634
829
  intptr_t socket_uuid = c->connecting_result.socket_uuid;
635
830
  memset(&c->connecting_result, 0, sizeof(c->connecting_result));
636
831
 
637
- /* initialize state watcher */
638
- state_watcher* connected_subchannel_watcher = static_cast<state_watcher*>(
639
- gpr_zalloc(sizeof(*connected_subchannel_watcher)));
640
- connected_subchannel_watcher->subchannel = c;
641
- connected_subchannel_watcher->connectivity_state = GRPC_CHANNEL_READY;
642
- GRPC_CLOSURE_INIT(&connected_subchannel_watcher->closure,
643
- on_connected_subchannel_connectivity_changed,
644
- connected_subchannel_watcher, grpc_schedule_on_exec_ctx);
645
-
646
832
  if (c->disconnected) {
647
- gpr_free(connected_subchannel_watcher);
648
833
  grpc_channel_stack_destroy(stk);
649
834
  gpr_free(stk);
650
835
  return false;
@@ -652,21 +837,14 @@ static bool publish_transport_locked(grpc_subchannel* c) {
652
837
 
653
838
  /* publish */
654
839
  c->connected_subchannel.reset(grpc_core::New<grpc_core::ConnectedSubchannel>(
655
- stk, c->channelz_subchannel.get(), socket_uuid));
840
+ stk, c->channelz_subchannel, socket_uuid));
656
841
  gpr_log(GPR_INFO, "New connected subchannel at %p for subchannel %p",
657
842
  c->connected_subchannel.get(), c);
658
843
 
659
- /* setup subchannel watching connected subchannel for changes; subchannel
660
- ref for connecting is donated to the state watcher */
661
- GRPC_SUBCHANNEL_WEAK_REF(c, "state_watcher");
662
- GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting");
663
- c->connected_subchannel->NotifyOnStateChange(
664
- c->pollset_set, &connected_subchannel_watcher->connectivity_state,
665
- &connected_subchannel_watcher->closure);
666
-
667
- /* signal completion */
668
- grpc_connectivity_state_set(&c->state_tracker, GRPC_CHANNEL_READY,
669
- GRPC_ERROR_NONE, "connected");
844
+ // Instantiate state watcher. Will clean itself up.
845
+ c->connected_subchannel_watcher =
846
+ grpc_core::MakeOrphanable<grpc_core::ConnectedSubchannelStateWatcher>(c);
847
+
670
848
  return true;
671
849
  }
672
850
 
@@ -683,8 +861,14 @@ static void on_subchannel_connected(void* arg, grpc_error* error) {
683
861
  } else if (c->disconnected) {
684
862
  GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting");
685
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");
686
870
  grpc_connectivity_state_set(
687
- &c->state_tracker, GRPC_CHANNEL_TRANSIENT_FAILURE,
871
+ &c->state_and_health_tracker, GRPC_CHANNEL_TRANSIENT_FAILURE,
688
872
  grpc_error_set_int(GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
689
873
  "Connect Failed", &error, 1),
690
874
  GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE),
@@ -725,6 +909,7 @@ static void subchannel_call_destroy(void* call, grpc_error* error) {
725
909
  grpc_call_stack_destroy(SUBCHANNEL_CALL_TO_CALL_STACK(c), nullptr,
726
910
  c->schedule_closure_after_destroy);
727
911
  connection->Unref(DEBUG_LOCATION, "subchannel_call");
912
+ c->~grpc_subchannel_call();
728
913
  }
729
914
 
730
915
  void grpc_subchannel_call_set_cleanup_closure(grpc_subchannel_call* call,
@@ -745,9 +930,71 @@ void grpc_subchannel_call_unref(
745
930
  GRPC_CALL_STACK_UNREF(SUBCHANNEL_CALL_TO_CALL_STACK(c), REF_REASON);
746
931
  }
747
932
 
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);
940
+ } 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;
946
+ }
947
+ }
948
+ GRPC_ERROR_UNREF(error);
949
+ }
950
+
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();
962
+ } else {
963
+ channelz_subchannel->RecordCallFailed();
964
+ }
965
+ GRPC_CLOSURE_RUN(call->original_recv_trailing_metadata,
966
+ GRPC_ERROR_REF(error));
967
+ }
968
+
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
+
748
994
  void grpc_subchannel_call_process_op(grpc_subchannel_call* call,
749
995
  grpc_transport_stream_op_batch* batch) {
750
996
  GPR_TIMER_SCOPE("grpc_subchannel_call_process_op", 0);
997
+ maybe_intercept_recv_trailing_metadata(call, batch);
751
998
  grpc_call_stack* call_stack = SUBCHANNEL_CALL_TO_CALL_STACK(call);
752
999
  grpc_call_element* top_elem = grpc_call_stack_element(call_stack, 0);
753
1000
  GRPC_CALL_LOG_OP(GPR_INFO, top_elem, batch);
@@ -822,10 +1069,12 @@ namespace grpc_core {
822
1069
 
823
1070
  ConnectedSubchannel::ConnectedSubchannel(
824
1071
  grpc_channel_stack* channel_stack,
825
- channelz::SubchannelNode* channelz_subchannel, intptr_t socket_uuid)
1072
+ grpc_core::RefCountedPtr<grpc_core::channelz::SubchannelNode>
1073
+ channelz_subchannel,
1074
+ intptr_t socket_uuid)
826
1075
  : RefCountedWithTracing<ConnectedSubchannel>(&grpc_trace_stream_refcount),
827
1076
  channel_stack_(channel_stack),
828
- channelz_subchannel_(channelz_subchannel),
1077
+ channelz_subchannel_(std::move(channelz_subchannel)),
829
1078
  socket_uuid_(socket_uuid) {}
830
1079
 
831
1080
  ConnectedSubchannel::~ConnectedSubchannel() {
@@ -856,22 +1105,14 @@ void ConnectedSubchannel::Ping(grpc_closure* on_initiate,
856
1105
 
857
1106
  grpc_error* ConnectedSubchannel::CreateCall(const CallArgs& args,
858
1107
  grpc_subchannel_call** call) {
859
- size_t allocation_size =
860
- GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_subchannel_call));
861
- if (args.parent_data_size > 0) {
862
- allocation_size +=
863
- GPR_ROUND_UP_TO_ALIGNMENT_SIZE(channel_stack_->call_stack_size) +
864
- args.parent_data_size;
865
- } else {
866
- allocation_size += channel_stack_->call_stack_size;
867
- }
868
- *call = static_cast<grpc_subchannel_call*>(
869
- gpr_arena_alloc(args.arena, allocation_size));
1108
+ const size_t allocation_size =
1109
+ GetInitialCallSizeEstimate(args.parent_data_size);
1110
+ *call = new (gpr_arena_alloc(args.arena, allocation_size))
1111
+ grpc_subchannel_call(this, args);
870
1112
  grpc_call_stack* callstk = SUBCHANNEL_CALL_TO_CALL_STACK(*call);
871
1113
  RefCountedPtr<ConnectedSubchannel> connection =
872
1114
  Ref(DEBUG_LOCATION, "subchannel_call");
873
1115
  connection.release(); // Ref is passed to the grpc_subchannel_call object.
874
- (*call)->connection = this;
875
1116
  const grpc_call_element_args call_args = {
876
1117
  callstk, /* call_stack */
877
1118
  nullptr, /* server_transport_data */
@@ -890,7 +1131,24 @@ grpc_error* ConnectedSubchannel::CreateCall(const CallArgs& args,
890
1131
  return error;
891
1132
  }
892
1133
  grpc_call_stack_set_pollset_or_pollset_set(callstk, args.pollent);
1134
+ if (channelz_subchannel_ != nullptr) {
1135
+ channelz_subchannel_->RecordCallStarted();
1136
+ }
893
1137
  return GRPC_ERROR_NONE;
894
1138
  }
895
1139
 
1140
+ size_t ConnectedSubchannel::GetInitialCallSizeEstimate(
1141
+ size_t parent_data_size) const {
1142
+ size_t allocation_size =
1143
+ GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_subchannel_call));
1144
+ if (parent_data_size > 0) {
1145
+ allocation_size +=
1146
+ GPR_ROUND_UP_TO_ALIGNMENT_SIZE(channel_stack_->call_stack_size) +
1147
+ parent_data_size;
1148
+ } else {
1149
+ allocation_size += channel_stack_->call_stack_size;
1150
+ }
1151
+ return allocation_size;
1152
+ }
1153
+
896
1154
  } // namespace grpc_core