grpc 1.18.0 → 1.22.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of grpc might be problematic. Click here for more details.

Files changed (428) hide show
  1. checksums.yaml +4 -4
  2. data/Makefile +4731 -7404
  3. data/etc/roots.pem +146 -0
  4. data/include/grpc/grpc.h +11 -6
  5. data/include/grpc/grpc_security.h +297 -4
  6. data/include/grpc/grpc_security_constants.h +1 -1
  7. data/include/grpc/impl/codegen/byte_buffer.h +13 -0
  8. data/include/grpc/impl/codegen/gpr_types.h +1 -1
  9. data/include/grpc/impl/codegen/grpc_types.h +30 -7
  10. data/include/grpc/impl/codegen/port_platform.h +88 -7
  11. data/include/grpc/impl/codegen/slice.h +2 -22
  12. data/include/grpc/impl/codegen/status.h +2 -1
  13. data/include/grpc/impl/codegen/sync_posix.h +18 -0
  14. data/include/grpc/slice.h +3 -3
  15. data/src/core/ext/filters/client_channel/backup_poller.cc +21 -16
  16. data/src/core/ext/filters/client_channel/backup_poller.h +8 -2
  17. data/src/core/ext/filters/client_channel/channel_connectivity.cc +3 -1
  18. data/src/core/ext/filters/client_channel/client_channel.cc +2435 -1557
  19. data/src/core/ext/filters/client_channel/client_channel.h +2 -10
  20. data/src/core/ext/filters/client_channel/client_channel_channelz.cc +6 -89
  21. data/src/core/ext/filters/client_channel/client_channel_channelz.h +8 -33
  22. data/src/core/ext/filters/client_channel/client_channel_factory.cc +22 -34
  23. data/src/core/ext/filters/client_channel/client_channel_factory.h +19 -38
  24. data/src/core/ext/filters/client_channel/client_channel_plugin.cc +9 -11
  25. data/src/core/ext/filters/client_channel/global_subchannel_pool.cc +179 -0
  26. data/src/core/ext/filters/client_channel/global_subchannel_pool.h +68 -0
  27. data/src/core/ext/filters/client_channel/health/health_check_client.cc +59 -55
  28. data/src/core/ext/filters/client_channel/health/health_check_client.h +20 -9
  29. data/src/core/ext/filters/client_channel/http_connect_handshaker.cc +146 -157
  30. data/src/core/ext/filters/client_channel/http_connect_handshaker.h +1 -1
  31. data/src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.cc +29 -32
  32. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc +844 -859
  33. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h +3 -1
  34. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.cc +2 -6
  35. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.cc +6 -2
  36. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h +14 -12
  37. data/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc +16 -12
  38. data/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h +3 -3
  39. data/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc +185 -312
  40. data/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc +143 -375
  41. data/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h +192 -245
  42. data/src/core/ext/filters/client_channel/lb_policy/xds/xds.cc +1554 -955
  43. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_channel_secure.cc +0 -43
  44. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_load_balancer_api.cc +14 -10
  45. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_load_balancer_api.h +2 -2
  46. data/src/core/ext/filters/client_channel/lb_policy.cc +115 -22
  47. data/src/core/ext/filters/client_channel/lb_policy.h +260 -129
  48. data/src/core/ext/filters/client_channel/lb_policy_factory.h +5 -2
  49. data/src/core/ext/filters/client_channel/lb_policy_registry.cc +107 -4
  50. data/src/core/ext/filters/client_channel/lb_policy_registry.h +10 -3
  51. data/src/core/ext/filters/client_channel/local_subchannel_pool.cc +96 -0
  52. data/src/core/ext/filters/client_channel/local_subchannel_pool.h +56 -0
  53. data/src/core/ext/filters/client_channel/parse_address.cc +24 -5
  54. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc +121 -122
  55. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc +84 -2
  56. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h +3 -0
  57. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_libuv.cc +179 -0
  58. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc +24 -10
  59. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc +111 -47
  60. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h +7 -13
  61. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc +2 -2
  62. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_libuv.cc +39 -0
  63. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc +0 -6
  64. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc +2 -64
  65. data/src/core/ext/filters/client_channel/resolver/dns/dns_resolver_selection.cc +28 -0
  66. data/src/core/{lib/iomgr/network_status_tracker.cc → ext/filters/client_channel/resolver/dns/dns_resolver_selection.h} +8 -15
  67. data/src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc +36 -82
  68. data/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc +111 -72
  69. data/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h +13 -8
  70. data/src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc +28 -63
  71. data/src/core/ext/filters/client_channel/resolver.cc +54 -1
  72. data/src/core/ext/filters/client_channel/resolver.h +52 -23
  73. data/src/core/ext/filters/client_channel/resolver_factory.h +3 -1
  74. data/src/core/ext/filters/client_channel/resolver_registry.cc +5 -2
  75. data/src/core/ext/filters/client_channel/resolver_registry.h +5 -4
  76. data/src/core/ext/filters/client_channel/resolver_result_parsing.cc +368 -241
  77. data/src/core/ext/filters/client_channel/resolver_result_parsing.h +58 -76
  78. data/src/core/ext/filters/client_channel/resolving_lb_policy.cc +543 -0
  79. data/src/core/ext/filters/client_channel/resolving_lb_policy.h +139 -0
  80. data/src/core/ext/filters/client_channel/server_address.cc +4 -54
  81. data/src/core/ext/filters/client_channel/server_address.h +1 -13
  82. data/src/core/ext/filters/client_channel/service_config.cc +329 -0
  83. data/src/core/ext/filters/client_channel/service_config.h +205 -0
  84. data/src/core/ext/filters/client_channel/subchannel.cc +803 -838
  85. data/src/core/ext/filters/client_channel/subchannel.h +295 -128
  86. data/src/core/ext/filters/client_channel/subchannel_interface.h +113 -0
  87. data/src/core/ext/filters/client_channel/subchannel_pool_interface.cc +97 -0
  88. data/src/core/ext/filters/client_channel/subchannel_pool_interface.h +94 -0
  89. data/src/core/ext/filters/deadline/deadline_filter.cc +3 -4
  90. data/src/core/ext/filters/deadline/deadline_filter.h +3 -2
  91. data/src/core/ext/filters/http/client/http_client_filter.cc +7 -5
  92. data/src/core/ext/filters/http/client/http_client_filter.h +1 -1
  93. data/src/core/ext/filters/http/client_authority_filter.cc +6 -3
  94. data/src/core/ext/filters/http/message_compress/message_compress_filter.cc +4 -3
  95. data/src/core/ext/filters/http/server/http_server_filter.cc +18 -12
  96. data/src/core/ext/filters/max_age/max_age_filter.cc +5 -2
  97. data/src/core/ext/filters/message_size/message_size_filter.cc +119 -77
  98. data/src/core/ext/filters/message_size/message_size_filter.h +33 -0
  99. data/src/core/ext/transport/chttp2/alpn/alpn.h +1 -1
  100. data/src/core/ext/transport/chttp2/client/chttp2_connector.cc +13 -12
  101. data/src/core/ext/transport/chttp2/client/insecure/channel_create.cc +45 -47
  102. data/src/core/ext/transport/chttp2/client/secure/secure_channel_create.cc +134 -143
  103. data/src/core/ext/transport/chttp2/server/chttp2_server.cc +68 -21
  104. data/src/core/ext/transport/chttp2/transport/bin_decoder.cc +4 -4
  105. data/src/core/ext/transport/chttp2/transport/bin_decoder.h +4 -4
  106. data/src/core/ext/transport/chttp2/transport/bin_encoder.cc +7 -6
  107. data/src/core/ext/transport/chttp2/transport/bin_encoder.h +4 -3
  108. data/src/core/ext/transport/chttp2/transport/chttp2_plugin.cc +9 -7
  109. data/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +156 -94
  110. data/src/core/ext/transport/chttp2/transport/flow_control.cc +2 -2
  111. data/src/core/ext/transport/chttp2/transport/flow_control.h +1 -1
  112. data/src/core/ext/transport/chttp2/transport/frame_data.cc +33 -37
  113. data/src/core/ext/transport/chttp2/transport/frame_data.h +1 -1
  114. data/src/core/ext/transport/chttp2/transport/frame_goaway.cc +6 -5
  115. data/src/core/ext/transport/chttp2/transport/frame_goaway.h +3 -2
  116. data/src/core/ext/transport/chttp2/transport/frame_ping.cc +5 -4
  117. data/src/core/ext/transport/chttp2/transport/frame_ping.h +1 -1
  118. data/src/core/ext/transport/chttp2/transport/frame_rst_stream.cc +8 -6
  119. data/src/core/ext/transport/chttp2/transport/frame_rst_stream.h +2 -1
  120. data/src/core/ext/transport/chttp2/transport/frame_settings.cc +6 -4
  121. data/src/core/ext/transport/chttp2/transport/frame_settings.h +2 -1
  122. data/src/core/ext/transport/chttp2/transport/frame_window_update.cc +7 -6
  123. data/src/core/ext/transport/chttp2/transport/frame_window_update.h +1 -1
  124. data/src/core/ext/transport/chttp2/transport/hpack_encoder.cc +74 -55
  125. data/src/core/ext/transport/chttp2/transport/hpack_parser.cc +33 -11
  126. data/src/core/ext/transport/chttp2/transport/hpack_parser.h +3 -2
  127. data/src/core/ext/transport/chttp2/transport/hpack_table.cc +7 -14
  128. data/src/core/ext/transport/chttp2/transport/hpack_table.h +10 -1
  129. data/src/core/ext/transport/chttp2/transport/incoming_metadata.cc +9 -5
  130. data/src/core/ext/transport/chttp2/transport/incoming_metadata.h +9 -3
  131. data/src/core/ext/transport/chttp2/transport/internal.h +43 -30
  132. data/src/core/ext/transport/chttp2/transport/parsing.cc +52 -70
  133. data/src/core/ext/transport/chttp2/transport/stream_lists.cc +3 -3
  134. data/src/core/ext/transport/chttp2/transport/writing.cc +70 -33
  135. data/src/core/ext/transport/inproc/inproc_transport.cc +26 -18
  136. data/src/core/lib/channel/channel_args.cc +2 -101
  137. data/src/core/lib/channel/channel_args.h +3 -37
  138. data/src/core/lib/channel/channel_stack.h +10 -6
  139. data/src/core/lib/channel/channel_trace.cc +4 -4
  140. data/src/core/lib/channel/channel_trace.h +4 -4
  141. data/src/core/lib/channel/channelz.cc +168 -38
  142. data/src/core/lib/channel/channelz.h +40 -44
  143. data/src/core/lib/channel/channelz_registry.cc +75 -107
  144. data/src/core/lib/channel/channelz_registry.h +10 -28
  145. data/src/core/lib/channel/connected_channel.cc +2 -2
  146. data/src/core/lib/channel/context.h +2 -2
  147. data/src/core/lib/channel/handshaker.cc +151 -218
  148. data/src/core/lib/channel/handshaker.h +110 -101
  149. data/src/core/lib/channel/handshaker_factory.h +11 -19
  150. data/src/core/lib/channel/handshaker_registry.cc +67 -51
  151. data/src/core/lib/channel/handshaker_registry.h +21 -16
  152. data/src/core/lib/compression/algorithm_metadata.h +3 -3
  153. data/src/core/lib/compression/compression.cc +14 -9
  154. data/src/core/lib/compression/compression_args.cc +127 -0
  155. data/src/core/lib/compression/compression_args.h +55 -0
  156. data/src/core/lib/compression/compression_internal.cc +16 -12
  157. data/src/core/lib/compression/compression_internal.h +1 -1
  158. data/src/core/lib/compression/stream_compression.cc +3 -2
  159. data/src/core/lib/compression/stream_compression.h +2 -2
  160. data/src/core/lib/compression/stream_compression_gzip.cc +9 -9
  161. data/src/core/lib/debug/trace.cc +13 -7
  162. data/src/core/lib/debug/trace.h +14 -1
  163. data/src/core/lib/gpr/arena.h +13 -9
  164. data/src/core/lib/gpr/cpu_posix.cc +5 -3
  165. data/src/core/lib/gpr/env.h +3 -6
  166. data/src/core/lib/gpr/env_linux.cc +6 -1
  167. data/src/core/lib/gpr/env_posix.cc +5 -0
  168. data/src/core/lib/gpr/env_windows.cc +7 -5
  169. data/src/core/lib/gpr/log.cc +9 -13
  170. data/src/core/lib/gpr/log_posix.cc +2 -1
  171. data/src/core/lib/gpr/string.cc +20 -7
  172. data/src/core/lib/gpr/string.h +10 -3
  173. data/src/core/lib/gpr/sync_posix.cc +65 -4
  174. data/src/core/lib/gpr/time.cc +8 -0
  175. data/src/core/lib/gpr/time_posix.cc +21 -2
  176. data/src/core/lib/gprpp/arena.cc +103 -0
  177. data/src/core/lib/gprpp/arena.h +121 -0
  178. data/src/core/lib/gprpp/atomic.h +75 -5
  179. data/src/core/lib/gprpp/fork.cc +13 -32
  180. data/src/core/lib/gprpp/fork.h +5 -1
  181. data/src/core/lib/gprpp/global_config.h +96 -0
  182. data/src/core/lib/gprpp/global_config_custom.h +29 -0
  183. data/src/core/lib/gprpp/global_config_env.cc +135 -0
  184. data/src/core/lib/gprpp/global_config_env.h +131 -0
  185. data/src/core/lib/gprpp/global_config_generic.h +44 -0
  186. data/src/core/lib/gprpp/inlined_vector.h +8 -0
  187. data/src/core/lib/gprpp/map.h +436 -0
  188. data/src/core/lib/gprpp/memory.h +2 -2
  189. data/src/core/lib/gprpp/optional.h +48 -0
  190. data/src/core/lib/gprpp/orphanable.h +6 -5
  191. data/src/core/lib/gprpp/{mutex_lock.h → pair.h} +15 -19
  192. data/src/core/lib/gprpp/ref_counted.h +36 -17
  193. data/src/core/lib/gprpp/sync.h +126 -0
  194. data/src/core/lib/gprpp/thd.h +42 -7
  195. data/src/core/lib/gprpp/thd_posix.cc +31 -13
  196. data/src/core/lib/gprpp/thd_windows.cc +47 -34
  197. data/src/core/lib/http/httpcli.cc +6 -5
  198. data/src/core/lib/http/httpcli_security_connector.cc +13 -15
  199. data/src/core/lib/http/parser.cc +3 -2
  200. data/src/core/lib/http/parser.h +2 -1
  201. data/src/core/lib/iomgr/buffer_list.cc +182 -24
  202. data/src/core/lib/iomgr/buffer_list.h +72 -10
  203. data/src/core/lib/iomgr/call_combiner.cc +84 -90
  204. data/src/core/lib/iomgr/call_combiner.h +75 -82
  205. data/src/core/lib/iomgr/cfstream_handle.cc +203 -0
  206. data/src/core/lib/iomgr/cfstream_handle.h +86 -0
  207. data/src/core/lib/iomgr/combiner.cc +11 -3
  208. data/src/core/lib/iomgr/combiner.h +1 -1
  209. data/src/core/lib/iomgr/endpoint.cc +2 -2
  210. data/src/core/lib/iomgr/endpoint.h +3 -2
  211. data/src/core/lib/iomgr/endpoint_cfstream.cc +375 -0
  212. data/src/core/lib/iomgr/endpoint_cfstream.h +49 -0
  213. data/src/core/lib/iomgr/endpoint_pair_windows.cc +2 -2
  214. data/src/core/lib/iomgr/error.cc +21 -17
  215. data/src/core/lib/iomgr/error.h +36 -6
  216. data/src/core/lib/iomgr/error_cfstream.cc +52 -0
  217. data/src/core/lib/iomgr/error_cfstream.h +31 -0
  218. data/src/core/lib/iomgr/error_internal.h +1 -1
  219. data/src/core/lib/iomgr/ev_epoll1_linux.cc +44 -28
  220. data/src/core/lib/iomgr/ev_epollex_linux.cc +173 -194
  221. data/src/core/lib/iomgr/ev_poll_posix.cc +16 -487
  222. data/src/core/lib/iomgr/ev_posix.cc +29 -19
  223. data/src/core/lib/iomgr/ev_posix.h +19 -3
  224. data/src/core/lib/iomgr/ev_windows.cc +2 -2
  225. data/src/core/lib/iomgr/exec_ctx.cc +1 -0
  226. data/src/core/lib/iomgr/exec_ctx.h +137 -8
  227. data/src/core/lib/iomgr/executor.cc +147 -95
  228. data/src/core/lib/iomgr/executor.h +55 -49
  229. data/src/core/lib/iomgr/fork_posix.cc +6 -5
  230. data/src/core/lib/{gprpp/atomic_with_std.h → iomgr/grpc_if_nametoindex.h} +8 -13
  231. data/src/core/lib/iomgr/grpc_if_nametoindex_posix.cc +42 -0
  232. data/src/core/lib/iomgr/{network_status_tracker.h → grpc_if_nametoindex_unsupported.cc} +15 -9
  233. data/src/core/lib/iomgr/internal_errqueue.cc +3 -5
  234. data/src/core/lib/iomgr/internal_errqueue.h +105 -3
  235. data/src/core/lib/iomgr/iomgr.cc +20 -13
  236. data/src/core/lib/iomgr/iomgr.h +15 -0
  237. data/src/core/lib/iomgr/iomgr_custom.cc +17 -3
  238. data/src/core/lib/iomgr/iomgr_custom.h +2 -0
  239. data/src/core/lib/iomgr/iomgr_internal.cc +10 -0
  240. data/src/core/lib/iomgr/iomgr_internal.h +12 -0
  241. data/src/core/lib/iomgr/iomgr_posix.cc +19 -2
  242. data/src/core/lib/iomgr/iomgr_posix_cfstream.cc +93 -0
  243. data/src/core/lib/iomgr/iomgr_windows.cc +18 -2
  244. data/src/core/lib/iomgr/lockfree_event.cc +4 -4
  245. data/src/core/lib/iomgr/port.h +35 -0
  246. data/src/core/lib/iomgr/resolve_address_posix.cc +4 -3
  247. data/src/core/lib/iomgr/resolve_address_windows.cc +2 -1
  248. data/src/core/lib/iomgr/resource_quota.cc +40 -37
  249. data/src/core/lib/iomgr/socket_utils_common_posix.cc +6 -2
  250. data/src/core/lib/iomgr/socket_windows.cc +19 -0
  251. data/src/core/lib/iomgr/socket_windows.h +8 -0
  252. data/src/core/lib/iomgr/tcp_client_cfstream.cc +216 -0
  253. data/src/core/lib/iomgr/tcp_client_custom.cc +2 -2
  254. data/src/core/lib/iomgr/tcp_client_posix.cc +3 -3
  255. data/src/core/lib/iomgr/tcp_client_windows.cc +7 -5
  256. data/src/core/lib/iomgr/tcp_custom.cc +10 -14
  257. data/src/core/lib/iomgr/tcp_posix.cc +256 -140
  258. data/src/core/lib/iomgr/tcp_server.cc +5 -0
  259. data/src/core/lib/iomgr/tcp_server.h +24 -0
  260. data/src/core/lib/iomgr/tcp_server_custom.cc +14 -12
  261. data/src/core/lib/iomgr/tcp_server_posix.cc +86 -12
  262. data/src/core/lib/iomgr/tcp_server_utils_posix.h +3 -0
  263. data/src/core/lib/iomgr/tcp_server_windows.cc +13 -11
  264. data/src/core/lib/iomgr/tcp_uv.cc +5 -7
  265. data/src/core/lib/iomgr/tcp_windows.cc +8 -14
  266. data/src/core/lib/iomgr/timer.h +2 -1
  267. data/src/core/lib/iomgr/timer_generic.cc +16 -16
  268. data/src/core/lib/iomgr/timer_manager.cc +20 -11
  269. data/src/core/lib/iomgr/udp_server.cc +8 -6
  270. data/src/core/lib/iomgr/wakeup_fd_posix.cc +1 -19
  271. data/src/core/lib/json/json.cc +1 -4
  272. data/src/core/lib/profiling/basic_timers.cc +10 -4
  273. data/src/core/lib/security/context/security_context.cc +6 -7
  274. data/src/core/lib/security/context/security_context.h +3 -4
  275. data/src/core/lib/security/credentials/alts/alts_credentials.cc +1 -1
  276. data/src/core/lib/security/credentials/alts/check_gcp_environment_no_op.cc +2 -2
  277. data/src/core/lib/security/credentials/composite/composite_credentials.h +4 -0
  278. data/src/core/lib/security/credentials/credentials.h +9 -1
  279. data/src/core/lib/security/credentials/google_default/google_default_credentials.cc +15 -3
  280. data/src/core/lib/security/credentials/google_default/google_default_credentials.h +2 -0
  281. data/src/core/lib/security/credentials/jwt/json_token.cc +1 -1
  282. data/src/core/lib/security/credentials/jwt/jwt_credentials.cc +2 -1
  283. data/src/core/lib/security/credentials/jwt/jwt_verifier.cc +10 -6
  284. data/src/core/lib/security/credentials/jwt/jwt_verifier.h +2 -1
  285. data/src/core/lib/security/credentials/oauth2/oauth2_credentials.cc +3 -3
  286. data/src/core/lib/security/credentials/plugin/plugin_credentials.cc +9 -8
  287. data/src/core/lib/security/credentials/ssl/ssl_credentials.cc +20 -2
  288. data/src/core/lib/security/credentials/ssl/ssl_credentials.h +2 -2
  289. data/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc +192 -0
  290. data/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h +210 -0
  291. data/src/core/lib/security/credentials/tls/spiffe_credentials.cc +129 -0
  292. data/src/core/lib/security/credentials/tls/spiffe_credentials.h +62 -0
  293. data/src/core/lib/security/security_connector/alts/alts_security_connector.cc +10 -8
  294. data/src/core/lib/security/security_connector/fake/fake_security_connector.cc +13 -12
  295. data/src/core/lib/security/security_connector/load_system_roots_linux.cc +7 -5
  296. data/src/core/lib/security/security_connector/local/local_security_connector.cc +10 -8
  297. data/src/core/lib/security/security_connector/security_connector.cc +0 -1
  298. data/src/core/lib/security/security_connector/security_connector.h +3 -3
  299. data/src/core/lib/security/security_connector/ssl/ssl_security_connector.cc +39 -38
  300. data/src/core/lib/security/security_connector/ssl_utils.cc +164 -26
  301. data/src/core/lib/security/security_connector/ssl_utils.h +70 -1
  302. data/src/core/lib/security/security_connector/tls/spiffe_security_connector.cc +426 -0
  303. data/src/core/lib/security/security_connector/tls/spiffe_security_connector.h +122 -0
  304. data/src/core/lib/security/transport/auth_filters.h +5 -2
  305. data/src/core/lib/security/transport/client_auth_filter.cc +55 -50
  306. data/src/core/lib/security/transport/secure_endpoint.cc +6 -6
  307. data/src/core/lib/security/transport/security_handshaker.cc +271 -303
  308. data/src/core/lib/security/transport/security_handshaker.h +11 -2
  309. data/src/core/lib/security/transport/server_auth_filter.cc +3 -3
  310. data/src/core/lib/slice/b64.h +2 -2
  311. data/src/core/lib/slice/percent_encoding.cc +3 -3
  312. data/src/core/lib/slice/percent_encoding.h +3 -3
  313. data/src/core/lib/slice/slice.cc +174 -122
  314. data/src/core/lib/slice/slice_buffer.cc +54 -21
  315. data/src/core/lib/slice/slice_hash_table.h +4 -4
  316. data/src/core/lib/slice/slice_intern.cc +49 -107
  317. data/src/core/lib/slice/slice_internal.h +264 -3
  318. data/src/core/lib/slice/slice_string_helpers.cc +10 -1
  319. data/src/core/lib/slice/slice_string_helpers.h +3 -1
  320. data/src/core/lib/slice/slice_utils.h +50 -0
  321. data/src/core/lib/slice/slice_weak_hash_table.h +6 -6
  322. data/src/core/lib/surface/api_trace.h +1 -1
  323. data/src/core/lib/surface/byte_buffer_reader.cc +17 -0
  324. data/src/core/lib/surface/call.cc +67 -46
  325. data/src/core/lib/surface/call.h +7 -2
  326. data/src/core/lib/surface/call_details.cc +0 -1
  327. data/src/core/lib/surface/channel.cc +89 -97
  328. data/src/core/lib/surface/channel.h +60 -6
  329. data/src/core/lib/surface/channel_init.h +5 -0
  330. data/src/core/lib/surface/completion_queue.cc +221 -216
  331. data/src/core/lib/surface/completion_queue.h +2 -1
  332. data/src/core/lib/surface/init.cc +82 -33
  333. data/src/core/lib/surface/init.h +1 -0
  334. data/src/core/lib/surface/init_secure.cc +1 -1
  335. data/src/core/lib/surface/lame_client.cc +5 -7
  336. data/src/core/lib/surface/server.cc +42 -47
  337. data/src/core/lib/surface/validate_metadata.cc +14 -8
  338. data/src/core/lib/surface/validate_metadata.h +13 -2
  339. data/src/core/lib/surface/version.cc +1 -1
  340. data/src/core/lib/transport/bdp_estimator.cc +3 -3
  341. data/src/core/lib/transport/bdp_estimator.h +2 -2
  342. data/src/core/lib/transport/connectivity_state.cc +10 -40
  343. data/src/core/lib/transport/connectivity_state.h +0 -8
  344. data/src/core/lib/transport/error_utils.cc +12 -0
  345. data/src/core/lib/transport/metadata.cc +258 -267
  346. data/src/core/lib/transport/metadata.h +227 -16
  347. data/src/core/lib/transport/metadata_batch.cc +1 -1
  348. data/src/core/lib/transport/metadata_batch.h +1 -1
  349. data/src/core/lib/transport/static_metadata.cc +477 -399
  350. data/src/core/lib/transport/static_metadata.h +273 -182
  351. data/src/core/lib/transport/status_metadata.cc +3 -3
  352. data/src/core/lib/transport/timeout_encoding.cc +1 -1
  353. data/src/core/lib/transport/timeout_encoding.h +1 -1
  354. data/src/core/lib/transport/transport.cc +39 -72
  355. data/src/core/lib/transport/transport.h +59 -24
  356. data/src/core/lib/transport/transport_impl.h +1 -1
  357. data/src/core/tsi/alts/handshaker/alts_handshaker_client.cc +3 -3
  358. data/src/core/tsi/alts/handshaker/alts_handshaker_client.h +1 -1
  359. data/src/core/tsi/alts/handshaker/alts_shared_resource.h +1 -1
  360. data/src/core/tsi/alts/handshaker/transport_security_common_api.cc +4 -3
  361. data/src/core/tsi/alts/handshaker/transport_security_common_api.h +1 -1
  362. data/src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.cc +1 -1
  363. data/src/core/tsi/fake_transport_security.cc +4 -4
  364. data/src/core/tsi/ssl/session_cache/ssl_session_cache.cc +1 -1
  365. data/src/core/tsi/ssl_transport_security.cc +12 -10
  366. data/src/core/tsi/ssl_transport_security.h +24 -4
  367. data/src/ruby/bin/math_pb.rb +18 -16
  368. data/src/ruby/ext/grpc/extconf.rb +12 -4
  369. data/src/ruby/ext/grpc/rb_call_credentials.c +8 -5
  370. data/src/ruby/ext/grpc/rb_channel.c +14 -10
  371. data/src/ruby/ext/grpc/rb_channel_credentials.c +8 -4
  372. data/src/ruby/ext/grpc/rb_compression_options.c +9 -7
  373. data/src/ruby/ext/grpc/rb_event_thread.c +2 -0
  374. data/src/ruby/ext/grpc/rb_grpc.c +23 -24
  375. data/src/ruby/ext/grpc/rb_grpc.h +4 -2
  376. data/src/ruby/ext/grpc/rb_grpc_imports.generated.c +24 -0
  377. data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +36 -0
  378. data/src/ruby/ext/grpc/rb_server.c +8 -4
  379. data/src/ruby/lib/grpc/errors.rb +22 -3
  380. data/src/ruby/lib/grpc/generic/bidi_call.rb +1 -1
  381. data/src/ruby/lib/grpc/generic/rpc_server.rb +2 -2
  382. data/src/ruby/lib/grpc/version.rb +1 -1
  383. data/src/ruby/pb/README.md +1 -1
  384. data/src/ruby/pb/grpc/health/v1/health_pb.rb +13 -10
  385. data/src/ruby/pb/grpc/health/v1/health_services_pb.rb +18 -0
  386. data/src/ruby/pb/src/proto/grpc/testing/empty_pb.rb +3 -1
  387. data/src/ruby/pb/src/proto/grpc/testing/messages_pb.rb +58 -56
  388. data/src/ruby/pb/src/proto/grpc/testing/test_pb.rb +2 -0
  389. data/src/ruby/spec/errors_spec.rb +141 -0
  390. data/third_party/cares/cares/ares.h +12 -0
  391. data/third_party/cares/cares/ares_create_query.c +5 -1
  392. data/third_party/cares/cares/ares_data.c +74 -73
  393. data/third_party/cares/cares/ares_destroy.c +6 -1
  394. data/third_party/cares/cares/ares_gethostbyaddr.c +5 -5
  395. data/third_party/cares/cares/ares_gethostbyname.c +15 -4
  396. data/third_party/cares/cares/ares_getnameinfo.c +11 -0
  397. data/third_party/cares/cares/ares_init.c +274 -173
  398. data/third_party/cares/cares/ares_library_init.c +21 -3
  399. data/third_party/cares/cares/ares_options.c +6 -2
  400. data/third_party/cares/cares/ares_parse_naptr_reply.c +7 -6
  401. data/third_party/cares/cares/ares_parse_ptr_reply.c +4 -2
  402. data/third_party/cares/cares/ares_platform.c +7 -0
  403. data/third_party/cares/cares/ares_private.h +19 -11
  404. data/third_party/cares/cares/ares_process.c +27 -2
  405. data/third_party/cares/cares/ares_rules.h +1 -1
  406. data/third_party/cares/cares/ares_search.c +7 -0
  407. data/third_party/cares/cares/ares_send.c +6 -0
  408. data/third_party/cares/cares/ares_strsplit.c +174 -0
  409. data/third_party/cares/cares/ares_strsplit.h +43 -0
  410. data/third_party/cares/cares/ares_version.h +4 -4
  411. data/third_party/cares/cares/config-win32.h +1 -1
  412. data/third_party/cares/cares/inet_ntop.c +2 -3
  413. data/third_party/cares/config_darwin/ares_config.h +3 -0
  414. data/third_party/cares/config_freebsd/ares_config.h +3 -0
  415. data/third_party/cares/config_linux/ares_config.h +3 -0
  416. data/third_party/cares/config_openbsd/ares_config.h +3 -0
  417. metadata +83 -48
  418. data/src/core/ext/filters/client_channel/request_routing.cc +0 -936
  419. data/src/core/ext/filters/client_channel/request_routing.h +0 -177
  420. data/src/core/ext/filters/client_channel/subchannel_index.cc +0 -248
  421. data/src/core/ext/filters/client_channel/subchannel_index.h +0 -76
  422. data/src/core/lib/channel/handshaker_factory.cc +0 -42
  423. data/src/core/lib/gpr/arena.cc +0 -192
  424. data/src/core/lib/gprpp/atomic_with_atm.h +0 -57
  425. data/src/core/lib/iomgr/wakeup_fd_cv.cc +0 -107
  426. data/src/core/lib/iomgr/wakeup_fd_cv.h +0 -69
  427. data/src/core/lib/transport/service_config.cc +0 -106
  428. data/src/core/lib/transport/service_config.h +0 -249
