grpc 1.18.0 → 1.22.0

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

Potentially problematic release.


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

Files changed (428) hide show
  1. checksums.yaml +4 -4
  2. data/Makefile +4731 -7404
  3. data/etc/roots.pem +146 -0
  4. data/include/grpc/grpc.h +11 -6
  5. data/include/grpc/grpc_security.h +297 -4
  6. data/include/grpc/grpc_security_constants.h +1 -1
  7. data/include/grpc/impl/codegen/byte_buffer.h +13 -0
  8. data/include/grpc/impl/codegen/gpr_types.h +1 -1
  9. data/include/grpc/impl/codegen/grpc_types.h +30 -7
  10. data/include/grpc/impl/codegen/port_platform.h +88 -7
  11. data/include/grpc/impl/codegen/slice.h +2 -22
  12. data/include/grpc/impl/codegen/status.h +2 -1
  13. data/include/grpc/impl/codegen/sync_posix.h +18 -0
  14. data/include/grpc/slice.h +3 -3
  15. data/src/core/ext/filters/client_channel/backup_poller.cc +21 -16
  16. data/src/core/ext/filters/client_channel/backup_poller.h +8 -2
  17. data/src/core/ext/filters/client_channel/channel_connectivity.cc +3 -1
  18. data/src/core/ext/filters/client_channel/client_channel.cc +2435 -1557
  19. data/src/core/ext/filters/client_channel/client_channel.h +2 -10
  20. data/src/core/ext/filters/client_channel/client_channel_channelz.cc +6 -89
  21. data/src/core/ext/filters/client_channel/client_channel_channelz.h +8 -33
  22. data/src/core/ext/filters/client_channel/client_channel_factory.cc +22 -34
  23. data/src/core/ext/filters/client_channel/client_channel_factory.h +19 -38
  24. data/src/core/ext/filters/client_channel/client_channel_plugin.cc +9 -11
  25. data/src/core/ext/filters/client_channel/global_subchannel_pool.cc +179 -0
  26. data/src/core/ext/filters/client_channel/global_subchannel_pool.h +68 -0
  27. data/src/core/ext/filters/client_channel/health/health_check_client.cc +59 -55
  28. data/src/core/ext/filters/client_channel/health/health_check_client.h +20 -9
  29. data/src/core/ext/filters/client_channel/http_connect_handshaker.cc +146 -157
  30. data/src/core/ext/filters/client_channel/http_connect_handshaker.h +1 -1
  31. data/src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.cc +29 -32
  32. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc +844 -859
  33. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h +3 -1
  34. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.cc +2 -6
  35. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.cc +6 -2
  36. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h +14 -12
  37. data/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc +16 -12
  38. data/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h +3 -3
  39. data/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc +185 -312
  40. data/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc +143 -375
  41. data/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h +192 -245
  42. data/src/core/ext/filters/client_channel/lb_policy/xds/xds.cc +1554 -955
  43. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_channel_secure.cc +0 -43
  44. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_load_balancer_api.cc +14 -10
  45. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_load_balancer_api.h +2 -2
  46. data/src/core/ext/filters/client_channel/lb_policy.cc +115 -22
  47. data/src/core/ext/filters/client_channel/lb_policy.h +260 -129
  48. data/src/core/ext/filters/client_channel/lb_policy_factory.h +5 -2
  49. data/src/core/ext/filters/client_channel/lb_policy_registry.cc +107 -4
  50. data/src/core/ext/filters/client_channel/lb_policy_registry.h +10 -3
  51. data/src/core/ext/filters/client_channel/local_subchannel_pool.cc +96 -0
  52. data/src/core/ext/filters/client_channel/local_subchannel_pool.h +56 -0
  53. data/src/core/ext/filters/client_channel/parse_address.cc +24 -5
  54. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc +121 -122
  55. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc +84 -2
  56. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h +3 -0
  57. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_libuv.cc +179 -0
  58. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc +24 -10
  59. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc +111 -47
  60. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h +7 -13
  61. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc +2 -2
  62. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_libuv.cc +39 -0
  63. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc +0 -6
  64. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc +2 -64
  65. data/src/core/ext/filters/client_channel/resolver/dns/dns_resolver_selection.cc +28 -0
  66. data/src/core/{lib/iomgr/network_status_tracker.cc → ext/filters/client_channel/resolver/dns/dns_resolver_selection.h} +8 -15
  67. data/src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc +36 -82
  68. data/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc +111 -72
  69. data/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h +13 -8
  70. data/src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc +28 -63
  71. data/src/core/ext/filters/client_channel/resolver.cc +54 -1
  72. data/src/core/ext/filters/client_channel/resolver.h +52 -23
  73. data/src/core/ext/filters/client_channel/resolver_factory.h +3 -1
  74. data/src/core/ext/filters/client_channel/resolver_registry.cc +5 -2
  75. data/src/core/ext/filters/client_channel/resolver_registry.h +5 -4
  76. data/src/core/ext/filters/client_channel/resolver_result_parsing.cc +368 -241
  77. data/src/core/ext/filters/client_channel/resolver_result_parsing.h +58 -76
  78. data/src/core/ext/filters/client_channel/resolving_lb_policy.cc +543 -0
  79. data/src/core/ext/filters/client_channel/resolving_lb_policy.h +139 -0
  80. data/src/core/ext/filters/client_channel/server_address.cc +4 -54
  81. data/src/core/ext/filters/client_channel/server_address.h +1 -13
  82. data/src/core/ext/filters/client_channel/service_config.cc +329 -0
  83. data/src/core/ext/filters/client_channel/service_config.h +205 -0
  84. data/src/core/ext/filters/client_channel/subchannel.cc +803 -838
  85. data/src/core/ext/filters/client_channel/subchannel.h +295 -128
  86. data/src/core/ext/filters/client_channel/subchannel_interface.h +113 -0
  87. data/src/core/ext/filters/client_channel/subchannel_pool_interface.cc +97 -0
  88. data/src/core/ext/filters/client_channel/subchannel_pool_interface.h +94 -0
  89. data/src/core/ext/filters/deadline/deadline_filter.cc +3 -4
  90. data/src/core/ext/filters/deadline/deadline_filter.h +3 -2
  91. data/src/core/ext/filters/http/client/http_client_filter.cc +7 -5
  92. data/src/core/ext/filters/http/client/http_client_filter.h +1 -1
  93. data/src/core/ext/filters/http/client_authority_filter.cc +6 -3
  94. data/src/core/ext/filters/http/message_compress/message_compress_filter.cc +4 -3
  95. data/src/core/ext/filters/http/server/http_server_filter.cc +18 -12
  96. data/src/core/ext/filters/max_age/max_age_filter.cc +5 -2
  97. data/src/core/ext/filters/message_size/message_size_filter.cc +119 -77
  98. data/src/core/ext/filters/message_size/message_size_filter.h +33 -0
  99. data/src/core/ext/transport/chttp2/alpn/alpn.h +1 -1
  100. data/src/core/ext/transport/chttp2/client/chttp2_connector.cc +13 -12
  101. data/src/core/ext/transport/chttp2/client/insecure/channel_create.cc +45 -47
  102. data/src/core/ext/transport/chttp2/client/secure/secure_channel_create.cc +134 -143
  103. data/src/core/ext/transport/chttp2/server/chttp2_server.cc +68 -21
  104. data/src/core/ext/transport/chttp2/transport/bin_decoder.cc +4 -4
  105. data/src/core/ext/transport/chttp2/transport/bin_decoder.h +4 -4
  106. data/src/core/ext/transport/chttp2/transport/bin_encoder.cc +7 -6
  107. data/src/core/ext/transport/chttp2/transport/bin_encoder.h +4 -3
  108. data/src/core/ext/transport/chttp2/transport/chttp2_plugin.cc +9 -7
  109. data/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +156 -94
  110. data/src/core/ext/transport/chttp2/transport/flow_control.cc +2 -2
  111. data/src/core/ext/transport/chttp2/transport/flow_control.h +1 -1
  112. data/src/core/ext/transport/chttp2/transport/frame_data.cc +33 -37
  113. data/src/core/ext/transport/chttp2/transport/frame_data.h +1 -1
  114. data/src/core/ext/transport/chttp2/transport/frame_goaway.cc +6 -5
  115. data/src/core/ext/transport/chttp2/transport/frame_goaway.h +3 -2
  116. data/src/core/ext/transport/chttp2/transport/frame_ping.cc +5 -4
  117. data/src/core/ext/transport/chttp2/transport/frame_ping.h +1 -1
  118. data/src/core/ext/transport/chttp2/transport/frame_rst_stream.cc +8 -6
  119. data/src/core/ext/transport/chttp2/transport/frame_rst_stream.h +2 -1
  120. data/src/core/ext/transport/chttp2/transport/frame_settings.cc +6 -4
  121. data/src/core/ext/transport/chttp2/transport/frame_settings.h +2 -1
  122. data/src/core/ext/transport/chttp2/transport/frame_window_update.cc +7 -6
  123. data/src/core/ext/transport/chttp2/transport/frame_window_update.h +1 -1
  124. data/src/core/ext/transport/chttp2/transport/hpack_encoder.cc +74 -55
  125. data/src/core/ext/transport/chttp2/transport/hpack_parser.cc +33 -11
  126. data/src/core/ext/transport/chttp2/transport/hpack_parser.h +3 -2
  127. data/src/core/ext/transport/chttp2/transport/hpack_table.cc +7 -14
  128. data/src/core/ext/transport/chttp2/transport/hpack_table.h +10 -1
  129. data/src/core/ext/transport/chttp2/transport/incoming_metadata.cc +9 -5
  130. data/src/core/ext/transport/chttp2/transport/incoming_metadata.h +9 -3
  131. data/src/core/ext/transport/chttp2/transport/internal.h +43 -30
  132. data/src/core/ext/transport/chttp2/transport/parsing.cc +52 -70
  133. data/src/core/ext/transport/chttp2/transport/stream_lists.cc +3 -3
  134. data/src/core/ext/transport/chttp2/transport/writing.cc +70 -33
  135. data/src/core/ext/transport/inproc/inproc_transport.cc +26 -18
  136. data/src/core/lib/channel/channel_args.cc +2 -101
  137. data/src/core/lib/channel/channel_args.h +3 -37
  138. data/src/core/lib/channel/channel_stack.h +10 -6
  139. data/src/core/lib/channel/channel_trace.cc +4 -4
  140. data/src/core/lib/channel/channel_trace.h +4 -4
  141. data/src/core/lib/channel/channelz.cc +168 -38
  142. data/src/core/lib/channel/channelz.h +40 -44
  143. data/src/core/lib/channel/channelz_registry.cc +75 -107
  144. data/src/core/lib/channel/channelz_registry.h +10 -28
  145. data/src/core/lib/channel/connected_channel.cc +2 -2
  146. data/src/core/lib/channel/context.h +2 -2
  147. data/src/core/lib/channel/handshaker.cc +151 -218
  148. data/src/core/lib/channel/handshaker.h +110 -101
  149. data/src/core/lib/channel/handshaker_factory.h +11 -19
  150. data/src/core/lib/channel/handshaker_registry.cc +67 -51
  151. data/src/core/lib/channel/handshaker_registry.h +21 -16
  152. data/src/core/lib/compression/algorithm_metadata.h +3 -3
  153. data/src/core/lib/compression/compression.cc +14 -9
  154. data/src/core/lib/compression/compression_args.cc +127 -0
  155. data/src/core/lib/compression/compression_args.h +55 -0
  156. data/src/core/lib/compression/compression_internal.cc +16 -12
  157. data/src/core/lib/compression/compression_internal.h +1 -1
  158. data/src/core/lib/compression/stream_compression.cc +3 -2
  159. data/src/core/lib/compression/stream_compression.h +2 -2
  160. data/src/core/lib/compression/stream_compression_gzip.cc +9 -9
  161. data/src/core/lib/debug/trace.cc +13 -7
  162. data/src/core/lib/debug/trace.h +14 -1
  163. data/src/core/lib/gpr/arena.h +13 -9
  164. data/src/core/lib/gpr/cpu_posix.cc +5 -3
  165. data/src/core/lib/gpr/env.h +3 -6
  166. data/src/core/lib/gpr/env_linux.cc +6 -1
  167. data/src/core/lib/gpr/env_posix.cc +5 -0
  168. data/src/core/lib/gpr/env_windows.cc +7 -5
  169. data/src/core/lib/gpr/log.cc +9 -13
  170. data/src/core/lib/gpr/log_posix.cc +2 -1
  171. data/src/core/lib/gpr/string.cc +20 -7
  172. data/src/core/lib/gpr/string.h +10 -3
  173. data/src/core/lib/gpr/sync_posix.cc +65 -4
  174. data/src/core/lib/gpr/time.cc +8 -0
  175. data/src/core/lib/gpr/time_posix.cc +21 -2
  176. data/src/core/lib/gprpp/arena.cc +103 -0
  177. data/src/core/lib/gprpp/arena.h +121 -0
  178. data/src/core/lib/gprpp/atomic.h +75 -5
  179. data/src/core/lib/gprpp/fork.cc +13 -32
  180. data/src/core/lib/gprpp/fork.h +5 -1
  181. data/src/core/lib/gprpp/global_config.h +96 -0
  182. data/src/core/lib/gprpp/global_config_custom.h +29 -0
  183. data/src/core/lib/gprpp/global_config_env.cc +135 -0
  184. data/src/core/lib/gprpp/global_config_env.h +131 -0
  185. data/src/core/lib/gprpp/global_config_generic.h +44 -0
  186. data/src/core/lib/gprpp/inlined_vector.h +8 -0
  187. data/src/core/lib/gprpp/map.h +436 -0
  188. data/src/core/lib/gprpp/memory.h +2 -2
  189. data/src/core/lib/gprpp/optional.h +48 -0
  190. data/src/core/lib/gprpp/orphanable.h +6 -5
  191. data/src/core/lib/gprpp/{mutex_lock.h → pair.h} +15 -19
  192. data/src/core/lib/gprpp/ref_counted.h +36 -17
  193. data/src/core/lib/gprpp/sync.h +126 -0
  194. data/src/core/lib/gprpp/thd.h +42 -7
  195. data/src/core/lib/gprpp/thd_posix.cc +31 -13
  196. data/src/core/lib/gprpp/thd_windows.cc +47 -34
  197. data/src/core/lib/http/httpcli.cc +6 -5
  198. data/src/core/lib/http/httpcli_security_connector.cc +13 -15
  199. data/src/core/lib/http/parser.cc +3 -2
  200. data/src/core/lib/http/parser.h +2 -1
  201. data/src/core/lib/iomgr/buffer_list.cc +182 -24
  202. data/src/core/lib/iomgr/buffer_list.h +72 -10
  203. data/src/core/lib/iomgr/call_combiner.cc +84 -90
  204. data/src/core/lib/iomgr/call_combiner.h +75 -82
  205. data/src/core/lib/iomgr/cfstream_handle.cc +203 -0
  206. data/src/core/lib/iomgr/cfstream_handle.h +86 -0
  207. data/src/core/lib/iomgr/combiner.cc +11 -3
  208. data/src/core/lib/iomgr/combiner.h +1 -1
  209. data/src/core/lib/iomgr/endpoint.cc +2 -2
  210. data/src/core/lib/iomgr/endpoint.h +3 -2
  211. data/src/core/lib/iomgr/endpoint_cfstream.cc +375 -0
  212. data/src/core/lib/iomgr/endpoint_cfstream.h +49 -0
  213. data/src/core/lib/iomgr/endpoint_pair_windows.cc +2 -2
  214. data/src/core/lib/iomgr/error.cc +21 -17
  215. data/src/core/lib/iomgr/error.h +36 -6
  216. data/src/core/lib/iomgr/error_cfstream.cc +52 -0
  217. data/src/core/lib/iomgr/error_cfstream.h +31 -0
  218. data/src/core/lib/iomgr/error_internal.h +1 -1
  219. data/src/core/lib/iomgr/ev_epoll1_linux.cc +44 -28
  220. data/src/core/lib/iomgr/ev_epollex_linux.cc +173 -194
  221. data/src/core/lib/iomgr/ev_poll_posix.cc +16 -487
  222. data/src/core/lib/iomgr/ev_posix.cc +29 -19
  223. data/src/core/lib/iomgr/ev_posix.h +19 -3
  224. data/src/core/lib/iomgr/ev_windows.cc +2 -2
  225. data/src/core/lib/iomgr/exec_ctx.cc +1 -0
  226. data/src/core/lib/iomgr/exec_ctx.h +137 -8
  227. data/src/core/lib/iomgr/executor.cc +147 -95
  228. data/src/core/lib/iomgr/executor.h +55 -49
  229. data/src/core/lib/iomgr/fork_posix.cc +6 -5
  230. data/src/core/lib/{gprpp/atomic_with_std.h → iomgr/grpc_if_nametoindex.h} +8 -13
  231. data/src/core/lib/iomgr/grpc_if_nametoindex_posix.cc +42 -0
  232. data/src/core/lib/iomgr/{network_status_tracker.h → grpc_if_nametoindex_unsupported.cc} +15 -9
  233. data/src/core/lib/iomgr/internal_errqueue.cc +3 -5
  234. data/src/core/lib/iomgr/internal_errqueue.h +105 -3
  235. data/src/core/lib/iomgr/iomgr.cc +20 -13
  236. data/src/core/lib/iomgr/iomgr.h +15 -0
  237. data/src/core/lib/iomgr/iomgr_custom.cc +17 -3
  238. data/src/core/lib/iomgr/iomgr_custom.h +2 -0
  239. data/src/core/lib/iomgr/iomgr_internal.cc +10 -0
  240. data/src/core/lib/iomgr/iomgr_internal.h +12 -0
  241. data/src/core/lib/iomgr/iomgr_posix.cc +19 -2
  242. data/src/core/lib/iomgr/iomgr_posix_cfstream.cc +93 -0
  243. data/src/core/lib/iomgr/iomgr_windows.cc +18 -2
  244. data/src/core/lib/iomgr/lockfree_event.cc +4 -4
  245. data/src/core/lib/iomgr/port.h +35 -0
  246. data/src/core/lib/iomgr/resolve_address_posix.cc +4 -3
  247. data/src/core/lib/iomgr/resolve_address_windows.cc +2 -1
  248. data/src/core/lib/iomgr/resource_quota.cc +40 -37
  249. data/src/core/lib/iomgr/socket_utils_common_posix.cc +6 -2
  250. data/src/core/lib/iomgr/socket_windows.cc +19 -0
  251. data/src/core/lib/iomgr/socket_windows.h +8 -0
  252. data/src/core/lib/iomgr/tcp_client_cfstream.cc +216 -0
  253. data/src/core/lib/iomgr/tcp_client_custom.cc +2 -2
  254. data/src/core/lib/iomgr/tcp_client_posix.cc +3 -3
  255. data/src/core/lib/iomgr/tcp_client_windows.cc +7 -5
  256. data/src/core/lib/iomgr/tcp_custom.cc +10 -14
  257. data/src/core/lib/iomgr/tcp_posix.cc +256 -140
  258. data/src/core/lib/iomgr/tcp_server.cc +5 -0
  259. data/src/core/lib/iomgr/tcp_server.h +24 -0
  260. data/src/core/lib/iomgr/tcp_server_custom.cc +14 -12
  261. data/src/core/lib/iomgr/tcp_server_posix.cc +86 -12
  262. data/src/core/lib/iomgr/tcp_server_utils_posix.h +3 -0
  263. data/src/core/lib/iomgr/tcp_server_windows.cc +13 -11
  264. data/src/core/lib/iomgr/tcp_uv.cc +5 -7
  265. data/src/core/lib/iomgr/tcp_windows.cc +8 -14
  266. data/src/core/lib/iomgr/timer.h +2 -1
  267. data/src/core/lib/iomgr/timer_generic.cc +16 -16
  268. data/src/core/lib/iomgr/timer_manager.cc +20 -11
  269. data/src/core/lib/iomgr/udp_server.cc +8 -6
  270. data/src/core/lib/iomgr/wakeup_fd_posix.cc +1 -19
  271. data/src/core/lib/json/json.cc +1 -4
  272. data/src/core/lib/profiling/basic_timers.cc +10 -4
  273. data/src/core/lib/security/context/security_context.cc +6 -7
  274. data/src/core/lib/security/context/security_context.h +3 -4
  275. data/src/core/lib/security/credentials/alts/alts_credentials.cc +1 -1
  276. data/src/core/lib/security/credentials/alts/check_gcp_environment_no_op.cc +2 -2
  277. data/src/core/lib/security/credentials/composite/composite_credentials.h +4 -0
  278. data/src/core/lib/security/credentials/credentials.h +9 -1
  279. data/src/core/lib/security/credentials/google_default/google_default_credentials.cc +15 -3
  280. data/src/core/lib/security/credentials/google_default/google_default_credentials.h +2 -0
  281. data/src/core/lib/security/credentials/jwt/json_token.cc +1 -1
  282. data/src/core/lib/security/credentials/jwt/jwt_credentials.cc +2 -1
  283. data/src/core/lib/security/credentials/jwt/jwt_verifier.cc +10 -6
  284. data/src/core/lib/security/credentials/jwt/jwt_verifier.h +2 -1
  285. data/src/core/lib/security/credentials/oauth2/oauth2_credentials.cc +3 -3
  286. data/src/core/lib/security/credentials/plugin/plugin_credentials.cc +9 -8
  287. data/src/core/lib/security/credentials/ssl/ssl_credentials.cc +20 -2
  288. data/src/core/lib/security/credentials/ssl/ssl_credentials.h +2 -2
  289. data/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc +192 -0
  290. data/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h +210 -0
  291. data/src/core/lib/security/credentials/tls/spiffe_credentials.cc +129 -0
  292. data/src/core/lib/security/credentials/tls/spiffe_credentials.h +62 -0
  293. data/src/core/lib/security/security_connector/alts/alts_security_connector.cc +10 -8
  294. data/src/core/lib/security/security_connector/fake/fake_security_connector.cc +13 -12
  295. data/src/core/lib/security/security_connector/load_system_roots_linux.cc +7 -5
  296. data/src/core/lib/security/security_connector/local/local_security_connector.cc +10 -8
  297. data/src/core/lib/security/security_connector/security_connector.cc +0 -1
  298. data/src/core/lib/security/security_connector/security_connector.h +3 -3
  299. data/src/core/lib/security/security_connector/ssl/ssl_security_connector.cc +39 -38
  300. data/src/core/lib/security/security_connector/ssl_utils.cc +164 -26
  301. data/src/core/lib/security/security_connector/ssl_utils.h +70 -1
  302. data/src/core/lib/security/security_connector/tls/spiffe_security_connector.cc +426 -0
  303. data/src/core/lib/security/security_connector/tls/spiffe_security_connector.h +122 -0
  304. data/src/core/lib/security/transport/auth_filters.h +5 -2
  305. data/src/core/lib/security/transport/client_auth_filter.cc +55 -50
  306. data/src/core/lib/security/transport/secure_endpoint.cc +6 -6
  307. data/src/core/lib/security/transport/security_handshaker.cc +271 -303
  308. data/src/core/lib/security/transport/security_handshaker.h +11 -2
  309. data/src/core/lib/security/transport/server_auth_filter.cc +3 -3
  310. data/src/core/lib/slice/b64.h +2 -2
  311. data/src/core/lib/slice/percent_encoding.cc +3 -3
  312. data/src/core/lib/slice/percent_encoding.h +3 -3
  313. data/src/core/lib/slice/slice.cc +174 -122
  314. data/src/core/lib/slice/slice_buffer.cc +54 -21
  315. data/src/core/lib/slice/slice_hash_table.h +4 -4
  316. data/src/core/lib/slice/slice_intern.cc +49 -107
  317. data/src/core/lib/slice/slice_internal.h +264 -3
  318. data/src/core/lib/slice/slice_string_helpers.cc +10 -1
  319. data/src/core/lib/slice/slice_string_helpers.h +3 -1
  320. data/src/core/lib/slice/slice_utils.h +50 -0
  321. data/src/core/lib/slice/slice_weak_hash_table.h +6 -6
  322. data/src/core/lib/surface/api_trace.h +1 -1
  323. data/src/core/lib/surface/byte_buffer_reader.cc +17 -0
  324. data/src/core/lib/surface/call.cc +67 -46
  325. data/src/core/lib/surface/call.h +7 -2
  326. data/src/core/lib/surface/call_details.cc +0 -1
  327. data/src/core/lib/surface/channel.cc +89 -97
  328. data/src/core/lib/surface/channel.h +60 -6
  329. data/src/core/lib/surface/channel_init.h +5 -0
  330. data/src/core/lib/surface/completion_queue.cc +221 -216
  331. data/src/core/lib/surface/completion_queue.h +2 -1
  332. data/src/core/lib/surface/init.cc +82 -33
  333. data/src/core/lib/surface/init.h +1 -0
  334. data/src/core/lib/surface/init_secure.cc +1 -1
  335. data/src/core/lib/surface/lame_client.cc +5 -7
  336. data/src/core/lib/surface/server.cc +42 -47
  337. data/src/core/lib/surface/validate_metadata.cc +14 -8
  338. data/src/core/lib/surface/validate_metadata.h +13 -2
  339. data/src/core/lib/surface/version.cc +1 -1
  340. data/src/core/lib/transport/bdp_estimator.cc +3 -3
  341. data/src/core/lib/transport/bdp_estimator.h +2 -2
  342. data/src/core/lib/transport/connectivity_state.cc +10 -40
  343. data/src/core/lib/transport/connectivity_state.h +0 -8
  344. data/src/core/lib/transport/error_utils.cc +12 -0
  345. data/src/core/lib/transport/metadata.cc +258 -267
  346. data/src/core/lib/transport/metadata.h +227 -16
  347. data/src/core/lib/transport/metadata_batch.cc +1 -1
  348. data/src/core/lib/transport/metadata_batch.h +1 -1
  349. data/src/core/lib/transport/static_metadata.cc +477 -399
  350. data/src/core/lib/transport/static_metadata.h +273 -182
  351. data/src/core/lib/transport/status_metadata.cc +3 -3
  352. data/src/core/lib/transport/timeout_encoding.cc +1 -1
  353. data/src/core/lib/transport/timeout_encoding.h +1 -1
  354. data/src/core/lib/transport/transport.cc +39 -72
  355. data/src/core/lib/transport/transport.h +59 -24
  356. data/src/core/lib/transport/transport_impl.h +1 -1
  357. data/src/core/tsi/alts/handshaker/alts_handshaker_client.cc +3 -3
  358. data/src/core/tsi/alts/handshaker/alts_handshaker_client.h +1 -1
  359. data/src/core/tsi/alts/handshaker/alts_shared_resource.h +1 -1
  360. data/src/core/tsi/alts/handshaker/transport_security_common_api.cc +4 -3
  361. data/src/core/tsi/alts/handshaker/transport_security_common_api.h +1 -1
  362. data/src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.cc +1 -1
  363. data/src/core/tsi/fake_transport_security.cc +4 -4
  364. data/src/core/tsi/ssl/session_cache/ssl_session_cache.cc +1 -1
  365. data/src/core/tsi/ssl_transport_security.cc +12 -10
  366. data/src/core/tsi/ssl_transport_security.h +24 -4
  367. data/src/ruby/bin/math_pb.rb +18 -16
  368. data/src/ruby/ext/grpc/extconf.rb +12 -4
  369. data/src/ruby/ext/grpc/rb_call_credentials.c +8 -5
  370. data/src/ruby/ext/grpc/rb_channel.c +14 -10
  371. data/src/ruby/ext/grpc/rb_channel_credentials.c +8 -4
  372. data/src/ruby/ext/grpc/rb_compression_options.c +9 -7
  373. data/src/ruby/ext/grpc/rb_event_thread.c +2 -0
  374. data/src/ruby/ext/grpc/rb_grpc.c +23 -24
  375. data/src/ruby/ext/grpc/rb_grpc.h +4 -2
  376. data/src/ruby/ext/grpc/rb_grpc_imports.generated.c +24 -0
  377. data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +36 -0
  378. data/src/ruby/ext/grpc/rb_server.c +8 -4
  379. data/src/ruby/lib/grpc/errors.rb +22 -3
  380. data/src/ruby/lib/grpc/generic/bidi_call.rb +1 -1
  381. data/src/ruby/lib/grpc/generic/rpc_server.rb +2 -2
  382. data/src/ruby/lib/grpc/version.rb +1 -1
  383. data/src/ruby/pb/README.md +1 -1
  384. data/src/ruby/pb/grpc/health/v1/health_pb.rb +13 -10
  385. data/src/ruby/pb/grpc/health/v1/health_services_pb.rb +18 -0
  386. data/src/ruby/pb/src/proto/grpc/testing/empty_pb.rb +3 -1
  387. data/src/ruby/pb/src/proto/grpc/testing/messages_pb.rb +58 -56
  388. data/src/ruby/pb/src/proto/grpc/testing/test_pb.rb +2 -0
  389. data/src/ruby/spec/errors_spec.rb +141 -0
  390. data/third_party/cares/cares/ares.h +12 -0
  391. data/third_party/cares/cares/ares_create_query.c +5 -1
  392. data/third_party/cares/cares/ares_data.c +74 -73
  393. data/third_party/cares/cares/ares_destroy.c +6 -1
  394. data/third_party/cares/cares/ares_gethostbyaddr.c +5 -5
  395. data/third_party/cares/cares/ares_gethostbyname.c +15 -4
  396. data/third_party/cares/cares/ares_getnameinfo.c +11 -0
  397. data/third_party/cares/cares/ares_init.c +274 -173
  398. data/third_party/cares/cares/ares_library_init.c +21 -3
  399. data/third_party/cares/cares/ares_options.c +6 -2
  400. data/third_party/cares/cares/ares_parse_naptr_reply.c +7 -6
  401. data/third_party/cares/cares/ares_parse_ptr_reply.c +4 -2
  402. data/third_party/cares/cares/ares_platform.c +7 -0
  403. data/third_party/cares/cares/ares_private.h +19 -11
  404. data/third_party/cares/cares/ares_process.c +27 -2
  405. data/third_party/cares/cares/ares_rules.h +1 -1
  406. data/third_party/cares/cares/ares_search.c +7 -0
  407. data/third_party/cares/cares/ares_send.c +6 -0
  408. data/third_party/cares/cares/ares_strsplit.c +174 -0
  409. data/third_party/cares/cares/ares_strsplit.h +43 -0
  410. data/third_party/cares/cares/ares_version.h +4 -4
  411. data/third_party/cares/cares/config-win32.h +1 -1
  412. data/third_party/cares/cares/inet_ntop.c +2 -3
  413. data/third_party/cares/config_darwin/ares_config.h +3 -0
  414. data/third_party/cares/config_freebsd/ares_config.h +3 -0
  415. data/third_party/cares/config_linux/ares_config.h +3 -0
  416. data/third_party/cares/config_openbsd/ares_config.h +3 -0
  417. metadata +83 -48
  418. data/src/core/ext/filters/client_channel/request_routing.cc +0 -936
  419. data/src/core/ext/filters/client_channel/request_routing.h +0 -177
  420. data/src/core/ext/filters/client_channel/subchannel_index.cc +0 -248
  421. data/src/core/ext/filters/client_channel/subchannel_index.h +0 -76
  422. data/src/core/lib/channel/handshaker_factory.cc +0 -42
  423. data/src/core/lib/gpr/arena.cc +0 -192
  424. data/src/core/lib/gprpp/atomic_with_atm.h +0 -57
  425. data/src/core/lib/iomgr/wakeup_fd_cv.cc +0 -107
  426. data/src/core/lib/iomgr/wakeup_fd_cv.h +0 -69
  427. data/src/core/lib/transport/service_config.cc +0 -106
  428. data/src/core/lib/transport/service_config.h +0 -249
