grpc 1.60.2 → 1.61.0.pre2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (279) hide show
  1. checksums.yaml +4 -4
  2. data/Makefile +208 -165
  3. data/include/grpc/event_engine/event_engine.h +59 -12
  4. data/include/grpc/event_engine/internal/memory_allocator_impl.h +6 -0
  5. data/include/grpc/event_engine/internal/slice_cast.h +12 -0
  6. data/include/grpc/event_engine/memory_allocator.h +3 -1
  7. data/include/grpc/event_engine/slice.h +5 -0
  8. data/include/grpc/grpc_security.h +22 -1
  9. data/include/grpc/impl/call.h +29 -0
  10. data/include/grpc/impl/channel_arg_names.h +12 -1
  11. data/include/grpc/impl/slice_type.h +1 -1
  12. data/include/grpc/module.modulemap +1 -0
  13. data/src/core/ext/filters/backend_metrics/backend_metric_filter.cc +54 -7
  14. data/src/core/ext/filters/backend_metrics/backend_metric_filter.h +20 -6
  15. data/src/core/ext/filters/channel_idle/channel_idle_filter.cc +10 -13
  16. data/src/core/ext/filters/channel_idle/channel_idle_filter.h +18 -10
  17. data/src/core/ext/filters/channel_idle/legacy_channel_idle_filter.cc +326 -0
  18. data/src/core/ext/filters/channel_idle/legacy_channel_idle_filter.h +143 -0
  19. data/src/core/ext/filters/client_channel/backend_metric.cc +2 -2
  20. data/src/core/ext/filters/client_channel/client_channel.cc +32 -6
  21. data/src/core/ext/filters/client_channel/client_channel_internal.h +2 -0
  22. data/src/core/ext/filters/client_channel/global_subchannel_pool.cc +1 -1
  23. data/src/core/ext/filters/client_channel/lb_policy/address_filtering.cc +54 -21
  24. data/src/core/ext/filters/client_channel/lb_policy/address_filtering.h +3 -2
  25. data/src/core/ext/filters/client_channel/lb_policy/child_policy_handler.cc +2 -1
  26. data/src/core/ext/filters/client_channel/lb_policy/endpoint_list.cc +12 -15
  27. data/src/core/ext/filters/client_channel/lb_policy/endpoint_list.h +8 -5
  28. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc +139 -92
  29. data/src/core/ext/filters/client_channel/lb_policy/health_check_client.cc +9 -4
  30. data/src/core/ext/filters/client_channel/lb_policy/oob_backend_metric.cc +9 -4
  31. data/src/core/ext/filters/client_channel/lb_policy/outlier_detection/outlier_detection.cc +10 -11
  32. data/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc +94 -93
  33. data/src/core/ext/filters/client_channel/lb_policy/priority/priority.cc +5 -3
  34. data/src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.cc +12 -15
  35. data/src/core/ext/filters/client_channel/lb_policy/rls/rls.cc +38 -16
  36. data/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc +25 -28
  37. data/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h +10 -10
  38. data/src/core/ext/filters/client_channel/lb_policy/weighted_round_robin/weighted_round_robin.cc +37 -35
  39. data/src/core/ext/filters/client_channel/lb_policy/weighted_target/weighted_target.cc +11 -9
  40. data/src/core/ext/filters/client_channel/lb_policy/xds/cds.cc +504 -461
  41. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_impl.cc +232 -122
  42. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_manager.cc +8 -6
  43. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_override_host.cc +642 -251
  44. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_override_host.h +2 -6
  45. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_wrr_locality.cc +7 -8
  46. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc +2 -1
  47. data/src/core/ext/filters/client_channel/resolver/dns/event_engine/event_engine_client_channel_resolver.cc +3 -1
  48. data/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc +2 -2
  49. data/src/core/ext/filters/client_channel/resolver/google_c2p/google_c2p_resolver.cc +2 -2
  50. data/src/core/ext/filters/client_channel/resolver/polling_resolver.cc +6 -8
  51. data/src/core/ext/filters/client_channel/resolver/xds/xds_dependency_manager.cc +1031 -0
  52. data/src/core/ext/filters/client_channel/resolver/xds/xds_dependency_manager.h +277 -0
  53. data/src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc +128 -270
  54. data/src/core/ext/filters/client_channel/resolver/xds/{xds_resolver.h → xds_resolver_attributes.h} +5 -4
  55. data/src/core/ext/filters/client_channel/resolver/xds/xds_resolver_trace.cc +25 -0
  56. data/src/core/ext/filters/client_channel/resolver/xds/xds_resolver_trace.h +30 -0
  57. data/src/core/ext/filters/client_channel/retry_filter.cc +1 -0
  58. data/src/core/ext/filters/client_channel/service_config_channel_arg_filter.cc +35 -17
  59. data/src/core/ext/filters/deadline/deadline_filter.cc +12 -0
  60. data/src/core/ext/filters/fault_injection/fault_injection_filter.cc +17 -13
  61. data/src/core/ext/filters/fault_injection/fault_injection_filter.h +13 -4
  62. data/src/core/ext/filters/http/client/http_client_filter.cc +23 -32
  63. data/src/core/ext/filters/http/client/http_client_filter.h +10 -5
  64. data/src/core/ext/filters/http/client_authority_filter.cc +14 -14
  65. data/src/core/ext/filters/http/client_authority_filter.h +12 -4
  66. data/src/core/ext/filters/http/http_filters_plugin.cc +42 -20
  67. data/src/core/ext/filters/http/message_compress/compression_filter.cc +55 -80
  68. data/src/core/ext/filters/http/message_compress/compression_filter.h +54 -12
  69. data/src/core/ext/filters/http/message_compress/legacy_compression_filter.cc +325 -0
  70. data/src/core/ext/filters/http/message_compress/legacy_compression_filter.h +139 -0
  71. data/src/core/ext/filters/http/server/http_server_filter.cc +41 -41
  72. data/src/core/ext/filters/http/server/http_server_filter.h +11 -4
  73. data/src/core/ext/filters/message_size/message_size_filter.cc +56 -76
  74. data/src/core/ext/filters/message_size/message_size_filter.h +35 -23
  75. data/src/core/ext/filters/rbac/rbac_filter.cc +15 -11
  76. data/src/core/ext/filters/rbac/rbac_filter.h +11 -4
  77. data/src/core/ext/filters/server_config_selector/server_config_selector_filter.cc +25 -13
  78. data/src/core/ext/filters/stateful_session/stateful_session_filter.cc +47 -50
  79. data/src/core/ext/filters/stateful_session/stateful_session_filter.h +21 -4
  80. data/src/core/ext/transport/chttp2/alpn/alpn.cc +1 -1
  81. data/src/core/ext/transport/chttp2/client/chttp2_connector.cc +2 -2
  82. data/src/core/ext/transport/chttp2/server/chttp2_server.cc +11 -2
  83. data/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +68 -145
  84. data/src/core/ext/transport/chttp2/transport/chttp2_transport.h +3 -3
  85. data/src/core/ext/transport/chttp2/transport/flow_control.cc +21 -82
  86. data/src/core/ext/transport/chttp2/transport/flow_control.h +1 -8
  87. data/src/core/ext/transport/chttp2/transport/frame.cc +506 -0
  88. data/src/core/ext/transport/chttp2/transport/frame.h +214 -0
  89. data/src/core/ext/transport/chttp2/transport/frame_rst_stream.cc +1 -1
  90. data/src/core/ext/transport/chttp2/transport/frame_settings.cc +33 -79
  91. data/src/core/ext/transport/chttp2/transport/frame_settings.h +4 -7
  92. data/src/core/ext/transport/chttp2/transport/hpack_parser.cc +27 -36
  93. data/src/core/ext/transport/chttp2/transport/hpack_parser.h +0 -2
  94. data/src/core/ext/transport/chttp2/transport/http2_settings.cc +122 -32
  95. data/src/core/ext/transport/chttp2/transport/http2_settings.h +142 -37
  96. data/src/core/ext/transport/chttp2/transport/internal.h +1 -22
  97. data/src/core/ext/transport/chttp2/transport/parsing.cc +23 -37
  98. data/src/core/ext/transport/chttp2/transport/writing.cc +26 -58
  99. data/src/core/ext/transport/inproc/inproc_transport.cc +172 -13
  100. data/src/core/ext/upb-gen/envoy/extensions/upstreams/http/v3/http_protocol_options.upb.h +712 -0
  101. data/src/core/ext/upb-gen/envoy/extensions/upstreams/http/v3/http_protocol_options.upb_minitable.c +151 -0
  102. data/src/core/ext/upb-gen/envoy/extensions/upstreams/http/v3/http_protocol_options.upb_minitable.h +33 -0
  103. data/src/core/ext/upbdefs-gen/envoy/extensions/upstreams/http/v3/http_protocol_options.upbdefs.c +133 -0
  104. data/src/core/ext/upbdefs-gen/envoy/extensions/upstreams/http/v3/http_protocol_options.upbdefs.h +50 -0
  105. data/src/core/ext/xds/certificate_provider_store.cc +2 -1
  106. data/src/core/ext/xds/certificate_provider_store.h +0 -5
  107. data/src/core/ext/xds/xds_api.cc +31 -18
  108. data/src/core/ext/xds/xds_api.h +2 -2
  109. data/src/core/ext/xds/xds_bootstrap.h +3 -0
  110. data/src/core/ext/xds/xds_certificate_provider.cc +88 -287
  111. data/src/core/ext/xds/xds_certificate_provider.h +44 -111
  112. data/src/core/ext/xds/xds_client.cc +420 -414
  113. data/src/core/ext/xds/xds_client.h +31 -22
  114. data/src/core/ext/xds/xds_client_grpc.cc +3 -1
  115. data/src/core/ext/xds/xds_cluster.cc +104 -11
  116. data/src/core/ext/xds/xds_cluster.h +9 -1
  117. data/src/core/ext/xds/xds_cluster_specifier_plugin.cc +9 -5
  118. data/src/core/ext/xds/xds_common_types.cc +14 -10
  119. data/src/core/ext/xds/xds_endpoint.cc +9 -4
  120. data/src/core/ext/xds/xds_endpoint.h +5 -1
  121. data/src/core/ext/xds/xds_health_status.cc +12 -2
  122. data/src/core/ext/xds/xds_health_status.h +4 -2
  123. data/src/core/ext/xds/xds_http_rbac_filter.cc +5 -3
  124. data/src/core/ext/xds/xds_listener.cc +14 -8
  125. data/src/core/ext/xds/xds_resource_type_impl.h +6 -4
  126. data/src/core/ext/xds/xds_route_config.cc +34 -22
  127. data/src/core/ext/xds/xds_route_config.h +1 -0
  128. data/src/core/ext/xds/xds_server_config_fetcher.cc +61 -57
  129. data/src/core/ext/xds/xds_transport.h +3 -0
  130. data/src/core/ext/xds/xds_transport_grpc.cc +47 -50
  131. data/src/core/ext/xds/xds_transport_grpc.h +4 -0
  132. data/src/core/lib/channel/call_tracer.cc +12 -0
  133. data/src/core/lib/channel/call_tracer.h +17 -3
  134. data/src/core/lib/channel/channel_args.cc +24 -14
  135. data/src/core/lib/channel/channel_args.h +74 -13
  136. data/src/core/lib/channel/channel_stack.cc +27 -0
  137. data/src/core/lib/channel/channel_stack.h +10 -10
  138. data/src/core/lib/channel/connected_channel.cc +64 -18
  139. data/src/core/lib/channel/promise_based_filter.h +1041 -1
  140. data/src/core/lib/channel/server_call_tracer_filter.cc +43 -35
  141. data/src/core/lib/compression/compression_internal.cc +0 -3
  142. data/src/core/lib/event_engine/ares_resolver.cc +35 -14
  143. data/src/core/lib/event_engine/ares_resolver.h +9 -10
  144. data/src/core/lib/event_engine/cf_engine/dns_service_resolver.cc +8 -1
  145. data/src/core/lib/event_engine/posix_engine/native_posix_dns_resolver.cc +132 -0
  146. data/src/core/lib/event_engine/posix_engine/native_posix_dns_resolver.h +61 -0
  147. data/src/core/lib/event_engine/posix_engine/posix_engine.cc +52 -36
  148. data/src/core/lib/event_engine/posix_engine/posix_engine.h +4 -9
  149. data/src/core/lib/event_engine/posix_engine/posix_engine_listener_utils.cc +11 -3
  150. data/src/core/lib/event_engine/posix_engine/tcp_socket_utils.cc +9 -2
  151. data/src/core/lib/event_engine/posix_engine/tcp_socket_utils.h +7 -0
  152. data/src/core/lib/event_engine/posix_engine/timer_manager.cc +17 -27
  153. data/src/core/lib/event_engine/posix_engine/timer_manager.h +0 -3
  154. data/src/core/lib/event_engine/ref_counted_dns_resolver_interface.h +55 -0
  155. data/src/core/lib/event_engine/windows/native_windows_dns_resolver.cc +114 -0
  156. data/src/core/lib/event_engine/windows/native_windows_dns_resolver.h +51 -0
  157. data/src/core/lib/event_engine/windows/windows_engine.cc +7 -7
  158. data/src/core/lib/experiments/config.cc +13 -0
  159. data/src/core/lib/experiments/config.h +3 -0
  160. data/src/core/lib/experiments/experiments.cc +245 -366
  161. data/src/core/lib/experiments/experiments.h +50 -156
  162. data/src/core/lib/gprpp/debug_location.h +13 -0
  163. data/src/core/lib/gprpp/dual_ref_counted.h +36 -7
  164. data/src/core/lib/gprpp/orphanable.h +27 -0
  165. data/src/core/lib/gprpp/ref_counted.h +63 -22
  166. data/src/core/lib/gprpp/ref_counted_ptr.h +70 -27
  167. data/src/core/lib/gprpp/ref_counted_string.h +13 -0
  168. data/src/core/lib/gprpp/status_helper.cc +1 -2
  169. data/src/core/lib/iomgr/combiner.cc +15 -51
  170. data/src/core/lib/iomgr/event_engine_shims/endpoint.cc +31 -0
  171. data/src/core/lib/iomgr/event_engine_shims/endpoint.h +16 -0
  172. data/src/core/lib/iomgr/tcp_client_posix.cc +4 -3
  173. data/src/core/lib/load_balancing/lb_policy.h +1 -1
  174. data/src/core/lib/promise/activity.cc +17 -2
  175. data/src/core/lib/promise/activity.h +5 -4
  176. data/src/core/lib/promise/all_ok.h +80 -0
  177. data/src/core/lib/promise/detail/join_state.h +2077 -0
  178. data/src/core/lib/promise/detail/promise_factory.h +1 -0
  179. data/src/core/lib/promise/detail/promise_like.h +8 -1
  180. data/src/core/lib/promise/detail/seq_state.h +3458 -150
  181. data/src/core/lib/promise/detail/status.h +42 -5
  182. data/src/core/lib/promise/for_each.h +13 -1
  183. data/src/core/lib/promise/if.h +4 -0
  184. data/src/core/lib/promise/latch.h +6 -3
  185. data/src/core/lib/promise/party.cc +33 -31
  186. data/src/core/lib/promise/party.h +142 -6
  187. data/src/core/lib/promise/poll.h +39 -13
  188. data/src/core/lib/promise/promise.h +4 -0
  189. data/src/core/lib/promise/seq.h +107 -7
  190. data/src/core/lib/promise/status_flag.h +196 -0
  191. data/src/core/lib/promise/try_join.h +132 -0
  192. data/src/core/lib/promise/try_seq.h +132 -10
  193. data/src/core/lib/resolver/endpoint_addresses.cc +0 -1
  194. data/src/core/lib/resolver/endpoint_addresses.h +48 -0
  195. data/src/core/lib/resource_quota/arena.h +2 -2
  196. data/src/core/lib/resource_quota/memory_quota.cc +57 -8
  197. data/src/core/lib/resource_quota/memory_quota.h +6 -0
  198. data/src/core/lib/security/authorization/grpc_server_authz_filter.cc +14 -11
  199. data/src/core/lib/security/authorization/grpc_server_authz_filter.h +14 -5
  200. data/src/core/lib/security/credentials/external/aws_external_account_credentials.cc +4 -0
  201. data/src/core/lib/security/credentials/external/aws_external_account_credentials.h +4 -0
  202. data/src/core/lib/security/credentials/external/external_account_credentials.cc +28 -20
  203. data/src/core/lib/security/credentials/external/external_account_credentials.h +4 -0
  204. data/src/core/lib/security/credentials/external/file_external_account_credentials.cc +4 -0
  205. data/src/core/lib/security/credentials/external/file_external_account_credentials.h +4 -0
  206. data/src/core/lib/security/credentials/external/url_external_account_credentials.cc +4 -0
  207. data/src/core/lib/security/credentials/external/url_external_account_credentials.h +4 -0
  208. data/src/core/lib/security/credentials/plugin/plugin_credentials.cc +2 -1
  209. data/src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.h +0 -3
  210. data/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc +12 -0
  211. data/src/core/lib/security/credentials/tls/grpc_tls_crl_provider.cc +22 -5
  212. data/src/core/lib/security/credentials/tls/grpc_tls_crl_provider.h +1 -5
  213. data/src/core/lib/security/credentials/tls/tls_credentials.cc +16 -0
  214. data/src/core/lib/security/credentials/xds/xds_credentials.cc +21 -28
  215. data/src/core/lib/security/credentials/xds/xds_credentials.h +2 -4
  216. data/src/core/lib/security/security_connector/tls/tls_security_connector.cc +4 -3
  217. data/src/core/lib/security/transport/auth_filters.h +71 -4
  218. data/src/core/lib/security/transport/client_auth_filter.cc +2 -4
  219. data/src/core/lib/security/transport/legacy_server_auth_filter.cc +244 -0
  220. data/src/core/lib/security/transport/server_auth_filter.cc +70 -90
  221. data/src/core/lib/slice/slice_buffer.h +3 -0
  222. data/src/core/lib/surface/builtins.cc +1 -1
  223. data/src/core/lib/surface/call.cc +683 -196
  224. data/src/core/lib/surface/call.h +26 -13
  225. data/src/core/lib/surface/call_trace.cc +42 -1
  226. data/src/core/lib/surface/channel.cc +0 -1
  227. data/src/core/lib/surface/channel.h +0 -6
  228. data/src/core/lib/surface/channel_init.h +26 -0
  229. data/src/core/lib/surface/init.cc +14 -8
  230. data/src/core/lib/surface/server.cc +256 -237
  231. data/src/core/lib/surface/server.h +26 -54
  232. data/src/core/lib/surface/version.cc +2 -2
  233. data/src/core/lib/surface/wait_for_cq_end_op.h +94 -0
  234. data/src/core/lib/transport/call_final_info.cc +38 -0
  235. data/src/core/lib/transport/call_final_info.h +54 -0
  236. data/src/core/lib/transport/connectivity_state.cc +3 -2
  237. data/src/core/lib/transport/connectivity_state.h +4 -0
  238. data/src/core/lib/transport/metadata_batch.h +4 -4
  239. data/src/core/lib/transport/transport.cc +70 -19
  240. data/src/core/lib/transport/transport.h +395 -25
  241. data/src/core/plugin_registry/grpc_plugin_registry.cc +3 -0
  242. data/src/core/plugin_registry/grpc_plugin_registry_extra.cc +0 -3
  243. data/src/core/tsi/alts/handshaker/alts_handshaker_client.cc +1 -1
  244. data/src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc +1 -1
  245. data/src/core/tsi/alts/handshaker/transport_security_common_api.cc +1 -1
  246. data/src/core/tsi/ssl_transport_security.cc +65 -43
  247. data/src/ruby/ext/grpc/rb_channel_args.c +3 -1
  248. data/src/ruby/ext/grpc/rb_grpc.c +0 -1
  249. data/src/ruby/ext/grpc/rb_grpc.h +0 -2
  250. data/src/ruby/ext/grpc/rb_grpc_imports.generated.c +4 -0
  251. data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +6 -0
  252. data/src/ruby/lib/grpc/version.rb +1 -1
  253. data/third_party/upb/upb/reflection/def_pool.h +2 -2
  254. data/third_party/zlib/adler32.c +5 -27
  255. data/third_party/zlib/compress.c +5 -16
  256. data/third_party/zlib/crc32.c +86 -162
  257. data/third_party/zlib/deflate.c +233 -336
  258. data/third_party/zlib/deflate.h +8 -8
  259. data/third_party/zlib/gzguts.h +11 -12
  260. data/third_party/zlib/infback.c +7 -23
  261. data/third_party/zlib/inffast.c +1 -4
  262. data/third_party/zlib/inffast.h +1 -1
  263. data/third_party/zlib/inflate.c +30 -99
  264. data/third_party/zlib/inftrees.c +6 -11
  265. data/third_party/zlib/inftrees.h +3 -3
  266. data/third_party/zlib/trees.c +224 -302
  267. data/third_party/zlib/uncompr.c +4 -12
  268. data/third_party/zlib/zconf.h +6 -2
  269. data/third_party/zlib/zlib.h +191 -188
  270. data/third_party/zlib/zutil.c +16 -44
  271. data/third_party/zlib/zutil.h +10 -10
  272. metadata +35 -13
  273. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_resolver.cc +0 -1173
  274. data/src/core/lib/event_engine/memory_allocator.cc +0 -74
  275. data/src/core/lib/transport/pid_controller.cc +0 -51
  276. data/src/core/lib/transport/pid_controller.h +0 -116
  277. data/third_party/upb/upb/collections/array.h +0 -17
  278. data/third_party/upb/upb/collections/map.h +0 -17
  279. data/third_party/upb/upb/upb.hpp +0 -18