@@ -33,7 +33,8 @@
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/service_config.h"
37
+ #include "src/core/ext/filters/client_channel/subchannel_pool_interface.h"
37
38
  #include "src/core/lib/backoff/backoff.h"
38
39
  #include "src/core/lib/channel/channel_args.h"
39
40
  #include "src/core/lib/channel/connected_channel.h"
@@ -41,249 +42,312 @@
41
42
  #include "src/core/lib/gpr/alloc.h"
42
43
  #include "src/core/lib/gprpp/debug_location.h"
43
44
  #include "src/core/lib/gprpp/manual_constructor.h"
44
- #include "src/core/lib/gprpp/mutex_lock.h"
45
45
  #include "src/core/lib/gprpp/ref_counted_ptr.h"
46
+ #include "src/core/lib/gprpp/sync.h"
46
47
  #include "src/core/lib/iomgr/sockaddr_utils.h"
47
- #include "src/core/lib/iomgr/timer.h"
48
48
  #include "src/core/lib/profiling/timers.h"
49
49
  #include "src/core/lib/slice/slice_internal.h"
50
50
  #include "src/core/lib/surface/channel.h"
51
51
  #include "src/core/lib/surface/channel_init.h"
52
52
  #include "src/core/lib/transport/connectivity_state.h"