@@ -26,30 +26,27 @@
26
26
  /// channel that uses pick_first to select from the list of balancer
27
27
  /// addresses.
28
28
  ///
29
- /// The first time the policy gets a request for a pick, a ping, or to exit
30
- /// the idle state, \a StartPickingLocked() is called. This method is
31
- /// responsible for instantiating the internal *streaming* call to the LB
32
- /// server (whichever address pick_first chose). The call will be complete
33
- /// when either the balancer sends status or when we cancel the call (e.g.,
34
- /// because we are shutting down). In needed, we retry the call. If we
35
- /// received at least one valid message from the server, a new call attempt
36
- /// will be made immediately; otherwise, we apply back-off delays between
37
- /// attempts.
29
+ /// When we get our initial update, we instantiate the internal *streaming*
30
+ /// call to the LB server (whichever address pick_first chose). The call
31
+ /// will be complete when either the balancer sends status or when we cancel
32
+ /// the call (e.g., because we are shutting down). In needed, we retry the
33
+ /// call. If we received at least one valid message from the server, a new
34
+ /// call attempt will be made immediately; otherwise, we apply back-off
35
+ /// delays between attempts.
38
36
  ///
39
37
  /// We maintain an internal round_robin policy instance for distributing
40
38
  /// requests across backends. Whenever we receive a new serverlist from
41
39
  /// the balancer, we update the round_robin policy with the new list of
42
40
  /// addresses. If we cannot communicate with the balancer on startup,
43
41
  /// however, we may enter fallback mode, in which case we will populate
44
- /// the RR policy's addresses from the backend addresses returned by the
42
+ /// the child policy's addresses from the backend addresses returned by the
45
43
  /// resolver.
46
44
  ///
47
- /// Once an RR policy instance is in place (and getting updated as described),
45
+ /// Once a child policy instance is in place (and getting updated as described),
48
46
  /// calls for a pick, a ping, or a cancellation will be serviced right
49
- /// away by forwarding them to the RR instance. Any time there's no RR
50
- /// policy available (i.e., right after the creation of the gRPCLB policy),
51
- /// pick and ping requests are added to a list of pending picks and pings
52
- /// to be flushed and serviced when the RR policy instance becomes available.
47
+ /// away by forwarding them to the child policy instance. Any time there's no
48
+ /// child policy available (i.e., right after the creation of the gRPCLB
49
+ /// policy), pick requests are queued.
53
50
  ///
54
51
  /// \see https://github.com/grpc/grpc/blob/master/doc/load-balancing.md for the
55
52
  /// high level design and details.
@@ -74,7 +71,6 @@
74
71
  #include <grpc/support/time.h>
75
72
 
76
73
  #include "src/core/ext/filters/client_channel/client_channel.h"
77
- #include "src/core/ext/filters/client_channel/client_channel_factory.h"
78
74
  #include "src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.h"
79
75
  #include "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h"
80
76
  #include "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h"
@@ -85,7 +81,6 @@
85
81
  #include "src/core/ext/filters/client_channel/parse_address.h"
86
82
  #include "src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h"
87
83
  #include "src/core/ext/filters/client_channel/server_address.h"
88
- #include "src/core/ext/filters/client_channel/subchannel_index.h"
89
84
  #include "src/core/lib/backoff/backoff.h"
90
85
  #include "src/core/lib/channel/channel_args.h"
91
86
  #include "src/core/lib/channel/channel_stack.h"
@@ -93,7 +88,6 @@
93
88
  #include "src/core/lib/gpr/string.h"
94
89
  #include "src/core/lib/gprpp/manual_constructor.h"
95
90
  #include "src/core/lib/gprpp/memory.h"
96
- #include "src/core/lib/gprpp/mutex_lock.h"
97
91
  #include "src/core/lib/gprpp/orphanable.h"
98
92
  #include "src/core/lib/gprpp/ref_counted_ptr.h"
99
93
  #include "src/core/lib/iomgr/combiner.h"