@@ -28,7 +28,7 @@
28
28
  #include "absl/status/status.h"
29
29
  #include "absl/strings/string_view.h"
30
30
  #include "google/protobuf/duration.upb.h"
31
- #include "upb/upb.hpp"
31
+ #include "upb/mem/arena.hpp"
32
32
  #include "xds/service/orca/v3/orca.upb.h"
33
33
 
34
34
  #include <grpc/impl/connectivity_state.h>
@@ -215,7 +215,8 @@ class OrcaProducer::OrcaStreamEventHandler
215
215
  void OrcaProducer::Start(RefCountedPtr<Subchannel> subchannel) {
216
216
  subchannel_ = std::move(subchannel);
217
217
  connected_subchannel_ = subchannel_->connected_subchannel();
218
- auto connectivity_watcher = MakeRefCounted<ConnectivityWatcher>(WeakRef());
218
+ auto connectivity_watcher =
219
+ MakeRefCounted<ConnectivityWatcher>(WeakRefAsSubclass<OrcaProducer>());
219
220
  connectivity_watcher_ = connectivity_watcher.get();
220
221
  subchannel_->WatchConnectivityState(std::move(connectivity_watcher));
221
222
  }
@@ -269,7 +270,8 @@ void OrcaProducer::MaybeStartStreamLocked() {
269
270
  if (connected_subchannel_ == nullptr) return;
270
271
  stream_client_ = MakeOrphanable<SubchannelStreamClient>(
271
272
  connected_subchannel_, subchannel_->pollset_set(),
272
- std::make_unique<OrcaStreamEventHandler>(WeakRef(), report_interval_),
273
+ std::make_unique<OrcaStreamEventHandler>(
274
+ WeakRefAsSubclass<OrcaProducer>(), report_interval_),
273
275
  GRPC_TRACE_FLAG_ENABLED(grpc_orca_client_trace) ? "OrcaClient" : nullptr);
274
276
  }