53
53
  #include "src/core/lib/transport/error_utils.h"
54
- #include "src/core/lib/transport/service_config.h"
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
+ TraceFlag grpc_trace_subchannel(false, "subchannel");
79
+ DebugOnlyTraceFlag grpc_trace_subchannel_refcount(false, "subchannel_refcount");
91
80
 
92
- } // namespace grpc_core
93
-
94
- struct grpc_subchannel {
95
- grpc_connector* connector;
81
+ //
82
+ // ConnectedSubchannel
83
+ //
96
84
 
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;
85
+ ConnectedSubchannel::ConnectedSubchannel(
86
+ grpc_channel_stack* channel_stack, const grpc_channel_args* args,
87
+ RefCountedPtr<channelz::SubchannelNode> channelz_subchannel,
88
+ intptr_t socket_uuid)
89
+ : ConnectedSubchannelInterface(&grpc_trace_subchannel_refcount),
90
+ channel_stack_(channel_stack),
91
+ args_(grpc_channel_args_copy(args)),
92
+ channelz_subchannel_(std::move(channelz_subchannel)),
93
+ socket_uuid_(socket_uuid) {}
103
94
 
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;
95
+ ConnectedSubchannel::~ConnectedSubchannel() {
96
+ grpc_channel_args_destroy(args_);
97
+ GRPC_CHANNEL_STACK_UNREF(channel_stack_, "connected_subchannel_dtor");
98
+ }
109
99
 
110
- grpc_subchannel_key* key;
100
+ void ConnectedSubchannel::NotifyOnStateChange(
101
+ grpc_pollset_set* interested_parties, grpc_connectivity_state* state,
102
+ grpc_closure* closure) {
103
+ grpc_transport_op* op = grpc_make_transport_op(nullptr);
104
+ grpc_channel_element* elem;
105
+ op->connectivity_state = state;
106
+ op->on_connectivity_state_change = closure;
107
+ op->bind_pollset_set = interested_parties;
108
+ elem = grpc_channel_stack_element(channel_stack_, 0);
109
+ elem->filter->start_transport_op(elem, op);
110
+ }
111
111
 
112
- /** set during connection */
113
- grpc_connect_out_args connecting_result;
112
+ void ConnectedSubchannel::Ping(grpc_closure* on_initiate,
113
+ grpc_closure* on_ack) {
114
+ grpc_transport_op* op = grpc_make_transport_op(nullptr);
115
+ grpc_channel_element* elem;
116
+ op->send_ping.on_initiate = on_initiate;
117
+ op->send_ping.on_ack = on_ack;
118
+ elem = grpc_channel_stack_element(channel_stack_, 0);
119
+ elem->filter->start_transport_op(elem, op);
120
+ }
114
121
 
115
- /** callback for connection finishing */
116
- grpc_closure on_connected;
122
+ RefCountedPtr<SubchannelCall> ConnectedSubchannel::CreateCall(
123
+ const CallArgs& args, grpc_error** error) {
124
+ const size_t allocation_size =
125
+ GetInitialCallSizeEstimate(args.parent_data_size);
126
+ RefCountedPtr<SubchannelCall> call(
127
+ new (args.arena->Alloc(allocation_size))
128
+ SubchannelCall(Ref(DEBUG_LOCATION, "subchannel_call"), args));
129
+ grpc_call_stack* callstk = SUBCHANNEL_CALL_TO_CALL_STACK(call.get());
130
+ const grpc_call_element_args call_args = {
131
+ callstk, /* call_stack */
132
+ nullptr, /* server_transport_data */
133
+ args.context, /* context */
134
+ args.path, /* path */
135
+ args.start_time, /* start_time */
136
+ args.deadline, /* deadline */
137
+ args.arena, /* arena */
138
+ args.call_combiner /* call_combiner */
139
+ };
140
+ *error = grpc_call_stack_init(channel_stack_, 1, SubchannelCall::Destroy,
141
+ call.get(), &call_args);
142
+ if (GPR_UNLIKELY(*error != GRPC_ERROR_NONE)) {
143
+ const char* error_string = grpc_error_string(*error);
144
+ gpr_log(GPR_ERROR, "error: %s", error_string);
145
+ return call;
146
+ }
147
+ grpc_call_stack_set_pollset_or_pollset_set(callstk, args.pollent);
148
+ if (channelz_subchannel_ != nullptr) {
149
+ channelz_subchannel_->RecordCallStarted();
150
+ }
151
+ return call;
152
+ }
117
153
 
118
- /** callback for our alarm */
119
- grpc_closure on_alarm;
154
+ size_t ConnectedSubchannel::GetInitialCallSizeEstimate(
155
+ size_t parent_data_size) const {
156
+ size_t allocation_size =
157
+ GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(SubchannelCall));
158
+ if (parent_data_size > 0) {
159
+ allocation_size +=
160
+ GPR_ROUND_UP_TO_ALIGNMENT_SIZE(channel_stack_->call_stack_size) +
161
+ parent_data_size;
162
+ } else {
163
+ allocation_size += channel_stack_->call_stack_size;
164
+ }
165
+ return allocation_size;
166
+ }
120
167
 