@@ -124,56 +118,31 @@ namespace {
124
118
 
125
119
  constexpr char kGrpclb[] = "grpclb";
126
120
 
121
+ class ParsedGrpcLbConfig : public LoadBalancingPolicy::Config {
122
+ public:
123
+ explicit ParsedGrpcLbConfig(
124
+ RefCountedPtr<LoadBalancingPolicy::Config> child_policy)
125
+ : child_policy_(std::move(child_policy)) {}
126
+ const char* name() const override { return kGrpclb; }
127
+
128
+ RefCountedPtr<LoadBalancingPolicy::Config> child_policy() const {
129
+ return child_policy_;
130
+ }
131
+
132
+ private:
133
+ RefCountedPtr<LoadBalancingPolicy::Config> child_policy_;
134
+ };
135
+
127
136
  class GrpcLb : public LoadBalancingPolicy {
128
137
  public:
129
- explicit GrpcLb(const Args& args);
138
+ explicit GrpcLb(Args args);
130
139
 
131
140
  const char* name() const override { return kGrpclb; }
132
141
 
133
- void UpdateLocked(const grpc_channel_args& args,
134
- grpc_json* lb_config) override;
135
- bool PickLocked(PickState* pick, grpc_error** error) override;
136
- void CancelPickLocked(PickState* pick, grpc_error* error) override;
137
- void CancelMatchingPicksLocked(uint32_t initial_metadata_flags_mask,
138
- uint32_t initial_metadata_flags_eq,
139
- grpc_error* error) override;
140
- void NotifyOnStateChangeLocked(grpc_connectivity_state* state,
141
- grpc_closure* closure) override;
142
- grpc_connectivity_state CheckConnectivityLocked(
143
- grpc_error** connectivity_error) override;
144
- void HandOffPendingPicksLocked(LoadBalancingPolicy* new_policy) override;
145
- void ExitIdleLocked() override;
142
+ void UpdateLocked(UpdateArgs args) override;
146
143
  void ResetBackoffLocked() override;
147
- void FillChildRefsForChannelz(
148
- channelz::ChildRefsList* child_subchannels,
149
- channelz::ChildRefsList* child_channels) override;
150
144
 
151
145
  private:
152
- /// Linked list of pending pick requests. It stores all information needed to
153
- /// eventually call (Round Robin's) pick() on them. They mainly stay pending
154
- /// waiting for the RR policy to be created.
155
- ///
156
- /// Note that when a pick is sent to the RR policy, we inject our own
157
- /// on_complete callback, so that we can intercept the result before
158
- /// invoking the original on_complete callback. This allows us to set the
159
- /// LB token metadata and add client_stats to the call context.
160
- /// See \a pending_pick_complete() for details.
161
- struct PendingPick {
162
- // The grpclb instance that created the wrapping. This instance is not
163
- // owned; reference counts are untouched. It's used only for logging
164
- // purposes.
165
- GrpcLb* grpclb_policy;
166
- // The original pick.
167
- PickState* pick;
168
- // Our on_complete closure and the original one.
169
- grpc_closure on_complete;
170
- grpc_closure* original_on_complete;
171
- // Stats for client-side load reporting.
172
- RefCountedPtr<GrpcLbClientStats> client_stats;
173
- // Next pending pick.
174
- PendingPick* next = nullptr;
175
- };
176
-
177
146
  /// Contains a call to the LB server and all the data related to the call.
178
147
  class BalancerCallState : public InternallyRefCounted<BalancerCallState> {
179
148
  public:
@@ -189,6 +158,7 @@ class GrpcLb : public LoadBalancingPolicy {
189
158
  GrpcLbClientStats* client_stats() const { return client_stats_.get(); }
190
159
 
191
160
  bool seen_initial_response() const { return seen_initial_response_; }
161
+ bool seen_serverlist() const { return seen_serverlist_; }
192
162
 
193
163
  private:
194
164
  // So Delete() can access our private dtor.
@@ -229,6 +199,7 @@ class GrpcLb : public LoadBalancingPolicy {
229
199
  grpc_byte_buffer* recv_message_payload_ = nullptr;
230
200
  grpc_closure lb_on_balancer_message_received_;
231
201
  bool seen_initial_response_ = false;
202
+ bool seen_serverlist_ = false;
232
203
 
233
204
  // recv_trailing_metadata
234
205
  grpc_closure lb_on_balancer_status_received_;
@@ -249,40 +220,121 @@ class GrpcLb : public LoadBalancingPolicy {
249
220
  grpc_closure client_load_report_closure_;
250
221
  };
251
222
 
223
+ class Serverlist : public RefCounted<Serverlist> {
224
+ public:
225
+ // Takes ownership of serverlist.
226
+ explicit Serverlist(grpc_grpclb_serverlist* serverlist)
227
+ : serverlist_(serverlist) {}
228
+
229
+ ~Serverlist() { grpc_grpclb_destroy_serverlist(serverlist_); }
230
+
231
+ bool operator==(const Serverlist& other) const;
232
+
233
+ const grpc_grpclb_serverlist* serverlist() const { return serverlist_; }
234
+
235
+ // Returns a text representation suitable for logging.
236
+ UniquePtr<char> AsText() const;
237
+
238
+ // Extracts all non-drop entries into a ServerAddressList.
239
+ ServerAddressList GetServerAddressList(
240
+ GrpcLbClientStats* client_stats) const;
241
+
242
+ // Returns true if the serverlist contains at least one drop entry and
243
+ // no backend address entries.
244
+ bool ContainsAllDropEntries() const;
245
+
246
+ // Returns the LB token to use for a drop, or null if the call
247
+ // should not be dropped.
248
+ //
249
+ // Note: This is called from the picker, so it will be invoked in
250
+ // the channel's data plane combiner, NOT the control plane
251
+ // combiner. It should not be accessed by any other part of the LB
252
+ // policy.
253
+ const char* ShouldDrop();
254
+
255
+ private:
256
+ grpc_grpclb_serverlist* serverlist_;
257
+
258
+ // Guarded by the channel's data plane combiner, NOT the control
259
+ // plane combiner. It should not be accessed by anything but the
260
+ // picker via the ShouldDrop() method.
261
+ size_t drop_index_ = 0;
262
+ };
263
+
264
+ class Picker : public SubchannelPicker {
265
+ public:
266
+ Picker(GrpcLb* parent, RefCountedPtr<Serverlist> serverlist,
267
+ UniquePtr<SubchannelPicker> child_picker,
268
+ RefCountedPtr<GrpcLbClientStats> client_stats)
269
+ : parent_(parent),
270
+ serverlist_(std::move(serverlist)),
271
+ child_picker_(std::move(child_picker)),
272
+ client_stats_(std::move(client_stats)) {}
273
+
274
+ PickResult Pick(PickArgs args) override;
275
+
276
+ private:
277
+ // Storing the address for logging, but not holding a ref.
278
+ // DO NOT DEFERENCE!
279
+ GrpcLb* parent_;
280
+
281
+ // Serverlist to be used for determining drops.
282
+ RefCountedPtr<Serverlist> serverlist_;
283
+
284
+ UniquePtr<SubchannelPicker> child_picker_;
285
+ RefCountedPtr<GrpcLbClientStats> client_stats_;
286
+ };
287
+
288
+ class Helper : public ChannelControlHelper {
289
+ public:
290
+ explicit Helper(RefCountedPtr<GrpcLb> parent)
291
+ : parent_(std::move(parent)) {}
292
+
293
+ RefCountedPtr<SubchannelInterface> CreateSubchannel(
294
+ const grpc_channel_args& args) override;
295
+ grpc_channel* CreateChannel(const char* target,
296
+ const grpc_channel_args& args) override;
297
+ void UpdateState(grpc_connectivity_state state,
298
+ UniquePtr<SubchannelPicker> picker) override;
299
+ void RequestReresolution() override;
300
+ void AddTraceEvent(TraceSeverity severity, const char* message) override;
301
+
302
+ void set_child(LoadBalancingPolicy* child) { child_ = child; }
303
+
304
+ private:
305
+ bool CalledByPendingChild() const;
306
+ bool CalledByCurrentChild() const;
307
+
308
+ RefCountedPtr<GrpcLb> parent_;
309
+ LoadBalancingPolicy* child_ = nullptr;
310
+ };
311
+
252
312
  ~GrpcLb();
253
313
 
254
314
  void ShutdownLocked() override;
255
315
 
256
- // Helper function used in ctor and UpdateLocked().
257
- void ProcessChannelArgsLocked(const grpc_channel_args& args);
316
+ // Helper functions used in UpdateLocked().
317
+ void ProcessAddressesAndChannelArgsLocked(const ServerAddressList& addresses,
318
+ const grpc_channel_args& args);
319
+ static void OnBalancerChannelConnectivityChangedLocked(void* arg,
320
+ grpc_error* error);
321
+ void CancelBalancerChannelConnectivityWatchLocked();
258
322
 
259
- // Methods for dealing with the balancer channel and call.
260
- void StartPickingLocked();
261
- void StartBalancerCallLocked();
323
+ // Methods for dealing with fallback state.
324
+ void MaybeEnterFallbackModeAfterStartup();
262
325
  static void OnFallbackTimerLocked(void* arg, grpc_error* error);
326
+
327
+ // Methods for dealing with the balancer call.
328
+ void StartBalancerCallLocked();
263
329
  void StartBalancerCallRetryTimerLocked();
264
330
  static void OnBalancerCallRetryTimerLocked(void* arg, grpc_error* error);
265
- static void OnBalancerChannelConnectivityChangedLocked(void* arg,
266
- grpc_error* error);
267
331
 
268
- // Pending pick methods.
269
- static void PendingPickSetMetadataAndContext(PendingPick* pp);
270
- PendingPick* PendingPickCreate(PickState* pick);
271
- void AddPendingPick(PendingPick* pp);
272
- static void OnPendingPickComplete(void* arg, grpc_error* error);
273
-
274
- // Methods for dealing with the RR policy.
275
- void CreateOrUpdateRoundRobinPolicyLocked();
276
- grpc_channel_args* CreateRoundRobinPolicyArgsLocked();
277
- void CreateRoundRobinPolicyLocked(const Args& args);
278
- bool PickFromRoundRobinPolicyLocked(bool force_async, PendingPick* pp,
279
- grpc_error** error);
280
- void UpdateConnectivityStateFromRoundRobinPolicyLocked(
281
- grpc_error* rr_state_error);
282
- static void OnRoundRobinConnectivityChangedLocked(void* arg,
283
- grpc_error* error);
284
- static void OnRoundRobinRequestReresolutionLocked(void* arg,
285
- grpc_error* error);
332
+ // Methods for dealing with the child policy.
333
+ grpc_channel_args* CreateChildPolicyArgsLocked(
334
+ bool is_backend_from_grpclb_load_balancer);
335
+ OrphanablePtr<LoadBalancingPolicy> CreateChildPolicyLocked(
336
+ const char* name, const grpc_channel_args* args);
337
+ void CreateOrUpdateChildPolicyLocked();
286
338
 
287
339
  // Who the client is trying to communicate with.
288
340
  const char* server_name_ = nullptr;
@@ -291,19 +343,10 @@ class GrpcLb : public LoadBalancingPolicy {
291
343
  grpc_channel_args* args_ = nullptr;
292
344
 
293
345
  // Internal state.
294
- bool started_picking_ = false;
295
346
  bool shutting_down_ = false;
296
- grpc_connectivity_state_tracker state_tracker_;
297
347
 
298
348
  // The channel for communicating with the LB server.
299
349
  grpc_channel* lb_channel_ = nullptr;
300
- // Mutex to protect the channel to the LB server. This is used when
301
- // processing a channelz request.
302
- gpr_mu lb_channel_mu_;
303
- grpc_connectivity_state lb_channel_connectivity_;
304
- grpc_closure lb_channel_on_connectivity_changed_;
305
- // Are we already watching the LB channel's connectivity?
306
- bool watching_lb_channel_ = false;
307
350
  // Response generator to inject address updates into lb_channel_.
308
351
  RefCountedPtr<FakeResolverResponseGenerator> response_generator_;
309
352
 
@@ -323,36 +366,88 @@ class GrpcLb : public LoadBalancingPolicy {
323
366
 
324
367
  // The deserialized response from the balancer. May be nullptr until one
325
368
  // such response has arrived.
326
- grpc_grpclb_serverlist* serverlist_ = nullptr;
327
- // Index into serverlist for next pick.
328
- // If the server at this index is a drop, we return a drop.
329
- // Otherwise, we delegate to the RR policy.
330
- size_t serverlist_index_ = 0;
331
-
332
- // Timeout in milliseconds for before using fallback backend addresses.
333
- // 0 means not using fallback.
334
- int lb_fallback_timeout_ms_ = 0;
369
+ RefCountedPtr<Serverlist> serverlist_;
370
+
371
+ // Whether we're in fallback mode.
372
+ bool fallback_mode_ = false;
335
373
  // The backend addresses from the resolver.
336
- UniquePtr<ServerAddressList> fallback_backend_addresses_;
337
- // Fallback timer.
338
- bool fallback_timer_callback_pending_ = false;
374
+ ServerAddressList fallback_backend_addresses_;
375
+ // State for fallback-at-startup checks.
376
+ // Timeout after startup after which we will go into fallback mode if
377
+ // we have not received a serverlist from the balancer.
378
+ int fallback_at_startup_timeout_ = 0;
379
+ bool fallback_at_startup_checks_pending_ = false;
339
380
  grpc_timer lb_fallback_timer_;
340
381
  grpc_closure lb_on_fallback_;
382
+ grpc_connectivity_state lb_channel_connectivity_ = GRPC_CHANNEL_IDLE;
383
+ grpc_closure lb_channel_on_connectivity_changed_;
341
384
 
342
- // Pending picks that are waiting on the RR policy's connectivity.
343
- PendingPick* pending_picks_ = nullptr;
344
-
345
- // The RR policy to use for the backends.
346
- OrphanablePtr<LoadBalancingPolicy> rr_policy_;
347
- grpc_connectivity_state rr_connectivity_state_;
348
- grpc_closure on_rr_connectivity_changed_;
349
- grpc_closure on_rr_request_reresolution_;
385
+ // The child policy to use for the backends.
386
+ OrphanablePtr<LoadBalancingPolicy> child_policy_;
387
+ // When switching child policies, the new policy will be stored here
388
+ // until it reports READY, at which point it will be moved to child_policy_.
389
+ OrphanablePtr<LoadBalancingPolicy> pending_child_policy_;
390
+ // The child policy config.
391
+ RefCountedPtr<LoadBalancingPolicy::Config> child_policy_config_;
392
+ // Child policy in state READY.
393
+ bool child_policy_ready_ = false;
350
394
  };
351
395
 
352
396
  //
353
- // serverlist parsing code
397
+ // GrpcLb::Serverlist
354
398
  //
355
399
 
400
+ bool GrpcLb::Serverlist::operator==(const Serverlist& other) const {
401
+ return grpc_grpclb_serverlist_equals(serverlist_, other.serverlist_);
402
+ }
403
+
404
+ void ParseServer(const grpc_grpclb_server* server,
405
+ grpc_resolved_address* addr) {
406
+ memset(addr, 0, sizeof(*addr));
407
+ if (server->drop) return;
408
+ const uint16_t netorder_port = grpc_htons((uint16_t)server->port);
409
+ /* the addresses are given in binary format (a in(6)_addr struct) in
410
+ * server->ip_address.bytes. */
411
+ const grpc_grpclb_ip_address* ip = &server->ip_address;
412
+ if (ip->size == 4) {
413
+ addr->len = static_cast<socklen_t>(sizeof(grpc_sockaddr_in));
414
+ grpc_sockaddr_in* addr4 = reinterpret_cast<grpc_sockaddr_in*>(&addr->addr);
415
+ addr4->sin_family = GRPC_AF_INET;
416
+ memcpy(&addr4->sin_addr, ip->bytes, ip->size);
417
+ addr4->sin_port = netorder_port;
418
+ } else if (ip->size == 16) {
419
+ addr->len = static_cast<socklen_t>(sizeof(grpc_sockaddr_in6));
420
+ grpc_sockaddr_in6* addr6 = (grpc_sockaddr_in6*)&addr->addr;
421
+ addr6->sin6_family = GRPC_AF_INET6;
422
+ memcpy(&addr6->sin6_addr, ip->bytes, ip->size);
423
+ addr6->sin6_port = netorder_port;
424
+ }
425
+ }
426
+
427
+ UniquePtr<char> GrpcLb::Serverlist::AsText() const {
428
+ gpr_strvec entries;
429
+ gpr_strvec_init(&entries);
430
+ for (size_t i = 0; i < serverlist_->num_servers; ++i) {
431
+ const auto* server = serverlist_->servers[i];
432
+ char* ipport;
433
+ if (server->drop) {
434
+ ipport = gpr_strdup("(drop)");
435
+ } else {
436
+ grpc_resolved_address addr;
437
+ ParseServer(server, &addr);
438
+ grpc_sockaddr_to_string(&ipport, &addr, false);
439
+ }
440
+ char* entry;
441
+ gpr_asprintf(&entry, " %" PRIuPTR ": %s token=%s\n", i, ipport,
442
+ server->load_balance_token);
443
+ gpr_free(ipport);
444
+ gpr_strvec_add(&entries, entry);
445
+ }
446
+ UniquePtr<char> result(gpr_strvec_flatten(&entries, nullptr));
447
+ gpr_strvec_destroy(&entries);
448
+ return result;
449
+ }
450
+
356
451
  // vtable for LB token channel arg.
357
452
  void* lb_token_copy(void* token) {
358
453
  return token == nullptr
@@ -395,35 +490,13 @@ bool IsServerValid(const grpc_grpclb_server* server, size_t idx, bool log) {
395
490
  return true;
396
491
  }
397
492
 
398
- void ParseServer(const grpc_grpclb_server* server,
399
- grpc_resolved_address* addr) {
400
- memset(addr, 0, sizeof(*addr));
401
- if (server->drop) return;
402
- const uint16_t netorder_port = grpc_htons((uint16_t)server->port);
403
- /* the addresses are given in binary format (a in(6)_addr struct) in
404
- * server->ip_address.bytes. */
405
- const grpc_grpclb_ip_address* ip = &server->ip_address;
406
- if (ip->size == 4) {
407
- addr->len = static_cast<socklen_t>(sizeof(grpc_sockaddr_in));
408
- grpc_sockaddr_in* addr4 = reinterpret_cast<grpc_sockaddr_in*>(&addr->addr);
409
- addr4->sin_family = GRPC_AF_INET;
410
- memcpy(&addr4->sin_addr, ip->bytes, ip->size);
411
- addr4->sin_port = netorder_port;
412
- } else if (ip->size == 16) {
413
- addr->len = static_cast<socklen_t>(sizeof(grpc_sockaddr_in6));
414
- grpc_sockaddr_in6* addr6 = (grpc_sockaddr_in6*)&addr->addr;
415
- addr6->sin6_family = GRPC_AF_INET6;
416
- memcpy(&addr6->sin6_addr, ip->bytes, ip->size);
417
- addr6->sin6_port = netorder_port;
418
- }
419
- }
420
-
421
- // Returns addresses extracted from \a serverlist.
422
- ServerAddressList ProcessServerlist(const grpc_grpclb_serverlist* serverlist) {
493
+ // Returns addresses extracted from the serverlist.
494
+ ServerAddressList GrpcLb::Serverlist::GetServerAddressList(
495
+ GrpcLbClientStats* client_stats) const {
423
496
  ServerAddressList addresses;
424
- for (size_t i = 0; i < serverlist->num_servers; ++i) {
425
- const grpc_grpclb_server* server = serverlist->servers[i];
426
- if (!IsServerValid(serverlist->servers[i], i, false)) continue;
497
+ for (size_t i = 0; i < serverlist_->num_servers; ++i) {
498
+ const grpc_grpclb_server* server = serverlist_->servers[i];
499
+ if (!IsServerValid(serverlist_->servers[i], i, false)) continue;
427
500
  // Address processing.
428
501
  grpc_resolved_address addr;
429
502
  ParseServer(server, &addr);
@@ -437,6 +510,11 @@ ServerAddressList ProcessServerlist(const grpc_grpclb_serverlist* serverlist) {
437
510
  grpc_slice lb_token_mdstr = grpc_slice_from_copied_buffer(
438
511
  server->load_balance_token, lb_token_length);
439
512
  lb_token = grpc_mdelem_from_slices(GRPC_MDSTR_LB_TOKEN, lb_token_mdstr);
513
+ if (client_stats != nullptr) {
514
+ GPR_ASSERT(grpc_mdelem_set_user_data(
515
+ lb_token, GrpcLbClientStats::Destroy,
516
+ client_stats->Ref().release()) == client_stats);
517
+ }
440
518
  } else {
441
519
  char* uri = grpc_sockaddr_to_uri(&addr);
442
520
  gpr_log(GPR_INFO,
@@ -458,6 +536,206 @@ ServerAddressList ProcessServerlist(const grpc_grpclb_serverlist* serverlist) {
458
536
  return addresses;
459
537
  }
460
538
 
539
+ bool GrpcLb::Serverlist::ContainsAllDropEntries() const {
540
+ if (serverlist_->num_servers == 0) return false;
541
+ for (size_t i = 0; i < serverlist_->num_servers; ++i) {
542
+ if (!serverlist_->servers[i]->drop) return false;
543
+ }
544
+ return true;
545
+ }
546
+
547
+ const char* GrpcLb::Serverlist::ShouldDrop() {
548
+ if (serverlist_->num_servers == 0) return nullptr;
549
+ grpc_grpclb_server* server = serverlist_->servers[drop_index_];
550
+ drop_index_ = (drop_index_ + 1) % serverlist_->num_servers;
551
+ return server->drop ? server->load_balance_token : nullptr;
552
+ }
553
+
554
+ //
555
+ // GrpcLb::Picker
556
+ //
557
+
558
+ GrpcLb::PickResult GrpcLb::Picker::Pick(PickArgs args) {
559
+ PickResult result;
560
+ // Check if we should drop the call.
561
+ const char* drop_token = serverlist_->ShouldDrop();
562
+ if (drop_token != nullptr) {
563
+ // Update client load reporting stats to indicate the number of
564
+ // dropped calls. Note that we have to do this here instead of in
565
+ // the client_load_reporting filter, because we do not create a
566
+ // subchannel call (and therefore no client_load_reporting filter)
567
+ // for dropped calls.
568
+ if (client_stats_ != nullptr) {
569
+ client_stats_->AddCallDropped(drop_token);
570
+ }
571
+ result.type = PickResult::PICK_COMPLETE;
572
+ return result;
573
+ }
574
+ // Forward pick to child policy.
575
+ result = child_picker_->Pick(args);
576
+ // If pick succeeded, add LB token to initial metadata.
577
+ if (result.type == PickResult::PICK_COMPLETE &&
578
+ result.connected_subchannel != nullptr) {
579
+ const grpc_arg* arg = grpc_channel_args_find(
580
+ result.connected_subchannel->args(), GRPC_ARG_GRPCLB_ADDRESS_LB_TOKEN);
581
+ if (arg == nullptr) {
582
+ gpr_log(GPR_ERROR,
583
+ "[grpclb %p picker %p] No LB token for connected subchannel %p",
584
+ parent_, this, result.connected_subchannel.get());
585
+ abort();
586
+ }
587
+ grpc_mdelem lb_token = {reinterpret_cast<uintptr_t>(arg->value.pointer.p)};
588
+ GPR_ASSERT(!GRPC_MDISNULL(lb_token));
589
+ grpc_linked_mdelem* mdelem_storage = static_cast<grpc_linked_mdelem*>(
590
+ args.call_state->Alloc(sizeof(grpc_linked_mdelem)));
591
+ GPR_ASSERT(grpc_metadata_batch_add_tail(
592
+ args.initial_metadata, mdelem_storage,
593
+ GRPC_MDELEM_REF(lb_token)) == GRPC_ERROR_NONE);
594
+ GrpcLbClientStats* client_stats = static_cast<GrpcLbClientStats*>(
595
+ grpc_mdelem_get_user_data(lb_token, GrpcLbClientStats::Destroy));
596
+ if (client_stats != nullptr) {
597
+ client_stats->AddCallStarted();
598
+ }
599
+ }
600
+ return result;
601
+ }
602
+
603
+ //
604
+ // GrpcLb::Helper
605
+ //
606
+
607
+ bool GrpcLb::Helper::CalledByPendingChild() const {
608
+ GPR_ASSERT(child_ != nullptr);
609
+ return child_ == parent_->pending_child_policy_.get();
610
+ }
611
+
612
+ bool GrpcLb::Helper::CalledByCurrentChild() const {
613
+ GPR_ASSERT(child_ != nullptr);
614
+ return child_ == parent_->child_policy_.get();
615
+ }
616
+
617
+ RefCountedPtr<SubchannelInterface> GrpcLb::Helper::CreateSubchannel(
618
+ const grpc_channel_args& args) {
619
+ if (parent_->shutting_down_ ||
620
+ (!CalledByPendingChild() && !CalledByCurrentChild())) {
621
+ return nullptr;
622
+ }
623
+ return parent_->channel_control_helper()->CreateSubchannel(args);
624
+ }
625
+
626
+ grpc_channel* GrpcLb::Helper::CreateChannel(const char* target,
627
+ const grpc_channel_args& args) {
628
+ if (parent_->shutting_down_ ||
629
+ (!CalledByPendingChild() && !CalledByCurrentChild())) {
630
+ return nullptr;
631
+ }
632
+ return parent_->channel_control_helper()->CreateChannel(target, args);
633
+ }
634
+
635
+ void GrpcLb::Helper::UpdateState(grpc_connectivity_state state,
636
+ UniquePtr<SubchannelPicker> picker) {
637
+ if (parent_->shutting_down_) return;
638
+ // If this request is from the pending child policy, ignore it until
639
+ // it reports READY, at which point we swap it into place.
640
+ if (CalledByPendingChild()) {
641
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_glb_trace)) {
642
+ gpr_log(GPR_INFO,
643
+ "[grpclb %p helper %p] pending child policy %p reports state=%s",
644
+ parent_.get(), this, parent_->pending_child_policy_.get(),
645
+ grpc_connectivity_state_name(state));
646
+ }
647
+ if (state != GRPC_CHANNEL_READY) return;
648
+ grpc_pollset_set_del_pollset_set(
649
+ parent_->child_policy_->interested_parties(),
650
+ parent_->interested_parties());
651
+ parent_->child_policy_ = std::move(parent_->pending_child_policy_);
652
+ } else if (!CalledByCurrentChild()) {
653
+ // This request is from an outdated child, so ignore it.
654
+ return;
655
+ }
656
+ // Record whether child policy reports READY.
657
+ parent_->child_policy_ready_ = state == GRPC_CHANNEL_READY;
658
+ // Enter fallback mode if needed.
659
+ parent_->MaybeEnterFallbackModeAfterStartup();
660
+ // There are three cases to consider here:
661
+ // 1. We're in fallback mode. In this case, we're always going to use
662
+ // the child policy's result, so we pass its picker through as-is.
663
+ // 2. The serverlist contains only drop entries. In this case, we
664
+ // want to use our own picker so that we can return the drops.
665
+ // 3. Not in fallback mode and serverlist is not all drops (i.e., it
666
+ // may be empty or contain at least one backend address). There are
667
+ // two sub-cases:
668
+ // a. The child policy is reporting state READY. In this case, we wrap
669
+ // the child's picker in our own, so that we can handle drops and LB
670
+ // token metadata for each pick.
671
+ // b. The child policy is reporting a state other than READY. In this
672
+ // case, we don't want to use our own picker, because we don't want
673
+ // to process drops for picks that yield a QUEUE result; this would
674
+ // result in dropping too many calls, since we will see the
675
+ // queued picks multiple times, and we'd consider each one a
676
+ // separate call for the drop calculation.
677
+ //
678
+ // Cases 1 and 3b: return picker from the child policy as-is.
679
+ if (parent_->serverlist_ == nullptr ||
680
+ (!parent_->serverlist_->ContainsAllDropEntries() &&
681
+ state != GRPC_CHANNEL_READY)) {
682
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_glb_trace)) {
683
+ gpr_log(GPR_INFO,
684
+ "[grpclb %p helper %p] state=%s passing child picker %p as-is",
685
+ parent_.get(), this, grpc_connectivity_state_name(state),
686
+ picker.get());
687
+ }
688
+ parent_->channel_control_helper()->UpdateState(state, std::move(picker));
689
+ return;
690
+ }
691
+ // Cases 2 and 3a: wrap picker from the child in our own picker.
692
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_glb_trace)) {
693
+ gpr_log(GPR_INFO, "[grpclb %p helper %p] state=%s wrapping child picker %p",
694
+ parent_.get(), this, grpc_connectivity_state_name(state),
695
+ picker.get());
696
+ }
697
+ RefCountedPtr<GrpcLbClientStats> client_stats;
698
+ if (parent_->lb_calld_ != nullptr &&
699
+ parent_->lb_calld_->client_stats() != nullptr) {
700
+ client_stats = parent_->lb_calld_->client_stats()->Ref();
701
+ }
702
+ parent_->channel_control_helper()->UpdateState(
703
+ state, UniquePtr<SubchannelPicker>(
704
+ New<Picker>(parent_.get(), parent_->serverlist_,
705
+ std::move(picker), std::move(client_stats))));
706
+ }
707
+
708
+ void GrpcLb::Helper::RequestReresolution() {
709
+ if (parent_->shutting_down_) return;
710
+ const LoadBalancingPolicy* latest_child_policy =
711
+ parent_->pending_child_policy_ != nullptr
712
+ ? parent_->pending_child_policy_.get()
713
+ : parent_->child_policy_.get();
714
+ if (child_ != latest_child_policy) return;
715
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_glb_trace)) {
716
+ gpr_log(GPR_INFO,
717
+ "[grpclb %p] Re-resolution requested from %schild policy (%p).",
718
+ parent_.get(), CalledByPendingChild() ? "pending " : "", child_);
719
+ }
720
+ // If we are talking to a balancer, we expect to get updated addresses
721
+ // from the balancer, so we can ignore the re-resolution request from
722
+ // the child policy. Otherwise, pass the re-resolution request up to the
723
+ // channel.
724
+ if (parent_->lb_calld_ == nullptr ||
725
+ !parent_->lb_calld_->seen_initial_response()) {
726
+ parent_->channel_control_helper()->RequestReresolution();
727
+ }
728
+ }
729
+
730
+ void GrpcLb::Helper::AddTraceEvent(TraceSeverity severity,
731
+ const char* message) {
732
+ if (parent_->shutting_down_ ||
733
+ (!CalledByPendingChild() && !CalledByCurrentChild())) {
734
+ return;
735
+ }
736
+ parent_->channel_control_helper()->AddTraceEvent(severity, message);
737
+ }
738
+
461
739
  //
462
740
  // GrpcLb::BalancerCallState
463
741
  //
@@ -530,7 +808,7 @@ void GrpcLb::BalancerCallState::Orphan() {
530
808
 
531
809
  void GrpcLb::BalancerCallState::StartQuery() {
532
810
  GPR_ASSERT(lb_call_ != nullptr);
533
- if (grpc_lb_glb_trace.enabled()) {
811
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_glb_trace)) {
534
812
  gpr_log(GPR_INFO, "[grpclb %p] lb_calld=%p: Starting LB call %p",
535
813
  grpclb_policy_.get(), this, lb_call_);
536
814
  }
@@ -542,7 +820,8 @@ void GrpcLb::BalancerCallState::StartQuery() {
542
820
  grpc_op* op = ops;
543
821
  op->op = GRPC_OP_SEND_INITIAL_METADATA;
544
822
  op->data.send_initial_metadata.count = 0;
545
- op->flags = 0;
823
+ op->flags = GRPC_INITIAL_METADATA_WAIT_FOR_READY |
824
+ GRPC_INITIAL_METADATA_WAIT_FOR_READY_EXPLICITLY_SET;
546
825
  op->reserved = nullptr;
547
826
  op++;
548
827
  // Op: send request message.
@@ -598,7 +877,7 @@ void GrpcLb::BalancerCallState::StartQuery() {
598
877
  call_error = grpc_call_start_batch_and_execute(
599
878
  lb_call_, ops, (size_t)(op - ops), &lb_on_balancer_status_received_);
600
879
  GPR_ASSERT(GRPC_CALL_OK == call_error);
601
- };
880
+ }
602
881
 
603
882
  void GrpcLb::BalancerCallState::ScheduleNextClientLoadReportLocked() {
604
883
  const grpc_millis next_client_load_report_time =
@@ -647,7 +926,7 @@ void GrpcLb::BalancerCallState::SendClientLoadReportLocked() {
647
926
  // Construct message payload.
648
927
  GPR_ASSERT(send_message_payload_ == nullptr);
649
928
  grpc_grpclb_request* request =
650
- grpc_grpclb_load_report_request_create_locked(client_stats_.get());
929
+ grpc_grpclb_load_report_request_create(client_stats_.get());
651
930
  // Skip client load report if the counters were all zero in the last
652
931
  // report and they are still zero in this one.
653
932
  if (LoadReportCountersAreZero(request)) {
@@ -736,7 +1015,7 @@ void GrpcLb::BalancerCallState::OnBalancerMessageReceivedLocked(
736
1015
  lb_calld->client_stats_report_interval_ = GPR_MAX(
737
1016
  GPR_MS_PER_SEC, grpc_grpclb_duration_to_millis(
738
1017
  &initial_response->client_stats_report_interval));
739
- if (grpc_lb_glb_trace.enabled()) {
1018
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_glb_trace)) {
740
1019
  gpr_log(GPR_INFO,
741
1020
  "[grpclb %p] lb_calld=%p: Received initial LB response "
742
1021
  "message; client load reporting interval = %" PRId64
@@ -744,7 +1023,7 @@ void GrpcLb::BalancerCallState::OnBalancerMessageReceivedLocked(
744
1023
  grpclb_policy, lb_calld,
745
1024
  lb_calld->client_stats_report_interval_);
746
1025
  }
747
- } else if (grpc_lb_glb_trace.enabled()) {
1026
+ } else if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_glb_trace)) {
748
1027
  gpr_log(GPR_INFO,
749
1028
  "[grpclb %p] lb_calld=%p: Received initial LB response message; "
750
1029
  "client load reporting NOT enabled",
@@ -756,60 +1035,71 @@ void GrpcLb::BalancerCallState::OnBalancerMessageReceivedLocked(
756
1035
  response_slice)) != nullptr) {
757
1036
  // Have seen initial response, look for serverlist.
758
1037
  GPR_ASSERT(lb_calld->lb_call_ != nullptr);
759
- if (grpc_lb_glb_trace.enabled()) {
1038
+ auto serverlist_wrapper = MakeRefCounted<Serverlist>(serverlist);
1039
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_glb_trace)) {
1040
+ UniquePtr<char> serverlist_text = serverlist_wrapper->AsText();
760
1041
  gpr_log(GPR_INFO,
761
1042
  "[grpclb %p] lb_calld=%p: Serverlist with %" PRIuPTR
762
- " servers received",
763
- grpclb_policy, lb_calld, serverlist->num_servers);
764
- for (size_t i = 0; i < serverlist->num_servers; ++i) {
765
- grpc_resolved_address addr;
766
- ParseServer(serverlist->servers[i], &addr);
767
- char* ipport;
768
- grpc_sockaddr_to_string(&ipport, &addr, false);
769
- gpr_log(GPR_INFO,
770
- "[grpclb %p] lb_calld=%p: Serverlist[%" PRIuPTR "]: %s",
771
- grpclb_policy, lb_calld, i, ipport);
772
- gpr_free(ipport);
773
- }
1043
+ " servers received:\n%s",
1044
+ grpclb_policy, lb_calld, serverlist->num_servers,
1045
+ serverlist_text.get());
774
1046
  }
1047
+ lb_calld->seen_serverlist_ = true;
775
1048
  // Start sending client load report only after we start using the
776
1049
  // serverlist returned from the current LB call.
777
1050
  if (lb_calld->client_stats_report_interval_ > 0 &&
778
1051
  lb_calld->client_stats_ == nullptr) {
779
- lb_calld->client_stats_.reset(New<GrpcLbClientStats>());
780
- // TODO(roth): We currently track this ref manually. Once the
781
- // ClosureRef API is ready, we should pass the RefCountedPtr<> along
782
- // with the callback.
783
- auto self = lb_calld->Ref(DEBUG_LOCATION, "client_load_report");
784
- self.release();
1052
+ lb_calld->client_stats_ = MakeRefCounted<GrpcLbClientStats>();
1053
+ // Ref held by callback.
1054
+ lb_calld->Ref(DEBUG_LOCATION, "client_load_report").release();
785
1055
  lb_calld->ScheduleNextClientLoadReportLocked();
786
1056
  }
787
1057
  // Check if the serverlist differs from the previous one.
788
- if (grpc_grpclb_serverlist_equals(grpclb_policy->serverlist_, serverlist)) {
789
- if (grpc_lb_glb_trace.enabled()) {
1058
+ if (grpclb_policy->serverlist_ != nullptr &&
1059
+ *grpclb_policy->serverlist_ == *serverlist_wrapper) {
1060
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_glb_trace)) {
790
1061
  gpr_log(GPR_INFO,
791
1062
  "[grpclb %p] lb_calld=%p: Incoming server list identical to "
792
1063
  "current, ignoring.",
793
1064
  grpclb_policy, lb_calld);
794
1065
  }
795
- grpc_grpclb_destroy_serverlist(serverlist);
796
1066
  } else { // New serverlist.
797
- if (grpclb_policy->serverlist_ != nullptr) {
798
- // Dispose of the old serverlist.
799
- grpc_grpclb_destroy_serverlist(grpclb_policy->serverlist_);
800
- } else {
801
- // Dispose of the fallback.
802
- grpclb_policy->fallback_backend_addresses_.reset();
803
- if (grpclb_policy->fallback_timer_callback_pending_) {
804
- grpc_timer_cancel(&grpclb_policy->lb_fallback_timer_);
805
- }
1067
+ // Dispose of the fallback.
1068
+ // TODO(roth): Ideally, we should stay in fallback mode until we
1069
+ // know that we can reach at least one of the backends in the new
1070
+ // serverlist. Unfortunately, we can't do that, since we need to
1071
+ // send the new addresses to the child policy in order to determine
1072
+ // if they are reachable, and if we don't exit fallback mode now,
1073
+ // CreateOrUpdateChildPolicyLocked() will use the fallback
1074
+ // addresses instead of the addresses from the new serverlist.
1075
+ // However, if we can't reach any of the servers in the new
1076
+ // serverlist, then the child policy will never switch away from
1077
+ // the fallback addresses, but the grpclb policy will still think
1078
+ // that we're not in fallback mode, which means that we won't send
1079
+ // updates to the child policy when the fallback addresses are
1080
+ // updated by the resolver. This is sub-optimal, but the only way
1081
+ // to fix it is to maintain a completely separate child policy for
1082
+ // fallback mode, and that's more work than we want to put into
1083
+ // the grpclb implementation at this point, since we're deprecating
1084
+ // it in favor of the xds policy. We will implement this the
1085
+ // right way in the xds policy instead.
1086
+ if (grpclb_policy->fallback_mode_) {
1087
+ gpr_log(GPR_INFO,
1088
+ "[grpclb %p] Received response from balancer; exiting "
1089
+ "fallback mode",
1090
+ grpclb_policy);
1091
+ grpclb_policy->fallback_mode_ = false;
1092
+ }
1093
+ if (grpclb_policy->fallback_at_startup_checks_pending_) {
1094
+ grpclb_policy->fallback_at_startup_checks_pending_ = false;
1095
+ grpc_timer_cancel(&grpclb_policy->lb_fallback_timer_);
1096
+ grpclb_policy->CancelBalancerChannelConnectivityWatchLocked();
806
1097
  }
807
1098
  // Update the serverlist in the GrpcLb instance. This serverlist
808
1099
  // instance will be destroyed either upon the next update or when the
809
1100
  // GrpcLb instance is destroyed.
810
- grpclb_policy->serverlist_ = serverlist;
811
- grpclb_policy->serverlist_index_ = 0;
812
- grpclb_policy->CreateOrUpdateRoundRobinPolicyLocked();
1101
+ grpclb_policy->serverlist_ = std::move(serverlist_wrapper);
1102
+ grpclb_policy->CreateOrUpdateChildPolicyLocked();
813
1103
  }
814
1104
  } else {
815
1105
  // No valid initial response or serverlist found.
@@ -845,7 +1135,7 @@ void GrpcLb::BalancerCallState::OnBalancerStatusReceivedLocked(
845
1135
  BalancerCallState* lb_calld = static_cast<BalancerCallState*>(arg);
846
1136
  GrpcLb* grpclb_policy = lb_calld->grpclb_policy();
847
1137
  GPR_ASSERT(lb_calld->lb_call_ != nullptr);
848
- if (grpc_lb_glb_trace.enabled()) {
1138
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_glb_trace)) {
849
1139
  char* status_details =
850
1140
  grpc_slice_to_c_string(lb_calld->lb_call_status_details_);
851
1141
  gpr_log(GPR_INFO,
@@ -855,13 +1145,31 @@ void GrpcLb::BalancerCallState::OnBalancerStatusReceivedLocked(
855
1145
  lb_calld->lb_call_, grpc_error_string(error));
856
1146
  gpr_free(status_details);
857
1147
  }
858
- grpclb_policy->TryReresolutionLocked(&grpc_lb_glb_trace, GRPC_ERROR_NONE);
859
1148
  // If this lb_calld is still in use, this call ended because of a failure so
860
1149
  // we want to retry connecting. Otherwise, we have deliberately ended this
861
1150
  // call and no further action is required.
862
1151
  if (lb_calld == grpclb_policy->lb_calld_.get()) {
1152
+ // If the fallback-at-startup checks are pending, go into fallback mode
1153
+ // immediately. This short-circuits the timeout for the fallback-at-startup
1154
+ // case.
1155
+ if (grpclb_policy->fallback_at_startup_checks_pending_) {
1156
+ GPR_ASSERT(!lb_calld->seen_serverlist_);
1157
+ gpr_log(GPR_INFO,
1158
+ "[grpclb %p] Balancer call finished without receiving "
1159
+ "serverlist; entering fallback mode",
1160
+ grpclb_policy);
1161
+ grpclb_policy->fallback_at_startup_checks_pending_ = false;
1162
+ grpc_timer_cancel(&grpclb_policy->lb_fallback_timer_);
1163
+ grpclb_policy->CancelBalancerChannelConnectivityWatchLocked();
1164
+ grpclb_policy->fallback_mode_ = true;
1165
+ grpclb_policy->CreateOrUpdateChildPolicyLocked();
1166
+ } else {
1167
+ // This handles the fallback-after-startup case.
1168
+ grpclb_policy->MaybeEnterFallbackModeAfterStartup();
1169
+ }
863
1170
  grpclb_policy->lb_calld_.reset();
864
1171
  GPR_ASSERT(!grpclb_policy->shutting_down_);
1172
+ grpclb_policy->channel_control_helper()->RequestReresolution();
865
1173
  if (lb_calld->seen_initial_response_) {
866
1174
  // If we lose connection to the LB server, reset the backoff and restart
867
1175
  // the LB call immediately.
@@ -913,25 +1221,18 @@ grpc_channel_args* BuildBalancerChannelArgs(
913
1221
  const ServerAddressList& addresses,
914
1222
  FakeResolverResponseGenerator* response_generator,
915
1223
  const grpc_channel_args* args) {
916
- ServerAddressList balancer_addresses = ExtractBalancerAddresses(addresses);
917
1224
  // Channel args to remove.
918
1225
  static const char* args_to_remove[] = {
919
1226
  // LB policy name, since we want to use the default (pick_first) in
920
1227
  // the LB channel.
921
1228
  GRPC_ARG_LB_POLICY_NAME,
1229
+ // Strip out the service config, since we don't want the LB policy
1230
+ // config specified for the parent channel to affect the LB channel.
1231
+ GRPC_ARG_SERVICE_CONFIG,
922
1232
  // The channel arg for the server URI, since that will be different for
923
1233
  // the LB channel than for the parent channel. The client channel
924
1234
  // factory will re-add this arg with the right value.
925
1235
  GRPC_ARG_SERVER_URI,
926
- // The resolved addresses, which will be generated by the name resolver
927
- // used in the LB channel. Note that the LB channel will use the fake
928
- // resolver, so this won't actually generate a query to DNS (or some
929
- // other name service). However, the addresses returned by the fake
930
- // resolver will have is_balancer=false, whereas our own addresses have
931
- // is_balancer=true. We need the LB channel to return addresses with
932
- // is_balancer=false so that it does not wind up recursively using the
933
- // grpclb LB policy, as per the special case logic in client_channel.c.
934
- GRPC_ARG_SERVER_ADDRESS_LIST,
935
1236
  // The fake resolver response generator, because we are replacing it
936
1237
  // with the one from the grpclb policy, used to propagate updates to
937
1238
  // the LB channel.
@@ -944,39 +1245,44 @@ grpc_channel_args* BuildBalancerChannelArgs(
944
1245
  // treated as a stand-alone channel and not inherit this argument from the
945
1246
  // args of the parent channel.
946
1247
  GRPC_SSL_TARGET_NAME_OVERRIDE_ARG,
1248
+ // Don't want to pass down channelz node from parent; the balancer
1249
+ // channel will get its own.
1250
+ GRPC_ARG_CHANNELZ_CHANNEL_NODE,
947
1251
  };
948
1252
  // Channel args to add.
949
- const grpc_arg args_to_add[] = {
950
- // New address list.
951
- // Note that we pass these in both when creating the LB channel
952
- // and via the fake resolver. The latter is what actually gets used.
953
- CreateServerAddressListChannelArg(&balancer_addresses),
954
- // The fake resolver response generator, which we use to inject
955
- // address updates into the LB channel.
1253
+ InlinedVector<grpc_arg, 3> args_to_add;
1254
+ // The fake resolver response generator, which we use to inject
1255
+ // address updates into the LB channel.
1256
+ args_to_add.emplace_back(
956
1257
  grpc_core::FakeResolverResponseGenerator::MakeChannelArg(
957
- response_generator),
958
- // A channel arg indicating the target is a grpclb load balancer.
959
- grpc_channel_arg_integer_create(
960
- const_cast<char*>(GRPC_ARG_ADDRESS_IS_GRPCLB_LOAD_BALANCER), 1),
961
- // A channel arg indicating this is an internal channels, aka it is
962
- // owned by components in Core, not by the user application.
963
- grpc_channel_arg_integer_create(
964
- const_cast<char*>(GRPC_ARG_CHANNELZ_CHANNEL_IS_INTERNAL_CHANNEL), 1),
965
- };
1258
+ response_generator));
1259
+ // A channel arg indicating the target is a grpclb load balancer.
1260
+ args_to_add.emplace_back(grpc_channel_arg_integer_create(
1261
+ const_cast<char*>(GRPC_ARG_ADDRESS_IS_GRPCLB_LOAD_BALANCER), 1));
1262
+ // The parent channel's channelz uuid.
1263
+ channelz::ChannelNode* channelz_node = nullptr;
1264
+ const grpc_arg* arg =
1265
+ grpc_channel_args_find(args, GRPC_ARG_CHANNELZ_CHANNEL_NODE);
1266
+ if (arg != nullptr && arg->type == GRPC_ARG_POINTER &&
1267
+ arg->value.pointer.p != nullptr) {
1268
+ channelz_node = static_cast<channelz::ChannelNode*>(arg->value.pointer.p);
1269
+ args_to_add.emplace_back(
1270
+ channelz::MakeParentUuidArg(channelz_node->uuid()));
1271
+ }
966
1272
  // Construct channel args.
967
1273
  grpc_channel_args* new_args = grpc_channel_args_copy_and_add_and_remove(
968
- args, args_to_remove, GPR_ARRAY_SIZE(args_to_remove), args_to_add,
969
- GPR_ARRAY_SIZE(args_to_add));
1274
+ args, args_to_remove, GPR_ARRAY_SIZE(args_to_remove), args_to_add.data(),
1275
+ args_to_add.size());
970
1276
  // Make any necessary modifications for security.
971
- return grpc_lb_policy_grpclb_modify_lb_channel_args(new_args);
1277
+ return grpc_lb_policy_grpclb_modify_lb_channel_args(addresses, new_args);
972
1278
  }
973
1279
 
974
1280
  //
975
1281
  // ctor and dtor
976
1282
  //
977
1283
 
978
- GrpcLb::GrpcLb(const LoadBalancingPolicy::Args& args)
979
- : LoadBalancingPolicy(args),
1284
+ GrpcLb::GrpcLb(Args args)
1285
+ : LoadBalancingPolicy(std::move(args)),
980
1286
  response_generator_(MakeRefCounted<FakeResolverResponseGenerator>()),
981
1287
  lb_call_backoff_(
982
1288
  BackOff::Options()
@@ -987,18 +1293,11 @@ GrpcLb::GrpcLb(const LoadBalancingPolicy::Args& args)
987
1293
  .set_max_backoff(GRPC_GRPCLB_RECONNECT_MAX_BACKOFF_SECONDS *
988
1294
  1000)) {
989
1295
  // Initialization.
990
- gpr_mu_init(&lb_channel_mu_);
991
- grpc_subchannel_index_ref();
1296
+ GRPC_CLOSURE_INIT(&lb_on_fallback_, &GrpcLb::OnFallbackTimerLocked, this,
1297
+ grpc_combiner_scheduler(combiner()));
992
1298
  GRPC_CLOSURE_INIT(&lb_channel_on_connectivity_changed_,
993
1299
  &GrpcLb::OnBalancerChannelConnectivityChangedLocked, this,
994
1300
  grpc_combiner_scheduler(args.combiner));
995
- GRPC_CLOSURE_INIT(&on_rr_connectivity_changed_,
996
- &GrpcLb::OnRoundRobinConnectivityChangedLocked, this,
997
- grpc_combiner_scheduler(args.combiner));
998
- GRPC_CLOSURE_INIT(&on_rr_request_reresolution_,
999
- &GrpcLb::OnRoundRobinRequestReresolutionLocked, this,
1000
- grpc_combiner_scheduler(args.combiner));
1001
- grpc_connectivity_state_init(&state_tracker_, GRPC_CHANNEL_IDLE, "grpclb");
1002
1301
  // Record server name.
1003
1302
  const grpc_arg* arg = grpc_channel_args_find(args.args, GRPC_ARG_SERVER_URI);
1004
1303
  const char* server_uri = grpc_channel_arg_get_string(arg);
@@ -1006,7 +1305,7 @@ GrpcLb::GrpcLb(const LoadBalancingPolicy::Args& args)
1006
1305
  grpc_uri* uri = grpc_uri_parse(server_uri, true);
1007
1306
  GPR_ASSERT(uri->path[0] != '\0');
1008
1307
  server_name_ = gpr_strdup(uri->path[0] == '/' ? uri->path + 1 : uri->path);
1009
- if (grpc_lb_glb_trace.enabled()) {
1308
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_glb_trace)) {
1010
1309
  gpr_log(GPR_INFO,
1011
1310
  "[grpclb %p] Will use '%s' as the server name for LB request.",
1012
1311
  this, server_name_);
@@ -1015,234 +1314,115 @@ GrpcLb::GrpcLb(const LoadBalancingPolicy::Args& args)
1015
1314
  // Record LB call timeout.
1016
1315
  arg = grpc_channel_args_find(args.args, GRPC_ARG_GRPCLB_CALL_TIMEOUT_MS);
1017
1316
  lb_call_timeout_ms_ = grpc_channel_arg_get_integer(arg, {0, 0, INT_MAX});
1018
- // Record fallback timeout.
1317
+ // Record fallback-at-startup timeout.
1019
1318
  arg = grpc_channel_args_find(args.args, GRPC_ARG_GRPCLB_FALLBACK_TIMEOUT_MS);
1020
- lb_fallback_timeout_ms_ = grpc_channel_arg_get_integer(
1319
+ fallback_at_startup_timeout_ = grpc_channel_arg_get_integer(
1021
1320
  arg, {GRPC_GRPCLB_DEFAULT_FALLBACK_TIMEOUT_MS, 0, INT_MAX});
1022
- // Process channel args.
1023
- ProcessChannelArgsLocked(*args.args);
1024
1321
  }
1025
1322
 
1026
1323
  GrpcLb::~GrpcLb() {
1027
- GPR_ASSERT(pending_picks_ == nullptr);
1028
- gpr_mu_destroy(&lb_channel_mu_);
1029
1324
  gpr_free((void*)server_name_);
1030
1325
  grpc_channel_args_destroy(args_);
1031
- grpc_connectivity_state_destroy(&state_tracker_);
1032
- if (serverlist_ != nullptr) {
1033
- grpc_grpclb_destroy_serverlist(serverlist_);
1034
- }
1035
- grpc_subchannel_index_unref();
1036
1326
  }
1037
1327
 
1038
1328
  void GrpcLb::ShutdownLocked() {
1039
- grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Channel shutdown");
1040
1329
  shutting_down_ = true;
1041
1330
  lb_calld_.reset();
1042
1331
  if (retry_timer_callback_pending_) {
1043
1332
  grpc_timer_cancel(&lb_call_retry_timer_);
1044
1333
  }
1045
- if (fallback_timer_callback_pending_) {
1334
+ if (fallback_at_startup_checks_pending_) {
1046
1335
  grpc_timer_cancel(&lb_fallback_timer_);
1336
+ CancelBalancerChannelConnectivityWatchLocked();
1337
+ }
1338
+ if (child_policy_ != nullptr) {
1339
+ grpc_pollset_set_del_pollset_set(child_policy_->interested_parties(),
1340
+ interested_parties());
1341
+ }
1342
+ if (pending_child_policy_ != nullptr) {
1343
+ grpc_pollset_set_del_pollset_set(
1344
+ pending_child_policy_->interested_parties(), interested_parties());
1047
1345
  }
1048
- rr_policy_.reset();
1049
- TryReresolutionLocked(&grpc_lb_glb_trace, GRPC_ERROR_CANCELLED);
1346
+ child_policy_.reset();
1347
+ pending_child_policy_.reset();
1050
1348
  // We destroy the LB channel here instead of in our destructor because
1051
1349
  // destroying the channel triggers a last callback to
1052
1350
  // OnBalancerChannelConnectivityChangedLocked(), and we need to be
1053
1351
  // alive when that callback is invoked.
1054
1352
  if (lb_channel_ != nullptr) {
1055
- gpr_mu_lock(&lb_channel_mu_);
1056
1353
  grpc_channel_destroy(lb_channel_);
1057
1354
  lb_channel_ = nullptr;
1058
- gpr_mu_unlock(&lb_channel_mu_);
1059
1355
  }
1060
- grpc_connectivity_state_set(&state_tracker_, GRPC_CHANNEL_SHUTDOWN,
1061
- GRPC_ERROR_REF(error), "grpclb_shutdown");
1062
- // Clear pending picks.
1063
- PendingPick* pp;
1064
- while ((pp = pending_picks_) != nullptr) {
1065
- pending_picks_ = pp->next;
1066
- pp->pick->connected_subchannel.reset();
1067
- // Note: pp is deleted in this callback.
1068
- GRPC_CLOSURE_SCHED(&pp->on_complete, GRPC_ERROR_REF(error));
1069
- }
1070
- GRPC_ERROR_UNREF(error);
1071
1356
  }
1072
1357
 
1073
1358
  //
1074
1359
  // public methods
1075
1360
  //
1076
1361
 
1077
- void GrpcLb::HandOffPendingPicksLocked(LoadBalancingPolicy* new_policy) {
1078
- PendingPick* pp;
1079
- while ((pp = pending_picks_) != nullptr) {
1080
- pending_picks_ = pp->next;
1081
- pp->pick->on_complete = pp->original_on_complete;
1082
- grpc_error* error = GRPC_ERROR_NONE;
1083
- if (new_policy->PickLocked(pp->pick, &error)) {
1084
- // Synchronous return; schedule closure.
1085
- GRPC_CLOSURE_SCHED(pp->pick->on_complete, error);
1086
- }
1087
- Delete(pp);
1088
- }
1089
- }
1090
-
1091
- // Cancel a specific pending pick.
1092
- //
1093
- // A grpclb pick progresses as follows:
1094
- // - If there's a Round Robin policy (rr_policy_) available, it'll be
1095
- // handed over to the RR policy (in CreateRoundRobinPolicyLocked()). From
1096
- // that point onwards, it'll be RR's responsibility. For cancellations, that
1097
- // implies the pick needs also be cancelled by the RR instance.
1098
- // - Otherwise, without an RR instance, picks stay pending at this policy's
1099
- // level (grpclb), inside the pending_picks_ list. To cancel these,
1100
- // we invoke the completion closure and set the pick's connected
1101
- // subchannel to nullptr right here.
1102
- void GrpcLb::CancelPickLocked(PickState* pick, grpc_error* error) {
1103
- PendingPick* pp = pending_picks_;
1104
- pending_picks_ = nullptr;
1105
- while (pp != nullptr) {
1106
- PendingPick* next = pp->next;
1107
- if (pp->pick == pick) {
1108
- pick->connected_subchannel.reset();
1109
- // Note: pp is deleted in this callback.
1110
- GRPC_CLOSURE_SCHED(&pp->on_complete,
1111
- GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
1112
- "Pick Cancelled", &error, 1));
1113
- } else {
1114
- pp->next = pending_picks_;
1115
- pending_picks_ = pp;
1116
- }
1117
- pp = next;
1118
- }
1119
- if (rr_policy_ != nullptr) {
1120
- rr_policy_->CancelPickLocked(pick, GRPC_ERROR_REF(error));
1121
- }
1122
- GRPC_ERROR_UNREF(error);
1123
- }
1124
-
1125
- // Cancel all pending picks.
1126
- //
1127
- // A grpclb pick progresses as follows:
1128
- // - If there's a Round Robin policy (rr_policy_) available, it'll be
1129
- // handed over to the RR policy (in CreateRoundRobinPolicyLocked()). From
1130
- // that point onwards, it'll be RR's responsibility. For cancellations, that
1131
- // implies the pick needs also be cancelled by the RR instance.
1132
- // - Otherwise, without an RR instance, picks stay pending at this policy's
1133
- // level (grpclb), inside the pending_picks_ list. To cancel these,
1134
- // we invoke the completion closure and set the pick's connected
1135
- // subchannel to nullptr right here.
1136
- void GrpcLb::CancelMatchingPicksLocked(uint32_t initial_metadata_flags_mask,
1137
- uint32_t initial_metadata_flags_eq,
1138
- grpc_error* error) {
1139
- PendingPick* pp = pending_picks_;
1140
- pending_picks_ = nullptr;
1141
- while (pp != nullptr) {
1142
- PendingPick* next = pp->next;
1143
- if ((*pp->pick->initial_metadata_flags & initial_metadata_flags_mask) ==
1144
- initial_metadata_flags_eq) {
1145
- // Note: pp is deleted in this callback.
1146
- GRPC_CLOSURE_SCHED(&pp->on_complete,
1147
- GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
1148
- "Pick Cancelled", &error, 1));
1149
- } else {
1150
- pp->next = pending_picks_;
1151
- pending_picks_ = pp;
1152
- }
1153
- pp = next;
1154
- }
1155
- if (rr_policy_ != nullptr) {
1156
- rr_policy_->CancelMatchingPicksLocked(initial_metadata_flags_mask,
1157
- initial_metadata_flags_eq,
1158
- GRPC_ERROR_REF(error));
1159
- }
1160
- GRPC_ERROR_UNREF(error);
1161
- }
1162
-
1163
- void GrpcLb::ExitIdleLocked() {
1164
- if (!started_picking_) {
1165
- StartPickingLocked();
1166
- }
1167
- }
1168
-
1169
1362
  void GrpcLb::ResetBackoffLocked() {
1170
1363
  if (lb_channel_ != nullptr) {
1171
1364
  grpc_channel_reset_connect_backoff(lb_channel_);
1172
1365
  }
1173
- if (rr_policy_ != nullptr) {
1174
- rr_policy_->ResetBackoffLocked();
1366
+ if (child_policy_ != nullptr) {
1367
+ child_policy_->ResetBackoffLocked();
1175
1368
  }
1176
- }
1177
-
1178
- bool GrpcLb::PickLocked(PickState* pick, grpc_error** error) {
1179
- PendingPick* pp = PendingPickCreate(pick);
1180
- bool pick_done = false;
1181
- if (rr_policy_ != nullptr) {
1182
- if (grpc_lb_glb_trace.enabled()) {
1183
- gpr_log(GPR_INFO, "[grpclb %p] about to PICK from RR %p", this,
1184
- rr_policy_.get());
1185
- }
1186
- pick_done =
1187
- PickFromRoundRobinPolicyLocked(false /* force_async */, pp, error);
1188
- } else { // rr_policy_ == NULL
1189
- if (pick->on_complete == nullptr) {
1190
- *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
1191
- "No pick result available but synchronous result required.");
1192
- pick_done = true;
1193
- } else {
1194
- if (grpc_lb_glb_trace.enabled()) {
1195
- gpr_log(GPR_INFO,
1196
- "[grpclb %p] No RR policy. Adding to grpclb's pending picks",
1197
- this);
1198
- }
1199
- AddPendingPick(pp);
1200
- if (!started_picking_) {
1201
- StartPickingLocked();
1202
- }
1203
- pick_done = false;
1204
- }
1369
+ if (pending_child_policy_ != nullptr) {
1370
+ pending_child_policy_->ResetBackoffLocked();
1205
1371
  }
1206
- return pick_done;
1207
1372
  }
1208
1373
 
1209
- void GrpcLb::FillChildRefsForChannelz(
1210
- channelz::ChildRefsList* child_subchannels,
1211
- channelz::ChildRefsList* child_channels) {
1212
- // delegate to the RoundRobin to fill the children subchannels.
1213
- rr_policy_->FillChildRefsForChannelz(child_subchannels, child_channels);
1214
- MutexLock lock(&lb_channel_mu_);
1215
- if (lb_channel_ != nullptr) {
1216
- grpc_core::channelz::ChannelNode* channel_node =
1217
- grpc_channel_get_channelz_node(lb_channel_);
1218
- if (channel_node != nullptr) {
1219
- child_channels->push_back(channel_node->uuid());
1220
- }
1374
+ void GrpcLb::UpdateLocked(UpdateArgs args) {
1375
+ const bool is_initial_update = lb_channel_ == nullptr;
1376
+ auto* grpclb_config =
1377
+ static_cast<const ParsedGrpcLbConfig*>(args.config.get());
1378
+ if (grpclb_config != nullptr) {
1379
+ child_policy_config_ = grpclb_config->child_policy();
1380
+ } else {
1381
+ child_policy_config_ = nullptr;
1382
+ }
1383
+ ProcessAddressesAndChannelArgsLocked(args.addresses, *args.args);
1384
+ // Update the existing child policy.
1385
+ if (child_policy_ != nullptr) CreateOrUpdateChildPolicyLocked();
1386
+ // If this is the initial update, start the fallback-at-startup checks
1387
+ // and the balancer call.
1388
+ if (is_initial_update) {
1389
+ fallback_at_startup_checks_pending_ = true;
1390
+ // Start timer.
1391
+ grpc_millis deadline = ExecCtx::Get()->Now() + fallback_at_startup_timeout_;
1392
+ Ref(DEBUG_LOCATION, "on_fallback_timer").release(); // Ref for callback
1393
+ grpc_timer_init(&lb_fallback_timer_, deadline, &lb_on_fallback_);
1394
+ // Start watching the channel's connectivity state. If the channel
1395
+ // goes into state TRANSIENT_FAILURE before the timer fires, we go into
1396
+ // fallback mode even if the fallback timeout has not elapsed.
1397
+ grpc_channel_element* client_channel_elem = grpc_channel_stack_last_element(
1398
+ grpc_channel_get_channel_stack(lb_channel_));
1399
+ GPR_ASSERT(client_channel_elem->filter == &grpc_client_channel_filter);
1400
+ // Ref held by callback.
1401
+ Ref(DEBUG_LOCATION, "watch_lb_channel_connectivity").release();
1402
+ grpc_client_channel_watch_connectivity_state(
1403
+ client_channel_elem,
1404
+ grpc_polling_entity_create_from_pollset_set(interested_parties()),
1405
+ &lb_channel_connectivity_, &lb_channel_on_connectivity_changed_,
1406
+ nullptr);
1407
+ // Start balancer call.
1408
+ StartBalancerCallLocked();
1221
1409
  }
1222
1410
  }
1223
1411
 
1224
- grpc_connectivity_state GrpcLb::CheckConnectivityLocked(
1225
- grpc_error** connectivity_error) {
1226
- return grpc_connectivity_state_get(&state_tracker_, connectivity_error);
1227
- }
1228
-
1229
- void GrpcLb::NotifyOnStateChangeLocked(grpc_connectivity_state* current,
1230
- grpc_closure* notify) {
1231
- grpc_connectivity_state_notify_on_state_change(&state_tracker_, current,
1232
- notify);
1233
- }
1412
+ //
1413
+ // helpers for UpdateLocked()
1414
+ //
1234
1415
 
1235
1416
  // Returns the backend addresses extracted from the given addresses.
1236
- UniquePtr<ServerAddressList> ExtractBackendAddresses(
1237
- const ServerAddressList& addresses) {
1417
+ ServerAddressList ExtractBackendAddresses(const ServerAddressList& addresses) {
1238
1418
  void* lb_token = (void*)GRPC_MDELEM_LB_TOKEN_EMPTY.payload;
1239
1419
  grpc_arg arg = grpc_channel_arg_pointer_create(
1240
1420
  const_cast<char*>(GRPC_ARG_GRPCLB_ADDRESS_LB_TOKEN), lb_token,
1241
1421
  &lb_token_arg_vtable);
1242
- auto backend_addresses = MakeUnique<ServerAddressList>();
1422
+ ServerAddressList backend_addresses;
1243
1423
  for (size_t i = 0; i < addresses.size(); ++i) {
1244
1424
  if (!addresses[i].IsBalancer()) {
1245
- backend_addresses->emplace_back(
1425
+ backend_addresses.emplace_back(
1246
1426
  addresses[i].address(),
1247
1427
  grpc_channel_args_copy_and_add(addresses[i].args(), &arg, 1));
1248
1428
  }
@@ -1250,18 +1430,10 @@ UniquePtr<ServerAddressList> ExtractBackendAddresses(
1250
1430
  return backend_addresses;
1251
1431
  }
1252
1432
 
1253
- void GrpcLb::ProcessChannelArgsLocked(const grpc_channel_args& args) {
1254
- const ServerAddressList* addresses = FindServerAddressListChannelArg(&args);
1255
- if (addresses == nullptr) {
1256
- // Ignore this update.
1257
- gpr_log(
1258
- GPR_ERROR,
1259
- "[grpclb %p] No valid LB addresses channel arg in update, ignoring.",
1260
- this);
1261
- return;
1262
- }
1433
+ void GrpcLb::ProcessAddressesAndChannelArgsLocked(
1434
+ const ServerAddressList& addresses, const grpc_channel_args& args) {
1263
1435
  // Update fallback address list.
1264
- fallback_backend_addresses_ = ExtractBackendAddresses(*addresses);
1436
+ fallback_backend_addresses_ = ExtractBackendAddresses(addresses);
1265
1437
  // Make sure that GRPC_ARG_LB_POLICY_NAME is set in channel args,
1266
1438
  // since we use this to trigger the client_load_reporting filter.
1267
1439
  static const char* args_to_remove[] = {GRPC_ARG_LB_POLICY_NAME};
@@ -1271,82 +1443,80 @@ void GrpcLb::ProcessChannelArgsLocked(const grpc_channel_args& args) {
1271
1443
  args_ = grpc_channel_args_copy_and_add_and_remove(
1272
1444
  &args, args_to_remove, GPR_ARRAY_SIZE(args_to_remove), &new_arg, 1);
1273
1445
  // Construct args for balancer channel.
1274
- grpc_channel_args* lb_channel_args =
1275
- BuildBalancerChannelArgs(*addresses, response_generator_.get(), &args);
1446
+ ServerAddressList balancer_addresses = ExtractBalancerAddresses(addresses);
1447
+ grpc_channel_args* lb_channel_args = BuildBalancerChannelArgs(
1448
+ balancer_addresses, response_generator_.get(), &args);
1276
1449
  // Create balancer channel if needed.
1277
1450
  if (lb_channel_ == nullptr) {
1278
1451
  char* uri_str;
1279
1452
  gpr_asprintf(&uri_str, "fake:///%s", server_name_);
1280
- gpr_mu_lock(&lb_channel_mu_);
1281
- lb_channel_ = grpc_client_channel_factory_create_channel(
1282
- client_channel_factory(), uri_str,
1283
- GRPC_CLIENT_CHANNEL_TYPE_LOAD_BALANCING, lb_channel_args);
1284
- gpr_mu_unlock(&lb_channel_mu_);
1453
+ lb_channel_ =
1454
+ channel_control_helper()->CreateChannel(uri_str, *lb_channel_args);
1285
1455
  GPR_ASSERT(lb_channel_ != nullptr);
1286
1456
  gpr_free(uri_str);
1287
1457
  }
1288
1458
  // Propagate updates to the LB channel (pick_first) through the fake
1289
1459
  // resolver.
1290
- response_generator_->SetResponse(lb_channel_args);
1291
- grpc_channel_args_destroy(lb_channel_args);
1460
+ Resolver::Result result;
1461
+ result.addresses = std::move(balancer_addresses);
1462
+ result.args = lb_channel_args;
1463
+ response_generator_->SetResponse(std::move(result));
1292
1464
  }
1293
1465
 
1294
- void GrpcLb::UpdateLocked(const grpc_channel_args& args, grpc_json* lb_config) {
1295
- ProcessChannelArgsLocked(args);
1296
- // Update the existing RR policy.
1297
- if (rr_policy_ != nullptr) CreateOrUpdateRoundRobinPolicyLocked();
1298
- // Start watching the LB channel connectivity for connection, if not
1299
- // already doing so.
1300
- if (!watching_lb_channel_) {
1301
- lb_channel_connectivity_ = grpc_channel_check_connectivity_state(
1302
- lb_channel_, true /* try to connect */);
1303
- grpc_channel_element* client_channel_elem = grpc_channel_stack_last_element(
1304
- grpc_channel_get_channel_stack(lb_channel_));
1305
- GPR_ASSERT(client_channel_elem->filter == &grpc_client_channel_filter);
1306
- watching_lb_channel_ = true;
1307
- // TODO(roth): We currently track this ref manually. Once the
1308
- // ClosureRef API is ready, we should pass the RefCountedPtr<> along
1309
- // with the callback.
1310
- auto self = Ref(DEBUG_LOCATION, "watch_lb_channel_connectivity");
1311
- self.release();
1312
- grpc_client_channel_watch_connectivity_state(
1313
- client_channel_elem,
1314
- grpc_polling_entity_create_from_pollset_set(interested_parties()),
1315
- &lb_channel_connectivity_, &lb_channel_on_connectivity_changed_,
1316
- nullptr);
1466
+ void GrpcLb::OnBalancerChannelConnectivityChangedLocked(void* arg,
1467
+ grpc_error* error) {
1468
+ GrpcLb* self = static_cast<GrpcLb*>(arg);
1469
+ if (!self->shutting_down_ && self->fallback_at_startup_checks_pending_) {
1470
+ if (self->lb_channel_connectivity_ != GRPC_CHANNEL_TRANSIENT_FAILURE) {
1471
+ // Not in TRANSIENT_FAILURE. Renew connectivity watch.
1472
+ grpc_channel_element* client_channel_elem =
1473
+ grpc_channel_stack_last_element(
1474
+ grpc_channel_get_channel_stack(self->lb_channel_));
1475
+ GPR_ASSERT(client_channel_elem->filter == &grpc_client_channel_filter);
1476
+ grpc_client_channel_watch_connectivity_state(
1477
+ client_channel_elem,
1478
+ grpc_polling_entity_create_from_pollset_set(
1479
+ self->interested_parties()),
1480
+ &self->lb_channel_connectivity_,
1481
+ &self->lb_channel_on_connectivity_changed_, nullptr);
1482
+ return; // Early out so we don't drop the ref below.
1483
+ }
1484
+ // In TRANSIENT_FAILURE. Cancel the fallback timer and go into
1485
+ // fallback mode immediately.
1486
+ gpr_log(GPR_INFO,
1487
+ "[grpclb %p] balancer channel in state TRANSIENT_FAILURE; "
1488
+ "entering fallback mode",
1489
+ self);
1490
+ self->fallback_at_startup_checks_pending_ = false;
1491
+ grpc_timer_cancel(&self->lb_fallback_timer_);
1492
+ self->fallback_mode_ = true;
1493
+ self->CreateOrUpdateChildPolicyLocked();
1317
1494
  }
1495
+ // Done watching connectivity state, so drop ref.
1496
+ self->Unref(DEBUG_LOCATION, "watch_lb_channel_connectivity");
1497
+ }
1498
+
1499
+ void GrpcLb::CancelBalancerChannelConnectivityWatchLocked() {
1500
+ grpc_channel_element* client_channel_elem = grpc_channel_stack_last_element(
1501
+ grpc_channel_get_channel_stack(lb_channel_));
1502
+ GPR_ASSERT(client_channel_elem->filter == &grpc_client_channel_filter);
1503
+ grpc_client_channel_watch_connectivity_state(
1504
+ client_channel_elem,
1505
+ grpc_polling_entity_create_from_pollset_set(interested_parties()),
1506
+ nullptr, &lb_channel_on_connectivity_changed_, nullptr);
1318
1507
  }
1319
1508
 
1320
1509
  //
1321
1510
  // code for balancer channel and call
1322
1511
  //
1323
1512
 
1324
- void GrpcLb::StartPickingLocked() {
1325
- // Start a timer to fall back.
1326
- if (lb_fallback_timeout_ms_ > 0 && serverlist_ == nullptr &&
1327
- !fallback_timer_callback_pending_) {
1328
- grpc_millis deadline = ExecCtx::Get()->Now() + lb_fallback_timeout_ms_;
1329
- // TODO(roth): We currently track this ref manually. Once the
1330
- // ClosureRef API is ready, we should pass the RefCountedPtr<> along
1331
- // with the callback.
1332
- auto self = Ref(DEBUG_LOCATION, "on_fallback_timer");
1333
- self.release();
1334
- GRPC_CLOSURE_INIT(&lb_on_fallback_, &GrpcLb::OnFallbackTimerLocked, this,
1335
- grpc_combiner_scheduler(combiner()));
1336
- fallback_timer_callback_pending_ = true;
1337
- grpc_timer_init(&lb_fallback_timer_, deadline, &lb_on_fallback_);
1338
- }
1339
- started_picking_ = true;
1340
- StartBalancerCallLocked();
1341
- }
1342
-
1343
1513
  void GrpcLb::StartBalancerCallLocked() {
1344
1514
  GPR_ASSERT(lb_channel_ != nullptr);
1345
1515
  if (shutting_down_) return;
1346
1516
  // Init the LB call data.
1347
1517
  GPR_ASSERT(lb_calld_ == nullptr);
1348
1518
  lb_calld_ = MakeOrphanable<BalancerCallState>(Ref());
1349
- if (grpc_lb_glb_trace.enabled()) {
1519
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_glb_trace)) {
1350
1520
  gpr_log(GPR_INFO,
1351
1521
  "[grpclb %p] Query for backends (lb_channel: %p, lb_calld: %p)",
1352
1522
  this, lb_channel_, lb_calld_.get());
@@ -1354,27 +1524,9 @@ void GrpcLb::StartBalancerCallLocked() {
1354
1524
  lb_calld_->StartQuery();
1355
1525
  }
1356
1526
 
1357
- void GrpcLb::OnFallbackTimerLocked(void* arg, grpc_error* error) {
1358
- GrpcLb* grpclb_policy = static_cast<GrpcLb*>(arg);
1359
- grpclb_policy->fallback_timer_callback_pending_ = false;
1360
- // If we receive a serverlist after the timer fires but before this callback
1361
- // actually runs, don't fall back.
1362
- if (grpclb_policy->serverlist_ == nullptr && !grpclb_policy->shutting_down_ &&
1363
- error == GRPC_ERROR_NONE) {
1364
- if (grpc_lb_glb_trace.enabled()) {
1365
- gpr_log(GPR_INFO,
1366
- "[grpclb %p] Falling back to use backends from resolver",
1367
- grpclb_policy);
1368
- }
1369
- GPR_ASSERT(grpclb_policy->fallback_backend_addresses_ != nullptr);
1370
- grpclb_policy->CreateOrUpdateRoundRobinPolicyLocked();
1371
- }
1372
- grpclb_policy->Unref(DEBUG_LOCATION, "on_fallback_timer");
1373
- }
1374
-
1375
1527
  void GrpcLb::StartBalancerCallRetryTimerLocked() {
1376
1528
  grpc_millis next_try = lb_call_backoff_.NextAttemptTime();
1377
- if (grpc_lb_glb_trace.enabled()) {
1529
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_glb_trace)) {
1378
1530
  gpr_log(GPR_INFO, "[grpclb %p] Connection to LB server lost...", this);
1379
1531
  grpc_millis timeout = next_try - ExecCtx::Get()->Now();
1380
1532
  if (timeout > 0) {
@@ -1401,7 +1553,7 @@ void GrpcLb::OnBalancerCallRetryTimerLocked(void* arg, grpc_error* error) {
1401
1553
  grpclb_policy->retry_timer_callback_pending_ = false;
1402
1554
  if (!grpclb_policy->shutting_down_ && error == GRPC_ERROR_NONE &&
1403
1555
  grpclb_policy->lb_calld_ == nullptr) {
1404
- if (grpc_lb_glb_trace.enabled()) {
1556
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_glb_trace)) {
1405
1557
  gpr_log(GPR_INFO, "[grpclb %p] Restarting call to LB server",
1406
1558
  grpclb_policy);
1407
1559
  }
@@ -1410,394 +1562,205 @@ void GrpcLb::OnBalancerCallRetryTimerLocked(void* arg, grpc_error* error) {
1410
1562
  grpclb_policy->Unref(DEBUG_LOCATION, "on_balancer_call_retry_timer");
1411
1563
  }
1412
1564
 
1413
- // Invoked as part of the update process. It continues watching the LB channel
1414
- // until it shuts down or becomes READY. It's invoked even if the LB channel
1415
- // stayed READY throughout the update (for example if the update is identical).
1416
- void GrpcLb::OnBalancerChannelConnectivityChangedLocked(void* arg,
1417
- grpc_error* error) {
1418
- GrpcLb* grpclb_policy = static_cast<GrpcLb*>(arg);
1419
- if (grpclb_policy->shutting_down_) goto done;
1420
- // Re-initialize the lb_call. This should also take care of updating the
1421
- // embedded RR policy. Note that the current RR policy, if any, will stay in
1422
- // effect until an update from the new lb_call is received.
1423
- switch (grpclb_policy->lb_channel_connectivity_) {
1424
- case GRPC_CHANNEL_CONNECTING:
1425
- case GRPC_CHANNEL_TRANSIENT_FAILURE: {
1426
- // Keep watching the LB channel.
1427
- grpc_channel_element* client_channel_elem =
1428
- grpc_channel_stack_last_element(
1429
- grpc_channel_get_channel_stack(grpclb_policy->lb_channel_));
1430
- GPR_ASSERT(client_channel_elem->filter == &grpc_client_channel_filter);
1431
- grpc_client_channel_watch_connectivity_state(
1432
- client_channel_elem,
1433
- grpc_polling_entity_create_from_pollset_set(
1434
- grpclb_policy->interested_parties()),
1435
- &grpclb_policy->lb_channel_connectivity_,
1436
- &grpclb_policy->lb_channel_on_connectivity_changed_, nullptr);
1437
- break;
1438
- }
1439
- // The LB channel may be IDLE because it's shut down before the update.
1440
- // Restart the LB call to kick the LB channel into gear.
1441
- case GRPC_CHANNEL_IDLE:
1442
- case GRPC_CHANNEL_READY:
1443
- grpclb_policy->lb_calld_.reset();
1444
- if (grpclb_policy->started_picking_) {
1445
- if (grpclb_policy->retry_timer_callback_pending_) {
1446
- grpc_timer_cancel(&grpclb_policy->lb_call_retry_timer_);
1447
- }
1448
- grpclb_policy->lb_call_backoff_.Reset();
1449
- grpclb_policy->StartBalancerCallLocked();
1450
- }
1451
- // fallthrough
1452
- case GRPC_CHANNEL_SHUTDOWN:
1453
- done:
1454
- grpclb_policy->watching_lb_channel_ = false;
1455
- grpclb_policy->Unref(DEBUG_LOCATION,
1456
- "watch_lb_channel_connectivity_cb_shutdown");
1457
- }
1458
- }
1459
-
1460
1565
  //
1461
- // PendingPick
1566
+ // code for handling fallback mode
1462
1567
  //
1463
1568
 
1464
- // Adds lb_token of selected subchannel (address) to the call's initial
1465
- // metadata.
1466
- grpc_error* AddLbTokenToInitialMetadata(
1467
- grpc_mdelem lb_token, grpc_linked_mdelem* lb_token_mdelem_storage,
1468
- grpc_metadata_batch* initial_metadata) {
1469
- GPR_ASSERT(lb_token_mdelem_storage != nullptr);
1470
- GPR_ASSERT(!GRPC_MDISNULL(lb_token));
1471
- return grpc_metadata_batch_add_tail(initial_metadata, lb_token_mdelem_storage,
1472
- lb_token);
1473
- }
1474
-
1475
- // Destroy function used when embedding client stats in call context.
1476
- void DestroyClientStats(void* arg) {
1477
- static_cast<GrpcLbClientStats*>(arg)->Unref();
1478
- }
1479
-
1480
- void GrpcLb::PendingPickSetMetadataAndContext(PendingPick* pp) {
1481
- // If connected_subchannel is nullptr, no pick has been made by the RR
1482
- // policy (e.g., all addresses failed to connect). There won't be any
1483
- // LB token available.
1484
- if (pp->pick->connected_subchannel != nullptr) {
1485
- const grpc_arg* arg =
1486
- grpc_channel_args_find(pp->pick->connected_subchannel->args(),
1487
- GRPC_ARG_GRPCLB_ADDRESS_LB_TOKEN);
1488
- if (arg != nullptr) {
1489
- grpc_mdelem lb_token = {
1490
- reinterpret_cast<uintptr_t>(arg->value.pointer.p)};
1491
- AddLbTokenToInitialMetadata(GRPC_MDELEM_REF(lb_token),
1492
- &pp->pick->lb_token_mdelem_storage,
1493
- pp->pick->initial_metadata);
1494
- } else {
1495
- gpr_log(GPR_ERROR,
1496
- "[grpclb %p] No LB token for connected subchannel pick %p",
1497
- pp->grpclb_policy, pp->pick);
1498
- abort();
1499
- }
1500
- // Pass on client stats via context. Passes ownership of the reference.
1501
- if (pp->client_stats != nullptr) {
1502
- pp->pick->subchannel_call_context[GRPC_GRPCLB_CLIENT_STATS].value =
1503
- pp->client_stats.release();
1504
- pp->pick->subchannel_call_context[GRPC_GRPCLB_CLIENT_STATS].destroy =
1505
- DestroyClientStats;
1506
- }
1507
- } else {
1508
- pp->client_stats.reset();
1569
+ void GrpcLb::MaybeEnterFallbackModeAfterStartup() {
1570
+ // Enter fallback mode if all of the following are true:
1571
+ // - We are not currently in fallback mode.
1572
+ // - We are not currently waiting for the initial fallback timeout.
1573
+ // - We are not currently in contact with the balancer.
1574
+ // - The child policy is not in state READY.
1575
+ if (!fallback_mode_ && !fallback_at_startup_checks_pending_ &&
1576
+ (lb_calld_ == nullptr || !lb_calld_->seen_serverlist()) &&
1577
+ !child_policy_ready_) {
1578
+ gpr_log(GPR_INFO,
1579
+ "[grpclb %p] lost contact with balancer and backends from "
1580
+ "most recent serverlist; entering fallback mode",
1581
+ this);
1582
+ fallback_mode_ = true;
1583
+ CreateOrUpdateChildPolicyLocked();
1509
1584
  }
1510
1585
  }
1511
1586
 
1512
- /* The \a on_complete closure passed as part of the pick requires keeping a
1513
- * reference to its associated round robin instance. We wrap this closure in
1514
- * order to unref the round robin instance upon its invocation */
1515
- void GrpcLb::OnPendingPickComplete(void* arg, grpc_error* error) {
1516
- PendingPick* pp = static_cast<PendingPick*>(arg);
1517
- PendingPickSetMetadataAndContext(pp);
1518
- GRPC_CLOSURE_SCHED(pp->original_on_complete, GRPC_ERROR_REF(error));
1519
- Delete(pp);
1520
- }
1521
-
1522
- GrpcLb::PendingPick* GrpcLb::PendingPickCreate(PickState* pick) {
1523
- PendingPick* pp = New<PendingPick>();
1524
- pp->grpclb_policy = this;
1525
- pp->pick = pick;
1526
- GRPC_CLOSURE_INIT(&pp->on_complete, &GrpcLb::OnPendingPickComplete, pp,
1527
- grpc_schedule_on_exec_ctx);
1528
- pp->original_on_complete = pick->on_complete;
1529
- pick->on_complete = &pp->on_complete;
1530
- return pp;
1531
- }
1532
-
1533
- void GrpcLb::AddPendingPick(PendingPick* pp) {
1534
- pp->next = pending_picks_;
1535
- pending_picks_ = pp;
1587
+ void GrpcLb::OnFallbackTimerLocked(void* arg, grpc_error* error) {
1588
+ GrpcLb* grpclb_policy = static_cast<GrpcLb*>(arg);
1589
+ // If we receive a serverlist after the timer fires but before this callback
1590
+ // actually runs, don't fall back.
1591
+ if (grpclb_policy->fallback_at_startup_checks_pending_ &&
1592
+ !grpclb_policy->shutting_down_ && error == GRPC_ERROR_NONE) {
1593
+ gpr_log(GPR_INFO,
1594
+ "[grpclb %p] No response from balancer after fallback timeout; "
1595
+ "entering fallback mode",
1596
+ grpclb_policy);
1597
+ grpclb_policy->fallback_at_startup_checks_pending_ = false;
1598
+ grpclb_policy->CancelBalancerChannelConnectivityWatchLocked();
1599
+ grpclb_policy->fallback_mode_ = true;
1600
+ grpclb_policy->CreateOrUpdateChildPolicyLocked();
1601
+ }
1602
+ grpclb_policy->Unref(DEBUG_LOCATION, "on_fallback_timer");
1536
1603
  }
1537
1604
 
1538
1605
  //
1539
- // code for interacting with the RR policy
1606
+ // code for interacting with the child policy
1540
1607
  //
1541
1608
 
1542
- // Performs a pick over \a rr_policy_. Given that a pick can return
1543
- // immediately (ignoring its completion callback), we need to perform the
1544
- // cleanups this callback would otherwise be responsible for.
1545
- // If \a force_async is true, then we will manually schedule the
1546
- // completion callback even if the pick is available immediately.
1547
- bool GrpcLb::PickFromRoundRobinPolicyLocked(bool force_async, PendingPick* pp,
1548
- grpc_error** error) {
1549
- // Check for drops if we are not using fallback backend addresses.
1550
- if (serverlist_ != nullptr && serverlist_->num_servers > 0) {
1551
- // Look at the index into the serverlist to see if we should drop this call.
1552
- grpc_grpclb_server* server = serverlist_->servers[serverlist_index_++];
1553
- if (serverlist_index_ == serverlist_->num_servers) {
1554
- serverlist_index_ = 0; // Wrap-around.
1555
- }
1556
- if (server->drop) {
1557
- // Update client load reporting stats to indicate the number of
1558
- // dropped calls. Note that we have to do this here instead of in
1559
- // the client_load_reporting filter, because we do not create a
1560
- // subchannel call (and therefore no client_load_reporting filter)
1561
- // for dropped calls.
1562
- if (lb_calld_ != nullptr && lb_calld_->client_stats() != nullptr) {
1563
- lb_calld_->client_stats()->AddCallDroppedLocked(
1564
- server->load_balance_token);
1565
- }
1566
- if (force_async) {
1567
- GRPC_CLOSURE_SCHED(pp->original_on_complete, GRPC_ERROR_NONE);
1568
- Delete(pp);
1569
- return false;
1570
- }
1571
- Delete(pp);
1572
- return true;
1573
- }
1574
- }
1575
- // Set client_stats.
1576
- if (lb_calld_ != nullptr && lb_calld_->client_stats() != nullptr) {
1577
- pp->client_stats = lb_calld_->client_stats()->Ref();
1578
- }
1579
- // Pick via the RR policy.
1580
- bool pick_done = rr_policy_->PickLocked(pp->pick, error);
1581
- if (pick_done) {
1582
- PendingPickSetMetadataAndContext(pp);
1583
- if (force_async) {
1584
- GRPC_CLOSURE_SCHED(pp->original_on_complete, *error);
1585
- *error = GRPC_ERROR_NONE;
1586
- pick_done = false;
1587
- }
1588
- Delete(pp);
1609
+ grpc_channel_args* GrpcLb::CreateChildPolicyArgsLocked(
1610
+ bool is_backend_from_grpclb_load_balancer) {
1611
+ InlinedVector<grpc_arg, 2> args_to_add;
1612
+ args_to_add.emplace_back(grpc_channel_arg_integer_create(
1613
+ const_cast<char*>(GRPC_ARG_ADDRESS_IS_BACKEND_FROM_GRPCLB_LOAD_BALANCER),
1614
+ is_backend_from_grpclb_load_balancer));
1615
+ if (is_backend_from_grpclb_load_balancer) {
1616
+ args_to_add.emplace_back(grpc_channel_arg_integer_create(
1617
+ const_cast<char*>(GRPC_ARG_INHIBIT_HEALTH_CHECKING), 1));
1589
1618
  }
1590
- // else, the pending pick will be registered and taken care of by the
1591
- // pending pick list inside the RR policy. Eventually,
1592
- // OnPendingPickComplete() will be called, which will (among other
1593
- // things) add the LB token to the call's initial metadata.
1594
- return pick_done;
1619
+ return grpc_channel_args_copy_and_add(args_, args_to_add.data(),
1620
+ args_to_add.size());
1595
1621
  }
1596
1622
 
1597
- void GrpcLb::CreateRoundRobinPolicyLocked(const Args& args) {
1598
- GPR_ASSERT(rr_policy_ == nullptr);
1599
- rr_policy_ = LoadBalancingPolicyRegistry::CreateLoadBalancingPolicy(
1600
- "round_robin", args);
1601
- if (GPR_UNLIKELY(rr_policy_ == nullptr)) {
1602
- gpr_log(GPR_ERROR, "[grpclb %p] Failure creating a RoundRobin policy",
1603
- this);
1604
- return;
1623
+ OrphanablePtr<LoadBalancingPolicy> GrpcLb::CreateChildPolicyLocked(
1624
+ const char* name, const grpc_channel_args* args) {
1625
+ Helper* helper = New<Helper>(Ref());
1626
+ LoadBalancingPolicy::Args lb_policy_args;
1627
+ lb_policy_args.combiner = combiner();
1628
+ lb_policy_args.args = args;
1629
+ lb_policy_args.channel_control_helper =
1630
+ UniquePtr<ChannelControlHelper>(helper);
1631
+ OrphanablePtr<LoadBalancingPolicy> lb_policy =
1632
+ LoadBalancingPolicyRegistry::CreateLoadBalancingPolicy(
1633
+ name, std::move(lb_policy_args));
1634
+ if (GPR_UNLIKELY(lb_policy == nullptr)) {
1635
+ gpr_log(GPR_ERROR, "[grpclb %p] Failure creating child policy %s", this,
1636
+ name);
1637
+ return nullptr;
1605
1638
  }
1606
- if (grpc_lb_glb_trace.enabled()) {
1607
- gpr_log(GPR_INFO, "[grpclb %p] Created new RR policy %p", this,
1608
- rr_policy_.get());
1639
+ helper->set_child(lb_policy.get());
1640
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_glb_trace)) {
1641
+ gpr_log(GPR_INFO, "[grpclb %p] Created new child policy %s (%p)", this,
1642
+ name, lb_policy.get());
1609
1643
  }
1610
- // TODO(roth): We currently track this ref manually. Once the new
1611
- // ClosureRef API is done, pass the RefCountedPtr<> along with the closure.
1612
- auto self = Ref(DEBUG_LOCATION, "on_rr_reresolution_requested");
1613
- self.release();
1614
- rr_policy_->SetReresolutionClosureLocked(&on_rr_request_reresolution_);
1615
- grpc_error* rr_state_error = nullptr;
1616
- rr_connectivity_state_ = rr_policy_->CheckConnectivityLocked(&rr_state_error);
1617
- // Connectivity state is a function of the RR policy updated/created.
1618
- UpdateConnectivityStateFromRoundRobinPolicyLocked(rr_state_error);
1619
1644
  // Add the gRPC LB's interested_parties pollset_set to that of the newly
1620
- // created RR policy. This will make the RR policy progress upon activity on
1621
- // gRPC LB, which in turn is tied to the application's call.
1622
- grpc_pollset_set_add_pollset_set(rr_policy_->interested_parties(),
1645
+ // created child policy. This will make the child policy progress upon
1646
+ // activity on gRPC LB, which in turn is tied to the application's call.
1647
+ grpc_pollset_set_add_pollset_set(lb_policy->interested_parties(),
1623
1648
  interested_parties());
1624
- // Subscribe to changes to the connectivity of the new RR.
1625
- // TODO(roth): We currently track this ref manually. Once the new
1626
- // ClosureRef API is done, pass the RefCountedPtr<> along with the closure.
1627
- self = Ref(DEBUG_LOCATION, "on_rr_connectivity_changed");
1628
- self.release();
1629
- rr_policy_->NotifyOnStateChangeLocked(&rr_connectivity_state_,
1630
- &on_rr_connectivity_changed_);
1631
- rr_policy_->ExitIdleLocked();
1632
- // Send pending picks to RR policy.
1633
- PendingPick* pp;
1634
- while ((pp = pending_picks_)) {
1635
- pending_picks_ = pp->next;
1636
- if (grpc_lb_glb_trace.enabled()) {
1637
- gpr_log(GPR_INFO,
1638
- "[grpclb %p] Pending pick about to (async) PICK from RR %p", this,
1639
- rr_policy_.get());
1640
- }
1641
- grpc_error* error = GRPC_ERROR_NONE;
1642
- PickFromRoundRobinPolicyLocked(true /* force_async */, pp, &error);
1643
- }
1649
+ return lb_policy;
1644
1650
  }
1645
1651
 
1646
- grpc_channel_args* GrpcLb::CreateRoundRobinPolicyArgsLocked() {
1647
- ServerAddressList tmp_addresses;
1648
- ServerAddressList* addresses = &tmp_addresses;
1652
+ void GrpcLb::CreateOrUpdateChildPolicyLocked() {
1653
+ if (shutting_down_) return;
1654
+ // Construct update args.
1655
+ UpdateArgs update_args;
1649
1656
  bool is_backend_from_grpclb_load_balancer = false;
1650
- if (serverlist_ != nullptr) {
1651
- tmp_addresses = ProcessServerlist(serverlist_);
1652
- is_backend_from_grpclb_load_balancer = true;
1653
- } else {
1654
- // If CreateOrUpdateRoundRobinPolicyLocked() is invoked when we haven't
1657
+ if (fallback_mode_) {
1658
+ // If CreateOrUpdateChildPolicyLocked() is invoked when we haven't
1655
1659
  // received any serverlist from the balancer, we use the fallback backends
1656
1660
  // returned by the resolver. Note that the fallback backend list may be
1657
1661
  // empty, in which case the new round_robin policy will keep the requested
1658
1662
  // picks pending.
1659
- GPR_ASSERT(fallback_backend_addresses_ != nullptr);
1660
- addresses = fallback_backend_addresses_.get();
1661
- }
1662
- GPR_ASSERT(addresses != nullptr);
1663
- // Replace the server address list in the channel args that we pass down to
1664
- // the subchannel.
1665
- static const char* keys_to_remove[] = {GRPC_ARG_SERVER_ADDRESS_LIST};
1666
- grpc_arg args_to_add[3] = {
1667
- CreateServerAddressListChannelArg(addresses),
1668
- // A channel arg indicating if the target is a backend inferred from a
1669
- // grpclb load balancer.
1670
- grpc_channel_arg_integer_create(
1671
- const_cast<char*>(
1672
- GRPC_ARG_ADDRESS_IS_BACKEND_FROM_GRPCLB_LOAD_BALANCER),
1673
- is_backend_from_grpclb_load_balancer),
1674
- };
1675
- size_t num_args_to_add = 2;
1676
- if (is_backend_from_grpclb_load_balancer) {
1677
- args_to_add[2] = grpc_channel_arg_integer_create(
1678
- const_cast<char*>(GRPC_ARG_INHIBIT_HEALTH_CHECKING), 1);
1679
- ++num_args_to_add;
1663
+ update_args.addresses = fallback_backend_addresses_;
1664
+ } else {
1665
+ update_args.addresses = serverlist_->GetServerAddressList(
1666
+ lb_calld_ == nullptr ? nullptr : lb_calld_->client_stats());
1667
+ is_backend_from_grpclb_load_balancer = true;
1680
1668
  }
1681
- grpc_channel_args* args = grpc_channel_args_copy_and_add_and_remove(
1682
- args_, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove), args_to_add,
1683
- num_args_to_add);
1684
- return args;
1685
- }
1686
-
1687
- void GrpcLb::CreateOrUpdateRoundRobinPolicyLocked() {
1688
- if (shutting_down_) return;
1689
- grpc_channel_args* args = CreateRoundRobinPolicyArgsLocked();
1690
- GPR_ASSERT(args != nullptr);
1691
- if (rr_policy_ != nullptr) {
1692
- if (grpc_lb_glb_trace.enabled()) {
1693
- gpr_log(GPR_INFO, "[grpclb %p] Updating RR policy %p", this,
1694
- rr_policy_.get());
1669
+ update_args.args =
1670
+ CreateChildPolicyArgsLocked(is_backend_from_grpclb_load_balancer);
1671
+ GPR_ASSERT(update_args.args != nullptr);
1672
+ update_args.config = child_policy_config_;
1673
+ // If the child policy name changes, we need to create a new child
1674
+ // policy. When this happens, we leave child_policy_ as-is and store
1675
+ // the new child policy in pending_child_policy_. Once the new child
1676
+ // policy transitions into state READY, we swap it into child_policy_,
1677
+ // replacing the original child policy. So pending_child_policy_ is
1678
+ // non-null only between when we apply an update that changes the child
1679
+ // policy name and when the new child reports state READY.
1680
+ //
1681
+ // Updates can arrive at any point during this transition. We always
1682
+ // apply updates relative to the most recently created child policy,
1683
+ // even if the most recent one is still in pending_child_policy_. This
1684
+ // is true both when applying the updates to an existing child policy
1685
+ // and when determining whether we need to create a new policy.
1686
+ //
1687
+ // As a result of this, there are several cases to consider here:
1688
+ //
1689
+ // 1. We have no existing child policy (i.e., we have started up but
1690
+ // have not yet received a serverlist from the balancer or gone
1691
+ // into fallback mode; in this case, both child_policy_ and
1692
+ // pending_child_policy_ are null). In this case, we create a
1693
+ // new child policy and store it in child_policy_.
1694
+ //
1695
+ // 2. We have an existing child policy and have no pending child policy
1696
+ // from a previous update (i.e., either there has not been a
1697
+ // previous update that changed the policy name, or we have already
1698
+ // finished swapping in the new policy; in this case, child_policy_
1699
+ // is non-null but pending_child_policy_ is null). In this case:
1700
+ // a. If child_policy_->name() equals child_policy_name, then we
1701
+ // update the existing child policy.
1702
+ // b. If child_policy_->name() does not equal child_policy_name,
1703
+ // we create a new policy. The policy will be stored in
1704
+ // pending_child_policy_ and will later be swapped into
1705
+ // child_policy_ by the helper when the new child transitions
1706
+ // into state READY.
1707
+ //
1708
+ // 3. We have an existing child policy and have a pending child policy
1709
+ // from a previous update (i.e., a previous update set
1710
+ // pending_child_policy_ as per case 2b above and that policy has
1711
+ // not yet transitioned into state READY and been swapped into
1712
+ // child_policy_; in this case, both child_policy_ and
1713
+ // pending_child_policy_ are non-null). In this case:
1714
+ // a. If pending_child_policy_->name() equals child_policy_name,
1715
+ // then we update the existing pending child policy.
1716
+ // b. If pending_child_policy->name() does not equal
1717
+ // child_policy_name, then we create a new policy. The new
1718
+ // policy is stored in pending_child_policy_ (replacing the one
1719
+ // that was there before, which will be immediately shut down)
1720
+ // and will later be swapped into child_policy_ by the helper
1721
+ // when the new child transitions into state READY.
1722
+ const char* child_policy_name = child_policy_config_ == nullptr
1723
+ ? "round_robin"
1724
+ : child_policy_config_->name();
1725
+ const bool create_policy =
1726
+ // case 1
1727
+ child_policy_ == nullptr ||
1728
+ // case 2b
1729
+ (pending_child_policy_ == nullptr &&
1730
+ strcmp(child_policy_->name(), child_policy_name) != 0) ||
1731
+ // case 3b
1732
+ (pending_child_policy_ != nullptr &&
1733
+ strcmp(pending_child_policy_->name(), child_policy_name) != 0);
1734
+ LoadBalancingPolicy* policy_to_update = nullptr;
1735
+ if (create_policy) {
1736
+ // Cases 1, 2b, and 3b: create a new child policy.
1737
+ // If child_policy_ is null, we set it (case 1), else we set
1738
+ // pending_child_policy_ (cases 2b and 3b).
1739
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_glb_trace)) {
1740
+ gpr_log(GPR_INFO, "[grpclb %p] Creating new %schild policy %s", this,
1741
+ child_policy_ == nullptr ? "" : "pending ", child_policy_name);
1695
1742
  }
1696
- rr_policy_->UpdateLocked(*args, nullptr);
1743
+ // Swap the policy into place.
1744
+ auto& lb_policy =
1745
+ child_policy_ == nullptr ? child_policy_ : pending_child_policy_;
1746
+ lb_policy = CreateChildPolicyLocked(child_policy_name, update_args.args);
1747
+ policy_to_update = lb_policy.get();
1697
1748
  } else {
1698
- LoadBalancingPolicy::Args lb_policy_args;
1699
- lb_policy_args.combiner = combiner();
1700
- lb_policy_args.client_channel_factory = client_channel_factory();
1701
- lb_policy_args.args = args;
1702
- CreateRoundRobinPolicyLocked(lb_policy_args);
1703
- }
1704
- grpc_channel_args_destroy(args);
1705
- }
1706
-
1707
- void GrpcLb::OnRoundRobinRequestReresolutionLocked(void* arg,
1708
- grpc_error* error) {
1709
- GrpcLb* grpclb_policy = static_cast<GrpcLb*>(arg);
1710
- if (grpclb_policy->shutting_down_ || error != GRPC_ERROR_NONE) {
1711
- grpclb_policy->Unref(DEBUG_LOCATION, "on_rr_reresolution_requested");
1712
- return;
1713
- }
1714
- if (grpc_lb_glb_trace.enabled()) {
1715
- gpr_log(
1716
- GPR_INFO,
1717
- "[grpclb %p] Re-resolution requested from the internal RR policy (%p).",
1718
- grpclb_policy, grpclb_policy->rr_policy_.get());
1719
- }
1720
- // If we are talking to a balancer, we expect to get updated addresses form
1721
- // the balancer, so we can ignore the re-resolution request from the RR
1722
- // policy. Otherwise, handle the re-resolution request using the
1723
- // grpclb policy's original re-resolution closure.
1724
- if (grpclb_policy->lb_calld_ == nullptr ||
1725
- !grpclb_policy->lb_calld_->seen_initial_response()) {
1726
- grpclb_policy->TryReresolutionLocked(&grpc_lb_glb_trace, GRPC_ERROR_NONE);
1727
- }
1728
- // Give back the wrapper closure to the RR policy.
1729
- grpclb_policy->rr_policy_->SetReresolutionClosureLocked(
1730
- &grpclb_policy->on_rr_request_reresolution_);
1731
- }
1732
-
1733
- void GrpcLb::UpdateConnectivityStateFromRoundRobinPolicyLocked(
1734
- grpc_error* rr_state_error) {
1735
- const grpc_connectivity_state curr_glb_state =
1736
- grpc_connectivity_state_check(&state_tracker_);
1737
- /* The new connectivity status is a function of the previous one and the new
1738
- * input coming from the status of the RR policy.
1739
- *
1740
- * current state (grpclb's)
1741
- * |
1742
- * v || I | C | R | TF | SD | <- new state (RR's)
1743
- * ===++====+=====+=====+======+======+
1744
- * I || I | C | R | [I] | [I] |
1745
- * ---++----+-----+-----+------+------+
1746
- * C || I | C | R | [C] | [C] |
1747
- * ---++----+-----+-----+------+------+
1748
- * R || I | C | R | [R] | [R] |
1749
- * ---++----+-----+-----+------+------+
1750
- * TF || I | C | R | [TF] | [TF] |
1751
- * ---++----+-----+-----+------+------+
1752
- * SD || NA | NA | NA | NA | NA | (*)
1753
- * ---++----+-----+-----+------+------+
1754
- *
1755
- * A [STATE] indicates that the old RR policy is kept. In those cases, STATE
1756
- * is the current state of grpclb, which is left untouched.
1757
- *
1758
- * In summary, if the new state is TRANSIENT_FAILURE or SHUTDOWN, stick to
1759
- * the previous RR instance.
1760
- *
1761
- * Note that the status is never updated to SHUTDOWN as a result of calling
1762
- * this function. Only glb_shutdown() has the power to set that state.
1763
- *
1764
- * (*) This function mustn't be called during shutting down. */
1765
- GPR_ASSERT(curr_glb_state != GRPC_CHANNEL_SHUTDOWN);
1766
- switch (rr_connectivity_state_) {
1767
- case GRPC_CHANNEL_TRANSIENT_FAILURE:
1768
- case GRPC_CHANNEL_SHUTDOWN:
1769
- GPR_ASSERT(rr_state_error != GRPC_ERROR_NONE);
1770
- break;
1771
- case GRPC_CHANNEL_IDLE:
1772
- case GRPC_CHANNEL_CONNECTING:
1773
- case GRPC_CHANNEL_READY:
1774
- GPR_ASSERT(rr_state_error == GRPC_ERROR_NONE);
1749
+ // Cases 2a and 3a: update an existing policy.
1750
+ // If we have a pending child policy, send the update to the pending
1751
+ // policy (case 3a), else send it to the current policy (case 2a).
1752
+ policy_to_update = pending_child_policy_ != nullptr
1753
+ ? pending_child_policy_.get()
1754
+ : child_policy_.get();
1775
1755
  }
1776
- if (grpc_lb_glb_trace.enabled()) {
1777
- gpr_log(
1778
- GPR_INFO,
1779
- "[grpclb %p] Setting grpclb's state to %s from new RR policy %p state.",
1780
- this, grpc_connectivity_state_name(rr_connectivity_state_),
1781
- rr_policy_.get());
1782
- }
1783
- grpc_connectivity_state_set(&state_tracker_, rr_connectivity_state_,
1784
- rr_state_error,
1785
- "update_lb_connectivity_status_locked");
1786
- }
1787
-
1788
- void GrpcLb::OnRoundRobinConnectivityChangedLocked(void* arg,
1789
- grpc_error* error) {
1790
- GrpcLb* grpclb_policy = static_cast<GrpcLb*>(arg);
1791
- if (grpclb_policy->shutting_down_) {
1792
- grpclb_policy->Unref(DEBUG_LOCATION, "on_rr_connectivity_changed");
1793
- return;
1756
+ GPR_ASSERT(policy_to_update != nullptr);
1757
+ // Update the policy.
1758
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_glb_trace)) {
1759
+ gpr_log(GPR_INFO, "[grpclb %p] Updating %schild policy %p", this,
1760
+ policy_to_update == pending_child_policy_.get() ? "pending " : "",
1761
+ policy_to_update);
1794
1762
  }
1795
- grpclb_policy->UpdateConnectivityStateFromRoundRobinPolicyLocked(
1796
- GRPC_ERROR_REF(error));
1797
- // Resubscribe. Reuse the "on_rr_connectivity_changed" ref.
1798
- grpclb_policy->rr_policy_->NotifyOnStateChangeLocked(
1799
- &grpclb_policy->rr_connectivity_state_,
1800
- &grpclb_policy->on_rr_connectivity_changed_);
1763
+ policy_to_update->UpdateLocked(std::move(update_args));
1801
1764
  }
1802
1765
 
1803
1766
  //
@@ -1807,23 +1770,45 @@ void GrpcLb::OnRoundRobinConnectivityChangedLocked(void* arg,
1807
1770
  class GrpcLbFactory : public LoadBalancingPolicyFactory {
1808
1771
  public:
1809
1772
  OrphanablePtr<LoadBalancingPolicy> CreateLoadBalancingPolicy(
1810
- const LoadBalancingPolicy::Args& args) const override {
1811
- /* Count the number of gRPC-LB addresses. There must be at least one. */
1812
- const ServerAddressList* addresses =
1813
- FindServerAddressListChannelArg(args.args);
1814
- if (addresses == nullptr) return nullptr;
1815
- bool found_balancer = false;
1816
- for (size_t i = 0; i < addresses->size(); ++i) {
1817
- if ((*addresses)[i].IsBalancer()) {
1818
- found_balancer = true;
1819
- break;
1820
- }
1821
- }
1822
- if (!found_balancer) return nullptr;
1823
- return OrphanablePtr<LoadBalancingPolicy>(New<GrpcLb>(args));
1773
+ LoadBalancingPolicy::Args args) const override {
1774
+ return OrphanablePtr<LoadBalancingPolicy>(New<GrpcLb>(std::move(args)));
1824
1775
  }
1825
1776
 
1826
1777
  const char* name() const override { return kGrpclb; }
1778
+
1779
+ RefCountedPtr<LoadBalancingPolicy::Config> ParseLoadBalancingConfig(
1780
+ const grpc_json* json, grpc_error** error) const override {
1781
+ GPR_DEBUG_ASSERT(error != nullptr && *error == GRPC_ERROR_NONE);
1782
+ if (json == nullptr) {
1783
+ return RefCountedPtr<LoadBalancingPolicy::Config>(
1784
+ New<ParsedGrpcLbConfig>(nullptr));
1785
+ }
1786
+ InlinedVector<grpc_error*, 2> error_list;
1787
+ RefCountedPtr<LoadBalancingPolicy::Config> child_policy;
1788
+ for (const grpc_json* field = json->child; field != nullptr;
1789
+ field = field->next) {
1790
+ if (field->key == nullptr) continue;
1791
+ if (strcmp(field->key, "childPolicy") == 0) {
1792
+ if (child_policy != nullptr) {
1793
+ error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
1794
+ "field:childPolicy error:Duplicate entry"));
1795
+ }
1796
+ grpc_error* parse_error = GRPC_ERROR_NONE;
1797
+ child_policy = LoadBalancingPolicyRegistry::ParseLoadBalancingConfig(
1798
+ field, &parse_error);
1799
+ if (parse_error != GRPC_ERROR_NONE) {
1800
+ error_list.push_back(parse_error);
1801
+ }
1802
+ }
1803
+ }
1804
+ if (error_list.empty()) {
1805
+ return RefCountedPtr<LoadBalancingPolicy::Config>(
1806
+ New<ParsedGrpcLbConfig>(std::move(child_policy)));
1807
+ } else {
1808
+ *error = GRPC_ERROR_CREATE_FROM_VECTOR("GrpcLb Parser", &error_list);
1809
+ return nullptr;
1810
+ }
1811
+ }
1827
1812
  };
1828
1813
 
1829
1814
  } // namespace