275
277
 
@@ -310,7 +312,10 @@ void OrcaWatcher::SetSubchannel(Subchannel* subchannel) {
310
312
  // If not, create a new one.
311
313
  subchannel->GetOrAddDataProducer(
312
314
  OrcaProducer::Type(), [&](Subchannel::DataProducerInterface** producer) {
313
- if (*producer != nullptr) producer_ = (*producer)->RefIfNonZero();
315
+ if (*producer != nullptr) {
316
+ producer_ =
317
+ (*producer)->RefIfNonZero().TakeAsSubclass<OrcaProducer>();
318
+ }
314
319
  if (producer_ == nullptr) {
315
320
  producer_ = MakeRefCounted<OrcaProducer>();
316
321
  *producer = producer_.get();
@@ -151,9 +151,8 @@ class OutlierDetectionLb : public LoadBalancingPolicy {
151
151
  }
152
152
  return;
153
153
  }
154
- WeakRefCountedPtr<SubchannelWrapper> self = WeakRef();
155
154
  work_serializer_->Run(
156
- [self = std::move(self)]() {
155
+ [self = WeakRefAsSubclass<SubchannelWrapper>()]() {
157
156
  if (self->subchannel_state_ != nullptr) {
158
157
  self->subchannel_state_->RemoveSubchannel(self.get());
159
158
  }
@@ -624,7 +623,7 @@ absl::Status OutlierDetectionLb::UpdateLocked(UpdateArgs args) {
624
623
  }
625
624
  auto old_config = std::move(config_);
626
625
  // Update config.
627
- config_ = std::move(args.config);
626
+ config_ = args.config.TakeAsSubclass<OutlierDetectionLbConfig>();
628
627
  // Update outlier detection timer.
629
628
  if (!config_->CountingEnabled()) {
630
629
  // No need for timer. Cancel the current timer, if any.
@@ -639,7 +638,8 @@ absl::Status OutlierDetectionLb::UpdateLocked(UpdateArgs args) {
639
638
  if (GRPC_TRACE_FLAG_ENABLED(grpc_outlier_detection_lb_trace)) {
640
639
  gpr_log(GPR_INFO, "[outlier_detection_lb %p] starting timer", this);
641
640
  }
642
- ejection_timer_ = MakeOrphanable<EjectionTimer>(Ref(), Timestamp::Now());
641
+ ejection_timer_ = MakeOrphanable<EjectionTimer>(
642
+ RefAsSubclass<OutlierDetectionLb>(), Timestamp::Now());
643
643
  for (const auto& p : endpoint_state_map_) {
644
644
  p.second->RotateBucket(); // Reset call counters.
645
645
  }
@@ -654,14 +654,14 @@ absl::Status OutlierDetectionLb::UpdateLocked(UpdateArgs args) {
654
654
  "[outlier_detection_lb %p] interval changed, replacing timer",
655
655
  this);
656
656
  }
657
- ejection_timer_ =
658
- MakeOrphanable<EjectionTimer>(Ref(), ejection_timer_->StartTime());
657
+ ejection_timer_ = MakeOrphanable<EjectionTimer>(
658
+ RefAsSubclass<OutlierDetectionLb>(), ejection_timer_->StartTime());
659
659
  }
660
660
  // Update subchannel and endpoint maps.
661
661
  if (args.addresses.ok()) {
662
662
  std::set<EndpointAddressSet> current_endpoints;
663
663
  std::set<grpc_resolved_address, ResolvedAddressLessThan> current_addresses;
664
- for (const EndpointAddresses& endpoint : *args.addresses) {
664
+ (*args.addresses)->ForEach([&](const EndpointAddresses& endpoint) {
665
665
  EndpointAddressSet key(endpoint.addresses());
666
666
  current_endpoints.emplace(key);
667
667
  for (const grpc_resolved_address& address : endpoint.addresses()) {
@@ -708,7 +708,7 @@ absl::Status OutlierDetectionLb::UpdateLocked(UpdateArgs args) {
708
708
  }
709
709
  it->second->DisableEjection();
710
710
  }
711
- }
711
+ });
712
712
  // Remove any entries we no longer need in the subchannel map.
713
713
  for (auto it = subchannel_state_map_.begin();
714
714
  it != subchannel_state_map_.end();) {
@@ -753,7 +753,6 @@ absl::Status OutlierDetectionLb::UpdateLocked(UpdateArgs args) {
753
753
  update_args.addresses = std::move(args.addresses);
754
754
  update_args.resolution_note = std::move(args.resolution_note);
755
755
  update_args.config = config_->child_policy();
756
- // Update the policy.
757
756
  update_args.args = std::move(args.args);
758
757
  if (GRPC_TRACE_FLAG_ENABLED(grpc_outlier_detection_lb_trace)) {
759
758
  gpr_log(GPR_INFO,
@@ -784,8 +783,8 @@ OrphanablePtr<LoadBalancingPolicy> OutlierDetectionLb::CreateChildPolicyLocked(
784
783
  LoadBalancingPolicy::Args lb_policy_args;
785
784
  lb_policy_args.work_serializer = work_serializer();
786
785
  lb_policy_args.args = args;
787
- lb_policy_args.channel_control_helper =
788
- std::make_unique<Helper>(Ref(DEBUG_LOCATION, "Helper"));
786
+ lb_policy_args.channel_control_helper = std::make_unique<Helper>(
787
+ RefAsSubclass<OutlierDetectionLb>(DEBUG_LOCATION, "Helper"));
789
788
  OrphanablePtr<LoadBalancingPolicy> lb_policy =
790
789
  MakeOrphanable<ChildPolicyHandler>(std::move(lb_policy_args),
791
790
  &grpc_outlier_detection_lb_trace);
@@ -21,7 +21,6 @@
21
21
  #include <inttypes.h>
22
22
  #include <string.h>
23
23
 
24
- #include <algorithm>
25
24
  #include <memory>
26
25
  #include <set>
27
26
  #include <string>
@@ -114,7 +113,7 @@ class PickFirst : public LoadBalancingPolicy {
114
113
  public:
115
114
  class SubchannelData {
116
115
  public:
117
- SubchannelData(SubchannelList* subchannel_list,
116
+ SubchannelData(SubchannelList* subchannel_list, size_t index,
118
117
  RefCountedPtr<SubchannelInterface> subchannel);
119
118
 
120
119
  SubchannelInterface* subchannel() const { return subchannel_.get(); }
@@ -125,12 +124,6 @@ class PickFirst : public LoadBalancingPolicy {
125
124
  return connectivity_status_;
126
125
  }
127
126
 
128
- // Returns the index into the subchannel list of this object.
129
- size_t Index() const {
130
- return static_cast<size_t>(this -
131
- &subchannel_list_->subchannels_.front());
132
- }
133
-
134
127
  // Resets the connection backoff.
135
128
  void ResetBackoffLocked() {
136
129
  if (subchannel_ != nullptr) subchannel_->ResetBackoff();
@@ -153,10 +146,8 @@ class PickFirst : public LoadBalancingPolicy {
153
146
  class Watcher
154
147
  : public SubchannelInterface::ConnectivityStateWatcherInterface {
155
148
  public:
156
- Watcher(SubchannelData* subchannel_data,
157
- RefCountedPtr<SubchannelList> subchannel_list)
158
- : subchannel_data_(subchannel_data),
159
- subchannel_list_(std::move(subchannel_list)) {}
149
+ Watcher(RefCountedPtr<SubchannelList> subchannel_list, size_t index)
150
+ : subchannel_list_(std::move(subchannel_list)), index_(index) {}
160
151
 
161
152
  ~Watcher() override {
162
153
  subchannel_list_.reset(DEBUG_LOCATION, "Watcher dtor");
@@ -164,8 +155,8 @@ class PickFirst : public LoadBalancingPolicy {
164
155
 
165
156
  void OnConnectivityStateChange(grpc_connectivity_state new_state,
166
157
  absl::Status status) override {
167
- subchannel_data_->OnConnectivityStateChange(new_state,
168
- std::move(status));
158
+ subchannel_list_->subchannels_[index_].OnConnectivityStateChange(
159
+ new_state, std::move(status));
169
160
  }
170
161
 
171
162
  grpc_pollset_set* interested_parties() override {
@@ -173,8 +164,8 @@ class PickFirst : public LoadBalancingPolicy {
173
164
  }
174
165
 
175
166
  private:
176
- SubchannelData* subchannel_data_;
177
167
  RefCountedPtr<SubchannelList> subchannel_list_;
168
+ const size_t index_;
178
169
  };
179
170
 
180
171
  // This method will be invoked once soon after instantiation to report
@@ -193,6 +184,7 @@ class PickFirst : public LoadBalancingPolicy {
193
184
 
194
185
  // Backpointer to owning subchannel list. Not owned.
195
186
  SubchannelList* subchannel_list_;
187
+ const size_t index_;
196
188
  // The subchannel.
197
189
  RefCountedPtr<SubchannelInterface> subchannel_;
198
190
  // Will be non-null when the subchannel's state is being watched.
@@ -205,7 +197,8 @@ class PickFirst : public LoadBalancingPolicy {
205
197
  };
206
198
 
207
199
  SubchannelList(RefCountedPtr<PickFirst> policy,
208
- EndpointAddressesList addresses, const ChannelArgs& args);
200
+ EndpointAddressesIterator* addresses,
201
+ const ChannelArgs& args);
209
202
 
210
203
  ~SubchannelList() override;
211
204
 
@@ -231,7 +224,9 @@ class PickFirst : public LoadBalancingPolicy {
231
224
  private:
232
225
  // Returns true if all subchannels have seen their initial
233
226
  // connectivity state notifications.
234
- bool AllSubchannelsSeenInitialState();
227
+ bool AllSubchannelsSeenInitialState() const {
228
+ return num_subchannels_seen_initial_notification_ == size();
229
+ }
235
230
 
236
231
  // Looks through subchannels_ starting from attempting_index_ to
237
232
  // find the first one not currently in TRANSIENT_FAILURE, then
@@ -262,6 +257,8 @@ class PickFirst : public LoadBalancingPolicy {
262
257
  // TODO(roth): Remove this when we remove the Happy Eyeballs experiment.
263
258
  bool in_transient_failure_ = false;
264
259
 
260
+ size_t num_subchannels_seen_initial_notification_ = 0;
261
+
265
262
  // The index into subchannels_ to which we are currently attempting
266
263
  // to connect during the initial Happy Eyeballs pass. Once the
267
264
  // initial pass is over, this will be equal to size().
@@ -413,9 +410,9 @@ void PickFirst::ResetBackoffLocked() {
413
410
 
414
411
  void PickFirst::AttemptToConnectUsingLatestUpdateArgsLocked() {
415
412
  // Create a subchannel list from latest_update_args_.
416
- EndpointAddressesList addresses;
413
+ EndpointAddressesIterator* addresses = nullptr;
417
414
  if (latest_update_args_.addresses.ok()) {
418
- addresses = *latest_update_args_.addresses;
415
+ addresses = latest_update_args_.addresses->get();
419
416
  }
420
417
  // Replace latest_pending_subchannel_list_.
421
418
  if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_pick_first_trace) &&
@@ -425,7 +422,7 @@ void PickFirst::AttemptToConnectUsingLatestUpdateArgsLocked() {
425
422
  latest_pending_subchannel_list_.get());
426
423
  }
427
424
  latest_pending_subchannel_list_ = MakeOrphanable<SubchannelList>(
428
- Ref(), std::move(addresses), latest_update_args_.args);
425
+ RefAsSubclass<PickFirst>(), addresses, latest_update_args_.args);
429
426
  // Empty update or no valid subchannels. Put the channel in
430
427
  // TRANSIENT_FAILURE and request re-resolution.
431
428
  if (latest_pending_subchannel_list_->size() == 0) {
@@ -483,9 +480,7 @@ class AddressFamilyIterator {
483
480
  absl::Status PickFirst::UpdateLocked(UpdateArgs args) {
484
481
  if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_pick_first_trace)) {
485
482
  if (args.addresses.ok()) {
486
- gpr_log(GPR_INFO,
487
- "Pick First %p received update with %" PRIuPTR " addresses", this,
488
- args.addresses->size());
483
+ gpr_log(GPR_INFO, "Pick First %p received update", this);
489
484
  } else {
490
485
  gpr_log(GPR_INFO, "Pick First %p received update with address error: %s",
491
486
  this, args.addresses.status().ToString().c_str());
@@ -495,51 +490,59 @@ absl::Status PickFirst::UpdateLocked(UpdateArgs args) {
495
490
  absl::Status status;
496
491
  if (!args.addresses.ok()) {
497
492
  status = args.addresses.status();
498
- } else if (args.addresses->empty()) {
499
- status = absl::UnavailableError("address list must not be empty");
500
493
  } else {
501
- // Shuffle the list if needed.
502
- auto config = static_cast<PickFirstConfig*>(args.config.get());
503
- if (config->shuffle_addresses()) {
504
- absl::c_shuffle(*args.addresses, bit_gen_);
505
- }
506
- // Flatten the list so that we have one address per endpoint.
507
- // While we're iterating, also determine the desired address family
508
- // order and the index of the first element of each family, for use in
509
- // the interleaving below.
510
- std::set<absl::string_view> address_families;
511
- std::vector<AddressFamilyIterator> address_family_order;
512
494
  EndpointAddressesList endpoints;
513
- for (const auto& endpoint : *args.addresses) {
514
- for (const auto& address : endpoint.addresses()) {
515
- endpoints.emplace_back(address, endpoint.args());
516
- if (IsPickFirstHappyEyeballsEnabled()) {
517
- absl::string_view scheme = GetAddressFamily(address);
518
- bool inserted = address_families.insert(scheme).second;
519
- if (inserted) {
520
- address_family_order.emplace_back(scheme, endpoints.size() - 1);
495
+ (*args.addresses)->ForEach([&](const EndpointAddresses& endpoint) {
496
+ endpoints.push_back(endpoint);
497
+ });
498
+ if (endpoints.empty()) {
499
+ status = absl::UnavailableError("address list must not be empty");
500
+ } else {
501
+ // Shuffle the list if needed.
502
+ auto config = static_cast<PickFirstConfig*>(args.config.get());
503
+ if (config->shuffle_addresses()) {
504
+ absl::c_shuffle(endpoints, bit_gen_);
505
+ }
506
+ // Flatten the list so that we have one address per endpoint.
507
+ // While we're iterating, also determine the desired address family
508
+ // order and the index of the first element of each family, for use in
509
+ // the interleaving below.
510
+ std::set<absl::string_view> address_families;
511
+ std::vector<AddressFamilyIterator> address_family_order;
512
+ EndpointAddressesList flattened_endpoints;
513
+ for (const auto& endpoint : endpoints) {
514
+ for (const auto& address : endpoint.addresses()) {
515
+ flattened_endpoints.emplace_back(address, endpoint.args());
516
+ if (IsPickFirstHappyEyeballsEnabled()) {
517
+ absl::string_view scheme = GetAddressFamily(address);
518
+ bool inserted = address_families.insert(scheme).second;
519
+ if (inserted) {
520
+ address_family_order.emplace_back(scheme,
521
+ flattened_endpoints.size() - 1);
522
+ }
521
523
  }
522
524
  }
523
525
  }
524
- }
525
- // Interleave addresses as per RFC-8305 section 4.
526
- if (IsPickFirstHappyEyeballsEnabled()) {
527
- EndpointAddressesList interleaved_endpoints;
528
- interleaved_endpoints.reserve(endpoints.size());
529
- std::vector<bool> endpoints_moved(endpoints.size());
530
- size_t scheme_index = 0;
531
- for (size_t i = 0; i < endpoints.size(); ++i) {
532
- EndpointAddresses* endpoint;
533
- do {
534
- auto& iterator = address_family_order[scheme_index++ %
535
- address_family_order.size()];
536
- endpoint = iterator.Next(endpoints, &endpoints_moved);
537
- } while (endpoint == nullptr);
538
- interleaved_endpoints.emplace_back(std::move(*endpoint));
526
+ endpoints = std::move(flattened_endpoints);
527
+ // Interleave addresses as per RFC-8305 section 4.
528
+ if (IsPickFirstHappyEyeballsEnabled()) {
529
+ EndpointAddressesList interleaved_endpoints;
530
+ interleaved_endpoints.reserve(endpoints.size());
531
+ std::vector<bool> endpoints_moved(endpoints.size());
532
+ size_t scheme_index = 0;
533
+ for (size_t i = 0; i < endpoints.size(); ++i) {
534
+ EndpointAddresses* endpoint;
535
+ do {
536
+ auto& iterator = address_family_order[scheme_index++ %
537
+ address_family_order.size()];
538
+ endpoint = iterator.Next(endpoints, &endpoints_moved);
539
+ } while (endpoint == nullptr);
540
+ interleaved_endpoints.emplace_back(std::move(*endpoint));
541
+ }
542
+ endpoints = std::move(interleaved_endpoints);
539
543
  }
540
- args.addresses = std::move(interleaved_endpoints);
541
- } else {
542
- args.addresses = std::move(endpoints);
544
+ args.addresses =
545
+ std::make_shared<EndpointAddressesListIterator>(std::move(endpoints));
543
546
  }
544
547
  }
545
548
  // If the update contains a resolver error and we have a previous update
@@ -617,18 +620,20 @@ void PickFirst::HealthWatcher::OnConnectivityStateChange(
617
620
  //
618
621
 
619
622
  PickFirst::SubchannelList::SubchannelData::SubchannelData(
620
- SubchannelList* subchannel_list,
623
+ SubchannelList* subchannel_list, size_t index,
621
624
  RefCountedPtr<SubchannelInterface> subchannel)
622
- : subchannel_list_(subchannel_list), subchannel_(std::move(subchannel)) {
625
+ : subchannel_list_(subchannel_list),
626
+ index_(index),
627
+ subchannel_(std::move(subchannel)) {
623
628
  if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_pick_first_trace)) {
624
629
  gpr_log(GPR_INFO,
625
630
  "[PF %p] subchannel list %p index %" PRIuPTR
626
631
  " (subchannel %p): starting watch",
627
- subchannel_list_->policy_.get(), subchannel_list_,
628
- subchannel_list_->size(), subchannel_.get());
632
+ subchannel_list_->policy_.get(), subchannel_list_, index_,
633
+ subchannel_.get());
629
634
  }
630
635
  auto watcher = std::make_unique<Watcher>(
631
- this, subchannel_list_->Ref(DEBUG_LOCATION, "Watcher"));
636
+ subchannel_list_->Ref(DEBUG_LOCATION, "Watcher"), index_);
632
637
  pending_watcher_ = watcher.get();
633
638
  subchannel_->WatchConnectivityState(std::move(watcher));
634
639
  }
@@ -639,7 +644,7 @@ void PickFirst::SubchannelList::SubchannelData::ShutdownLocked() {
639
644
  gpr_log(GPR_INFO,
640
645
  "[PF %p] subchannel list %p index %" PRIuPTR " of %" PRIuPTR
641
646
  " (subchannel %p): cancelling watch and unreffing subchannel",
642
- subchannel_list_->policy_.get(), subchannel_list_, Index(),
647
+ subchannel_list_->policy_.get(), subchannel_list_, index_,
643
648
  subchannel_list_->size(), subchannel_.get());
644
649
  }
645
650
  subchannel_->CancelConnectivityStateWatch(pending_watcher_);
@@ -659,7 +664,7 @@ void PickFirst::SubchannelList::SubchannelData::OnConnectivityStateChange(
659
664
  "status=%s, shutting_down=%d, pending_watcher=%p, "
660
665
  "seen_transient_failure=%d, p->selected_=%p, "
661
666
  "p->subchannel_list_=%p, p->latest_pending_subchannel_list_=%p",
662
- p, subchannel_list_, Index(), subchannel_list_->size(),
667
+ p, subchannel_list_, index_, subchannel_list_->size(),
663
668
  subchannel_.get(),
664
669
  (connectivity_state_.has_value()
665
670
  ? ConnectivityStateName(*connectivity_state_)
@@ -753,6 +758,11 @@ void PickFirst::SubchannelList::SubchannelData::OnConnectivityStateChange(
753
758
  seen_transient_failure_ = true;
754
759
  subchannel_list_->last_failure_ = connectivity_status_;
755
760
  }
761
+ // If this is the initial connectivity state update for this subchannel,
762
+ // increment the counter in the subchannel list.
763
+ if (!old_state.has_value()) {
764
+ ++subchannel_list_->num_subchannels_seen_initial_notification_;
765
+ }
756
766
  // If we haven't yet seen the initial connectivity state notification
757
767
  // for all subchannels, do nothing.
758
768
  if (!subchannel_list_->AllSubchannelsSeenInitialState()) return;
@@ -771,7 +781,7 @@ void PickFirst::SubchannelList::SubchannelData::OnConnectivityStateChange(
771
781
  if (!IsPickFirstHappyEyeballsEnabled()) {
772
782
  // Ignore any other updates for subchannels we're not currently trying to
773
783
  // connect to.
774
- if (Index() != subchannel_list_->attempting_index_) return;
784
+ if (index_ != subchannel_list_->attempting_index_) return;
775
785
  // React to the connectivity state.
776
786
  ReactToConnectivityStateLocked();
777
787
  return;
@@ -784,7 +794,7 @@ void PickFirst::SubchannelList::SubchannelData::OnConnectivityStateChange(
784
794
  if (!prev_seen_transient_failure && seen_transient_failure_) {
785
795
  // If a connection attempt fails before the timer fires, then
786
796
  // cancel the timer and start connecting on the next subchannel.
787
- if (Index() == subchannel_list_->attempting_index_) {
797
+ if (index_ == subchannel_list_->attempting_index_) {
788
798
  if (subchannel_list_->timer_handle_.has_value()) {
789
799
  p->channel_control_helper()->GetEventEngine()->Cancel(
790
800
  *subchannel_list_->timer_handle_);
@@ -858,7 +868,7 @@ void PickFirst::SubchannelList::SubchannelData::
858
868
  // We skip subchannels in state TRANSIENT_FAILURE to avoid a
859
869
  // large recursion that could overflow the stack.
860
870
  SubchannelData* found_subchannel = nullptr;
861
- for (size_t next_index = Index() + 1;
871
+ for (size_t next_index = index_ + 1;
862
872
  next_index < subchannel_list_->size(); ++next_index) {
863
873
  SubchannelData* sc = &subchannel_list_->subchannels_[next_index];
864
874
  GPR_ASSERT(sc->connectivity_state_.has_value());
@@ -946,14 +956,14 @@ void PickFirst::SubchannelList::SubchannelData::RequestConnectionWithTimer() {
946
956
  GPR_ASSERT(connectivity_state_ == GRPC_CHANNEL_CONNECTING);
947
957
  }
948
958
  // If this is not the last subchannel in the list, start the timer.
949
- if (Index() != subchannel_list_->size() - 1) {
959
+ if (index_ != subchannel_list_->size() - 1) {
950
960
  PickFirst* p = subchannel_list_->policy_.get();
951
961
  if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_pick_first_trace)) {
952
962
  gpr_log(GPR_INFO,
953
963
  "Pick First %p subchannel list %p: starting Connection "
954
964
  "Attempt Delay timer for %" PRId64 "ms for index %" PRIuPTR,
955
965
  p, subchannel_list_, p->connection_attempt_delay_.millis(),
956
- Index());
966
+ index_);
957
967
  }
958
968
  subchannel_list_->timer_handle_ =
959
969
  p->channel_control_helper()->GetEventEngine()->RunAfter(
@@ -1029,7 +1039,7 @@ void PickFirst::SubchannelList::SubchannelData::ProcessUnselectedReadyLocked() {
1029
1039
  gpr_log(GPR_INFO, "[PF %p] starting health watch", p);
1030
1040
  }
1031
1041
  auto watcher = std::make_unique<HealthWatcher>(
1032
- p->Ref(DEBUG_LOCATION, "HealthWatcher"));
1042
+ p->RefAsSubclass<PickFirst>(DEBUG_LOCATION, "HealthWatcher"));
1033
1043
  p->health_watcher_ = watcher.get();
1034
1044
  auto health_data_watcher = MakeHealthCheckWatcher(
1035
1045
  p->work_serializer(), subchannel_list_->args_, std::move(watcher));
@@ -1041,7 +1051,7 @@ void PickFirst::SubchannelList::SubchannelData::ProcessUnselectedReadyLocked() {
1041
1051
  }
1042
1052
  // Unref all other subchannels in the list.
1043
1053
  for (size_t i = 0; i < subchannel_list_->size(); ++i) {
1044
- if (i != Index()) {
1054
+ if (i != index_) {
1045
1055
  subchannel_list_->subchannels_[i].ShutdownLocked();
1046
1056
  }
1047
1057
  }
@@ -1052,7 +1062,7 @@ void PickFirst::SubchannelList::SubchannelData::ProcessUnselectedReadyLocked() {
1052
1062
  //
1053
1063
 
1054
1064
  PickFirst::SubchannelList::SubchannelList(RefCountedPtr<PickFirst> policy,
1055
- EndpointAddressesList addresses,
1065
+ EndpointAddressesIterator* addresses,
1056
1066
  const ChannelArgs& args)
1057
1067
  : InternallyRefCounted<SubchannelList>(
1058
1068
  GRPC_TRACE_FLAG_ENABLED(grpc_lb_pick_first_trace) ? "SubchannelList"
@@ -1062,14 +1072,12 @@ PickFirst::SubchannelList::SubchannelList(RefCountedPtr<PickFirst> policy,
1062
1072
  .Remove(
1063
1073
  GRPC_ARG_INTERNAL_PICK_FIRST_OMIT_STATUS_MESSAGE_PREFIX)) {
1064
1074
  if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_pick_first_trace)) {
1065
- gpr_log(GPR_INFO,
1066
- "[PF %p] Creating subchannel list %p for %" PRIuPTR
1067
- " subchannels - channel args: %s",
1068
- policy_.get(), this, addresses.size(), args_.ToString().c_str());
1075
+ gpr_log(GPR_INFO, "[PF %p] Creating subchannel list %p - channel args: %s",
1076
+ policy_.get(), this, args_.ToString().c_str());
1069
1077
  }
1070
- subchannels_.reserve(addresses.size());
1078
+ if (addresses == nullptr) return;
1071
1079
  // Create a subchannel for each address.
1072
- for (const EndpointAddresses& address : addresses) {
1080
+ addresses->ForEach([&](const EndpointAddresses& address) {
1073
1081
  GPR_ASSERT(address.addresses().size() == 1);
1074
1082
  RefCountedPtr<SubchannelInterface> subchannel =
1075
1083
  policy_->channel_control_helper()->CreateSubchannel(
@@ -1081,7 +1089,7 @@ PickFirst::SubchannelList::SubchannelList(RefCountedPtr<PickFirst> policy,
1081
1089
  "[PF %p] could not create subchannel for address %s, ignoring",
1082
1090
  policy_.get(), address.ToString().c_str());
1083
1091
  }
1084
- continue;
1092
+ return;
1085
1093
  }
1086
1094
  if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_pick_first_trace)) {
1087
1095
  gpr_log(GPR_INFO,
@@ -1090,8 +1098,8 @@ PickFirst::SubchannelList::SubchannelList(RefCountedPtr<PickFirst> policy,
1090
1098
  policy_.get(), this, subchannels_.size(), subchannel.get(),
1091
1099
  address.ToString().c_str());
1092
1100
  }
1093
- subchannels_.emplace_back(this, std::move(subchannel));
1094
- }
1101
+ subchannels_.emplace_back(this, subchannels_.size(), std::move(subchannel));
1102
+ });
1095
1103
  }
1096
1104
 
1097
1105
  PickFirst::SubchannelList::~SubchannelList() {
@@ -1123,13 +1131,6 @@ void PickFirst::SubchannelList::ResetBackoffLocked() {
1123
1131
  }
1124
1132
  }
1125
1133
 
1126
- bool PickFirst::SubchannelList::AllSubchannelsSeenInitialState() {
1127
- for (auto& sd : subchannels_) {
1128
- if (!sd.connectivity_state().has_value()) return false;
1129
- }
1130
- return true;
1131
- }
1132
-
1133
1134
  void PickFirst::SubchannelList::StartConnectingNextSubchannel() {
1134
1135
  // Find the next subchannel not in state TRANSIENT_FAILURE.
1135
1136
  // We skip subchannels in state TRANSIENT_FAILURE to avoid a
@@ -335,7 +335,7 @@ absl::Status PriorityLb::UpdateLocked(UpdateArgs args) {
335
335
  gpr_log(GPR_INFO, "[priority_lb %p] received update", this);
336
336
  }
337
337
  // Update config.
338
- config_ = std::move(args.config);
338
+ config_ = args.config.TakeAsSubclass<PriorityLbConfig>();
339
339
  // Update args.
340
340
  args_ = std::move(args.args);
341
341
  // Update addresses.
@@ -411,7 +411,8 @@ void PriorityLb::ChoosePriorityLocked() {
411
411
  // Create child if needed.
412
412
  if (child == nullptr) {
413
413
  child = MakeOrphanable<ChildPriority>(
414
- Ref(DEBUG_LOCATION, "ChildPriority"), child_name);
414
+ RefAsSubclass<PriorityLb>(DEBUG_LOCATION, "ChildPriority"),
415
+ child_name);
415
416
  auto child_config = config_->children().find(child_name);
416
417
  GPR_DEBUG_ASSERT(child_config != config_->children().end());
417
418
  // TODO(roth): If the child reports a non-OK status with the
@@ -684,7 +685,8 @@ absl::Status PriorityLb::ChildPriority::UpdateLocked(
684
685
  if (priority_policy_->addresses_.ok()) {
685
686
  auto it = priority_policy_->addresses_->find(name_);
686
687
  if (it == priority_policy_->addresses_->end()) {
687
- update_args.addresses.emplace();
688
+ update_args.addresses = std::make_shared<EndpointAddressesListIterator>(
689
+ EndpointAddressesList());
688
690
  } else {
689
691
  update_args.addresses = it->second;
690
692
  }
@@ -346,7 +346,7 @@ RingHash::PickResult RingHash::Picker::Pick(PickArgs args) {
346
346
  return endpoint_info.picker->Pick(args);
347
347
  case GRPC_CHANNEL_IDLE:
348
348
  new EndpointConnectionAttempter(
349
- ring_hash_->Ref(DEBUG_LOCATION, "EndpointConnectionAttempter"),
349
+ ring_hash_.Ref(DEBUG_LOCATION, "EndpointConnectionAttempter"),
350
350
  endpoint_info.endpoint);
351
351
  ABSL_FALLTHROUGH_INTENDED;
352
352
  case GRPC_CHANNEL_CONNECTING:
@@ -554,7 +554,8 @@ void RingHash::RingHashEndpoint::UpdateChildPolicyLocked() {
554
554
  GPR_ASSERT(config.ok());
555
555
  // Update child policy.
556
556
  LoadBalancingPolicy::UpdateArgs update_args;
557
- update_args.addresses.emplace().emplace_back(ring_hash_->endpoints_[index_]);
557
+ update_args.addresses =
558
+ std::make_shared<SingleEndpointIterator>(ring_hash_->endpoints_[index_]);
558
559
  update_args.args = ring_hash_->args_;
559
560
  update_args.config = std::move(*config);
560
561
  // TODO(roth): If the child reports a non-OK status with the update,
@@ -622,18 +623,14 @@ absl::Status RingHash::UpdateLocked(UpdateArgs args) {
622
623
  // Check address list.
623
624
  if (args.addresses.ok()) {
624
625
  if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_ring_hash_trace)) {
625
- gpr_log(GPR_INFO, "[RH %p] received update with %" PRIuPTR " addresses",
626
- this, args.addresses->size());
626
+ gpr_log(GPR_INFO, "[RH %p] received update", this);
627
627
  }
628
628
  // De-dup endpoints, taking weight into account.
629
629
  endpoints_.clear();
630
- endpoints_.reserve(args.addresses->size());
631
630
  std::map<EndpointAddressSet, size_t> endpoint_indices;
632
- size_t num_skipped = 0;
633
- for (size_t i = 0; i < args.addresses->size(); ++i) {
634
- EndpointAddresses& endpoint = (*args.addresses)[i];
631
+ (*args.addresses)->ForEach([&](const EndpointAddresses& endpoint) {
635
632
  const EndpointAddressSet key(endpoint.addresses());
636
- auto p = endpoint_indices.emplace(key, i - num_skipped);
633
+ auto p = endpoint_indices.emplace(key, endpoints_.size());
637
634
  if (!p.second) {
638
635
  // Duplicate endpoint. Combine weights and skip the dup.
639
636
  EndpointAddresses& prev_endpoint = endpoints_[p.first->second];
@@ -651,11 +648,10 @@ absl::Status RingHash::UpdateLocked(UpdateArgs args) {
651
648
  prev_endpoint.addresses(),
652
649
  prev_endpoint.args().Set(GRPC_ARG_ADDRESS_WEIGHT,
653
650
  weight_arg + prev_weight_arg));
654
- ++num_skipped;
655
651
  } else {
656
- endpoints_.push_back(std::move(endpoint));
652
+ endpoints_.push_back(endpoint);
657
653
  }
658
- }
654
+ });
659
655
  } else {
660
656
  if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_ring_hash_trace)) {
661
657
  gpr_log(GPR_INFO, "[RH %p] received update with addresses error: %s",
@@ -681,8 +677,8 @@ absl::Status RingHash::UpdateLocked(UpdateArgs args) {
681
677
  it->second->UpdateLocked(i);
682
678
  endpoint_map.emplace(address_set, std::move(it->second));
683
679
  } else {
684
- endpoint_map.emplace(address_set,
685
- MakeOrphanable<RingHashEndpoint>(Ref(), i));
680
+ endpoint_map.emplace(address_set, MakeOrphanable<RingHashEndpoint>(
681
+ RefAsSubclass<RingHash>(), i));
686
682
  }
687
683
  }
688
684
  endpoint_map_ = std::move(endpoint_map);
@@ -783,7 +779,8 @@ void RingHash::UpdateAggregatedConnectivityStateLocked(
783
779
  // Note that we use our own picker regardless of connectivity state.
784
780
  channel_control_helper()->UpdateState(
785
781
  state, status,
786
- MakeRefCounted<Picker>(Ref(DEBUG_LOCATION, "RingHashPicker")));
782
+ MakeRefCounted<Picker>(
783
+ RefAsSubclass<RingHash>(DEBUG_LOCATION, "RingHashPicker")));
787
784
  // While the ring_hash policy is reporting TRANSIENT_FAILURE, it will
788
785
  // not be getting any pick requests from the priority policy.
789
786
  // However, because the ring_hash policy does not attempt to