121
- /** pollset_set tracking who's interested in a connection
122
- being setup */
123
- grpc_pollset_set* pollset_set;
168
+ //
169
+ // SubchannelCall
170
+ //
124
171
 
125
- grpc_core::UniquePtr<char> health_check_service_name;
172
+ void SubchannelCall::StartTransportStreamOpBatch(
173
+ grpc_transport_stream_op_batch* batch) {
174
+ GPR_TIMER_SCOPE("subchannel_call_process_op", 0);
175
+ MaybeInterceptRecvTrailingMetadata(batch);
176
+ grpc_call_stack* call_stack = SUBCHANNEL_CALL_TO_CALL_STACK(this);
177
+ grpc_call_element* top_elem = grpc_call_stack_element(call_stack, 0);
178
+ GRPC_CALL_LOG_OP(GPR_INFO, top_elem, batch);
179
+ top_elem->filter->start_transport_stream_op_batch(top_elem, batch);
180
+ }
126
181
 
127
- /** mutex protecting remaining elements */
128
- gpr_mu mu;
182
+ void* SubchannelCall::GetParentData() {
183
+ grpc_channel_stack* chanstk = connected_subchannel_->channel_stack();
184
+ return (char*)this + GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(SubchannelCall)) +
185
+ GPR_ROUND_UP_TO_ALIGNMENT_SIZE(chanstk->call_stack_size);
186
+ }
129
187
 
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;
188
+ grpc_call_stack* SubchannelCall::GetCallStack() {
189
+ return SUBCHANNEL_CALL_TO_CALL_STACK(this);
190
+ }
134
191
 
135
- /** have we seen a disconnection? */
136
- bool disconnected;
137
- /** are we connecting */
138
- bool connecting;
192
+ void SubchannelCall::SetAfterCallStackDestroy(grpc_closure* closure) {
193
+ GPR_ASSERT(after_call_stack_destroy_ == nullptr);
194
+ GPR_ASSERT(closure != nullptr);
195
+ after_call_stack_destroy_ = closure;
196
+ }
139
197
 
140
- /** connectivity state tracking */
141
- grpc_connectivity_state_tracker state_tracker;
142
- grpc_connectivity_state_tracker state_and_health_tracker;
198
+ RefCountedPtr<SubchannelCall> SubchannelCall::Ref() {
199
+ IncrementRefCount();
200
+ return RefCountedPtr<SubchannelCall>(this);
201
+ }
143
202
 
144
- external_state_watcher root_external_state_watcher;
203
+ RefCountedPtr<SubchannelCall> SubchannelCall::Ref(
204
+ const grpc_core::DebugLocation& location, const char* reason) {
205
+ IncrementRefCount(location, reason);
206
+ return RefCountedPtr<SubchannelCall>(this);
207
+ }
145
208
 
146
- /** backoff state */
147
- grpc_core::ManualConstructor<grpc_core::BackOff> backoff;
148
- grpc_millis next_attempt_deadline;
149
- grpc_millis min_connect_timeout_ms;
209
+ void SubchannelCall::Unref() {
210
+ GRPC_CALL_STACK_UNREF(SUBCHANNEL_CALL_TO_CALL_STACK(this), "");
211
+ }
150
212
 
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;
213
+ void SubchannelCall::Unref(const DebugLocation& location, const char* reason) {
214
+ GRPC_CALL_STACK_UNREF(SUBCHANNEL_CALL_TO_CALL_STACK(this), reason);
215
+ }
159
216
 
160
- grpc_core::RefCountedPtr<grpc_core::channelz::SubchannelNode>
161
- channelz_subchannel;
162
- };
217
+ void SubchannelCall::Destroy(void* arg, grpc_error* error) {
218
+ GPR_TIMER_SCOPE("subchannel_call_destroy", 0);
219
+ SubchannelCall* self = static_cast<SubchannelCall*>(arg);
220
+ // Keep some members before destroying the subchannel call.
221
+ grpc_closure* after_call_stack_destroy = self->after_call_stack_destroy_;
222
+ RefCountedPtr<ConnectedSubchannel> connected_subchannel =
223
+ std::move(self->connected_subchannel_);
224
+ // Destroy the subchannel call.
225
+ self->~SubchannelCall();
226
+ // Destroy the call stack. This should be after destroying the subchannel
227
+ // call, because call->after_call_stack_destroy(), if not null, will free the
228
+ // call arena.
229
+ grpc_call_stack_destroy(SUBCHANNEL_CALL_TO_CALL_STACK(self), nullptr,
230
+ after_call_stack_destroy);
231
+ // Automatically reset connected_subchannel. This should be after destroying
232
+ // the call stack, because destroying call stack needs access to the channel
233
+ // stack.
234
+ }
163
235
 
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
- };
236
+ void SubchannelCall::MaybeInterceptRecvTrailingMetadata(
237
+ grpc_transport_stream_op_batch* batch) {
238
+ // only intercept payloads with recv trailing.
239
+ if (!batch->recv_trailing_metadata) {
240
+ return;
241
+ }
242
+ // only add interceptor is channelz is enabled.
243
+ if (connected_subchannel_->channelz_subchannel() == nullptr) {
244
+ return;
245
+ }
246
+ GRPC_CLOSURE_INIT(&recv_trailing_metadata_ready_, RecvTrailingMetadataReady,
247
+ this, grpc_schedule_on_exec_ctx);
248
+ // save some state needed for the interception callback.
249
+ GPR_ASSERT(recv_trailing_metadata_ == nullptr);
250
+ recv_trailing_metadata_ =
251
+ batch->payload->recv_trailing_metadata.recv_trailing_metadata;
252
+ original_recv_trailing_metadata_ =
253
+ batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready;
254
+ batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready =
255
+ &recv_trailing_metadata_ready_;
256
+ }
177
257
 
