grpc 1.38.0 → 1.40.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 (340) hide show
  1. checksums.yaml +4 -4
  2. data/Makefile +68 -21
  3. data/include/grpc/event_engine/endpoint_config.h +48 -0
  4. data/include/grpc/event_engine/event_engine.h +23 -29
  5. data/include/grpc/event_engine/port.h +2 -0
  6. data/include/grpc/event_engine/slice_allocator.h +21 -36
  7. data/include/grpc/grpc.h +9 -2
  8. data/include/grpc/grpc_security.h +32 -0
  9. data/include/grpc/grpc_security_constants.h +1 -0
  10. data/include/grpc/impl/codegen/grpc_types.h +33 -19
  11. data/include/grpc/impl/codegen/port_platform.h +41 -0
  12. data/src/core/ext/filters/client_channel/client_channel.cc +415 -249
  13. data/src/core/ext/filters/client_channel/client_channel.h +42 -18
  14. data/src/core/ext/filters/client_channel/config_selector.h +19 -6
  15. data/src/core/ext/filters/client_channel/health/health_check_client.cc +2 -0
  16. data/src/core/ext/filters/client_channel/health/health_check_client.h +3 -3
  17. data/src/core/ext/filters/client_channel/http_proxy.cc +16 -1
  18. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc +7 -8
  19. data/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc +12 -21
  20. data/src/core/ext/filters/client_channel/lb_policy/priority/priority.cc +3 -5
  21. data/src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.cc +734 -0
  22. data/src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.h +10 -0
  23. data/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc +8 -15
  24. data/src/core/ext/filters/client_channel/lb_policy/weighted_target/weighted_target.cc +3 -6
  25. data/src/core/ext/filters/client_channel/lb_policy/xds/cds.cc +18 -36
  26. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_impl.cc +14 -22
  27. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_manager.cc +2 -9
  28. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_resolver.cc +68 -103
  29. data/src/core/ext/filters/client_channel/lb_policy.cc +1 -15
  30. data/src/core/ext/filters/client_channel/lb_policy.h +70 -46
  31. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc +1 -3
  32. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_event_engine.cc +31 -0
  33. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_event_engine.cc +28 -0
  34. data/src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc +1 -3
  35. data/src/core/ext/filters/client_channel/resolver/google_c2p/google_c2p_resolver.cc +7 -2
  36. data/src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc +116 -76
  37. data/src/core/ext/filters/client_channel/retry_filter.cc +967 -544
  38. data/src/core/ext/filters/client_channel/retry_service_config.cc +57 -28
  39. data/src/core/ext/filters/client_channel/retry_service_config.h +9 -3
  40. data/src/core/ext/filters/client_channel/service_config_call_data.h +45 -5
  41. data/src/core/ext/filters/client_idle/client_idle_filter.cc +1 -1
  42. data/src/core/ext/filters/http/client/http_client_filter.cc +5 -2
  43. data/src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc +2 -1
  44. data/src/core/ext/transport/chttp2/server/chttp2_server.cc +5 -1
  45. data/src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.cc +3 -2
  46. data/src/core/ext/transport/chttp2/transport/bin_decoder.cc +1 -1
  47. data/src/core/{lib/event_engine/slice_allocator.cc → ext/transport/chttp2/transport/chttp2_slice_allocator.cc} +23 -16
  48. data/src/core/ext/transport/chttp2/transport/chttp2_slice_allocator.h +74 -0
  49. data/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +12 -10
  50. data/src/core/ext/transport/chttp2/transport/flow_control.h +1 -1
  51. data/src/core/ext/transport/chttp2/transport/frame_data.cc +4 -4
  52. data/src/core/ext/transport/chttp2/transport/frame_goaway.cc +8 -8
  53. data/src/core/ext/transport/chttp2/transport/frame_settings.cc +5 -5
  54. data/src/core/ext/transport/chttp2/transport/hpack_parser.cc +639 -752
  55. data/src/core/ext/transport/chttp2/transport/hpack_parser.h +190 -69
  56. data/src/core/ext/transport/chttp2/transport/internal.h +2 -1
  57. data/src/core/ext/transport/chttp2/transport/parsing.cc +72 -56
  58. data/src/core/ext/transport/chttp2/transport/varint.cc +6 -4
  59. data/src/core/ext/transport/inproc/inproc_transport.cc +42 -31
  60. data/src/core/ext/upb-generated/envoy/config/bootstrap/v3/bootstrap.upb.c +56 -35
  61. data/src/core/ext/upb-generated/envoy/config/bootstrap/v3/bootstrap.upb.h +180 -76
  62. data/src/core/ext/upb-generated/envoy/config/cluster/v3/cluster.upb.c +35 -27
  63. data/src/core/ext/upb-generated/envoy/config/cluster/v3/cluster.upb.h +97 -48
  64. data/src/core/ext/upb-generated/envoy/config/core/v3/base.upb.c +45 -9
  65. data/src/core/ext/upb-generated/envoy/config/core/v3/base.upb.h +67 -7
  66. data/src/core/ext/upb-generated/envoy/config/core/v3/protocol.upb.c +66 -9
  67. data/src/core/ext/upb-generated/envoy/config/core/v3/protocol.upb.h +227 -0
  68. data/src/core/ext/upb-generated/envoy/config/core/v3/resolver.upb.c +46 -0
  69. data/src/core/ext/upb-generated/envoy/config/core/v3/resolver.upb.h +121 -0
  70. data/src/core/ext/upb-generated/envoy/config/core/v3/substitution_format_string.upb.c +1 -0
  71. data/src/core/ext/upb-generated/envoy/config/core/v3/udp_socket_config.upb.c +35 -0
  72. data/src/core/ext/upb-generated/envoy/config/core/v3/udp_socket_config.upb.h +90 -0
  73. data/src/core/ext/upb-generated/envoy/config/listener/v3/listener.upb.c +32 -24
  74. data/src/core/ext/upb-generated/envoy/config/listener/v3/listener.upb.h +120 -73
  75. data/src/core/ext/upb-generated/envoy/config/listener/v3/listener_components.upb.c +4 -2
  76. data/src/core/ext/upb-generated/envoy/config/listener/v3/listener_components.upb.h +15 -0
  77. data/src/core/ext/upb-generated/envoy/config/listener/v3/quic_config.upb.c +48 -0
  78. data/src/core/ext/upb-generated/envoy/config/listener/v3/quic_config.upb.h +171 -0
  79. data/src/core/ext/upb-generated/envoy/config/listener/v3/udp_listener_config.upb.c +8 -6
  80. data/src/core/ext/upb-generated/envoy/config/listener/v3/udp_listener_config.upb.h +27 -19
  81. data/src/core/ext/upb-generated/envoy/config/rbac/v3/rbac.upb.c +1 -0
  82. data/src/core/ext/upb-generated/envoy/config/route/v3/route.upb.c +24 -7
  83. data/src/core/ext/upb-generated/envoy/config/route/v3/route.upb.h +57 -0
  84. data/src/core/ext/upb-generated/envoy/config/route/v3/route_components.upb.c +29 -17
  85. data/src/core/ext/upb-generated/envoy/config/route/v3/route_components.upb.h +72 -0
  86. data/src/core/ext/upb-generated/envoy/extensions/filters/http/fault/v3/fault.upb.c +3 -2
  87. data/src/core/ext/upb-generated/envoy/extensions/filters/http/fault/v3/fault.upb.h +4 -0
  88. data/src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.c +6 -5
  89. data/src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.h +15 -11
  90. data/src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.c +85 -43
  91. data/src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.h +274 -91
  92. data/src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/common.upb.c +11 -8
  93. data/src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/common.upb.h +30 -13
  94. data/src/core/ext/upb-generated/envoy/service/status/v3/csds.upb.c +33 -5
  95. data/src/core/ext/upb-generated/envoy/service/status/v3/csds.upb.h +115 -0
  96. data/src/core/ext/upb-generated/envoy/type/http/v3/path_transformation.upb.c +60 -0
  97. data/src/core/ext/upb-generated/envoy/type/http/v3/path_transformation.upb.h +181 -0
  98. data/src/core/ext/upb-generated/envoy/type/matcher/v3/regex.upb.c +1 -0
  99. data/src/core/ext/upb-generated/validate/validate.upb.c +82 -66
  100. data/src/core/ext/upb-generated/validate/validate.upb.h +220 -124
  101. data/src/core/ext/upbdefs-generated/envoy/annotations/deprecation.upbdefs.c +15 -7
  102. data/src/core/ext/upbdefs-generated/envoy/config/accesslog/v3/accesslog.upbdefs.c +53 -52
  103. data/src/core/ext/upbdefs-generated/envoy/config/bootstrap/v3/bootstrap.upbdefs.c +318 -277
  104. data/src/core/ext/upbdefs-generated/envoy/config/bootstrap/v3/bootstrap.upbdefs.h +5 -0
  105. data/src/core/ext/upbdefs-generated/envoy/config/cluster/v3/cluster.upbdefs.c +437 -410
  106. data/src/core/ext/upbdefs-generated/envoy/config/core/v3/base.upbdefs.c +198 -170
  107. data/src/core/ext/upbdefs-generated/envoy/config/core/v3/base.upbdefs.h +10 -0
  108. data/src/core/ext/upbdefs-generated/envoy/config/core/v3/config_source.upbdefs.c +9 -8
  109. data/src/core/ext/upbdefs-generated/envoy/config/core/v3/protocol.upbdefs.c +219 -163
  110. data/src/core/ext/upbdefs-generated/envoy/config/core/v3/protocol.upbdefs.h +15 -0
  111. data/src/core/ext/upbdefs-generated/envoy/config/core/v3/resolver.upbdefs.c +59 -0
  112. data/src/core/ext/upbdefs-generated/envoy/config/core/v3/resolver.upbdefs.h +40 -0
  113. data/src/core/ext/upbdefs-generated/envoy/config/core/v3/substitution_format_string.upbdefs.c +29 -25
  114. data/src/core/ext/upbdefs-generated/envoy/config/core/v3/udp_socket_config.upbdefs.c +52 -0
  115. data/src/core/ext/upbdefs-generated/envoy/config/core/v3/udp_socket_config.upbdefs.h +35 -0
  116. data/src/core/ext/upbdefs-generated/envoy/config/listener/v3/listener.upbdefs.c +135 -125
  117. data/src/core/ext/upbdefs-generated/envoy/config/listener/v3/listener.upbdefs.h +5 -0
  118. data/src/core/ext/upbdefs-generated/envoy/config/listener/v3/listener_components.upbdefs.c +131 -123
  119. data/src/core/ext/upbdefs-generated/envoy/config/listener/v3/quic_config.upbdefs.c +90 -0
  120. data/src/core/ext/upbdefs-generated/envoy/config/listener/v3/quic_config.upbdefs.h +35 -0
  121. data/src/core/ext/upbdefs-generated/envoy/config/listener/v3/udp_listener_config.upbdefs.c +32 -24
  122. data/src/core/ext/upbdefs-generated/envoy/config/route/v3/route.upbdefs.c +69 -55
  123. data/src/core/ext/upbdefs-generated/envoy/config/route/v3/route.upbdefs.h +5 -0
  124. data/src/core/ext/upbdefs-generated/envoy/config/route/v3/route_components.upbdefs.c +684 -664
  125. data/src/core/ext/upbdefs-generated/envoy/config/route/v3/route_components.upbdefs.h +5 -0
  126. data/src/core/ext/upbdefs-generated/envoy/extensions/filters/http/fault/v3/fault.upbdefs.c +13 -10
  127. data/src/core/ext/upbdefs-generated/envoy/extensions/filters/http/router/v3/router.upbdefs.c +13 -10
  128. data/src/core/ext/upbdefs-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upbdefs.c +441 -375
  129. data/src/core/ext/upbdefs-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upbdefs.h +10 -0
  130. data/src/core/ext/upbdefs-generated/envoy/extensions/transport_sockets/tls/v3/common.upbdefs.c +122 -114
  131. data/src/core/ext/upbdefs-generated/envoy/extensions/transport_sockets/tls/v3/tls.upbdefs.c +1 -1
  132. data/src/core/ext/upbdefs-generated/envoy/service/status/v3/csds.upbdefs.c +112 -79
  133. data/src/core/ext/upbdefs-generated/envoy/service/status/v3/csds.upbdefs.h +5 -0
  134. data/src/core/ext/upbdefs-generated/envoy/type/http/v3/path_transformation.upbdefs.c +64 -0
  135. data/src/core/ext/upbdefs-generated/envoy/type/http/v3/path_transformation.upbdefs.h +50 -0
  136. data/src/core/ext/upbdefs-generated/envoy/type/matcher/v3/regex.upbdefs.c +35 -32
  137. data/src/core/ext/upbdefs-generated/google/rpc/status.upbdefs.c +4 -4
  138. data/src/core/ext/upbdefs-generated/validate/validate.upbdefs.c +182 -160
  139. data/src/core/ext/xds/certificate_provider_store.h +1 -1
  140. data/src/core/ext/xds/xds_api.cc +582 -257
  141. data/src/core/ext/xds/xds_api.h +46 -8
  142. data/src/core/ext/xds/xds_bootstrap.cc +4 -1
  143. data/src/core/ext/xds/xds_client.cc +66 -43
  144. data/src/core/ext/xds/xds_client.h +0 -4
  145. data/src/core/ext/xds/xds_http_filters.cc +3 -2
  146. data/src/core/ext/xds/xds_http_filters.h +3 -0
  147. data/src/core/lib/address_utils/sockaddr_utils.cc +13 -0
  148. data/src/core/lib/address_utils/sockaddr_utils.h +10 -0
  149. data/src/core/lib/channel/call_tracer.h +85 -0
  150. data/src/core/lib/channel/channel_stack.h +1 -1
  151. data/src/core/lib/channel/channelz.h +3 -0
  152. data/src/core/lib/channel/context.h +3 -0
  153. data/src/core/lib/channel/status_util.h +4 -0
  154. data/src/core/lib/compression/stream_compression.h +1 -1
  155. data/src/core/lib/compression/stream_compression_gzip.h +1 -1
  156. data/src/core/lib/compression/stream_compression_identity.h +1 -1
  157. data/src/core/lib/debug/stats.h +1 -1
  158. data/src/core/lib/event_engine/endpoint_config.cc +46 -0
  159. data/src/core/lib/event_engine/endpoint_config_internal.h +42 -0
  160. data/src/core/lib/event_engine/event_engine.cc +50 -0
  161. data/src/core/lib/event_engine/sockaddr.cc +14 -12
  162. data/src/core/lib/event_engine/sockaddr.h +44 -0
  163. data/src/core/lib/gpr/murmur_hash.cc +4 -2
  164. data/src/core/lib/gpr/wrap_memcpy.cc +2 -1
  165. data/src/core/lib/gprpp/manual_constructor.h +1 -1
  166. data/src/core/lib/gprpp/orphanable.h +3 -3
  167. data/src/core/lib/gprpp/status_helper.h +3 -0
  168. data/src/core/lib/gprpp/sync.h +2 -30
  169. data/src/core/lib/iomgr/buffer_list.cc +1 -1
  170. data/src/core/lib/iomgr/endpoint_pair_event_engine.cc +33 -0
  171. data/src/core/lib/iomgr/error.cc +5 -4
  172. data/src/core/lib/iomgr/error.h +1 -1
  173. data/src/core/lib/iomgr/ev_apple.h +1 -1
  174. data/src/core/lib/iomgr/event_engine/closure.cc +54 -0
  175. data/src/core/lib/iomgr/event_engine/closure.h +33 -0
  176. data/src/core/lib/iomgr/event_engine/endpoint.cc +192 -0
  177. data/src/core/lib/iomgr/event_engine/endpoint.h +53 -0
  178. data/src/core/lib/iomgr/event_engine/iomgr.cc +105 -0
  179. data/src/core/lib/iomgr/event_engine/iomgr.h +24 -0
  180. data/src/core/lib/iomgr/event_engine/pollset.cc +87 -0
  181. data/{include/grpc/event_engine/channel_args.h → src/core/lib/iomgr/event_engine/pollset.h} +7 -10
  182. data/src/core/lib/iomgr/event_engine/promise.h +51 -0
  183. data/src/core/lib/iomgr/event_engine/resolved_address_internal.cc +41 -0
  184. data/src/core/lib/iomgr/event_engine/resolved_address_internal.h +35 -0
  185. data/src/core/lib/iomgr/event_engine/resolver.cc +110 -0
  186. data/src/core/lib/iomgr/event_engine/tcp.cc +263 -0
  187. data/src/core/lib/iomgr/event_engine/timer.cc +57 -0
  188. data/src/core/lib/iomgr/exec_ctx.cc +8 -0
  189. data/src/core/lib/iomgr/exec_ctx.h +3 -4
  190. data/src/core/lib/iomgr/executor/threadpool.cc +2 -3
  191. data/src/core/lib/iomgr/executor/threadpool.h +2 -2
  192. data/src/core/lib/iomgr/iomgr.cc +1 -1
  193. data/src/core/lib/iomgr/iomgr_posix.cc +2 -0
  194. data/src/core/lib/iomgr/iomgr_posix_cfstream.cc +40 -10
  195. data/src/core/lib/iomgr/pollset_custom.cc +2 -2
  196. data/src/core/lib/iomgr/pollset_custom.h +3 -1
  197. data/src/core/lib/iomgr/pollset_uv.cc +3 -1
  198. data/src/core/lib/iomgr/pollset_uv.h +5 -1
  199. data/src/core/lib/iomgr/port.h +7 -5
  200. data/src/core/lib/iomgr/python_util.h +1 -1
  201. data/src/core/lib/iomgr/resolve_address.cc +5 -1
  202. data/src/core/lib/iomgr/resolve_address.h +6 -0
  203. data/src/core/lib/iomgr/resource_quota.cc +2 -0
  204. data/src/core/lib/iomgr/sockaddr.h +1 -0
  205. data/src/core/lib/iomgr/socket_mutator.cc +15 -2
  206. data/src/core/lib/iomgr/socket_mutator.h +26 -2
  207. data/src/core/lib/iomgr/socket_utils_common_posix.cc +4 -4
  208. data/src/core/lib/iomgr/socket_utils_posix.h +2 -2
  209. data/src/core/lib/iomgr/tcp_client_posix.cc +7 -2
  210. data/src/core/lib/iomgr/tcp_client_windows.cc +2 -0
  211. data/src/core/lib/iomgr/tcp_posix.cc +42 -39
  212. data/src/core/lib/iomgr/tcp_posix.h +8 -0
  213. data/src/core/lib/iomgr/tcp_server_custom.cc +3 -4
  214. data/src/core/lib/iomgr/tcp_server_posix.cc +7 -0
  215. data/src/core/lib/iomgr/tcp_server_utils_posix_common.cc +2 -1
  216. data/src/core/lib/iomgr/timer.h +6 -1
  217. data/src/core/lib/iomgr/timer_manager.cc +1 -1
  218. data/src/core/lib/json/json_reader.cc +1 -2
  219. data/src/core/lib/matchers/matchers.cc +8 -20
  220. data/src/core/lib/matchers/matchers.h +2 -1
  221. data/src/core/lib/security/authorization/authorization_engine.h +44 -0
  222. data/src/core/lib/security/authorization/authorization_policy_provider.h +32 -0
  223. data/src/core/lib/security/authorization/authorization_policy_provider_vtable.cc +46 -0
  224. data/src/core/lib/security/authorization/evaluate_args.cc +209 -0
  225. data/src/core/lib/security/authorization/evaluate_args.h +91 -0
  226. data/src/core/lib/security/credentials/google_default/google_default_credentials.cc +3 -1
  227. data/src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.cc +49 -0
  228. data/src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.h +7 -0
  229. data/src/core/lib/security/credentials/tls/tls_utils.cc +32 -0
  230. data/src/core/lib/security/credentials/tls/tls_utils.h +13 -0
  231. data/src/core/lib/security/security_connector/local/local_security_connector.cc +9 -6
  232. data/src/core/lib/security/security_connector/ssl_utils.cc +5 -0
  233. data/src/core/lib/security/security_connector/tls/tls_security_connector.cc +6 -18
  234. data/src/core/lib/security/transport/security_handshaker.cc +12 -4
  235. data/src/core/lib/security/transport/server_auth_filter.cc +0 -7
  236. data/src/core/lib/slice/slice.cc +12 -2
  237. data/src/core/lib/slice/slice_internal.h +1 -0
  238. data/src/core/lib/surface/call.cc +26 -7
  239. data/src/core/lib/surface/call.h +11 -0
  240. data/src/core/lib/surface/completion_queue.cc +22 -22
  241. data/src/core/lib/surface/completion_queue.h +1 -1
  242. data/src/core/lib/surface/completion_queue_factory.cc +1 -2
  243. data/src/core/lib/surface/init.cc +1 -3
  244. data/src/core/lib/surface/init.h +10 -1
  245. data/src/core/lib/surface/server.cc +3 -1
  246. data/src/core/lib/surface/server.h +3 -3
  247. data/src/core/lib/surface/version.cc +2 -4
  248. data/src/core/lib/transport/error_utils.cc +2 -2
  249. data/src/core/lib/transport/metadata_batch.cc +13 -2
  250. data/src/core/lib/transport/metadata_batch.h +7 -0
  251. data/src/core/lib/transport/transport.h +2 -0
  252. data/src/core/lib/transport/transport_op_string.cc +1 -1
  253. data/src/core/plugin_registry/grpc_plugin_registry.cc +4 -0
  254. data/src/core/tsi/alts/crypt/gsec.h +2 -0
  255. data/src/ruby/ext/grpc/extconf.rb +2 -0
  256. data/src/ruby/ext/grpc/rb_grpc_imports.generated.c +6 -0
  257. data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +10 -1
  258. data/src/ruby/lib/grpc/version.rb +1 -1
  259. data/third_party/boringssl-with-bazel/err_data.c +269 -263
  260. data/third_party/boringssl-with-bazel/src/crypto/asn1/a_object.c +8 -6
  261. data/third_party/boringssl-with-bazel/src/crypto/cipher_extra/cipher_extra.c +4 -0
  262. data/third_party/boringssl-with-bazel/src/crypto/curve25519/curve25519.c +1 -1
  263. data/third_party/boringssl-with-bazel/src/crypto/curve25519/internal.h +1 -1
  264. data/third_party/boringssl-with-bazel/src/crypto/evp/evp.c +9 -0
  265. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/bn/prime.c +0 -4
  266. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/digest/digest.c +7 -0
  267. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/digest/md32_common.h +87 -121
  268. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/md4/md4.c +20 -30
  269. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/md5/md5.c +19 -30
  270. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/rand/internal.h +1 -4
  271. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/rand/rand.c +0 -13
  272. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/rsa/rsa.c +26 -24
  273. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/rsa/rsa_impl.c +10 -7
  274. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/sha/sha1.c +28 -39
  275. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/sha/sha256.c +48 -66
  276. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/sha/sha512.c +4 -5
  277. data/third_party/boringssl-with-bazel/src/crypto/hpke/hpke.c +362 -371
  278. data/third_party/boringssl-with-bazel/src/crypto/pkcs7/pkcs7_x509.c +4 -2
  279. data/third_party/boringssl-with-bazel/src/crypto/rand_extra/passive.c +2 -2
  280. data/third_party/boringssl-with-bazel/src/crypto/rsa_extra/rsa_asn1.c +1 -2
  281. data/third_party/boringssl-with-bazel/src/crypto/x509/internal.h +101 -11
  282. data/third_party/boringssl-with-bazel/src/crypto/x509/t_x509a.c +3 -0
  283. data/third_party/boringssl-with-bazel/src/crypto/x509/x509_cmp.c +2 -2
  284. data/third_party/boringssl-with-bazel/src/crypto/x509/x509_req.c +3 -0
  285. data/third_party/boringssl-with-bazel/src/crypto/x509/x509_set.c +1 -1
  286. data/third_party/boringssl-with-bazel/src/crypto/x509/x509_trs.c +2 -0
  287. data/third_party/boringssl-with-bazel/src/crypto/x509/x509_vfy.c +14 -15
  288. data/third_party/boringssl-with-bazel/src/crypto/x509/x509_vpm.c +53 -73
  289. data/third_party/boringssl-with-bazel/src/crypto/x509/x509cset.c +31 -0
  290. data/third_party/boringssl-with-bazel/src/crypto/x509/x509rset.c +3 -0
  291. data/third_party/boringssl-with-bazel/src/crypto/x509/x_all.c +3 -0
  292. data/third_party/boringssl-with-bazel/src/crypto/x509/x_req.c +5 -8
  293. data/third_party/boringssl-with-bazel/src/crypto/x509/x_sig.c +5 -0
  294. data/third_party/boringssl-with-bazel/src/crypto/x509/x_x509a.c +3 -0
  295. data/third_party/boringssl-with-bazel/src/crypto/x509v3/internal.h +7 -0
  296. data/third_party/boringssl-with-bazel/src/crypto/x509v3/v3_purp.c +1 -1
  297. data/third_party/boringssl-with-bazel/src/crypto/x509v3/v3_utl.c +5 -8
  298. data/third_party/boringssl-with-bazel/src/include/openssl/aead.h +1 -1
  299. data/third_party/boringssl-with-bazel/src/include/openssl/arm_arch.h +66 -1
  300. data/third_party/boringssl-with-bazel/src/include/openssl/base.h +40 -9
  301. data/third_party/boringssl-with-bazel/src/include/openssl/bytestring.h +1 -0
  302. data/third_party/boringssl-with-bazel/src/include/openssl/chacha.h +1 -1
  303. data/third_party/boringssl-with-bazel/src/include/openssl/digest.h +6 -2
  304. data/third_party/boringssl-with-bazel/src/include/openssl/ecdsa.h +14 -0
  305. data/third_party/boringssl-with-bazel/src/include/openssl/evp.h +19 -11
  306. data/third_party/boringssl-with-bazel/src/include/openssl/hpke.h +325 -0
  307. data/third_party/boringssl-with-bazel/src/include/openssl/pkcs7.h +23 -7
  308. data/third_party/boringssl-with-bazel/src/include/openssl/rsa.h +99 -63
  309. data/third_party/boringssl-with-bazel/src/include/openssl/ssl.h +139 -109
  310. data/third_party/boringssl-with-bazel/src/include/openssl/tls1.h +12 -19
  311. data/third_party/boringssl-with-bazel/src/include/openssl/x509.h +48 -50
  312. data/third_party/boringssl-with-bazel/src/include/openssl/x509_vfy.h +451 -435
  313. data/third_party/boringssl-with-bazel/src/include/openssl/x509v3.h +0 -1
  314. data/third_party/boringssl-with-bazel/src/ssl/d1_both.cc +2 -2
  315. data/third_party/boringssl-with-bazel/src/ssl/d1_srtp.cc +1 -1
  316. data/third_party/boringssl-with-bazel/src/ssl/encrypted_client_hello.cc +773 -84
  317. data/third_party/boringssl-with-bazel/src/ssl/handoff.cc +80 -47
  318. data/third_party/boringssl-with-bazel/src/ssl/handshake.cc +24 -19
  319. data/third_party/boringssl-with-bazel/src/ssl/handshake_client.cc +189 -86
  320. data/third_party/boringssl-with-bazel/src/ssl/handshake_server.cc +45 -56
  321. data/third_party/boringssl-with-bazel/src/ssl/internal.h +272 -167
  322. data/third_party/boringssl-with-bazel/src/ssl/s3_both.cc +2 -2
  323. data/third_party/boringssl-with-bazel/src/ssl/s3_lib.cc +2 -2
  324. data/third_party/boringssl-with-bazel/src/ssl/s3_pkt.cc +14 -19
  325. data/third_party/boringssl-with-bazel/src/ssl/ssl_lib.cc +34 -102
  326. data/third_party/boringssl-with-bazel/src/ssl/ssl_privkey.cc +2 -0
  327. data/third_party/boringssl-with-bazel/src/ssl/ssl_session.cc +8 -31
  328. data/third_party/boringssl-with-bazel/src/ssl/ssl_stat.cc +3 -0
  329. data/third_party/boringssl-with-bazel/src/ssl/ssl_transcript.cc +4 -3
  330. data/third_party/boringssl-with-bazel/src/ssl/ssl_versions.cc +7 -3
  331. data/third_party/boringssl-with-bazel/src/ssl/t1_lib.cc +576 -648
  332. data/third_party/boringssl-with-bazel/src/ssl/tls13_both.cc +31 -3
  333. data/third_party/boringssl-with-bazel/src/ssl/tls13_client.cc +98 -39
  334. data/third_party/boringssl-with-bazel/src/ssl/tls13_enc.cc +141 -94
  335. data/third_party/boringssl-with-bazel/src/ssl/tls13_server.cc +58 -68
  336. data/third_party/xxhash/xxhash.h +77 -195
  337. metadata +81 -39
  338. data/src/core/lib/gpr/arena.h +0 -47
  339. data/third_party/boringssl-with-bazel/src/crypto/hpke/internal.h +0 -267
  340. data/third_party/boringssl-with-bazel/src/crypto/x509/vpm_int.h +0 -71
