grpc 1.46.3-x86_64-linux → 1.47.0-x86_64-linux

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 (487) hide show
  1. checksums.yaml +4 -4
  2. data/Makefile +49 -97
  3. data/include/grpc/event_engine/event_engine.h +42 -7
  4. data/include/grpc/event_engine/memory_allocator.h +0 -15
  5. data/include/grpc/event_engine/port.h +1 -1
  6. data/include/grpc/event_engine/slice.h +286 -0
  7. data/include/grpc/event_engine/slice_buffer.h +112 -0
  8. data/include/grpc/grpc_security.h +11 -0
  9. data/include/grpc/impl/codegen/port_platform.h +100 -36
  10. data/include/grpc/impl/codegen/slice.h +1 -1
  11. data/src/core/ext/filters/channel_idle/channel_idle_filter.cc +18 -30
  12. data/src/core/ext/filters/channel_idle/channel_idle_filter.h +4 -1
  13. data/src/core/ext/filters/client_channel/backend_metric.cc +17 -12
  14. data/src/core/ext/filters/client_channel/backend_metric.h +19 -9
  15. data/src/core/ext/filters/client_channel/backup_poller.cc +5 -5
  16. data/src/core/ext/filters/client_channel/backup_poller.h +2 -4
  17. data/src/core/ext/filters/client_channel/channel_connectivity.cc +42 -20
  18. data/src/core/ext/filters/client_channel/client_channel.cc +60 -17
  19. data/src/core/ext/filters/client_channel/client_channel.h +26 -6
  20. data/src/core/ext/filters/client_channel/client_channel_channelz.cc +3 -5
  21. data/src/core/ext/filters/client_channel/client_channel_channelz.h +12 -2
  22. data/src/core/ext/filters/client_channel/client_channel_factory.cc +5 -0
  23. data/src/core/ext/filters/client_channel/client_channel_factory.h +8 -0
  24. data/src/core/ext/filters/client_channel/client_channel_plugin.cc +4 -13
  25. data/src/core/ext/filters/client_channel/config_selector.cc +1 -0
  26. data/src/core/ext/filters/client_channel/config_selector.h +7 -5
  27. data/src/core/ext/filters/client_channel/connector.h +8 -2
  28. data/src/core/ext/filters/client_channel/dynamic_filters.cc +13 -2
  29. data/src/core/ext/filters/client_channel/dynamic_filters.h +11 -1
  30. data/src/core/ext/filters/client_channel/global_subchannel_pool.cc +2 -0
  31. data/src/core/ext/filters/client_channel/global_subchannel_pool.h +3 -0
  32. data/src/core/ext/filters/client_channel/health/health_check_client.cc +14 -1
  33. data/src/core/ext/filters/client_channel/health/health_check_client.h +2 -0
  34. data/src/core/ext/filters/client_channel/http_proxy.cc +10 -2
  35. data/src/core/ext/filters/client_channel/http_proxy.h +3 -0
  36. data/src/core/ext/filters/client_channel/lb_policy/address_filtering.cc +6 -2
  37. data/src/core/ext/filters/client_channel/lb_policy/address_filtering.h +1 -0
  38. data/src/core/ext/filters/client_channel/lb_policy/backend_metric_data.h +49 -0
  39. data/src/core/ext/filters/client_channel/lb_policy/child_policy_handler.cc +12 -0
  40. data/src/core/ext/filters/client_channel/lb_policy/child_policy_handler.h +5 -0
  41. data/src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.cc +9 -3
  42. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc +59 -19
  43. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_balancer_addresses.cc +4 -0
  44. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h +6 -0
  45. data/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc +10 -1
  46. data/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h +6 -3
  47. data/src/core/ext/filters/client_channel/lb_policy/oob_backend_metric.cc +408 -0
  48. data/src/core/ext/filters/client_channel/lb_policy/oob_backend_metric.h +57 -0
  49. data/src/core/ext/filters/client_channel/lb_policy/outlier_detection/outlier_detection.cc +1038 -0
  50. data/src/core/ext/filters/client_channel/lb_policy/outlier_detection/outlier_detection.h +54 -0
  51. data/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc +60 -52
  52. data/src/core/ext/filters/client_channel/lb_policy/priority/priority.cc +102 -60
  53. data/src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.cc +157 -96
  54. data/src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.h +2 -0
  55. data/src/core/ext/filters/client_channel/lb_policy/rls/rls.cc +45 -10
  56. data/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc +182 -171
  57. data/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h +39 -36
  58. data/src/core/ext/filters/client_channel/lb_policy/weighted_target/weighted_target.cc +30 -5
  59. data/src/core/ext/filters/client_channel/lb_policy/xds/cds.cc +99 -23
  60. data/src/core/ext/filters/client_channel/lb_policy/xds/xds.h +6 -0
  61. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_impl.cc +30 -4
  62. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_manager.cc +23 -3
  63. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_resolver.cc +75 -11
  64. data/src/core/ext/filters/client_channel/lb_policy.cc +4 -2
  65. data/src/core/ext/filters/client_channel/lb_policy.h +18 -24
  66. data/src/core/ext/filters/client_channel/lb_policy_factory.h +2 -0
  67. data/src/core/ext/filters/client_channel/lb_policy_registry.cc +8 -1
  68. data/src/core/ext/filters/client_channel/lb_policy_registry.h +6 -1
  69. data/src/core/ext/filters/client_channel/local_subchannel_pool.cc +4 -0
  70. data/src/core/ext/filters/client_channel/local_subchannel_pool.h +1 -0
  71. data/src/core/ext/filters/client_channel/proxy_mapper.h +1 -1
  72. data/src/core/ext/filters/client_channel/proxy_mapper_registry.cc +2 -0
  73. data/src/core/ext/filters/client_channel/proxy_mapper_registry.h +5 -0
  74. data/src/core/ext/filters/client_channel/resolver/binder/binder_resolver.cc +23 -5
  75. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc +134 -43
  76. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h +8 -1
  77. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc +10 -8
  78. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc +1 -1
  79. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc +26 -9
  80. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h +13 -4
  81. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc +2 -1
  82. data/src/core/ext/filters/client_channel/resolver/dns/dns_resolver_selection.cc +2 -0
  83. data/src/core/ext/filters/client_channel/resolver/dns/dns_resolver_selection.h +2 -1
  84. data/src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc +30 -7
  85. data/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc +13 -14
  86. data/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h +5 -2
  87. data/src/core/ext/filters/client_channel/resolver/google_c2p/google_c2p_resolver.cc +59 -13
  88. data/src/core/ext/filters/client_channel/resolver/polling_resolver.cc +13 -1
  89. data/src/core/ext/filters/client_channel/resolver/polling_resolver.h +8 -1
  90. data/src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc +15 -11
  91. data/src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc +89 -33
  92. data/src/core/ext/filters/client_channel/resolver_result_parsing.cc +5 -11
  93. data/src/core/ext/filters/client_channel/resolver_result_parsing.h +11 -5
  94. data/src/core/ext/filters/client_channel/retry_filter.cc +42 -2
  95. data/src/core/ext/filters/client_channel/retry_service_config.cc +8 -9
  96. data/src/core/ext/filters/client_channel/retry_service_config.h +10 -1
  97. data/src/core/ext/filters/client_channel/retry_throttle.cc +1 -8
  98. data/src/core/ext/filters/client_channel/retry_throttle.h +7 -1
  99. data/src/core/ext/filters/client_channel/service_config_channel_arg_filter.cc +22 -5
  100. data/src/core/ext/filters/client_channel/subchannel.cc +156 -160
  101. data/src/core/ext/filters/client_channel/subchannel.h +80 -20
  102. data/src/core/ext/filters/client_channel/subchannel_interface.h +41 -23
  103. data/src/core/ext/filters/client_channel/subchannel_interface_internal.h +38 -0
  104. data/src/core/ext/filters/client_channel/subchannel_pool_interface.cc +12 -2
  105. data/src/core/ext/filters/client_channel/subchannel_pool_interface.h +6 -3
  106. data/src/core/ext/filters/client_channel/subchannel_stream_client.cc +16 -2
  107. data/src/core/ext/filters/client_channel/subchannel_stream_client.h +12 -0
  108. data/src/core/ext/filters/deadline/deadline_filter.cc +6 -2
  109. data/src/core/ext/filters/fault_injection/fault_injection_filter.cc +1 -4
  110. data/src/core/ext/filters/http/client/http_client_filter.cc +14 -5
  111. data/src/core/ext/filters/http/client/http_client_filter.h +7 -1
  112. data/src/core/ext/filters/http/client_authority_filter.cc +5 -10
  113. data/src/core/ext/filters/http/http_filters_plugin.cc +7 -8
  114. data/src/core/ext/filters/http/message_compress/message_compress_filter.cc +1 -0
  115. data/src/core/ext/filters/http/message_compress/message_decompress_filter.cc +3 -1
  116. data/src/core/ext/filters/http/server/http_server_filter.cc +80 -247
  117. data/src/core/ext/filters/http/server/http_server_filter.h +31 -2
  118. data/src/core/ext/filters/message_size/message_size_filter.cc +20 -26
  119. data/src/core/ext/filters/message_size/message_size_filter.h +2 -2
  120. data/src/core/ext/filters/rbac/rbac_filter.cc +1 -0
  121. data/src/core/ext/transport/chttp2/client/chttp2_connector.cc +101 -135
  122. data/src/core/ext/transport/chttp2/client/chttp2_connector.h +9 -7
  123. data/src/core/ext/transport/chttp2/server/chttp2_server.cc +44 -15
  124. data/src/core/ext/transport/chttp2/server/chttp2_server.h +2 -0
  125. data/src/core/ext/transport/chttp2/transport/bin_decoder.cc +3 -3
  126. data/src/core/ext/transport/chttp2/transport/bin_decoder.h +2 -1
  127. data/src/core/ext/transport/chttp2/transport/bin_encoder.cc +1 -0
  128. data/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +69 -20
  129. data/src/core/ext/transport/chttp2/transport/chttp2_transport.h +5 -0
  130. data/src/core/ext/transport/chttp2/transport/context_list.cc +4 -0
  131. data/src/core/ext/transport/chttp2/transport/context_list.h +4 -1
  132. data/src/core/ext/transport/chttp2/transport/flow_control.cc +6 -2
  133. data/src/core/ext/transport/chttp2/transport/flow_control.h +6 -2
  134. data/src/core/ext/transport/chttp2/transport/frame.h +0 -4
  135. data/src/core/ext/transport/chttp2/transport/frame_data.cc +7 -1
  136. data/src/core/ext/transport/chttp2/transport/frame_data.h +4 -1
  137. data/src/core/ext/transport/chttp2/transport/frame_goaway.cc +3 -0
  138. data/src/core/ext/transport/chttp2/transport/frame_goaway.h +3 -1
  139. data/src/core/ext/transport/chttp2/transport/frame_ping.cc +5 -0
  140. data/src/core/ext/transport/chttp2/transport/frame_ping.h +3 -0
  141. data/src/core/ext/transport/chttp2/transport/frame_rst_stream.cc +6 -2
  142. data/src/core/ext/transport/chttp2/transport/frame_rst_stream.h +3 -0
  143. data/src/core/ext/transport/chttp2/transport/frame_settings.cc +12 -3
  144. data/src/core/ext/transport/chttp2/transport/frame_settings.h +4 -0
  145. data/src/core/ext/transport/chttp2/transport/frame_window_update.cc +4 -1
  146. data/src/core/ext/transport/chttp2/transport/frame_window_update.h +3 -0
  147. data/src/core/ext/transport/chttp2/transport/hpack_encoder.cc +14 -12
  148. data/src/core/ext/transport/chttp2/transport/hpack_encoder.h +15 -2
  149. data/src/core/ext/transport/chttp2/transport/hpack_encoder_table.cc +3 -0
  150. data/src/core/ext/transport/chttp2/transport/hpack_encoder_table.h +3 -0
  151. data/src/core/ext/transport/chttp2/transport/hpack_parser.cc +25 -7
  152. data/src/core/ext/transport/chttp2/transport/hpack_parser.h +8 -1
  153. data/src/core/ext/transport/chttp2/transport/hpack_parser_table.cc +55 -37
  154. data/src/core/ext/transport/chttp2/transport/hpack_parser_table.h +38 -21
  155. data/src/core/ext/transport/chttp2/transport/http2_settings.h +0 -1
  156. data/src/core/ext/transport/chttp2/transport/internal.h +24 -3
  157. data/src/core/ext/transport/chttp2/transport/parsing.cc +27 -6
  158. data/src/core/ext/transport/chttp2/transport/stream_lists.cc +13 -9
  159. data/src/core/ext/transport/chttp2/transport/stream_map.cc +1 -1
  160. data/src/core/ext/transport/chttp2/transport/stream_map.h +1 -0
  161. data/src/core/ext/transport/chttp2/transport/varint.h +2 -0
  162. data/src/core/ext/transport/chttp2/transport/writing.cc +38 -2
  163. data/src/core/ext/transport/inproc/inproc_transport.cc +8 -5
  164. data/src/core/ext/upb-generated/xds/service/orca/v3/orca.upb.c +47 -0
  165. data/src/core/ext/upb-generated/xds/service/orca/v3/orca.upb.h +109 -0
  166. data/src/core/ext/xds/certificate_provider_store.cc +4 -2
  167. data/src/core/ext/xds/certificate_provider_store.h +1 -1
  168. data/src/core/ext/xds/xds_certificate_provider.cc +4 -1
  169. data/src/core/ext/xds/xds_certificate_provider.h +1 -1
  170. data/src/core/ext/xds/xds_channel_stack_modifier.cc +5 -5
  171. data/src/core/ext/xds/xds_client.cc +46 -22
  172. data/src/core/ext/xds/xds_cluster.cc +106 -16
  173. data/src/core/ext/xds/xds_cluster.h +3 -0
  174. data/src/core/ext/xds/xds_http_fault_filter.cc +3 -3
  175. data/src/core/ext/xds/xds_listener.cc +19 -9
  176. data/src/core/ext/xds/xds_server_config_fetcher.cc +2 -1
  177. data/src/core/lib/address_utils/sockaddr_utils.cc +56 -23
  178. data/src/core/lib/address_utils/sockaddr_utils.h +7 -4
  179. data/src/core/lib/avl/avl.h +3 -1
  180. data/src/core/lib/channel/call_finalization.h +4 -0
  181. data/src/core/lib/channel/call_tracer.h +8 -2
  182. data/src/core/lib/channel/channel_args.cc +41 -22
  183. data/src/core/lib/channel/channel_args.h +33 -3
  184. data/src/core/lib/channel/channel_args_preconditioning.cc +3 -3
  185. data/src/core/lib/channel/channel_args_preconditioning.h +3 -2
  186. data/src/core/lib/channel/channel_stack.cc +41 -3
  187. data/src/core/lib/channel/channel_stack.h +49 -3
  188. data/src/core/lib/channel/channel_stack_builder.cc +9 -19
  189. data/src/core/lib/channel/channel_stack_builder.h +15 -27
  190. data/src/core/lib/channel/channel_stack_builder_impl.cc +36 -41
  191. data/src/core/lib/channel/channel_stack_builder_impl.h +3 -6
  192. data/src/core/lib/channel/channel_trace.cc +8 -13
  193. data/src/core/lib/channel/channel_trace.h +6 -3
  194. data/src/core/lib/channel/channelz.cc +8 -13
  195. data/src/core/lib/channel/channelz.h +13 -4
  196. data/src/core/lib/channel/channelz_registry.cc +7 -14
  197. data/src/core/lib/channel/channelz_registry.h +10 -9
  198. data/src/core/lib/channel/connected_channel.cc +21 -31
  199. data/src/core/lib/channel/connected_channel.h +1 -0
  200. data/src/core/lib/channel/promise_based_filter.cc +444 -189
  201. data/src/core/lib/channel/promise_based_filter.h +160 -27
  202. data/src/core/lib/channel/status_util.cc +2 -0
  203. data/src/core/lib/channel/status_util.h +0 -3
  204. data/src/core/lib/compression/compression_internal.cc +45 -10
  205. data/src/core/lib/compression/compression_internal.h +1 -1
  206. data/src/core/lib/config/core_configuration.cc +3 -0
  207. data/src/core/lib/config/core_configuration.h +2 -1
  208. data/src/core/lib/event_engine/channel_args_endpoint_config.cc +4 -2
  209. data/src/core/lib/event_engine/channel_args_endpoint_config.h +3 -2
  210. data/src/core/lib/event_engine/default_event_engine_factory.cc +8 -2
  211. data/src/core/lib/event_engine/event_engine.cc +12 -2
  212. data/src/core/lib/event_engine/event_engine_factory.h +5 -0
  213. data/src/core/lib/event_engine/handle_containers.h +67 -0
  214. data/src/core/lib/event_engine/iomgr_engine.cc +206 -0
  215. data/src/core/lib/event_engine/iomgr_engine.h +118 -0
  216. data/src/core/lib/event_engine/memory_allocator.cc +12 -4
  217. data/src/core/lib/event_engine/resolved_address.cc +4 -2
  218. data/src/core/lib/event_engine/slice.cc +102 -0
  219. data/src/core/lib/event_engine/slice_buffer.cc +50 -0
  220. data/src/core/lib/{iomgr/event_engine/pollset.h → event_engine/trace.cc} +3 -10
  221. data/src/core/lib/{iomgr/endpoint_pair_event_engine.cc → event_engine/trace.h} +12 -14
  222. data/src/core/lib/gpr/log.cc +5 -0
  223. data/src/core/lib/gpr/tls.h +3 -5
  224. data/src/core/lib/gprpp/bitset.h +5 -1
  225. data/src/core/lib/gprpp/chunked_vector.h +4 -0
  226. data/src/core/lib/gprpp/construct_destruct.h +1 -0
  227. data/src/core/lib/gprpp/dual_ref_counted.h +1 -4
  228. data/src/core/lib/gprpp/examine_stack.h +0 -1
  229. data/src/core/lib/gprpp/fork.cc +3 -6
  230. data/src/core/lib/gprpp/global_config.h +2 -4
  231. data/src/core/lib/gprpp/global_config_env.cc +3 -2
  232. data/src/core/lib/gprpp/global_config_env.h +3 -1
  233. data/src/core/lib/gprpp/global_config_generic.h +0 -4
  234. data/src/core/lib/gprpp/host_port.cc +2 -0
  235. data/src/core/lib/gprpp/manual_constructor.h +0 -1
  236. data/src/core/lib/gprpp/match.h +2 -0
  237. data/src/core/lib/gprpp/memory.h +1 -5
  238. data/src/core/lib/gprpp/orphanable.h +1 -4
  239. data/src/core/lib/gprpp/ref_counted.h +1 -3
  240. data/src/core/lib/gprpp/ref_counted_ptr.h +1 -1
  241. data/src/core/lib/gprpp/stat.h +0 -2
  242. data/src/core/lib/gprpp/stat_posix.cc +7 -2
  243. data/src/core/lib/gprpp/status_helper.cc +8 -4
  244. data/src/core/lib/gprpp/status_helper.h +4 -0
  245. data/src/core/lib/gprpp/sync.h +3 -1
  246. data/src/core/lib/gprpp/table.h +10 -0
  247. data/src/core/lib/gprpp/thd.h +2 -5
  248. data/src/core/lib/gprpp/thd_posix.cc +4 -2
  249. data/src/core/lib/gprpp/thd_windows.cc +2 -0
  250. data/src/core/lib/gprpp/time.cc +8 -0
  251. data/src/core/lib/gprpp/time.h +6 -1
  252. data/src/core/lib/gprpp/time_util.cc +4 -0
  253. data/src/core/lib/gprpp/time_util.h +1 -1
  254. data/src/core/lib/gprpp/unique_type_name.h +104 -0
  255. data/src/core/lib/http/format_request.cc +29 -0
  256. data/src/core/lib/http/format_request.h +2 -0
  257. data/src/core/lib/http/httpcli.cc +88 -81
  258. data/src/core/lib/http/httpcli.h +39 -7
  259. data/src/core/lib/http/httpcli_security_connector.cc +3 -4
  260. data/src/core/lib/iomgr/endpoint.cc +4 -4
  261. data/src/core/lib/iomgr/endpoint.h +6 -4
  262. data/src/core/lib/iomgr/endpoint_cfstream.cc +7 -4
  263. data/src/core/lib/iomgr/endpoint_pair_posix.cc +2 -1
  264. data/src/core/lib/iomgr/ev_posix.cc +1 -4
  265. data/src/core/lib/iomgr/exec_ctx.h +1 -2
  266. data/src/core/lib/iomgr/internal_errqueue.cc +38 -47
  267. data/src/core/lib/iomgr/internal_errqueue.h +1 -6
  268. data/src/core/lib/iomgr/iomgr.cc +0 -1
  269. data/src/core/{ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_event_engine.cc → lib/iomgr/iomgr_fwd.h} +9 -12
  270. data/src/core/lib/iomgr/pollset_set.h +1 -2
  271. data/src/core/lib/iomgr/port.h +25 -6
  272. data/src/core/lib/iomgr/resolve_address.cc +8 -0
  273. data/src/core/lib/iomgr/resolve_address.h +21 -14
  274. data/src/core/lib/iomgr/resolve_address_impl.h +2 -3
  275. data/src/core/lib/iomgr/resolve_address_posix.cc +8 -14
  276. data/src/core/lib/iomgr/resolve_address_posix.h +5 -2
  277. data/src/core/lib/iomgr/resolve_address_windows.cc +7 -14
  278. data/src/core/lib/iomgr/resolve_address_windows.h +5 -2
  279. data/src/core/lib/iomgr/sockaddr.h +2 -3
  280. data/src/core/lib/iomgr/sockaddr_posix.h +2 -0
  281. data/src/core/lib/iomgr/sockaddr_windows.h +2 -0
  282. data/src/core/lib/iomgr/socket_utils_common_posix.cc +3 -2
  283. data/src/core/lib/iomgr/tcp_client_cfstream.cc +10 -2
  284. data/src/core/lib/iomgr/tcp_client_posix.cc +12 -5
  285. data/src/core/lib/iomgr/tcp_client_windows.cc +13 -6
  286. data/src/core/lib/iomgr/tcp_posix.cc +9 -27
  287. data/src/core/lib/iomgr/tcp_server_posix.cc +26 -12
  288. data/src/core/lib/iomgr/tcp_server_utils_posix_common.cc +30 -27
  289. data/src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.cc +7 -4
  290. data/src/core/lib/iomgr/tcp_server_windows.cc +13 -5
  291. data/src/core/lib/iomgr/tcp_windows.cc +7 -4
  292. data/src/core/lib/json/json.h +1 -2
  293. data/src/core/lib/json/json_reader.cc +9 -1
  294. data/src/core/lib/json/json_util.cc +7 -0
  295. data/src/core/lib/json/json_util.h +10 -1
  296. data/src/core/lib/json/json_writer.cc +6 -1
  297. data/src/core/lib/promise/activity.cc +1 -1
  298. data/src/core/lib/promise/activity.h +6 -6
  299. data/src/core/lib/promise/arena_promise.h +11 -1
  300. data/src/core/lib/promise/call_push_pull.h +4 -0
  301. data/src/core/lib/promise/context.h +1 -1
  302. data/src/core/lib/promise/detail/basic_seq.h +2 -2
  303. data/src/core/lib/promise/detail/promise_factory.h +0 -1
  304. data/src/core/lib/promise/latch.h +0 -1
  305. data/src/core/lib/promise/loop.h +1 -0
  306. data/src/core/lib/promise/race.h +0 -1
  307. data/src/core/lib/promise/seq.h +0 -2
  308. data/src/core/lib/promise/sleep.cc +2 -0
  309. data/src/core/lib/promise/sleep.h +10 -0
  310. data/src/core/lib/promise/try_seq.h +2 -2
  311. data/src/core/lib/resolver/resolver_factory.h +1 -2
  312. data/src/core/lib/resolver/server_address.cc +9 -3
  313. data/src/core/lib/resolver/server_address.h +4 -4
  314. data/src/core/lib/resource_quota/api.cc +14 -1
  315. data/src/core/lib/resource_quota/api.h +4 -1
  316. data/src/core/lib/resource_quota/arena.cc +0 -6
  317. data/src/core/lib/resource_quota/arena.h +1 -2
  318. data/src/core/lib/resource_quota/memory_quota.cc +47 -5
  319. data/src/core/lib/resource_quota/memory_quota.h +24 -5
  320. data/src/core/lib/resource_quota/resource_quota.h +8 -0
  321. data/src/core/lib/resource_quota/thread_quota.cc +2 -0
  322. data/src/core/lib/resource_quota/thread_quota.h +4 -0
  323. data/src/core/lib/security/authorization/grpc_server_authz_filter.cc +3 -0
  324. data/src/core/lib/security/credentials/alts/alts_credentials.cc +8 -2
  325. data/src/core/lib/security/credentials/alts/alts_credentials.h +2 -2
  326. data/src/core/lib/security/credentials/call_creds_util.cc +2 -0
  327. data/src/core/lib/security/credentials/channel_creds_registry.h +1 -0
  328. data/src/core/lib/security/credentials/composite/composite_credentials.cc +7 -3
  329. data/src/core/lib/security/credentials/composite/composite_credentials.h +5 -4
  330. data/src/core/lib/security/credentials/credentials.h +17 -10
  331. data/src/core/lib/security/credentials/external/aws_external_account_credentials.cc +81 -0
  332. data/src/core/lib/security/credentials/external/aws_external_account_credentials.h +8 -0
  333. data/src/core/lib/security/credentials/external/external_account_credentials.cc +3 -0
  334. data/src/core/lib/security/credentials/external/url_external_account_credentials.cc +2 -0
  335. data/src/core/lib/security/credentials/fake/fake_credentials.cc +13 -3
  336. data/src/core/lib/security/credentials/fake/fake_credentials.h +2 -2
  337. data/src/core/lib/security/credentials/google_default/google_default_credentials.cc +25 -15
  338. data/src/core/lib/security/credentials/google_default/google_default_credentials.h +2 -2
  339. data/src/core/lib/security/credentials/iam/iam_credentials.cc +4 -1
  340. data/src/core/lib/security/credentials/iam/iam_credentials.h +2 -2
  341. data/src/core/lib/security/credentials/insecure/insecure_credentials.cc +8 -2
  342. data/src/core/lib/security/credentials/insecure/insecure_credentials.h +4 -4
  343. data/src/core/lib/security/credentials/jwt/jwt_credentials.cc +3 -2
  344. data/src/core/lib/security/credentials/jwt/jwt_credentials.h +2 -2
  345. data/src/core/lib/security/credentials/local/local_credentials.cc +8 -2
  346. data/src/core/lib/security/credentials/local/local_credentials.h +2 -2
  347. data/src/core/lib/security/credentials/oauth2/oauth2_credentials.cc +10 -6
  348. data/src/core/lib/security/credentials/oauth2/oauth2_credentials.h +4 -4
  349. data/src/core/lib/security/credentials/plugin/plugin_credentials.cc +4 -1
  350. data/src/core/lib/security/credentials/plugin/plugin_credentials.h +1 -1
  351. data/src/core/lib/security/credentials/ssl/ssl_credentials.cc +8 -2
  352. data/src/core/lib/security/credentials/ssl/ssl_credentials.h +4 -4
  353. data/src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.cc +10 -0
  354. data/src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.h +5 -7
  355. data/src/core/lib/security/credentials/tls/grpc_tls_certificate_verifier.cc +26 -1
  356. data/src/core/lib/security/credentials/tls/grpc_tls_certificate_verifier.h +28 -4
  357. data/src/core/lib/security/credentials/tls/tls_credentials.cc +10 -0
  358. data/src/core/lib/security/credentials/tls/tls_credentials.h +2 -2
  359. data/src/core/lib/security/credentials/xds/xds_credentials.cc +12 -3
  360. data/src/core/lib/security/credentials/xds/xds_credentials.h +5 -5
  361. data/src/core/lib/security/security_connector/fake/fake_security_connector.cc +1 -1
  362. data/src/core/lib/security/security_connector/fake/fake_security_connector.h +1 -1
  363. data/src/core/lib/security/security_connector/security_connector.cc +1 -1
  364. data/src/core/lib/security/security_connector/security_connector.h +1 -1
  365. data/src/core/lib/security/security_connector/ssl/ssl_security_connector.cc +1 -1
  366. data/src/core/lib/security/transport/client_auth_filter.cc +6 -8
  367. data/src/core/lib/security/transport/secure_endpoint.cc +23 -12
  368. data/src/core/lib/security/transport/security_handshaker.cc +5 -5
  369. data/src/core/lib/security/transport/security_handshaker.h +1 -1
  370. data/src/core/lib/security/transport/server_auth_filter.cc +3 -2
  371. data/src/core/lib/service_config/service_config.h +4 -8
  372. data/src/core/lib/service_config/service_config_call_data.h +4 -1
  373. data/src/core/lib/service_config/service_config_impl.cc +7 -0
  374. data/src/core/lib/service_config/service_config_impl.h +9 -2
  375. data/src/core/lib/service_config/service_config_parser.cc +8 -0
  376. data/src/core/lib/service_config/service_config_parser.h +7 -0
  377. data/src/core/lib/slice/b64.cc +1 -1
  378. data/src/core/lib/slice/b64.h +2 -0
  379. data/src/core/lib/slice/percent_encoding.cc +4 -1
  380. data/src/core/lib/slice/percent_encoding.h +0 -6
  381. data/src/core/lib/slice/slice.cc +2 -1
  382. data/src/core/lib/slice/slice.h +10 -5
  383. data/src/core/lib/slice/slice_api.cc +1 -1
  384. data/src/core/lib/slice/slice_buffer.cc +50 -23
  385. data/src/core/lib/slice/slice_buffer.h +106 -0
  386. data/src/core/lib/slice/slice_buffer_api.cc +35 -0
  387. data/src/core/lib/slice/slice_internal.h +4 -3
  388. data/src/core/lib/slice/slice_refcount.h +2 -3
  389. data/src/core/lib/slice/slice_refcount_base.h +2 -3
  390. data/src/core/lib/slice/slice_split.cc +3 -0
  391. data/src/core/lib/slice/slice_split.h +0 -4
  392. data/src/core/lib/slice/slice_string_helpers.cc +4 -0
  393. data/src/core/lib/slice/slice_string_helpers.h +1 -4
  394. data/src/core/lib/surface/builtins.cc +7 -2
  395. data/src/core/lib/surface/byte_buffer.cc +7 -1
  396. data/src/core/lib/surface/byte_buffer_reader.cc +4 -4
  397. data/src/core/lib/surface/call.cc +41 -26
  398. data/src/core/lib/surface/call.h +16 -2
  399. data/src/core/lib/surface/call_details.cc +4 -4
  400. data/src/core/lib/surface/call_log_batch.cc +7 -1
  401. data/src/core/lib/surface/call_test_only.h +4 -1
  402. data/src/core/lib/surface/channel.cc +179 -242
  403. data/src/core/lib/surface/channel.h +94 -57
  404. data/src/core/lib/surface/channel_init.h +2 -0
  405. data/src/core/lib/surface/channel_ping.cc +8 -2
  406. data/src/core/lib/surface/channel_stack_type.cc +0 -2
  407. data/src/core/lib/surface/channel_stack_type.h +0 -2
  408. data/src/core/lib/surface/completion_queue.cc +14 -6
  409. data/src/core/lib/surface/completion_queue.h +5 -1
  410. data/src/core/lib/surface/completion_queue_factory.cc +1 -0
  411. data/src/core/lib/surface/completion_queue_factory.h +1 -3
  412. data/src/core/lib/surface/event_string.cc +1 -7
  413. data/src/core/lib/surface/event_string.h +1 -1
  414. data/src/core/lib/surface/init.cc +17 -45
  415. data/src/core/lib/surface/init.h +0 -8
  416. data/src/core/lib/surface/lame_client.cc +64 -110
  417. data/src/core/lib/surface/lame_client.h +40 -2
  418. data/src/core/lib/surface/metadata_array.cc +2 -0
  419. data/src/core/lib/surface/server.cc +69 -56
  420. data/src/core/lib/surface/server.h +39 -9
  421. data/src/core/lib/surface/validate_metadata.cc +2 -5
  422. data/src/core/lib/surface/validate_metadata.h +3 -0
  423. data/src/core/lib/surface/version.cc +2 -2
  424. data/src/core/lib/transport/bdp_estimator.cc +3 -1
  425. data/src/core/lib/transport/bdp_estimator.h +2 -3
  426. data/src/core/lib/transport/byte_stream.cc +4 -3
  427. data/src/core/lib/transport/byte_stream.h +5 -1
  428. data/src/core/lib/transport/connectivity_state.cc +6 -4
  429. data/src/core/lib/transport/connectivity_state.h +2 -3
  430. data/src/core/lib/transport/error_utils.cc +4 -2
  431. data/src/core/lib/transport/error_utils.h +5 -1
  432. data/src/core/lib/{channel → transport}/handshaker.cc +9 -4
  433. data/src/core/lib/{channel → transport}/handshaker.h +13 -6
  434. data/src/core/lib/{channel → transport}/handshaker_factory.h +9 -10
  435. data/src/core/lib/{channel → transport}/handshaker_registry.cc +5 -1
  436. data/src/core/lib/{channel → transport}/handshaker_registry.h +5 -4
  437. data/src/core/{ext/filters/client_channel → lib/transport}/http_connect_handshaker.cc +24 -10
  438. data/src/core/{ext/filters/client_channel → lib/transport}/http_connect_handshaker.h +3 -3
  439. data/src/core/lib/transport/metadata_batch.cc +287 -0
  440. data/src/core/lib/transport/metadata_batch.h +133 -264
  441. data/src/core/lib/transport/parsed_metadata.cc +2 -0
  442. data/src/core/lib/transport/parsed_metadata.h +10 -3
  443. data/src/core/lib/transport/status_conversion.cc +2 -0
  444. data/src/core/lib/transport/status_conversion.h +2 -2
  445. data/src/core/lib/transport/tcp_connect_handshaker.cc +253 -0
  446. data/src/core/lib/transport/tcp_connect_handshaker.h +39 -0
  447. data/src/core/lib/transport/timeout_encoding.cc +2 -6
  448. data/src/core/lib/transport/timeout_encoding.h +5 -1
  449. data/src/core/lib/transport/transport.cc +18 -17
  450. data/src/core/lib/transport/transport.h +28 -2
  451. data/src/core/lib/transport/transport_impl.h +10 -0
  452. data/src/core/lib/transport/transport_op_string.cc +9 -10
  453. data/src/core/lib/uri/uri_parser.cc +11 -3
  454. data/src/core/lib/uri/uri_parser.h +0 -2
  455. data/src/core/plugin_registry/grpc_plugin_registry.cc +11 -0
  456. data/src/core/tsi/ssl/session_cache/ssl_session.h +2 -0
  457. data/src/core/tsi/ssl/session_cache/ssl_session_boringssl.cc +2 -0
  458. data/src/core/tsi/ssl/session_cache/ssl_session_openssl.cc +2 -0
  459. data/src/ruby/ext/grpc/extconf.rb +2 -2
  460. data/src/ruby/lib/grpc/2.5/grpc_c.so +0 -0
  461. data/src/ruby/lib/grpc/2.6/grpc_c.so +0 -0
  462. data/src/ruby/lib/grpc/2.7/grpc_c.so +0 -0
  463. data/src/ruby/lib/grpc/3.0/grpc_c.so +0 -0
  464. data/src/ruby/lib/grpc/3.1/grpc_c.so +0 -0
  465. data/src/ruby/lib/grpc/grpc_c.so +0 -0
  466. data/src/ruby/lib/grpc/version.rb +1 -1
  467. data/third_party/abseil-cpp/absl/cleanup/cleanup.h +140 -0
  468. data/third_party/abseil-cpp/absl/cleanup/internal/cleanup.h +100 -0
  469. data/third_party/abseil-cpp/absl/container/flat_hash_set.h +504 -0
  470. metadata +36 -29
  471. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_event_engine.cc +0 -31
  472. data/src/core/lib/event_engine/sockaddr.cc +0 -40
  473. data/src/core/lib/event_engine/sockaddr.h +0 -44
  474. data/src/core/lib/gprpp/capture.h +0 -76
  475. data/src/core/lib/iomgr/event_engine/closure.cc +0 -77
  476. data/src/core/lib/iomgr/event_engine/closure.h +0 -42
  477. data/src/core/lib/iomgr/event_engine/endpoint.cc +0 -172
  478. data/src/core/lib/iomgr/event_engine/endpoint.h +0 -52
  479. data/src/core/lib/iomgr/event_engine/iomgr.cc +0 -85
  480. data/src/core/lib/iomgr/event_engine/pollset.cc +0 -87
  481. data/src/core/lib/iomgr/event_engine/promise.h +0 -51
  482. data/src/core/lib/iomgr/event_engine/resolved_address_internal.cc +0 -47
  483. data/src/core/lib/iomgr/event_engine/resolved_address_internal.h +0 -37
  484. data/src/core/lib/iomgr/event_engine/resolver.cc +0 -133
  485. data/src/core/lib/iomgr/event_engine/resolver.h +0 -56
  486. data/src/core/lib/iomgr/event_engine/tcp.cc +0 -296
  487. data/src/core/lib/iomgr/event_engine/timer.cc +0 -62