178
- static void maybe_start_connecting_locked(grpc_subchannel* c);
258
+ namespace {
179
259
 
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";
260
+ // Sets *status based on the rest of the parameters.
261
+ void GetCallStatus(grpc_status_code* status, grpc_millis deadline,
262
+ grpc_metadata_batch* md_batch, grpc_error* error) {
263
+ if (error != GRPC_ERROR_NONE) {
264
+ grpc_error_get_status(error, deadline, status, nullptr, nullptr, nullptr);
265
+ } else {
266
+ if (md_batch->idx.named.grpc_status != nullptr) {
267
+ *status = grpc_get_status_code_from_metadata(
268
+ md_batch->idx.named.grpc_status->md);
269
+ } else {
270
+ *status = GRPC_STATUS_UNKNOWN;
271
+ }
193
272
  }
194
- GPR_UNREACHABLE_CODE(return "UNKNOWN");
273
+ GRPC_ERROR_UNREF(error);
195
274
  }
196
275
 
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)));
276
+ } // namespace
277
+
278
+ void SubchannelCall::RecvTrailingMetadataReady(void* arg, grpc_error* error) {
279
+ SubchannelCall* call = static_cast<SubchannelCall*>(arg);
280
+ GPR_ASSERT(call->recv_trailing_metadata_ != nullptr);
281
+ grpc_status_code status = GRPC_STATUS_OK;
282
+ GetCallStatus(&status, call->deadline_, call->recv_trailing_metadata_,
283
+ GRPC_ERROR_REF(error));
284
+ channelz::SubchannelNode* channelz_subchannel =
285
+ call->connected_subchannel_->channelz_subchannel();
286
+ GPR_ASSERT(channelz_subchannel != nullptr);
287
+ if (status == GRPC_STATUS_OK) {
288
+ channelz_subchannel->RecordCallSucceeded();
289
+ } else {
290
+ channelz_subchannel->RecordCallFailed();
205
291
  }
206
- grpc_connectivity_state_set(&c->state_tracker, state, error, reason);
292
+ GRPC_CLOSURE_RUN(call->original_recv_trailing_metadata_,
293
+ GRPC_ERROR_REF(error));
207
294
  }
208
295
 
209
- namespace grpc_core {
296
+ void SubchannelCall::IncrementRefCount() {
297
+ GRPC_CALL_STACK_REF(SUBCHANNEL_CALL_TO_CALL_STACK(this), "");
298
+ }
299
+
300
+ void SubchannelCall::IncrementRefCount(const grpc_core::DebugLocation& location,
301
+ const char* reason) {
302
+ GRPC_CALL_STACK_REF(SUBCHANNEL_CALL_TO_CALL_STACK(this), reason);
303
+ }
210
304
 
211
- class ConnectedSubchannelStateWatcher
212
- : public InternallyRefCounted<ConnectedSubchannelStateWatcher> {
305
+ //
306
+ // Subchannel::ConnectedSubchannelStateWatcher
307
+ //
308
+
309
+ class Subchannel::ConnectedSubchannelStateWatcher {
213
310
  public:
214
311
  // Must be instantiated while holding c->mu.
215
- explicit ConnectedSubchannelStateWatcher(grpc_subchannel* c)
216
- : subchannel_(c) {
312
+ explicit ConnectedSubchannelStateWatcher(Subchannel* c) : subchannel_(c) {
217
313
  // Steal subchannel ref for connecting.
218
314
  GRPC_SUBCHANNEL_WEAK_REF(subchannel_, "state_watcher");
219
315
  GRPC_SUBCHANNEL_WEAK_UNREF(subchannel_, "connecting");
220
316
  // Start watching for connectivity state changes.
221
- // Callback uses initial ref to this.
222
317
  GRPC_CLOSURE_INIT(&on_connectivity_changed_, OnConnectivityChanged, this,
223
318
  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");
319
+ c->connected_subchannel_->NotifyOnStateChange(c->pollset_set_,
320
+ &pending_connectivity_state_,
321
+ &on_connectivity_changed_);
245
322
  }
246
323
 
247
324
  ~ConnectedSubchannelStateWatcher() {
248
325
  GRPC_SUBCHANNEL_WEAK_UNREF(subchannel_, "state_watcher");
249
326
  }
250
327
 
251
- void Orphan() override { health_check_client_.reset(); }
252
-
253
328
  private:
254
329
  static void OnConnectivityChanged(void* arg, grpc_error* error) {
255
330
  auto* self = static_cast<ConnectedSubchannelStateWatcher*>(arg);
256
- grpc_subchannel* c = self->subchannel_;
331
+ Subchannel* c = self->subchannel_;
257
332
  {
258
- MutexLock lock(&c->mu);
333
+ MutexLock lock(&c->mu_);
259
334
  switch (self->pending_connectivity_state_) {
260
335
  case GRPC_CHANNEL_TRANSIENT_FAILURE:
261
336
  case GRPC_CHANNEL_SHUTDOWN: {
262
- if (!c->disconnected && c->connected_subchannel != nullptr) {
263
- if (grpc_trace_stream_refcount.enabled()) {
337
+ if (!c->disconnected_ && c->connected_subchannel_ != nullptr) {
338
+ if (grpc_trace_subchannel.enabled()) {
264
339
  gpr_log(GPR_INFO,
265
340
  "Connected subchannel %p of subchannel %p has gone into "
266
341
  "%s. Attempting to reconnect.",
267
- c->connected_subchannel.get(), c,
342
+ c->connected_subchannel_.get(), c,
268
343
  grpc_connectivity_state_name(
269
344
  self->pending_connectivity_state_));
270
345
  }
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;
346
+ c->connected_subchannel_.reset();
347
+ c->SetConnectivityStateLocked(GRPC_CHANNEL_TRANSIENT_FAILURE);
348
+ c->backoff_begun_ = false;
349
+ c->backoff_.Reset();
285
350
  }
286
- self->health_check_client_.reset();
287
351
  break;
288
352
  }
289
353
  default: {
@@ -291,197 +355,239 @@ class ConnectedSubchannelStateWatcher
291
355
  // a callback for READY, because that was the state we started
292
356
  // this watch from. And a connected subchannel should never go
293
357
  // 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(
358
+ c->SetConnectivityStateLocked(self->pending_connectivity_state_);
359
+ c->connected_subchannel_->NotifyOnStateChange(
304
360
  nullptr, &self->pending_connectivity_state_,
305
361
  &self->on_connectivity_changed_);
306
- self = nullptr; // So we don't unref below.
362
+ return; // So we don't delete ourself below.
307
363
  }
308
364
  }
309
365
  }
310
- // Don't unref until we've released the lock, because this might
366
+ // Don't delete until we've released the lock, because this might
311
367
  // 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_);
368
+ Delete(self);
330
369
  }
331
370
 
332
- grpc_subchannel* subchannel_;
371
+ Subchannel* subchannel_;
333
372
  grpc_closure on_connectivity_changed_;
334
373
  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
374
  };
340
375
 
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)))
376
+ //
377
+ // Subchannel::ConnectivityStateWatcherList
378
+ //
350
379
 
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
380
+ void Subchannel::ConnectivityStateWatcherList::AddWatcherLocked(
381
+ UniquePtr<ConnectivityStateWatcher> watcher) {
382
+ watchers_.insert(MakePair(watcher.get(), std::move(watcher)));
383
+ }
363
384
 
364
- /*
365
- * connection implementation
366
- */
385
+ void Subchannel::ConnectivityStateWatcherList::RemoveWatcherLocked(
386
+ ConnectivityStateWatcher* watcher) {
387
+ watchers_.erase(watcher);
388
+ }
367
389
 
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);
390
+ void Subchannel::ConnectivityStateWatcherList::NotifyLocked(
391
+ Subchannel* subchannel, grpc_connectivity_state state) {
392
+ for (const auto& p : watchers_) {
393
+ RefCountedPtr<ConnectedSubchannel> connected_subchannel;
394
+ if (state == GRPC_CHANNEL_READY) {
395
+ connected_subchannel = subchannel->connected_subchannel_;
396
+ }
397
+ // TODO(roth): In principle, it seems wrong to send this notification
398
+ // to the watcher while holding the subchannel's mutex, since it could
399
+ // lead to a deadlock if the watcher calls back into the subchannel
400
+ // before returning back to us. In practice, this doesn't happen,
401
+ // because the LB policy code that watches subchannels always bounces
402
+ // the notification into the client_channel control-plane combiner
403
+ // before processing it. But if we ever have any other callers here,
404
+ // we will probably need to change this.
405
+ p.second->OnConnectivityStateChange(state, std::move(connected_subchannel));
406
+ }
372
407
  }
373
408
 
374
- /*
375
- * grpc_subchannel implementation
376
- */
409
+ //
410
+ // Subchannel::HealthWatcherMap::HealthWatcher
411
+ //
377
412
 
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();
413
+ // State needed for tracking the connectivity state with a particular
414
+ // health check service name.
415
+ class Subchannel::HealthWatcherMap::HealthWatcher
416
+ : public InternallyRefCounted<HealthWatcher> {
417
+ public:
418
+ HealthWatcher(Subchannel* c, UniquePtr<char> health_check_service_name,
419
+ grpc_connectivity_state subchannel_state)
420
+ : subchannel_(c),
421
+ health_check_service_name_(std::move(health_check_service_name)),
422
+ state_(subchannel_state == GRPC_CHANNEL_READY ? GRPC_CHANNEL_CONNECTING
423
+ : subchannel_state) {
424
+ GRPC_SUBCHANNEL_WEAK_REF(subchannel_, "health_watcher");
425
+ GRPC_CLOSURE_INIT(&on_health_changed_, OnHealthChanged, this,
426
+ grpc_schedule_on_exec_ctx);
427
+ // If the subchannel is already connected, start health checking.
428
+ if (subchannel_state == GRPC_CHANNEL_READY) StartHealthCheckingLocked();
386
429
  }
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
- }
398
430
 
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);
431
+ ~HealthWatcher() {
432
+ GRPC_SUBCHANNEL_WEAK_UNREF(subchannel_, "health_watcher");
408
433
  }
409
- #endif
410
- return old_val;
411
- }
412
434
 
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
- }
435
+ const char* health_check_service_name() const {
436
+ return health_check_service_name_.get();
437
+ }
421
438
 
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
- }
439
+ grpc_connectivity_state state() const { return state_; }
429
440
 
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;
441
+ void AddWatcherLocked(grpc_connectivity_state initial_state,
442
+ UniquePtr<ConnectivityStateWatcher> watcher) {
443
+ if (state_ != initial_state) {
444
+ RefCountedPtr<ConnectedSubchannel> connected_subchannel;
445
+ if (state_ == GRPC_CHANNEL_READY) {
446
+ connected_subchannel = subchannel_->connected_subchannel_;
447
+ }
448
+ watcher->OnConnectivityStateChange(state_,
449
+ std::move(connected_subchannel));
450
+ }
451
+ watcher_list_.AddWatcherLocked(std::move(watcher));
452
+ }
453
+
454
+ void RemoveWatcherLocked(ConnectivityStateWatcher* watcher) {
455
+ watcher_list_.RemoveWatcherLocked(watcher);
456
+ }
457
+
458
+ bool HasWatchers() const { return !watcher_list_.empty(); }
459
+
460
+ void NotifyLocked(grpc_connectivity_state state) {
461
+ if (state == GRPC_CHANNEL_READY) {
462
+ // If we had not already notified for CONNECTING state, do so now.
463
+ // (We may have missed this earlier, because if the transition
464
+ // from IDLE to CONNECTING to READY was too quick, the connected
465
+ // subchannel may not have sent us a notification for CONNECTING.)
466
+ if (state_ != GRPC_CHANNEL_CONNECTING) {
467
+ state_ = GRPC_CHANNEL_CONNECTING;
468
+ watcher_list_.NotifyLocked(subchannel_, state_);
439
469
  }
470
+ // If we've become connected, start health checking.
471
+ StartHealthCheckingLocked();
440
472
  } else {
441
- return nullptr;
473
+ state_ = state;
474
+ watcher_list_.NotifyLocked(subchannel_, state_);
475
+ // We're not connected, so stop health checking.
476
+ health_check_client_.reset();
477
+ }
478
+ }
479
+
480
+ void Orphan() override {
481
+ watcher_list_.Clear();
482
+ health_check_client_.reset();
483
+ Unref();
484
+ }
485
+
486
+ private:
487
+ void StartHealthCheckingLocked() {
488
+ GPR_ASSERT(health_check_client_ == nullptr);
489
+ health_check_client_ = MakeOrphanable<HealthCheckClient>(
490
+ health_check_service_name_.get(), subchannel_->connected_subchannel_,
491
+ subchannel_->pollset_set_, subchannel_->channelz_node_);
492
+ Ref().release(); // Ref for health callback tracked manually.
493
+ health_check_client_->NotifyOnHealthChange(&state_, &on_health_changed_);
494
+ }
495
+
496
+ static void OnHealthChanged(void* arg, grpc_error* error) {
497
+ auto* self = static_cast<HealthWatcher*>(arg);
498
+ Subchannel* c = self->subchannel_;
499
+ {
500
+ MutexLock lock(&c->mu_);
501
+ if (self->state_ != GRPC_CHANNEL_SHUTDOWN &&
502
+ self->health_check_client_ != nullptr) {
503
+ self->watcher_list_.NotifyLocked(c, self->state_);
504
+ // Renew watch.
505
+ self->health_check_client_->NotifyOnHealthChange(
506
+ &self->state_, &self->on_health_changed_);
507
+ return; // So we don't unref below.
508
+ }
442
509
  }
510
+ // Don't unref until we've released the lock, because this might
511
+ // cause the subchannel (which contains the lock) to be destroyed.
512
+ self->Unref();
443
513
  }