@@ -39,6 +39,7 @@
39
39
  #include "src/core/ext/filters/client_channel/service_config.h"
40
40
  #include "src/core/ext/filters/client_channel/subchannel.h"
41
41
  #include "src/core/ext/filters/client_channel/subchannel_pool_interface.h"
42
+ #include "src/core/lib/channel/call_tracer.h"
42
43
  #include "src/core/lib/gprpp/sync.h"
43
44
  #include "src/core/lib/iomgr/error.h"
44
45
  #include "src/core/lib/iomgr/polling_entity.h"
@@ -132,9 +133,11 @@ class ClientChannel {
132
133
  void RemoveConnectivityWatcher(
133
134
  AsyncConnectivityStateWatcherInterface* watcher);
134
135
 
135
- RefCountedPtr<LoadBalancedCall> CreateLoadBalancedCall(
136
+ OrphanablePtr<LoadBalancedCall> CreateLoadBalancedCall(
136
137
  const grpc_call_element_args& args, grpc_polling_entity* pollent,
137
- grpc_closure* on_call_destruction_complete);
138
+ grpc_closure* on_call_destruction_complete,
139
+ ConfigSelector::CallDispatchController* call_dispatch_controller,
140
+ bool is_transparent_retry);
138
141
 
139
142
  private:
140
143
  class CallData;
@@ -273,7 +276,6 @@ class ClientChannel {
273
276
  // Fields set at construction and never modified.
274
277
  //
275
278
  const bool deadline_checking_enabled_;
276
- const bool enable_retries_;
277
279
  grpc_channel_stack* owning_stack_;
278
280
  ClientChannelFactory* client_channel_factory_;
279
281
  const grpc_channel_args* channel_args_;
@@ -369,12 +371,10 @@ class ClientChannel {
369
371
  // ClientChannel::LoadBalancedCall
370
372
  //
371
373
 
372
- // This object is ref-counted, but it cannot inherit from RefCounted<>,
373
- // because it is allocated on the arena and can't free its memory when
374
- // its refcount goes to zero. So instead, it manually implements the
375
- // same API as RefCounted<>, so that it can be used with RefCountedPtr<>.
374
+ // TODO(roth): As part of simplifying cancellation in the filter stack,
375
+ // this should no longer need to be ref-counted.
376
376
  class ClientChannel::LoadBalancedCall
377
- : public RefCounted<LoadBalancedCall, PolymorphicRefCount, kUnrefCallDtor> {
377
+ : public InternallyRefCounted<LoadBalancedCall, kUnrefCallDtor> {
378
378
  public:
379
379
  // If on_call_destruction_complete is non-null, then it will be
380
380
  // invoked once the LoadBalancedCall is completely destroyed.
@@ -382,11 +382,15 @@ class ClientChannel::LoadBalancedCall
382
382
  // the LB call has a subchannel call and ensuring that the
383
383
  // on_call_destruction_complete closure passed down from the surface
384
384
  // is not invoked until after the subchannel call stack is destroyed.
385
- LoadBalancedCall(ClientChannel* chand, const grpc_call_element_args& args,
386
- grpc_polling_entity* pollent,
387
- grpc_closure* on_call_destruction_complete);
385
+ LoadBalancedCall(
386
+ ClientChannel* chand, const grpc_call_element_args& args,
387
+ grpc_polling_entity* pollent, grpc_closure* on_call_destruction_complete,
388
+ ConfigSelector::CallDispatchController* call_dispatch_controller,
389
+ bool is_transparent_retry);
388
390
  ~LoadBalancedCall() override;
389
391
 
392
+ void Orphan() override;
393
+
390
394
  void StartTransportStreamOpBatch(grpc_transport_stream_op_batch* batch);
391
395
 
392
396
  // Invoked by channel for queued LB picks when the picker is updated.
@@ -438,10 +442,10 @@ class ClientChannel::LoadBalancedCall
438
442
  // Resumes all pending batches on subchannel_call_.
439
443
  void PendingBatchesResume();
440
444
 
441
- static void RecvTrailingMetadataReadyForLoadBalancingPolicy(
442
- void* arg, grpc_error_handle error);
443
- void InjectRecvTrailingMetadataReadyForLoadBalancingPolicy(
444
- grpc_transport_stream_op_batch* batch);
445
+ static void SendInitialMetadataOnComplete(void* arg, grpc_error_handle error);
446
+ static void RecvInitialMetadataReady(void* arg, grpc_error_handle error);
447
+ static void RecvMessageReady(void* arg, grpc_error_handle error);
448
+ static void RecvTrailingMetadataReady(void* arg, grpc_error_handle error);
445
449
 
446
450
  void CreateSubchannelCall();
447
451
  // Invoked when a pick is completed, on both success or failure.
@@ -459,7 +463,6 @@ class ClientChannel::LoadBalancedCall
459
463
  // that uses any one of them, we should store them in the call
460
464
  // context. This will save per-call memory overhead.
461
465
  grpc_slice path_; // Request path.
462
- gpr_cycle_counter call_start_time_;
463
466
  grpc_millis deadline_;
464
467
  Arena* arena_;
465
468
  grpc_call_stack* owning_call_;
@@ -467,6 +470,11 @@ class ClientChannel::LoadBalancedCall
467
470
  grpc_call_context_element* call_context_;
468
471
  grpc_polling_entity* pollent_;
469
472
  grpc_closure* on_call_destruction_complete_;
473
+ ConfigSelector::CallDispatchController* call_dispatch_controller_;
474
+
475
+ CallTracer::CallAttemptTracer* call_attempt_tracer_;
476
+
477
+ gpr_cycle_counter lb_call_start_time_ = gpr_get_cycle_counter();
470
478
 
471
479
  // Set when we get a cancel_stream op.
472
480
  grpc_error_handle cancel_error_ = GRPC_ERROR_NONE;
@@ -486,14 +494,30 @@ class ClientChannel::LoadBalancedCall
486
494
 
487
495
  RefCountedPtr<ConnectedSubchannel> connected_subchannel_;
488
496
  const LoadBalancingPolicy::BackendMetricData* backend_metric_data_ = nullptr;
489
- std::function<void(grpc_error_handle, LoadBalancingPolicy::MetadataInterface*,
497
+ std::function<void(absl::Status, LoadBalancingPolicy::MetadataInterface*,
490
498
  LoadBalancingPolicy::CallState*)>
491
499
  lb_recv_trailing_metadata_ready_;
492
500
 
493
501
  RefCountedPtr<SubchannelCall> subchannel_call_;
494
502
 
495
- // For intercepting recv_trailing_metadata_ready for the LB policy.
503
+ // For intercepting send_initial_metadata on_complete.
504
+ gpr_atm* peer_string_ = nullptr;
505
+ grpc_closure send_initial_metadata_on_complete_;
506
+ grpc_closure* original_send_initial_metadata_on_complete_ = nullptr;
507
+
508
+ // For intercepting recv_initial_metadata_ready.
509
+ grpc_metadata_batch* recv_initial_metadata_ = nullptr;
510
+ grpc_closure recv_initial_metadata_ready_;
511
+ grpc_closure* original_recv_initial_metadata_ready_ = nullptr;
512
+
513
+ // For intercepting recv_message_ready.
514
+ OrphanablePtr<ByteStream>* recv_message_ = nullptr;
515
+ grpc_closure recv_message_ready_;
516
+ grpc_closure* original_recv_message_ready_ = nullptr;
517
+
518
+ // For intercepting recv_trailing_metadata_ready.
496
519
  grpc_metadata_batch* recv_trailing_metadata_ = nullptr;
520
+ grpc_transport_stream_stats* transport_stream_stats_ = nullptr;
497
521
  grpc_closure recv_trailing_metadata_ready_;
498
522
  grpc_closure* original_recv_trailing_metadata_ready_ = nullptr;
499
523
 
@@ -44,6 +44,22 @@ namespace grpc_core {
44
44
  // MethodConfig and provide input to LB policies on a per-call basis.
45
45
  class ConfigSelector : public RefCounted<ConfigSelector> {
46
46
  public:
47
+ using CallAttributes = std::map<const char*, absl::string_view>;
48
+
49
+ // An interface to be used by the channel when dispatching calls.
50
+ class CallDispatchController {
51
+ public:
52
+ virtual ~CallDispatchController() = default;
53
+
54
+ // Called by the channel to decide if it should retry the call upon a
55
+ // failure.
56
+ virtual bool ShouldRetry() = 0;
57
+
58
+ // Called by the channel when no more LB picks will be performed for
59
+ // the call.
60
+ virtual void Commit() = 0;
61
+ };
62
+
47
63
  struct GetCallConfigArgs {
48
64
  grpc_slice* path;
49
65
  grpc_metadata_batch* initial_metadata;
@@ -60,11 +76,9 @@ class ConfigSelector : public RefCounted<ConfigSelector> {
60
76
  // the call to ensure that method_configs lives long enough.
61
77
  RefCountedPtr<ServiceConfig> service_config;
62
78
  // Call attributes that will be accessible to LB policy implementations.
63
- std::map<const char*, absl::string_view> call_attributes;
64
- // A callback that, if set, will be invoked when the call is
65
- // committed (i.e., when we know that we will never again need to
66
- // ask the picker for a subchannel for this call).
67
- std::function<void()> on_call_committed;
79
+ CallAttributes call_attributes;
80
+ // Call dispatch controller.
81
+ CallDispatchController* call_dispatch_controller = nullptr;
68
82
  };
69
83
 
70
84
  ~ConfigSelector() override = default;
@@ -85,7 +99,6 @@ class ConfigSelector : public RefCounted<ConfigSelector> {
85
99
  // The channel will call this when the resolver returns a new ConfigSelector
86
100
  // to determine what set of dynamic filters will be configured.
87
101
  virtual std::vector<const grpc_channel_filter*> GetFilters() { return {}; }
88
-
89
102
  // Modifies channel args to be passed to the dynamic filter stack.
90
103
  // Takes ownership of argument. Caller takes ownership of result.
91
104
  virtual grpc_channel_args* ModifyChannelArgs(grpc_channel_args* args) {
@@ -352,6 +352,7 @@ void HealthCheckClient::CallState::StartCall() {
352
352
  batch_.recv_initial_metadata = true;
353
353
  // Add recv_message op.
354
354
  payload_.recv_message.recv_message = &recv_message_;
355
+ payload_.recv_message.call_failed_before_recv_message = nullptr;
355
356
  // recv_message callback takes ref, handled manually.
356
357
  call_->Ref(DEBUG_LOCATION, "recv_message_ready").release();
357
358
  payload_.recv_message.recv_message_ready = GRPC_CLOSURE_INIT(
@@ -478,6 +479,7 @@ void HealthCheckClient::CallState::DoneReadingRecvMessage(
478
479
  // callbacks from the original batch have completed yet.
479
480
  recv_message_batch_.payload = &payload_;
480
481
  payload_.recv_message.recv_message = &recv_message_;
482
+ payload_.recv_message.call_failed_before_recv_message = nullptr;
481
483
  payload_.recv_message.recv_message_ready = GRPC_CLOSURE_INIT(
482
484
  &recv_message_ready_, RecvMessageReady, this, grpc_schedule_on_exec_ctx);
483
485
  recv_message_batch_.recv_message = true;
@@ -128,14 +128,14 @@ class HealthCheckClient : public InternallyRefCounted<HealthCheckClient> {
128
128
  grpc_slice_buffer recv_message_buffer_;
129
129
  Atomic<bool> seen_response_{false};
130
130
 
131
+ // True if the cancel_stream batch has been started.
132
+ Atomic<bool> cancelled_{false};
133
+
131
134
  // recv_trailing_metadata
132
135
  grpc_metadata_batch recv_trailing_metadata_;
133
136
  grpc_transport_stream_stats collect_stats_;
134
137
  grpc_closure recv_trailing_metadata_ready_;
135
138
 
136
- // True if the cancel_stream batch has been started.
137
- Atomic<bool> cancelled_{false};
138
-
139
139
  // Closure for call stack destruction.
140
140
  grpc_closure after_call_stack_destruction_;
141
141
  };
@@ -36,6 +36,7 @@
36
36
  #include "src/core/lib/gpr/env.h"
37
37
  #include "src/core/lib/gpr/string.h"
38
38
  #include "src/core/lib/gprpp/host_port.h"
39
+ #include "src/core/lib/iomgr/resolve_address.h"
39
40
  #include "src/core/lib/slice/b64.h"
40
41
  #include "src/core/lib/uri/uri_parser.h"
41
42
 
@@ -107,6 +108,17 @@ done:
107
108
  return proxy_name;
108
109
  }
109
110
 
111
+ // Adds the default port if target does not contain a port.
112
+ std::string MaybeAddDefaultPort(absl::string_view target) {
113
+ absl::string_view host;
114
+ absl::string_view port;
115
+ SplitHostPort(target, &host, &port);
116
+ if (port.empty()) {
117
+ return JoinHostPort(host, kDefaultSecurePortInt);
118
+ }
119
+ return std::string(target);
120
+ }
121
+
110
122
  class HttpProxyMapper : public ProxyMapperInterface {
111
123
  public:
112
124
  bool MapName(const char* server_uri, const grpc_channel_args* args,
@@ -118,6 +130,7 @@ class HttpProxyMapper : public ProxyMapperInterface {
118
130
  *name_to_resolve = GetHttpProxyServer(args, &user_cred);
119
131
  if (*name_to_resolve == nullptr) return false;
120
132
  char* no_proxy_str = nullptr;
133
+ std::string server_target;
121
134
  absl::StatusOr<URI> uri = URI::Parse(server_uri);
122
135
  if (!uri.ok() || uri->path().empty()) {
123
136
  gpr_log(GPR_ERROR,
@@ -173,10 +186,12 @@ class HttpProxyMapper : public ProxyMapperInterface {
173
186
  if (!use_proxy) goto no_use_proxy;
174
187
  }
175
188
  }
189
+ server_target =
190
+ MaybeAddDefaultPort(absl::StripPrefix(uri->path(), "/")).c_str();
176
191
  grpc_arg args_to_add[2];
177
192
  args_to_add[0] = grpc_channel_arg_string_create(
178
193
  const_cast<char*>(GRPC_ARG_HTTP_CONNECT_SERVER),
179
- const_cast<char*>(absl::StripPrefix(uri->path(), "/").data()));
194
+ const_cast<char*>(server_target.c_str()));
180
195
  if (user_cred != nullptr) {
181
196
  /* Use base64 encoding for user credentials as stated in RFC 7617 */
182
197
  char* encoded_user_cred =
@@ -606,7 +606,6 @@ const char* GrpcLb::Serverlist::ShouldDrop() {
606
606
  //
607
607
 
608
608
  GrpcLb::PickResult GrpcLb::Picker::Pick(PickArgs args) {
609
- PickResult result;
610
609
  // Check if we should drop the call.
611
610
  const char* drop_token =
612
611
  serverlist_ == nullptr ? nullptr : serverlist_->ShouldDrop();
@@ -619,16 +618,16 @@ GrpcLb::PickResult GrpcLb::Picker::Pick(PickArgs args) {
619
618
  if (client_stats_ != nullptr) {
620
619
  client_stats_->AddCallDropped(drop_token);
621
620
  }
622
- result.type = PickResult::PICK_COMPLETE;
623
- return result;
621
+ return PickResult::Drop(
622
+ absl::UnavailableError("drop directed by grpclb balancer"));
624
623
  }
625
624
  // Forward pick to child policy.
626
- result = child_picker_->Pick(args);
625
+ PickResult result = child_picker_->Pick(args);
627
626
  // If pick succeeded, add LB token to initial metadata.
628
- if (result.type == PickResult::PICK_COMPLETE &&
629
- result.subchannel != nullptr) {
627
+ auto* complete_pick = absl::get_if<PickResult::Complete>(&result.result);
628
+ if (complete_pick != nullptr) {
630
629
  const SubchannelWrapper* subchannel_wrapper =
631
- static_cast<SubchannelWrapper*>(result.subchannel.get());
630
+ static_cast<SubchannelWrapper*>(complete_pick->subchannel.get());
632
631
  // Encode client stats object into metadata for use by
633
632
  // client_load_reporting filter.
634
633
  GrpcLbClientStats* client_stats = subchannel_wrapper->client_stats();
@@ -654,7 +653,7 @@ GrpcLb::PickResult GrpcLb::Picker::Pick(PickArgs args) {
654
653
  args.initial_metadata->Add(kGrpcLbLbTokenMetadataKey, lb_token);
655
654
  }
656
655
  // Unwrap subchannel to pass up to the channel.
657
- result.subchannel = subchannel_wrapper->wrapped_subchannel();
656
+ complete_pick->subchannel = subchannel_wrapper->wrapped_subchannel();
658
657
  }
659
658
  return result;
660
659
  }
@@ -114,10 +114,7 @@ class PickFirst : public LoadBalancingPolicy {
114
114
  : subchannel_(std::move(subchannel)) {}
115
115
 
116
116
  PickResult Pick(PickArgs /*args*/) override {
117
- PickResult result;
118
- result.type = PickResult::PICK_COMPLETE;
119
- result.subchannel = subchannel_;
120
- return result;
117
+ return PickResult::Complete(subchannel_);
121
118
  }
122
119
 
123
120
  private:
@@ -197,12 +194,10 @@ void PickFirst::AttemptToConnectUsingLatestUpdateArgsLocked() {
197
194
  // (If we are idle, then this will happen in ExitIdleLocked() if we
198
195
  // haven't gotten a non-empty update by the time the application tries
199
196
  // to start a new call.)
200
- grpc_error_handle error =
201
- grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING("Empty update"),
202
- GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE);
197
+ absl::Status status = absl::UnavailableError("Empty update");
203
198
  channel_control_helper()->UpdateState(
204
- GRPC_CHANNEL_TRANSIENT_FAILURE, grpc_error_to_absl_status(error),
205
- absl::make_unique<TransientFailurePicker>(error));
199
+ GRPC_CHANNEL_TRANSIENT_FAILURE, status,
200
+ absl::make_unique<TransientFailurePicker>(status));
206
201
  return;
207
202
  }
208
203
  // If one of the subchannels in the new list is already in state
@@ -314,13 +309,11 @@ void PickFirst::PickFirstSubchannelData::ProcessConnectivityChangeLocked(
314
309
  p->subchannel_list_ = std::move(p->latest_pending_subchannel_list_);
315
310
  // Set our state to that of the pending subchannel list.
316
311
  if (p->subchannel_list_->in_transient_failure()) {
317
- grpc_error_handle error = grpc_error_set_int(
318
- GRPC_ERROR_CREATE_FROM_STATIC_STRING(
319
- "selected subchannel failed; switching to pending update"),
320
- GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE);
312
+ absl::Status status = absl::UnavailableError(
313
+ "selected subchannel failed; switching to pending update");
321
314
  p->channel_control_helper()->UpdateState(
322
- GRPC_CHANNEL_TRANSIENT_FAILURE, grpc_error_to_absl_status(error),
323
- absl::make_unique<TransientFailurePicker>(error));
315
+ GRPC_CHANNEL_TRANSIENT_FAILURE, status,
316
+ absl::make_unique<TransientFailurePicker>(status));
324
317
  } else {
325
318
  p->channel_control_helper()->UpdateState(
326
319
  GRPC_CHANNEL_CONNECTING, absl::Status(),
@@ -393,13 +386,11 @@ void PickFirst::PickFirstSubchannelData::ProcessConnectivityChangeLocked(
393
386
  subchannel_list()->set_in_transient_failure(true);
394
387
  // Only report new state in case 1.
395
388
  if (subchannel_list() == p->subchannel_list_.get()) {
396
- grpc_error_handle error = grpc_error_set_int(
397
- GRPC_ERROR_CREATE_FROM_STATIC_STRING(
398
- "failed to connect to all addresses"),
399
- GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE);
389
+ absl::Status status =
390
+ absl::UnavailableError("failed to connect to all addresses");
400
391
  p->channel_control_helper()->UpdateState(
401
- GRPC_CHANNEL_TRANSIENT_FAILURE, grpc_error_to_absl_status(error),
402
- absl::make_unique<TransientFailurePicker>(error));
392
+ GRPC_CHANNEL_TRANSIENT_FAILURE, status,
393
+ absl::make_unique<TransientFailurePicker>(status));
403
394
  }
404
395
  }
405
396
  sd->CheckConnectivityStateAndStartWatchingLocked();
@@ -472,12 +472,10 @@ void PriorityLb::TryNextPriorityLocked(bool report_connecting) {
472
472
  this);
473
473
  }
474
474
  current_child_from_before_update_ = nullptr;
475
- grpc_error_handle error = grpc_error_set_int(
476
- GRPC_ERROR_CREATE_FROM_STATIC_STRING("no ready priority"),
477
- GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE);
475
+ absl::Status status = absl::UnavailableError("no ready priority");
478
476
  channel_control_helper()->UpdateState(
479
- GRPC_CHANNEL_TRANSIENT_FAILURE, grpc_error_to_absl_status(error),
480
- absl::make_unique<TransientFailurePicker>(error));
477
+ GRPC_CHANNEL_TRANSIENT_FAILURE, status,
478
+ absl::make_unique<TransientFailurePicker>(status));
481
479
  }
482
480
 
483
481
  void PriorityLb::SelectPriorityLocked(uint32_t priority) {
@@ -16,8 +16,742 @@
16
16
 
17
17
  #include <grpc/support/port_platform.h>
18
18
 
19
+ #include <stdlib.h>
20
+ #include <string.h>
21
+
22
+ #include "absl/strings/numbers.h"
23
+ #include "absl/strings/str_cat.h"
24
+ #define XXH_INLINE_ALL
25
+ #include "xxhash.h"
26
+
27
+ #include <grpc/support/alloc.h>
28
+ #include "src/core/ext/filters/client_channel/lb_policy/subchannel_list.h"
29
+ #include "src/core/ext/filters/client_channel/lb_policy_registry.h"
30
+ #include "src/core/ext/filters/client_channel/subchannel.h"
31
+ #include "src/core/lib/address_utils/sockaddr_utils.h"
32
+ #include "src/core/lib/channel/channel_args.h"
33
+ #include "src/core/lib/debug/trace.h"
34
+ #include "src/core/lib/gpr/string.h"
35
+ #include "src/core/lib/gpr/useful.h"
36
+ #include "src/core/lib/gprpp/ref_counted_ptr.h"
37
+ #include "src/core/lib/gprpp/sync.h"
38
+ #include "src/core/lib/transport/connectivity_state.h"
39
+ #include "src/core/lib/transport/error_utils.h"
40
+ #include "src/core/lib/transport/static_metadata.h"
41
+
19
42
  namespace grpc_core {
20
43
 
21
44
  const char* kRequestRingHashAttribute = "request_ring_hash";
45
+ TraceFlag grpc_lb_ring_hash_trace(false, "ring_hash_lb");
46
+
47
+ // Helper Parser method
48
+ void ParseRingHashLbConfig(const Json& json, size_t* min_ring_size,
49
+ size_t* max_ring_size,
50
+ std::vector<grpc_error_handle>* error_list) {
51
+ *min_ring_size = 1024;
52
+ *max_ring_size = 8388608;
53
+ if (json.type() != Json::Type::OBJECT) {
54
+ error_list->push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
55
+ "ring_hash_experimental should be of type object"));
56
+ return;
57
+ }
58
+ const Json::Object& ring_hash = json.object_value();
59
+ auto ring_hash_it = ring_hash.find("min_ring_size");
60
+ if (ring_hash_it != ring_hash.end()) {
61
+ if (ring_hash_it->second.type() != Json::Type::NUMBER) {
62
+ error_list->push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
63
+ "field:min_ring_size error: should be of type number"));
64
+ } else {
65
+ *min_ring_size = gpr_parse_nonnegative_int(
66
+ ring_hash_it->second.string_value().c_str());
67
+ }
68
+ }
69
+ ring_hash_it = ring_hash.find("max_ring_size");
70
+ if (ring_hash_it != ring_hash.end()) {
71
+ if (ring_hash_it->second.type() != Json::Type::NUMBER) {
72
+ error_list->push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
73
+ "field:max_ring_size error: should be of type number"));
74
+ } else {
75
+ *max_ring_size = gpr_parse_nonnegative_int(
76
+ ring_hash_it->second.string_value().c_str());
77
+ }
78
+ }
79
+ if (*min_ring_size == 0 || *min_ring_size > 8388608 || *max_ring_size == 0 ||
80
+ *max_ring_size > 8388608 || *min_ring_size > *max_ring_size) {
81
+ error_list->push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
82
+ "field:max_ring_size and or min_ring_size error: "
83
+ "values need to be in the range of 1 to 8388608 "
84
+ "and max_ring_size cannot be smaller than "
85
+ "min_ring_size"));
86
+ }
87
+ }
88
+
89
+ namespace {
90
+
91
+ constexpr char kRingHash[] = "ring_hash_experimental";
92
+
93
+ class RingHashLbConfig : public LoadBalancingPolicy::Config {
94
+ public:
95
+ RingHashLbConfig(size_t min_ring_size, size_t max_ring_size)
96
+ : min_ring_size_(min_ring_size), max_ring_size_(max_ring_size) {}
97
+ const char* name() const override { return kRingHash; }
98
+ size_t min_ring_size() const { return min_ring_size_; }
99
+ size_t max_ring_size() const { return max_ring_size_; }
100
+
101
+ private:
102
+ size_t min_ring_size_;
103
+ size_t max_ring_size_;
104
+ };
105
+
106
+ //
107
+ // ring_hash LB policy
108
+ //
109
+ class RingHash : public LoadBalancingPolicy {
110
+ public:
111
+ explicit RingHash(Args args);
112
+
113
+ const char* name() const override { return kRingHash; }
114
+
115
+ void UpdateLocked(UpdateArgs args) override;
116
+ void ResetBackoffLocked() override;
117
+
118
+ private:
119
+ ~RingHash() override;
120
+
121
+ // Forward declaration.
122
+ class RingHashSubchannelList;
123
+
124
+ // Data for a particular subchannel in a subchannel list.
125
+ // This subclass adds the following functionality:
126
+ // - Tracks the previous connectivity state of the subchannel, so that
127
+ // we know how many subchannels are in each state.
128
+ class RingHashSubchannelData
129
+ : public SubchannelData<RingHashSubchannelList, RingHashSubchannelData> {
130
+ public:
131
+ RingHashSubchannelData(
132
+ SubchannelList<RingHashSubchannelList, RingHashSubchannelData>*
133
+ subchannel_list,
134
+ const ServerAddress& address,
135
+ RefCountedPtr<SubchannelInterface> subchannel)
136
+ : SubchannelData(subchannel_list, address, std::move(subchannel)),
137
+ address_(address) {}
138
+
139
+ grpc_connectivity_state connectivity_state() const {
140
+ return last_connectivity_state_;
141
+ }
142
+ const ServerAddress& address() const { return address_; }
143
+
144
+ bool seen_failure_since_ready() const { return seen_failure_since_ready_; }
145
+
146
+ // Performs connectivity state updates that need to be done both when we
147
+ // first start watching and when a watcher notification is received.
148
+ void UpdateConnectivityStateLocked(
149
+ grpc_connectivity_state connectivity_state);
150
+
151
+ private:
152
+ // Performs connectivity state updates that need to be done only
153
+ // after we have started watching.
154
+ void ProcessConnectivityChangeLocked(
155
+ grpc_connectivity_state connectivity_state) override;
156
+
157
+ ServerAddress address_;
158
+ grpc_connectivity_state last_connectivity_state_ = GRPC_CHANNEL_SHUTDOWN;
159
+ bool seen_failure_since_ready_ = false;
160
+ };
161
+
162
+ // A list of subchannels.
163
+ class RingHashSubchannelList
164
+ : public SubchannelList<RingHashSubchannelList, RingHashSubchannelData> {
165
+ public:
166
+ RingHashSubchannelList(RingHash* policy, TraceFlag* tracer,
167
+ ServerAddressList addresses,
168
+ const grpc_channel_args& args)
169
+ : SubchannelList(policy, tracer, std::move(addresses),
170
+ policy->channel_control_helper(), args) {
171
+ // Need to maintain a ref to the LB policy as long as we maintain
172
+ // any references to subchannels, since the subchannels'
173
+ // pollset_sets will include the LB policy's pollset_set.
174
+ policy->Ref(DEBUG_LOCATION, "subchannel_list").release();
175
+ }
176
+
177
+ ~RingHashSubchannelList() override {
178
+ RingHash* p = static_cast<RingHash*>(policy());
179
+ p->Unref(DEBUG_LOCATION, "subchannel_list");
180
+ }
181
+
182
+ // Starts watching the subchannels in this list.
183
+ void StartWatchingLocked();
184
+
185
+ // Updates the counters of subchannels in each state when a
186
+ // subchannel transitions from old_state to new_state.
187
+ void UpdateStateCountersLocked(grpc_connectivity_state old_state,
188
+ grpc_connectivity_state new_state);
189
+
190
+ // Updates the RH policy's connectivity state based on the
191
+ // subchannel list's state counters, creating new picker and new ring.
192
+ // Furthermore, return a bool indicating whether the aggregated state is
193
+ // Transient Failure.
194
+ bool UpdateRingHashConnectivityStateLocked();
195
+
196
+ private:
197
+ size_t num_idle_ = 0;
198
+ size_t num_ready_ = 0;
199
+ size_t num_connecting_ = 0;
200
+ size_t num_transient_failure_ = 0;
201
+ };
202
+
203
+ class Picker : public SubchannelPicker {
204
+ public:
205
+ Picker(RefCountedPtr<RingHash> parent,
206
+ RingHashSubchannelList* subchannel_list);
207
+
208
+ PickResult Pick(PickArgs args) override;
209
+
210
+ private:
211
+ struct RingEntry {
212
+ uint64_t hash;
213
+ RefCountedPtr<SubchannelInterface> subchannel;
214
+ grpc_connectivity_state connectivity_state;
215
+ };
216
+
217
+ // A fire-and-forget class that schedules subchannel connection attempts
218
+ // on the control plane WorkSerializer.
219
+ class SubchannelConnectionAttempter : public Orphanable {
220
+ public:
221
+ explicit SubchannelConnectionAttempter(
222
+ RefCountedPtr<RingHash> ring_hash_lb)
223
+ : ring_hash_lb_(std::move(ring_hash_lb)) {
224
+ GRPC_CLOSURE_INIT(&closure_, RunInExecCtx, this, nullptr);
225
+ }
226
+
227
+ void AddSubchannel(RefCountedPtr<SubchannelInterface> subchannel) {
228
+ subchannels_.push_back(std::move(subchannel));
229
+ }
230
+
231
+ void Orphan() override {
232
+ // Hop into ExecCtx, so that we're not holding the data plane mutex
233
+ // while we run control-plane code.
234
+ ExecCtx::Run(DEBUG_LOCATION, &closure_, GRPC_ERROR_NONE);
235
+ }
236
+
237
+ private:
238
+ static void RunInExecCtx(void* arg, grpc_error* /*error*/) {
239
+ auto* self = static_cast<SubchannelConnectionAttempter*>(arg);
240
+ self->ring_hash_lb_->work_serializer()->Run(
241
+ [self]() {
242
+ if (!self->ring_hash_lb_->shutdown_) {
243
+ for (auto& subchannel : self->subchannels_) {
244
+ subchannel->AttemptToConnect();
245
+ }
246
+ }
247
+ delete self;
248
+ },
249
+ DEBUG_LOCATION);
250
+ }
251
+
252
+ RefCountedPtr<RingHash> ring_hash_lb_;
253
+ grpc_closure closure_;
254
+ absl::InlinedVector<RefCountedPtr<SubchannelInterface>, 10> subchannels_;
255
+ };
256
+
257
+ RefCountedPtr<RingHash> parent_;
258
+
259
+ // A ring of subchannels.
260
+ std::vector<RingEntry> ring_;
261
+ };
262
+
263
+ void ShutdownLocked() override;
264
+
265
+ // Current config from resolver.
266
+ RefCountedPtr<RingHashLbConfig> config_;
267
+
268
+ // list of subchannels.
269
+ OrphanablePtr<RingHashSubchannelList> subchannel_list_;
270
+ // indicating if we are shutting down.
271
+ bool shutdown_ = false;
272
+ };
273
+
274
+ //
275
+ // RingHash::Picker
276
+ //
277
+
278
+ RingHash::Picker::Picker(RefCountedPtr<RingHash> parent,
279
+ RingHashSubchannelList* subchannel_list)
280
+ : parent_(std::move(parent)) {
281
+ size_t num_subchannels = subchannel_list->num_subchannels();
282
+ // Store the weights while finding the sum.
283
+ struct AddressWeight {
284
+ std::string address;
285
+ // Default weight is 1 for the cases where a weight is not provided,
286
+ // each occurrence of the address will be counted a weight value of 1.
287
+ uint32_t weight = 1;
288
+ double normalized_weight;
289
+ };
290
+ std::vector<AddressWeight> address_weights;
291
+ size_t sum = 0;
292
+ address_weights.reserve(num_subchannels);
293
+ for (size_t i = 0; i < num_subchannels; ++i) {
294
+ RingHashSubchannelData* sd = subchannel_list->subchannel(i);
295
+ const ServerAddressWeightAttribute* weight_attribute = static_cast<
296
+ const ServerAddressWeightAttribute*>(sd->address().GetAttribute(
297
+ ServerAddressWeightAttribute::kServerAddressWeightAttributeKey));
298
+ AddressWeight address_weight;
299
+ address_weight.address =
300
+ grpc_sockaddr_to_string(&sd->address().address(), false);
301
+ if (weight_attribute != nullptr) {
302
+ GPR_ASSERT(weight_attribute->weight() != 0);
303
+ address_weight.weight = weight_attribute->weight();
304
+ }
305
+ sum += address_weight.weight;
306
+ address_weights.push_back(std::move(address_weight));
307
+ }
308
+ // Calculating normalized weights and find min and max.
309
+ double min_normalized_weight = 1.0;
310
+ double max_normalized_weight = 0.0;
311
+ for (auto& address : address_weights) {
312
+ address.normalized_weight = static_cast<double>(address.weight) / sum;
313
+ min_normalized_weight =
314
+ std::min(address.normalized_weight, min_normalized_weight);
315
+ max_normalized_weight =
316
+ std::max(address.normalized_weight, max_normalized_weight);
317
+ }
318
+ // Scale up the number of hashes per host such that the least-weighted host
319
+ // gets a whole number of hashes on the ring. Other hosts might not end up
320
+ // with whole numbers, and that's fine (the ring-building algorithm below can
321
+ // handle this). This preserves the original implementation's behavior: when
322
+ // weights aren't provided, all hosts should get an equal number of hashes. In
323
+ // the case where this number exceeds the max_ring_size, it's scaled back down
324
+ // to fit.
325
+ const size_t min_ring_size = parent_->config_->min_ring_size();
326
+ const size_t max_ring_size = parent_->config_->max_ring_size();
327
+ const double scale = std::min(
328
+ std::ceil(min_normalized_weight * min_ring_size) / min_normalized_weight,
329
+ static_cast<double>(max_ring_size));
330
+ // Reserve memory for the entire ring up front.
331
+ const uint64_t ring_size = std::ceil(scale);
332
+ ring_.reserve(ring_size);
333
+ // Populate the hash ring by walking through the (host, weight) pairs in
334
+ // normalized_host_weights, and generating (scale * weight) hashes for each
335
+ // host. Since these aren't necessarily whole numbers, we maintain running
336
+ // sums -- current_hashes and target_hashes -- which allows us to populate the
337
+ // ring in a mostly stable way.
338
+ absl::InlinedVector<char, 196> hash_key_buffer;
339
+ double current_hashes = 0.0;
340
+ double target_hashes = 0.0;
341
+ uint64_t min_hashes_per_host = ring_size;
342
+ uint64_t max_hashes_per_host = 0;
343
+ for (size_t i = 0; i < num_subchannels; ++i) {
344
+ const std::string& address_string = address_weights[i].address;
345
+ hash_key_buffer.assign(address_string.begin(), address_string.end());
346
+ hash_key_buffer.emplace_back('_');
347
+ auto offset_start = hash_key_buffer.end();
348
+ target_hashes += scale * address_weights[i].normalized_weight;
349
+ size_t count = 0;
350
+ auto current_state =
351
+ subchannel_list->subchannel(i)->subchannel()->CheckConnectivityState();
352
+ while (current_hashes < target_hashes) {
353
+ const std::string count_str = absl::StrCat(count);
354
+ hash_key_buffer.insert(offset_start, count_str.begin(), count_str.end());
355
+ absl::string_view hash_key(hash_key_buffer.data(),
356
+ hash_key_buffer.size());
357
+ const uint64_t hash = XXH64(hash_key.data(), hash_key.size(), 0);
358
+ ring_.push_back({hash,
359
+ subchannel_list->subchannel(i)->subchannel()->Ref(),
360
+ current_state});
361
+ ++count;
362
+ ++current_hashes;
363
+ hash_key_buffer.erase(offset_start, hash_key_buffer.end());
364
+ }
365
+ min_hashes_per_host =
366
+ std::min(static_cast<uint64_t>(i), min_hashes_per_host);
367
+ max_hashes_per_host =
368
+ std::max(static_cast<uint64_t>(i), max_hashes_per_host);
369
+ }
370
+ std::sort(ring_.begin(), ring_.end(),
371
+ [](const RingEntry& lhs, const RingEntry& rhs) -> bool {
372
+ return lhs.hash < rhs.hash;
373
+ });
374
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_ring_hash_trace)) {
375
+ gpr_log(GPR_INFO,
376
+ "[RH %p picker %p] created picker from subchannel_list=%p "
377
+ "with %" PRIuPTR " ring entries",
378
+ parent_.get(), this, subchannel_list, ring_.size());
379
+ }
380
+ }
381
+
382
+ RingHash::PickResult RingHash::Picker::Pick(PickArgs args) {
383
+ auto hash =
384
+ args.call_state->ExperimentalGetCallAttribute(kRequestRingHashAttribute);
385
+ uint64_t h;
386
+ if (!absl::SimpleAtoi(hash, &h)) {
387
+ return PickResult::Fail(
388
+ absl::InternalError("xds ring hash value is not a number"));
389
+ }
390
+ // Ported from https://github.com/RJ/ketama/blob/master/libketama/ketama.c
391
+ // (ketama_get_server) NOTE: The algorithm depends on using signed integers
392
+ // for lowp, highp, and first_index. Do not change them!
393
+ int64_t lowp = 0;
394
+ int64_t highp = ring_.size();
395
+ int64_t first_index = 0;
396
+ while (true) {
397
+ first_index = (lowp + highp) / 2;
398
+ if (first_index == static_cast<int64_t>(ring_.size())) {
399
+ first_index = 0;
400
+ break;
401
+ }
402
+ uint64_t midval = ring_[first_index].hash;
403
+ uint64_t midval1 = first_index == 0 ? 0 : ring_[first_index - 1].hash;
404
+ if (h <= midval && h > midval1) {
405
+ break;
406
+ }
407
+ if (midval < h) {
408
+ lowp = first_index + 1;
409
+ } else {
410
+ highp = first_index - 1;
411
+ }
412
+ if (lowp > highp) {
413
+ first_index = 0;
414
+ break;
415
+ }
416
+ }
417
+ OrphanablePtr<SubchannelConnectionAttempter> subchannel_connection_attempter;
418
+ auto ScheduleSubchannelConnectionAttempt =
419
+ [&](RefCountedPtr<SubchannelInterface> subchannel) {
420
+ if (subchannel_connection_attempter == nullptr) {
421
+ subchannel_connection_attempter =
422
+ MakeOrphanable<SubchannelConnectionAttempter>(parent_);
423
+ }
424
+ subchannel_connection_attempter->AddSubchannel(std::move(subchannel));
425
+ };
426
+ switch (ring_[first_index].connectivity_state) {
427
+ case GRPC_CHANNEL_READY:
428
+ return PickResult::Complete(ring_[first_index].subchannel);
429
+ case GRPC_CHANNEL_IDLE:
430
+ ScheduleSubchannelConnectionAttempt(ring_[first_index].subchannel);
431
+ ABSL_FALLTHROUGH_INTENDED;
432
+ case GRPC_CHANNEL_CONNECTING:
433
+ return PickResult::Queue();
434
+ default: // GRPC_CHANNEL_TRANSIENT_FAILURE
435
+ break;
436
+ }
437
+ ScheduleSubchannelConnectionAttempt(ring_[first_index].subchannel);
438
+ // Loop through remaining subchannels to find one in READY.
439
+ // On the way, we make sure the right set of connection attempts
440
+ // will happen.
441
+ bool found_second_subchannel = false;
442
+ bool found_first_non_failed = false;
443
+ for (size_t i = 1; i < ring_.size(); ++i) {
444
+ const RingEntry& entry = ring_[(first_index + i) % ring_.size()];
445
+ if (entry.subchannel == ring_[first_index].subchannel) {
446
+ continue;
447
+ }
448
+ if (entry.connectivity_state == GRPC_CHANNEL_READY) {
449
+ return PickResult::Complete(entry.subchannel);
450
+ }
451
+ if (!found_second_subchannel) {
452
+ switch (entry.connectivity_state) {
453
+ case GRPC_CHANNEL_IDLE:
454
+ ScheduleSubchannelConnectionAttempt(entry.subchannel);
455
+ ABSL_FALLTHROUGH_INTENDED;
456
+ case GRPC_CHANNEL_CONNECTING:
457
+ return PickResult::Queue();
458
+ default:
459
+ break;
460
+ }
461
+ found_second_subchannel = true;
462
+ }
463
+ if (!found_first_non_failed) {
464
+ if (entry.connectivity_state == GRPC_CHANNEL_TRANSIENT_FAILURE) {
465
+ ScheduleSubchannelConnectionAttempt(entry.subchannel);
466
+ } else {
467
+ if (entry.connectivity_state == GRPC_CHANNEL_IDLE) {
468
+ ScheduleSubchannelConnectionAttempt(entry.subchannel);
469
+ }
470
+ found_first_non_failed = true;
471
+ }
472
+ }
473
+ }
474
+ return PickResult::Fail(absl::UnavailableError(
475
+ "xds ring hash found a subchannel that is in TRANSIENT_FAILURE state"));
476
+ }
477
+
478
+ //
479
+ // RingHash::RingHashSubchannelList
480
+ //
481
+
482
+ void RingHash::RingHashSubchannelList::StartWatchingLocked() {
483
+ if (num_subchannels() == 0) return;
484
+ // Check current state of each subchannel synchronously.
485
+ for (size_t i = 0; i < num_subchannels(); ++i) {
486
+ grpc_connectivity_state state =
487
+ subchannel(i)->CheckConnectivityStateLocked();
488
+ subchannel(i)->UpdateConnectivityStateLocked(state);
489
+ }
490
+ // Start connectivity watch for each subchannel.
491
+ for (size_t i = 0; i < num_subchannels(); i++) {
492
+ if (subchannel(i)->subchannel() != nullptr) {
493
+ subchannel(i)->StartConnectivityWatchLocked();
494
+ }
495
+ }
496
+ RingHash* p = static_cast<RingHash*>(policy());
497
+ // Sending up the initial picker while all subchannels are in IDLE state.
498
+ p->channel_control_helper()->UpdateState(
499
+ GRPC_CHANNEL_READY, absl::Status(),
500
+ absl::make_unique<Picker>(p->Ref(DEBUG_LOCATION, "RingHashPicker"),
501
+ this));
502
+ }
503
+
504
+ void RingHash::RingHashSubchannelList::UpdateStateCountersLocked(
505
+ grpc_connectivity_state old_state, grpc_connectivity_state new_state) {
506
+ GPR_ASSERT(new_state != GRPC_CHANNEL_SHUTDOWN);
507
+ if (old_state == GRPC_CHANNEL_IDLE) {
508
+ GPR_ASSERT(num_idle_ > 0);
509
+ --num_idle_;
510
+ } else if (old_state == GRPC_CHANNEL_READY) {
511
+ GPR_ASSERT(num_ready_ > 0);
512
+ --num_ready_;
513
+ } else if (old_state == GRPC_CHANNEL_CONNECTING) {
514
+ GPR_ASSERT(num_connecting_ > 0);
515
+ --num_connecting_;
516
+ } else if (old_state == GRPC_CHANNEL_TRANSIENT_FAILURE) {
517
+ GPR_ASSERT(num_transient_failure_ > 0);
518
+ --num_transient_failure_;
519
+ }
520
+ if (new_state == GRPC_CHANNEL_IDLE) {
521
+ ++num_idle_;
522
+ } else if (new_state == GRPC_CHANNEL_READY) {
523
+ ++num_ready_;
524
+ } else if (new_state == GRPC_CHANNEL_CONNECTING) {
525
+ ++num_connecting_;
526
+ } else if (new_state == GRPC_CHANNEL_TRANSIENT_FAILURE) {
527
+ ++num_transient_failure_;
528
+ }
529
+ }
530
+
531
+ // Sets the RH policy's connectivity state and generates a new picker based
532
+ // on the current subchannel list or requests an re-attempt by returning true..
533
+ bool RingHash::RingHashSubchannelList::UpdateRingHashConnectivityStateLocked() {
534
+ RingHash* p = static_cast<RingHash*>(policy());
535
+ // Only set connectivity state if this is the current subchannel list.
536
+ if (p->subchannel_list_.get() != this) return false;
537
+ // The overall aggregation rules here are:
538
+ // 1. If there is at least one subchannel in READY state, report READY.
539
+ // 2. If there are 2 or more subchannels in TRANSIENT_FAILURE state, report
540
+ // TRANSIENT_FAILURE.
541
+ // 3. If there is at least one subchannel in CONNECTING state, report
542
+ // CONNECTING.
543
+ // 4. If there is at least one subchannel in IDLE state, report IDLE.
544
+ // 5. Otherwise, report TRANSIENT_FAILURE.
545
+ if (num_ready_ > 0) {
546
+ /* READY */
547
+ p->channel_control_helper()->UpdateState(
548
+ GRPC_CHANNEL_READY, absl::Status(),
549
+ absl::make_unique<Picker>(p->Ref(DEBUG_LOCATION, "RingHashPicker"),
550
+ this));
551
+ return false;
552
+ }
553
+ if (num_connecting_ > 0 && num_transient_failure_ < 2) {
554
+ p->channel_control_helper()->UpdateState(
555
+ GRPC_CHANNEL_CONNECTING, absl::Status(),
556
+ absl::make_unique<QueuePicker>(p->Ref(DEBUG_LOCATION, "QueuePicker")));
557
+ return false;
558
+ }
559
+ if (num_idle_ > 0 && num_transient_failure_ < 2) {
560
+ p->channel_control_helper()->UpdateState(
561
+ GRPC_CHANNEL_IDLE, absl::Status(),
562
+ absl::make_unique<Picker>(p->Ref(DEBUG_LOCATION, "RingHashPicker"),
563
+ this));
564
+ return false;
565
+ }
566
+ absl::Status status =
567
+ absl::UnavailableError("connections to backend failing or idle");
568
+ p->channel_control_helper()->UpdateState(
569
+ GRPC_CHANNEL_TRANSIENT_FAILURE, status,
570
+ absl::make_unique<TransientFailurePicker>(status));
571
+ return true;
572
+ }
573
+
574
+ //
575
+ // RingHash::RingHashSubchannelData
576
+ //
577
+
578
+ void RingHash::RingHashSubchannelData::UpdateConnectivityStateLocked(
579
+ grpc_connectivity_state connectivity_state) {
580
+ RingHash* p = static_cast<RingHash*>(subchannel_list()->policy());
581
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_ring_hash_trace)) {
582
+ gpr_log(
583
+ GPR_INFO,
584
+ "[RR %p] connectivity changed for subchannel %p, subchannel_list %p "
585
+ "(index %" PRIuPTR " of %" PRIuPTR "): prev_state=%s new_state=%s",
586
+ p, subchannel(), subchannel_list(), Index(),
587
+ subchannel_list()->num_subchannels(),
588
+ ConnectivityStateName(last_connectivity_state_),
589
+ ConnectivityStateName(connectivity_state));
590
+ }
591
+ // Decide what state to report for aggregation purposes.
592
+ // If we haven't seen a failure since the last time we were in state
593
+ // READY, then we report the state change as-is. However, once we do see
594
+ // a failure, we report TRANSIENT_FAILURE and do not report any subsequent
595
+ // state changes until we go back into state READY.
596
+ if (!seen_failure_since_ready_) {
597
+ if (connectivity_state == GRPC_CHANNEL_TRANSIENT_FAILURE) {
598
+ seen_failure_since_ready_ = true;
599
+ }
600
+ subchannel_list()->UpdateStateCountersLocked(last_connectivity_state_,
601
+ connectivity_state);
602
+ } else {
603
+ if (connectivity_state == GRPC_CHANNEL_READY) {
604
+ seen_failure_since_ready_ = false;
605
+ subchannel_list()->UpdateStateCountersLocked(
606
+ GRPC_CHANNEL_TRANSIENT_FAILURE, connectivity_state);
607
+ }
608
+ }
609
+ // Record last seen connectivity state.
610
+ last_connectivity_state_ = connectivity_state;
611
+ }
612
+
613
+ void RingHash::RingHashSubchannelData::ProcessConnectivityChangeLocked(
614
+ grpc_connectivity_state connectivity_state) {
615
+ RingHash* p = static_cast<RingHash*>(subchannel_list()->policy());
616
+ GPR_ASSERT(subchannel() != nullptr);
617
+ // If the new state is TRANSIENT_FAILURE, re-resolve.
618
+ // Only do this if we've started watching, not at startup time.
619
+ // Otherwise, if the subchannel was already in state TRANSIENT_FAILURE
620
+ // when the subchannel list was created, we'd wind up in a constant
621
+ // loop of re-resolution.
622
+ // Also attempt to reconnect.
623
+ if (connectivity_state == GRPC_CHANNEL_TRANSIENT_FAILURE) {
624
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_ring_hash_trace)) {
625
+ gpr_log(GPR_INFO,
626
+ "[RR %p] Subchannel %p has gone into TRANSIENT_FAILURE. "
627
+ "Requesting re-resolution",
628
+ p, subchannel());
629
+ }
630
+ p->channel_control_helper()->RequestReresolution();
631
+ }
632
+ // Update state counters.
633
+ UpdateConnectivityStateLocked(connectivity_state);
634
+ // Update the RH policy's connectivity state, creating new picker and new
635
+ // ring.
636
+ bool transient_failure =
637
+ subchannel_list()->UpdateRingHashConnectivityStateLocked();
638
+ // While the ring_hash policy is reporting TRANSIENT_FAILURE, it will
639
+ // not be getting any pick requests from the priority policy.
640
+ // However, because the ring_hash policy does not attempt to
641
+ // reconnect to subchannels unless it is getting pick requests,
642
+ // it will need special handling to ensure that it will eventually
643
+ // recover from TRANSIENT_FAILURE state once the problem is resolved.
644
+ // Specifically, it will make sure that it is attempting to connect to
645
+ // at least one subchannel at any given time. After a given subchannel
646
+ // fails a connection attempt, it will move on to the next subchannel
647
+ // in the ring. It will keep doing this until one of the subchannels
648
+ // successfully connects, at which point it will report READY and stop
649
+ // proactively trying to connect. The policy will remain in
650
+ // TRANSIENT_FAILURE until at least one subchannel becomes connected,
651
+ // even if subchannels are in state CONNECTING during that time.
652
+ if (transient_failure &&
653
+ connectivity_state == GRPC_CHANNEL_TRANSIENT_FAILURE) {
654
+ size_t next_index = (Index() + 1) % subchannel_list()->num_subchannels();
655
+ RingHashSubchannelData* next_sd = subchannel_list()->subchannel(next_index);
656
+ next_sd->subchannel()->AttemptToConnect();
657
+ }
658
+ }
659
+
660
+ //
661
+ // RingHash
662
+ //
663
+
664
+ RingHash::RingHash(Args args) : LoadBalancingPolicy(std::move(args)) {
665
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_ring_hash_trace)) {
666
+ gpr_log(GPR_INFO, "[RH %p] Created", this);
667
+ }
668
+ }
669
+
670
+ RingHash::~RingHash() {
671
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_ring_hash_trace)) {
672
+ gpr_log(GPR_INFO, "[RH %p] Destroying Ring Hash policy", this);
673
+ }
674
+ GPR_ASSERT(subchannel_list_ == nullptr);
675
+ }
676
+
677
+ void RingHash::ShutdownLocked() {
678
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_ring_hash_trace)) {
679
+ gpr_log(GPR_INFO, "[RH %p] Shutting down", this);
680
+ }
681
+ shutdown_ = true;
682
+ subchannel_list_.reset();
683
+ }
684
+
685
+ void RingHash::ResetBackoffLocked() { subchannel_list_->ResetBackoffLocked(); }
686
+
687
+ void RingHash::UpdateLocked(UpdateArgs args) {
688
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_ring_hash_trace)) {
689
+ gpr_log(GPR_INFO, "[RR %p] received update with %" PRIuPTR " addresses",
690
+ this, args.addresses.size());
691
+ }
692
+ config_ = std::move(args.config);
693
+ // Filter out any address with weight 0.
694
+ ServerAddressList addresses;
695
+ addresses.reserve(args.addresses.size());
696
+ for (ServerAddress& address : args.addresses) {
697
+ const ServerAddressWeightAttribute* weight_attribute =
698
+ static_cast<const ServerAddressWeightAttribute*>(address.GetAttribute(
699
+ ServerAddressWeightAttribute::kServerAddressWeightAttributeKey));
700
+ if (weight_attribute == nullptr || weight_attribute->weight() > 0) {
701
+ addresses.push_back(std::move(address));
702
+ }
703
+ }
704
+ subchannel_list_ = MakeOrphanable<RingHashSubchannelList>(
705
+ this, &grpc_lb_ring_hash_trace, std::move(addresses), *args.args);
706
+ if (subchannel_list_->num_subchannels() == 0) {
707
+ // If the new list is empty, immediately transition to TRANSIENT_FAILURE.
708
+ absl::Status status = absl::UnavailableError("Empty update");
709
+ channel_control_helper()->UpdateState(
710
+ GRPC_CHANNEL_TRANSIENT_FAILURE, status,
711
+ absl::make_unique<TransientFailurePicker>(status));
712
+ } else {
713
+ // Start watching the new list.
714
+ subchannel_list_->StartWatchingLocked();
715
+ }
716
+ }
717
+
718
+ //
719
+ // factory
720
+ //
721
+
722
+ class RingHashFactory : public LoadBalancingPolicyFactory {
723
+ public:
724
+ OrphanablePtr<LoadBalancingPolicy> CreateLoadBalancingPolicy(
725
+ LoadBalancingPolicy::Args args) const override {
726
+ return MakeOrphanable<RingHash>(std::move(args));
727
+ }
728
+
729
+ const char* name() const override { return kRingHash; }
730
+
731
+ RefCountedPtr<LoadBalancingPolicy::Config> ParseLoadBalancingConfig(
732
+ const Json& json, grpc_error** error) const override {
733
+ size_t min_ring_size;
734
+ size_t max_ring_size;
735
+ std::vector<grpc_error_handle> error_list;
736
+ ParseRingHashLbConfig(json, &min_ring_size, &max_ring_size, &error_list);
737
+ if (error_list.empty()) {
738
+ return MakeRefCounted<RingHashLbConfig>(min_ring_size, max_ring_size);
739
+ } else {
740
+ *error = GRPC_ERROR_CREATE_FROM_VECTOR(
741
+ "ring_hash_experimental LB policy config", &error_list);
742
+ return nullptr;
743
+ }
744
+ }
745
+ };
746
+
747
+ } // namespace
748
+
749
+ void GrpcLbPolicyRingHashInit() {
750
+ grpc_core::LoadBalancingPolicyRegistry::Builder::
751
+ RegisterLoadBalancingPolicyFactory(
752
+ absl::make_unique<grpc_core::RingHashFactory>());
753
+ }
754
+
755
+ void GrpcLbPolicyRingHashShutdown() {}
22
756
 
23
757
  } // namespace grpc_core