@@ -0,0 +1,1038 @@
1
+ //
2
+ // Copyright 2022 gRPC authors.
3
+ //
4
+ // Licensed under the Apache License, Version 2.0 (the "License");
5
+ // you may not use this file except in compliance with the License.
6
+ // You may obtain a copy of the License at
7
+ //
8
+ // http://www.apache.org/licenses/LICENSE-2.0
9
+ //
10
+ // Unless required by applicable law or agreed to in writing, software
11
+ // distributed under the License is distributed on an "AS IS" BASIS,
12
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ // See the License for the specific language governing permissions and
14
+ // limitations under the License.
15
+ //
16
+
17
+ #include <grpc/support/port_platform.h>
18
+
19
+ #include "src/core/ext/filters/client_channel/lb_policy/outlier_detection/outlier_detection.h"
20
+
21
+ #include <stddef.h>
22
+
23
+ #include <algorithm>
24
+ #include <atomic>
25
+ #include <cmath>
26
+ #include <cstdint>
27
+ #include <map>
28
+ #include <memory>
29
+ #include <set>
30
+ #include <string>
31
+ #include <utility>
32
+ #include <vector>
33
+
34
+ #include "absl/container/inlined_vector.h"
35
+ #include "absl/memory/memory.h"
36
+ #include "absl/random/random.h"
37
+ #include "absl/status/status.h"
38
+ #include "absl/status/statusor.h"
39
+ #include "absl/strings/string_view.h"
40
+ #include "absl/types/variant.h"
41
+
42
+ #include <grpc/impl/codegen/connectivity_state.h>
43
+ #include <grpc/impl/codegen/grpc_types.h>
44
+ #include <grpc/support/alloc.h>
45
+ #include <grpc/support/log.h>
46
+
47
+ #include "src/core/ext/filters/client_channel/lb_policy.h"
48
+ #include "src/core/ext/filters/client_channel/lb_policy/child_policy_handler.h"
49
+ #include "src/core/ext/filters/client_channel/lb_policy_factory.h"
50
+ #include "src/core/ext/filters/client_channel/lb_policy_registry.h"
51
+ #include "src/core/ext/filters/client_channel/subchannel_interface.h"
52
+ #include "src/core/lib/channel/channel_args.h"
53
+ #include "src/core/lib/debug/trace.h"
54
+ #include "src/core/lib/gpr/env.h"
55
+ #include "src/core/lib/gpr/string.h"
56
+ #include "src/core/lib/gprpp/debug_location.h"
57
+ #include "src/core/lib/gprpp/orphanable.h"
58
+ #include "src/core/lib/gprpp/ref_counted.h"
59
+ #include "src/core/lib/gprpp/ref_counted_ptr.h"
60
+ #include "src/core/lib/iomgr/closure.h"
61
+ #include "src/core/lib/iomgr/error.h"
62
+ #include "src/core/lib/iomgr/exec_ctx.h"
63
+ #include "src/core/lib/iomgr/iomgr_fwd.h"
64
+ #include "src/core/lib/iomgr/pollset_set.h"
65
+ #include "src/core/lib/iomgr/timer.h"
66
+ #include "src/core/lib/iomgr/work_serializer.h"
67
+ #include "src/core/lib/json/json.h"
68
+ #include "src/core/lib/json/json_util.h"
69
+ #include "src/core/lib/resolver/server_address.h"
70
+ #include "src/core/lib/transport/connectivity_state.h"
71
+
72
+ namespace grpc_core {
73
+
74
+ TraceFlag grpc_outlier_detection_lb_trace(false, "outlier_detection_lb");
75
+
76
+ // TODO(donnadionne): Remove once outlier detection is no longer experimental
77
+ bool XdsOutlierDetectionEnabled() {
78
+ char* value = gpr_getenv("GRPC_EXPERIMENTAL_ENABLE_OUTLIER_DETECTION");
79
+ bool parsed_value;
80
+ bool parse_succeeded = gpr_parse_bool_value(value, &parsed_value);
81
+ gpr_free(value);
82
+ return parse_succeeded && parsed_value;
83
+ }
84
+
85
+ namespace {
86
+
87
+ constexpr char kOutlierDetection[] = "outlier_detection_experimental";
88
+
89
+ // Config for xDS Cluster Impl LB policy.
90
+ class OutlierDetectionLbConfig : public LoadBalancingPolicy::Config {
91
+ public:
92
+ OutlierDetectionLbConfig(
93
+ OutlierDetectionConfig outlier_detection_config,
94
+ RefCountedPtr<LoadBalancingPolicy::Config> child_policy)
95
+ : outlier_detection_config_(outlier_detection_config),
96
+ child_policy_(std::move(child_policy)) {}
97
+
98
+ const char* name() const override { return kOutlierDetection; }
99
+
100
+ bool CountingEnabled() const {
101
+ return (
102
+ outlier_detection_config_.interval != Duration::Infinity() &&
103
+ (outlier_detection_config_.success_rate_ejection.has_value() ||
104
+ outlier_detection_config_.failure_percentage_ejection.has_value()));
105
+ }
106
+
107
+ const OutlierDetectionConfig& outlier_detection_config() const {
108
+ return outlier_detection_config_;
109
+ }
110
+
111
+ RefCountedPtr<LoadBalancingPolicy::Config> child_policy() const {
112
+ return child_policy_;
113
+ }
114
+
115
+ private:
116
+ OutlierDetectionConfig outlier_detection_config_;
117
+ RefCountedPtr<LoadBalancingPolicy::Config> child_policy_;
118
+ };
119
+
120
+ // xDS Cluster Impl LB policy.
121
+ class OutlierDetectionLb : public LoadBalancingPolicy {
122
+ public:
123
+ explicit OutlierDetectionLb(Args args);
124
+
125
+ const char* name() const override { return kOutlierDetection; }
126
+
127
+ void UpdateLocked(UpdateArgs args) override;
128
+ void ExitIdleLocked() override;
129
+ void ResetBackoffLocked() override;
130
+
131
+ private:
132
+ class SubchannelState;
133
+ class SubchannelWrapper : public DelegatingSubchannel {
134
+ public:
135
+ SubchannelWrapper(RefCountedPtr<SubchannelState> subchannel_state,
136
+ RefCountedPtr<SubchannelInterface> subchannel)
137
+ : DelegatingSubchannel(std::move(subchannel)),
138
+ subchannel_state_(std::move(subchannel_state)) {
139
+ if (subchannel_state_ != nullptr) {
140
+ subchannel_state_->AddSubchannel(this);
141
+ if (subchannel_state_->ejection_time().has_value()) {
142
+ ejected_ = true;
143
+ }
144
+ }
145
+ }
146
+
147
+ ~SubchannelWrapper() override {
148
+ if (subchannel_state_ != nullptr) {
149
+ subchannel_state_->RemoveSubchannel(this);
150
+ }
151
+ }
152
+
153
+ void Eject();
154
+
155
+ void Uneject();
156
+
157
+ grpc_connectivity_state CheckConnectivityState() override;
158
+
159
+ void WatchConnectivityState(
160
+ grpc_connectivity_state initial_state,
161
+ std::unique_ptr<ConnectivityStateWatcherInterface> watcher) override;
162
+
163
+ void CancelConnectivityStateWatch(
164
+ ConnectivityStateWatcherInterface* watcher) override;
165
+
166
+ RefCountedPtr<SubchannelState> subchannel_state() const {
167
+ return subchannel_state_;
168
+ }
169
+
170
+ private:
171
+ class WatcherWrapper
172
+ : public SubchannelInterface::ConnectivityStateWatcherInterface {
173
+ public:
174
+ WatcherWrapper(std::unique_ptr<
175
+ SubchannelInterface::ConnectivityStateWatcherInterface>
176
+ watcher,
177
+ grpc_connectivity_state initial_state, bool ejected)
178
+ : watcher_(std::move(watcher)),
179
+ last_seen_state_(initial_state),
180
+ ejected_(ejected) {}
181
+
182
+ void Eject() {
183
+ ejected_ = true;
184
+ if (last_seen_state_ != GRPC_CHANNEL_TRANSIENT_FAILURE) {
185
+ watcher_->OnConnectivityStateChange(GRPC_CHANNEL_TRANSIENT_FAILURE);
186
+ }
187
+ }
188
+
189
+ void Uneject() {
190
+ ejected_ = false;
191
+ if (last_seen_state_ != GRPC_CHANNEL_TRANSIENT_FAILURE) {
192
+ watcher_->OnConnectivityStateChange(last_seen_state_);
193
+ }
194
+ }
195
+
196
+ void OnConnectivityStateChange(
197
+ grpc_connectivity_state new_state) override {
198
+ last_seen_state_ = new_state;
199
+ if (!ejected_) {
200
+ watcher_->OnConnectivityStateChange(new_state);
201
+ }
202
+ }
203
+
204
+ grpc_pollset_set* interested_parties() override {
205
+ return watcher_->interested_parties();
206
+ }
207
+
208
+ private:
209
+ std::unique_ptr<SubchannelInterface::ConnectivityStateWatcherInterface>
210
+ watcher_;
211
+ grpc_connectivity_state last_seen_state_;
212
+ bool ejected_;
213
+ };
214
+
215
+ RefCountedPtr<SubchannelState> subchannel_state_;
216
+ bool ejected_ = false;
217
+ std::map<SubchannelInterface::ConnectivityStateWatcherInterface*,
218
+ WatcherWrapper*>
219
+ watchers_;
220
+ };
221
+
222
+ class SubchannelState : public RefCounted<SubchannelState> {
223
+ public:
224
+ struct Bucket {
225
+ std::atomic<uint64_t> successes;
226
+ std::atomic<uint64_t> failures;
227
+ };
228
+
229
+ void RotateBucket() {
230
+ backup_bucket_->successes = 0;
231
+ backup_bucket_->failures = 0;
232
+ current_bucket_.swap(backup_bucket_);
233
+ active_bucket_.store(current_bucket_.get());
234
+ }
235
+
236
+ absl::optional<std::pair<double, uint64_t>> GetSuccessRateAndVolume() {
237
+ uint64_t total_request =
238
+ backup_bucket_->successes + backup_bucket_->failures;
239
+ if (total_request == 0) {
240
+ return absl::nullopt;
241
+ }
242
+ double success_rate =
243
+ backup_bucket_->successes * 100.0 /
244
+ (backup_bucket_->successes + backup_bucket_->failures);
245
+ return {
246
+ {success_rate, backup_bucket_->successes + backup_bucket_->failures}};
247
+ }
248
+
249
+ void AddSubchannel(SubchannelWrapper* wrapper) {
250
+ subchannels_.insert(wrapper);
251
+ }
252
+
253
+ void RemoveSubchannel(SubchannelWrapper* wrapper) {
254
+ subchannels_.erase(wrapper);
255
+ }
256
+
257
+ void AddSuccessCount() { active_bucket_.load()->successes.fetch_add(1); }
258
+
259
+ void AddFailureCount() { active_bucket_.load()->failures.fetch_add(1); }
260
+
261
+ absl::optional<Timestamp> ejection_time() const { return ejection_time_; }
262
+
263
+ void Eject(const Timestamp& time) {
264
+ ejection_time_ = time;
265
+ ++multiplier_;
266
+ for (auto& subchannel : subchannels_) {
267
+ subchannel->Eject();
268
+ }
269
+ }
270
+
271
+ void Uneject() {
272
+ ejection_time_.reset();
273
+ for (auto& subchannel : subchannels_) {
274
+ subchannel->Uneject();
275
+ }
276
+ }
277
+
278
+ void MaybeUneject(uint64_t base_ejection_time_in_millis,
279
+ uint64_t max_ejection_time_in_millis) {
280
+ if (!ejection_time_.has_value()) {
281
+ if (multiplier_ > 0) {
282
+ --multiplier_;
283
+ }
284
+ } else {
285
+ GPR_ASSERT(ejection_time_.has_value());
286
+ auto change_time = ejection_time_.value() +
287
+ Duration::Milliseconds(std::min(
288
+ base_ejection_time_in_millis * multiplier_,
289
+ std::max(base_ejection_time_in_millis,
290
+ max_ejection_time_in_millis)));
291
+ if (change_time < ExecCtx::Get()->Now()) {
292
+ Uneject();
293
+ }
294
+ }
295
+ }
296
+
297
+ private:
298
+ std::unique_ptr<Bucket> current_bucket_ = absl::make_unique<Bucket>();
299
+ std::unique_ptr<Bucket> backup_bucket_ = absl::make_unique<Bucket>();
300
+ // The bucket used to update call counts.
301
+ // Points to either current_bucket or active_bucket.
302
+ std::atomic<Bucket*> active_bucket_{current_bucket_.get()};
303
+ uint32_t multiplier_ = 0;
304
+ absl::optional<Timestamp> ejection_time_;
305
+ std::set<SubchannelWrapper*> subchannels_;
306
+ };
307
+
308
+ // A simple wrapper for ref-counting a picker from the child policy.
309
+ class RefCountedPicker : public RefCounted<RefCountedPicker> {
310
+ public:
311
+ explicit RefCountedPicker(std::unique_ptr<SubchannelPicker> picker)
312
+ : picker_(std::move(picker)) {}
313
+ PickResult Pick(PickArgs args) { return picker_->Pick(args); }
314
+
315
+ private:
316
+ std::unique_ptr<SubchannelPicker> picker_;
317
+ };
318
+
319
+ // A picker that wraps the picker from the child to perform outlier detection.
320
+ class Picker : public SubchannelPicker {
321
+ public:
322
+ Picker(OutlierDetectionLb* outlier_detection_lb,
323
+ RefCountedPtr<RefCountedPicker> picker, bool counting_enabled);
324
+
325
+ PickResult Pick(PickArgs args) override;
326
+
327
+ private:
328
+ class SubchannelCallTracker;
329
+ RefCountedPtr<RefCountedPicker> picker_;
330
+ bool counting_enabled_;
331
+ };
332
+
333
+ class Helper : public ChannelControlHelper {
334
+ public:
335
+ explicit Helper(RefCountedPtr<OutlierDetectionLb> outlier_detection_policy)
336
+ : outlier_detection_policy_(std::move(outlier_detection_policy)) {}
337
+
338
+ ~Helper() override {
339
+ outlier_detection_policy_.reset(DEBUG_LOCATION, "Helper");
340
+ }
341
+
342
+ RefCountedPtr<SubchannelInterface> CreateSubchannel(
343
+ ServerAddress address, const grpc_channel_args& args) override;
344
+ void UpdateState(grpc_connectivity_state state, const absl::Status& status,
345
+ std::unique_ptr<SubchannelPicker> picker) override;
346
+ void RequestReresolution() override;
347
+ absl::string_view GetAuthority() override;
348
+ void AddTraceEvent(TraceSeverity severity,
349
+ absl::string_view message) override;
350
+
351
+ private:
352
+ RefCountedPtr<OutlierDetectionLb> outlier_detection_policy_;
353
+ };
354
+
355
+ class EjectionTimer : public InternallyRefCounted<EjectionTimer> {
356
+ public:
357
+ EjectionTimer(RefCountedPtr<OutlierDetectionLb> parent,
358
+ Timestamp start_time);
359
+
360
+ void Orphan() override;
361
+
362
+ Timestamp StartTime() const { return start_time_; }
363
+
364
+ private:
365
+ static void OnTimer(void* arg, grpc_error_handle error);
366
+ void OnTimerLocked(grpc_error_handle);
367
+
368
+ RefCountedPtr<OutlierDetectionLb> parent_;
369
+ grpc_timer timer_;
370
+ grpc_closure on_timer_;
371
+ bool timer_pending_ = true;
372
+ Timestamp start_time_;
373
+ absl::BitGen bit_gen_;
374
+ };
375
+
376
+ ~OutlierDetectionLb() override;
377
+
378
+ static std::string MakeKeyForAddress(const ServerAddress& address);
379
+
380
+ void ShutdownLocked() override;
381
+
382
+ OrphanablePtr<LoadBalancingPolicy> CreateChildPolicyLocked(
383
+ const grpc_channel_args* args);
384
+
385
+ void MaybeUpdatePickerLocked();
386
+
387
+ // Current config from the resolver.
388
+ RefCountedPtr<OutlierDetectionLbConfig> config_;
389
+
390
+ // Internal state.
391
+ bool shutting_down_ = false;
392
+
393
+ OrphanablePtr<LoadBalancingPolicy> child_policy_;
394
+
395
+ // Latest state and picker reported by the child policy.
396
+ grpc_connectivity_state state_ = GRPC_CHANNEL_IDLE;
397
+ absl::Status status_;
398
+ RefCountedPtr<RefCountedPicker> picker_;
399
+ std::map<std::string, RefCountedPtr<SubchannelState>> subchannel_state_map_;
400
+ OrphanablePtr<EjectionTimer> ejection_timer_;
401
+ };
402
+
403
+ //
404
+ // OutlierDetectionLb::SubchannelWrapper
405
+ //
406
+
407
+ void OutlierDetectionLb::SubchannelWrapper::Eject() {
408
+ ejected_ = true;
409
+ for (auto& watcher : watchers_) {
410
+ watcher.second->Eject();
411
+ }
412
+ }
413
+
414
+ void OutlierDetectionLb::SubchannelWrapper::Uneject() {
415
+ ejected_ = false;
416
+ for (auto& watcher : watchers_) {
417
+ watcher.second->Uneject();
418
+ }
419
+ }
420
+
421
+ grpc_connectivity_state
422
+ OutlierDetectionLb::SubchannelWrapper::CheckConnectivityState() {
423
+ if (ejected_) return GRPC_CHANNEL_TRANSIENT_FAILURE;
424
+ return wrapped_subchannel()->CheckConnectivityState();
425
+ }
426
+
427
+ void OutlierDetectionLb::SubchannelWrapper::WatchConnectivityState(
428
+ grpc_connectivity_state initial_state,
429
+ std::unique_ptr<ConnectivityStateWatcherInterface> watcher) {
430
+ ConnectivityStateWatcherInterface* watcher_ptr = watcher.get();
431
+ auto watcher_wrapper = absl::make_unique<WatcherWrapper>(
432
+ std::move(watcher), initial_state, ejected_);
433
+ watchers_.emplace(watcher_ptr, watcher_wrapper.get());
434
+ wrapped_subchannel()->WatchConnectivityState(initial_state,
435
+ std::move(watcher_wrapper));
436
+ }
437
+
438
+ void OutlierDetectionLb::SubchannelWrapper::CancelConnectivityStateWatch(
439
+ ConnectivityStateWatcherInterface* watcher) {
440
+ auto it = watchers_.find(watcher);
441
+ if (it == watchers_.end()) return;
442
+ wrapped_subchannel()->CancelConnectivityStateWatch(it->second);
443
+ watchers_.erase(it);
444
+ }
445
+
446
+ //
447
+ // OutlierDetectionLb::Picker::SubchannelCallTracker
448
+ //
449
+
450
+ class OutlierDetectionLb::Picker::SubchannelCallTracker
451
+ : public LoadBalancingPolicy::SubchannelCallTrackerInterface {
452
+ public:
453
+ SubchannelCallTracker(
454
+ std::unique_ptr<LoadBalancingPolicy::SubchannelCallTrackerInterface>
455
+ original_subchannel_call_tracker,
456
+ RefCountedPtr<SubchannelState> subchannel_state)
457
+ : original_subchannel_call_tracker_(
458
+ std::move(original_subchannel_call_tracker)),
459
+ subchannel_state_(std::move(subchannel_state)) {}
460
+
461
+ ~SubchannelCallTracker() override {
462
+ subchannel_state_.reset(DEBUG_LOCATION, "SubchannelCallTracker");
463
+ }
464
+
465
+ void Start() override {
466
+ // This tracker does not care about started calls only finished calls.
467
+ // Delegate if needed.
468
+ if (original_subchannel_call_tracker_ != nullptr) {
469
+ original_subchannel_call_tracker_->Start();
470
+ }
471
+ }
472
+
473
+ void Finish(FinishArgs args) override {
474
+ // Delegate if needed.
475
+ if (original_subchannel_call_tracker_ != nullptr) {
476
+ original_subchannel_call_tracker_->Finish(args);
477
+ }
478
+ // Record call completion based on status for outlier detection
479
+ // calculations.
480
+ if (subchannel_state_ != nullptr) {
481
+ if (args.status.ok()) {
482
+ subchannel_state_->AddSuccessCount();
483
+ } else {
484
+ subchannel_state_->AddFailureCount();
485
+ }
486
+ }
487
+ }
488
+
489
+ private:
490
+ std::unique_ptr<LoadBalancingPolicy::SubchannelCallTrackerInterface>
491
+ original_subchannel_call_tracker_;
492
+ RefCountedPtr<SubchannelState> subchannel_state_;
493
+ };
494
+
495
+ //
496
+ // OutlierDetectionLb::Picker
497
+ //
498
+
499
+ OutlierDetectionLb::Picker::Picker(OutlierDetectionLb* outlier_detection_lb,
500
+ RefCountedPtr<RefCountedPicker> picker,
501
+ bool counting_enabled)
502
+ : picker_(std::move(picker)), counting_enabled_(counting_enabled) {
503
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_outlier_detection_lb_trace)) {
504
+ gpr_log(GPR_INFO,
505
+ "[outlier_detection_lb %p] constructed new picker %p and counting "
506
+ "is %s",
507
+ outlier_detection_lb, this,
508
+ (counting_enabled ? "enabled" : "disabled"));
509
+ }
510
+ }
511
+
512
+ LoadBalancingPolicy::PickResult OutlierDetectionLb::Picker::Pick(
513
+ LoadBalancingPolicy::PickArgs args) {
514
+ if (picker_ == nullptr) { // Should never happen.
515
+ return PickResult::Fail(absl::InternalError(
516
+ "outlier_detection picker not given any child picker"));
517
+ }
518
+ // Delegate to child picker
519
+ PickResult result = picker_->Pick(args);
520
+ auto* complete_pick = absl::get_if<PickResult::Complete>(&result.result);
521
+ if (complete_pick != nullptr) {
522
+ // Unwrap subchannel to pass back up the stack.
523
+ auto* subchannel_wrapper =
524
+ static_cast<SubchannelWrapper*>(complete_pick->subchannel.get());
525
+ // Inject subchannel call tracker to record call completion as long as
526
+ // not both success_rate_ejection and failure_percentage_ejection are unset.
527
+ if (counting_enabled_) {
528
+ complete_pick->subchannel_call_tracker =
529
+ absl::make_unique<SubchannelCallTracker>(
530
+ std::move(complete_pick->subchannel_call_tracker),
531
+ subchannel_wrapper->subchannel_state());
532
+ }
533
+ complete_pick->subchannel = subchannel_wrapper->wrapped_subchannel();
534
+ }
535
+ return result;
536
+ }
537
+
538
+ //
539
+ // OutlierDetectionLb
540
+ //
541
+
542
+ OutlierDetectionLb::OutlierDetectionLb(Args args)
543
+ : LoadBalancingPolicy(std::move(args)) {
544
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_outlier_detection_lb_trace)) {
545
+ gpr_log(GPR_INFO, "[outlier_detection_lb %p] created", this);
546
+ }
547
+ }
548
+
549
+ OutlierDetectionLb::~OutlierDetectionLb() {
550
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_outlier_detection_lb_trace)) {
551
+ gpr_log(GPR_INFO,
552
+ "[outlier_detection_lb %p] destroying outlier_detection LB policy",
553
+ this);
554
+ }
555
+ }
556
+
557
+ std::string OutlierDetectionLb::MakeKeyForAddress(
558
+ const ServerAddress& address) {
559
+ // Strip off attributes to construct the key.
560
+ return ServerAddress(address.address(),
561
+ grpc_channel_args_copy(address.args()))
562
+ .ToString();
563
+ }
564
+
565
+ void OutlierDetectionLb::ShutdownLocked() {
566
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_outlier_detection_lb_trace)) {
567
+ gpr_log(GPR_INFO, "[outlier_detection_lb %p] shutting down", this);
568
+ }
569
+ ejection_timer_.reset();
570
+ shutting_down_ = true;
571
+ // Remove the child policy's interested_parties pollset_set from the
572
+ // xDS policy.
573
+ if (child_policy_ != nullptr) {
574
+ grpc_pollset_set_del_pollset_set(child_policy_->interested_parties(),
575
+ interested_parties());
576
+ child_policy_.reset();
577
+ }
578
+ // Drop our ref to the child's picker, in case it's holding a ref to
579
+ // the child.
580
+ picker_.reset();
581
+ }
582
+
583
+ void OutlierDetectionLb::ExitIdleLocked() {
584
+ if (child_policy_ != nullptr) child_policy_->ExitIdleLocked();
585
+ }
586
+
587
+ void OutlierDetectionLb::ResetBackoffLocked() {
588
+ if (child_policy_ != nullptr) child_policy_->ResetBackoffLocked();
589
+ }
590
+
591
+ void OutlierDetectionLb::UpdateLocked(UpdateArgs args) {
592
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_outlier_detection_lb_trace)) {
593
+ gpr_log(GPR_INFO, "[outlier_detection_lb %p] Received update", this);
594
+ }
595
+ auto old_config = std::move(config_);
596
+ // Update config.
597
+ config_ = std::move(args.config);
598
+ // Update outlier detection timer.
599
+ if (!config_->CountingEnabled()) {
600
+ // No need for timer. Cancel the current timer, if any.
601
+ ejection_timer_.reset();
602
+ } else if (ejection_timer_ == nullptr) {
603
+ // No timer running. Start it now.
604
+ ejection_timer_ =
605
+ MakeOrphanable<EjectionTimer>(Ref(), ExecCtx::Get()->Now());
606
+ for (const auto& p : subchannel_state_map_) {
607
+ p.second->RotateBucket(); // Reset call counters.
608
+ }
609
+ } else if (old_config->outlier_detection_config().interval !=
610
+ config_->outlier_detection_config().interval) {
611
+ // Timer interval changed. Cancel the current timer and start a new one
612
+ // with the same start time.
613
+ // Note that if the new deadline is in the past, the timer will fire
614
+ // immediately.
615
+ ejection_timer_ =
616
+ MakeOrphanable<EjectionTimer>(Ref(), ejection_timer_->StartTime());
617
+ }
618
+ // Create policy if needed.
619
+ if (child_policy_ == nullptr) {
620
+ child_policy_ = CreateChildPolicyLocked(args.args);
621
+ }
622
+ if (args.addresses.ok()) {
623
+ std::set<std::string> current_addresses;
624
+ for (const ServerAddress& address : *args.addresses) {
625
+ std::string address_key = MakeKeyForAddress(address);
626
+ auto& subchannel_state = subchannel_state_map_[address_key];
627
+ if (subchannel_state == nullptr) {
628
+ subchannel_state = MakeRefCounted<SubchannelState>();
629
+ }
630
+ current_addresses.emplace(address_key);
631
+ }
632
+ for (auto it = subchannel_state_map_.begin();
633
+ it != subchannel_state_map_.end();) {
634
+ if (current_addresses.find(it->first) == current_addresses.end()) {
635
+ // remove each map entry for a subchannel address not in the updated
636
+ // address list.
637
+ it = subchannel_state_map_.erase(it);
638
+ } else {
639
+ ++it;
640
+ }
641
+ }
642
+ }
643
+ // Construct update args.
644
+ UpdateArgs update_args;
645
+ update_args.addresses = std::move(args.addresses);
646
+ update_args.config = config_->child_policy();
647
+ update_args.args = grpc_channel_args_copy(args.args);
648
+ // Update the policy.
649
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_outlier_detection_lb_trace)) {
650
+ gpr_log(GPR_INFO,
651
+ "[outlier_detection_lb %p] Updating child policy handler %p", this,
652
+ child_policy_.get());
653
+ }
654
+ child_policy_->UpdateLocked(std::move(update_args));
655
+ }
656
+
657
+ void OutlierDetectionLb::MaybeUpdatePickerLocked() {
658
+ if (picker_ != nullptr) {
659
+ auto outlier_detection_picker =
660
+ absl::make_unique<Picker>(this, picker_, config_->CountingEnabled());
661
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_outlier_detection_lb_trace)) {
662
+ gpr_log(GPR_INFO,
663
+ "[outlier_detection_lb %p] updating connectivity: state=%s "
664
+ "status=(%s) picker=%p",
665
+ this, ConnectivityStateName(state_), status_.ToString().c_str(),
666
+ outlier_detection_picker.get());
667
+ }
668
+ channel_control_helper()->UpdateState(state_, status_,
669
+ std::move(outlier_detection_picker));
670
+ }
671
+ }
672
+
673
+ OrphanablePtr<LoadBalancingPolicy> OutlierDetectionLb::CreateChildPolicyLocked(
674
+ const grpc_channel_args* args) {
675
+ LoadBalancingPolicy::Args lb_policy_args;
676
+ lb_policy_args.work_serializer = work_serializer();
677
+ lb_policy_args.args = args;
678
+ lb_policy_args.channel_control_helper =
679
+ absl::make_unique<Helper>(Ref(DEBUG_LOCATION, "Helper"));
680
+ OrphanablePtr<LoadBalancingPolicy> lb_policy =
681
+ MakeOrphanable<ChildPolicyHandler>(std::move(lb_policy_args),
682
+ &grpc_outlier_detection_lb_trace);
683
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_outlier_detection_lb_trace)) {
684
+ gpr_log(GPR_INFO,
685
+ "[outlier_detection_lb %p] Created new child policy handler %p",
686
+ this, lb_policy.get());
687
+ }
688
+ // Add our interested_parties pollset_set to that of the newly created
689
+ // child policy. This will make the child policy progress upon activity on
690
+ // this policy, which in turn is tied to the application's call.
691
+ grpc_pollset_set_add_pollset_set(lb_policy->interested_parties(),
692
+ interested_parties());
693
+ return lb_policy;
694
+ }
695
+
696
+ //
697
+ // OutlierDetectionLb::Helper
698
+ //
699
+
700
+ RefCountedPtr<SubchannelInterface> OutlierDetectionLb::Helper::CreateSubchannel(
701
+ ServerAddress address, const grpc_channel_args& args) {
702
+ if (outlier_detection_policy_->shutting_down_) return nullptr;
703
+ std::string key = MakeKeyForAddress(address);
704
+ RefCountedPtr<SubchannelState> subchannel_state;
705
+ auto it = outlier_detection_policy_->subchannel_state_map_.find(key);
706
+ if (it != outlier_detection_policy_->subchannel_state_map_.end()) {
707
+ subchannel_state = it->second->Ref();
708
+ }
709
+ auto subchannel = MakeRefCounted<SubchannelWrapper>(
710
+ subchannel_state,
711
+ outlier_detection_policy_->channel_control_helper()->CreateSubchannel(
712
+ std::move(address), args));
713
+ if (subchannel_state != nullptr) {
714
+ subchannel_state->AddSubchannel(subchannel.get());
715
+ }
716
+ return subchannel;
717
+ }
718
+
719
+ void OutlierDetectionLb::Helper::UpdateState(
720
+ grpc_connectivity_state state, const absl::Status& status,
721
+ std::unique_ptr<SubchannelPicker> picker) {
722
+ if (outlier_detection_policy_->shutting_down_) return;
723
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_outlier_detection_lb_trace)) {
724
+ gpr_log(GPR_INFO,
725
+ "[outlier_detection_lb %p] child connectivity state update: "
726
+ "state=%s (%s) "
727
+ "picker=%p",
728
+ outlier_detection_policy_.get(), ConnectivityStateName(state),
729
+ status.ToString().c_str(), picker.get());
730
+ }
731
+ // Save the state and picker.
732
+ outlier_detection_policy_->state_ = state;
733
+ outlier_detection_policy_->status_ = status;
734
+ outlier_detection_policy_->picker_ =
735
+ MakeRefCounted<RefCountedPicker>(std::move(picker));
736
+ // Wrap the picker and return it to the channel.
737
+ outlier_detection_policy_->MaybeUpdatePickerLocked();
738
+ }
739
+
740
+ void OutlierDetectionLb::Helper::RequestReresolution() {
741
+ if (outlier_detection_policy_->shutting_down_) return;
742
+ outlier_detection_policy_->channel_control_helper()->RequestReresolution();
743
+ }
744
+
745
+ absl::string_view OutlierDetectionLb::Helper::GetAuthority() {
746
+ return outlier_detection_policy_->channel_control_helper()->GetAuthority();
747
+ }
748
+
749
+ void OutlierDetectionLb::Helper::AddTraceEvent(TraceSeverity severity,
750
+ absl::string_view message) {
751
+ if (outlier_detection_policy_->shutting_down_) return;
752
+ outlier_detection_policy_->channel_control_helper()->AddTraceEvent(severity,
753
+ message);
754
+ }
755
+
756
+ //
757
+ // OutlierDetectionLb::EjectionTimer
758
+ //
759
+
760
+ OutlierDetectionLb::EjectionTimer::EjectionTimer(
761
+ RefCountedPtr<OutlierDetectionLb> parent, Timestamp start_time)
762
+ : parent_(std::move(parent)), start_time_(start_time) {
763
+ GRPC_CLOSURE_INIT(&on_timer_, OnTimer, this, nullptr);
764
+ Ref().release();
765
+ grpc_timer_init(
766
+ &timer_,
767
+ start_time_ + parent_->config_->outlier_detection_config().interval,
768
+ &on_timer_);
769
+ }
770
+
771
+ void OutlierDetectionLb::EjectionTimer::Orphan() {
772
+ if (timer_pending_) {
773
+ timer_pending_ = false;
774
+ grpc_timer_cancel(&timer_);
775
+ }
776
+ Unref();
777
+ }
778
+
779
+ void OutlierDetectionLb::EjectionTimer::OnTimer(void* arg,
780
+ grpc_error_handle error) {
781
+ auto* self = static_cast<EjectionTimer*>(arg);
782
+ (void)GRPC_ERROR_REF(error); // ref owned by lambda
783
+ self->parent_->work_serializer()->Run(
784
+ [self, error]() { self->OnTimerLocked(error); }, DEBUG_LOCATION);
785
+ }
786
+
787
+ void OutlierDetectionLb::EjectionTimer::OnTimerLocked(grpc_error_handle error) {
788
+ if (error == GRPC_ERROR_NONE && timer_pending_) {
789
+ std::map<SubchannelState*, double> success_rate_ejection_candidates;
790
+ std::map<SubchannelState*, double> failure_percentage_ejection_candidates;
791
+ size_t ejected_host_count = 0;
792
+ double success_rate_sum = 0;
793
+ auto time_now = ExecCtx::Get()->Now();
794
+ auto& config = parent_->config_->outlier_detection_config();
795
+ for (auto& state : parent_->subchannel_state_map_) {
796
+ auto* subchannel_state = state.second.get();
797
+ // For each address, swap the call counter's buckets in that address's
798
+ // map entry.
799
+ subchannel_state->RotateBucket();
800
+ // Gather data to run success rate algorithm or failure percentage
801
+ // algorithm.
802
+ if (subchannel_state->ejection_time().has_value()) {
803
+ ++ejected_host_count;
804
+ }
805
+ absl::optional<std::pair<double, uint64_t>> host_success_rate_and_volume =
806
+ subchannel_state->GetSuccessRateAndVolume();
807
+ if (!host_success_rate_and_volume.has_value()) {
808
+ continue;
809
+ }
810
+ double success_rate = host_success_rate_and_volume->first;
811
+ uint64_t request_volume = host_success_rate_and_volume->second;
812
+ if (config.success_rate_ejection.has_value()) {
813
+ if (request_volume >= config.success_rate_ejection->request_volume) {
814
+ success_rate_ejection_candidates[subchannel_state] = success_rate;
815
+ success_rate_sum += success_rate;
816
+ }
817
+ }
818
+ if (config.failure_percentage_ejection.has_value()) {
819
+ if (request_volume >=
820
+ config.failure_percentage_ejection->request_volume) {
821
+ failure_percentage_ejection_candidates[subchannel_state] =
822
+ success_rate;
823
+ }
824
+ }
825
+ }
826
+ // success rate algorithm
827
+ if (!success_rate_ejection_candidates.empty() &&
828
+ success_rate_ejection_candidates.size() >=
829
+ config.success_rate_ejection->minimum_hosts) {
830
+ // calculate ejection threshold: (mean - stdev *
831
+ // (success_rate_ejection.stdev_factor / 1000))
832
+ double mean = success_rate_sum / success_rate_ejection_candidates.size();
833
+ double variance = 0;
834
+ std::for_each(success_rate_ejection_candidates.begin(),
835
+ success_rate_ejection_candidates.end(),
836
+ [&variance, mean](std::pair<SubchannelState*, double> v) {
837
+ variance += std::pow(v.second - mean, 2);
838
+ });
839
+ variance /= success_rate_ejection_candidates.size();
840
+ double stdev = std::sqrt(variance);
841
+ const double success_rate_stdev_factor =
842
+ static_cast<double>(config.success_rate_ejection->stdev_factor) /
843
+ 1000;
844
+ double ejection_threshold = mean - stdev * success_rate_stdev_factor;
845
+ for (auto& candidate : success_rate_ejection_candidates) {
846
+ if (candidate.second < ejection_threshold) {
847
+ uint32_t random_key = absl::Uniform(bit_gen_, 1, 100);
848
+ double current_percent = 100.0 * ejected_host_count /
849
+ parent_->subchannel_state_map_.size();
850
+ if (random_key <
851
+ config.success_rate_ejection->enforcement_percentage &&
852
+ (ejected_host_count == 0 ||
853
+ (current_percent < config.max_ejection_percent))) {
854
+ // Eject and record the timestamp for use when ejecting addresses in
855
+ // this iteration.
856
+ candidate.first->Eject(time_now);
857
+ ++ejected_host_count;
858
+ }
859
+ }
860
+ }
861
+ }
862
+ // failure percentage algorithm
863
+ if (!failure_percentage_ejection_candidates.empty() &&
864
+ failure_percentage_ejection_candidates.size() >=
865
+ config.failure_percentage_ejection->minimum_hosts) {
866
+ for (auto& candidate : failure_percentage_ejection_candidates) {
867
+ // Extra check to make sure success rate algorithm didn't already
868
+ // eject this backend.
869
+ if (candidate.first->ejection_time().has_value()) continue;
870
+ if ((100.0 - candidate.second) >
871
+ config.failure_percentage_ejection->threshold) {
872
+ uint32_t random_key = absl::Uniform(bit_gen_, 1, 100);
873
+ double current_percent = 100.0 * ejected_host_count /
874
+ parent_->subchannel_state_map_.size();
875
+ if (random_key <
876
+ config.failure_percentage_ejection->enforcement_percentage &&
877
+ (ejected_host_count == 0 ||
878
+ (current_percent < config.max_ejection_percent))) {
879
+ // Eject and record the timestamp for use when ejecting addresses in
880
+ // this iteration.
881
+ candidate.first->Eject(time_now);
882
+ ++ejected_host_count;
883
+ }
884
+ }
885
+ }
886
+ }
887
+ // For each address in the map:
888
+ // If the address is not ejected and the multiplier is greater than 0,
889
+ // decrease the multiplier by 1. If the address is ejected, and the
890
+ // current time is after ejection_timestamp + min(base_ejection_time *
891
+ // multiplier, max(base_ejection_time, max_ejection_time)), un-eject the
892
+ // address.
893
+ for (auto& state : parent_->subchannel_state_map_) {
894
+ auto* subchannel_state = state.second.get();
895
+ subchannel_state->MaybeUneject(config.base_ejection_time.millis(),
896
+ config.max_ejection_time.millis());
897
+ }
898
+ timer_pending_ = false;
899
+ parent_->ejection_timer_ =
900
+ MakeOrphanable<EjectionTimer>(parent_, ExecCtx::Get()->Now());
901
+ }
902
+ Unref(DEBUG_LOCATION, "Timer");
903
+ GRPC_ERROR_UNREF(error);
904
+ }
905
+
906
+ //
907
+ // factory
908
+ //
909
+
910
+ class OutlierDetectionLbFactory : public LoadBalancingPolicyFactory {
911
+ public:
912
+ OrphanablePtr<LoadBalancingPolicy> CreateLoadBalancingPolicy(
913
+ LoadBalancingPolicy::Args args) const override {
914
+ return MakeOrphanable<OutlierDetectionLb>(std::move(args));
915
+ }
916
+
917
+ const char* name() const override { return kOutlierDetection; }
918
+
919
+ RefCountedPtr<LoadBalancingPolicy::Config> ParseLoadBalancingConfig(
920
+ const Json& json, grpc_error_handle* error) const override {
921
+ GPR_DEBUG_ASSERT(error != nullptr && *error == GRPC_ERROR_NONE);
922
+ if (json.type() == Json::Type::JSON_NULL) {
923
+ // This policy was configured in the deprecated loadBalancingPolicy
924
+ // field or in the client API.
925
+ *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
926
+ "field:loadBalancingPolicy error:outlier_detection policy requires "
927
+ "configuration. Please use loadBalancingConfig field of service "
928
+ "config instead.");
929
+ return nullptr;
930
+ }
931
+ std::vector<grpc_error_handle> error_list;
932
+ // Outlier detection config
933
+ OutlierDetectionConfig outlier_detection_config;
934
+ auto it = json.object_value().find("successRateEjection");
935
+ if (it != json.object_value().end()) {
936
+ if (it->second.type() != Json::Type::OBJECT) {
937
+ error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
938
+ "field:successRateEjection error:type must be object"));
939
+ } else {
940
+ OutlierDetectionConfig::SuccessRateEjection success_config;
941
+ const Json::Object& object = it->second.object_value();
942
+ ParseJsonObjectField(object, "stdevFactor",
943
+ &success_config.stdev_factor, &error_list,
944
+ /*required=*/false);
945
+ ParseJsonObjectField(object, "enforcementPercentage",
946
+ &success_config.enforcement_percentage,
947
+ &error_list, /*required=*/false);
948
+ ParseJsonObjectField(object, "minimumHosts",
949
+ &success_config.minimum_hosts, &error_list,
950
+ /*required=*/false);
951
+ ParseJsonObjectField(object, "requestVolume",
952
+ &success_config.request_volume, &error_list,
953
+ /*required=*/false);
954
+ outlier_detection_config.success_rate_ejection = success_config;
955
+ }
956
+ }
957
+ it = json.object_value().find("failurePercentageEjection");
958
+ if (it != json.object_value().end()) {
959
+ if (it->second.type() != Json::Type::OBJECT) {
960
+ error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
961
+ "field:successRateEjection error:type must be object"));
962
+ } else {
963
+ OutlierDetectionConfig::FailurePercentageEjection failure_config;
964
+ const Json::Object& object = it->second.object_value();
965
+ ParseJsonObjectField(object, "threshold", &failure_config.threshold,
966
+ &error_list, /*required=*/false);
967
+ ParseJsonObjectField(object, "enforcementPercentage",
968
+ &failure_config.enforcement_percentage,
969
+ &error_list, /*required=*/false);
970
+ ParseJsonObjectField(object, "minimumHosts",
971
+ &failure_config.minimum_hosts, &error_list,
972
+ /*required=*/false);
973
+ ParseJsonObjectField(object, "requestVolume",
974
+ &failure_config.request_volume, &error_list,
975
+ /*required=*/false);
976
+ outlier_detection_config.failure_percentage_ejection = failure_config;
977
+ }
978
+ }
979
+ ParseJsonObjectFieldAsDuration(json.object_value(), "interval",
980
+ &outlier_detection_config.interval,
981
+ &error_list);
982
+ ParseJsonObjectFieldAsDuration(json.object_value(), "baseEjectionTime",
983
+ &outlier_detection_config.base_ejection_time,
984
+ &error_list, /*required=*/false);
985
+ if (!ParseJsonObjectFieldAsDuration(
986
+ json.object_value(), "maxEjectionTime",
987
+ &outlier_detection_config.max_ejection_time, &error_list,
988
+ /*required=*/false)) {
989
+ outlier_detection_config.max_ejection_time = std::max(
990
+ outlier_detection_config.base_ejection_time, Duration::Seconds(300));
991
+ }
992
+ ParseJsonObjectField(json.object_value(), "maxEjectionPercent",
993
+ &outlier_detection_config.max_ejection_percent,
994
+ &error_list, /*required=*/false);
995
+ RefCountedPtr<LoadBalancingPolicy::Config> child_policy;
996
+ it = json.object_value().find("childPolicy");
997
+ if (it == json.object_value().end()) {
998
+ error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
999
+ "field:childPolicy error:required field missing"));
1000
+ } else {
1001
+ grpc_error_handle parse_error = GRPC_ERROR_NONE;
1002
+ child_policy = LoadBalancingPolicyRegistry::ParseLoadBalancingConfig(
1003
+ it->second, &parse_error);
1004
+ if (child_policy == nullptr) {
1005
+ GPR_DEBUG_ASSERT(parse_error != GRPC_ERROR_NONE);
1006
+ std::vector<grpc_error_handle> child_errors;
1007
+ child_errors.push_back(parse_error);
1008
+ error_list.push_back(
1009
+ GRPC_ERROR_CREATE_FROM_VECTOR("field:childPolicy", &child_errors));
1010
+ }
1011
+ }
1012
+ if (!error_list.empty()) {
1013
+ *error = GRPC_ERROR_CREATE_FROM_VECTOR(
1014
+ "outlier_detection_experimental LB policy config", &error_list);
1015
+ return nullptr;
1016
+ }
1017
+ return MakeRefCounted<OutlierDetectionLbConfig>(outlier_detection_config,
1018
+ std::move(child_policy));
1019
+ }
1020
+ };
1021
+
1022
+ } // namespace
1023
+
1024
+ } // namespace grpc_core
1025
+
1026
+ //
1027
+ // Plugin registration
1028
+ //
1029
+
1030
+ void grpc_lb_policy_outlier_detection_init() {
1031
+ if (grpc_core::XdsOutlierDetectionEnabled()) {
1032
+ grpc_core::LoadBalancingPolicyRegistry::Builder::
1033
+ RegisterLoadBalancingPolicyFactory(
1034
+ absl::make_unique<grpc_core::OutlierDetectionLbFactory>());
1035
+ }
1036
+ }
1037
+
1038
+ void grpc_lb_policy_outlier_detection_shutdown() {}