514
+
515
+ Subchannel* subchannel_;
516
+ UniquePtr<char> health_check_service_name_;
517
+ OrphanablePtr<HealthCheckClient> health_check_client_;
518
+ grpc_closure on_health_changed_;
519
+ grpc_connectivity_state state_;
520
+ ConnectivityStateWatcherList watcher_list_;
521
+ };
522
+
523
+ //
524
+ // Subchannel::HealthWatcherMap
525
+ //
526
+
527
+ void Subchannel::HealthWatcherMap::AddWatcherLocked(
528
+ Subchannel* subchannel, grpc_connectivity_state initial_state,
529
+ UniquePtr<char> health_check_service_name,
530
+ UniquePtr<ConnectivityStateWatcher> watcher) {
531
+ // If the health check service name is not already present in the map,
532
+ // add it.
533
+ auto it = map_.find(health_check_service_name.get());
534
+ HealthWatcher* health_watcher;
535
+ if (it == map_.end()) {
536
+ const char* key = health_check_service_name.get();
537
+ auto w = MakeOrphanable<HealthWatcher>(
538
+ subchannel, std::move(health_check_service_name), subchannel->state_);
539
+ health_watcher = w.get();
540
+ map_[key] = std::move(w);
541
+ } else {
542
+ health_watcher = it->second.get();
543
+ }
544
+ // Add the watcher to the entry.
545
+ health_watcher->AddWatcherLocked(initial_state, std::move(watcher));
444
546
  }
445
547
 
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);
548
+ void Subchannel::HealthWatcherMap::RemoveWatcherLocked(
549
+ const char* health_check_service_name, ConnectivityStateWatcher* watcher) {
550
+ auto it = map_.find(health_check_service_name);
551
+ GPR_ASSERT(it != map_.end());
552
+ it->second->RemoveWatcherLocked(watcher);
553
+ // If we just removed the last watcher for this service name, remove
554
+ // the map entry.
555
+ if (!it->second->HasWatchers()) map_.erase(it);
456
556
  }
457
557
 
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);
558
+ void Subchannel::HealthWatcherMap::NotifyLocked(grpc_connectivity_state state) {
559
+ for (const auto& p : map_) {
560
+ p.second->NotifyLocked(state);
466
561
  }
467
- GRPC_SUBCHANNEL_WEAK_UNREF(c, "strong-unref");
468
562
  }
469
563
 
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);
564
+ grpc_connectivity_state
565
+ Subchannel::HealthWatcherMap::CheckConnectivityStateLocked(
566
+ Subchannel* subchannel, const char* health_check_service_name) {
567
+ auto it = map_.find(health_check_service_name);
568
+ if (it == map_.end()) {
569
+ // If the health check service name is not found in the map, we're
570
+ // not currently doing a health check for that service name. If the
571
+ // subchannel's state without health checking is READY, report
572
+ // CONNECTING, since that's what we'd be in as soon as we do start a
573
+ // watch. Otherwise, report the channel's state without health checking.
574
+ return subchannel->state_ == GRPC_CHANNEL_READY ? GRPC_CHANNEL_CONNECTING
575
+ : subchannel->state_;
479
576
  }
577
+ HealthWatcher* health_watcher = it->second.get();
578
+ return health_watcher->state();
480
579
  }
481
580
 
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) {
581
+ void Subchannel::HealthWatcherMap::ShutdownLocked() { map_.clear(); }
582
+
583
+ //
584
+ // Subchannel
585
+ //
586
+
587
+ namespace {
588
+
589
+ BackOff::Options ParseArgsForBackoffValues(
590
+ const grpc_channel_args* args, grpc_millis* min_connect_timeout_ms) {
485
591
  grpc_millis initial_backoff_ms =
486
592
  GRPC_SUBCHANNEL_INITIAL_CONNECT_BACKOFF_SECONDS * 1000;
487
593
  *min_connect_timeout_ms =
@@ -518,7 +624,8 @@ static void parse_args_for_backoff_values(
518
624
  }
519
625
  }
520
626
  }
521
- backoff_options->set_initial_backoff(initial_backoff_ms)
627
+ return BackOff::Options()
628
+ .set_initial_backoff(initial_backoff_ms)
522
629
  .set_multiplier(fixed_reconnect_backoff
523
630
  ? 1.0
524
631
  : GRPC_SUBCHANNEL_RECONNECT_BACKOFF_MULTIPLIER)
@@ -527,630 +634,488 @@ static void parse_args_for_backoff_values(
527
634
  .set_max_backoff(max_backoff_ms);
528
635
  }
529
636
 
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
637
  } // 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
638
 
639
+ Subchannel::Subchannel(SubchannelKey* key, grpc_connector* connector,
640
+ const grpc_channel_args* args)
641
+ : key_(key),
642
+ connector_(connector),
643
+ backoff_(ParseArgsForBackoffValues(args, &min_connect_timeout_ms_)) {
564
644
  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();
645
+ gpr_atm_no_barrier_store(&ref_pair_, 1 << INTERNAL_REF_BITS);
646
+ grpc_connector_ref(connector_);
647
+ pollset_set_ = grpc_pollset_set_create();
580
648
  grpc_resolved_address* addr =
581
649
  static_cast<grpc_resolved_address*>(gpr_malloc(sizeof(*addr)));
582
- grpc_get_subchannel_address_arg(args->args, addr);
650
+ GetAddressFromSubchannelAddressArg(args, addr);
583
651
  grpc_resolved_address* new_address = nullptr;
584
652
  grpc_channel_args* new_args = nullptr;
585
- if (grpc_proxy_mappers_map_address(addr, args->args, &new_address,
586
- &new_args)) {
653
+ if (grpc_proxy_mappers_map_address(addr, args, &new_address, &new_args)) {
587
654
  GPR_ASSERT(new_address != nullptr);
588
655
  gpr_free(addr);
589
656
  addr = new_address;
590
657
  }
591
658
  static const char* keys_to_remove[] = {GRPC_ARG_SUBCHANNEL_ADDRESS};
592
- grpc_arg new_arg = grpc_create_subchannel_address_arg(addr);
659
+ grpc_arg new_arg = CreateSubchannelAddressArg(addr);
593
660
  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,
661
+ args_ = grpc_channel_args_copy_and_add_and_remove(
662
+ new_args != nullptr ? new_args : args, keys_to_remove,
596
663
  GPR_ARRAY_SIZE(keys_to_remove), &new_arg, 1);
597
664
  gpr_free(new_arg.value.string);
598
665
  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,
666
+ GRPC_CLOSURE_INIT(&on_connecting_finished_, OnConnectingFinished, this,
602
667
  grpc_schedule_on_exec_ctx);
603
- grpc_connectivity_state_init(&c->state_tracker, GRPC_CHANNEL_IDLE,
604
- "subchannel");
605
- grpc_connectivity_state_init(&c->state_and_health_tracker, GRPC_CHANNEL_IDLE,
606
- "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
-
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
-
627
- const grpc_arg* arg =
628
- grpc_channel_args_find(c->args, GRPC_ARG_ENABLE_CHANNELZ);
629
- bool channelz_enabled =
668
+ const grpc_arg* arg = grpc_channel_args_find(args_, GRPC_ARG_ENABLE_CHANNELZ);
669
+ const bool channelz_enabled =
630
670
  grpc_channel_arg_get_bool(arg, GRPC_ENABLE_CHANNELZ_DEFAULT);
631
671
  arg = grpc_channel_args_find(
632
- c->args, GRPC_ARG_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE);
672
+ args_, GRPC_ARG_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE);
633
673
  const grpc_integer_options options = {
634
674
  GRPC_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE_DEFAULT, 0, INT_MAX};
635
675
  size_t channel_tracer_max_memory =
636
676
  (size_t)grpc_channel_arg_get_integer(arg, options);
637
677
  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"));
678
+ channelz_node_ = MakeRefCounted<channelz::SubchannelNode>(
679
+ this, channel_tracer_max_memory);
680
+ channelz_node_->AddTraceEvent(
681
+ channelz::ChannelTrace::Severity::Info,
682
+ grpc_slice_from_static_string("subchannel created"));
644
683
  }
645
-
646
- return grpc_subchannel_index_register(key, c);
647
684
  }
648
685
 
649
- grpc_core::channelz::SubchannelNode* grpc_subchannel_get_channelz_node(
650
- grpc_subchannel* subchannel) {
651
- return subchannel->channelz_subchannel.get();
686
+ Subchannel::~Subchannel() {
687
+ if (channelz_node_ != nullptr) {
688
+ channelz_node_->AddTraceEvent(
689
+ channelz::ChannelTrace::Severity::Info,
690
+ grpc_slice_from_static_string("Subchannel destroyed"));
691
+ channelz_node_->MarkSubchannelDestroyed();
692
+ }
693
+ grpc_channel_args_destroy(args_);
694
+ grpc_connector_unref(connector_);
695
+ grpc_pollset_set_destroy(pollset_set_);
696
+ Delete(key_);
652
697
  }
653
698
 
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;
699
+ Subchannel* Subchannel::Create(grpc_connector* connector,
700
+ const grpc_channel_args* args) {
701
+ SubchannelKey* key = New<SubchannelKey>(args);
702
+ SubchannelPoolInterface* subchannel_pool =
703
+ SubchannelPoolInterface::GetSubchannelPoolFromChannelArgs(args);
704
+ GPR_ASSERT(subchannel_pool != nullptr);
705
+ Subchannel* c = subchannel_pool->FindSubchannel(key);
706
+ if (c != nullptr) {
707
+ Delete(key);
708
+ return c;
659
709
  }
710
+ c = New<Subchannel>(key, connector, args);
711
+ // Try to register the subchannel before setting the subchannel pool.
712
+ // Otherwise, in case of a registration race, unreffing c in
713
+ // RegisterSubchannel() will cause c to be tried to be unregistered, while
714
+ // its key maps to a different subchannel.
715
+ Subchannel* registered = subchannel_pool->RegisterSubchannel(key, c);
716
+ if (registered == c) c->subchannel_pool_ = subchannel_pool->Ref();
717
+ return registered;
660
718
  }
661
719
 
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);
720
+ Subchannel* Subchannel::Ref(GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
721
+ gpr_atm old_refs;
722
+ old_refs = RefMutate((1 << INTERNAL_REF_BITS),
723
+ 0 GRPC_SUBCHANNEL_REF_MUTATE_PURPOSE("STRONG_REF"));
724
+ GPR_ASSERT((old_refs & STRONG_REF_MASK) != 0);
725
+ return this;
677
726
  }
678
727
 
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;
728
+ void Subchannel::Unref(GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
729
+ gpr_atm old_refs;
730
+ // add a weak ref and subtract a strong ref (atomically)
731
+ old_refs = RefMutate(
732
+ static_cast<gpr_atm>(1) - static_cast<gpr_atm>(1 << INTERNAL_REF_BITS),
733
+ 1 GRPC_SUBCHANNEL_REF_MUTATE_PURPOSE("STRONG_UNREF"));
734
+ if ((old_refs & STRONG_REF_MASK) == (1 << INTERNAL_REF_BITS)) {
735
+ Disconnect();
736
+ }
737
+ GRPC_SUBCHANNEL_WEAK_UNREF(this, "strong-unref");
687
738
  }
688
739
 
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));
740
+ Subchannel* Subchannel::WeakRef(GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
741
+ gpr_atm old_refs;
742
+ old_refs = RefMutate(1, 0 GRPC_SUBCHANNEL_REF_MUTATE_PURPOSE("WEAK_REF"));
743
+ GPR_ASSERT(old_refs != 0);
744
+ return this;
703
745
  }
704
746
 
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);
727
- }
728
-
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);
765
- }
766
- }
747
+ namespace {
767
748
 
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);
782
- }
783
- }
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
- }
749
+ void subchannel_destroy(void* arg, grpc_error* error) {
750
+ Subchannel* self = static_cast<Subchannel*>(arg);
751
+ Delete(self);
804
752
  }
805
753
 
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));
754
+ } // namespace
831
755
 
832
- if (c->disconnected) {
833
- grpc_channel_stack_destroy(stk);
834
- gpr_free(stk);
835
- return false;
756
+ void Subchannel::WeakUnref(GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
757
+ gpr_atm old_refs;
758
+ old_refs = RefMutate(-static_cast<gpr_atm>(1),
759
+ 1 GRPC_SUBCHANNEL_REF_MUTATE_PURPOSE("WEAK_UNREF"));
760
+ if (old_refs == 1) {
761
+ GRPC_CLOSURE_SCHED(GRPC_CLOSURE_CREATE(subchannel_destroy, this,
762
+ grpc_schedule_on_exec_ctx),
763
+ GRPC_ERROR_NONE);
836
764
  }
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
765
  }
850
766
 
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");
767
+ Subchannel* Subchannel::RefFromWeakRef(GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
768
+ for (;;) {
769
+ gpr_atm old_refs = gpr_atm_acq_load(&ref_pair_);
770
+ if (old_refs >= (1 << INTERNAL_REF_BITS)) {
771
+ gpr_atm new_refs = old_refs + (1 << INTERNAL_REF_BITS);
772
+ if (gpr_atm_rel_cas(&ref_pair_, old_refs, new_refs)) {
773
+ return this;
774
+ }
775
+ } else {
776
+ return nullptr;
777
+ }
882
778
  }
883
- gpr_mu_unlock(&c->mu);
884
- GRPC_SUBCHANNEL_WEAK_UNREF(c, "connected");
885
- grpc_channel_args_destroy(delete_channel_args);
886
779
  }
887
780
 
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);
781
+ intptr_t Subchannel::GetChildSocketUuid() {
782
+ if (connected_subchannel_ != nullptr) {
783
+ return connected_subchannel_->socket_uuid();
894
784
  } else {
895
- subchannel->backoff_begun = false;
896
- maybe_start_connecting_locked(subchannel);
785
+ return 0;
897
786
  }
898
- gpr_mu_unlock(&subchannel->mu);
899
- }
900
-
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();
913
- }
914
-
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;
920
787
  }
921
788
 
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;
789
+ const char* Subchannel::GetTargetAddress() {
790
+ const grpc_arg* addr_arg =
791
+ grpc_channel_args_find(args_, GRPC_ARG_SUBCHANNEL_ADDRESS);
792
+ const char* addr_str = grpc_channel_arg_get_string(addr_arg);
793
+ GPR_ASSERT(addr_str != nullptr); // Should have been set by LB policy.
794
+ return addr_str;
926
795
  }
927
796
 
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);
797
+ channelz::SubchannelNode* Subchannel::channelz_node() {
798
+ return channelz_node_.get();
931
799
  }
932
800
 
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);
801
+ grpc_connectivity_state Subchannel::CheckConnectivityState(
802
+ const char* health_check_service_name,
803
+ RefCountedPtr<ConnectedSubchannel>* connected_subchannel) {
804
+ MutexLock lock(&mu_);
805
+ grpc_connectivity_state state;
806
+ if (health_check_service_name == nullptr) {
807
+ state = state_;
940
808
  } 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
- }
809
+ state = health_watcher_map_.CheckConnectivityStateLocked(
810
+ this, health_check_service_name);
947
811
  }
948
- GRPC_ERROR_UNREF(error);
812
+ if (connected_subchannel != nullptr && state == GRPC_CHANNEL_READY) {
813
+ *connected_subchannel = connected_subchannel_;
814
+ }
815
+ return state;
949
816
  }
950
817
 
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();
818
+ void Subchannel::WatchConnectivityState(
819
+ grpc_connectivity_state initial_state,
820
+ UniquePtr<char> health_check_service_name,
821
+ UniquePtr<ConnectivityStateWatcher> watcher) {
822
+ MutexLock lock(&mu_);
823
+ grpc_pollset_set* interested_parties = watcher->interested_parties();
824
+ if (interested_parties != nullptr) {
825
+ grpc_pollset_set_add_pollset_set(pollset_set_, interested_parties);
826
+ }
827
+ if (health_check_service_name == nullptr) {
828
+ if (state_ != initial_state) {
829
+ watcher->OnConnectivityStateChange(state_, connected_subchannel_);
830
+ }
831
+ watcher_list_.AddWatcherLocked(std::move(watcher));
962
832
  } else {
963
- channelz_subchannel->RecordCallFailed();
833
+ health_watcher_map_.AddWatcherLocked(this, initial_state,
834
+ std::move(health_check_service_name),
835
+ std::move(watcher));
964
836
  }
965
- GRPC_CLOSURE_RUN(call->original_recv_trailing_metadata,
966
- GRPC_ERROR_REF(error));
967
837
  }
968
838
 
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;
839
+ void Subchannel::CancelConnectivityStateWatch(
840
+ const char* health_check_service_name, ConnectivityStateWatcher* watcher) {
841
+ MutexLock lock(&mu_);
842
+ grpc_pollset_set* interested_parties = watcher->interested_parties();
843
+ if (interested_parties != nullptr) {
844
+ grpc_pollset_set_del_pollset_set(pollset_set_, interested_parties);
976
845
  }
977
- // only add interceptor is channelz is enabled.
978
- if (call->connection->channelz_subchannel() == nullptr) {
979
- return;
846
+ if (health_check_service_name == nullptr) {
847
+ watcher_list_.RemoveWatcherLocked(watcher);
848
+ } else {
849
+ health_watcher_map_.RemoveWatcherLocked(health_check_service_name, watcher);
980
850
  }
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
851
  }
993
852
 
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);
853
+ void Subchannel::AttemptToConnect() {
854
+ MutexLock lock(&mu_);
855
+ MaybeStartConnectingLocked();
1002
856
  }
1003
857
 
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;
858
+ void Subchannel::ResetBackoff() {
859
+ MutexLock lock(&mu_);
860
+ backoff_.Reset();
861
+ if (have_retry_alarm_) {
862
+ retry_immediately_ = true;
863
+ grpc_timer_cancel(&retry_alarm_);
864
+ } else {
865
+ backoff_begun_ = false;
866
+ MaybeStartConnectingLocked();
867
+ }
1010
868
  }
1011
869
 
1012
- const grpc_subchannel_key* grpc_subchannel_get_key(
1013
- const grpc_subchannel* subchannel) {
1014
- return subchannel->key;
870
+ grpc_arg Subchannel::CreateSubchannelAddressArg(
871
+ const grpc_resolved_address* addr) {
872
+ return grpc_channel_arg_string_create(
873
+ (char*)GRPC_ARG_SUBCHANNEL_ADDRESS,
874
+ addr->len > 0 ? grpc_sockaddr_to_uri(addr) : gpr_strdup(""));
1015
875
  }
1016
876
 
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;
877
+ const char* Subchannel::GetUriFromSubchannelAddressArg(
878
+ const grpc_channel_args* args) {
879
+ const grpc_arg* addr_arg =
880
+ grpc_channel_args_find(args, GRPC_ARG_SUBCHANNEL_ADDRESS);
881
+ const char* addr_str = grpc_channel_arg_get_string(addr_arg);
882
+ GPR_ASSERT(addr_str != nullptr); // Should have been set by LB policy.
883
+ return addr_str;
1022
884
  }
1023
885
 
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
- }
886
+ namespace {
1028
887
 
1029
- static void grpc_uri_to_sockaddr(const char* uri_str,
1030
- grpc_resolved_address* addr) {
888
+ void UriToSockaddr(const char* uri_str, grpc_resolved_address* addr) {
1031
889
  grpc_uri* uri = grpc_uri_parse(uri_str, 0 /* suppress_errors */);
1032
890
  GPR_ASSERT(uri != nullptr);
1033
891
  if (!grpc_parse_uri(uri, addr)) memset(addr, 0, sizeof(*addr));
1034
892
  grpc_uri_destroy(uri);
1035
893
  }
1036
894
 
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);
895
+ } // namespace
896
+
897
+ void Subchannel::GetAddressFromSubchannelAddressArg(
898
+ const grpc_channel_args* args, grpc_resolved_address* addr) {
899
+ const char* addr_uri_str = GetUriFromSubchannelAddressArg(args);
1040
900
  memset(addr, 0, sizeof(*addr));
1041
901
  if (*addr_uri_str != '\0') {
1042
- grpc_uri_to_sockaddr(addr_uri_str, addr);
902
+ UriToSockaddr(addr_uri_str, addr);
1043
903
  }
1044
904
  }
1045
905
 
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
- }
906
+ namespace {
1053
907
 
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;
908
+ // Returns a string indicating the subchannel's connectivity state change to
909
+ // \a state.
910
+ const char* SubchannelConnectivityStateChangeString(
911
+ grpc_connectivity_state state) {
912
+ switch (state) {
913
+ case GRPC_CHANNEL_IDLE:
914
+ return "Subchannel state change to IDLE";
915
+ case GRPC_CHANNEL_CONNECTING:
916
+ return "Subchannel state change to CONNECTING";
917
+ case GRPC_CHANNEL_READY:
918
+ return "Subchannel state change to READY";
919
+ case GRPC_CHANNEL_TRANSIENT_FAILURE:
920
+ return "Subchannel state change to TRANSIENT_FAILURE";
921
+ case GRPC_CHANNEL_SHUTDOWN:
922
+ return "Subchannel state change to SHUTDOWN";
923
+ }
924
+ GPR_UNREACHABLE_CODE(return "UNKNOWN");
1060
925
  }
1061
926
 
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(""));
927
+ } // namespace
928
+
929
+ // Note: Must be called with a state that is different from the current state.
930
+ void Subchannel::SetConnectivityStateLocked(grpc_connectivity_state state) {
931
+ state_ = state;
932
+ if (channelz_node_ != nullptr) {
933
+ channelz_node_->AddTraceEvent(
934
+ channelz::ChannelTrace::Severity::Info,
935
+ grpc_slice_from_static_string(
936
+ SubchannelConnectivityStateChangeString(state)));
937
+ }
938
+ // Notify non-health watchers.
939
+ watcher_list_.NotifyLocked(this, state);
940
+ // Notify health watchers.
941
+ health_watcher_map_.NotifyLocked(state);
1066
942
  }
1067
943
 
1068
- namespace grpc_core {
944
+ void Subchannel::MaybeStartConnectingLocked() {
945
+ if (disconnected_) {
946
+ // Don't try to connect if we're already disconnected.
947
+ return;
948
+ }
949
+ if (connecting_) {
950
+ // Already connecting: don't restart.
951
+ return;
952
+ }
953
+ if (connected_subchannel_ != nullptr) {
954
+ // Already connected: don't restart.
955
+ return;
956
+ }
957
+ connecting_ = true;
958
+ GRPC_SUBCHANNEL_WEAK_REF(this, "connecting");
959
+ if (!backoff_begun_) {
960
+ backoff_begun_ = true;
961
+ ContinueConnectingLocked();
962
+ } else {
963
+ GPR_ASSERT(!have_retry_alarm_);
964
+ have_retry_alarm_ = true;
965
+ const grpc_millis time_til_next =
966
+ next_attempt_deadline_ - ExecCtx::Get()->Now();
967
+ if (time_til_next <= 0) {
968
+ gpr_log(GPR_INFO, "Subchannel %p: Retry immediately", this);
969
+ } else {
970
+ gpr_log(GPR_INFO, "Subchannel %p: Retry in %" PRId64 " milliseconds",
971
+ this, time_til_next);
972
+ }
973
+ GRPC_CLOSURE_INIT(&on_retry_alarm_, OnRetryAlarm, this,
974
+ grpc_schedule_on_exec_ctx);
975
+ grpc_timer_init(&retry_alarm_, next_attempt_deadline_, &on_retry_alarm_);
976
+ }
977
+ }
1069
978
 
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) {}
979
+ void Subchannel::OnRetryAlarm(void* arg, grpc_error* error) {
980
+ Subchannel* c = static_cast<Subchannel*>(arg);
981
+ // TODO(soheilhy): Once subchannel refcounting is simplified, we can get use
982
+ // MutexLock instead of ReleasableMutexLock, here.
983
+ ReleasableMutexLock lock(&c->mu_);
984
+ c->have_retry_alarm_ = false;
985
+ if (c->disconnected_) {
986
+ error = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING("Disconnected",
987
+ &error, 1);
988
+ } else if (c->retry_immediately_) {
989
+ c->retry_immediately_ = false;
990
+ error = GRPC_ERROR_NONE;
991
+ } else {
992
+ GRPC_ERROR_REF(error);
993
+ }
994
+ if (error == GRPC_ERROR_NONE) {
995
+ gpr_log(GPR_INFO, "Failed to connect to channel, retrying");
996
+ c->ContinueConnectingLocked();
997
+ lock.Unlock();
998
+ } else {
999
+ lock.Unlock();
1000
+ GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting");
1001
+ }
1002
+ GRPC_ERROR_UNREF(error);
1003
+ }
1080
1004
 
1081
- ConnectedSubchannel::~ConnectedSubchannel() {
1082
- grpc_channel_args_destroy(args_);
1083
- GRPC_CHANNEL_STACK_UNREF(channel_stack_, "connected_subchannel_dtor");
1005
+ void Subchannel::ContinueConnectingLocked() {
1006
+ grpc_connect_in_args args;
1007
+ args.interested_parties = pollset_set_;
1008
+ const grpc_millis min_deadline =
1009
+ min_connect_timeout_ms_ + ExecCtx::Get()->Now();
1010
+ next_attempt_deadline_ = backoff_.NextAttemptTime();
1011
+ args.deadline = std::max(next_attempt_deadline_, min_deadline);
1012
+ args.channel_args = args_;
1013
+ SetConnectivityStateLocked(GRPC_CHANNEL_CONNECTING);
1014
+ grpc_connector_connect(connector_, &args, &connecting_result_,
1015
+ &on_connecting_finished_);
1084
1016
  }
1085
1017
 
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);
1018
+ void Subchannel::OnConnectingFinished(void* arg, grpc_error* error) {
1019
+ auto* c = static_cast<Subchannel*>(arg);
1020
+ grpc_channel_args* delete_channel_args = c->connecting_result_.channel_args;
1021
+ GRPC_SUBCHANNEL_WEAK_REF(c, "on_connecting_finished");
1022
+ {
1023
+ MutexLock lock(&c->mu_);
1024
+ c->connecting_ = false;
1025
+ if (c->connecting_result_.transport != nullptr &&
1026
+ c->PublishTransportLocked()) {
1027
+ // Do nothing, transport was published.
1028
+ } else if (c->disconnected_) {
1029
+ GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting");
1030
+ } else {
1031
+ gpr_log(GPR_INFO, "Connect failed: %s", grpc_error_string(error));
1032
+ c->SetConnectivityStateLocked(GRPC_CHANNEL_TRANSIENT_FAILURE);
1033
+ GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting");
1034
+ }
1035
+ }
1036
+ GRPC_SUBCHANNEL_WEAK_UNREF(c, "on_connecting_finished");
1037
+ grpc_channel_args_destroy(delete_channel_args);
1096
1038
  }
1097
1039
 
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);
1040
+ namespace {
1041
+
1042
+ void ConnectionDestroy(void* arg, grpc_error* error) {
1043
+ grpc_channel_stack* stk = static_cast<grpc_channel_stack*>(arg);
1044
+ grpc_channel_stack_destroy(stk);
1045
+ gpr_free(stk);
1106
1046
  }
1107
1047
 
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;
1048
+ } // namespace
1049
+
1050
+ bool Subchannel::PublishTransportLocked() {
1051
+ // Construct channel stack.
1052
+ grpc_channel_stack_builder* builder = grpc_channel_stack_builder_create();
1053
+ grpc_channel_stack_builder_set_channel_arguments(
1054
+ builder, connecting_result_.channel_args);
1055
+ grpc_channel_stack_builder_set_transport(builder,
1056
+ connecting_result_.transport);
1057
+ if (!grpc_channel_init_create_stack(builder, GRPC_CLIENT_SUBCHANNEL)) {
1058
+ grpc_channel_stack_builder_destroy(builder);
1059
+ return false;
1134
1060
  }
1135
- grpc_call_stack_set_pollset_or_pollset_set(callstk, args.pollent);
1136
- if (channelz_subchannel_ != nullptr) {
1137
- channelz_subchannel_->RecordCallStarted();
1061
+ grpc_channel_stack* stk;
1062
+ grpc_error* error = grpc_channel_stack_builder_finish(
1063
+ builder, 0, 1, ConnectionDestroy, nullptr,
1064
+ reinterpret_cast<void**>(&stk));
1065
+ if (error != GRPC_ERROR_NONE) {
1066
+ grpc_transport_destroy(connecting_result_.transport);
1067
+ gpr_log(GPR_ERROR, "error initializing subchannel stack: %s",
1068
+ grpc_error_string(error));
1069
+ GRPC_ERROR_UNREF(error);
1070
+ return false;
1071
+ }
1072
+ intptr_t socket_uuid = connecting_result_.socket_uuid;
1073
+ memset(&connecting_result_, 0, sizeof(connecting_result_));
1074
+ if (disconnected_) {
1075
+ grpc_channel_stack_destroy(stk);
1076
+ gpr_free(stk);
1077
+ return false;
1138
1078
  }
1139
- return GRPC_ERROR_NONE;
1079
+ // Publish.
1080
+ connected_subchannel_.reset(
1081
+ New<ConnectedSubchannel>(stk, args_, channelz_node_, socket_uuid));
1082
+ gpr_log(GPR_INFO, "New connected subchannel at %p for subchannel %p",
1083
+ connected_subchannel_.get(), this);
1084
+ // Instantiate state watcher. Will clean itself up.
1085
+ New<ConnectedSubchannelStateWatcher>(this);
1086
+ // Report initial state.
1087
+ SetConnectivityStateLocked(GRPC_CHANNEL_READY);
1088
+ return true;
1140
1089
  }
1141
1090
 
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;
1091
+ void Subchannel::Disconnect() {
1092
+ // The subchannel_pool is only used once here in this subchannel, so the
1093
+ // access can be outside of the lock.
1094
+ if (subchannel_pool_ != nullptr) {
1095
+ subchannel_pool_->UnregisterSubchannel(key_);
1096
+ subchannel_pool_.reset();
1152
1097
  }
1153
- return allocation_size;
1098
+ MutexLock lock(&mu_);
1099
+ GPR_ASSERT(!disconnected_);
1100
+ disconnected_ = true;
1101
+ grpc_connector_shutdown(connector_, GRPC_ERROR_CREATE_FROM_STATIC_STRING(
1102
+ "Subchannel disconnected"));
1103
+ connected_subchannel_.reset();
1104
+ health_watcher_map_.ShutdownLocked();
1105
+ }
1106
+
1107
+ gpr_atm Subchannel::RefMutate(
1108
+ gpr_atm delta, int barrier GRPC_SUBCHANNEL_REF_MUTATE_EXTRA_ARGS) {
1109
+ gpr_atm old_val = barrier ? gpr_atm_full_fetch_add(&ref_pair_, delta)
1110
+ : gpr_atm_no_barrier_fetch_add(&ref_pair_, delta);
1111
+ #ifndef NDEBUG
1112
+ if (grpc_trace_subchannel_refcount.enabled()) {
1113
+ gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
1114
+ "SUBCHANNEL: %p %12s 0x%" PRIxPTR " -> 0x%" PRIxPTR " [%s]", this,
1115
+ purpose, old_val, old_val + delta, reason);
1116
+ }
1117
+ #endif
1118
+ return old_val;
1154
1119
  }
1155
1120
 
1156
1121
  } // namespace grpc_core